Effektive Methoden, um die Bewegung in einem Tower Defense-Spiel kontinuierlich zu aktualisieren?

8

Wir sind vier Leute, die ein Tower Defense-Spiel als Projekt in der ersten Klasse an einer Universität machen. Das Spiel wird wirklich einfach!

  • Drei verschiedene Türme
  • Drei verschiedene Monster
  • Eine Karte (vielleicht noch etwas hinzufügen, wenn wir Zeit haben)

Das Spiel muss objektorientiert sein.

Die Klassenstruktur ist wie folgt

  • Spiel - Zeichnen von Grafiken usw.
  • Level - Jedes Level ist ein Objekt dieser Klasse. Jede Ebene hat eine endliche Anzahl von Wellenobjekten (in einer Liste)
  • Welle - Enthält eine Liste von Monsterobjekten.
  • Monster - Dies ist eine Superklasse. Wir machen Unterklassen für die verschiedenen Arten von Monstern
  • Turm - Superklasse zu den Türmen. Für jeden Turmtyp gibt es Unterklassen.

Wir überlegen, wie wir das Problem lösen können, dass viele Objekte gleichzeitig etwas tun müssen, z. B. ein Pixel in eine Richtung bewegen.

Was wir uns ausgedacht haben, ist die Idee, einen av class Timer zu implementieren, um zu steuern, wann Objekte Dinge tun. Ich bin mir nicht sicher, ob dies der beste Weg ist. Könnte jemand einige gute Ideen geben, wie der Fall des kontinuierlichen Updates gelöst werden kann?

Øyvind
quelle

Antworten:

12

Game Coding Complete beschreibt eine Update-Schleife gut. Es ist einfach eine while-Schleife in Ihrer Hauptklasse, die Folgendes ausführt (mehr oder weniger):

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

Sie übergeben eine dt (Delta-Zeit), je nachdem, ob Ihr Spiel mit einer festen oder variablen Bildrate ausgeführt werden soll. Für eine feste Bildrate ist dies nicht erforderlich.

Um das zu tun, was Sie ganz einfach tun möchten, verwenden Sie den Begriff der 2D-Vektoren, wobei ein Vektor die Position des Monsters (x, y) und ein Geschwindigkeitsvektor die Richtung darstellt, in die sich das Monster bewegt (in Einheiten / Sek.) ).

Um Monster mit unterschiedlichen Geschwindigkeiten zu erstellen, müssen Sie lediglich den Geschwindigkeitsvektor nach Ihren Wünschen ändern und die Funktion monster.update () dies für Sie erledigen lassen.

Zum Beispiel:

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

Und Ihre Aktualisierungsmethode würde folgendermaßen aussehen (für eine feste Bildrate von 60 Bildern pro Sekunde):

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

Dies ist als Euler-Aktualisierungsmethode bekannt und eine sehr einfache und unkomplizierte Methode zum Implementieren der Bewegungsgleichungen.

Hoffe das hilft.

Ray Dey
quelle
+1 für die gute Erklärung. Ich würde sagen, es wäre erwähnenswert, dass "variable Zeit" nicht der einzige Ansatz (obwohl mein persönlicher Favorit) zum Timing von Aktualisierungsschleifen ist. Variable Zeit gegen feste Zeit wird an Orten wie diesem oft diskutiert und ist a wert Suche :)
Zaky Deutsch
3

Grundsätzlich verwende ich eine Update-Schleife und kein ereignisbasiertes System.

Um Monster zu aktualisieren, können Sie eine Liste von Monstern durchlaufen und sie in der Aktualisierungsschleife mit beispielsweise aktualisieren. monster.update()

Wenn ein Monster laufen muss, muss es seine Position aktualisieren. Bei der Aktualisierungsmethode berechne ich die neue Position auf der Grundlage der verstrichenen Zeit, die in einer separaten 'Timer'-Klasse gespeichert ist.

Das sollte alles 'Walking' Zeug sein;)

Marco
quelle
Wir haben die Methode für die Monsterbewegung. Das ist einfach genug. Das Problem ist, wie man Monster dazu bringt, sich zu bewegen und Türme zu schießen, wenn sie eine andere "Geschwindigkeit" haben ...
Øyvind
1
@ Øyvind: Übergeben Sie einfach die verstrichene Zeit als Parameter an die Aktualisierungsmethode. Dann kann ein Monster seine neue Position berechnen, indem es sich bewegt elapsedTime * movementPerSecond. Oder Sie könnten eine Abklingzeit auf dem if(cooldown > 0){ cooldown -= elapsedTime } else { cooldown = X, shoot(); }
Schussturm haben
2

Ich nehme an, es wird seinen Zweck für ein Uni-Projekt gut erfüllen, aber in einem echten Spiel hätte ich eine konkrete Monsterklasse und anstatt Unterklassen für Typen, die verschiedenen Arten von Monstern, die in Datendateien beschrieben sind. Geschwindigkeit, Gesundheitspunkte, Resistenzen gegen verschiedene Arten von Schaden und Sprites können in Dateien perfekt beschrieben werden. Dies erleichtert Ihnen das Hinzufügen neuer Monstertypen zu Ihrem Spiel und Sie müssen nicht jedes Mal kompilieren will das tun.

Sowieso über die Bewegung. Geben Sie allen "beweglichen" Objekten eine Geschwindigkeitsvariable. In jedem Frame Ihrer Spielelogik durchlaufen Sie all diese beweglichen Objekte und tun so etwas

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

Dies gilt für Monster, Raketen von Türmen usw.

Zaky Deutsch
quelle