Detectando “Qualquer Botão Pressione”

10

Estou tentando permitir que o player pressione qualquer botão para continuar na página principal. Consegui fazer isso fazendo uma Lista de botões, passando por eles e verificando se um deles estava inativo; no entanto, sinto que esse código é meio feio e me pergunto se existe uma maneira mais simples de fazer isso em que simplesmente não estou pensando?

Aqui está o que meu código se parece agora:

            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
fonte
Pessoalmente, eu faria um grande loop de IF, em vez de criar uma matriz e um loop.
Jgallant
@ Jon O que é um grande loop de IF e por que seria melhor?
Craftworkgames
Eu amo toda a resposta que esta pergunta está recebendo. Acho que @Katu obteve a resposta "correta".
Seth Battin

Respostas:

10

Isso deve fazer o trabalho. No final de cada loop de atualização, salve o estado de previousGamePadState. Então você pode compará-los. Esta é uma maneira rápida de detectar alterações. Não há necessidade de loop.

GamePadState.PacketNumber :

Você pode usar o PacketNumber para determinar se o estado de entrada foi alterado. Se o valor de PacketNumber permanecer o mesmo entre duas chamadas seqüenciais para GetState, não houve alteração na entrada.

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

EDIT: Alterado para o método. Não é garantido que funcione corretamente como está, mas deve funcionar. Além disso, como isso realmente detecta alterações na entrada, por isso, se o usuário libera o botão, isso também é visto. Eu também adicionei ifpara detectar o movimento do dedo polegar, para que você possa ignorá-los pelo menos.

Espero que isso ajude você. Deixe-me saber, se não atender às suas necessidades, tenho certeza de que podemos resolver isso.

Como detectar se um botão do controlador foi pressionado neste quadro Propriedade GamePadState.PacketNumber

Katu
fonte
Existe uma maneira análoga de escrever isso para GamePadStatee enum Buttons, que é mais próximo do contexto que o OP parece estar usando.
Seth Battin
1
Não deve responder nada antes do café da manhã :)
Katu
1
Agora ele faz o trabalho e não pode ficar mais rápido que isso.
Katu
Uau, método totalmente diferente, e acho que você está certo sobre ser o mais rápido. Agradável.
Seth Battin
Isso detecta apenas pressionamentos de botão ou também detecta liberações de botão?
George Duckett
1

Se você não se importa com o uso do Reflection, pode usar algo assim (possivelmente até exatamente isso):

        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
fonte
1

Você pode construirGamePadState manualmente um vazio e, em seguida, verificar a igualdade (in) com o real atual, que você busca chamando 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.

}
Seth Battin
fonte
Não tenho ideia se isso funciona; Eu nunca tentei fazer isso. Deixe-me saber se funciona para você.
Seth Battin
Idéia inteligente, embora só funcione se o GamePadState substituir o Equals, o que é improvável. Muito provavelmente, ele usará a igualdade de referência e, portanto, a instrução if acima nunca será avaliada como verdadeira.
Craftworkgames
@craftworkgames Equalsé diferente; ele compara duas referências por ser a mesma instância. Mas GamePadStatesobrecarrega o operador == para comparar seus valores, aos quais vinculei na minha resposta ( op_Equality).
Seth Battin
Na verdade, eu não sabia que o GamePadState era uma estrutura que provavelmente funcionaria. Tecnicamente, porém, o comportamento de Igual a e == geralmente é o mesmo, é claro, depende da implementação, mas as diretrizes o recomendam dessa maneira. Se você quer verdadeiramente a igualdade de referência que há também Object.ReferenceEquals msdn.microsoft.com/en-us/library/bsc2ak47.aspx
craftworkgames
Ah, você está certo, o GamePadState é do tipo valor, portanto não é relevante. Independentemente, == está sobrecarregado, também pode usá-lo IMO.
Seth Battin
1

Como Buttons é uma enumaration, você pode usar o método Enum.GetValues como este:

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

foreach (var button in buttonList)
{
    if (GamePad.GetState(PlayerIndex.One).IsButtonDown(button))
        ExitMainMenu= true;
}
artesanato
fonte