Snelle tip trigonometrie voor ontwikkelaars van Flash-games

Bij het implementeren van een tank in een isometrische oorlogszone, hebt u geleerd hoe u een object laat draaien om de aanwijzer onder ogen te zien en naar een locatie op klik te gaan. In deze Snelle tip gaan we in het algemeen in op de wiskunde erachter: trigonometrie.


Eindresultaat voorbeeld

Dit is het eindresultaat van mijn vorige zelfstudie. Het maakt gebruik van de trigonometrische principes die we in deze snelle tip behandelen:

Beweeg de muis om het torentje erop te richten en klik ergens op om de tank zover te krijgen.

Elke programmeur, in het bijzonder elke spelprogrammeur, staat voor de behoefte om objecten op het scherm vroeg of laat te verplaatsen. Het is een eenvoudige taak als u een object in één richting moet verplaatsen, bijvoorbeeld langs de x- of y-as. Maar stel dat je een object wilt maken, volg de muisaanwijzer op de plaats waar je hem verplaatst, of maak een racegame waarin je de versnelling van een auto regelt door op de pijltoets omhoog te drukken en de pijlen naar links en rechts te gebruiken om te sturen.

Stel dat u eenmaal op de pijl naar rechts drukt en het voegt 10 graden toe aan de rotatie-eigenschappen van uw auto, maar u wilt toch dat de auto vooruit gaat (dwz versnellen) wanneer u op een pijl-omhoog drukt, zelfs als een auto naar de bodem is gedraaid het scherm of een linker- of een rechterkant enz. en je wilt niet dat het eruitziet alsof het zijwaarts verschuift. Hoe zou je dat doen? Dat is waar een beetje trigonometrie helpt!

Voor degenen die goed zijn in wiskunde, zal het geen probleem zijn, maar er zijn veel mensen die het helemaal niet begrijpen of er zelfs bang voor zijn. Ik zal proberen deze zo duidelijk mogelijk op te splitsen in deze Quick Tip.

Stap 1: Het flitscoördinatensysteem

Laten we bij het begin het cartesiaanse coördinatensysteem onthouden. Klinkt dit ingewikkeld? Als dat zo is, kijk dan naar de afbeelding hieronder en ik weet zeker dat het bekend zal zijn:

Het heeft X- en Y-assen; je kunt duidelijk zien waar X en Y positief en negatief zijn. Als het gaat om coördinaten in Flash, is de situatie enigszins anders. Flash heeft ook zijn coördinatenstelsel, maar het lijkt erop dat het Cartesiaanse systeem op zijn kop staat:

Het heeft ook X- en Y-assen en het punt van oorsprong, met als enig verschil dat de Y-as positief is beneden de X-as.

Elk symbool dat in Flash is gemaakt, heeft een eigen ingebouwd coördinatensysteem. Als u een nieuw symbool maakt, of het nu een filmclip of een knop is, ziet u mogelijk een "registratiepunt" -eigenschap in het dialoogvenster voor het maken van symbolen. Wat is het? Het registratiepunt is een punt van oorsprong van een symbool. Het punt dat het object ronddraait als u de rotatie-eigenschap ervan wijzigt.

Notitie: het beginpunt van de stadiuminstantie bevindt zich in de linkerbovenhoek. Dit betekent dat alle punten op het podium positieve X- en Y-coördinaten hebben.

In deze Snelle tip bekijken we de drie meest gebruikte trigonometrische functies in Flash; Sine, Cosine en Atan2. Sommige mensen vragen zich misschien af, hoe kunnen we deze functies gebruiken in Flash? Laten we eens kijken naar enkele praktische voorbeelden en begrijpen waarom we ze nodig hebben en hoe ze ons leven een beetje gemakkelijker kunnen maken.

Stap 2: Hoek berekenen

Laten we de hoek tussen twee punten berekenen. Maak een nieuw Flash-bestand (ActionScript 3.0). Selecteer het eerste frame van de tijdlijn en druk op F9 om een ​​actiescherm te openen.

Laten we op dit punt iets eenvoudigs maken. Typ dit gewoon in het Actions Panel:

 stage.addEventListener (MouseEvent.CLICK, calculateAngle) functie calculateAngle (e: MouseEvent): void trace ("stage X" + e.stageX); trace ("stage Y" + e.stageY)

Dit geeft ons de positie van de muisaanwijzer elke keer dat we op het werkgebied klikken. Niet echt fascinerend, is het?

Ok, stel nu dat je een object van een object de coördinaten van je muiswijzer wilt laten weten ten opzichte van dit object, en laat het dan de richting zien om te reizen om de positie van de aanwijzer te bereiken.

Sluit het Actions Panel en ga naar Insert> New Symbol of druk op Ctrl + F8.

Geef het een willekeurige naam (of laat een standaardnaam achter) en druk op OK. Het kleine dradenkruis in het midden van het scherm is het registratiepunt van het symbool of het punt van oorsprong. Dit zijn de X- en Y-posities van het object. Pak nu het Oval-gereedschap (O-toets) en teken een cirkel (met ingedrukte Shift-toets) overal op het scherm.

