Suggerimento rapido Trigonometria per sviluppatori di giochi Flash

In Distribuisci un carro armato in una zona di guerra isometrica, hai imparato come far ruotare un oggetto per affrontare il puntatore e spostarti verso una posizione al clic. In questo suggerimento, daremo un'occhiata generale alla matematica dietro di esso: trigonometria.


Anteprima del risultato finale

Questo è il risultato finale del mio precedente tutorial. Fa uso dei principi di trigonometria che tratteremo in questo suggerimento rapido:

Muovi il mouse per fare in modo che la torretta miri verso di esso e fai clic su un punto qualsiasi per portare il carro a guidare fino a quel punto.

Qualsiasi programmatore, in particolare qualsiasi programmatore di giochi, deve affrontare la necessità di spostare gli oggetti sullo schermo prima o poi. È un compito semplice se è necessario spostare un oggetto in una direzione, ad esempio lungo l'asse x o y. Ma supponiamo di voler far seguire a un oggetto il tuo puntatore del mouse ovunque lo sposti, o creare un gioco di corse in cui controlli l'accelerazione di un'auto premendo il tasto freccia su e usando le frecce sinistra e destra per guidare.

Supponiamo che tu preme il tasto freccia destra una volta e aggiunge 10 gradi alla proprietà di rotazione della tua auto ma desideri comunque che l'auto si muova in avanti (cioè accelera) quando premi un tasto freccia su, anche se una macchina è girata verso il fondo di lo schermo o il lato sinistro o destro ecc. e non vuoi che sembri che scivoli di lato. Quindi, come lo faresti? Ecco dove un po 'di trigonometria aiuta!

Per quelli che sono bravi in ​​matematica non sarà un problema, ma ci sono molte persone che non lo capiscono affatto, o ne hanno persino paura. Proverò a suddividerlo il più chiaramente possibile in questo suggerimento rapido.

Passaggio 1: il sistema di coordinate Flash

All'inizio, ricordiamo il sistema di coordinate cartesiane. Sembra complicato? Se è così, basta guardare l'immagine qui sotto e sono sicuro che sarà familiare:

Ha assi X e Y; puoi vedere chiaramente dove X e Y sono positivi e negativi. Quando si tratta di coordinate in Flash, la situazione è leggermente diversa. Flash ha anche il suo sistema di coordinate, ma sembra che il sistema cartesiano sia capovolto:

Ha anche assi X e Y e il punto di origine, l'unica differenza è che l'asse Y è positivo sotto l'asse X..

Qualsiasi simbolo creato in Flash ha il proprio sistema di coordinate incorporato. Se crei un nuovo simbolo, che si tratti di un clip filmato o di un pulsante, potresti vedere una proprietà "punto di registrazione" nella finestra di dialogo di creazione del simbolo. Che cos'è? Il punto di registrazione è un punto di origine di un simbolo. Il punto in cui ruoterà l'oggetto se modificate la sua proprietà di rotazione.

Nota: il punto di origine dell'istanza di stage si trova nell'angolo in alto a sinistra. Ciò significa che tutti i punti sullo stage hanno coordinate X e Y positive.

In questo suggerimento rapido vedremo le tre funzioni trigonometriche più comunemente utilizzate in Flash; Sine, Cosine e Atan2. Alcuni potrebbero chiedersi, come possiamo usare queste funzioni in Flash? Bene, diamo un'occhiata ad alcuni esempi pratici e comprendiamo perché ne abbiamo bisogno e come possono rendere la nostra vita un po 'più facile.

Passaggio 2: calcolo dell'angolo

Calcoliamo l'angolo tra due punti. Crea un nuovo file Flash (ActionScript 3.0). Seleziona il primo fotogramma della timeline e premi F9 per aprire un pannello Azioni.

A questo punto facciamo qualcosa di semplice. Basta digitare questo nel pannello Azioni:

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

Questo ci darà la posizione del puntatore del mouse ogni volta che cliccheremo sul palco. Non esattamente affascinante, vero??

Ok, ora supponiamo di voler "dire" ad alcuni oggetti le coordinate del tuo puntatore del mouse relative a questo oggetto, quindi mostrargli la direzione in cui viaggiare per raggiungere la posizione del puntatore.

Chiudi il pannello Azioni e vai a Inserisci> Nuovo simbolo o premi Ctrl + F8.

Dagli qualsiasi nome (o lascia un nome predefinito) e premi OK. Il piccolo mirino nel mezzo dello schermo è il punto di registrazione del simbolo o il suo punto di origine. Questa sarà la posizione X e Y dell'oggetto. Ora prendi lo strumento Ovale (tasto O) e disegna un cerchio (con il tasto Shift premuto) in qualsiasi punto dello schermo.

