¿Métodos efectivos para actualizar continuamente el movimiento en un juego de defensa de torres?

8

Somos cuatro chicos haciendo un juego de Tower Defense como un proyecto en primer grado en una universidad. ¡El juego va a ser realmente simple!

  • Tres torres diferentes
  • Tres monstruos diferentes
  • Un mapa (quizás agregue un poco más si tenemos tiempo)

El juego tiene que estar orientado a objetos.

La estructura de clases es la siguiente

  • Juego - Dibujo de gráficos, etc.
  • Nivel : cada nivel es un objeto de esta clase. Cada nivel tiene un número finito de objetos de onda (en una lista)
  • Ola : contiene una lista de objetos monstruosos.
  • Monstruo : esta es una superclase. Hacemos subclases para los diferentes tipos de monstruos.
  • Torre - Superclase a las torres. Hay subclases para cada tipo de torre.

Estamos pensando en cómo resolver el problema de que muchos objetos tienen que hacer cosas, al mismo tiempo, por ejemplo, mover un píxel en una dirección.

Se nos ocurrió la idea de implementar av class Timer, para controlar cuándo los objetos hacen las cosas. No estoy seguro de que esta sea la mejor manera de hacerlo. ¿Podría alguien dar algunas buenas ideas sobre cómo resolver el caso de actualización continua?

Øyvind
fuente

Respuestas:

12

Game Coding Complete describe bien un bucle de actualización. Es simplemente un ciclo while que se ejecuta en su clase principal que hace lo siguiente (más o menos):

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

Usted pasa un dt (tiempo delta) dependiendo de si desea que su juego se ejecute a una velocidad de cuadro fija o variable. Para una velocidad de cuadro fija, esto no es necesario.

Ahora, para hacer lo que quiere hacer con bastante facilidad, use la noción de vectores 2D, donde un vector representa la posición del monstruo (x, y) y un vector de velocidad que representa la dirección en la que viaja el monstruo (en unidades / seg. )

Entonces, para crear monstruos con diferentes velocidades, todo lo que necesitas hacer es cambiar el vector de velocidad a lo que quieras y dejar que la función monster.update () lo maneje por ti.

Por ejemplo:

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

Y su método de actualización se vería así (para una velocidad de cuadro fija de 60 cuadros 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

Esto se conoce como el método de actualización de Euler y es un método muy sencillo y directo para implementar las ecuaciones de movimiento.

Espero que esto ayude.

Ray Dey
fuente
+1 por la gran explicación. Diría que valdría la pena mencionar que el "tiempo variable" no es el único enfoque (aunque mi favorito personal) para la sincronización de los ciclos de actualización, el tiempo variable frente al tiempo fijo a menudo se debate en lugares como este y vale la pena búsqueda :)
Zaky alemán
3

Básicamente, uso un ciclo de actualización y no un sistema basado en eventos.

Para actualizar monstruos, puede iterar una lista de monstruos y actualizarlos en el ciclo de actualización con, digamos, monster.update()

Si un monstruo tiene que caminar, debe actualizar su posición. Entonces, en el método de actualización calculo la nueva posición en base al tiempo transcurrido, que se almacena en una clase separada de 'temporizador'.

Eso debería ser todo lo de 'caminar';)

Marco
fuente
Tenemos el método para el movimiento de monstruos. Eso es bastante simple. El problema es cómo conseguir monstruos mover y torres para disparar, cuando tienen diferentes "velocidad" ...
Øyvind
1
@ Øyvind: simplemente pase el tiempo transcurrido como parámetro al método de actualización. Entonces un monstruo puede calcular su nueva posición moviéndose elapsedTime * movementPerSecond. O podrías tener un enfriamiento en la torre de tiro: if(cooldown > 0){ cooldown -= elapsedTime } else { cooldown = X, shoot(); }etc.
bummzack
2

Supongo que cumplirá bien su propósito para un proyecto uni, pero en un juego real tendría una clase de monstruo concreta y, en lugar de subclasificar por tipos, tener los diferentes tipos de monstruos descritos en los archivos de datos. La velocidad, los puntos de vida, las resistencias a los diferentes tipos de daños y los sprites se pueden describir perfectamente en los archivos, te facilitará agregar nuevos tipos de monstruos a tu juego, y no tendrás que compilar cada vez que quiero hacerlo

De todos modos, sobre el movimiento. Dele a todos sus objetos "móviles" una variable de velocidad diferente. Cada cuadro en la lógica de tu juego recorres todos esos objetos móviles y haces algo como

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

Esto se aplica a monstruos, misiles de torres, etc.

Zaky German
fuente