În implementarea unui rezervor într-o zonă izometrică de război, ați învățat cum să faceți ca un obiect să se rotească să se îndrepte spre pointer și să se deplaseze către o locație la apăsare. În acest sfat rapid, vom analiza în general matematica din spatele ei: trigonometria.
Acesta este rezultatul final al tutorialului meu anterior. Folosește principiile de trigonometru pe care le vom acoperi în acest Sfat rapid:
Mutați mouse-ul pentru a face turela să țintească, și faceți clic oriunde pentru a obține rezervorul de a conduce până la acel moment.
Orice programator, în special orice programator de jocuri, se confruntă cu nevoia de a muta obiecte pe ecran mai devreme sau mai târziu. Este o sarcină simplă dacă trebuie să mutați un obiect într-o direcție, de exemplu de-a lungul axei x sau y. Dar să presupunem că vrei să faci un obiect să urmezi indicatorul mouse-ului oriunde îl muți ori să creezi un joc de curse în care să controlezi accelerarea unei mașini prin apăsarea tastei săgeată sus și să folosești săgețile stânga și dreapta pentru a direcționa.
Să presupunem că apăsați o dată pe tasta săgeată dreapta și adăugați 10 grade la proprietatea de rotație a mașinii, dar totuși doriți ca autovehiculul să meargă înainte (adică să accelereze) atunci când apăsați o tastă săgeată în sus, chiar dacă o mașină este rotită spre partea de jos a ecranul sau o stânga sau pe partea dreaptă etc. și nu doriți ca acesta să pară ca fiind alunecos lateral. Deci, cum ai face asta? Aici ajută puțin trigonometria!
Pentru cei care sunt buni la matematică, nu va fi o problemă, dar există o mulțime de oameni care nu o înțeleg deloc sau chiar sunt speriați de ea. Voi încerca să o descompun cât se poate de clar în acest sfat rapid.
La început, să ne amintim sistemul de coordonate carteziene. Sunet complicat? Dacă da, uită-te la imaginea de mai jos și sunt sigur că va fi familiar:
Are axe X și Y; puteți vedea în mod clar unde X și Y sunt pozitive și negative. Când vine vorba de coordonatele în Flash, situația este puțin diferită. Flash are, de asemenea, sistemul său de coordonate, dar arată ca sistemul cartezian cu susul în jos:
De asemenea, are axele X și Y și punctul de origine, singura diferență fiind aceea că axa Y este pozitivă de mai jos axa X..
Orice simbol creat în Flash are propriul sistem de coordonate încorporat. Dacă creați un nou simbol, fie că este vorba de un clip video sau de un buton, este posibil să vedeți o proprietate "punct de înregistrare" în caseta de dialog Creare simboluri. Ce este? Punctul de înregistrare este un punct de origine al unui simbol. Punctul în care obiectul se va roti în jur dacă schimbați proprietatea de rotație.
Notă: punctul de origine al instanței de scenă este în colțul din stânga sus. Aceasta înseamnă că toate punctele de pe scenă au coordonate pozitive X și Y.
În acest sfat rapid vom analiza cele trei funcții trigonometrice cele mai utilizate în Flash; Sine, Cosine și Atan2. Unii oameni ar putea întreba, cum putem folosi aceste funcții în Flash? Să aruncăm o privire asupra unor exemple practice și să înțelegem de ce avem nevoie de ele și de modul în care ne pot face viața un pic mai ușoară.
Să calculăm unghiul dintre două puncte. Creați un nou fișier Flash (ActionScript 3.0). Selectați primul cadru al liniei temporale și apăsați F9 pentru a deschide un Panou de acțiuni.
În acest moment să facem ceva simplu. Doar tastați acest lucru în Panoul de acțiuni:
etapa.addEventListener (MouseEvent.CLICK, calculateAngle) funcția calculateAngle (e: MouseEvent): void trace ("etapa X" + e.stageX); urmări ("etapa Y" + e.stageY)
Acest lucru ne va da poziția indicatorul mouse-ului de fiecare dată când facem clic pe scenă. Nu este chiar fascinant, nu-i așa??
Ok, acum presupuneți că doriți să "spuneți" un obiect coordonatele cursorului mouse-ului față de acest obiect, apoi arătați-i direcția de deplasare pentru a ajunge la poziția pointerului.
Închideți panoul de acțiuni și accesați Insert> New Symbol sau doar apăsați Ctrl + F8.
Dați-i un nume (sau lăsați un nume implicit) și apăsați OK. Micul cruce în mijlocul ecranului este punctul de înregistrare al simbolului sau punctul de origine al acestuia. Acestea vor fi pozițiile X și Y ale obiectului. Acum, apucați instrumentul Oval (tasta O) și desenați un cerc (cu tasta Shift apăsată) oriunde pe ecran.
Faceți clic pe cerc pentru ao selecta și accesați panoul Proprietăți> Poziție și dimensiune. Pentru tipul W (lățimea) în 20, același pentru H (înălțime) și pentru tipul de poziție X și Y din (-10). Aceasta va face cercul de 20x20 px și va centra exact la punctul de înregistrare. Acum, părăsiți modul de editare a simbolurilor (faceți clic pe Scenă 1 de mai sus), prindeți acest simbol în bibliotecă și pur și simplu trageți-l pe scenă (oriunde, vom obține poziția dinamică mai târziu). Odată ce obiectul dvs. este pe scenă, dați-i un nume de instanță mCircle
.
Acum dorim să calculam direcția de la poziția Y și X a cercului nostru la poziția Y și X a indicatorului mouse-ului. Linia roșie din imaginea de mai jos este direcția pe care trebuie să o cunoaștem. Acesta poate fi găsit utilizând un standard Math.atan2 ()
funcţie.
S-o facem acum. Ștergeți instrucțiunile "urmărire" din cod și creați o nouă variabilă. Apoi urmăriți această variabilă pentru a vedea ce obțineți:
starea.addEventListener (MouseEvent.CLICK, calculateAngle); var myAtan2: Număr; funcția calculateAngle (e: MouseEvent): void myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x); trace (myAtan2);
Rețineți că e.stageY - mCircle.y
este vertical distanța de la mouse la cerc și e.stageX - mCircle.x
este orizontală.
Veți primi aceste tipuri de numere în panoul de ieșire:
-2.419017353128333 3.0118660246925346 2.5704959452340326 1.6726588917423932 1.0238847495551058 0.21368467849101092
Acestea sunt unghiurile relative (între linia axei X și linia roșie) în radiani. De ce nu sunt grade? Ei bine, Flash utilizează radiani pentru a calcula sine și cosinus, dar dacă vrei să știi ce sunt aceste unghiuri în grade, poți înmulți întotdeauna "myAtan2" cu 180 și împărți Math.PI
. Asa:
urmări (myAtan2 * 180 / Math.PI) // vă oferă unghiul în grade;
Editor: Ca o resursă suplimentară, iată un set mare de funcții pentru conversia grad / radian. Este stocat ca un snippet pe snipplr.com, cel mai recent membru al rețelei Envato!
După cum știm unghiul dintre două puncte, putem calcula acum câte pixeli trebuie să adăugăm la proprietățile cercului X și Y în fiecare cadru până când ajunge la punctul de clic. Să examinăm ce trebuie să știm aici:
Linia albastră este cosinusul unghiului, iar portocaliu este Sine a unghiului. Cu alte cuvinte,
Mai degrabă decât să explice Cum sinus și cosinus, voi demonstra cum să le folosesc cu câteva exemple practice. Din nefericire, sinusul și cosinusul sunt relațiile dintre Y și X în unghiul nostru.
Imaginați-vă că unghiul dintre două obiecte este de 45 de grade. În acest caz, relația dintre sinus și cosinus este 1: 1 (a se vedea imaginea de mai jos), ceea ce înseamnă că trebuie să creștem proprietățile X și Y ale cercului nostru cu aceeași valoare pentru fiecare cadru pentru a ajunge la destinație. De exemplu, trebuie să adăugați 5 pixeli la X și 5 pixeli la Y în fiecare cadru.
În această diagramă, unghiul sa schimbat, iar relația dintre sine și cosinus s-a schimbat prea mult. E vorba de 1: 2 acum.
În acest caz, trebuie să adăugăm de două ori mai mulți pixeli la proprietatea X a cercului nostru decât la Y. De ex. X + = 10, Y + = 5;
Veți întreba probabil de ce avem nevoie de sine și cosinus dacă știm deja coordonatele punctului de clic - putem să ne mutăm mCircle
pentru ei imediat? Ați fi putut face acest lucru dacă doriți ca cercul dvs. (sau orice alt obiect) să "teleporteze" la un punct al punctului de acces imediat ce apare clicul. Dar dacă vrei să se miște treptat în direcția clicului? Pentru a face acest lucru trebuie să adăugați o anumită sumă de pixeli proprietăților X și Y, de exemplu, fiecare cadru sau fiecare secundă.
Să calculăm acum câte pixeli ar trebui să adăugăm proprietăților X și Y bazate pe sinus și cosinus al unghiului dintre obiectul nostru și un punct de clic. Rețineți că Flash cunoaște unghiul dintre acestea din această operațiune:
myAtan2 = Math.atan2 (e.stageY - mCircle.y, e.stageX - mCircle.x);
În acest scop, ar trebui să ne actualizăm puțin codul.
starea.addEventListener (MouseEvent.CLICK, calculateAngle); // 2 este suma maximă a pixelilor care se adaugă la proprietățile obiectelor X și Y în fiecare cadru // puteți utiliza orice număr care vă place var moveAmount: Number = 2; var myAtan2: Număr; var mouseClickX: Număr; var mouseClickY: Număr; funcția calculateAngle (e: MouseEvent): void mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x); addEventListener (Event.ENTER_FRAME, moveTheCircle); funcția moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * mutareAmount;
Rețineți ce am făcut aici: am promovat toate variabilele mele în afara funcțiilor, pentru că acum am mai multe funcții și vreau ca aceste variabile să fie accesibile din fiecare funcție.
var moveAmount: Număr = 2; var myAtan2: Număr; var mouseClickX: Număr; var mouseClickY: Număr;
Stadiul are un ascultător de evenimente pentru clicurile de mouse, astfel încât atunci când apare clicul, metoda calculateAngle ()
devine apelat și variabilele următoare sunt instanțiate:
mouseClickX = e.stageX; mouseClickY = e.stageY; myAtan2 = Math.atan2 (mouseClickY - mCircle.y, mouseClickX - mCircle.x);
Această funcție adaugă, de asemenea, un ascultător de evenimente pentru intrarea în cadru pe scena, care apelează moveTheCircle ()
fiecare cadru.
addEventListener (Event.ENTER_FRAME, moveTheCircle);
Acum, să ne descurcăm moveTheCircle ()
metoda în sine. Deocamdată, au doar două lucruri:
mCircle.x + = Math.cos (myAtan2) * mutareAmount; mCircle.y + = Math.sin (myAtan2) * mutareAmount;
După cum puteți vedea, prima linie calculează câte pixeli ar trebui să adauge la proprietatea X, iar al doilea se referă la Y. Permiteți-mi să explic. Math.cos găsește cosinul (proprietatea x) a unghiului "myAtan2", Math.sin face același lucru cu proprietatea sine (y). Dacă unghiul myAtan2 este egal cu aproximativ 0.785 radiani (45 de grade), cosinusul și sinusoidele vor fi egale cu aproximativ 0.707 ... Puteți folosi un calculator pentru a verifica afară.
Un calcul simplu va arăta câți pixeli vor adăuga codul de mai sus la proprietățile X și Y ale obiectului dacă unghiul este de 45 de grade.
Cosin (45 de grade) = 0,707 * 2 = 1,414; Sinus (45 de grade) = 0,707 * 2 = 1,414; astfel încât codul va rezolva aceste rezultate: mCircle.x + = 1.414 pixeli; mCircle.y + = 1.414 pixeli;
Dacă unghiul este de exemplu. 60 de grade, atunci rezultatele ar fi așa:
Cosin (60 de grade) = 0,5 * 2 = 1; Sinus (60 de grade) = 0,866 * 2 = 1,732; Și codul ar funcționa astfel: mCircle.x + = 1 pixel; mCircle.y + = 1.732 pixeli;
Ei bine, aproape am terminat. Dar există încă o mică problemă cu codul nostru. S-ar putea să fi observat că obiectul nostru nu se oprește niciodată, chiar dacă ajunge la punctul de clic pe care îl mai mișcă. Putem rezolva această problemă foarte ușor. Când obiectul nostru se mișcă spre punctul de clic, distanța dintre ele se scurtează, astfel încât absolut se reduce și valoarea distanței. Putem urmări astfel:
urmări (Math.abs (mCircle.x - mouseClickX)); urmări (Math.abs (mCircle.y - mouseClickY));
(Math.abs ()
transformă numerele negative în pozitive prin simpla multiplicare cu -1. Nu face nimic pentru numerele care sunt deja pozitive.)
Nu este nevoie să adăugați această instrucțiune de urmărire la codul dvs., l-am pus aici doar pentru a vă arăta modul în care puteți vedea valoarea absolută. În acest caz, ambele valori absolute sunt mai mici de 3 atunci când obiectul atinge punctul de clic. Așadar, ceea ce avem nevoie acum este să adăugăm unul dacă
declarație în interiorul nostru moveTheCircle ()
funcţie.
Funcția moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * mutareAmount; // Verificați dacă distanțele orizontale și verticale de la cerc la punctul mouse-ului sunt foarte apropiate dacă (Math.abs (mCircle.x - mouseClickX) < 3 && Math.abs(mCircle.y - mouseClickY) < 3) removeEventListener(Event.ENTER_FRAME, moveTheCircle);
Când valoarea absolută se situează sub 3, ascultătorul de intrare a cadrului este eliminat. Trebuie să verificăm atât valorile absolute ale lui X, cât și ale lui Y, deoarece unul dintre ele ar putea atinge 3 chiar și atunci când cel de-al doilea nu are. Aceasta înseamnă că obiectele se pot opri astfel:
Imaginea de mai sus arată versiunea în care este verificată numai valoarea absolută a lui X. Valoarea absolută a distanței X este deja mai mică de 3, astfel încât nu a mai acordat nici o atenție valorii Y.
Asta este. Sper că acest sfat rapid vă va ajuta să înțelegeți unele trigonometrii folosite în dezvoltarea Flash :)