Klik op de cirkel om deze te selecteren en ga naar het paneel Eigenschappen> Positie en grootte. Voor W (breedte) type in 20, hetzelfde voor H (hoogte) en voor X- en Y-positietype in (-10). Dit maakt de cirkel 20x20 px en centreert het precies naar het registratiepunt. Verlaat nu de symboolbewerkingsmodus (klik hierboven op Scene 1), pak dit symbool in je bibliotheek en sleep het eenvoudig naar het werkvlak (waar dan ook, het krijgt later dynamisch een positie). Zodra je object op het podium staat, geef je het een instantienaam van mCircle.

Nu willen we de richting berekenen van de Y- en X-positie van onze cirkel naar de Y- en X-positie van de muisaanwijzer. De rode lijn in de afbeelding hieronder is de richting die we moeten kennen. Het kan worden gevonden door een standaard te gebruiken Math.atan2 () functie.

Laten we het nu doen. Verwijder de "trace" -instructies uit de code en maak in plaats hiervan een nieuwe variabele. Vervolgens traceer je deze variabele om te zien wat je krijgt:

 stage.addEventListener (MouseEvent.CLICK, calculateAngle); var myAtan2: Number; function calculateAngle (e: MouseEvent): void myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x); trace (myAtan2); 

Let daar op e.stageY - mCircle.y is de verticaal afstand van de muis tot de cirkel, en e.stageX - mCircle.x is de horizontale afstand.

U krijgt dit soort cijfers in het uitvoerpaneel:

 -2.419017353128333 3.0118660246925346 2.5704959452340326 1.6726588917423932 1.0238847495551058 0.21368467849101092

Dit zijn de relatieve hoeken (tussen de X-aslijn en de rode lijn) in radialen. Waarom geen graden? Welnu, Flash gebruikt radialen om sinus en cosinus te berekenen, maar als je wilt weten wat deze hoeken in graden zijn, kun je "myAtan2" altijd vermenigvuldigen met 180 en delen door Math.PI. Zoals dit:

 trace (myAtan2 * 180 / Math.PI) // geeft je de hoek in graden;

Editor: Als extra hulpmiddel is hier een groot aantal functies voor graden / radialen conversie. Het is opgeslagen als een fragment op snipplr.com, het nieuwste lid van Envato's netwerk!

Stap 3: Sine en Cosine begrijpen

Omdat we de hoek tussen twee punten kennen, kunnen we nu berekenen hoeveel pixels we aan de X- en Y-eigenschappen van de cirkel moeten toevoegen, totdat het het klikpunt bereikt. Laten we eens kijken wat we hier moeten weten:

De blauwe lijn is de Cosinus van de hoek en de oranje is de Sinus van de hoek. Met andere woorden,

  • Sinus (hoek) == e.stageY - mCircle.y
  • Cosinus (hoek) == e.stageX - mCircle.x

In plaats van uit te leggen hoe sinus en cosinus werk, ik zal laten zien hoe ze te gebruiken met een aantal praktische voorbeelden. Botweg zijn de sinus en cosinus de relaties tussen Y en X in onze invalshoek.

Stel je voor dat de hoek tussen twee objecten 45 graden is. In dit geval is de relatie tussen sinus en cosinus 1: 1 (zie de afbeelding hieronder), wat betekent dat we de X- en Y-eigenschappen van onze cirkel met elk frame moeten verhogen om de bestemming te bereiken. Je moet bijvoorbeeld elk beeld 5 pixels toevoegen aan X en 5 pixels aan Y.

In dit diagram is de hoek veranderd en is de relatie tussen sinus en cosinus ook veranderd. Het is nu ongeveer 1: 2.

In dit geval moeten we tweemaal zoveel pixels toevoegen aan de X-eigenschap van onze cirkel dan aan Y. Afb. X + = 10, Y + = 5;

Stap 4: Praktische voorbeelden

Je zult je waarschijnlijk afvragen waarom we sinus en cosinus nodig hebben als we de coördinaten van het klikpunt al kennen - we kunnen gewoon onze mCircle voor hen meteen? Nou, je zou het op deze manier kunnen doen als je wilde dat je cirkel (of een ander object) op een klikpuntcoördinaten teleporteerde zodra er een klik plaatsvond. Maar wat als u wilt dat het geleidelijk in de richting van de klik beweegt? Hiervoor moet u een bepaald aantal pixels toevoegen aan de X- en Y-eigenschappen, bijvoorbeeld elk frame of elke seconde.

Laten we nu berekenen hoeveel pixels we moeten toevoegen aan de X- en Y-eigenschappen op basis van sinus en cosinus van de hoek tussen ons object en een klikpunt. Onthoud dat Flash de hoek tussen deze operaties kent vanuit deze bewerking:

 myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x);

