När du distribuerar en tank i en isometrisk krigszon lärde du dig hur man gör ett objekt rotera för att möta pekaren och flytta mot en plats på klicka. I denna Snabba Tips tar vi en allmän titt på matematiken bakom den: trigonometri.
Detta är det slutliga resultatet från min tidigare handledning. Den använder sig av de trigonometriska principerna som vi kommer att täcka i denna Snabba Tips:
Flytta musen för att få tornet att sikta på det och klicka någonstans för att få tanken att köra till den punkten.
Varje programmerare, speciellt vilken spelprogrammerare som helst, står inför ett behov av att flytta objekt på skärmen förr eller senare. Det är en enkel uppgift om du behöver flytta ett objekt i en riktning, till exempel längs x- eller y-axeln. Men antar att du vill göra ett objekt med muspekaren var du än flyttar den eller skapa ett tävlingsspel där du kontrollerar en bils acceleration genom att trycka upp pilknappen och använda vänster och högerpil för att styra.
Låt oss säga att du trycker på den högra pilknappen en gång och den lägger till 10 grader i din bils rotationsegenskap men du vill fortfarande att bilen ska gå framåt (dvs. accelerera) när du trycker på en pil uppåt, även om en bil vrids mot botten av skärmen eller en vänster eller höger sida etc. och du vill inte att den ska se ut som den glider åt sidan. Så hur skulle du göra det? Det är där en liten trigonometri hjälper!
För dem som är bra i matematiken kommer det inte att vara ett problem, men det finns många människor som inte förstår det alls eller är ens rädda för det. Jag ska försöka bryta ner det så klart som möjligt i den här snabba tipsen.
Låt oss komma ihåg det kartesiska koordinatsystemet. Ljud komplicerat? Om så är fallet, titta bara på bilden nedan och jag är säker på att det kommer att bli bekant:
Den har X- och Y-axlar; du kan tydligt se var X och Y är positiva och negativa. När det gäller koordinater i Flash är situationen lite annorlunda. Flash har också sitt koordinatsystem men det ser ut som det kartesiska systemet upp och ner:
Det har också X- och Y-axlar och ursprungspunkten, den enda skillnaden är att Y-axeln är positiv Nedan X-axeln.
En symbol som skapats i Flash har ett eget inbyggt koordinatsystem. Om du skapar en ny symbol, oavsett om det är ett filmklipp eller en knapp, kan du kanske se en "registreringspunkt" -egenskap i dialogrutan för att skapa symbol. Vad är det? Registreringspunkten är en ursprungspunkt för en symbol. Poängen att objektet roterar runt om du ändrar rotationsegenskapen.
Notera: Ursprungspunkten för scenförekomsten är i sitt vänstra övre hörn. Det betyder att alla punkter på scenen har positiva X- och Y-koordinater.
I denna Snabba Tips ser vi på de tre mest använda trigonometriska funktionerna i Flash; Sine, Cosine och Atan2. Vissa människor kanske frågar, hur kan vi använda dessa funktioner i Flash? Tja, låt oss titta på några praktiska exempel och förstå varför vi behöver dem och hur de kan göra vårt liv lite enklare.
Låt oss beräkna vinkeln mellan två punkter. Skapa en ny Flash-fil (ActionScript 3.0). Välj den första ramen på tidslinjen och tryck F9 för att öppna en åtgärdspanel.
Låt oss nu göra något enkelt. Skriv bara in detta i åtgärdspanelen:
stage.addEventListener (MouseEvent.CLICK, calculateAngle) funktionen beräknaAngle (e: MouseEvent): void trace ("stage X" + e.stageX); spår ("steg Y" + e.stageY)
Detta ger oss muspekarens position varje gång vi klickar på scenen. Inte exakt fascinerande, är det?
OK, antar nu att du vill "berätta" några objekt muspekarens koordinater i förhållande till det här objektet, visa sedan riktningen för att resa för att nå pekarens position.
Stäng handlingspanelen och gå till Infoga> Nytt symbol eller tryck bara på Ctrl + F8.
Ge det något namn (eller lämna ett standardnamn) och tryck på OK. Den lilla korset i mitten av skärmen är symbolens registreringspunkt eller dess ursprungspunkt. Detta blir objektets X- och Y-positioner. Ta nu det ovala verktyget (O-tangenten) och dra en cirkel (med Shift-tangenten tryckt) var som helst på skärmen.
Klicka på cirkeln för att välja den och gå till dess Egenskaper-panel> Position och storlek. För W (bredd) typ i 20, samma för H (höjd) och för X och Y position typ (-10). Detta kommer att göra cirkeln 20x20 px och exakt centrera den till registreringspunkten. Avsluta nu symbolredigeringsläget (Klicka på scen 1 ovan), ta den här symbolen i ditt bibliotek och dra den helt enkelt till scenen (var som helst, vi får den positionen dynamiskt senare). När ditt objekt är på scenen, ge det ett förekomstnamn på mCircle
.
Nu vill vi beräkna riktningen från vår cirkels Y- och X-position till muspekarens Y- och X-position. Den röda linjen i bilden nedan är den riktning vi behöver veta. Det kan hittas med hjälp av en standard Math.atan2 ()
fungera.
Låt oss göra det nu. Ta bort "spår" -sättningarna från koden och skapa en ny variabel istället. Spåra sedan denna variabel för att se vad du får:
stage.addEventListener (MouseEvent.CLICK, calculateAngle); var myAtan2: Number; funktionen beräknaAngle (e: MouseEvent): void myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x); trace (myAtan2);
Anteckna det e.stageY - mCircle.y
är vertikal avstånd från musen till cirkeln, och e.stageX - mCircle.x
är horisontellt avstånd.
Du får dessa typer av nummer i utmatningspanelen:
-2.419017353128333 3.0118660246925346 2.5704959452340326 1.6726588917423932 1.0238847495551058 0.21368467849101092
Dessa är de relativa vinklarna (mellan X-axelinjen och den röda linjen) i radianer. Varför inte graderar? Jo, Flash använder radianer för att beräkna sinus och cosinus, men om du vill veta vad dessa vinklar är i grader kan du alltid multiplicera "myAtan2" med 180 och dela upp det med Math.PI
. Så här:
spår (myAtan2 * 180 / Math.PI) // ger dig vinkeln i grader;
Redaktör: Som en extra resurs, här är en bra uppsättning funktioner för grad / radian konvertering. Den är lagrad som ett snipp på snipplr.com, den senaste medlemmen i Envatos nätverk!
Som vi vet vinkeln mellan två punkter kan vi nu beräkna hur många pixlar vi måste lägga till i cirkelens X- och Y-egenskaper varje ram tills den når klickpunkten. Låt oss undersöka vad vi behöver veta här:
Den blå linjen är vinkeln Cosine, och den orange är vinkelns Sine. Med andra ord,
Snarare än att förklara på vilket sätt sinus och cosinus arbete, ska jag visa hur man använder dem med några praktiska exempel. Helt klart är sinus och cosinus relationerna mellan Y och X i vår vinkel.
Tänk vinkeln mellan två objekt är 45 grader. I detta fall är förhållandet mellan sinus och cosinus 1: 1 (se bilden nedan), vilket innebär att vi måste öka X- och Y-egenskaperna hos vår cirkel med samma mängd varje ram för att nå destinationen. Till exempel måste du lägga till 5 pixlar till X och 5 pixlar till Y varje ram.
I detta diagram har vinkeln förändrats och förhållandet mellan sinus och cosinus har ändrats också. Det är ungefär 1: 2 nu.
I det här fallet måste vi lägga till dubbelt så många pixlar i vår cirkels X-egenskap än till Y. T.ex. X + = 10, Y + = 5;
Du kommer noggrant att fråga varför vi behöver sinus och kosinus om vi redan vet klickpunktens koordinater - vi kan bara flytta vårt mCircle
till dem genast? Tja, du kunde ha gjort det på det här sättet om du ville att din cirkel (eller något annat objekt) skulle "teleportera" vid en klickpunktskoordinater så snart som ett klick inträffar. Men vad händer om du vill att den ska röra sig gradvis i riktning mot klicket? För att göra detta måste du lägga till en viss mängd pixlar till dess X- och Y-egenskaper, till exempel varje ram eller varje sekund.
Låt oss nu beräkna hur många pixlar vi ska lägga till i dess X- och Y-egenskaper baserat på sinus och cosinus av vinkeln mellan vårt objekt och en klickpunkt. Kom ihåg att Flash vet vinkeln mellan dem från den här operationen:
myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x);
För detta ändamål borde vi uppdatera vår kod lite.
stage.addEventListener (MouseEvent.CLICK, calculateAngle); // 2 är den maximala mängden pixlar som ska läggas till objekten X och Y egenskaper varje ram // du kan använda vilket nummer du vill var moveAmount: Number = 2; var myAtan2: Number; var mouseClickX: Number; var mouseClickY: Number; funktionen beräknaAngle (e: MouseEvent): void mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x); addEventListener (Event.ENTER_FRAME, moveTheCircle); funktion moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount;
Observera vad jag har gjort här: Jag främjade alla mina variabler utanför några funktioner, för nu har jag mer än en funktion och jag vill att dessa variabler ska vara tillgängliga från alla funktioner.
var moveAmount: Number = 2; var myAtan2: Number; var mouseClickX: Number; var mouseClickY: Number;
Scenen har en händelseloggare för musklick, så när klicket inträffar, metoden calculateAngle ()
kallas och de följande variablerna är instantierade:
mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x);
Den här funktionen lägger också till en händelseloggare för att ange ram till scenen, som kallar moveTheCircle ()
Metod varje ram.
addEventListener (Event.ENTER_FRAME, moveTheCircle);
Nu, låt oss bryta ner vårt moveTheCircle ()
själva metoden. För nu gör det bara två saker:
mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount;
Som du kan se beräknar den första raden hur många pixlar den ska lägga till X-egenskapen och den andra handlar om Y. Låt mig förklara. Math.cos finner cosinus (x-egenskapen) i "myAtan2" -vinkeln, Math.sin gör detsamma med sin sinus (y-egenskap). Om vår myAtan2-vinkel motsvarar ungefär 0,785 radianer (45 grader) kommer cosinus och sinus båda att vara lika med ca 0,707 ... Du kan använda en räknare för att kolla upp den.
En enkel beräkning visar hur många pixlar koden ovan lägger till i objektets X- och Y-egenskaper om vinkeln är 45 grader.
Cosinus (45 grader) = 0,707 * 2 = 1,414; Sine (45 grader) = 0,707 * 2 = 1,414; så koden kommer att uträtta dessa resultat: mCircle.x + = 1.414 pixlar; mCircle.y + = 1.414 pixlar;
Om vinkeln exempelvis är. 60 grader då skulle resultaten bli så här:
Cosine (60 grader) = 0,5 * 2 = 1; Sine (60 grader) = 0,866 * 2 = 1,732; Och koden skulle fungera så här: mCircle.x + = 1 pixel; mCircle.y + = 1.732 pixlar;
Jo, vi är nästan färdiga. Men det finns fortfarande ett litet problem med vår kod. Du kanske har märkt att vårt föremål aldrig slutar, även om det når klickpunkten, fortsätter det fortfarande att flytta. Vi kan enkelt lösa detta problem. När vårt objekt rör sig mot klickpunkten, avståndet mellan dem förkortar så absolut Värdet på avståndet minskar också. Vi kan hålla reda på det så här:
spår (Math.abs (mCircle.x - mouseClickX)); spår (Math.abs (mCircle.y - mouseClickY));
(Math.abs ()
omvandlar negativa tal till positiva genom att helt enkelt multiplicera dem med -1. Det gör inget för nummer som redan är positiva.)
Du behöver inte lägga till detta spårningsdeklaration till din kod, jag har lagt den här bara för att visa dig hur du kan se absolutvärdet. I det här fallet är båda absoluta värdena mindre än 3 när objektet når klickpunkten. Så vad vi behöver nu är att lägga till en om
uttalande inuti vårt moveTheCircle ()
fungera.
funktion moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount; // Kontrollera om de horisontella och vertikala avstånden från cirkeln till muspunkten är mycket nära om (Math.abs (mCircle.x - mouseClickX) < 3 && Math.abs(mCircle.y - mouseClickY) < 3) removeEventListener(Event.ENTER_FRAME, moveTheCircle);
När det absoluta värdet blir under 3, tas in-frame lyssnaren bort. Vi måste kontrollera både X och Ys absoluta värden eftersom en av dem kan nå 3 även när den andra inte har det. Det betyder att objekten kan stoppa så här:
Bilden ovan visar den version där endast X: s absolutvärde är markerat. X-avståndets absoluta värde är redan mindre än 3, så det slutade att uppmärksamma Y-värdet.
Jo det är det. Jag hoppas att den här snabba tipsen hjälper dig att förstå några trigonometri som används i Flash-utveckling :)