How to slow down or stop key presses in XNA

后端 未结 12 2116
北恋
北恋 2021-02-01 05:38

I\'ve begun writing a game using XNA Framework and have hit some simple problem I do not know how to solve correctly.

I\'m displaying a menu using Texture2D and using th

相关标签:
12条回答
  • 2021-02-01 06:05

    I thought the previous answers were a bit over-complicated, so I'm giving this one here...

    Copy the KeyPress class below in a new file, declare the KeyPress variables, initialize them in your Initialize() method. From there you can do if ([yourkey].IsPressed()) ...

    Note: this answer works only for Keyboard input, but it should be easily ported to Gamepad or any other input. I think keeping the code for the different types of input separate is better.

    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;
            }
        }
    }
    

    Usage:

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

    I might be wrong, but I think my answer is easier on resources than the accepted answer and also more readable!

    0 讨论(0)
  • 2021-02-01 06:05

    I save the GamePadState and KeyboardState from the previous update run. At the next update run i check for buttons that were not pressed last run, but are pressed now. Then I save the current state.

    I have all of this wrapped up in a static class that I can use to query for specific buttons and/or get a list of pressed buttons since the last update. This makes it really easy to work with multiple keys simultaneously (something you certainly want in games) and it would be trivially extensible to chords.

    0 讨论(0)
  • 2021-02-01 06:06

    Ok, I've figured it out. First, I added a

    private Keys keyPressed = Keys.None;
    

    and in my Update() method, I do the following:

     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;
    }
    

    It seems to be working correctly.

    0 讨论(0)
  • 2021-02-01 06:07

    Well what you could do is something like this (Also will track every key)

    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;
        }
    }
    

    By doing it this way you're able to check every key. You could also do this for just every key by create separate DateTimes and seperate bool values.

    0 讨论(0)
  • 2021-02-01 06:10

    the best way to implement this is to cache the keyboard/gamepad state from the update statement that just passed.

    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;
    

    In your case, you probably only want to move "down" in the first case above, when the key was just pressed.

    0 讨论(0)
  • 2021-02-01 06:15

    If your application is for a Windows machine, I've had great success using this event driven class that I found here: gamedev.net forum post

    It handles typical key presses and the short pauses before the repeating starts, just like normal text entry in a Windows application. Also included is mouse move/wheel events.

    You can subscribe to the events, for example, using the following code:

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

    Then in the methods themselves:

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

    ...and so forth. It really is a great class. I've found it's flexibility much improved over XNA's default keyboard handling. Good Luck!

    0 讨论(0)
提交回复
热议问题