Immer wärmer Intelligentes Zielen mit hitzesuchenden Raketen

Im vorherigen Tutorial hatten wir eine Zielrakete, die einem einzelnen Ziel nachjagte. In diesem Tutorial erfahren Sie, wie Sie Ihre Zielraketen in hitzesuchende Raketen für mehrere Ziele umwandeln.

Wenn Sie das erste Homing Missile-Tutorial nicht gelesen haben, können Sie diese ZIP-Datei herunterladen, die den Quellcode enthält, mit dem wir in diesem Tutorial beginnen.


Endergebnisvorschau

Werfen wir einen Blick auf das Endergebnis, auf das wir hinarbeiten:


Schritt 1: Ändern Sie die Kanonengrafik

Der einzige Movieclip in der Bibliothek, den wir ändern müssen, ist der Kanone, da wir es vor dem Schießen auf das nächste Ziel ausrichten lassen. Denken Sie daran, dass 0 0 von Drehung bedeutet, nach rechts zu zeigen, machen Sie die Grafik entsprechend.


Schritt 2: Deklarieren Sie die Entfernungsvariablen für die Kanone

Ich werde das wiederverwenden targetX und targetY Variablen, um die Entfernung der Kanone vom Ziel zu berechnen, so erkläre ich sie am Anfang der Klasse anstatt im Inneren der Klasse Spiel spielen Funktion sowie eine neue Variable zum Speichern der berechneten Entfernung:

 private Var-Rakete: Rakete = neue Rakete (); private var Geschwindigkeit: int = 15; private var-Kanone: Kanone = neue Kanone (); private var missileOut: Boolean = false; private Variabilität: int = 10; private var target: Target = neues Ziel (); private var Etage: int = 385; private Schwerkraft: Zahl = 0,5; private var targetVY: Number = 0; // Aktuelle vertikale Geschwindigkeit des Ziels private var Entfernung: int; private var targetX: int; private var targetY: int;

Jetzt die targetX und targetY Variablen werden bereits für die deklariert Spiel spielen Funktion:

 private Funktion playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var explosion: Explosion = neue Explosion (); addChild (explosion); explosion.x = missile.x; explosion.y = Flugkörper.y; removeChild (Rakete); missileOut = false;  else targetX = target.x - missile.x; targetY = target.y - missile.y; var rotation: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (Drehung - missile.rotation)> 180) wenn (Drehung> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && Drehung < 0) missile.rotation += (360 - rotation + missile.rotation) / ease;  else if (rotation < missile.rotation) missile.rotation -= Math.abs(missile.rotation - rotation) / ease; else missile.rotation += Math.abs(rotation - missile.rotation) / ease; var vx:Number = speed * (90 - Math.abs(missile.rotation)) / 90; var vy:Number; if (missile.rotation < 0) vy = -speed + Math.abs(vx); else vy = speed - Math.abs(vx); missile.x += vx; missile.y += vy;   targetVY += gravity; target.y += targetVY; if (target.y > floor) target.y = floor; targetVY = -18; 

Schritt 3: Richten Sie die Kanone auf das Ziel

Vorher im Spiel spielen Funktion Wir waren nur daran interessiert zu wissen, ob die Rakete sich um ihre Rotation und Bewegung kümmern sollte. Jetzt müssen wir zuerst wissen, ob die Rakete noch nicht geschossen wurde, und die Rotation der Kanone aktualisieren.

 private Funktion playGame (event: Event): void if (! missileOut) targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.rotation = Math.atan2 (targetY, targetX) * 180 / Math.PI;  else if (missile.hitTestObject (target)) var explosion: Explosion = neue Explosion (); addChild (explosion); explosion.x = missile.x; explosion.y = Flugkörper.y; removeChild (Rakete); missileOut = false;  else targetX = target.x - missile.x; targetY = target.y - missile.y; var rotation: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (Drehung - missile.rotation)> 180) wenn (Drehung> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && Drehung < 0) missile.rotation += (360 - rotation + missile.rotation) / ease;  else if (rotation < missile.rotation) missile.rotation -= Math.abs(missile.rotation - rotation) / ease; else missile.rotation += Math.abs(rotation - missile.rotation) / ease; var vx:Number = speed * (90 - Math.abs(missile.rotation)) / 90; var vy:Number; if (missile.rotation < 0) vy = -speed + Math.abs(vx); else vy = speed - Math.abs(vx); missile.x += vx; missile.y += vy;   targetVY += gravity; target.y += targetVY; if (target.y > floor) target.y = floor; targetVY = -18; 

