如何减慢或停止XNA中的按键操作

tom*_*mzx 21 c# xna

我已经开始使用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
Run Code Online (Sandbox Code Playgroud)

我想要的是让玩家多次点击向上/向下键以便从一个菜单项转到另一个菜单项,或者在进入下一个菜单项之前有一些最小等待时间的方法.

Joe*_*nez 26

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

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;
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可能只想在上面的第一种情况下"向下"移动,只需按下按键即可.


RCI*_*CIX 18

我已经构建了一个(大)类,可以帮助解决任何和所有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
    }
}
Run Code Online (Sandbox Code Playgroud)

只需将其复制到一个单独的类fie中并将其移动到命名空间,然后声明一个(inputHelper变量),在initialiaze部分初始化它,并在更新逻辑之前在更新循环中调用inputHelper.Update().然后,只要您需要与输入相关的内容,只需使用InputHelper!例如,在您的情况下,您将使用InputHelper.IsNewPress([输入按钮/键的类型])来检查是否要向下或向上移动菜单项.对于此示例:inputHelper.IsNewPress(Keys.Down)


Jam*_*and 6

处理这类事情的一个很好的方法是为你感兴趣的每个键存储一个计数器,如果键是关闭的话你会增加每一帧,如果它关闭则重置为0.

这样做的好处是,您可以测试密钥的绝对状态(如果计数器非零,密钥已关闭),并且还可以轻松检查是否只是按下此框架的菜单等(计数器是1).加上键重复变得容易(计数器%重复延迟为零).