Ottenere più caldo mira astutamente con i missili che cercano il calore

Nel tutorial precedente avevamo un missile homing che inseguiva un singolo bersaglio. Questo tutorial ti mostrerà come convertire i tuoi missili homing in missili a ricerca di calore per bersagli multipli.

Se non hai letto il primo tutorial di Homing Missile, puoi scaricare questo file .zip, che contiene il codice sorgente che inizieremo con questo tutorial.


Anteprima del risultato finale

Diamo un'occhiata al risultato finale su cui lavoreremo:


Passaggio 1: modifica il grafico cannone

L'unico filmato nella libreria che dovremo modificare è il Cannone, dal momento che lo faremo mirare al bersaglio più vicino prima di sparare. Ricorda che 0ш di rotazione significa puntare a destra, quindi rendere l'immagine di conseguenza.


Passaggio 2: dichiarare le variabili di distanza per il cannone

Ho intenzione di riutilizzare il TargetX e targetY variabili per calcolare la distanza del cannone dal bersaglio, quindi le dichiarerò all'inizio della classe invece che all'interno gioca funzione, così come una nuova variabile per memorizzare la distanza calcolata:

 missile var privato: Missile = new Missile (); velocità var privata: int = 15; cannone var privato: Cannon = new Cannon (); private var missileOut: Boolean = false; private var ease: int = 10; target var privato: Target = new Target (); piano privato var: int = 385; gravità var privata: Number = 0.5; private var targetVY: Number = 0; // Velocità verticale attuale della distanza var privata: int; private var targetX: int; private var targetY: int;

Ora il TargetX e targetY le variabili saranno già dichiarate per il gioca funzione:

 private function playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var explosion: Explosion = new Explosion (); addChild (esplosione); explosion.x = missile.x; explosion.y = missile.y; removeChild (missile); missileOut = falso;  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 && rotazione < 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 > piano) target.y = piano; targetVY = -18; 

Step 3: Fai il Cannon Point verso il bersaglio

Precedentemente nel gioca funzione a cui eravamo interessati solo a sapere se il missile era fuori per prendersi cura della sua rotazione e del suo movimento. Ora dobbiamo prima sapere se il missile non è ancora stato sparato e aggiornare la rotazione del cannone.

 private function 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 = new Explosion (); addChild (esplosione); explosion.x = missile.x; explosion.y = missile.y; removeChild (missile); missileOut = falso;  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 && rotazione < 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 > piano) target.y = piano; targetVY = -18; 

Ora il cannone ruota in relazione alla posizione del bersaglio.


Step 4: Abbina la rotazione del missile con quella del cannone.

Il cannone sta ruotando, ma il missile continua a sparare verso l'alto. Sostituisci la rotazione hard-coded con la posizione corrente del cannone nel momento in cui il missile viene sparato.

 funzione privata shoot (event: MouseEvent): void if (! missileOut) addChild (missile); swapChildren (missile, cannone); // il missile uscirà da dietro il missile cannoneOut = true; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = cannon.rotation; 

Ora il missile sembrerà effettivamente uscito dal cannone.


Passaggio 5: più di un obiettivo

In questo momento il missile homing è un programma per perseguire un obiettivo, ma se avessimo più obiettivi? Come deciderà quale seguire?

Per prima cosa, decidiamo quanti bersagli ci saranno, quindi metteremo ciascun bersaglio in una matrice. In questo esempio dirò che ci sono 2 bersagli e assegnerò a ciascun bersaglio una posizione casuale sullo schermo.

 target var privato: target; piano privato var: int = 385; gravità var privata: Number = 0.5; private var targetVY: Number = 0; // Velocità verticale attuale della distanza var privata: int; private var targetX: int; private var targetY: int; private var numTargets: int = 2; target var privati: Array = []; funzione pubblica Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); per (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);  

Ora abbiamo più di un obiettivo sullo schermo.

Il missile sta ancora riconoscendo l'esistenza di un bersaglio. Lo sistemeremo dopo.


Passaggio 6: cercare l'obiettivo più vicino

Abbiamo il missile che cerca il bersaglio variabile, quindi controlliamo il obiettivi Metti in fila e vedi quale è più vicino. Il bersaglio la variabile farà riferimento al più vicino all'inizio del gioca funzione.

 private function 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];  

A questo punto l'obiettivo più vicino è l'unico in movimento, ma il missile sta riconoscendo l'esistenza di entrambi:


Passaggio 7: Correggi lo scopo del cannone

Potresti aver notato che mentre il missile cerca il bersaglio previsto, il cannone è bloccato puntando allo stesso bersaglio, indipendentemente dal fatto che sia più vicino o più lontano dell'altro. La distanza è impostata in relazione alla posizione del missile, quindi se non ci sono missili sul palco dobbiamo aggiornare la sua posizione per far combaciare il cannone in modo che sappia sempre quale è più vicino.

 private function 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; 

