Deze tutorial zal gids jij door het toevoegen van dodelijk nauwkeurige homing raketten aan het arsenaal van je volgende spel.
Laten we eens kijken naar het eindresultaat waar we naartoe zullen werken:
Maak een nieuwe Flash-documentenset voor ActionScript 3.0. Ik gebruik de dimensies van 600x400 en een framesnelheid van 30 FPS. Sla het bestand op met een naam naar keuze.
Naast de FLA moeten we ook een documentklasse maken. Maak een nieuw Actionscript-bestand en voeg deze code toe:
pakket import flash.display.Sprite; public class Hoofd breidt uit openbare functie Main ()
Bewaar dit bestand in dezelfde map als onze FLA. Geef het een naamMain.as.
Om de code te compileren van de Hoofd klasse, we moeten het koppelen aan de FLA. Over theяeigenschappen paneel van de FLA, naastKlasse, voer de naam van de documentklasse in, in dit geval, Hoofd.
Sla vervolgens de wijzigingen op de FLA op.
We hebben een raketafbeelding nodig om tijdens het fotograferen te laten zien. U kunt hier in Flash een bitmap importeren of een vorm tekenen. Ik zal een kleine vorm gebruiken in dit voorbeeld.
Wat hier van belang is, is dat je het raketpunt recht naar rechts moet richten, omdat dat het beginpunt voor de rotatie is. Dus 0 betekent recht naar rechts wijzen, -90ø betekent naar boven, 90ø betekent naar beneden en 180 duizend naar links. Later zullen we de raket moeten draaien in overeenstemming met zijn richting.
Zodra je de raketafbeelding hebt, selecteer je deze en druk je op F8 om een filmclip te maken. Noem het "Missile", zorg ervoor dat de Registratiepunt staat in het midden en vink het selectievakje "Exporteren voor ActionScript" aan.
Je zult eindigen met een Missile MovieClip in de bibliotheek.
Als u een Missile-instantie in het werkgebied hebt, verwijdert u deze. We zullen de Missile MovieClip per code toevoegen.
Het eerste dat een geleide raket moet weten, is waar het doelwit zich bevindt. We gaan eerst de rotatie van de raket instellen op basis van de positie van de muiscursor. Laten we werken met de enterFrame Gebeurtenis voor een constante rotatie-update.
Voeg een ... toe Raket bijvoorbeeld op het podium, plaats ik het in het midden (300, 200). Bereken vervolgens de afstand van de raket tot de muiscursor (ik bewaar deze in variabelen TargetX en targetY). Ten slotte is de hoek van de raket de boog tangens van beide punten (TargetX, targetY). Het resultaat dat u krijgt, staat in radialen, maar de rotatie werkt in graden, dus u moet de conversie uitvoeren door te vermenigvuldigen met 180 / Pi. (Zie dit artikel voor meer informatie.)
import flash.events.Event; public class Main breidt Sprite uit private var-raket: Missile = new Missile (); public function Main () addChild (raket); raket.x = 300; raket.y = 200; addEventListener (Event.ENTER_FRAME, playGame); private function 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;
(Niet zeker wat Math.atan2 ()
is voor? Bekijk dit artikel over trigonometrie.
als jij Publiceren (Ctrl + Enter) het document op dit punt, zou je zoiets als dit moeten krijgen:
Beweeg je muis in de buurt van de raket om hem te zien draaien.
We hebben de rotatie, nu hebben we de beweging nodig. De raket moet het doelwit zoeken, ongeacht of het een vast of een bewegend doelwit is. Wat we zullen doen is de beweging berekenen volgens de huidige rotatie van de raket. Laten we een waarde voor de snelheid instellen en de raket laten jagen na de muiscursor.
We zullen een aantal nieuwe variabelen toevoegen om de snelheid te berekenen (vx, vy). Wanneer de raket naar rechts wijst, is de hoek kleiner dan 90 km en hoger dan -90 km, dus deze is altijd lager dan de absolute waarde van 90 | Als het naar links wijst, heeft zijn hoek een absolute waarde hoger dan 90 km. Dit zal bepalen vx in overeenstemming met snelheid, dan vy zal het verschil zijn van snelheid en vx.
privé var snelheid: int = 10; public function Main () addChild (raket); raket.x = 300; raket.y = 200; addEventListener (Event.ENTER_FRAME, playGame); private function 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 in x is relatief ten opzichte van de hoek, wanneer deze 90 × of 90 is, moet vx 0 zijn. Var vx: Number = speed * (90 - Math.abs (raket.rotatie)) / 90; var vy: Number; // Velocity in y is het verschil in snelheid en vx. als (raket.rotatie < 0) vy = -speed + Math.abs(vx);//Going upwards. else vy = speed - Math.abs(vx);//Going downwards. missile.x += vx; missile.y += vy;
Je krijgt een raket achter je aan.
Je kunt een andere snelheid gebruiken als je wilt.
Raketten komen niet uit de lucht vallen, ze worden uit raketwerpers afgeschoten. Laten we een MovieClip maken die een kanon voorstelt (ik gebruik een eenvoudige rechthoek), en noem die Kanon. Ik ga een toevoegen Kanon bijvoorbeeld door code, dus ik ga het podium leeg houden.
Nu, in plaats van een raket toe te voegen, ga ik gewoon een kanon toevoegen en een raket zal worden toegevoegd op de positie van het kanon wanneer ik op het podium klik. We zullen een Boolean toevoegen om te controleren of de raket is neergeschoten en ook een nieuwe functie voor het maken van opnamen na de klik.
import flash.events.MouseEvent; public class Main breidt Sprite uit private var-raket: Missile = new Missile (); privé var snelheid: int = 10; privé var-kanon: kanon = nieuw kanon (); private var missileOut: Boolean = false; // Is de raket neergeschoten? public function Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, schieten); private function 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: Number = speed * (90 - Math.abs (raket.rotatie)) / 90; var vy: Number; als (raket.rotatie < 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;
Dit is wat je krijgt:
Dit ziet er niet goed uit. We moeten het kanon ook laten draaien, of de raket dwingen naar boven te gaan nadat hij is neergeschoten. Omdat optie # 1 de gemakkelijkste benadering is, nemen we optie # 2.
Als het kanon verticaal is, zouden we verwachten dat de raket omhoog schiet en dan op het juiste spoor komt richting zijn doelwit. De aanpak die ik zal gebruiken om dit te bereiken is om de raket een starthoek van -90ø (naar boven gericht) te geven en vloeiend te laten draaien om de muiscursor op het goede spoor te krijgen. We voegen een toe gemak variabele om de zachtheid of scherpte van de rotatie te bepalen. Vervolgens maken we een andere variabele om de werkelijke rotatie die recht naar het doel wijst te volgen, terwijl de rotatie van de raket zal veranderen volgens de gemak we zetten (gemak = 1 gedraagt zich net als voorheen, alles wat hoger is, maakt een vloeiendere beurt).
Omdat de helft van de rotatiewaarden negatief zijn, moeten we ze in sommige gevallen uitrekenen tegen 360 om het werkelijke verschil tussen de richthoek en de rotatie van de raket te krijgen.
privé var gemak: int = 10; public function Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, schieten); private function playGame (event: Event): void if (missileOut) var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; var rotatie: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (rotation - raket.rotatie)> 180) if (rotatie> 0 && raket.rotatie < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotatie < 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
Bekijken:
Let op wat er gebeurt als u uw muis uit de SWF verplaatst en hoe dit verschilt van het vorige voorbeeld.
naast de Raket Filmclip, we hebben een explosie-animatie nodig. In mijn geval maak ik een afzonderlijke MovieClip met een eenvoudige tween van een cirkel die groter wordt. Ik exporteer het als Explosie. druk op O om de te selecteren Oval Tool, en hou vast Verschuiving terwijl je het ovaal tekent om een cirkel te krijgen.
Voor een mooier visueel effect, zal ik de cirkel in een andere Movie Clip van zijn eigen plaatsen, en geef het een schuin filter om een donkerdere kleur aan de onderkant en een lichtere kleur aan de bovenkant te krijgen. Vervolgens ga ik naar frame 10 en druk op F6 om een te maken keyframe, klik vervolgens met de rechtermuisknop tussen frame 1 en 10 en maak een Klassieke Tween. Terug op frame 10, druk op Q om de te selecteren Gratis transformatie tool en vergroot de cirkel.
Maak vervolgens een nieuwe Klassieke Tween om frame 20 in te voegen, zal ik een toevoegen vervagen filter effect.
Laat het ten slotte in een laatste Classic Tween verdwijnen naar frame 30 met een Alpha kleureffect gaat naar 0.
De explosie-animatie moet worden verwijderd nadat deze is voltooid, anders loopt deze oneindig door. Voeg een nieuwe laag toe en druk op F6 op het laatste frame en druk vervolgens op F9 om de te openen acties paneel en voeg deze code toe:
hou op();
parent.removeChild (deze);
Dit zal het maken Explosie bijvoorbeeld zichzelf verwijderen nadat de animatie is voltooid.
Nu wanneer het raket ontmoet de cursor, we zullen hem vervangen door een Explosie aanleg. We hoeven alleen maar een nieuwe voorwaarde toe te voegen in de spel spelen()
functie.
private function playGame (event: Event): void if (missileOut) if (missile.hitTestPoint (mouseX, mouseY)) var explosion: Explosion = new Explosion (); addChild (explosie); explosion.x = raket.x; explosion.y = missile.y; removeChild (raket); missileOut = false; else var targetX: int = mouseX - missile.x; var targetY: int = mouseY - missile.y; var rotatie: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (rotation - raket.rotatie)> 180) if (rotatie> 0 && raket.rotatie < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotatie < 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;
Kijk eens:
De muiscursor achtervolgen was leuk, maar het is zinloos in een spel; we moeten een doelwit maken. Ik ga een aantal cirkels tekenen om een te vormen Doelwit Filmclip.
Nu voegen we een toe Doelwit bijvoorbeeld om de raket een meer tastbaar doel te geven. Dus we zullen elke verwijzing van de muiscursor naar de positie van het doelwit vervangen. We zullen ook niet testen op een hitpoint, maar op een object.
privé var-doel: doel = nieuw doel (); public function Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); addChild (doel); target.x = 550; target.y = 50; private function playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var explosion: Explosion = new Explosion (); addChild (explosie); explosion.x = raket.x; explosion.y = missile.y; removeChild (raket); missileOut = false; else var targetX: int = target.x - missile.x; var targetY: int = target.y - missile.y; var rotatie: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (rotation - raket.rotatie)> 180) if (rotatie> 0 && raket.rotatie < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotatie < 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 ()
methode controleert eigenlijk alleen op een overlapping tussen de selectiekaders van de twee objecten (d.w.z. de blauwe vakken die verschijnen wanneer u op een exemplaar van het object in de fase klikt), dus pas op voor dat; het is geen pixel-perfecte botsingsdetectie. Het doet het werk echter prima hier.
U kunt proberen het doelwit op verschillende locaties te plaatsen, evenals het kanon.
We hebben al gezien dat de raket een bewegend doelwit zal achtervolgen, zoals de muisaanwijzer, dus laten we nu de Doelwit bijvoorbeeld verplaats een beetje.
Dit is geen realistische fysica, ik ga het doel verticaal laten stuiteren. Ik kies een referentiepunt als grondniveau en voeg een zwaartekrachtwaarde toe om het doel te beïnvloeden. En om het dynamischer te maken, zal ik de raketsnelheid verhogen naar 15.
privé var verdieping: int = 385; private var gravity: Number = 0.5; private var targetVY: Number = 0; // Huidige verticale snelheid van de openbare doelfunctie Main () addChild (cannon); cannon.x = 50; cannon.y = 380; addEventListener (Event.ENTER_FRAME, playGame); stage.addEventListener (MouseEvent.CLICK, shoot); addChild (doel); target.x = 550; target.y = 50; private function playGame (event: Event): void if (missileOut) if (missile.hitTestObject (target)) var explosion: Explosion = new Explosion (); addChild (explosie); explosion.x = raket.x; explosion.y = missile.y; removeChild (raket); missileOut = false; else var targetX: int = target.x - missile.x; var targetY: int = target.y - missile.y; var rotatie: int = Math.atan2 (targetY, targetX) * 180 / Math.PI; if (Math.abs (rotation - raket.rotatie)> 180) if (rotatie> 0 && raket.rotatie < 0) missile.rotation -= (360 - rotation + missile.rotation) / ease; else if (missile.rotation > 0 && rotatie < 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 > vloer) target.y = verdieping; targetVY = -18;
als jij Publiceren dit nu, je zou een bewegend doelwit moeten krijgen.
Of u nu een nauwkeurige homing-raket wilt, of liever een vloeiende animatie, u kunt beide resultaten krijgen op basis van dit voorbeeld. Nu heb je een nieuw wapen om toe te voegen aan je arsenaal, misschien kun je proberen een Worms-achtig spel te maken, of zelfs het algoritme gebruiken op iets anders dan een raket, zoals een rare mug die je personage volgt.
Ik hoop dat je deze tutorial nuttig hebt gevonden. Bedankt voor het lezen!