Jetzt dreht sich die Kanone in Bezug auf die Position des Ziels.


Schritt 4: Stimmen Sie die Rotation der Rakete mit der Kanone ab.

Die Kanone dreht sich, aber die Rakete wird weiter nach oben geschossen. Ersetzen Sie die fest codierte Rotation durch die aktuelle Position der Kanone im Moment des Abschusses der Rakete.

 private Funktion shoot (Ereignis: MouseEvent): void if (! missileOut) addChild (missile); swapChildren (Rakete, Kanone); // Rakete kommt hinter der Kanone heraus missileOut = true; missile.x = cannon.x; missile.y = Kanone.y; missile.rotation = cannon.rotation; 

Jetzt sieht die Rakete so aus, als würde sie tatsächlich aus der Kanone herauskommen.


Schritt 5: Mehr als ein Ziel

Im Moment ist die Zielrakete ein Programm, um ein Ziel zu erreichen, aber was ist, wenn wir mehr Ziele haben? Wie wird es entscheiden, nach welchem ​​zu gehen??

Zuerst entscheiden wir, wie viele Ziele es gibt, dann setzen wir jedes Ziel in ein Array. In diesem Beispiel möchte ich sagen, dass es zwei Ziele gibt, und ich gebe jedem Ziel eine zufällige Position auf dem Bildschirm.

 privates var-Ziel: Ziel; private var Etage: int = 385; private Schwerkraft: Zahl = 0,5; private var targetVY: Number = 0; // Aktuelle vertikale Geschwindigkeit des Ziels private var Entfernung: int; private var targetX: int; private var targetY: int; private var numTargets: int = 2; private var-Ziele: Array = []; öffentliche Funktion Main () addChild (Kanone); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, Schießen); für (var i: int = 0; i < numTargets; i++)  target = new Target(); addChild(target); target.x = Math.random() * 600; target.y = Math.random() * 400; targets.push(target);  

Jetzt haben wir mehr als ein Ziel auf dem Bildschirm.

Die Rakete erkennt immer noch nur die Existenz eines Ziels an. Wir werden das als nächstes beheben.


Schritt 6: Suchen Sie das nächstgelegene Ziel

Wir haben die Rakete gesucht Ziel variabel, also überprüfen wir die Ziele Array und sehen, welche näher ist. Das Ziel Die Variable referenziert die am nächsten liegende Spiel spielen Funktion.

 private Funktion playGame (event: Event): void for (var i: int = 0; i < targets.length; i++)  targetX = targets[i].x - missile.x; targetY = targets[i].y - missile.y; var dist:int = Math.sqrt(targetX * targetX + targetY * targetY);//the distance from one point to another in a 2D space. if (i == 0 || dist < distance)  distance = dist; target = targets[i];  

An diesem Punkt ist das nächste Ziel das einzige, das sich bewegt, aber die Rakete erkennt die Existenz von beiden an:


Schritt 7: Fixieren Sie das Ziel der Kanone

Sie haben vielleicht bemerkt, dass, während die Rakete das erwartete Ziel sucht, die Kanone auf dasselbe Ziel gerichtet ist, unabhängig davon, ob sie näher oder weiter als das andere ist. Die Entfernung wird in Relation zur Position der Rakete festgelegt. Wenn sich also keine Rakete auf der Bühne befindet, müssen wir ihre Position an die Kanone anpassen, damit sie immer weiß, welche näher ist.

 private Funktion playGame (event: Event): void for (var i: int = 0; i < targets.length; i++)  targetX = targets[i].x - missile.x; targetY = targets[i].y - missile.y; var dist:int = Math.sqrt(targetX * targetX + targetY * targetY); if (i == 0 || dist < distance)  distance = dist; target = targets[i];   if (!missileOut)  missile.x = cannon.x; missile.y = cannon.y; targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.rotation = Math.atan2(targetY, targetX) * 180 / Math.PI; 

Jetzt zielt die Kanone immer auf das nächste Ziel.


Schritt 8: Bewegen Sie die Kanone

Bevor die Rakete geschossen wird, zeigt die Kanone bereits auf das nächste Ziel und ändert ihre Richtung, wenn sie näher an das andere Ziel herangefahren wird. Fügen Sie ein paar Zeilen hinzu, um die Kanone mit dem Mauszeiger zu positionieren.

 private Funktion playGame (Ereignis: Ereignis): void cannon.x = mouseX; cannon.y = mouseY;

Jetzt können Sie die Kanone frei bewegen.