Ora il cannone mirerà sempre al bersaglio più vicino.


Step 8: Muovi il Cannone

Prima che il missile venga sparato, il cannone punta già al bersaglio più vicino e cambierà direzione se si avvicina all'altro bersaglio. Aggiungiamo un paio di linee per posizionare il cannone con il cursore del mouse.

 private function playGame (event: Event): void cannon.x = mouseX; cannon.y = mouseY;

Ora puoi muovere liberamente il cannone.


Passo 9: bersaglio colpito, bersaglio distrutto

Per rendere le cose più dinamiche qui, ho intenzione di ricollocare un bersaglio dopo essere stato colpito da un missile, o sostituirlo con uno nuovo, e lasciare un Esplosione istanza al suo posto.

 if (missile.hitTestObject (target)) var explosion: Explosion = new Explosion (); addChild (esplosione); explosion.x = missile.x; explosion.y = missile.y; removeChild (missile); missileOut = falso; esplosione = nuova esplosione (); addChild (esplosione); explosion.x = target.x; explosion.y = target.y; explosion.scaleX = explosion.scaleY = 1.5; target.x = Math.random () * 600; 

Questo è ciò che otterrai:


Step 10: Missili multipli

Abbiamo creato più obiettivi, quindi ora possiamo creare più missili allo stesso modo. La differenza qui è che tutti i missili devono continuare a muoversi in qualsiasi momento fino a quando non colpiscono, e in realtà stiamo per rimuovere quelli che sono già esplosi, quindi abbiamo bisogno di modificare alcune righe del nostro codice affinché funzioni. Per prima cosa, avremo bisogno di una matrice per i missili.

 missili var privati: Array = [];

Quindi, dobbiamo assicurarci che tutti i missili si comportino correttamente:

 private function playGame (event: Event): void cannon.x = mouseX; cannon.y = mouseY; per (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 (rotazione> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotazione < 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 > piano) target.y = piano; targetVY = -18;  private function shoot (event: MouseEvent): void missile = new Missile (); missiles.push (missile); // nell'array addChild (missile); swapChildren (missile, cannone); // il missile uscirà da dietro il missile cannoneOut = true; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = cannon.rotation; 

Ora quando un bersaglio viene distrutto, i missili cercheranno il prossimo bersaglio.

A questo punto tutti i missili stanno inseguendo lo stesso obiettivo. Per far sì che ogni missile cerchi il proprio bersaglio, sarebbe meglio creare una classe separata per i missili in cui si determina individualmente il bersaglio più vicino.


Step 11: Crea un mirino

A questo punto hai già capito l'idea principale di questo tutorial, ma ammettiamolo, un nemico non si muoverà solo in base alla sua distanza da te o dai tuoi missili. Puoi usare un altro indicatore, come un mirino. Crea un filmato ed esportalo in Actionscript.


Step 12: Usa il mirino

Ora sarà chiaro a tutti a chi si rivolge l'obiettivo. Basta aggiungere un'istanza di Crosshair Un filmato.

 private var crosshair: Crosshair = new Crosshair (); funzione pubblica Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); per (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); 

Quindi posizionalo sul bersaglioLa posizione come ultima istruzione nel gioca funzione.

 targetVY + = gravità; target.y + = targetVY; se (target.y> floor) target.y = floor; targetVY = -18;  crosshair.x = target.x; crosshair.y = target.y; 

Otterrai un mirino che segna la posizione del bersaglio più vicino.


Passaggio 13: sposta tutti i target

Ricordi cosa ho detto a proposito dei missili? Lo stesso vale per gli obiettivi: avranno un aspetto migliore nella propria classe con un insieme di istruzioni a sé stanti. Questo è solo un esempio veloce, ma nel tuo gioco non consiglio la codifica di tutti gli oggetti nel Principale classe. Più il tuo gioco è complesso, meno roba potrai codificare all'interno del gioco Principale classe.

Gli obiettivi sono già in una matrice, che è già stata controllata in a per loop, quindi sposterò le istruzioni di rimbalzo all'interno del per loop, in modo che tutti gli obiettivi, non importa quanti, si muoveranno sempre nello stesso modo.

 private function playGame (event: Event): void cannon.x = mouseX; cannon.y = mouseY; targetVY + = gravità; per (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 > floor) target [i] .y = floor;  if (target.y> = floor) targetVY = -18; 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++)  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 (rotazione> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotazione < 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; 

Guarda:


Conclusione

Missili Homing, missili a ricerca di calore, entrambi sono un'arma divertente e utile da avere in giro in un gioco di tiro o magari in qualche altro tipo di app. Questo tutorial mostra un esempio del suo utilizzo e dell'algoritmo per farlo, ma per le migliori pratiche si consiglia di avere classi separate per i missili e gli obiettivi, a meno che la tua app sia semplice e breve come questa.

Spero tu abbia trovato utile questo tutorial. Grazie per aver letto!