【问题标题】:How to slow down or stop key presses in XNA如何在 XNA 中减慢或停止按键
【发布时间】:2010-10-28 14:45:23
【问题描述】:

我已经开始使用 XNA Framework 编写游戏,但遇到了一些我不知道如何正确解决的简单问题。

我正在使用 Texture2D 显示菜单并使用键盘(或游戏手柄)更改所选的菜单项。我的问题是当前用于在菜单项之间切换的功能太快了。我可能会单击向下按钮,它会向下移动 5 或 6 个菜单项(由于 Update() 被多次调用,从而更新所选项目)。

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

我正在寻找一种方法,让玩家多次单击向上/向下键以从一个菜单项转到另一个菜单项,或者在进入下一个菜单项之前有某种最短等待时间菜单项。

【问题讨论】:

    标签: c# xna


    【解决方案1】:

    实现这一点的最佳方法是从刚刚传递的更新语句中缓存键盘/游戏手柄状态。

    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;
    

    在您的情况下,您可能只想在上面的第一种情况下,当刚刚按下键时“向下”移动。

    【讨论】:

      【解决方案2】:

      我已经构建了一个(大型)类,它对任何和所有与 XNA 输入相关的任务都有很大帮助,它使您的要求变得容易。

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

      只需将它复制到一个单独的类文件中并将其移动到您的命名空间,然后声明一个(inputHelper 变量),在初始化部分对其进行初始化,并在更新逻辑之前在更新循环中调用 inputHelper.Update()。然后,每当您需要与输入相关的内容时,只需使用 InputHelper!例如,在您的情况下,您将使用 InputHelper.IsNewPress([type of input button/key here]) 来检查是否要向下或向上移动菜单项。对于这个例子:inputHelper.IsNewPress(Keys.Down)

      【讨论】:

        【解决方案3】:

        处理这种事情的一个好方法是为您感兴趣的每个键存储一个计数器,如果键按下,则每帧递增,如果按下则重置为 0。

        这样做的好处是,您可以测试键的绝对状态(如果计数器非零,则键按下),还可以轻松检查是否刚刚按下此帧以获取菜单等(计数器为 1)。加号键重复变得容易(计数器%重复延迟为零)。

        【讨论】:

        • 你真的想在这里监控 TIME,而不是简单的计数器。至少,如果您希望它以不同的渲染速度在不同的计算机上以相同的方式执行。
        • 除非你使用固定速率的逻辑更新,我几乎总是推荐。
        【解决方案4】:

        如果您的应用程序适用于 Windows 机器,那么我在使用我在这里找到的这个事件驱动类方面取得了巨大成功:gamedev.net forum post

        它处理典型的按键和重复开始之前的短暂暂停,就像 Windows 应用程序中的正常文本输入一样。还包括鼠标移动/滚轮事件。

        您可以订阅事件,例如,使用以下代码:

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

        然后在方法本身中:

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

        ...等等。这真是一堂很棒的课。我发现它的灵活性比 XNA 的默认键盘处理有了很大的提高。祝你好运!

        【讨论】:

        • 你能给这段代码更多的细节吗,我想我正在寻找这样的东西。如何添加 InputSystem.KeyDown += new KeyEventHandler(KeyDownFunction); .. ?我尝试键盘状态输入系统;但似乎不对。
        【解决方案5】:

        我认为之前的答案有点过于复杂,所以我在这里给出这个......

        将下面的 KeyPress 类复制到一个新文件中,声明 KeyPress 变量,在 Initialize() 方法中初始化它们。从那里你可以做if ([yourkey].IsPressed()) ...

        注意:此答案仅适用于键盘输入,但应该可以轻松移植到游戏手柄或任何其他输入。我认为将不同类型输入的代码分开比较好。

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

        用法:

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

        我可能错了,但我认为我的答案在资源上比公认的答案更容易,而且更具可读性!

        【讨论】:

          【解决方案6】:

          您可以存储从最后一次按下的键(左、右...)开始的整数值时间,如果该时间大于某个限制,您可以轮询是否按下了新键。但是,这只能针对菜单进行,因为在游戏中您会立即需要该信息。

          【讨论】:

            【解决方案7】:

            您还可以做的是让自己成为一个结合了 KyeUp 和 KeyDown 的函数,它会在按键被按下一次时告诉您,仅在更新的 1 个循环中,因此它仅在您每次再次按键时才起作用。

            【讨论】:

              【解决方案8】:

              好的,我想通了。首先,我添加了一个

              private Keys keyPressed = Keys.None;
              

              在我的 Update() 方法中,我执行以下操作:

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

              它似乎工作正常。

              【讨论】:

              • 似乎有点不稳定,从这里的代码来看,keyPressed 设置为相同的值(即 Keys.None)。还缺什么吗?
              • @Spoike:你说得对,我忘了提到 keyPressed 是在 // 检查新的游戏手柄按下时定义的。代码已添加。
              • 我一定遗漏了一些东西,但在我看来,您正在覆盖最后一个“if”中的状态。如果用户同时按下“上”和“下”,您将只记得“上”。您不想同时处理多个键吗?这听起来像是游戏中的一个严重限制。
              • @Ranieri:我不记得两者(上/下),因为此代码仅用于菜单中,玩家想要从实际选项向上或向下选择一个选项,目标这是限制菜单项的上/下选择。由于 update() 函数在一秒钟内被多次调用,因此出现了问题,这是对这个问题的一个小修复。
              【解决方案9】:

              我保存了上次更新运行的 GamePadState 和 KeyboardState。在下一次更新运行时,我检查上次运行时未按下但现在按下的按钮。然后我保存当前状态。

              我将所有这些都包含在一个静态类中,我可以使用它来查询特定按钮和/或获取自上次更新以来按下的按钮列表。这使得同时使用多个键变得非常容易(你在游戏中肯定想要的东西),并且可以很容易地扩展到和弦。

              【讨论】:

                【解决方案10】:

                拉涅利,那看起来像什么?我很难应付这些更新周期...

                嗯嗯……

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

                SetStates() 是私有的,它在 Update() 中调用

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

                这里是更新...

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

                我已尝试添加额外检查..

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

                似乎没有任何明显的效果 - 我似乎无法减慢菜单确认速度,

                【讨论】:

                  【解决方案11】:

                  你可以做的是这样的事情(也会跟踪每个键)

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

                  通过这种方式,您可以检查每个键。您也可以通过创建单独的 DateTimes 和单独的 bool 值来为每个键执行此操作。

                  【讨论】:

                    【解决方案12】:

                    我知道这是旧的,但是如何: 添加线程安全字典:

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

                    然后用这个方法来跟踪按下的按键,判断是否有按键弹跳:

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

                    这是我在 Update 方法中添加的内容:

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

                    我使用 50 毫秒,但您可以使用对您的应用有意义的任何内容,或者将其绑定到 GameTime 或其他任何内容...

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-11-24
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多