Schritt 9: Ziel getroffen, Ziel zerstört

Um die Dinge hier dynamischer zu gestalten, verlagere ich ein Ziel, nachdem es von einer Rakete getroffen wurde oder Ersetzen Sie es durch ein neues, und lass ein Explosion Instanz an seiner Stelle.

 if (missile.hitTestObject (Ziel)) var explosion: Explosion = new Explosion (); addChild (explosion); explosion.x = missile.x; explosion.y = Flugkörper.y; removeChild (Rakete); missileOut = false; Explosion = neue Explosion (); addChild (explosion); explosion.x = target.x; explosion.y = Ziel.y; explosion.scaleX = explosion.scaleY = 1,5; target.x = Math.random () * 600; 

Das wirst du bekommen:


Schritt 10: Mehrere Raketen

Wir haben mehrere Ziele gemacht, so dass wir jetzt mehrere Raketen auf dieselbe Weise herstellen können. Der Unterschied hier ist, dass sich alle Raketen ständig bewegen müssen, bis sie getroffen werden, und wir werden tatsächlich die bereits explodierten entfernen, so dass wir ein paar Zeilen unseres Codes ändern müssen, damit dies funktioniert. Zuerst brauchen wir ein Array für die Raketen.

 private Var-Raketen: Array = [];

Dann müssen wir sicherstellen, dass sich alle Raketen korrekt verhalten:

 private Funktion playGame (Ereignis: Ereignis): void cannon.x = mouseX; cannon.y = mouseY; für (var i: int = 0; i < targets.length; i++)  targetX = targets[i].x - missile.x; targetY = targets[i].y - missile.y; var dist:int = Math.sqrt(targetX * targetX + targetY * targetY); if (i == 0 || dist < distance)  distance = dist; target = targets[i];   if (!missileOut)  missile.x = cannon.x; missile.y = cannon.y; targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.rotation = Math.atan2(targetY, targetX) * 180 / Math.PI;  else  for (i = 0; i < missiles.length; i++)//each missile must keep moving  missile = missiles[i]; if (missile.hitTestObject(target))  var explosion:Explosion = new Explosion(); addChild(explosion); explosion.x = missile.x; explosion.y = missile.y; removeChild(missile); missiles.splice(i, 1);//out of the Array if (missiles.length < 1)//only if no missiles are out at all missileOut = false; explosion= new Explosion(); addChild(explosion); explosion.x = target.x; explosion.y = target.y; explosion.scaleX = explosion.scaleY = 1.5; target.x = Math.random() * 600;  else  targetX = target.x - missile.x; targetY = target.y - missile.y; var rotation:int = Math.atan2(targetY, targetX) * 180 / Math.PI; if (Math.abs(rotation - missile.rotation) > 180) if (Rotation> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && Drehung < 0) missile.rotation += (360 - rotation + missile.rotation) / ease;  else if (rotation < missile.rotation) missile.rotation -= Math.abs(missile.rotation - rotation) / ease; else missile.rotation += Math.abs(rotation - missile.rotation) / ease; var vx:Number = speed * (90 - Math.abs(missile.rotation)) / 90; var vy:Number; if (missile.rotation < 0) vy = -speed + Math.abs(vx); else vy = speed - Math.abs(vx); missile.x += vx; missile.y += vy;    targetVY += gravity; target.y += targetVY; if (target.y > floor) target.y = floor; targetVY = -18;  private function shoot (Ereignis: MouseEvent): void missile = new Missile (); missiles.push (Rakete); // in das Array addChild (Rakete); swapChildren (Rakete, Kanone); // Rakete kommt hinter der Kanone heraus missileOut = true; missile.x = cannon.x; missile.y = Kanone.y; missile.rotation = cannon.rotation; 

Wenn nun ein Ziel zerstört wird, suchen die Raketen das nächste Ziel.

An diesem Punkt jagen alle Raketen dem gleichen Ziel nach. Damit jede Rakete ihr eigenes Ziel sucht, ist es besser, für die Raketen eine eigene Klasse zu erstellen, in der Sie das nächstgelegene Ziel individuell bestimmen.


Schritt 11: Machen Sie ein Fadenkreuz

An diesem Punkt haben Sie die Grundidee dieses Tutorials bereits verstanden, aber seien wir ehrlich, ein Feind bewegt sich nicht nur abhängig von seiner Entfernung zu Ihnen oder Ihren Raketen. Sie können einen anderen Indikator verwenden, z. B. ein Fadenkreuz. Machen Sie einen Movieclip und exportieren Sie ihn nach Actionscript.


