Estoy usando C # e intento obtener la posición del mouse de hardware. Lo primero que probé fue la funcionalidad XNA simple que es fácil de usar
Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Después de eso, también hago el dibujo del mouse, y en comparación con el mouse de hardware de Windows, este nuevo mouse con coordenadas proporcionadas por xna se está "aflojando". Con eso quiero decir, que está detrás de unos pocos cuadros. Por ejemplo, si el juego se ejecuta a 600 fps, por supuesto, responderá, pero a 60 fps el retraso del mouse por software ya no es aceptable. Por lo tanto, intenté usar lo que pensé que era un mouse de hardware,
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);
pero el resultado fue exactamente el mismo. También intenté obtener el cursor de formulario de Windows, y eso también fue un callejón sin salida, pero funcionó, pero con el mismo retraso. Jugando con la funcionalidad xna:
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale
cambió el tiempo de retraso por razones algo obvias, pero la conclusión es que, independientemente de que todavía estaba detrás del mouse predeterminado de Windows. He visto en algunos juegos, que ofrecen opciones para el mouse acelerado por hardware, y en otros (creo) ya es por defecto. ¿Alguien puede dar alguna pista sobre cómo lograr eso?
fuente
Mouse.GetState()
esté roto. ¿Está seguro de que está obteniendo la posición del mouse en el mismo marco que lo está dibujando? Recuerde también que el cursor de Windows tiene habilitada la aceleración / desaceleración, por lo que se siente más sensible. Si desea acercarse al hardware, debe presionar DirectInput, que le dará deltas de movimiento en lugar de posiciones absolutas del mouse. Pero creo queMouse.GetState()
sigue siendo la forma correcta de hacerlo en XNA.Mouse.GetState()
no está roto, y mientras lasIsFixedTimeStep == true
personas no puedan ver el retraso a menos que se comparen directamente con el mouse de Windows visible. Sin embargo, si se establece IsFixedTimeStep en falso a una velocidad de fotogramas más baja, será visible para todos. Acerca de la entrada directa, lo consideré una posibilidad (último recurso).Respuestas:
Lo que está viendo no es un retraso de entrada.
Para obtener la posición del cursor en Windows puede usar
WM_MOUSEMOVE
oGetCursorPos
. Ambos proporcionan la posición del cursor después de que Windows lo haya procesado, aplicando cosas como la aceleración. Esta es la posición del cursor que usa Windows, incluso para dibujar. Y casi siempre lo que quieres usar también.Esto es lo que usa XNA . Específicamente
GetCursorPos
( MSDN ). Esto significa que, cuando llamaMouse.GetState
, obtiene la posición real del cursor tal como lo ve Windows, con prácticamente cero retraso.Ahora, podría usar
WM_INPUT
(o DirectInput, aunque eso está en desuso). Esto le proporciona los datos de puntero sin formato. Esto es antes de que Windows pueda aplicar cosas como la aceleración, y generalmente no es lo que desea.Lo que está viendo es el retraso de salida.
Esto se debe al " cursor de hardware ". Se trata de un pequeño duende que se ve arrastrado por la pantalla por la GPU en el mismo final de su tubería. Y me refiero al final . Viene después del búfer de trama: se inserta en el flujo de datos a medida que la imagen se envía al monitor. La razón por la que reacciona tan rápido es porque su posición se establece configurando directamente los registros de la GPU. No hay que esperar en la tubería en absoluto.
Tu juego, por otro lado, tiene que pasar por la tubería de GPU. Esto agrega muchos retrasos por sí solo. El más problemático de estos para usted es el doble búfer, que (estoy bastante seguro) no puede desactivar en XNA 4. No dibuja directamente en el búfer de cuadros, sino en el backbuffer. Que se presenta cada ~ 16 ms (a 60 FPS). Eso significa que está viendo un mínimo de aproximadamente 16 ms entre recibir el resultado de
Mouse.GetState
obtener algo basado en ese resultado en la pantalla. Probablemente por más tiempo. Ciertamente mucho más lento que el cursor de hardware.Entonces, ¿cuáles son las soluciones?
Una es usar
SetCursor
( MSDN ) para cambiar la imagen que se muestra con el cursor de hardware, para obtener una imagen que se adapte mejor a su juego (o simplemente vivir con el cursor de Windows).Y el otro (mucho más fácil) es aceptar el retraso y configurarlo
Game.IsMouseVisible = false
para ocultar el retraso relativo. Muestra tu propio cursor en el juego. Será 16 ms más lento que el cursor oculto de Windows, pero ¿a quién le importa? Los jugadores están acostumbrados. Y 16ms es casi visualmente imperceptible de todos modos (es por eso que renderizamos las cosas a 60FPS).fuente