J'utilise C # et j'essaie d'obtenir la position de la souris matérielle. La première chose que j'ai essayée était une fonctionnalité XNA simple qui est simple à utiliser
Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Après cela, je fais aussi le dessin de la souris, et en comparant avec la souris matérielle Windows, cette nouvelle souris avec les coordonnées fournies par xna "se relâche". J'entends par là qu'il est en retard de quelques images. Par exemple, si le jeu tourne à 600 fps, il sera bien sûr réactif, mais à 60 fps, le retard de la souris logicielle n'est plus acceptable. J'ai donc essayé d'utiliser ce que je pensais être une souris matérielle,
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);
mais le résultat était exactement le même. J'ai également essayé d'obtenir le curseur de formulaire Windows, et c'était une impasse aussi bien - mais avec le même retard. Jouer avec la fonctionnalité xna:
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale
a changé le temps de retard pour des raisons quelque peu évidentes, mais l'essentiel est qu'indépendamment, il était toujours derrière la souris Windows par défaut. J'ai vu dans certains jeux, qu'ils fournissent une option pour la souris accélérée matériellement, et dans d'autres (je pense) c'est déjà par défaut. Quelqu'un peut-il nous montrer comment y parvenir?
la source
Mouse.GetState()
soit cassé. Êtes-vous sûr d'obtenir la position de la souris dans le même cadre que celui que vous dessinez? Rappelez-vous également que le curseur Windows a activé l'accélération / décélération, donc il se sent plus réactif. Si vous voulez vous rapprocher du matériel, vous devez appuyer sur DirectInput, qui vous donnera des deltas de mouvement au lieu de positions absolues de la souris. Mais je crois queMouse.GetState()
c'est toujours la bonne façon de le faire dans XNA.Mouse.GetState()
n'est pas cassé, et tant que lesIsFixedTimeStep == true
gens ne devraient pas pouvoir voir le retard à moins d'être comparés directement avec la souris Windows visible. Cependant, en définissant IsFixedTimeStep sur false à un débit d'images inférieur, cela devient visible pour tout le monde. À propos de l'entrée directe, j'ai considéré que c'était une posabilité (dernier recours).Réponses:
Ce que vous voyez n'est pas un décalage d'entrée.
Pour obtenir la position du curseur dans Windows, vous pouvez utiliser
WM_MOUSEMOVE
ouGetCursorPos
. Ils fournissent tous deux la position du curseur une fois que Windows l'a traité, en appliquant des choses comme l'accélération. Il s'agit de la position du curseur utilisée par Windows, y compris pour le dessin. Et presque toujours aussi ce que vous voulez utiliser.C'est ce que XNA utilise . Plus précisément
GetCursorPos
( MSDN ). Cela signifie que, lorsque vous appelezMouse.GetState
, vous obtenez la position réelle du curseur telle que Windows la voit - avec un délai pratiquement nul.Maintenant, vous pouvez utiliser
WM_INPUT
(ou DirectInput, bien que ce soit obsolète). Cela vous donne les données brutes du pointeur. C'est avant que Windows puisse appliquer des choses comme l'accélération, et ce n'est généralement pas ce que vous voulez.Ce que vous voyez, c'est un décalage de sortie.
Cela est dû au " curseur matériel ". Il s'agit d'un petit sprite qui est dessiné sur l'écran par le GPU à la toute fin de son pipeline. Et je veux dire la fin . Il vient après le tampon de trame - il est inséré dans le flux de données lorsque l'image est envoyée au moniteur. La raison pour laquelle il réagit si rapidement est que sa position est définie en définissant directement les registres GPU. Il n'y a aucune attente dans le pipeline.
Votre jeu, en revanche, doit passer par le pipeline GPU. Cela ajoute beaucoup de retards en soi. Le plus problématique pour vous est la double mise en mémoire tampon - que (je suis presque sûr) vous ne pouvez pas désactiver dans XNA 4. Vous ne dessinez pas directement dans le tampon de trame - vous dessinez dans le backbuffer. Qui est présenté toutes les ~ 16 ms (à 60FPS). Cela signifie que vous regardez au moins environ 16 ms entre la réception du résultat de l'
Mouse.GetState
obtention de quelque chose basé sur ce résultat à l'écran. Probablement plus. Certainement beaucoup plus lent que le curseur matériel.Alors, quelles sont les solutions?
La première consiste à utiliser
SetCursor
( MSDN ) pour modifier l'image qui est affichée par le curseur matériel, pour obtenir une image qui convient mieux à votre jeu (ou tout simplement vivre avec le curseur Windows).Et l'autre (beaucoup plus facile) consiste à simplement accepter le décalage et
Game.IsMouseVisible = false
à masquer le décalage relatif. Affichez votre propre curseur dans le jeu. Il sera 16 ms plus lent que le curseur Windows caché - mais peu importe? Les joueurs y sont habitués. Et 16 ms est de toute façon presque imperceptible visuellement (c'est pourquoi nous rendons les choses à 60FPS).la source