Hallo Flash-Entwickler, willkommen zum zweiten Teil meines Tower Defense Game-Tutorials. Im ersten Teil haben wir den grundlegenden Mechanismus entwickelt, mit dem Sie Türme erstellen und in Richtung des Mausklicks schießen können. Aber dafür sind Türmchen nicht geeignet! In diesem Teil erweitern wir das Spiel um Feinde, grundlegende künstliche Intelligenz (KI) in Türmchen und einige weitere Spielelemente. Sind Sie bereit?
Dies ist das Spiel, das wir in diesem Tutorial erstellen werden:
Klicken Sie auf die orangefarbenen Kreise, um Türmchen zu platzieren. Die roten Kreise sind Feinde, und die Zahl auf jedem steht für ihre Trefferpunkte.
Im vorherigen Tutorial haben wir ein Spiel entwickelt, das Platzhalter für die Türmchen hatte. Wir könnten Revolver einsetzen, indem Sie auf diese Platzhalter klicken, und die Revolver auf den Mauszeiger richten und Kugeln auf den Punkt ausrichten, auf den der Benutzer geklickt hat.
Wir haben mit a beendet Main
Klasse, die die Spielschleife und Spiellogik hatte. Ansonsten hatten wir die Turm
Klasse, die außer der aktualisieren
Funktion, die den Turm drehen ließ.
Wir haben zuvor die Kugeln in erstellt Main
Klasse und angehängt ein ENTER_FRAME
Hörer, um es zu verschieben. Das Aufzählungszeichen hatte zuvor nicht genügend Eigenschaften, um es als separate Klasse zu betrachten. In einem solchen Spiel können Aufzählungszeichen jedoch viele Variationen wie Geschwindigkeit, Schaden usw. haben. Es ist daher ratsam, den Aufzählungscode herauszuziehen und in einem separaten Code zu kapseln Kugel
Klasse. Machen wir das.
Erstellen Sie eine neue Klasse namens Kugel
, Erweiterung der Sprite
Klasse. Der grundlegende Code für diese Klasse sollte lauten:
package import flash.display.Sprite; public class Bullet erweitert Sprite public function Bullet ()
Als Nächstes setzen wir den Code zum Zeichnen der Aufzählungsgrafik aus Main
, im Kugel
. Wie wir es mit dem gemacht haben Turm
Klasse erstellen wir eine Funktion namens zeichnen
in dem Kugel
Klasse:
private Funktion draw (): void var g: Graphics = this.graphics; g.beginFill (0xEEEEEE); g.DrawCircle (0, 0, 5); g.endFill ();
Und wir nennen diese Funktion aus dem Kugel
Konstrukteur:
öffentliche Funktion Bullet () draw ();
Jetzt fügen wir der Aufzählungslinie einige Eigenschaften hinzu. Fügen Sie vier Variablen hinzu: Geschwindigkeit
, speed_x
, schnell
und Beschädigung
, Vor dem Kugel
Konstrukteur:
private var Geschwindigkeit: Anzahl; private var speed_x: Anzahl; private var speed_y: Anzahl; öffentlicher Var-Schaden: int;
Wozu dienen diese Variablen??
Geschwindigkeit
: Diese Variable speichert die Geschossgeschwindigkeit.speed_x
und schnell
: Diese speichern die x- und y-Komponenten der Geschwindigkeit, so dass die Berechnung des Zerreißens der Geschwindigkeit in ihre Komponenten nicht immer wieder durchgeführt werden muss. Beschädigung
: Dies ist die Menge an Schaden, die die Kugel einem Feind zufügen kann. Wir halten diese Variable öffentlich, da wir dies in unserer Spielschleife in der Main
Klasse. Wir initialisieren diese Variablen im Konstruktor. Aktualisieren Sie Ihre Kugel
Konstrukteur:
öffentliche Funktion Aufzählungszeichen (Winkel: Anzahl) Geschwindigkeit = 5; Schaden = 1; speed_x = Math.cos (Winkel * Math.PI / 180) * Geschwindigkeit; speed_y = Math.sin (Winkel * Math.PI / 180) * Geschwindigkeit; zeichnen();
Beachten Sie die Winkel
Variable erhalten wir im Konstruktor. Dies ist die Richtung (in Grad), in der sich die Kugel bewegt. Wir brechen einfach die Geschwindigkeit
in seine x- und y-Komponenten und zwischenspeichern, um sie später zu verwenden.
Das letzte, was in der bleibt Kugel
Klasse soll eine haben aktualisieren
Funktion, die aus der Spieleschleife aufgerufen wird, um die Kugel zu aktualisieren (zu bewegen). Fügen Sie am Ende des Programms die folgende Funktion hinzu Kugel
Klasse:
öffentliche Funktion update (): void x + = speed_x; y + = Geschwindigkeit_y;
Bingo! Wir sind fertig mit unserem Kugel
Klasse.
Wir haben eine Menge Bullet-Code von entfernt Main
Klasse für sich Kugel
Klasse, also bleibt viel Code ungenutzt in Main
und viel muss aktualisiert werden.
Löschen Sie zuerst das createBullet ()
und moveBullet ()
Funktionen. Entfernen Sie auch die bullet_speed
Variable.
Gehen Sie als nächstes zum schießen
Funktion und aktualisieren Sie es mit dem folgenden Code:
privates Funktionsshooting (e: MouseEvent): void for each (var-Revolver: Revolver in Revolver) var new_bullet: Bullet = neues Bullet (Turret.rotation); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; addChild (new_bullet);
Wir benutzen das nicht mehr createBullet
Funktion zum Erstellen von Aufzählungszeichen verwenden Sie stattdessen die Kugel
Konstruktor und übergeben Sie den Turm Drehung
Dies ist die Bewegungsrichtung der Kugel, und wir müssen sie nicht in der Kugel speichern Drehung
Eigentum wie früher. Wir hängen auch keinen Listener an der Kugel an, da die Kugel innerhalb der nächsten Spielschleife aktualisiert wird.
Jetzt, da wir die Kugeln aus der Spielschleife aktualisieren müssen, benötigen wir eine Referenz, um irgendwo gespeichert zu werden. Die Lösung ist die gleiche wie für die Türmchen: Erstellen Sie einen neuen Array
genannt Kugeln
und drücken Sie die Kugeln darauf, wenn sie erstellt werden.
Zuerst deklarieren Sie ein Array direkt unter dem Türmchen
Array-Deklaration:
private var ghost_turret: Turm; private var-Geschütztürme: Array = []; private var Aufzählungszeichen: Array = [];
Nun füllen Sie dieses Array aus. Wir machen das immer dann, wenn wir eine neue Kugel erstellen - also in der schießen
Funktion. Fügen Sie unmittelbar vor dem Hinzufügen des Aufzählungszeichens zur Bühne Folgendes hinzu:
var new_bullet: Bullet = neues Bullet (Turret.rotation); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
So wie wir die Türme der Spielschleife aktualisieren, werden auch die Kugeln aktualisiert. Aber diesmal anstelle von ein für jeden
Schleife verwenden wir eine grundlegende zum
Schleife. Zuvor müssen wir zwei Variablen oben in der Spielschleife hinzufügen, damit wir wissen, welche Variablen in der Spielschleife verwendet werden und diese für die Speicherbereinigung freigeben können.
var Turm: Turm; var bullet: Kugel;
Fügen Sie am Ende der Spielschleife den folgenden Code hinzu:
für (var i: int = Geschosse. Länge - 1; i> = 0; i -) Geschoss = Geschosse [i]; if (! bullet) weiter; bullet.update ();
Hier durchfahren wir alle Kugeln auf der Bühne und nennen sie ihre aktualisieren
Funktion, die sie bewegen lässt. Beachten Sie hier, dass wir das iterieren Kugeln
Array umgekehrt. Warum? Wir werden das vor uns sehen.
Jetzt haben wir eine Turm
außerhalb bereits deklarierte Variable, müssen wir sie nicht erneut innerhalb von deklarieren für jeden
Schleife von Türmchen. Ändern Sie es zu:
für jedes (Revolver in Revolver) turret.update ();
Schließlich fügen wir die Randüberprüfungsbedingung hinzu. Dies war zuvor in der Kugel ENTER_FRAME
aber jetzt überprüfen wir es in der Spieleschleife:
if (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (bullet); fortsetzen;
Wir prüfen, ob sich das Geschoss außerhalb der Bühnengrenze befindet. Wenn dies der Fall ist, entfernen wir zuerst seine Referenz von der Bühne Kugeln
Array mit der spleißen
Funktion, und entfernen Sie die Kugel von der Bühne und fahren Sie mit der nächsten Iteration fort. So sollte Ihre Spielschleife aussehen:
private Funktion gameLoop (e: Event): void var turret: Turret; var bullet: Kugel; für jedes (Revolver in Revolver) turret.update (); für (var i: int = Aufzählungszeichen.Länge - 1; i> = 0; i--) Aufzählungszeichen = Aufzählungszeichen [i]; if (! bullet) weiter; bullet.update ();
Wenn Sie das Spiel jetzt ausführen, sollten Sie dieselbe Funktionalität wie in Teil 1 haben, wobei der Code viel sauberer und übersichtlicher ist.
Jetzt fügen wir eines der wichtigsten Elemente des Spiels hinzu: den Feind. Als Erstes erstellen Sie eine neue Klasse mit dem Namen Feind
Erweiterung der Sprite
Klasse:
package import flash.display.Sprite; public class Enemy erweitert Sprite public function Enemy ()
Jetzt fügen wir der Klasse einige Eigenschaften hinzu. Fügen Sie sie vor Ihrem hinzu Feind
Konstrukteur:
private var speed_x: Anzahl; private var speed_y: Anzahl;
Wir initialisieren diese Variablen im Feind
Konstrukteur:
öffentliche Funktion Enemy () speed_x = -1.5; speed_y = 0;
Als nächstes erstellen wir die zeichnen
und aktualisieren
Funktionen für die Feind
Klasse. Diese sind denjenigen von sehr ähnlich Kugel
. Fügen Sie den folgenden Code hinzu:
private Funktion draw (): void var g: Graphics = this.graphics; g.beginFill (0xff3333); g.DrawCircle (0, 0, 15); g.endFill (); public function update (): void x + = Geschwindigkeit_x; y + = Geschwindigkeit_y;
In unserem Spiel müssen wir viele Ereignisse haben, die zu bestimmten Zeiten oder wiederholt in bestimmten Abständen stattfinden. Ein solches Timing kann mit einem Zeitzähler erreicht werden. Der Zähler ist nur eine Variable, die mit der Zeit im Spiel erhöht wird. Wichtig ist hier, wann und um wie viel Betrag der Zähler erhöht wird. Das Timing wird in der Regel auf zwei Arten durchgeführt: Zeitbasiert und Frame-basiert.
Der Unterschied besteht darin, dass die auf Zeit basierende Spieleinheit auf Echtzeit basiert (d. H. Die Anzahl der durchgelassenen Millisekunden). In einem Frame-basierten Spiel basiert die Schritteinheit jedoch auf Frame-Einheiten (d. H. Die Anzahl der durchlaufenden Frames).
Für unser Spiel verwenden wir einen Frame-basierten Counter. Wir haben einen Zähler, den wir in der Spielschleife, in dem jeder Frame ausgeführt wird, um eins erhöhen, und im Grunde die Anzahl der Frames angeben, die seit dem Start des Spiels vergangen sind. Gehen Sie voran und deklarieren Sie eine Variable nach den anderen Variablendeklarationen in der Main
Klasse:
private var ghost_turret: Turm; private var-Geschütztürme: Array = []; private var Aufzählungszeichen: Array = []; private var global_time: Anzahl = 0;
Wir erhöhen diese Variable in der Spielschleife oben:
global_time ++;
Basierend auf diesem Zähler können wir beispielsweise Feinde erstellen, was wir als nächstes tun werden.
Was wir jetzt tun wollen, ist, alle zwei Sekunden Feinde auf dem Spielfeld zu erstellen. Aber wir haben es hier mit Frames zu tun. Nach wie vielen Frames sollten wir also Feinde erstellen? Nun, unser Spiel läuft mit 30 FPS und erhöht damit die Geschwindigkeit global_time
30 mal pro Sekunde. Eine einfache Berechnung sagt uns, dass 3 Sekunden = 90 Frames sind.
Fügen Sie am Ende der Spielschleife Folgendes hinzu ob
Block:
if (global_time% 90 == 0)
Worum geht es in diesem Zustand? Wir verwenden den Modulo-Operator (%), der den Rest einer Division ergibt - also global_time% 90
gibt uns den Rest wann global_time
wird durch geteilt 90
. Wir prüfen, ob es sich um den Rest handelt 0
, da dies nur dann der Fall sein wird, wenn global_time
ist ein Vielfaches von 90
- das heißt, die Bedingung kehrt zurück wahr
wann global_time
gleich 0
, 90
, 180
und so weiter… Auf diese Weise erreichen wir alle 90 Bilder oder 3 Sekunden einen Trigger.
Bevor wir den Feind erstellen, deklarieren Sie ein anderes Array namens Feinde
knapp unterhalb der Türmchen
und Kugeln
Array. Dies wird verwendet, um Verweise auf Gegner auf der Bühne zu speichern.
private var ghost_turret: Turm; private var-Geschütztürme: Array = []; private var Aufzählungszeichen: Array = []; private var-feinde: Array = []; private var global_time: Anzahl = 0;
Erkläre auch eine Feind
Variable am oberen Rand der Spielschleife:
global_time ++; var Turm: Turm; var bullet: Kugel; var Feind: Feind;
Fügen Sie schließlich den folgenden Code in das ein ob
Block, den wir zuvor erstellt haben:
Feind = neuer Feind (); Feind.x = 410; Feind.y = 30 + Math.random () * 370; Feinde.push (Feind); addChild (Feind);
Hier erstellen wir einen neuen Feind, positionieren ihn zufällig rechts von der Bühne, schieben ihn in die Feinde
Array und fügen Sie es der Bühne hinzu.
So wie wir die Kugeln in der Spielschleife aktualisieren, aktualisieren wir die Feinde. Fügen Sie den folgenden Code unter dem Revolver ein für jeden
Schleife:
for (var j: int = Feinde. Länge - 1; j> = 0; j--) Feind = Feinde [j]; Feind.Update (); wenn (Feind.x < 0) enemies.splice(j, 1); enemy.parent.removeChild(enemy); continue;
So wie wir eine Begrenzungsprüfung für Kugeln durchgeführt haben, überprüfen wir auch die Feinde. Bei Feinden prüfen wir nur, ob sie die linke Seite der Bühne verlassen haben, da sie sich nur von rechts nach links bewegen. Sie sollten Feinde von rechts kommen sehen, wenn Sie das Spiel jetzt ausführen.
Jeder Feind hat etwas Leben / Gesundheit und unsere auch. Wir werden auch die verbleibende Gesundheit der Feinde zeigen. Lässt einige Variablen im deklarieren Feind
Klasse für das Gesundheitswesen:
private var health_txt: TextField; private var Gesundheit: int; private var speed_x: Anzahl; private var speed_y: Anzahl;
Wir initialisieren die Gesundheit
Variable im Konstruktor weiter. Fügen Sie Folgendes dem hinzu Feind
Konstrukteur:
Gesundheit = 2;
Jetzt initialisieren wir die Health-Textvariable, um sie im Zentrum des Feindes anzuzeigen. Wir machen das im zeichnen
Funktion:
health_txt = new TextField (); health_txt.height = 20; health_txt.width = 15; health_txt.textColor = 0xffffff; health_txt.x = -5; health_txt.y = -8; health_txt.text = Gesundheit + ""; addChild (health_txt);
Alles, was wir tun, ist ein neues zu erstellen Textfeld
, Legen Sie die Farbe fest, positionieren Sie sie und setzen Sie ihren Text auf den aktuellen Wert von Gesundheit
Schließlich fügen wir eine Funktion hinzu, um die Gesundheit des Feindes zu aktualisieren:
öffentliche Funktion updateHealth (Betrag: int): int Gesundheit + = Betrag; health_txt.text = Gesundheit + ""; Gesundheit zurückgeben;
Die Funktion akzeptiert eine Ganzzahl, die zum Zustand hinzugefügt werden soll, aktualisiert den Zustandstext und gibt den endgültigen Zustand zurück. Wir rufen diese Funktion in unserer Spieleschleife auf, um die Gesundheit jedes Gegners zu aktualisieren und festzustellen, ob er noch lebt.
Zuerst können wir unsere ändern schießen
ein bisschen funktionieren. Ersetzen Sie das vorhandene schießen
Funktion mit Folgendem:
private Funktion schießen (Turm: Turm, Feind: Feind): void Var Winkel: Anzahl = Math.atan2 (Feind.y - Turm.y, Feind.x - Turm.x) / Math.PI * 180; Drehbewegung = Winkel; var new_bullet: Bullet = new Bullet (Winkel); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
Das schießen
Funktion akzeptiert jetzt zwei Parameter. Der erste ist ein Hinweis auf einen Turm, der das Schießen übernimmt. Die zweite ist ein Hinweis auf einen Feind, auf den er schießen soll.
Der neue Code ähnelt dem in der Turm
Klasse aktualisieren
Funktion, aber anstelle der Mausposition verwenden wir jetzt die Koordinaten des Feindes. So können Sie jetzt den gesamten Code aus dem entfernen aktualisieren
Funktion des Turm
Klasse.
Wie kann man die Türmchen auf Feinde schießen lassen? Nun, die Logik ist für unser Spiel einfach. Wir lassen alle Türmchen auf den ersten Feind im schießen Feinde
Array. Was? Lassen Sie uns etwas Code setzen und dann versuchen zu verstehen. Addiere folgende Zeilen am Ende des für jeden
Schleife zum Aktualisieren der Revolver:
für jedes (Revolver in Revolver) turret.update (); für jeden (Feind in Feinden) schießen (Turm, Feind); brechen;
Für jeden Turm aktualisieren wir ihn jetzt, iterieren dann die Feinde
schießen Sie den ersten Gegner im Array und brechen Sie die Schleife ab. Im Wesentlichen schießt jeder Turm auf den frühesten erschaffenen Gegner, da er sich immer am Anfang des Arrays befindet. Versuchen Sie, das Spiel auszuführen, und Sie sollten Türme sehen, die die Feinde erschießen.
Aber warten Sie, was fließt dieser Kugelstrom? Sieht aus, als würden sie zu schnell schießen. Mal sehen warum.
Wie wir wissen, läuft die Spielschleife jedes Bild, d. H. In unserem Fall 30-mal pro Sekunde, so dass die Schießaussage, die wir im vorherigen Schritt hinzugefügt haben, mit der Geschwindigkeit unserer Spielschleife aufgerufen wird, und wir sehen einen Fluss von Kugeln. Sieht aus, als hätten wir auch einen Timing-Mechanismus in den Türmchen. Wechseln Sie zum Turm
Klasse und fügen Sie den folgenden Code hinzu:
private var local_time: Anzahl = 0; private var reload_time: int;
Ortszeit
: Unser Zähler wird gerufen Ortszeit
im Gegensatz zu dem global_time
in dem Main
Klasse. Dies hat zwei Gründe: erstens, weil diese Variable lokal ist Turm
Klasse; Zweitens, weil es nicht immer so vorgeht wie bei uns global_time
Variable - wird im Laufe des Spiels mehrmals zurückgesetzt. Nachladezeit
: Dies ist die Zeit, die der Revolver nach dem Schießen einer Kugel zum Laden benötigt. Im Grunde ist es der Zeitunterschied zwischen zwei Kugelschüssen eines Turms. Denken Sie daran, dass alle Zeiteinheiten in unserem Spiel Frames sind. Inkrementieren Sie die Ortszeit
Variable in der aktualisieren
Funktion und initialisieren die Nachladezeit
im Konstruktor:
öffentliche Funktion update (): void local_time ++;
öffentliche Funktion Turret () reload_time = 30; zeichnen();
Als nächstes fügen Sie die folgenden zwei Funktionen am Ende von hinzu Turm
Klasse:
public function isReady (): Boolean return local_time> reload_time; public function reset (): void local_time = 0;
ist bereit
gibt nur dann true zurück, wenn der aktuelle Ortszeit
ist größer als der Nachladezeit
, d. h. wenn der Turm erneut geladen wurde. Und das zurücksetzen
Funktion setzt einfach das zurück Ortszeit
Variable, um es erneut zu laden.
Nun zurück in die Main
Klasse, ändern Sie den Schießcode in der Spielschleife, die wir im vorherigen Schritt hinzugefügt haben:
für jedes (Revolver in Revolver) turret.update (); if (! turret.isReady ()) fortsetzen; für jeden (Feind in Feinden) schießen (Turm, Feind); turret.reset (); brechen;
Wenn nun der Turm nicht fertig ist (ist bereit()
kehrt zurück falsch
) fahren wir mit der nächsten Iteration der Revolverschleife fort. Sie werden sehen, dass die Türmchen jetzt im Abstand von 30 Bildern oder 1 Sekunde ausgelöst werden. Cool!
Immer noch etwas nicht richtig. Die Türme schießen auf Feinde ungeachtet der Entfernung zwischen ihnen. Was hier fehlt, ist das Angebot eines Turms. Jeder Turm sollte eine eigene Reichweite haben, in die er einen Gegner schießen kann. Fügen Sie eine weitere Variable zum hinzu Turm
Klasse aufgerufen Angebot
und setze es auf 120
im Konstruktor:
private var reload_time: int; private var local_time: Anzahl = 0; privater var Bereich: int;
öffentliche Funktion Turret () reload_time = 30; Bereich = 120; zeichnen();
Fügen Sie auch eine aufgerufene Funktion hinzu canShoot
am Ende des Unterrichts:
public function canShoot (Feind: Feind): Boolean var dx: Number = enemy.x - x; var dy: Anzahl = Feind.y - y; if (Math.sqrt (dx * dx + dy * dy) <= range) return true; else return false;
Jeder Turm kann nur dann auf einen Gegner schießen, wenn er bestimmte Kriterien erfüllt. Zum Beispiel können Sie den Turm nur auf rote Gegner mit weniger als der Hälfte ihrer Lebensdauer und höchstens 30 Pixeln entfernt lassen. All diese Logik, um zu bestimmen, ob der Turm einen Feind abschießen kann oder nicht, geht in die canShoot
Funktion, die zurückkehrt wahr
oder falsch
nach der Logik.
Unsere Logik ist einfach. Wenn der Feind in Reichweite ist, kehre zurück wahr
; sonst falsch zurückgeben. Wenn also die Entfernung zwischen dem Turm und dem Feind (Math.sqrt (dx * dx + dy * dy)
) ist kleiner oder gleich Angebot
, es kehrt zurück wahr
. Ein wenig mehr Modifikation im Shoot-Bereich der Spielschleife:
für jedes (Revolver in Revolver) turret.update (); if (! turret.isReady ()) fortsetzen; für jeden (Feind in Feinden) if (turret.canShoot (Feind)) schießen (Turret, Feind); turret.reset (); brechen;
Nur wenn der Feind sich innerhalb der Reichweite des Turms befindet, wird der Turm schießen.
Ein sehr wichtiger Teil jedes Spiels ist die Kollisionserkennung. In unserem Spiel wird eine Kollisionsprüfung zwischen Kugeln und Feinden durchgeführt. Wir werden den Kollisionserkennungscode in die für jeden
Schleife, die die Kugeln in der Spielschleife aktualisiert.
Die Logik ist einfach. Für jede Kugel durchqueren wir die Feinde
Array und überprüfen, ob es eine Kollision zwischen ihnen gibt. In diesem Fall entfernen wir die Kugel, aktualisieren die Gesundheit des Feindes und brechen aus der Schleife, um andere Feinde zu überprüfen. Fügen wir etwas Code hinzu:
für (i = Geschosse. Länge - 1; i> = 0; i--) Geschoss = Geschosse [i]; // Wenn das Aufzählungszeichen nicht definiert ist, fahren Sie mit der nächsten Iteration fort. if (! bullet) continue; bullet.update (); if (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (bullet); fortsetzen; for (var k: int = Feinde. Länge - 1; k> = 0; k--) Feind = Feinde [k]; if (bullet.hitTestObject (Feind)) bullets.splice (i, 1); bullet.parent.removeChild (bullet); if (enemy.updateHealth (-1) == 0) enemies.splice (k, 1); Feind.Parent.RemoveChild (Feind); brechen;
Wir verwenden ActionScript hitTestObject
Funktion zur Überprüfung auf Kollision zwischen Kugel und Feind. Wenn die Kollision auftritt, wird das Geschoss auf dieselbe Weise entfernt wie beim Verlassen der Bühne. Die Gesundheit des Feindes wird dann mithilfe von aktualisiert updateHealth
Methode, zu der Kugel
's Beschädigung
Eigentum wird übergeben. Wenn die updateHealth
Funktion gibt eine ganze Zahl zurück, die kleiner oder gleich ist 0
, Das bedeutet, dass der Feind tot ist, und wir entfernen ihn genauso wie die Kugel.
Und unsere Kollisionserkennung ist fertig!
Denken Sie daran, dass wir die Feinde und Kugeln in unserer Spielschleife rückwärts durchqueren. Lass uns verstehen warum. Angenommen, wir haben einen Aufstieg benutzt zum
Schleife. Wir sind im Index i = 3
und wir entfernen eine Kugel aus dem Array. Bei Entfernung des Artikels an Position 3
, Sein Platz wird durch den Artikel dann an Position gefüllt 4
. Also jetzt der Artikel vorher an Position 4
ist um 3
. Nach der Iteration ich
erhöht sich um 1
und wird 4
und so Position an Position 4
wird geprüft.
Ups, siehst du, was gerade passiert ist? Wir haben den Artikel gerade auf Position verpasst 3
die als Ergebnis des Spleißens nach hinten verschoben. Und so verwenden wir eine Umkehrung zum
Schleife, die dieses Problem beseitigt. Sie können sehen warum.
Lassen Sie uns ein paar Extras hinzufügen, damit das Spiel gut aussieht. Wir werden Funktionen hinzufügen, um den Bereich eines Revolvers anzuzeigen, wenn die Maus darauf bewegt wird. Wechseln Sie zum Turm
Klasse und fügen Sie einige Variablen hinzu:
privater var Bereich: int; private var reload_time: int; private var local_time: Anzahl = 0; privater var Körper: Sprite; private var range_circle: Sprite;
Nächstes Update der zeichnen
Funktion auf Folgendes:
private Funktion draw (): void range_circle = new Sprite (); g = range_circle.graphics; g.beginFill (0x00D700); g.DrawCircle (0, 0, Bereich); g.endFill (); range_circle.alpha = 0,2; range_circle.visible = false; addChild (range_circle); body = new Sprite (); var g: Graphics = Körpergrafiken; g.beginFill (0xD7D700); g.DrawCircle (0, 0, 20); g.beginFill (0x800000); g.DrawRect (0, -5, 25, 10); g.endFill (); addChild (Körper);
Wir unterteilen die Grafiken des Revolvers in zwei Teile: den Körper und die Bereichsgrafik. Wir tun dies, um die verschiedenen Teile des Turms zu ordnen. Hier brauchen wir die range_circle
Hinter dem Körper des Turms zu sein, und so fügen wir ihn zuerst der Bühne hinzu. Zum Schluss fügen wir zwei Maus-Listener hinzu, um die Bereichsgrafik umzuschalten:
private Funktion onMouseOver (e: MouseEvent): void range_circle.visible = true; private Funktion onMouseOut (e: MouseEvent): void range_circle.visible = false;
Verbinden Sie nun die Listener mit den jeweiligen Ereignissen am Ende des Konstruktors:
body.addEventListener (MouseEvent.MOUSE_OVER, onMouseOver); body.addEventListener (MouseEvent.MOUSE_OUT, onMouseOut);
Wenn Sie das Spiel ausführen und versuchen, einen Turm bereitzustellen, wird ein Flackern angezeigt, wenn Sie sich auf den Platzhaltern befinden. Warum das?
Erinnern wir uns, dass wir die mouseEnabled
Eigentum des Geisterturms an falsch
? Wir haben das getan, weil der Geisterrevolver Mausereignisse erfasst hat, indem er zwischen Maus und Platzhalter kam. Die gleiche Situation ist wieder da, da der Turm selbst jetzt zwei Kinder hat - seinen Körper und das Range-Sprite -, die die Mausereignisse dazwischen erfassen.
Die Lösung ist die gleiche. Wir können uns individuell einstellen mouseEnabled
Eigenschaften zu falsch
. Eine bessere Lösung ist jedoch die Einstellung der Geisterrevolver mouseChildren
Eigentum an falsch
. Dies bedeutet, dass alle Kinder des Geister-Revolveres Mausereignisse erhalten. Ordentlich, was? Gehen Sie voran und setzen Sie es auf falsch
in dem Main
Konstrukteur:
ghost_turret = new Turret (); ghost_turret.alpha = 0,5; ghost_turret.mouseEnabled = false; ghost_turret.mouseChildren = false; ghost_turret.visible = false; addChild (ghost_turret);
Problem gelöst.
Wir könnten diese Demo um weitere erweiterte Funktionen erweitern und sie in ein spielbares Spiel verwandeln. Einige davon könnten sein:
Mal sehen, was Sie aus dieser grundlegenden Demo herausfinden können. Ich freue mich über Ihre Tower Defense-Spiele und Ihre Kommentare oder Vorschläge für die Serie.