Il tau è solamente un "mezzuccio" che serve per non far rieseguire la funzione più volte in riferimento allo stesso urto. Infatti succede che la palla, al momento dell'urto, non sia esattamente tangente al piano, ma che "gli entri un pò dentro", perché ovviamente la palla si muove a passi finiti. In questo caso, all'istante dopo l'urto, la palla sarà probabilmente ancora a contatto con il piano, e quindi la funzione si ritroverebbe ad invertire di nuovo la velocità, causando un errore. Il tau fa in modo che questo non avvenga, impendendo l'esecuzione ripetuta (a meno di tau istanti di tempo) della funzione.
Esiste una soluzione molto più raffinata a questo problema (soluzione che ho implementato per un altro mio progetto), che consiste nello spostare al momento dell'urto la palla in una posizione che sia realmente tangente al piano. Non avevo tempo per metterla nel tuo esempio né sapevo se ti interessasse, per cui ho lasciato il tau. Se ti serve e non sai come fare ti do una mano, per ora non entro nei dettagli perché non è semplice.
Veniamo alla funzione hitControl.
La prima cosa da fare è capire *se* sta avvenendo un urto o meno. Logicamente non vogliamo banalmente usare la funzione hitTest di Flash perché è alquanto imprecisa.
Allora ho ragionato così:
Calcolo in qualche modo la distanza fra la palla e il piano, poi se quasta distanza è minore o uguale al raggio della palla, ne deduco che siamo in presenza dell'urto. Chiaro fin qui?
Per calcolare questa distanza ho fatto un paio di considerazioni algebriche, che vado a scriverti:
L'equazione del piano su cui batte la palla (che poi è una retta) è questa:
y = wy + tan(theta)*(x - wx)
dove wx e wy sono le coordinate di un punto qualsiasi della retta (ad esempio, in flash, wx = _root.piano._x e wy = _root.piano._y) e theta è l'angolo di rotazione della retta
L'equazione della traiettoria della palla è invece:
(x - px)/vx = (y - py)/vy
dove px = _root.palla._x e py = _root.palla._y
Si possono mettere queste due equazioni a sistema per trovare l'intersezione. Ti risparmio i passaggi algebrici, ma i valori che si trovano alla fine sono proprio quelli che ho scritto nel codice associati alle variabili hitx e hity.
// calcolo dell'intersezione della tangente alla traiettoria della palla con il piano
hitx = (vy/vx*px - py + wy - wx*Math.tan(theta))/(vy/vx - Math.tan(theta)); // ascissa
hity = Math.tan(theta)*(hitx - wx) + wy; // ordinata
Calcoliamo ora la distanza fra questo punto (la proiezione della palla sulla retta) e la palla, con il teorema di pitagora:
// distanza fra l'intersezione e la palla:
dist = Math.sqrt(Math.pow(px-hitx,2) + Math.pow(py-hity,2));
Se questa distanza risulterà inferiore o uguale al raggio della palla, allora abbiamo un urto, altrimenti no:
// controlla se è avvenuto l'urto:
if (dist <= raggio) // l'urto è avvenuto
{
Tutto chiaro?
Ora non resta da capire cosa c'è da fare per rendere realistico il rimbalzo.
Nel codice è tutto sintetizzato, ma la teoria che ci sta dietro è questa:
Inizialmente ci spostiamo nel sistema di riferimento del piano, moltiplicando il vettore della velocità per la matrice di rotazione per un angolo pari a theta.
A questo punto, abbiamo la velocità espressa in queste due componenti: una parallela alla retta ed una perpendicolare.
Adesso semplicemente invertiamo il segno della componente perpendicolare.
Non ci resta ora che ruotare al contrario il nostro vettore velocità e il gioco è fatto. Nel codice è riportato soltanto un passaggio, con tutte le operazioni concentrate in un'istruzione sola.
Mi rendo conto che queste cose possono non essere facili da capire (né da spiegare per scritto via forum!) se nonsi conosce un pò di trigonometria... io ci ho provato
Spara pure altre domande se ne hai