Denne opplæringen vil guide du ved å legge til dødelige nøyaktige homing missiler til arsenalen i ditt neste spill.
La oss se på det endelige resultatet vi vil jobbe for:
Opprett et nytt Flash-dokumentsett for ActionScript 3.0. Jeg skal bruke dimensjonene på 600x400, og en bildefrekvens på 30 FPS. Lagre filen med et valgfritt navn.
Foruten FLA, må vi også lage en dokumentklasse. Opprett en ny Actionscript-fil, og legg til denne koden:
pakke import flash.display.Sprite; offentlig klasse Hoved utvider Sprite offentlig funksjon Main ()
Lagre denne filen i samme katalog som vår FLA. Navn itjaMain.as.
For å kompilere koden fra Hoved klasse, må vi koble den med FLA. På thejaEiendommer panel av FLA, next toяKlasse, skriv inn navnet på dokumentklassen, i dette tilfellet, Hoved.
Deretter lagrer du endringene på FLA.
Vi trenger en rakettgrafikk som skal vises når du tar bilder. Du kan importere en bitmap eller tegne en form der ute på Flash. Jeg bruker en liten figur på dette eksempelet.
Det som er viktig her er at du må gjøre rakettpunktet rett til høyre, siden det er opprinnelsespunktet for rotasjonen. Så 0ш betyr peker rett til høyre, -90ш betyr oppover, 90ш betyr nedover, og 180ш peker mot venstre. Senere må vi rotere missilet i henhold til retningen.
Når du har rakettgrafikk, velger du den og trykker på F8 å lage en filmklipp. Gi det navnet "Missile", sørg for at Registreringspunkt er i midten, og kryss av i avkrysningsruten "Export for ActionScript".
Du vil ende opp med en Missile MovieClip i biblioteket.
Hvis du har en Missile-forekomst på scenen, må du slette den. Vi legger til Missile MovieClip etter kode.
Det første som en homing missil trenger å vite er hvor målet ligger. Vi skal sette rotasjonen av missilen i henhold til musepekerenes posisjon først. La oss jobbe med enterframe Hendelse for en konstant rotasjonsoppdatering.
Legg til en Rakett Eksempel på scenen, jeg plasserer den i midten (300, 200). Beregn deretter avstanden fra raketten til musemarkøren (jeg lagrer den i variabler targetX og targetY). Endelig vil rakets vinkel være bue tangent av begge punkter (targetX, targetY). Resultatet du får vil være i radianer, men rotasjonen fungerer i grader, så du må gjøre konverteringen ved å multiplisere med 180 / Pi. (For å se hvorfor, sjekk denne artikkelen.)
importere flash.events.Event; offentlig klasse Main utvider Sprite private var missil: Missile = new Missile (); offentlig funksjon Main () addChild (missil); missile.x = 300; missile.y = 200; addEventListener (Event.ENTER_FRAME, playGame); privat funksjon playGame (event: Event): void var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; missile.rotation = Math.atan2 (targetY, targetX) * 180 / Math.PI;
(Ikke sikker på hva Math.atan2 ()
er for? Sjekk ut denne artikkelen om trigonometri.
Hvis du publisere (Ctrl + Enter) dokumentet på dette punktet, bør du få noe slikt:
Flytt musen i nærheten av raketten for å se den rotere.
Vi har rotasjonen, nå trenger vi bevegelsen. Missilet må søke målet, uansett om det er et fast eller et bevegelig mål. Det vi skal gjøre er å beregne bevegelsen i henhold til den nåværende rotasjonen av raketten. La oss sette en verdi for hastigheten, og gjør rakettjakt etter musepekeren.
Vi vil inkludere et par nye variabler for å beregne hastigheten (vx, vy). Når raketten peker mot høyre, er vinkelen lavere enn 90ш og høyere enn -90ш, så den er alltid lavere enn absolutt verdien av 90ш. Når den peker til venstre, har vinkelen sin en absolutt verdi høyere enn 90ш. Dette vil avgjøre vx i samsvar med hastighet, deretter vy vil være forskjellen på hastighet og vx.
privat varhastighet: int = 10; offentlig funksjon Main () addChild (missil); missile.x = 300; missile.y = 200; addEventListener (Event.ENTER_FRAME, playGame); privat funksjon playGame (event: Event): void var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; missile.rotation = Math.atan2 (targetY, targetX) * 180 / Math.PI; // Velocity i x er i forhold til vinkelen, når det er 90ш eller -90ш, skal vx være 0. var vx: Number = speed * (90 - Math.abs (missile.rotation)) / 90; var vy: Nummer; // Velocity i y er forskjellen i hastighet og vx. hvis (missile.rotation < 0) vy = -speed + Math.abs(vx);//Going upwards. else vy = speed - Math.abs(vx);//Going downwards. missile.x += vx; missile.y += vy;
Du får et missil som jager på markøren din.
Du kan bruke en annen hastighet hvis du vil.
Missiler kommer ikke ut av tynn luft, de skyves ut av rakettskyttere. La oss lage en MovieClip som representerer en kanon (jeg skal bruke et enkelt rektangel), og nevne det Kanon. Jeg skal legge til en Kanon eksempel ved kode, så jeg skal holde scenen tom.
Nå, i stedet for å legge til en rakett, skal jeg bare legge til en kanon, og et missil vil bli lagt på kanonens posisjon når jeg klikker på scenen. Vi legger til en boolsk for å sjekke om missilet har blitt skutt, og også en ny funksjon for opptak etter klikk.
importer flash.events.MouseEvent; offentlig klasse Main utvider Sprite private var missil: Missile = new Missile (); privat varhastighet: int = 10; privat var kanon: kanon = ny kanon (); private var missileOut: Boolean = false; // Har raketten blitt skutt? offentlig funksjon Main () addChild (kanon); kanon.x = 50; kanon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); privat funksjon playGame (event: Event): void if (missileOut) var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; missile.rotation = Math.atan2 (targetY, targetX) * 180 / Math.PI; var vx: Nummer = hastighet * (90 - Math.abs (missile.rotation)) / 90; var vy: tall; hvis (missile.rotation < 0) vy = -speed + Math.abs(vx); else vy = speed - Math.abs(vx); missile.x += vx; missile.y += vy; private function shoot(event:MouseEvent):void if (!missileOut) addChild(missile); swapChildren(missile, cannon);//missile will come out from behind cannon missileOut = true; missile.x = cannon.x; missile.y = cannon.y;
Dette er hva du får:
Dette ser ikke bra ut. Vi må enten gjøre kanonen roter også, eller tvinge raketten til å gå oppover rett etter å ha blitt skutt. Siden alternativ nr. 1 er den enkleste tilnærmingen, tar vi alternativ nr. 2.
Hvis kanonen er vertikal, ville vi forvente at raketten skulle starte oppover og deretter komme seg på vei mot målet. Tilnærmingen jeg skal bruke for å oppnå dette er å gi raketten en startvinkel på -90ш (peker oppover), og roter jevnt for å komme på sporet til musemarkøren. Vi legger til en letthet variabel for å bestemme glattheten eller skarpheten av rotasjonen. Da lager vi en annen variabel for å holde oversikt over den faktiske rotasjonen som peker rett mot målet, mens rakettens rotasjon vil endres i henhold til letthet vi setter (letthet = 1 vil oppføre seg som før, noe høyere vil gjøre en jevnere sving).
Siden halvparten av rotasjonsverdiene er negative, må vi i noen tilfeller beregne dem mot 360 for å få den faktiske forskjellen mellom målvinkelen og missilens rotasjon.
privat var lett: int = 10; offentlig funksjon Main () addChild (kanon); kanon.x = 50; kanon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); privat funksjon playGame (event: Event): void if (missileOut) var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; var rotasjon: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; hvis (Math.abs (rotasjon - missil.rotasjon)> 180) hvis (rotasjon> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotasjon < 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; private function shoot(event:MouseEvent):void if (!missileOut) addChild(missile); swapChildren(missile, cannon);//missile will come out from behind cannon missileOut = true; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = -90;//missile will start pointing upwards
Sjekk det ut:
Legg merke til hva som skjer når du beveger musen ut av SWF, og hvordan dette er forskjellig fra forrige eksempel.
Ved siden av Rakett Filmklipp, vi trenger en eksplosjonsanimasjon. I mitt tilfelle lager jeg en egen MovieClip med en enkel tween av en sirkel som utvides. Jeg eksporterer det som Eksplosjon. trykk O for å velge Oval Tool, og hold Skifte mens du tegner den ovale for å få en sirkel.
For en finere visuell effekt, setter jeg sirkelen inn i en annen filmklipp, og gir den en bevel filter for å få en mørkere farge nederst og en lysere farge øverst. Deretter går jeg til ramme 10 og trykker på F6 å lage en keyframe, høyreklikk mellom ramme 1 og 10 og opprett en Classic Tween. Tilbake på ramme 10, trykk Q for å velge Gratis Transform Tool og forstørre sirkelen.
Deretter oppretter du en annen Classic Tween å ramme 20, legger jeg til en Uklarhet filtereffekt.
Endelig, gjør det forsvinner i en siste Classic Tween å ramme 30 med en Alpha fargeffekten går til 0.
Eksplosjonsanimasjonen må fjernes etter at den er ferdig, eller den vil løpe på ubestemt tid. Legg til et nytt lag og trykk F6 på den siste rammen, og trykk deretter på F9 å åpne handlinger panel, og legg til denne koden:
Stoppe();
parent.removeChild (this);
Dette vil gjøre Eksplosjon eksempel fjerner seg selv etter at animasjonen er ferdig.
Nå når rakett møter markøren, erstatter vi den med en Eksplosjon forekomst. Vi trenger bare å legge til en ny betinget i spill()
funksjon.
privat funksjon playGame (event: Event): void if (missileOut) if (missile.hitTestPoint (mouseX, mouseY)) var eksplosjon: Explosion = new Explosion (); addChild (eksplosjon); eksplosjon.x = missil.x; eksplosjon.y = missil.y; removeChild (missil); missileOut = false; else var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; var rotasjon: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; hvis (Math.abs (rotasjon - missil.rotasjon)> 180) hvis (rotasjon> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotasjon < 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;
Ta en titt:
Chasing etter at musemarkøren var underholdende, men det er meningsløst i et spill; Vi må lage et mål. Jeg skal tegne en gruppe sirkler for å danne en Mål Filmklipp.
Nå legger vi til en Mål Eksempel på at missilet har et mer konkret mål. Så erstatter vi noen referanse av musemarkøren for målets posisjon. Også, vi vil ikke teste for et treffpunkt, men et objekt.
privat varemål: Mål = nytt mål (); offentlig funksjon Main () addChild (kanon); kanon.x = 50; kanon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); addChild (target); target.x = 550; target.y = 50; privat funksjon playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var eksplosjon: Explosion = new Explosion (); addChild (eksplosjon); eksplosjon.x = missil.x; eksplosjon.y = missil.y; removeChild (missil); missileOut = false; annet var targetX: int = target.x - missile.x; var targetY: int = target.y - missile.y; var rotasjon: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; hvis (Math.abs (rotasjon - missil.rotasjon)> 180) hvis (rotasjon> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotasjon < 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; private function shoot(event:MouseEvent):void if (!missileOut) addChild(missile); swapChildren(missile, cannon); //missile will come out from behind cannon missileOut = true; missile.x = cannon.x; missile.y = cannon.y; missile.rotation = -90;//missile will start pointing upwards
De hitTestObject ()
Metoden kontrollerer faktisk bare for en overlapping mellom grensekassene til de to objektene (dvs. de blå boksene som vises når du klikker på en forekomst av objektet i scenen), så pass på det; Det er ikke piksel-perfekt kollisjonsdeteksjon. Men det gjør jobben bare bra her.
Du kan prøve å plassere målet på forskjellige steder, så vel som kanonen.
Vi så allerede at missilen vil jage et bevegelig mål, for eksempel musemarkøren, så nå la oss gjøre Mål eksempel flytte litt.
Dette er ikke realistisk fysikk, jeg skal bare få målet til å hoppe lodret. Jeg velger et referansepunkt som bakkenivå, og legger til en tyngdekraftsverdi som påvirker målet. Og for å gjøre det mer dynamisk, øker jeg raketthastigheten til 15.
privat var gulv: int = 385; privat var tyngdekraften: tall = 0,5; private var targetVY: Number = 0; // Nåværende vertikal hastighet for mål-offentlig funksjon Main () addChild (kanon); kanon.x = 50; kanon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); addChild (target); target.x = 550; target.y = 50; privat funksjon playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var eksplosjon: Explosion = new Explosion (); addChild (eksplosjon); eksplosjon.x = missil.x; eksplosjon.y = missil.y; removeChild (missil); missileOut = false; annet var targetX: int = target.x - missile.x; var targetY: int = target.y - missile.y; var rotasjon: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; hvis (Math.abs (rotasjon - missil.rotasjon)> 180) hvis (rotasjon> 0 && missile.rotation < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotasjon < 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 > gulv) target.y = gulv; targetVY = -18;
Hvis du publisere Dette nå, bør du få et bevegelig mål.
Enten du vil ha en nøyaktig homing missil, eller du foretrekker en jevn animasjon, kan du få begge resultatene basert på dette eksemplet. Nå har du et nytt våpen å legge til i arsenalet ditt, kanskje du kan prøve å lage et ormaktig spill, eller til og med bruke algoritmen på noe annet enn et missil, som noen rare mygg som følger karakteren din.
Jeg håper du har funnet denne opplæringen nyttig. Takk for at du leste!