Entrada versus entrada orientada a eventos

19

Estou desenvolvendo um jogo usando pesquisas para o método de entrada. No entanto, agora que estou aprofundando os menus do jogo e outros componentes da interface do usuário, estou descobrindo que provavelmente gostaria de ter uma entrada orientada a eventos. Talvez até tendo os dois, usando eventos direcionados para a interface do usuário e sondando a entrada "mundo". Estou curioso para saber qual é o melhor caminho a percorrer.

Estou definindo a pesquisa como: a cada ciclo de atualização, verifico quais teclas são pressionadas, onde está o mouse, os botões pressionados, depois os percorremos e executamos ações com base nas informações coletadas.

Estou definindo evento orientado como: eventos baseados em interrupção, quando um evento acontece e a interrupção é acionada e um bloco de código é executado com base no evento.

Você acha que é melhor seguir todos os eventos, todas as pesquisas ou é aceitável uma combinação de ambos? Se você tem prós e contras, liste-os. Obrigado.

EDITAR

O jogo é baseado em Java / OpenGL, por isso será lançado no Windows / Mac / Linux. A possibilidade de estender isso para dispositivos móveis é baixa. O jogo é estilo RTS, terceira pessoa 3D.

EDIT 2

Ainda não estou totalmente satisfeito com a maneira como implementei isso, mas o que estou buscando é capturar eventos na minha interface do usuário e se eles não forem tratados por nenhum dos meus componentes da interface do usuário, passo o evento para o diretório "Mundo" para picking / seleção. Algo como:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

Dessa forma, não recebo cliques vazando pela interface do usuário para selecionar objetos atrás dos botões e o que não.

Atualmente, meus controles de câmera ainda são baseados em pesquisas, e isso parece estar funcionando por enquanto, mas posso atualizá-los mais tarde.

Agradeço todas as respostas, desculpe, eu só poderia escolher uma!

MichaelHouse
fonte
6
Não tenho certeza em Java, mas em geral você sempre precisa pesquisar dados. Você pode publicar eventos quando as coisas mudarem, mas isso ainda é baseado em um sistema de pesquisa.
James
O ponto de foco mais relevante na minha opinião é projetar um loop de eventos livre de qualquer outra carga que não seja a coleção de entrada. Deixe-me explicar: o sistema operacional fará a interrupção controlada por entrada e a tratará no "encadeamento de entrada" global; esse encadeamento do SO redirecionará as mensagens para o aplicativo atualmente em foco e gravará as informações na fila de mensagens. A fila de mensagens deve ser pesquisada por PeekMessage ou GetMessage. A maneira mais rápida de conseguir isso é usar o GetMessage e deixar o agendador acordá-lo. Você pode marcar a mensagem com muito tempo.
precisa saber é o seguinte

Respostas:

17

Depende dos requisitos do seu jogo e hardware. A maioria dos jogos geralmente está interessada em alterações no estado de entrada, ou seja, o usuário pressiona a tecla de disparo e sua arma começa a disparar, o usuário libera a tecla de disparo e sua arma para de disparar, o usuário pressiona a tecla de movimento e começa a se mover, solta a tecla de movimento e para de se mover , etc., para que um sistema de entrada orientado a eventos faça mais sentido nesses casos, pois as informações já estão em um formato adequado. Além disso, na plataforma Windows, você já recebe eventos para alterações no estado do teclado e do mouse; portanto, geralmente é uma conversão 1: 1 de eventos de entrada de baixo nível para eventos de jogo de alto nível. Com a pesquisa, muitas vezes você terá que gerar esses eventos manualmente comparando o estado entre o quadro atual e o último. Basicamente, "quais botões foram pressionados agora?"

Dito isto, em certas plataformas, você fica preso com a entrada de sondagem em um nível baixo e não há como evitar a verificação de borda. No entanto, sempre obtive os melhores resultados usando eventos para toda a lógica de alto nível, pois é assim que esses sistemas tendem a operar.

Skyler York
fonte
Obrigado, incluímos informações adicionais sobre a plataforma e o objetivo do jogo.
MichaelHouse
1
Observe que GetAsyncKeyStateé uma maneira simples de usar a pesquisa no Win32.
quer
Derp, fiz uma pergunta nos comentários de Nate Bross com os quais você lida aqui, então acho que vou refinar. Todos os PCs oferecem essa interrupção de hardware 1: 1 no relacionamento de eventos do teclado do SO e que tipo de plataforma é limitada à pesquisa de baixo nível?
Michael.bartnett
@Macke: às vezes, o antivírus relata programas que usam essa API porque podem receber pressionamentos de tecla de todo o sistema global, permitindo assim o registro de chaves malicioso. O artigo mais impressionante sobre ele em toda a internet (eu saiba) é esta: securelist.com/analysis/publications/36358/...
v.oddou
7

Não vejo razão para que você não possa fazer as duas coisas e obter o melhor dos dois mundos.

Eventos de entrada são gerados por polling (em algum nível, o driver faz uma sondagem no hardware para ver em que estado está) e, como o loop principal faz uma sondagem em todos os dispositivos de entrada, você pode facilmente implementar o seu. Algo simples como abaixo é o que eu usei no passado.

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

Eu sei que você definiu eventos como interrupções e o que eu coloquei aqui não é "verdadeiramente baseado em eventos", mas não vejo o que a descrição acima não fornece que interrupções causam - a maioria dos usuários não notará o único quadro perdido, a menos que seu jogo seja executado em uma taxa de quadros muito baixa.

Nate
fonte
1
Estou curioso sobre a natureza de obter informações dos dispositivos. Os eventos de teclado despachados pelo sistema operacional são o resultado de pesquisas no nível do driver de dispositivo? Ou um evento do teclado corresponde a uma interrupção? Ou há interrupções, mas o sistema operacional as armazena em buffer e as despacha quando achar necessário?
Michael.bartnett
Não sou positivo em como ele funciona nesse nível, mas é mais básico: alguns softwares são executados em loop e verificam o estado do teclado e o comparam ao estado anterior, se alterado, a alteração é alterada.
Nate
5

Existem dois problemas diferentes aqui:

  1. Como você lê a entrada do usuário no SO / hardware?

  2. Como você processa a entrada do usuário no seu mecanismo?

Para a leitura, isso depende claramente da sua plataforma e do tipo de entrada que você deseja ler. Observe que é fácil converter uma coisa para outra na sua camada de entrada. (Ou seja, aponte e emita eventos para o mecanismo ou ouça eventos e emita estado para o mecanismo.)

Para o processamento, existem algumas opções diferentes:

  • Para controle de movimento do jogador (e esquemas semelhantes), a pesquisa pode ser mais simples, pois você precisa recalcular a velocidade de cada quadro. É muito provável que seu loop interno seja baseado em pesquisas:

    ou seja, algo como speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Para eventos discretos (míssil de fogo, jogo de pausa, teletransporte para o outro lado do planeta), o processamento de eventos é preferível; caso contrário, seu código será repleto de maybeLaunchMissile(key_state);chamadas, e isso é ... ruim, tudo bem. ;)

Espero que ajude.

Macke
fonte