Fai clic sul cerchio per selezionarlo e vai al pannello Proprietà> Posizione e dimensioni. Per W (larghezza) digitare in 20, lo stesso per H (altezza) e per X e Y digitare il tipo in (-10). Questo farà il cerchio 20x20 px e lo centrerà esattamente al punto di registrazione. Ora esci dalla modalità di modifica dei simboli (fai clic su Scena 1 sopra), prendi questo simbolo nel tuo grimorio e trascinalo semplicemente sul palco (ovunque, la posizione verrà acquisita dinamicamente in seguito). Una volta che il tuo oggetto è sul palco, dagli un nome di istanza mCircle.

Ora vogliamo calcolare la direzione dalla posizione Y e X del nostro cerchio alla posizione Y e X del puntatore del mouse. La linea rossa nell'immagine sotto è la direzione che dobbiamo sapere. Può essere trovato usando uno standard Math.atan2 () funzione.

Facciamolo adesso. Elimina le istruzioni "trace" dal codice e crea invece una nuova variabile. Quindi traccia questa variabile per vedere cosa ottieni:

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

Nota che e.stageY - mCircle.y è il verticale distanza dal mouse al cerchio, e e.stageX - mCircle.x è il distanza orizzontale.

Otterrai questi tipi di numeri nel pannello di output:

 -2.419017353128333 3.0118660246925346 2.5704959452340326 1.6726588917423932 1.0238847495551058 0.21368467849101092

Questi sono gli angoli relativi (tra la linea dell'asse X e la linea rossa) in radianti. Perché non i gradi? Beh, Flash usa i radianti per calcolare seno e coseno, ma se vuoi sapere quali sono questi angoli in gradi puoi sempre moltiplicare "myAtan2" per 180 e dividerlo per Math.PI. Come questo:

 trace (myAtan2 * 180 / Math.PI) // fornisce l'angolo in gradi;

Editor: Come risorsa aggiuntiva, ecco un ottimo set di funzioni per la conversione gradi / radianti. È memorizzato come snippet su snipplr.com, l'ultimo membro della rete di Envato!

Step 3: Comprensione del seno e del coseno

Poiché conosciamo l'angolo tra due punti, ora possiamo calcolare quanti pixel dobbiamo aggiungere alle proprietà X e Y del cerchio ogni fotogramma finché non raggiunge il punto di scatto. Esaminiamo ciò che dobbiamo sapere qui:

La linea blu è il coseno dell'angolo e l'arancione è il seno dell'angolo. In altre parole,

  • Sine (angolo) == e.stageY - mCircle.y
  • Coseno (angolo) == e.stageX - mCircle.x

Piuttosto che spiegare Come il seno e il coseno funzionano, dimostrerò come usarli con alcuni esempi pratici. Parlando senza mezzi termini, il seno e il coseno sono le relazioni tra Y e X nel nostro angolo.

Immagina che l'angolo tra due oggetti sia di 45 gradi. In questo caso la relazione tra seno e coseno è 1: 1 (vedi l'immagine sotto), il che significa che dobbiamo aumentare le proprietà X e Y del nostro cerchio della stessa quantità ogni fotogramma per raggiungere la destinazione. Ad esempio, devi aggiungere 5 pixel a X e 5 pixel a Y ogni fotogramma.

In questo diagramma, l'angolo è cambiato e anche la relazione tra seno e coseno è cambiata. È circa 1: 2 ora.

In questo caso dobbiamo aggiungere il doppio di pixel alla proprietà X del nostro cerchio rispetto a Y. E.g. X + = 10, Y + = 5;

Passaggio 4: esempi pratici

Probabilmente ti chiederai perché abbiamo bisogno di seno e coseno se conosciamo già le coordinate del punto di scatto - possiamo semplicemente spostare il nostro mCircle a loro subito? Bene, avresti potuto farlo in questo modo se volevi che il tuo cerchio (o qualsiasi altro oggetto) "teletrasportasse" in corrispondenza di coordinate di un clic non appena si verifica un clic. Ma cosa succede se vuoi che si muova gradualmente nella direzione del clic? Per fare ciò è necessario aggiungere una determinata quantità di pixel alle sue proprietà X e Y, ad esempio, ogni fotogramma o ogni secondo.

Calcoliamo ora quanti pixel dovremmo aggiungere alle sue proprietà X e Y in base al seno e al coseno dell'angolo tra il nostro oggetto e un punto di scatto. Ricorda, Flash conosce l'angolo tra di loro da questa operazione:

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

