Métodos eficazes para atualizar continuamente o movimento em um jogo de defesa de torre?

8

Somos quatro caras fazendo um jogo de Tower Defense como um projeto na primeira série de uma universidade. O jogo vai ser muito simples!

  • Três torres diferentes
  • Três monstros diferentes
  • Um mapa (talvez adicione mais se tivermos tempo)

O jogo deve ser orientado a objetos.

A estrutura da classe é a seguinte

  • Jogo - Desenho de gráfico, etc.
  • Nível - Todo nível é um objeto desta classe. Cada nível tem um número finito de objetos de onda (em uma lista)
  • Wave - Contém uma lista de objetos-monstro.
  • Monstro - Esta é uma superclasse. Criamos subclasses para os diferentes tipos de monstros
  • Torre - Superclasse para as torres. Existem subclasses para cada tipo de torre.

Estamos pensando em como resolver o problema que muitos objetos precisam fazer, ao mesmo tempo, por exemplo, mover um pixel em uma direção.

O que surgiu foi a idéia de implementar uma classe Timer, para controlar quando os objetos fazem as coisas. Não sei se essa é a melhor maneira de fazê-lo. Alguém poderia dar algumas boas idéias sobre como resolver o caso de atualização contínua?

Øyvind
fonte

Respostas:

12

Game Coding Complete descreve bem um loop de atualização. É simplesmente um loop while em execução na sua classe principal que faz o seguinte (mais ou menos):

while( game.isRunning )  
{  
  GetInput();
  Update( dt );
  Render();
}

Você passa em um dt (tempo delta), dependendo se deseja que seu jogo seja executado em uma taxa de quadros fixa ou variável. Para uma taxa de quadros fixa, isso não é necessário.

Agora, para fazer o que você deseja fazer com bastante facilidade, use a noção de vetores 2D, onde um vetor representa a posição do monstro (x, y) e um vetor de velocidade que representa a direção na qual o monstro está viajando (em unidades / s )

Então, para criar monstros com velocidades diferentes, tudo o que você precisa fazer é mudar o vetor de velocidade para o que quiser e deixar a função monster.update () lidar com isso para você.

Por exemplo:

Monster monster = new Monster();
monster.position = new Vector2( 0, 0 );
monster.velocity = new Vector2( 1, 0 );   // Every frame I want the monster 
                                          // to move 1 unit to the right

E seu método de atualização ficaria assim (para uma taxa de quadros fixa de 60 quadros por segundo):

monster.position += monster.velocity * ( 1.0f / 60.0f ); // The ( 1.0f / 60.0f ) would  
                                                         // be dt if it was passed into the Update() method

Isso é conhecido como método de atualização de Euler e é um método muito fácil e direto de implementar as equações de movimento.

Espero que isto ajude.

Ray Dey
fonte
+1 para a ótima explicação. Eu diria que vale a pena mencionar que o "tempo variável" não é a única abordagem (embora seja a minha favorita) ao tempo dos ciclos de atualização; o tempo variável versus o tempo fixo é frequentemente debatido em lugares como esse e vale a pena pesquisa :)
Zaky German
3

Basicamente, eu uso um loop de atualização e não um sistema baseado em eventos.

Para atualizar monstros, você pode iterar uma lista de monstros e atualizá-los no loop de atualização com, digamos, monster.update()

Se um monstro tem que andar, ele precisa atualizar sua posição. Portanto, no método de atualização, calculo a nova posição com base no tempo decorrido, que é armazenado em uma classe 'timer' separada.

Isso deve ser todo o material 'andando';)

Marco
fonte
Temos o método para o movimento de monstros. Isso é bastante simples. O problema é como obter monstros a se mover, e torres para atirar, quando eles têm "velocidade" diferente ...
Øyvind
11
@ Øyvind: Basta passar o tempo decorrido como parâmetro para o método de atualização. Então um monstro pode calcular sua nova posição movendo-se elapsedTime * movementPerSecond. Ou você poderia ter um cooldown sobre a torre de tiro: if(cooldown > 0){ cooldown -= elapsedTime } else { cooldown = X, shoot(); }etc.
bummzack
2

Suponho que ele cumpra bem seu objetivo em um projeto uni, mas em um jogo real eu teria uma classe de monstros concreta e, em vez de subclassificar tipos, teria os diferentes tipos de monstros descritos nos arquivos de dados. Velocidade, pontos de vida, resistências a diferentes tipos de dano e sprites podem ser perfeitamente descritos em arquivos, será mais fácil adicionar novos tipos de monstros ao seu jogo e você não precisará compilar cada vez que quiser quer fazer isso.

Enfim, sobre o movimento. Dê a todos os seus objetos "móveis" diferentes uma variável de velocidade. Cada quadro em sua lógica de jogo, você percorre todos esses objetos móveis e faz algo como

object.x += Math.cos(object.angle) * object.speed * timeSinceLastIteration;
object.y += Math.sin(object.angle) * object.speed * timeSinceLastIteration;

Isso se aplica a monstros, mísseis de torres, etc ...

Zaky German
fonte