C # / XNA donanım fare konumunu olsun


10

C # kullanıyorum ve donanım fare konumunu almaya çalışıyorum. Denediğim ilk şey, kullanımı basit olan basit XNA işleviydi

Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

Bundan sonra farenin çizimini de yapıyorum ve windows donanım faresine kıyasla, xna sağlanan bu yeni fare koordinatları "yavaşlıyor". Demek istediğim, birkaç kare geride kalıyor. Örneğin, oyun 600 fps'de çalışıyorsa, lanet cevap verir, ancak 60 fps yazılımda fare gecikmesi artık kabul edilemez. Bu yüzden bir donanım faresi olduğunu düşündüğüm şeyi kullanmayı denedim,

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);

ama sonuç tamamen aynıydı. Ayrıca Windows form imlecini almayı denedim ve bu da iyi bir sonuçtu, ancak aynı gecikmeyle. Xna işlevselliği ile uğraşmak:

GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale

gecikme süresini biraz belirgin nedenlerle değiştirdi, ancak sonuçta, varsayılan Windows faresinin arkasında olmasına rağmen. Bazı oyunlarda donanım hızlandırılmış fare için seçenek sunduğunu gördüm ve diğerlerinde (sanırım) zaten varsayılan olarak. Herkes bunu başarmak için biraz yol açabilir.


2
Mouse.GetState()Kırıldığını sanmıyorum . Fare konumunu çizdiğinizle aynı çerçevede aldığınızdan emin misiniz? Ayrıca Windows imlecinin hızlanma / yavaşlamanın etkin olduğunu unutmayın, bu yüzden daha duyarlı hissediyor . Donanıma daha yakın olmak istiyorsanız, DirectInput'a basmalısınız, bu da mutlak fare konumları yerine hareket deltaları verecektir. Ancak Mouse.GetState()XNA'da bunu yapmanın hala doğru yolu olduğuna inanıyorum .
Panda Pijama

Hayır, Mouse.GetState()kırık değildir ve IsFixedTimeStep == trueinsanlar doğrudan görünür fare faresiyle karşılaştırılmadıkça gecikmeyi göremez. Ancak IsFixedTimeStep öğesini alt kare hızında false olarak ayarlamak herkes tarafından görülebilir. Doğrudan giriş hakkında bir olasılık (son çare) olduğunu düşündüm.
12'de

İstediğinizden emin değilsiniz, ancak imleç grafiğini pencerenizdeyken değiştirmeye ve sonra her zaman görünür hale getirmeye ne dersiniz?
William Mariager

Tam olarak ne yaptığımı, şey sadece göstermek istemiyorum, ama aynı zamanda farenin kesin konumunu bilmek. Ama elde ettiğim şey ne olması gerektiğinin biraz gerisindedir.
Sunder

Yanıtlar:


17

Gördüğünüz şey girdi gecikmesi değil .

Windows'da imlecin konumunu almak için WM_MOUSEMOVEveya tuşunu kullanabilirsiniz GetCursorPos. Her ikisi de Windows işlemeden sonra imleç konumunu sağlar ve hızlanma gibi şeyler uygular. Bu, çizim de dahil olmak üzere Windows'un kullandığı imleç konumudur. Ve neredeyse her zaman kullanmak istediğiniz şey.

XNA bunu kullanır . Özellikle GetCursorPos( MSDN ). Bu Mouse.GetState, aradığınızda, imlecin gerçek konumunu, Windows'un gördüğü gibi elde edersiniz - neredeyse sıfır gecikmeyle.

Artık kullanabilirsiniz WM_INPUT(veya kullanımdan kaldırılmış olsa da DirectInput). Bu size ham işaretçi verilerini verir. Bu, Windows hızlandırma gibi şeyleri uygulamadan önce ve genellikle istediğiniz şey değildir .

Gördüğünüz şey çıktı gecikmesidir.

Bunun nedeni " donanım imleci ". Bu, en GPU ile ekran üzerinde çizilmiş olur küçük sprite olduğunu çok onun boru hattının sonuna. Ve son demek istiyorum . Çerçeve arabelleğinden sonra gelir - görüntü monitöre gönderilirken veri akışına eklenir. Bu kadar hızlı tepki vermesinin nedeni, doğrudan GPU kayıtları ayarlanarak konumunun ayarlanmış olmasıdır. Boru hattında hiç beklemek yok.

Oyunun ise GPU boru hattından geçmesi gerekiyor. Bu, kendi başına bol miktarda gecikme ekler. Bunların sizin için en problemli olanı, XNA 4'te kapatamayacağınız (eminim) çift arabelleğe almadır. Doğrudan çerçeve arabelleğine çizmezsiniz - backbuffer'a çizersiniz. Hangi her ~ 16ms (60FPS de) sundu. Bu, Mouse.GetStateekrandaki sonuca göre bir şey elde etmenin sonucunu almak arasında en az 16 ms aradığınız anlamına gelir . Muhtemelen daha uzun. Kesinlikle donanım imlecinden çok daha yavaş.

Peki çözümler neler?

Bunlardan biri, donanım imleci tarafından görüntülenen görüntüyü değiştirmek için SetCursor( MSDN ) kullanmak , oyununuza daha uygun bir görüntü olmak (ya da sadece Windows imleciyle yaşamak).

Ve diğeri (çok daha kolay) sadece gecikmeyi kabul etmek Game.IsMouseVisible = falseve göreceli gecikmeyi gizlemeye ayarlamaktır . Oyunda kendi imlecinizi gösterin. Gizli Windows imlecinden 16ms daha yavaş olacak - ama kimin umurunda? Oyuncular buna alışkınlar. Ve 16ms zaten neredeyse görsel olarak algılanamaz (bu yüzden 60FPS'de bir şeyler oluşturuyoruz).


Konunun ayrıntılı açıklaması için teşekkür ederim. Büyük olasılıkla sadece XNA fare ile yapışacağım. Birisi için başka bir geçici çözüm olması durumunda kabul etmeden önce biraz bekleyecek.
Sunder

Sanırım gecikmeyi kabul etmek ya da etmemek playtesting ile cevaplanması gereken bir soru.
Zonko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.