Nei precedenti Suggerimenti rapidi, abbiamo esaminato la collisione rivelazione: in sostanza, rilevando che due forme si sono sovrapposte. Ora siamo pronti a guardare la collisione reazione: fare accadere qualcosa a causa di una collisione. In questo suggerimento rapido, esamineremo le reazioni di riflessione e scorrimento.
Diamo un'occhiata al risultato finale che otterremo alla fine di questo tutorial. Ogni demo Flash ha un pulsante di riavvio; fai clic per ripristinare la posizione dei cerchi nella parte superiore dello stage.
Il primo demo mostra riflessione:
Il secondo spettacolo scorrevole:
Ho affrontato questo argomento in diverse fasi con gli studenti, e l'esperienza mi ha insegnato che l'approccio frontale di spiegare la matematica vettoriale ai fresher ha come risultato facce vuote e menti confuse. Quindi, invece di presentare una lezione di matematica qui, riferirò coloro che sono interessati a indagare ulteriormente su questo argomento alla pagina di Wolfram sulla riflessione.
Qui semplificherò le mie spiegazioni con gli schemi qui sotto. Richiama aggiunta vettoriale:
Ora, osserva lo schema qui sotto. A è la velocità del cerchio prima di una collisione e A 'è la sua velocità dopo la collisione.
È ovvio che A '= A + 2 V (Ap)
, dove V (Ap)
rappresenta il vettore con una grandezza di Ap, nella direzione della sinistra normale. (Puoi vederlo seguendo le linee tratteggiate).
Per ottenere V (Ap)
, dovremo proiettare A sulla sinistra normale.
Ecco l'implementazione della riflessione di ActionScript. Ho evidenziato le parti importanti. La riga 67 - 69 è da calcolare V (Ap
) (v_leftNormSeg2
) e la riga 70 implementa la formula. Si può fare riferimento al completo Actionscript sotto Reaction1.as.
(Dovresti riconoscere la maggior parte del codice dal precedente suggerimento rapido.)
aggiornamento della funzione privata (e: Event): void for (var i: int = 0; i < circles.length; i++) //calculating line's perpendicular distance to ball var c1_circle:Vector2D = new Vector2D(circles[i].x - x1, circles[i].y - y1); var c1_circle_onNormal:Number = c1_circle.projectionOn(leftNormal); var c1_circle_onLine:Number = c1_circle.projectionOn(line); //if collision happened, undo movement if (Math.abs(c1_circle_onNormal) <= circles[i].radius && line.dotProduct(c1_circle) > 0 && c1_circle_onLine < line.getMagnitude()) //redefine velocity var v_leftNormSeg2:Vector2D = leftNormal.clone(); var leftNormSeg2_mag:Number = Math.abs(velos[i].projectionOn(leftNormal)) v_leftNormSeg2.setMagnitude(leftNormSeg2_mag); velos[i] = velos[i].add(v_leftNormSeg2.multiply(2)); circles[i].x += velos[i].x; circles[i].y += velos[i].y;
Prendi nota che questa formula di riflessione è applicabile alla linea di qualsiasi sfumatura. In effetti, puoi programmare la tua linea per essere regolabile in fase di esecuzione e vederla riflettere cerchi come la presentazione Flash di seguito. Basta cliccare e trascinare vicino all'estremità inferiore per ridefinirlo.
Il concetto di scorrimento lungo la linea è quasi identico al riflesso. Osservare lo schema qui sotto.
Il vettore della diapositiva è A '= A + V (Ap)
con V (Ap)
rappresenta un vettore con magnitudine di UNp
. Di nuovo, per ottenere Ap dovremo proiettare A sulla sinistra normale.
Si noti che mentre il cerchio scorre lungo la linea, è in collisione con la linea. Naturalmente, i punti di collisione differiscono tra i cerchi che si scontrano sulla linea, quindi alcuni si sovrappongono alla linea mentre si muovono lungo di essa. Questo non sembra buono, quindi dovremo riposizionarli.
Ora, riposizioniamo i cerchi sulla linea mantenendo il loro contatto con la linea. Fare riferimento allo schema seguente.
Una variabile importante da calcolare è la proiezione di A lungo la linea. Il raggio del cerchio è facilmente disponibile, e abbiamo già B, quindi possiamo formare i vettori di B e C. L'aggiunta dei due ci darà A, la posizione esatta per riposizionare il cerchio. Semplice!
La seguente presentazione Flash è codificata secondo l'idea menzionata. Ma c'è un problema: i cerchi tremolano lungo la linea.
C'è un ultimo dettaglio che ci è mancato. Il diagramma sopra mostra la grandezza di C dovrebbe essere equivalente al raggio del cerchio. Tuttavia, questo posizionerà il cerchio al di sopra della linea. Poiché non vi è alcuna collisione rilevata, il cerchio cadrà nuovamente sulla linea, che a sua volta contrassegnerà il rilevamento delle collisioni e farà riposizionare il cerchio.
Questo ciclo si ripeterà fino a superare la fine del segmento di linea; il risultato visivo di questo ciclo è l'effetto tremolante.
La soluzione a questo problema è impostare la magnitudine di C su un valore leggermente inferiore al raggio del cerchio: (raggio di cerchio - 1)
, dire. Osserva sotto la demo Flash che utilizza questa idea:
Ecco quindi l'importante snippet di ActionScript per scorrere lungo la linea. Ho evidenziato le parti importanti.
aggiornamento della funzione privata (e: Event): void for (var i: int = 0; i < circles.length; i++) //calculating line's perpendicular distance to ball var c1_circle:Vector2D = new Vector2D(circles[i].x - x1, circles[i].y - y1); var c1_circle_onNormal:Number = c1_circle.projectionOn(leftNormal); var c1_circle_onLine:Number = c1_circle.projectionOn(line); //check for collision if (Math.abs(c1_circle_onNormal) <= circles[i].radius) //check if within segment //if within segment, reposition and recalculate velocity if (line.dotProduct(c1_circle) > 0 && c1_circle_onLine < line.getMagnitude()) //repostion circle var v_lineSeg:Vector2D = line.clone(); v_lineSeg.setMagnitude(c1_circle_onLine); var v_leftNormSeg1:Vector2D = leftNormal.clone(); v_leftNormSeg1.setMagnitude(circles[i].radius - 1); //v_leftNormSeg1.setMagnitude(circles[i].radius); //uncomment this to check out the error: jittering effect var reposition:Vector2D = v_lineSeg.add(v_leftNormSeg1) circles[i].x = x1+reposition.x; circles[i].y = y1+reposition.y; //redefine velocity var v_leftNormSeg2:Vector2D = leftNormal.clone(); var leftNormSeg2_mag:Number = Math.abs(velos[i].projectionOn(leftNormal)) v_leftNormSeg2.setMagnitude(leftNormSeg2_mag); var veloAlongLine:Vector2D = velos[i].add(v_leftNormSeg2); circles[i].x += veloAlongLine.x; circles[i].y += veloAlongLine.y; //if not in segment (e.g. slide out of segment), continue to fall down else circles[i].x += velos[i].x; circles[i].y += velos[i].y; //No collision in the first place, fall down else circles[i].x += velos[i].x; circles[i].y += velos[i].y;
Spero che questo sia utile. Grazie per aver letto. Chiedi se ci sono domande e ci vediamo al prossimo suggerimento.