Removendo o atraso no início de um pressionamento de tecla

11

Estou fazendo um jogo simples, e um dos problemas que encontrei é o atraso irritante ao pressionar uma tecla continuamente.

Então, basicamente, quando eu pressiono (por muito tempo), por exemplo Up, meu objeto move 1 unidade para cima, não move (por aproximadamente 1 segundo) e depois move continuamente 1 unidade para cima (sem atrasos).

Atualmente, eu uso isso para mover o objeto (SDL2):

while (SDL_PollEvent(&event))
{
    switch (event.type)
    {
    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_UP:
            //Move object 1 unit up
            break;
        //Other unrelated things omitted
        }
        break;
    //Omitted other cases
    }
}

O que eu gostaria de ter é remover o atraso, para que o objeto possa se mover imediatamente Upmuito rapidamente. Há alguma maneira de fazer isso?

Rakete1111
fonte

Respostas:

19

Ao esperar que os eventos de pressionamento de tecla sejam acionados, você provavelmente estará à mercê da taxa de repetição de eventos-chave que o SO controla (e quais usuários podem se especificar).

Em vez disso, convém chamar SDL_GetKeyboardStatena parte superior do loop de atualização do jogo (a parte da atualização que ocorre a cada quadro, independentemente de um evento ter ou não chegado) para obter o estado do teclado e verificar se o A tecla está pressionada ou não durante qualquer quadro individual.


fonte
Não seria melhor ouvir as mensagens da janela? Às vezes, usando a pesquisa, sinto falta de teclas muito curtas e esse problema piora quando a taxa de quadros é baixa.
Roy T.
@RoyT. Realmente depende do seu jogo e do tipo de ação que você deseja acionar com a tecla. Se o pressionamento de tecla for uma coisa única, como uma tecla de "ação", que fecha uma caixa de diálogo, uma fila de mensagens é a abordagem correta - você deseja ouvir um evento atômico. - Se, por outro lado, o status da chave representa um estado em andamento como uma tecla "mover", a lógica é geralmente while key UP is down move 30 units per second- e por segundo só faz sentido quando você tem um tempo mensurável entre a tecla pressionada e a tecla ativada - geralmente mais de um quadro.
Falco
@RoyT. Você também pode ouvir as mensagens (e usá-las para atualizar sua própria matriz de estados do teclado); Optei por sugerir essa abordagem por sua simplicidade. Você certamente pode escrever outra resposta. A parte importante é apenas evitar confiar nas mensagens do SO para verificar se a chave está continuamente inativa, porque é isso que o leva à taxa de repetição da chave do SO.
E por quadro você quer dizer jogo tick, não quadro de vídeo, certo? Porque não estamos sendo plebeus e codificando a lógica do jogo no loop de renderização. :-)
corsiKa
@ JoshPetrie Concordo plenamente, só queria apontar esta pequena advertência se você precisar verificar um 'clique' em vez de uma 'imprensa'. :)
Roy T.
10

Uma maneira alternativa (a abordagem de Josh também é ótima!) Seria configurar um booleano SDL_KEYDOWNe possivelmente também ignorar todos os principais eventos repetidos. Isso você pode fazer verificando o repeatmembro do evento principal.

Então você pode implementar seu próprio cronômetro, que não precisa ser nada extravagante, e implementar a repetição de teclas. Você pode acionar a ação diretamente do cronômetro ou até gerar um SDL_KEYDOWNevento e unificar as soluções.

Tyyppi_77
fonte