Voor dit doel moeten we onze code een beetje bijwerken.

 stage.addEventListener (MouseEvent.CLICK, calculateAngle); // 2 is het maximale aantal pixels dat aan elk object moet worden toegevoegd aan de objecten X- en Y-eigenschappen // u kunt elk gewenst getal gebruiken var moveAmount: Number = 2; var myAtan2: Number; var mouseClickX: Number; var mouseClickY: Number; function calculateAngle (e: MouseEvent): void mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x); addEventListener (Event.ENTER_FRAME, moveTheCircle);  functie moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount; 

Merk op wat ik hier heb gedaan: ik promootte al mijn variabelen buiten alle functies, omdat ik nu meer dan één functie heb en ik wil dat deze variabelen toegankelijk zijn vanuit elke functie.

 var moveAmount: Number = 2; var myAtan2: Number; var mouseClickX: Number; var mouseClickY: Number;

De fase heeft een gebeurtenislistener voor muisklikken, dus wanneer de klik plaatsvindt, de methode calculateAngle () wordt aangeroepen en de volgende variabelen worden geïnstantieerd:

 mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x);

Deze functie voegt ook een gebeurtenislistener toe voor het invoeren van frame naar de stage, die de moveTheCircle () methode elk frame.

 addEventListener (Event.ENTER_FRAME, moveTheCircle);

Stap 5: Pixels berekenen

Laten we nu onze moveTheCircle () methode zelf. Voor nu doet het slechts twee dingen:

 mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount;

Zoals u kunt zien, berekent de eerste regel hoeveel pixels het moet toevoegen aan de X-eigenschap en de tweede lijn gaat over Y. Laat het me uitleggen. Math.cos vindt de cosinus (x-eigenschap) van de "myAtan2" -hoek, Math.sin doet hetzelfde met zijn sine (y-eigenschap). Als onze myAtan2-hoek gelijk is aan ongeveer 0,785 radialen (45 graden), zijn de cosinus en sinus beide gelijk aan ongeveer 0,707 ... U kunt een rekenmachine gebruiken om deze uit te checken.

Een eenvoudige berekening toont hoeveel pixels de bovenstaande code zal toevoegen aan de X- en Y-eigenschappen van ons object als de hoek 45 graden is.

 Cosinus (45 graden) = 0,707 * 2 = 1,414; Sinus (45 graden) = 0,707 * 2 = 1,414; dus de code zal deze resultaten berekenen: mCircle.x + = 1.414 pixels; mCircle.y + = 1.414 pixels;

Als de hoek bijvoorbeeld is. 60 graden dan zouden de resultaten als volgt zijn:

 Cosinus (60 graden) = 0,5 * 2 = 1; Sinus (60 graden) = 0,866 * 2 = 1,732; En de code zou op deze manier werken: mCircle.x + = 1 pixel; mCircle.y + = 1.732 pixels;

Stap 6: Een probleem oplossen met de code

Wel, we zijn bijna klaar. Maar er is nog steeds een klein probleempje met onze code. U hebt misschien gemerkt dat ons object nooit stopt, zelfs als het het klikpunt bereikt, blijft het altijd in beweging. We kunnen dit probleem heel gemakkelijk oplossen. Terwijl ons object naar het klikpunt toe beweegt, wordt de afstand daartussen zo korter absoluut waarde van de afstand neemt ook af. We kunnen het zo volgen:

 trace (Math.abs (mCircle.x - mouseClickX)); trace (Math.abs (mCircle.y - mouseClickY));

(Math.abs () verandert negatieve getallen in positieve door ze simpelweg te vermenigvuldigen met -1. Het doet niets met getallen die al positief zijn.)

U hoeft deze traceerinstructie niet toe te voegen aan uw code, ik heb hem hier geplaatst om u de manier te tonen waarop u de absolute waarde kunt zien. In dit geval zijn beide absolute waarden minder dan 3 als het object het klikpunt bereikt. Dus wat we nu nodig hebben, is er een toevoegen als verklaring binnen ons moveTheCircle () functie.

 functie moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount; // Controleer of de horizontale en verticale afstanden van de cirkel tot het muispunt erg dichtbij zijn (Math.abs (mCircle.x - mouseClickX) < 3 && Math.abs(mCircle.y - mouseClickY) < 3)  removeEventListener(Event.ENTER_FRAME, moveTheCircle);  

Wanneer de absolute waarde onder de 3 komt, wordt de enterframe-luisteraar verwijderd. We moeten zowel de absolute als de absolute waarden van X en Y controleren, omdat een ervan 3 zou kunnen bereiken, zelfs wanneer de tweede dat niet is. Dit betekent dat de objecten op deze manier kunnen stoppen:

De bovenstaande afbeelding toont de versie waarin alleen de absolute waarde van X is gecontroleerd. De absolute waarde van de X-afstand is al minder dan 3 en dus is er geen aandacht meer voor de Y-waarde.


Conclusie

Nou, dat is het dan. Ik hoop dat deze Snelle tip je helpt trigonometrie te begrijpen die wordt gebruikt in de ontwikkeling van Flash :)