为阅读XNA菜单的Xbox360指拨时是否需要非零阈值以防止轻拂? [英] Is a non-zero threshold required to prevent flicking when reading the Xbox360 thumbstick for an XNA menu?

查看:90
本文介绍了为阅读XNA菜单的Xbox360指拨时是否需要非零阈值以防止轻拂?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我游戏中的垂直菜单允许您在指尖上按向上或向下以跳到下一个(或上一个)菜单项.我通过存储旧的指杆状态来实现这一点.如果状态为零,但现在不为零,则选择下一个(或上一个)菜单项.

The vertical menus in my game allow you to press up or down on the thumbstick to jump to the next (or previous) menu item. I implement this by storing the old thumbstick state. If the state was zero and is now non-zero, the next (or previous) menu item is selected.

我从未在连接到PC或Xbox的Xbox控制器上注意到此实现的任何轻弹".我已经测试了几个控制器.

I have never noticed any "flicking" with this implementation either on Xbox controller attached to a PC or an Xbox. I have tested with several controllers.

但是,当我回答问题

However when I answered the question question XNA - how to tell if a thumb stick was "twitched" in a certain direction, Andrew Russell commented:

虽然这是正确的主意, 阈值必须高于零(对于 在菜单中使用),并且需要有一个 激活和激活之间的余量 停用以防止其滑动.

While this is the right idea, the threshold needs to be above zero (for use in menus), and there needs to be a margin between activation and deactivation to prevent it flicking.

我的理解是Xna已经在拇指输入上提供了过滤和死区",并且不需要阈值或裕量来防止轻拂.安德鲁的声明令我担心.

My understanding is that Xna already provides filtering and a "dead-zone" on the thumb-stick input and that no threshold or margin is necessary to prevent flicking. Andrew's statement worried me.

是否存在需要阈值或边距以防止轻拂"的控制器?

为了安全起见,我应该在阈值和边距中进行编码吗?

以下代码是我的XNA菜单输入轮询方法的最小实现.唯一的区别是,在控件的值在同一方向上短时不为零后,我的实际菜单会自动滚动.与该问题有关的逻辑在ProcessUserInput函数中.

The following code is a minimal implementation of my method of input polling for XNA menus. The only difference is that my actual menus autoscroll after the control's value has been non-zero in the same direction for a short while. The logic related to this question is in the ProcessUserInput function.

球代表活动菜单项.向上或向下按左拇指拨杆,将球跳到下一个/上一个菜单项.我无法将它变成闪烁".

The ball represents the active menu item. Press the left thumbstick up or down to jump the ball to the next/previous menu item. I can't get it to "flicker".

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace WindowsGame
{
    public class Ball
    {
        public float RADIUS = DIAMETER * 0.5f;
        const int DIAMETER = 40;
        static readonly uint WHITE = Color.White.PackedValue;
        static readonly uint BLACK = new Color(0, 0, 0, 0).PackedValue;

        Texture2D m_texture;

        public Ball(GraphicsDevice graphicsDevice)
        {
            m_texture = new Texture2D(graphicsDevice, DIAMETER, DIAMETER);

            uint[] data = new uint[DIAMETER * DIAMETER];

            for (int i = 0; i < DIAMETER; i++)
            {
                float iPosition = i - RADIUS;

                for (int j = 0; j < DIAMETER; j++)
                {
                    data[i * DIAMETER + j] = new Vector2(iPosition, j - RADIUS).Length() <= RADIUS ? WHITE : BLACK;
                }
            }

            m_texture.SetData<uint>(data);
        }

        public Vector2 Position { get; set; }

        private Rectangle DrawRectangle
        {
            get
            {
                return new Rectangle((int)Math.Round(Position.X - RADIUS), (int)Math.Round(Position.Y - RADIUS), DIAMETER, DIAMETER);
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(m_texture, DrawRectangle, Color.White);
        }
    }

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Matrix viewMatrix;
        Matrix inverseViewMatrix;
        Ball ball;
        GamePadState m_lastGamePadState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            ball = new Ball(GraphicsDevice);
            viewMatrix = Matrix.CreateTranslation(Window.ClientBounds.Width * 0.5f, Window.ClientBounds.Height * 0.5f, 0.0f);
            inverseViewMatrix = Matrix.Invert(viewMatrix);
            m_lastGamePadState = GamePad.GetState(PlayerIndex.One);
            base.Initialize();
        }

        private void ProcessUserInput()
        {
            GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);

            if (m_lastGamePadState.ThumbSticks.Left.Y == 0.0f)
            {
                ball.Position += Vector2.UnitY * (-Math.Sign(gamePadState.ThumbSticks.Left.Y) * ball.RADIUS * 2.0f);
            }

            m_lastGamePadState = gamePadState;
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            ProcessUserInput();
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, viewMatrix);
            ball.Draw(spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

推荐答案

基本上是让控件感觉好".

需要将阈值设置为零以上(因为摇杆永远不会精确地位于零上).死区算作一个阈值,但很小很小.我认为默认的XNA死区约为0.24.这太小了,无法在菜单中使用.

Setting a threshold above zero is required (because the sticks are never exactly on zero). The dead-zone counts as a threshold, but it's very small. I think the default XNA dead-zone is about 0.24. This is way too small to use in a menu.

怀疑-但是我现在无法测试-XNA的按按钮解释"代码使用与激活相同的,微小的,不令人满意的死区阈值.

I suspect - but I am not in a position to test this right now - that XNA's interpret-the-thumbsticks-as-buttons code uses the same, tiny, unsatisfying dead zone as its activation threshold.

从您链接的答案中可以看到,我将激活阈值设置为0.85,这要高得多.诚然,我的代码不适用于菜单.菜单的调整可能要小一些,但仍不如默认的死区小.

As you can see from my answer you linked, I set an activation threshold at 0.85, which is considerably higher. Admittedly, my code is not for a menu. The tuning for a menu might be a bit smaller, but still not as small as the default dead-zone.

对于边距(例如:在0.85处激活,在0.75处停用).当您专门响应"off-on-off"过渡时,要获得令人满意的感觉,这是特别需要的.当您仅检测到"on"状态时,并没有必要.

As for the margin (eg: activate at 0.85, deactivate at 0.75). This is particularly required to get a satisfying feel when you're specifically responding to an "off-on-off" transition. It is not really necessary when you're simply detecting the "on" state.

这还可以防止您将摇杆运动解释为按下按钮(例如菜单),并且在极少数情况下可能会收到虚假的双击.

It also prevents the situation where you're interpreting stick movement as button presses (as you might for a menu) and may, on rare occasion, receive a spurious double-press.

这篇关于为阅读XNA菜单的Xbox360指拨时是否需要非零阈值以防止轻拂?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