Eu realmente nunca fiz muita programação de jogos antes, uma pergunta bastante direta.
Imagine que estou construindo um jogo Tetris, com o loop principal parecido com isso.
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
remove all complete rows
move rows down so there are no gaps
if we can spawn a new block
spawn a new current block
else
game over
Até agora, tudo no jogo acontece instantaneamente - as coisas são geradas instantaneamente, as linhas são removidas instantaneamente etc. Mas e se eu não quiser que as coisas aconteçam instantaneamente (ou seja, animar coisas)?
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
?? animate complete rows disappearing (somehow, wait over multiple frames until the animation is done)
?? animate rows moving downwards (and again, wait over multiple frames)
if we can spawn a new block
spawn a new current block
else
game over
No meu clone Pong, isso não foi um problema, pois todos os quadros que eu estava apenas movendo a bola e procurando colisões.
Como posso entender minha questão? Certamente, a maioria dos jogos envolve alguma ação que leva mais do que um quadro, e outras coisas param até a ação ser concluída.
Action
classe e uma fila de ações a serem executadas. Quando uma ação estiver concluída, remova-a da fila e execute a próxima ação etc. Muito mais flexível que uma máquina de estado.Estou tirando isso do Game Coding Complete de Mike McShaffry.
Ele fala sobre um 'Process Manager', que se resume a uma lista de tarefas que precisam ser realizadas. Por exemplo, um processo controlaria a animação para desenhar uma espada (AnimProcess), abrir uma porta ou, no seu caso, fazer a linha desaparecer.
O processo seria adicionado à lista de gerenciadores de processos, que seria iterada a cada quadro e Update () chamado em cada um. Entidades muito parecidas, mas para ações. Haveria um sinalizador de morte para remover da lista quando terminar.
A outra coisa interessante sobre eles é como eles podem vincular, tendo um ponteiro para o próximo processo. Dessa forma, seu processo de linha animada pode realmente consistir em:
(Como os processos podem ser de uso único, condicionalmente lá ou lá por um período de tempo X)
Se você quiser mais detalhes, pergunte.
fonte
Você pode usar uma fila de ações prioritárias. Você empurra uma ação e um tempo. A cada quadro, você obtém o tempo e libera todas as ações que têm um tempo especificado antes desse horário e as executa. Bônus: A abordagem é paralela, e você pode implementar quase toda a lógica do jogo dessa maneira.
fonte
Você sempre precisa saber a diferença de horário entre o quadro anterior e o atual, para fazer duas coisas.
Decida quando atualizar seu modelo: por exemplo. no tetris, quando uma remoção de linha começa, você não deseja mais que as coisas colidam com a linha; portanto, você remove a linha do 'modelo' do seu aplicativo.
-Você precisa manipular o objeto que está em um estado de transição para uma classe separada que resolve a animação / evento por um período de tempo. No exemplo do tetris, a linha desapareceria lentamente (altere um pouco a opacidade de cada quadro). Após a opacidade ser 0, você transfere todos os blocos no topo da linha um para baixo.
Isso pode parecer um pouco complicado no começo, mas você entenderá isso, apenas certifique-se de abstrair muito em diferentes classes, isso facilitará. Verifique também se os eventos que demoram algum tempo, como a remoção de uma linha no tetris, são do tipo "Fire and Forget", basta criar um novo objeto que lide com tudo o que precisa ser feito automaticamente e que, quando tudo estiver pronto, remove-se do seu cenário.
fonte
Você precisa pensar no jogo como uma "máquina de estados finitos". O jogo pode estar em um dos vários estados: no seu caso, "espera de entrada", "peça descendo", "linha explodindo".
Você faz coisas diferentes, dependendo do estado. Por exemplo, durante a "descida da peça", você ignora a entrada do jogador e anima a peça da linha atual para a próxima linha. Algo assim:
fonte