Des méthodes efficaces pour mettre à jour en permanence les mouvements dans un jeu de tower defense?

8

Nous sommes quatre gars qui font un jeu Tower Defense comme projet en première année dans une université. Le jeu va être vraiment simple!

  • Trois tours différentes
  • Trois monstres différents
  • Une carte (peut-être en ajouter si nous avons le temps)

Le jeu doit être orienté objet.

La structure des classes est la suivante

  • Jeu - Dessin graphique, etc.
  • Niveau - Chaque niveau est un objet de cette classe. Chaque niveau a un nombre fini d'objets d'onde (dans une liste)
  • Wave - Contient une liste d'objets monstres.
  • Monster - C'est une superclasse. Nous faisons des sous-classes pour les différents types de monstres
  • Tower - Superclass aux tours. Il existe des sous-classes pour chaque type de tour.

Nous réfléchissons à la façon de résoudre le problème que de nombreux objets doivent faire en même temps, par exemple déplacer un pixel dans une direction.

Nous avons eu l'idée d'implémenter la classe av Timer, pour contrôler quand les objets font des choses. Je ne suis pas sûr que ce soit la meilleure façon de procéder. Quelqu'un pourrait-il donner de bonnes idées sur la façon de résoudre le cas de mise à jour continue?

Øyvind
la source

Réponses:

12

Game Coding Complete décrit bien une boucle de mise à jour. Il s'agit simplement d'une boucle while exécutée dans votre classe principale qui effectue les opérations suivantes (plus ou moins):

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

Vous passez dans un dt (delta time) selon que vous voulez que votre jeu fonctionne à une fréquence d'images fixe ou variable. Pour une fréquence d'images fixe, cela n'est pas nécessaire.

Maintenant, pour faire ce que vous voulez faire assez facilement, utilisez la notion de vecteurs 2D, où un vecteur représente la position du monstre (x, y) et un vecteur de vitesse qui représente la direction dans laquelle le monstre se déplace (en unités / s ).

Donc, pour créer des monstres avec des vitesses différentes, tout ce que vous avez à faire est de changer le vecteur de vitesse en ce que vous voulez et laissez la fonction monster.update () le gérer pour vous.

Par exemple:

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

Et votre méthode de mise à jour ressemblerait à ceci (pour une fréquence d'images fixe de 60 images par seconde):

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

Ceci est connu comme la méthode de mise à jour d'Euler et c'est une méthode très simple et directe de mise en œuvre des équations de mouvement.

J'espère que cela t'aides.

Ray Dey
la source
+1 pour la grande explication. Je dirais qu'il vaut la peine de mentionner que le «temps variable» n'est pas la seule approche (bien que mon préféré) pour le timing des boucles de mise à jour, le temps variable vs le temps fixe est souvent débattu dans des endroits comme celui-ci et vaut la peine recherche :)
Zaky German
3

Fondamentalement, j'utilise une boucle de mise à jour et non un système basé sur des événements.

Pour mettre à jour des monstres, vous pouvez parcourir une liste de monstres et les mettre à jour dans la boucle de mise à jour avec, disons, monster.update()

Si un monstre doit marcher, il doit mettre à jour sa position. Donc, dans la méthode de mise à jour, je calcule la nouvelle position sur la base du temps écoulé, qui est stocké dans une classe de «minuterie» séparée.

Cela devrait être tout ce qui marche '';)

Marco
la source
Nous avons la méthode pour le mouvement des monstres. C'est assez simple. Le problème est de savoir comment faire bouger les monstres et tirer des tours, quand ils ont une "vitesse" différente ...
Øyvind
1
@ Øyvind: il suffit de passer le temps écoulé en paramètre à la méthode de mise à jour. Ensuite, un monstre peut calculer sa nouvelle position en se déplaçant elapsedTime * movementPerSecond. Ou vous pourriez avoir un temps de recharge sur la tour de tir: if(cooldown > 0){ cooldown -= elapsedTime } else { cooldown = X, shoot(); }etc.
bummzack
2

Je suppose que cela remplira bien son objectif pour un projet uni, mais dans un vrai jeu, j'aurais une classe de monstres concrets, et au lieu de sous-classer les types, avoir les différents types de monstres décrits dans les fichiers de données. La vitesse, les points de vie, les résistances à différents types de dégâts et les sprites peuvent être parfaitement décrits dans les fichiers, il vous sera plus facile d'ajouter de nouveaux types de monstres à votre jeu, et vous n'aurez pas à compiler chaque fois que vous le feriez veulent le faire.

Bref, sur le mouvement. Donnez à tous vos objets "mobiles" différents une variable de vitesse. Chaque image de votre logique de jeu vous fait parcourir tous ces objets mobiles et fait quelque chose comme

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

Cela s'applique aux monstres, aux missiles des tours, etc ...

Zaky German
la source