A tal fine dovremmo aggiornare un po 'il nostro codice.

 stage.addEventListener (MouseEvent.CLICK, calculateAngle); // 2 è la quantità massima di pixel da aggiungere agli oggetti X e Y proprietà ogni fotogramma // è possibile utilizzare qualsiasi numero che ti piace var moveAmount: Number = 2; var myAtan2: Number; var mouseClickX: Number; var mouseClickY: numero; 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);  function moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount; 

Nota quello che ho fatto qui: ho promosso tutte le mie variabili al di fuori di qualsiasi funzione, perché ora ho più di una funzione e voglio che queste variabili siano accessibili da ogni funzione.

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

Lo stage ha un listener di eventi per i clic del mouse, quindi quando si verifica il clic, il metodo calculateAngle () viene chiamato e le seguenti variabili vengono istanziate:

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

Questa funzione aggiunge anche un listener di eventi per l'immissione di frame sullo stage, che chiama il moveTheCircle () metodo ogni fotogramma.

 addEventListener (Event.ENTER_FRAME, moveTheCircle);

Passaggio 5: calcolo dei pixel

Ora, abbattiamo il nostro moveTheCircle () metodo stesso. Per ora fa solo due cose:

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

Come puoi vedere, la prima riga calcola quanti pixel deve aggiungere alla proprietà X e la seconda riguarda Y. Lasciami spiegare. Math.cos trova il coseno (proprietà x) dell'angolo "myAtan2", Math.sin fa lo stesso con il suo seno (proprietà y). Se il nostro angolo myAtan2 equivale a circa 0,785 radianti (45 gradi), il coseno e il seno saranno entrambi uguali a circa 0,707 ... Puoi usare una calcolatrice per controllarlo.

Un semplice calcolo mostrerà quanti pixel il codice sopra verrà aggiunto alle proprietà X e Y del nostro oggetto se l'angolo è 45 gradi.

 Coseno (45 gradi) = 0,707 * 2 = 1,414; Seno (45 gradi) = 0,707 * 2 = 1,414; quindi il codice risolverà questi risultati: mCircle.x + = 1.414 pixel; mCircle.y + = 1.414 pixel;

Se l'angolo e.g è. 60 gradi quindi i risultati sarebbero come questo:

 Coseno (60 gradi) = 0,5 * 2 = 1; Seno (60 gradi) = 0.866 * 2 = 1.732; E il codice funzionerebbe in questo modo: mCircle.x + = 1 pixel; mCircle.y + = 1.732 pixel;

Passaggio 6: risolvere un problema con il codice

Bene, abbiamo quasi finito. Ma c'è ancora un piccolo problema con il nostro codice. Potresti aver notato che il nostro oggetto non si ferma mai, anche se raggiunge il punto di scatto continua a muoversi. Possiamo risolvere questo problema molto facilmente. Mentre il nostro oggetto si sposta verso il punto di scatto, la distanza tra loro si accorcia assoluto anche il valore della distanza diminuisce. Possiamo tenerne traccia in questo modo:

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

(Math.abs () trasforma i numeri negativi in ​​positivi semplicemente moltiplicandoli per -1. Non fa nulla ai numeri che sono già positivi.)

Non è necessario aggiungere questa istruzione di tracciamento al codice, l'ho messo qui solo per mostrarti il ​​modo in cui puoi vedere il valore assoluto. In questo caso, entrambi i valori assoluti sono inferiori a 3 quando l'oggetto raggiunge il punto di clic. Quindi quello di cui abbiamo bisogno ora è aggiungerne uno Se dichiarazione dentro la nostra moveTheCircle () funzione.

 function moveTheCircle (e: Event): void mCircle.x + = Math.cos (myAtan2) * moveAmount; mCircle.y + = Math.sin (myAtan2) * moveAmount; // Controlla se le distanze orizzontali e verticali dal cerchio al punto del mouse sono molto vicine se (Math.abs (mCircle.x - mouseClickX) < 3 && Math.abs(mCircle.y - mouseClickY) < 3)  removeEventListener(Event.ENTER_FRAME, moveTheCircle);  

Quando il valore assoluto scende al di sotto di 3, il listener di enter frame viene rimosso. Dobbiamo controllare i valori assoluti di X e Y perché uno di essi potrebbe raggiungere 3 anche se il secondo no. Ciò significa che gli oggetti potrebbero fermarsi in questo modo:

L'immagine sopra mostra la versione in cui viene controllato solo il valore assoluto di X. Il valore assoluto della distanza X è già inferiore a 3, quindi ha smesso di prestare attenzione al valore Y.


Conclusione

Bene, è tutto. Spero che questo suggerimento rapido ti aiuti a capire un po 'di trigonometria utilizzata nello sviluppo di Flash :)