Обнаружение «любого нажатия кнопки»

10

Я пытаюсь позволить игроку нажать любую кнопку, чтобы продолжить с главной страницы. Я смог сделать это, составив список кнопок, просматривая их и проверяя, не работает ли одна из них; Тем не менее, я чувствую, что этот код выглядит некрасиво, и мне интересно, есть ли более простой способ сделать это, о котором я просто не думаю?

Вот как выглядит мой код сейчас:

            if (GamePad.GetState(PlayerIndex.One).IsConnected)
            {
                var buttonList = new List<Buttons>()
                {
                    {Buttons.A},
                    {Buttons.B},
                    {Buttons.Y},
                    {Buttons.X},
                    {Buttons.Start},
                    {Buttons.Back},
                    {Buttons.RightShoulder},
                    {Buttons.LeftShoulder},
                    {Buttons.RightTrigger},
                    {Buttons.LeftTrigger}
                };

                foreach (var button in buttonList)
                {
                    if (GamePad.GetState(PlayerIndex.One).IsButtonDown(button))
                        ExitMainMenu= true;
                }
            }
LogicaLInsanity
источник
Лично я бы просто сделал большой цикл IF, в отличие от создания массива и цикла.
jgallant
@Jon Что такое большой цикл ЕСЛИ и почему он лучше?
craftworkgames
Я люблю все ответы, которые получает этот вопрос. Я думаю, что @Katu получил "правильный" ответ, хотя.
Сет Бэттин

Ответы:

10

Это должно сделать работу. В конце каждого цикла обновления сохраняйте состояние previousGamePadState. Тогда вы можете сравнить их. Это быстрый способ обнаружить изменения. Не надо зацикливаться.

GamePadState.PacketNumber :

Вы можете использовать PacketNumber, чтобы определить, изменилось ли состояние ввода. Если значение PacketNumber остается неизменным между двумя последовательными вызовами GetState, то входные данные не изменились.

public bool HasInputChanged(GamePadState previousGamePadState, bool ignoreThumbsticks)
{ 
    GamePadState currentState = GamePad.GetState( PlayerIndex.One );
    if ((currentState.IsConnected) && (currentState.PacketNumber != previousGamePadState.PacketNumber))
    {
        //ignore thumbstick movement
        if ((ignoreThumbsticks == true) && ((currentState.ThumbSticks.Left.Length() != previousGamePadState.ThumbSticks.Left.Length() )&&(currentState.ThumbSticks.Right.Length() != previousGamePadState.ThumbSticks.Right.Length()) ))
            return false;
        return true
    }
    return false;
}

РЕДАКТИРОВАТЬ: Изменено на метод. Это не гарантировано, чтобы работать правильно, как есть, но должно работать. Кроме того, потому что это действительно обнаруживает изменения в вводе, поэтому, если пользователь отпускает кнопку, это видно и с этим. Я также добавил, ifчтобы обнаружить движение большого пальца, чтобы вы могли игнорировать их по крайней мере.

Надеюсь, это поможет вам. Дайте мне знать, если это не соответствует вашим потребностям, я уверен, что мы можем решить это.

Как: определить, была ли нажата кнопка контроллера в этом кадре GamePadState.PacketNumber Свойство

Кату
источник
Есть аналогичный способ написать это для GamePadStateи enum Buttons, который ближе к контексту, который использует OP.
Сет Бэттин
1
Не следует ничего отвечать до утреннего кофе :)
Katu
1
Теперь он делает свою работу, и он не может получить быстрее, чем это.
Кату
Вау, совершенно другой метод, и я думаю, что вы правы в том, что он самый быстрый. Ницца.
Сет Бэттин
Это обнаруживает только нажатия кнопок, или это также обнаруживает нажатия кнопки?
Джордж Дакетт
1

Если вы не возражаете против использования Reflection, вы можете использовать что-то вроде этого (возможно, даже это точно):

        var properties = typeof(GamePadButtons).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var property in properties)
        {
            var value = property.GetValue(GamePad.GetState(PlayerIndex.One).Buttons);
            if (value is ButtonState && (ButtonState)value == ButtonState.Pressed)
                ExitMainMenu = true;
        }
Pandacoder
источник
1

Вы можете вручную создать пустойGamePadState , а затем проверить его на (в) равенство с текущим реальным, который вы вызываете, вызывая GamePad.GetState.

playerInput = GamePad.GetState(PlayerIndex.One);  
emptyInput = new GamePadState(Vector2.Zero, Vector2.Zero, 0, 0);
if (playerInput != emptyInput){

    // yay!!!!, a button push!
    // 
    // P.S., remember to allow any PlayerIndex to take control of the the game 
    // from the main menu.  It sucks when you pick up controller2 and it doesn't work.

}
Сет Баттин
источник
Я понятия не имею, работает ли это; Я никогда не пытался это сделать. Дайте мне знать, если это сработает для вас.
Сет Бэттин,
Умная идея, хотя она будет работать, только если GamePadState переопределит Equals, что маловероятно. Скорее всего, он будет использовать ссылочное равенство и, следовательно, вышеприведенное выражение if никогда не будет иметь значение true.
craftworkgames
@craftworkgames Equalsотличается от других; он сравнивает две ссылки как один и тот же экземпляр. Но GamePadStateперегружает ли оператор == для сравнения их значений, на которые я ссылался в своем ответе ( op_Equality).
Сет Бэттин
На самом деле я не осознавал, что GamePadState - это структура, которая, вероятно, будет работать. Технически, однако, поведение Equals и == часто одинаково, конечно, это зависит от реализации, но рекомендации рекомендуют это таким образом. Если вы хотите истинно равенство ссылок вы есть также object.ReferenceEquals msdn.microsoft.com/en-us/library/bsc2ak47.aspx
craftworkgames
Ах, вы правы, GamePadState является типом значения, так что это не имеет значения. Независимо от того, == перегружен, может также использовать его IMO.
Сет Бэттин
1

Поскольку кнопки - это перечисление, вы можете использовать метод Enum.GetValues, например:

var buttonList = (Buttons[])Enum.GetValues(typeof(Buttons));

foreach (var button in buttonList)
{
    if (GamePad.GetState(PlayerIndex.One).IsButtonDown(button))
        ExitMainMenu= true;
}
craftworkgames
источник