Meer informatie over lineaire Kinematica

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.


Eindresultaat voorbeeld

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.


Stap 1: Vectorhoeveelheid

Alle vectorgrootheden hebben twee componenten: grootte en richting.


Stap 2: Verandering in Vectorhoeveelheid

Een verandering in vectorhoeveelheden verwijst naar een van deze gevallen:

  1. Verandering van richting
  2. Verandering in grootte
  3. Verandering in zowel grootte als richting

Stap 3: verplaatsing als een vectorhoeveelheid

Verplaatsing, snelheid en versnelling zijn vectorgrootheden. Hun definities zijn als volgt:

  • Verplaatsing - Vector van het kortste pad dat van oorsprong naar bestemming wijst. Ik definieer oorsprong als punt (0, 0) en bestemming als de locatie van het deeltje ten opzichte van dit punt. Kort gezegd verwijst het naar het Cartesiaanse coördinatenstelsel zoals geïmplementeerd door Flash.
  • Velocity - Velocity is de verandering van verplaatsing in de loop van de tijd.
  • Acceleratie - Acceleratie is de verandering van snelheid in de loop van de tijd.

De onderstaande animatie toont verplaatsing zoals we later in Flash gaan implementeren.


Stap 4: Snelheid als een vectorhoeveelheid

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.


Stap 5: Versnelling als een Vector Hoeveelheid

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.


Stap 6: begin met het bouwen van een projectiel

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;

Stap 7: Projectiel initialiseren

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 (); 

Stap 8: Accessors van Vectorhoeveelheden

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

Stap 9: Updaters van Vectorhoeveelheden

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; 

Stap 10: Updater voor de oriëntatie van Sprite

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; 

Stap 11: De hoofdklasse

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;

Stap 12: Main initialiseren

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); 

Stap 13: Toetsenbord Event-luisteraars

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; 

Stap 14: EnterFrame Event-luisteraars

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 (); 

Stap 15: Motion bijwerken

Het bijwerken van de beweging moet in de volgende volgorde plaatsvinden:

  1. Definieer een nieuwe versnelling volgens de toetsaanslag van de gebruiker.
  2. Gebruik de versnelling om de huidige snelheid bij te werken.
  3. Gebruik de huidige snelheid om de huidige verplaatsing bij te werken.
  4. Verfijn verplaatsing om het object binnen de grenzen te houden.

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 (); 

Stap 16: Beweging vertragen

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 (); 

Stap 17: Blijf binnen

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);

Stap 18: Orient Sprite

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.


Stap 19: Verkrijg Set and Go!

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.


Conclusie

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.