Suggerimento rapido reazione di collisione tra un cerchio e un segmento di linea

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.


Anteprima del risultato finale

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:


Passaggio 1: la formula di riflessione

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.


Passaggio 2: implementazione

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;  

Passaggio 3: una versione interattiva

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.


Passaggio 4: scorrimento lungo la linea

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.


Passaggio 5: ridefinire la posizione

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:


Passaggio 6: implementazione

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;   

Conclusione

Spero che questo sia utile. Grazie per aver letto. Chiedi se ci sono domande e ci vediamo al prossimo suggerimento.