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!


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.


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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.