Het afbeelden van animaties in termen van vectoren is intuïtief, maar begrip van vectorwiskunde is lastig. In deze tutorial hoop ik die pijn te verzachten en een oplossing te bieden voor animatieproblemen met behulp van een aangepaste geschreven Vector2D-klasse. We zullen kijken naar enkele fundamentele concepten van lineaire kinematica in de Euleriaanse benadering: verplaatsing, snelheid en versnelling. Vervolgens bouwen we er een eenvoudige applicatie mee.
Laten we eens kijken naar het uiteindelijke resultaat waar we naartoe zullen werken. Klik hieronder op het Flash-paneel en bedien de pijlpunt door op de vier richtingstoetsen te drukken.
Alle vectorgrootheden hebben twee componenten: grootte en richting.
Een verandering in vectorhoeveelheden verwijst naar een van deze gevallen:
Verplaatsing, snelheid en versnelling zijn vectorgrootheden. Hun definities zijn als volgt:
De onderstaande animatie toont verplaatsing zoals we later in Flash gaan implementeren.
Velocity wordt geïllustreerd door de onderstaande animatie. Notitiesnelheid is constant, wat betekent dat versnelling ontbreekt in dit scenario. Als de snelheid nul is, blijft de verplaatsing constant constant.
Versnelling wordt geïllustreerd door de onderstaande animatie. Opmerking: kinematica houdt in constante versnelling. Als de versnelling in de loop van de tijd verandert, valt deze onder het onderwerp dynamica. Dynamica is de studie van krachten die de oorzaak zijn van versnelling in de loop van de tijd. Eén zo'n kracht is zwaartekracht en ik heb een bericht geschreven over het animeren ervan.
Nu u een korte kennis hebt gekregen van de lineaire kinematica-grootheden en in staat bent om ze te relateren aan vectoren, kunnen we beginnen met het bouwen van onze Projectile-klasse. We zouden graag zien dat het projectiel al deze grootheden kan vastleggen: verplaatsing, snelheid en versnelling - zodat het op elk frame kan worden gemanipuleerd.
Hieronder staan de gegevens die we zullen opnemen in onze Projectile-klasse:
private var displace: Vector2D; private var velo: Vector2D; privé var acc: Vector2D;
Na het starten van deze Projectile-klasse zullen we de genoemde variabelen initialiseren en de grafische weergave ervan tekenen.
public function Projectile () // teken afbeeldingen this.draw (); // begin alle vectorgrootheden verdraaien = nieuwe Vector2D (this.x, this.y); velo = new Vector2D (0, 0); acc = nieuwe Vector2D (0, 0); beschermde functie draw (): void // tekening de pijlpunt var hoogte: Number = 30; var width: Number = 60; graphics.beginFill (0x0000FF); graphics.moveTo (0, 0); graphics.lineTo (breedte / -3, hoogte / -2); graphics.lineTo (width / 2, 0); graphics.lineTo (breedte / -3, hoogte / 2); graphics.lineTo (0, 0); graphics.endFill ();
De volgende zijn accessors van onze privévariabelen - verplaatsen
, velo
, acc
- in de klasse Projectile.
public function setDisp (mag: Number, angle: Number): void displace.redefine (mag, angle); openbare functie getDisp (): Vector2D return displace; openbare functie setVelo (mag: Number, angle: Number): void velo.redefine (mag, angle); openbare functie getVelo (): Vector2D return velo; public function setAcc (mag: Number, angle: Number): void acc.redefine (mag, angle); openbare functie getAcc (): Vector2D return acc
Na het vernieuwen van elk frame, moeten we de snelheid bijwerken (met behulp van versnelling) en de verplaatsing bijwerken (met behulp van de genoemde snelheid). Dit kan worden bereikt met behulp van de volgende functies. Voor een uitgebreide uitleg over Vector-toevoeging, ga naar deze geweldige post van Daniel Sidhon.
openbare functie applyVelo (): void this.displace = this.displace.add (velo); openbare functie applyAcc (): void this.velo = this.velo.add (acc); // update de positie van de sprite door verplaatsing. public function animate (): void this.x = this.displace.x; this.y = this.displace.y;
We zullen ook de oriëntatie van de Sprite moeten bijwerken. Dit kan worden bereikt via de omwenteling
eigendom van Sprite.
public function orient (): void this.rotation = Math2.degreeOf (velo.getAngle ());
Ik heb ook een Math2
statische klasse, waarin ik een functie heb geschreven om gemakkelijk heen en weer te converteren van de eenheden graden en radialen van de hoek.
public static function radianOf (deg: Number): Number return deg / 180 * Math.PI; public static function degreeOf (rad: Number): Number return rad / Math.PI * 180;
Nu we onze Projectile- en Math2-klasse hebben opgezet, kunnen we beginnen met het coderen van onze hoofdklasse. We hebben ook een Vector2D-klasse nodig, hoewel een grondige uitleg niet is opgenomen vanwege het eerder genoemde artikel over Vectors van Daniel Sidhon. Ik veronderstel dat lezers de Vector2D-klasse begrijpen na het te hebben gelezen. Als er echter verduidelijkingen nodig zijn, stel me dan snel uw vragen.
Allereerst moeten we privévariabelen van deze klasse kennen.
privé var b1: Projectiel; // keypress flags privé-UP: Boolean = false; privé var DOWN: Boolean = false; private var LEFT: Boolean = false; private var RIGHT: Boolean = false;
Bij initialisatie van Main, functie in het
zal gelanceerd worden. Deze functie maakt een nieuw projectiel en stelt de beginsnelheid in. Vervolgens zullen luisteraars aan evenementen worden toegewezen.
private function init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // startpunt b1 = nieuw Projectiel (); stage.addChild (b1); // instellen van de beginsnelheid b1.setVelo (5, Math2.radianOf (30)); // instellen van gebeurtenislisteners b1.addEventListener (Event.ENTER_FRAME, proj_enterFrame); stage.addEventListener (KeyboardEvent.KEY_DOWN, handle_keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, handle_keyUp);
Ik heb gebruikersbesturing gedefinieerd als toetsaanslagen van de pijltoetsen Omhoog, Links, Omlaag en Links. Na het indrukken en loslaten van die toetsen worden vlagvariabelen van Main (stap 11) waar en onwaar gemaakt. Op basis van deze vlaggen worden de vectorgrootheden op elk frame gemanipuleerd. Merk ook op dat ik de besturing heb verdeeld in horizontale en verticale as-manipulators.
private function handle_keyDown (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) UP = true; else if (e.keyCode == Keyboard.DOWN) DOWN = true; if (e.keyCode == Keyboard.LEFT) LEFT = true; else if (e.keyCode == Keyboard.RIGHT) RIGHT = true; private function handle_keyUp (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) UP = false; else if (e.keyCode == Keyboard.DOWN) DOWN = false; if (e.keyCode == Keyboard.LEFT) LEFT = false; else if (e.keyCode == Keyboard.RIGHT) RIGHT = false;
Na verversing van elk frame zal de volgende code worden uitgevoerd. Het is lang, maar maak je geen zorgen; lees gewoon verder.
private function proj_enterFrame (e: Event): void // define acceleration var accMag: Number = 0.1; if (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc (); else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc (); if (LEFT) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc (); else if (RIGHT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc (); // vertragen als er niets wordt ingedrukt om wrijving te simuleren. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc (); b1.applyVelo (); // sprite beperken tot randen van de fase b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient ();
Het bijwerken van de beweging moet in de volgende volgorde plaatsvinden:
Ik heb de codes gemarkeerd voor eenvoudige identificatie van deze stappen.
private function proj_enterFrame (e: Event): void // define acceleration var accMag: Number = 0.1; if (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc (); else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc (); if (LEFT) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc (); else if (RIGHT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc (); // vertragen als er niets wordt ingedrukt om wrijving te simuleren. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc (); b1.applyVelo (); // sprite beperken tot randen van de fase b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient ();
Mogelijk vindt u tussen deze oplichtende codes nog andere functies. Wat zijn ze? Een daarvan is om een andere vector toe te passen om ons projectiel te vertragen als de gebruiker niet op toetsen drukt. Dit wordt toegepast voordat we snelheid toevoegen aan onze verplaatsing.
// vertragen als er niets wordt ingedrukt om wrijving te simuleren. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc ();
De volgende is om ons projectiel te beperken om altijd op het podium te blijven, anders vliegt het uit het scherm. Nog een keer, implementBound
is een functie die ik heb opgenomen in de statische klasse Math2. Gegeven een bovengrens, ondergrens en een willekeurige waarde, implementBound
retourneert een waarde die binnen de grenzen valt.
Nadat we deze beperkingen op onze verplaatsing hebben toegepast (en pas daarna), werken we de positie van de Sprite bij met deze verplaatsingswaarde.
// sprite beperken tot randen van de fase b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y);
Voordat we deze sprite verlaten zoals hij is, moeten we hem zodanig oriënteren dat hij altijd in de positie wijst die hij met de functie gebruikt oriënteren
.
Nu is alles klaar. Terwijl je dit stuk start door op Ctrl + Enter te drukken, zie je een pijl die geleidelijk langzamer gaat als hij diagonaal over het scherm loopt. Druk op de vier richtingsknoppen om de pijl te verplaatsen. Maak je geen zorgen over het verliezen van je pijl; het blijft in je blik.
Dit artikel moet je vertrouwd maken met het gebruik van vectoren om beweging te animeren. Als je eenmaal de kinematica hebt begrepen, ga je verder met het lezen van mijn bericht over de dynamiek. Laat me weten hoe het gaat. Terima Kasih.