Ordem correta das operações em um loop de jogo de plataformas

7

Corri um problema no meu mecanismo Mega Man, e a estrutura do loop do meu jogo está dificultando a correção. Com o Rush Jet, ou qualquer outra plataforma em queda, o Mega Man precisa permanecer ligado à plataforma à medida que ela cai. No momento, o melhor que posso fazer (sem recorrer a soluções alternativas, como campos de força mágicos que o derrubam), permite que ele caia em um único quadro quando a plataforma começar a cair. Mas mesmo isso requer que a plataforma em queda o puxe para baixo durante a verificação de colisão. Sem esse passo extra, ele constantemente "treme" ao cair à medida que a plataforma desce.

A ordem dos eventos no meu loop do jogo está fazendo isso acontecer. É assim:

  1. Mega Man e Rush Jet estão voando horizontalmente por um tempo.
  2. Fase de pensamento: O jogador pressiona para baixo - a plataforma decide ajustar sua velocidade para baixo.
  3. Fase de ação: a plataforma se move para baixo, o jogador não tem consciência disso.
  4. Fase de reação: os dois não estão colidindo, portanto, nenhuma verificação de "força de ligação" pode ocorrer.
  5. No próximo quadro, Mega Man cai. Um quadro depois, a gravidade alcança e ele pousa na plataforma novamente, redefinindo sua velocidade y para 0.

Você pode ver lá a ordem básica do meu loop:

  1. Fase de reflexão, em que você analisa colisões do quadro anterior e quaisquer outras variáveis ​​para decidir sobre transições de estado e outros ajustes.
  2. Fase de ação - todos se movem de acordo com sua velocidade.
  3. Fase de reação - verificações de colisão, ajuste as posições para corrigi-las. Isso também lida com efeitos como plataformas móveis, por exemplo. empurre o jogador por alguma quantia. As mudanças em sua velocidade são aplicadas no próximo quadro, durante a fase de ação.

Tentei reordenar essas etapas e várias outras alterações, mas todas pioram tudo, com todos os tipos de erros. Se eu precisar fazer mudanças radicais no meu mecanismo para corrigir essas coisas, prefiro saber qual é a maneira "correta" antes de perder tempo.

Eu sei que uma solução possível seria a etapa do movimento olhar para quem estava tocando a plataforma no quadro anterior e puxá-lo para que eles realmente se movessem juntos. Isso parece muito complexo, porém, atingindo componentes assim. Meu código de mecanismo já parece muito mais complicado do que o jogo original poderia ter sido, sugerindo que estou fazendo algo errado.

Então, existe uma sequência adequada de eventos? Há outra pergunta aqui sobre como mover as coisas junto com uma plataforma, mas isso não aborda a questão da ordem dos eventos que causa o meu problema. Além disso, se alguém realmente souber como os jogos clássicos do Mega Man fizeram isso, isso obviamente seria uma grande ajuda.

Encontre tanto do meu código quanto você deseja em https://github.com/Tesserex/C--MegaMan-Engine/tree/master/Mega%20Man . O CollisionComponent e MovementComponent pode ser o mais útil.

Tesserex
fonte
11
Eu não entendo completamente, mas como o mega-homem e a plataforma se movem juntos, talvez não seja uma coisa horrível unir o movimento deles. (se eles se movem juntos como uma entidade, por que não programá-los para ser uma entidade ou pelo menos aprisioná-los de alguma forma?)
Michael Coleman
A maneira como resolvi o problema de "cair depois de uma plataforma" foi não passar para o estado de queda até que o jogador estivesse fora de contato com o chão por pelo menos dois quadros. O jogador cai; mas as animações não mudam para que o jogador não perceba. Isso também lida muito bem com descer ladeiras.
Blecki
@ Blecki - Isso pode ou não funcionar para mim - meu sistema é personalizável, portanto seria uma mudança bastante genérica. Enfim, ainda estou interessado se alguém souber a ordem do loop do jogo "correta".
Tesserex

Respostas:

2

Sei que esta resposta não se encaixa no título desta pergunta, mas acho que poderia resolver seu problema.

