În sfatul meu rapid anterior, am analizat ideea de detectare a coliziunilor în general și, în special, la detectarea coliziunilor dintre o pereche de cercuri. În acest sfat rapid, vom examina detectarea unei coliziuni între un cerc și o linie.
Acesta este rezultatul pe care îl vom lucra. Faceți clic pe butonul Restart pentru a repoziționa toate cercurile din partea de sus a scenei și urmăriți-le căderea.
Rețineți că cercurile se ciocnesc cu linia chiar și în afara segmentului care este desenat. Următorul Sfat rapid va arăta cum să remediați acest lucru.
Pentru a verifica dacă un cerc s-a ciocnit cu o linie, trebuie să verificăm lungimea perpendiculară de la linie la cerc. Respectați diagrama de mai jos.
Din diagrama de mai sus este clar că cazurile 3 și 4 ar trebui să detecteze o coliziune între cerc și linie. Deci, concluzionăm că dacă lungimea perpendiculară (marcată cu roșu) este egală sau mai mică decât raza cercului, o coliziune sa produs din cauza cercului care atinge sau suprapune linia. Întrebarea este, cum putem calcula această lungime perpendiculară? Ei bine, vectorii ne pot ajuta să ne simplificăm problema.
Pentru a trasa o linie pe scenă, avem nevoie de două coordonate (c1 și c2). Linia trasată de la c1 la c2 va forma un vector care indică c2 (Notați direcția săgeții).
În continuare, trebuie să găsim linia normal. Linia normală este o altă linie care face 90 ° cu linia originală și intersectează cu ea într-un punct. În ciuda faptului că linia normală este o altă linie, forma normală a vectorului poate fi identificată în continuare ca fiind stânga sau dreapta normală față de vectorul liniei. Normalul stâng este vectorul de linie însuși, rotit -90 °. Dreapta normală este aceeași, dar se rotește la 90 °. Rețineți că axa y din spațiul coordonatelor Flash este inversată în comparație cu axa y pe un grafic tipic - astfel încât rotirea pozitivă este în sensul acelor de ceasornic și rotația negativă este în sens contrar acelor de ceasornic.
Norma stângă este utilizată în încercarea noastră de a calcula lungimea perpendiculară dintre cerc și linie. Detalii se găsesc în diagrama de mai jos. A se referă la un vector care indică c1 în cerc. Lungimea perpendiculară se referă efectiv la vectorul A proeminență pe stânga normală. Rezultă această proiecție folosind trigonometria: este | A | Cosine (theta)
, Unde | A |
se referă la magnitudinea vectorului A.
Abordarea cea mai simplă este de a utiliza operațiile vectoriale, în special produsul dot. Pornind de la ecuația produsului punct, rearanjăm termenii astfel încât să ajungem la a doua expresie prezentată mai jos. Rețineți că partea dreaptă a celei de-a doua ecuații este proiecția pe care am dorit să o calculam!
Rețineți, de asemenea, că partea stângă și cea dreaptă a ecuației va produce, în cele din urmă, același rezultat, deși diferit în abordările lor. Deci, în loc să folosim partea dreaptă a ecuației, putem opta pentru partea stângă a ecuației. Pentru a ajunge cu ușurință la rezultatul final, este favorabil să folosiți stânga, deoarece variabilele pot fi rezolvate cu ușurință. Dacă insistăm să folosim dreptul la ecuație, ar trebui să împingem ActionScript prin munca matematică riguroasă în calculul tetei unghiului. Încheiem cu diagrama de mai jos.
(* Notă suplimentară: Dacă cercul cade sub vectorul liniei, lungimea perpendiculară calculată din formula din diagrama de mai sus va produce o valoare negativă.)
Acum, că am înțeles abordarea matematic, să continuăm să o implementăm în ActionScript. În această primă secțiune, rețineți că vectorul liniei este rotit -90 ° pentru a forma normalul stâng.
// declararea coordonatelor x1 = 50; y1 = 100; x2 = 250; y2 = 150; // desen linie graphics.lineStyle (3); graphics.moveTo (x1, y1); grafice.lineTo (x2, y2) // formarea vectorilor de linie linia = vector2D noi (x2 - x1, y2 - y1); leftNormal = line.ro (Math.PI * -0.5);
În această a doua secțiune, am subliniat calculele menționate și condiția de a verifica coliziunea dintre cerc și linie.
actualizarea funcției private (e: Event): void pentru (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); circles[i].y += 2; //if collision happened, undo movement if (Math.abs(c1_circle_onNormal) <= circles[i].radius) circles[i].y -= 2;
Pentru cei care ar dori să investigheze în continuare, următoarele sunt fragmente de metode utilizate în Vector.as
/ ** * Metoda de obținere a proiecției vectorului curent pe o anumită axă * @ axa paramului O axă unde vectorul este proiectat pe * @backurn Lungimea de proiecție a vectorului curent pe axa dată * / proiecția funcției publiceOn (axa: Vector2D): Numărul return this.dotProduct (axis.normalise ())
/ ** * Metoda de a efectua produsul punct cu un alt vector * @ param vector2 Un vector pentru a efectua produsul punct cu vectorul curent * @ return Un număr scalar de produs punct * / funcția publică dotProduct (vector2: Vector2D): Numărul var componentX: Numărul = this._vecX * vector2.x; var componentY: Numărul = this._vecY * vector2.y; retur componentaX + componentY;
/ ** * Metoda de obținere a vectorului unic al vectorului curent * @return O copie a vectorului normalizat * / funcția publică normalize (): Vector2D returnează vectorul Vector2D (this._vecX / this.getMagnitude (), this._vecY / this. getMagnitude ())
/ ** * Metoda de obținere a magnitudinii actuale a vectorului * @return Mărimea tipului Number * / funcția publică getMagnitude (): Număr return Math.sqrt (_vecX * _vecX + _vecY * _vecY);
Apăsați butonul Restart pentru a repoziționa toate cercurile din partea de sus a etapei. Rețineți că coliziunea se situează între întreg (inclusiv secțiunea care nu este desenată) și cercurile. Pentru a limita doar coliziunea la segmentul de linie, păstrați acordul pentru următorul Sfat rapid.
Vă mulțumim pentru lectură. Rămâi acordat pentru următorul sfat.