Schritt 12: Verwenden Sie das Fadenkreuz

Nun wird jedem klar sein, auf welches Ziel es gerichtet ist. Fügen Sie einfach eine Instanz von hinzu Fadenkreuz Filmausschnitt.

 privates var-Fadenkreuz: Fadenkreuz = neues Fadenkreuz (); öffentliche Funktion Main () addChild (Kanone); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, Schießen); für (var i: int = 0; i < numTargets; i++)  target = new Target(); addChild(target); target.x = Math.random() * 600; target.y = Math.random() * 400; targets.push(target);  addChild(crosshair); 

Dann legen Sie es auf die ZielPosition als letzte Anweisung in der Spiel spielen Funktion.

 targetVY + = Schwerkraft; target.y + = targetVY; if (target.y> Etage) target.y = Etage; targetVY = -18;  Fadenkreuz.x = Ziel.x; Fadenkreuz.y = Ziel.y; 

Sie erhalten ein Fadenkreuz, das die Position des nächstgelegenen Ziels markiert.


Schritt 13: Alle Ziele verschieben

Erinnern Sie sich an das, was ich über die Raketen gesagt habe? Gleiches gilt für die Ziele: Sie werden in ihrer eigenen Klasse mit eigenen Anweisungen besser aussehen. Dies ist nur ein kurzes Beispiel, aber ich empfehle Ihnen in Ihrem Spiel nicht, alle Objekte in der Main Klasse. Je komplexer Ihr Spiel ist, desto weniger Code programmieren Sie im Main Klasse.

Die Ziele befinden sich bereits in einem Array, das bereits in a geprüft wird zum Schleife, also bewege ich die Prellanweisungen in die zum Schleife, so dass alle Ziele, egal wie viele, sich immer gleich bewegen.

 private Funktion playGame (Ereignis: Ereignis): void cannon.x = mouseX; cannon.y = mouseY; targetVY + = Schwerkraft; für (var i: int = 0; i < targets.length; i++)  targetX = targets[i].x - missile.x; targetY = targets[i].y - missile.y; var dist:int = Math.sqrt(targetX * targetX + targetY * targetY); if (i == 0 || dist < distance)  distance = dist; target = targets[i];  targets[i].y += targetVY; if (targets[i].y > Boden) Ziele [i] .y = Boden;  if (target.y> = floor) targetVY = -18; if (! missileOut) missile.x = cannon.x; missile.y = Kanone.y; targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.rotation = Math.atan2 (targetY, targetX) * 180 / Math.PI;  else für (i = 0; i < missiles.length; i++)  missile = missiles[i]; if (missile.hitTestObject(target))  var explosion:Explosion = new Explosion(); addChild(explosion); explosion.x = missile.x; explosion.y = missile.y; removeChild(missile); missiles.splice(i, 1); if (missiles.length < 1) missileOut = false; explosion= new Explosion(); addChild(explosion); explosion.x = target.x; explosion.y = target.y; explosion.scaleX = explosion.scaleY = 1.5; target.x = Math.random() * 600;  else  targetX = target.x - missile.x; targetY = target.y - missile.y; var rotation:int = Math.atan2(targetY, targetX) * 180 / Math.PI; if (Math.abs(rotation - missile.rotation) > 180) if (Rotation> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && Drehung < 0) missile.rotation += (360 - rotation + missile.rotation) / ease;  else if (rotation < missile.rotation) missile.rotation -= Math.abs(missile.rotation - rotation) / ease; else missile.rotation += Math.abs(rotation - missile.rotation) / ease; var vx:Number = speed * (90 - Math.abs(missile.rotation)) / 90; var vy:Number; if (missile.rotation < 0) vy = -speed + Math.abs(vx); else vy = speed - Math.abs(vx); missile.x += vx; missile.y += vy;    crosshair.x = target.x; crosshair.y = target.y; 

Schau mal:


Fazit

Zielraketen und hitzesuchende Raketen sind beide eine lustige und nützliche Waffe, die Sie in einem Schießspiel oder einer anderen Art von App verwenden können. Dieses Tutorial zeigt ein Beispiel für seine Verwendung und den Algorithmus, um es zu erstellen. Für bewährte Methoden wird jedoch empfohlen, separate Klassen für die Raketen und die Ziele zu verwenden, es sei denn, Ihre Anwendung ist so einfach und kurz wie diese.

Ich hoffe, Sie fanden dieses Tutorial hilfreich. Danke fürs Lesen!