visual una teclado tecla simular presionar presionada mostrar evento detectar boton asignar c# xna

una - simular presionar tecla c#



Cómo reducir la velocidad o detener las pulsaciones de teclas en XNA (12)

Bueno, lo que podrías hacer es algo como esto (también hará un seguimiento de cada clave)

int[] keyVals; TimeSpan pressWait = new TimeSpan(0, 0, 1); Dictionary<Keys, bool> keyDowns = new Dictionary<Keys, bool>(); Dictionary<Keys, DateTime> keyTimes = new Dictionary<Keys, DateTime>(); public ConstructorNameHere { keyVals = Enum.GetValues(typeof(Keys)) as int[]; foreach (int k in keyVals) { keyDowns.Add((Keys)k, false); keyTimes.Add((Keys)k, new DateTime()+ new TimeSpan(1,0,0)); } } protected override void Update(GameTime gameTime) { foreach (int i in keyVals) { Keys key = (Keys)i; switch (key) { case Keys.Enter: keyTimes[key] = (Keyboard.GetState().IsKeyUp(key)) ? ((keyDowns[key]) ? DateTime.Now + pressWait : keyTimes[key]) : keyTimes[key]; keyDowns[key] = (keyTimes[key] > DateTime.Now) ? false : Keyboard.GetState().IsKeyDown(key); if (keyTimes[key] < DateTime.Now) { // Code for what happens when Keys.Enter is pressed goes here. } break; } }

Al hacerlo de esta manera, usted puede comprobar cada clave. También puede hacer esto solo para cada clave creando DateTimes y valores bool separados.

Empecé a escribir un juego con XNA Framework y encontré un problema simple que no sé cómo resolver correctamente.

Estoy mostrando un menú usando Texture2D y usando el teclado (o gamepad). Cambio el elemento del menú que está seleccionado. Mi problema es que la función actual que se usa para alternar entre los elementos del menú es demasiado rápida. Podría hacer clic en el botón hacia abajo y bajará 5 o 6 elementos del menú (debido al hecho de que a Update () se le llama muchas veces, así se actualiza el elemento seleccionado).

ex. (> indicate selected) > MenuItem1 MenuItem2 MenuItem3 MenuItem4 MenuItem5 I press the down key for just a second), then I have this state: MenuItem1 MenuItem2 MenuItem3 > MenuItem4 MenuItem5 What I want is (until I press the key again) MenuItem1 > MenuItem2 MenuItem3 MenuItem4 MenuItem5

Lo que estoy buscando es una forma de hacer que el jugador haga clic en la tecla arriba / abajo varias veces para pasar de un elemento del menú a otro, o para tener algún tiempo de espera mínimo antes de pasar al siguiente elemento del menú.


Guardo el GamePadState y KeyboardState de la ejecución de la actualización anterior. En la próxima ejecución de la actualización, compruebo los botones que no se presionaron la última ejecución, pero que se presionan ahora. Entonces guardo el estado actual.

Tengo todo esto envuelto en una clase estática que puedo usar para consultar botones específicos y / u obtener una lista de botones presionados desde la última actualización. Esto hace que sea realmente fácil trabajar con varias teclas simultáneamente (algo que ciertamente desea en los juegos) y sería trivialmente extensible a los acordes.


He creado una clase (grande) que ayuda mucho con todas y cada una de las tareas relacionadas con la entrada de XNA, hace que lo que pidas sea fácil.

using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace YourNamespaceHere { /// <summary> /// an enum of all available mouse buttons. /// </summary> public enum MouseButtons { LeftButton, MiddleButton, RightButton, ExtraButton1, ExtraButton2 } public class InputHelper { private GamePadState _lastGamepadState; private GamePadState _currentGamepadState; #if (!XBOX) private KeyboardState _lastKeyboardState; private KeyboardState _currentKeyboardState; private MouseState _lastMouseState; private MouseState _currentMouseState; #endif private PlayerIndex _index = PlayerIndex.One; private bool refreshData = false; /// <summary> /// Fetches the latest input states. /// </summary> public void Update() { if (!refreshData) refreshData = true; if (_lastGamepadState == null && _currentGamepadState == null) { _lastGamepadState = _currentGamepadState = GamePad.GetState(_index); } else { _lastGamepadState = _currentGamepadState; _currentGamepadState = GamePad.GetState(_index); } #if (!XBOX) if (_lastKeyboardState == null && _currentKeyboardState == null) { _lastKeyboardState = _currentKeyboardState = Keyboard.GetState(); } else { _lastKeyboardState = _currentKeyboardState; _currentKeyboardState = Keyboard.GetState(); } if (_lastMouseState == null && _currentMouseState == null) { _lastMouseState = _currentMouseState = Mouse.GetState(); } else { _lastMouseState = _currentMouseState; _currentMouseState = Mouse.GetState(); } #endif } /// <summary> /// The previous state of the gamepad. /// Exposed only for convenience. /// </summary> public GamePadState LastGamepadState { get { return _lastGamepadState; } } /// <summary> /// the current state of the gamepad. /// Exposed only for convenience. /// </summary> public GamePadState CurrentGamepadState { get { return _currentGamepadState; } } /// <summary> /// the index that is used to poll the gamepad. /// </summary> public PlayerIndex Index { get { return _index; } set { _index = value; if (refreshData) { Update(); Update(); } } } #if (!XBOX) /// <summary> /// The previous keyboard state. /// Exposed only for convenience. /// </summary> public KeyboardState LastKeyboardState { get { return _lastKeyboardState; } } /// <summary> /// The current state of the keyboard. /// Exposed only for convenience. /// </summary> public KeyboardState CurrentKeyboardState { get { return _currentKeyboardState; } } /// <summary> /// The previous mouse state. /// Exposed only for convenience. /// </summary> public MouseState LastMouseState { get { return _lastMouseState; } } /// <summary> /// The current state of the mouse. /// Exposed only for convenience. /// </summary> public MouseState CurrentMouseState { get { return _currentMouseState; } } #endif /// <summary> /// The current position of the left stick. /// Y is automatically reversed for you. /// </summary> public Vector2 LeftStickPosition { get { return new Vector2( _currentGamepadState.ThumbSticks.Left.X, -CurrentGamepadState.ThumbSticks.Left.Y); } } /// <summary> /// The current position of the right stick. /// Y is automatically reversed for you. /// </summary> public Vector2 RightStickPosition { get { return new Vector2( _currentGamepadState.ThumbSticks.Right.X, -_currentGamepadState.ThumbSticks.Right.Y); } } /// <summary> /// The current velocity of the left stick. /// Y is automatically reversed for you. /// expressed as: /// current stick position - last stick position. /// </summary> public Vector2 LeftStickVelocity { get { Vector2 temp = _currentGamepadState.ThumbSticks.Left - _lastGamepadState.ThumbSticks.Left; return new Vector2(temp.X, -temp.Y); } } /// <summary> /// The current velocity of the right stick. /// Y is automatically reversed for you. /// expressed as: /// current stick position - last stick position. /// </summary> public Vector2 RightStickVelocity { get { Vector2 temp = _currentGamepadState.ThumbSticks.Right - _lastGamepadState.ThumbSticks.Right; return new Vector2(temp.X, -temp.Y); } } /// <summary> /// the current position of the left trigger. /// </summary> public float LeftTriggerPosition { get { return _currentGamepadState.Triggers.Left; } } /// <summary> /// the current position of the right trigger. /// </summary> public float RightTriggerPosition { get { return _currentGamepadState.Triggers.Right; } } /// <summary> /// the velocity of the left trigger. /// expressed as: /// current trigger position - last trigger position. /// </summary> public float LeftTriggerVelocity { get { return _currentGamepadState.Triggers.Left - _lastGamepadState.Triggers.Left; } } /// <summary> /// the velocity of the right trigger. /// expressed as: /// current trigger position - last trigger position. /// </summary> public float RightTriggerVelocity { get { return _currentGamepadState.Triggers.Right - _lastGamepadState.Triggers.Right; } } #if (!XBOX) /// <summary> /// the current mouse position. /// </summary> public Vector2 MousePosition { get { return new Vector2(_currentMouseState.X, _currentMouseState.Y); } } /// <summary> /// the current mouse velocity. /// Expressed as: /// current mouse position - last mouse position. /// </summary> public Vector2 MouseVelocity { get { return ( new Vector2(_currentMouseState.X, _currentMouseState.Y) - new Vector2(_lastMouseState.X, _lastMouseState.Y) ); } } /// <summary> /// the current mouse scroll wheel position. /// See the Mouse''s ScrollWheel property for details. /// </summary> public float MouseScrollWheelPosition { get { return _currentMouseState.ScrollWheelValue; } } /// <summary> /// the mouse scroll wheel velocity. /// Expressed as: /// current scroll wheel position - /// the last scroll wheel position. /// </summary> public float MouseScrollWheelVelocity { get { return (_currentMouseState.ScrollWheelValue - _lastMouseState.ScrollWheelValue); } } #endif /// <summary> /// Used for debug purposes. /// Indicates if the user wants to exit immediately. /// </summary> public bool ExitRequested { #if (!XBOX) get { return ( (IsCurPress(Buttons.Start) && IsCurPress(Buttons.Back)) || IsCurPress(Keys.Escape)); } #else get { return (IsCurPress(Buttons.Start) && IsCurPress(Buttons.Back)); } #endif } /// <summary> /// Checks if the requested button is a new press. /// </summary> /// <param name="button"> /// The button to check. /// </param> /// <returns> /// a bool indicating whether the selected button is being /// pressed in the current state but not the last state. /// </returns> public bool IsNewPress(Buttons button) { return ( _lastGamepadState.IsButtonUp(button) && _currentGamepadState.IsButtonDown(button)); } /// <summary> /// Checks if the requested button is a current press. /// </summary> /// <param name="button"> /// the button to check. /// </param> /// <returns> /// a bool indicating whether the selected button is being /// pressed in the current state and in the last state. /// </returns> public bool IsCurPress(Buttons button) { return ( _lastGamepadState.IsButtonDown(button) && _currentGamepadState.IsButtonDown(button)); } /// <summary> /// Checks if the requested button is an old press. /// </summary> /// <param name="button"> /// the button to check. /// </param> /// <returns> /// a bool indicating whether the selected button is not being /// pressed in the current state and is being pressed in the last state. /// </returns> public bool IsOldPress(Buttons button) { return ( _lastGamepadState.IsButtonDown(button) && _currentGamepadState.IsButtonUp(button)); } #if (!XBOX) /// <summary> /// Checks if the requested key is a new press. /// </summary> /// <param name="key"> /// the key to check. /// </param> /// <returns> /// a bool that indicates whether the selected key is being /// pressed in the current state and not in the last state. /// </returns> public bool IsNewPress(Keys key) { return ( _lastKeyboardState.IsKeyUp(key) && _currentKeyboardState.IsKeyDown(key)); } /// <summary> /// Checks if the requested key is a current press. /// </summary> /// <param name="key"> /// the key to check. /// </param> /// <returns> /// a bool that indicates whether the selected key is being /// pressed in the current state and in the last state. /// </returns> public bool IsCurPress(Keys key) { return ( _lastKeyboardState.IsKeyDown(key) && _currentKeyboardState.IsKeyDown(key)); } /// <summary> /// Checks if the requested button is an old press. /// </summary> /// <param name="key"> /// the key to check. /// </param> /// <returns> /// a bool indicating whether the selectde button is not being /// pressed in the current state and being pressed in the last state. /// </returns> public bool IsOldPress(Keys key) { return ( _lastKeyboardState.IsKeyDown(key) && _currentKeyboardState.IsKeyUp(key)); } /// <summary> /// Checks if the requested mosue button is a new press. /// </summary> /// <param name="button"> /// teh mouse button to check. /// </param> /// <returns> /// a bool indicating whether the selected mouse button is being /// pressed in the current state but not in the last state. /// </returns> public bool IsNewPress(MouseButtons button) { switch (button) { case MouseButtons.LeftButton: return ( _lastMouseState.LeftButton == ButtonState.Released && _currentMouseState.LeftButton == ButtonState.Pressed); case MouseButtons.MiddleButton: return ( _lastMouseState.MiddleButton == ButtonState.Released && _currentMouseState.MiddleButton == ButtonState.Pressed); case MouseButtons.RightButton: return ( _lastMouseState.RightButton == ButtonState.Released && _currentMouseState.RightButton == ButtonState.Pressed); case MouseButtons.ExtraButton1: return ( _lastMouseState.XButton1 == ButtonState.Released && _currentMouseState.XButton1 == ButtonState.Pressed); case MouseButtons.ExtraButton2: return ( _lastMouseState.XButton2 == ButtonState.Released && _currentMouseState.XButton2 == ButtonState.Pressed); default: return false; } } /// <summary> /// Checks if the requested mosue button is a current press. /// </summary> /// <param name="button"> /// the mouse button to be checked. /// </param> /// <returns> /// a bool indicating whether the selected mouse button is being /// pressed in the current state and in the last state. /// </returns> public bool IsCurPress(MouseButtons button) { switch (button) { case MouseButtons.LeftButton: return ( _lastMouseState.LeftButton == ButtonState.Pressed && _currentMouseState.LeftButton == ButtonState.Pressed); case MouseButtons.MiddleButton: return ( _lastMouseState.MiddleButton == ButtonState.Pressed && _currentMouseState.MiddleButton == ButtonState.Pressed); case MouseButtons.RightButton: return ( _lastMouseState.RightButton == ButtonState.Pressed && _currentMouseState.RightButton == ButtonState.Pressed); case MouseButtons.ExtraButton1: return ( _lastMouseState.XButton1 == ButtonState.Pressed && _currentMouseState.XButton1 == ButtonState.Pressed); case MouseButtons.ExtraButton2: return ( _lastMouseState.XButton2 == ButtonState.Pressed && _currentMouseState.XButton2 == ButtonState.Pressed); default: return false; } } /// <summary> /// Checks if the requested mosue button is an old press. /// </summary> /// <param name="button"> /// the mouse button to check. /// </param> /// <returns> /// a bool indicating whether the selected mouse button is not being /// pressed in the current state and is being pressed in the old state. /// </returns> public bool IsOldPress(MouseButtons button) { switch (button) { case MouseButtons.LeftButton: return ( _lastMouseState.LeftButton == ButtonState.Pressed && _currentMouseState.LeftButton == ButtonState.Released); case MouseButtons.MiddleButton: return ( _lastMouseState.MiddleButton == ButtonState.Pressed && _currentMouseState.MiddleButton == ButtonState.Released); case MouseButtons.RightButton: return ( _lastMouseState.RightButton == ButtonState.Pressed && _currentMouseState.RightButton == ButtonState.Released); case MouseButtons.ExtraButton1: return ( _lastMouseState.XButton1 == ButtonState.Pressed && _currentMouseState.XButton1 == ButtonState.Released); case MouseButtons.ExtraButton2: return ( _lastMouseState.XButton2 == ButtonState.Pressed && _currentMouseState.XButton2 == ButtonState.Released); default: return false; } } #endif } }

Solo cópielo en una clase separada y muévalo a su espacio de nombres, luego declare uno (variable inputHelper), inicialícelo en la parte inicialiaze y llame a inputHelper.Update () en su ciclo de actualización antes de la lógica de actualización. Luego, cuando necesite algo relacionado con la entrada, ¡solo use InputHelper! por ejemplo, en su situación, usaría InputHelper.IsNewPress ([tipo de botón / tecla de entrada aquí]) para verificar si desea mover el elemento del menú hacia arriba o hacia abajo. Para este ejemplo: inputHelper.IsNewPress (Keys.Down)


Lo que también puede hacer es crear una función que combine KyeUp y KeyDown que le indique cuándo se presionó una vez la tecla, solo en 1 ciclo de la actualización, de modo que solo funcione cada vez que presione la tecla nuevamente.


Ok, lo he descubierto. Primero, agregué un

private Keys keyPressed = Keys.None;

y en mi método Update (), hago lo siguiente:

KeyboardState keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyUp(keyPressed)) { keyPressed = Keys.None; } if (keyboardState.IsKeyDown(keyPressed)) { return; } // Some additionnal stuff is done according to direction if (keyboardState.IsKeyDown(Keys.Up)) { keyPressed = Keys.Up; } else if (keyboardState.IsKeyDown(Keys.Down)) { keyPressed = Keys.Down; }

Parece estar funcionando correctamente.


Pensé que las respuestas anteriores eran un poco demasiado complicadas, así que estoy dando esta aquí ...

Copie la clase de KeyPress a continuación en un nuevo archivo, declare las variables de KeyPress, inicialícelas en su método Initialize (). Desde allí, puedes hacer if ([yourkey].IsPressed()) ...

Nota: esta respuesta solo funciona para la entrada del teclado, pero debe ser fácilmente transferida a Gamepad o cualquier otra entrada. Creo que es mejor mantener el código para los diferentes tipos de entrada por separado.

public class KeyPress { public KeyPress(Keys Key) { key = Key; isHeld = false; } public bool IsPressed { get { return isPressed(); } } public static void Update() { state = Keyboard.GetState(); } private Keys key; private bool isHeld; private static KeyboardState state; private bool isPressed() { if (state.IsKeyDown(key)) { if (isHeld) return false; else { isHeld = true; return true; } } else { if (isHeld) isHeld = false; return false; } } }

Uso:

// Declare variable KeyPress escape; // Initialize() escape = new KeyPress(Keys.Escape) // Update() KeyPress.Update(); if (escape.IsPressed()) ...

Puede que me equivoque, pero creo que mi respuesta es más fácil en los recursos que en la respuesta aceptada y también más legible.


Puede almacenar en tiempo entero el valor de la última tecla presionada (izquierda, derecha ...) y si este tiempo es mayor que algún límite, puede sondear la nueva tecla presionada. Sin embargo, esto solo se puede hacer para el menú, porque en el juego necesitarías esa información inmediatamente.


Ranieri, ¿qué aspecto tiene? Me está costando hacer malabarismos con estos ciclos de actualización ...

Hmmmm ...

public static bool CheckKeyPress(Keys key) { return keyboardState.IsKeyUp(key) && lastKeyboardState.IsKeyDown(key); }

SetStates () es privado y se llama en la Actualización ()

private static void SetStates() { lastKeyboardState = keyboardState; keyboardState = Keyboard.GetState(); }

Aquí está la actualización ...

public sealed override void Update(GameTime gameTime) { // Called to set the states of the input devices SetStates(); base.Update(gameTime); }

He intentado agregar cheques adicionales ..

if (Xin.CheckKeyPress(Keys.Enter) || Xin.CheckButtonPress(Buttons.A)) { if (Xin.LastKeyboardState != Xin.KeyboardState || Xin.LastGamePadState(PlayerIndex.One) != Xin.GamePadState(PlayerIndex.One)) {

no parece tener ningún efecto notable, parece que no puedo frenar las confirmaciones del menú,


Sé que esto es antiguo, pero ¿qué tal ?: Agregar un diccionario seguro para hilos:

private ConcurrentDictionary<Keys, DateTime> _keyBounceDict = new ConcurrentDictionary<Keys, DateTime>();

Luego use este método para rastrear las teclas presionadas y determinar si hay un rebote de teclas:

/////////////////////////////////////////////////////////////////////////////////////////// /// IsNotKeyBounce - determines if a key is bouncing and therefore not valid within /// a certain "delay" period /////////////////////////////////////////////////////////////////////////////////////////// private bool IsNotKeyBounce(Keys thekey, double delay) { bool OKtoPress = true; if (_keyBounceDict.ContainsKey(thekey)) { TimeSpan ts = DateTime.Now - _keyBounceDict[thekey]; if (ts.TotalMilliseconds < _tsKeyBounceTiming) { OKtoPress = false; } else { DateTime dummy; _keyBounceDict.TryRemove(thekey, out dummy); } } else { _keyBounceDict.AddOrUpdate(thekey, DateTime.Now, (key, oldValue) => oldValue); } return OKtoPress; }

Aquí está lo que puse en mi método de actualización:

if (Keyboard.GetState().IsKeyDown(Keys.W)) { if (IsNotKeyBounce(Keys.W, 50.0)) _targetNew.Distance *= 1.1f; }

Uso 50 ms, pero puedes usar lo que tenga sentido para tu aplicación o vincularlo a GameTime o lo que sea ...


Si su aplicación es para una máquina con Windows, he tenido un gran éxito al utilizar esta clase basada en eventos que encontré aquí: publicación en el foro de gamedev.net

Maneja las pulsaciones de teclas típicas y las breves pausas antes de que comience la repetición, al igual que la entrada de texto normal en una aplicación de Windows. También se incluye el movimiento del ratón / eventos de la rueda.

Puede suscribirse a los eventos, por ejemplo, utilizando el siguiente código:

InputSystem.KeyDown += new KeyEventHandler(KeyDownFunction); InputSystem.KeyUp += new KeyEventHandler(KeyUpFunction);

Luego en los propios métodos:

void KeyDownFunction(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.F) facepalm(); } void KeyUpFunction(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.F) release(); }

...Etcétera. Realmente es una gran clase. He encontrado que su flexibilidad ha mejorado mucho con respecto al manejo del teclado predeterminado de XNA. ¡Buena suerte!


Una buena manera de lidiar con este tipo de cosas es almacenar un contador para cada clave que le interesa, que incrementa cada cuadro si la tecla está presionada y restablece a 0 si está arriba.

La ventaja de esto es que puede probar el estado absoluto de la tecla (si el contador no es cero, la tecla está abajo) y también puede verificar fácilmente si se ha pulsado este cuadro para ver los menús y similares (el contador es 1). La repetición de la tecla más se vuelve fácil (el contador% de demora de la repetición es cero).


la mejor manera de implementar esto es almacenar en caché el estado del teclado / gamepad de la instrucción de actualización que acaba de pasar.

KeyboardState oldState; ... var newState = Keyboard.GetState(); if (newState.IsKeyDown(Keys.Down) && !oldState.IsKeyDown(Keys.Down)) { // the player just pressed down } else if (newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down)) { // the player is holding the key down } else if (!newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down)) { // the player was holding the key down, but has just let it go } oldState = newState;

En su caso, es probable que solo desee moverse "hacia abajo" en el primer caso anterior, cuando se presionó la tecla.