Eu olhei para sua base de código e você tem um design de componente agregado para compor entidades de jogos. Eu estou supondo que o rush jet tem sua própria entidade de jogo e lista de componentes ("rush jet" é o que chamarei de plataforma móvel, sim, não sei nada sobre jogos mega man). Se for esse o caso, você deve tentar passar pelo rush jet uma entidade de jogo de jogador e criar algum tipo de ponte (não é o melhor termo para usar).

Para essa "ponte", o jato do rush não recebe informações do teclado. Em vez disso, o jogador receberia informações e, em seu sistema de mensagens (o dos componentes do jogo em uma entidade), você poderia ter outro componente do jogo vinculado ao jet jet que também interceptaria a mensagem de movimento. Assim, o jogador e a plataforma seriam movidos juntos. Depois que o jato de corrida acabar, o componente do jogo que serve como ponte entre o jato de corrida e o jogador será descartado e removido.

Eu acho que essa é uma alternativa plausível. O movimento ocorre no loop do jogo e, em seguida, ocorrem as verificações de colisão para garantir que o jet rush e o jogador estejam dentro dos limites. Eu também acredito que é perfeitamente bom que o rush jet dependa do jogador dessa maneira. Não é a solução mais sublime, mas provavelmente funcionará.

PS: Eu gosto da sua base de código. O código não é o melhor, mas é legal.

Michael Coleman
fonte
Obrigado. Eu acho que é uma abordagem nova. As entidades do jogo são definidas externamente, e a maior razão pela qual eu queria que funcionasse sem algum tipo de conexão especial entre elas é para que outras plataformas em queda não precisem do mesmo tratamento especial para funcionar. Mas talvez eu possa usar esse tipo de abordagem para facilitar a criação dessas plataformas.
Tesserex 04/04
A única coisa que une a plataforma e o player é um componente da entidade. Assim, você pode criar outras plataformas e não anexar esse componente de entidade ao player. Você deixa a plataforma aberta para extensão, para facilitar.
Michael Coleman
bem, da única maneira que consegui funcionar até agora, usei um hitbox para me comunicar entre os dois. Portanto, parece que não há uma solução simples que não crie pelo menos um pequeno objeto em cada caso.
Tesserex
Sim, mas esse pequeno objeto é realmente um problema? Ele está sendo alocado apenas durante um quadro uma vez. Quantidade muito pequena na minha opinião.
Michael Coleman
Certo, funciona bem. Você só precisa se lembrar disso toda vez que criar essa plataforma.
Tesserex
0

Ok, então, na sua forma mais básica, um loop de jogo se parece com isso:

while game is running
    act upon user input
    update all game objects
    re-draw everything to the screen

No seu caso, o que deve acontecer é:

  1. O loop começa.
  2. Você atualiza todos os objetos com base nas teclas pressionadas que ocorreram. A plataforma se move para baixo.
  3. Você atualiza todos os objetos com base em suas velocidades. Dentro desse passo, deve haver uma verificação de colisão para não percorrer toda a distância ou alterar suas velocidades para zero quando eles atingem (atravessam) paredes e os colocam nos lugares certos.
  4. Agora desenhe tudo na tela, o usuário nunca viu nenhum estado de erro, então tudo parece ótimo; sem nervosismo nunca.

E é assim que a maioria dos jogos que escrevo faz com que funcione.

Atualização: Se você precisar de mais informações sobre como escrever um bom ciclo de jogo, veja agora mais além deste bom guia .

Robert Massaioli
fonte
Esse artigo parece ser inteiramente sobre como fazer o tempo do loop do jogo corretamente com a velocidade do hardware. Mas sua sugestão parece sugerir que meu pedido está correto. Do jeito que você tem, acho que o problema ainda existiria. Eu acho que tenho que fazer algum tipo de mágica unindo os dois.
Tesserex
@ Tesserex: eu não entendo; se você mudar a posição da plataforma antes que o jogador verifique sua gravidade, ele não descerá e se conectará à plataforma antes que o próximo passo ocorra? Sem olhar para o seu código, parece que você tem um problema de ordem de operações, portanto, meu post.
Robert Maraioli