În tutorialul precedent am avut o lovitură de rachete care a urmărit după o singură țintă. Acest tutorial vă va arăta cum să vă convertiți rachetele de găzduire în rachete căutând căldură pentru mai multe ținte.
Dacă nu ați citit primul tutorial Homing Missile, puteți descărca acest fișier .zip, care conține codul sursă pe care îl vom începe în acest tutorial.
Să aruncăm o privire la rezultatul final la care vom lucra:
Singurul film Clip din Biblioteca pe care trebuie să-l schimbăm este Tun, deoarece vom face ca scopul să fie cel mai apropiat țintă înainte de fotografiere. Amintiți-vă că 0º de rotație înseamnă să îndrepți spre dreapta, așa că faceți graficul în consecință.
O să reutilizez targetX și targetY variabile pentru a calcula distanța tunului de țintă, așa că le voi declara la începutul clasei în loc de joaca jocul funcția, precum și o nouă variabilă pentru a stoca distanța calculată:
rachetă privată var: Missile = nouă rachetă (); viteză privată var: int = 15; privat var cannon: Cannon = nou Cannon (); private var missileOut: boolean = fals; privat var ușurință: int = 10; target privat var: Target = new Target (); privat var pod: int = 385; privat var gravitate: Number = 0.5; private var targetVY: Number = 0; // Viteza curentă verticală a distanței țintă private var: int; private var targetX: int; private target targetY: int;
Acum targetX și targetY variabilele vor fi deja declarate pentru joaca jocul funcţie:
funcția privată playGame (eveniment: Eveniment): void if (missileOut) if (missile.hitTestObject (target)) var explozie: Explozie = Explozie nouă; addChild (explozie); exploion.x = rachetă.x; exploion.y = rachetă; removeChild (rachete); missileOut = false; altceva targetX = target.x - missile.x; targetY = target.y - missile.y; var rotație: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; dacă (Math.abs (rotație - rachetă.ro)> 180) if (rotire> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotație < 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 > podea) target.y = podea; targetVY = -18;
Anterior în joaca jocul am fost interesați doar să aflăm dacă racheta era în afara să se ocupe de rotație și de mișcare. Acum trebuie să știm mai întâi dacă racheta nu a fost împușcată și să actualizeze rotația tunului.
funcția privată playGame (eveniment: Eveniment): void if (! missileOut) targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.ro = Math.atan2 (targetY, targetX) * 180 / Math.PI; altceva if (missile.hitTestObject (target)) var explozie: Explozie = Explozie nouă (); addChild (explozie); exploion.x = rachetă.x; exploion.y = rachetă; removeChild (rachete); missileOut = false; altceva targetX = target.x - missile.x; targetY = target.y - missile.y; var rotație: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; dacă (Math.abs (rotație - rachetă.ro)> 180) if (rotire> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotație < 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 > podea) target.y = podea; targetVY = -18;
Acum tunul se rotește în raport cu poziția țintă.
Tunul se rotește, dar racheta continuă să fie împinsă în sus. Înlocuiți rotația codată greu cu locația curentă a tunului în momentul în care se trage racheta.
funcția privată (eveniment: MouseEvent): void if (! missileOut) addChild (rachetă); swapChildren (rachetă, tun); / / racheta va ieși din spatele tunului rachetăOut = adevărat; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = cannon.rotation;
Acum, racheta va arăta de parcă ar ieși din tun.
În momentul de față, rachetele de găzduire sunt programate pentru a merge după o țintă, dar dacă avem mai multe ținte? Cum va decide cine să meargă după?
Mai întâi, hai să determinăm câte ținte vor exista, atunci vom pune fiecare țintă într-o matrice. În acest exemplu, am să spun că există două ținte și voi da fiecărei țintă o poziție aleatorie pe ecran.
target privat var: Țintă; privat var pod: int = 385; privat var gravitate: Number = 0.5; private var targetVY: Number = 0; // Viteza curentă verticală a distanței țintă private var: int; private var targetX: int; private target targetY: int; private var numTargets: int = 2; obiective private var: Array = []; funcția publică principală () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, trageți); pentru (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);
Acum avem mai mult de o țintă pe ecran.
Racheta încă recunoaște existența unei singure ținte. Vom repara următorul lucru.
Avem racheta care caută ţintă variabilă, deci hai să verificăm obiective
Array și a vedea care este mai aproape. ţintă variabila va fi cea mai apropiată la începutul joaca jocul funcţie.
funcția privată playGame (eveniment: Eveniment): void pentru (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];
În acest moment, ținta cea mai apropiată este singura care se mișcă, dar racheta recunoaște existența ambelor:
S-ar putea să fi observat că în timp ce racheta caută ținta așteptată, tunul a rămas în direcția aceleiași ținte, indiferent dacă este mai aproape sau mai departe decât celălalt. Distanța este stabilită în funcție de poziția rachetei, deci dacă nu există nici o rachetă pe scenă, trebuie să ne actualizăm poziția pentru a se potrivi cu tunul, astfel încât să știe întotdeauna care este mai aproape.
funcția privată playGame (eveniment: Eveniment): void pentru (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;
Acum tunul va viza mereu ținta cea mai apropiată.
Înainte ca racheta să fie împușcată, tunul indică deja ținta cea mai apropiată și va schimba direcția dacă se va apropia de cealaltă țintă. Să adăugăm câteva linii pentru a poziționa tunul cu ajutorul cursorului mouse-ului.
funcția privată playGame (eveniment: eveniment): void cannon.x = mouseX; cannon.y = mouseY;
Acum puteți muta tunul liber.
Pentru a face lucrurile mai dinamice aici, voi muta o țintă după ce am fost lovită de o rachetă sau înlocuiți-l cu unul nou, și lăsați-o Explozie exemplu în locul său.
dacă (missile.hitTestObject (țintă)) var explozie: Explozie = Explozie nouă (); addChild (explozie); exploion.x = rachetă.x; exploion.y = rachetă; removeChild (rachete); missileOut = false; explozie = Explozie nouă (); addChild (explozie); exploion.x = target.x; exploion.y = target.y; explozie.scaleX = explozie.scaleY = 1.5; target.x = Math.random () * 600;
Aceasta este ceea ce veți obține:
Am făcut mai multe ținte, așa că acum putem face mai multe rachete în același mod. Diferența este că toate rachetele trebuie să continue să se deplaseze în permanență până când au lovit și de fapt vom elimina cele care au explodat deja, așa că trebuie să modificăm câteva rânduri din codul nostru pentru ca acest lucru să funcționeze. În primul rând, vom avea nevoie de o matrice pentru rachete.
rachete private var: Array = [];
Apoi, trebuie să ne asigurăm că toate rachetele se comportă corect:
funcția privată playGame (eveniment: eveniment): void cannon.x = mouseX; cannon.y = mouseY; pentru (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 (rotire> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotație < 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 > podea) target.y = podea; targetVY = -18; funcția privată (eveniment: MouseEvent): void rachetă = nouă rachetă (); rachete (rachete); // în array addChild (rachetă); swapChildren (rachetă, tun); / / racheta va ieși din spatele tunului rachetăOut = adevărat; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = cannon.rotation;
Acum, când o țintă este distrusă, rachetele vor căuta următoarea țintă.
În acest moment, toate rachetele sunt urmărite după aceeași țintă. Pentru ca fiecare rachetă să caute ținta proprie, ar fi mai bine să faceți o clasă separată pentru rachetele în care stabiliți cel mai apropiat țintă individual.
În acest moment ați înțeles deja ideea principală a acestui tutorial, dar hai să ne confruntăm cu asta, un inamic nu se va deplasa în funcție de distanța față de tine sau de rachetele tale. Puteți utiliza un alt indicator, cum ar fi o cruce. Faceți un film Clip și exportați-l în Actionscript.
Acum va fi evident pentru oricine care este țintă. Doar adăugați o instanță a Crosshair Clip video.
privat var crosshair: Crosshair = nou Crosshair (); funcția publică principală () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, trageți); pentru (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);
Apoi puneți-l pe ţintăpoziția lui ca ultima instrucțiune din joaca jocul funcţie.
targetVY + = gravitate; target.y + = targetVY; dacă (target.y> floor) target.y = floor; targetVY = -18; crosshair.x = target.x; crosshair.y = target.y;
Veți obține o cruce care marchează poziția celui mai apropiat țintă.
Îți amintești ce am spus despre rachete? Același lucru se aplică și țintelor: Vor arăta mai bine în clasa proprie, cu un set de instrucțiuni proprii. Acesta este doar un exemplu rapid, dar în joc nu recomand codarea tuturor obiectelor din Principal clasă. Cu cât este mai complex jocul, cu atât mai puține lucruri pe care le vei codifica înăuntru Principal clasă.
Obiectivele sunt deja într-o matrice, care este deja verificată într-un pentru buclă, așa că voi mișca instrucțiunile de bouncing înăuntru pentru astfel încât toate țintele, indiferent de cât de multe, să se miște la fel în orice moment.
funcția privată playGame (eveniment: eveniment): void cannon.x = mouseX; cannon.y = mouseY; targetVY + = gravitate; pentru (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 > podea) ținte [i] .y = etaj; dacă (target.y> = floor) targetVY = -18; dacă (! missileOut) missile.x = cannon.x; missile.y = cannon.y; targetX = target.x - cannon.x; targetY = target.y - cannon.y; cannon.ro = Math.atan2 (targetY, targetX) * 180 / Math.PI; altceva pentru (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 (rotire> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotație < 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;
Aruncati o privire:
Rachete rachete, rachete căutând căldură, ambele sunt o arma distractivă și folositoare pentru a avea în jur într-un joc de fotografiere sau poate un alt tip de aplicație. Acest tutorial prezintă un exemplu de utilizare și algoritmul de a face acest lucru, dar pentru cele mai bune practici este recomandat să aveți clase separate pentru rachete și ținte, cu excepția cazului în care aplicația dvs. este la fel de simplă și scurtă ca aceasta.
Sper că ați găsit acest tutorial util. Vă mulțumim pentru lectură!