Predicting Kollisjons Points Med Math i AS3
4
Del
7
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Dette innlegget er en del av en serie som heter Collision Detection og Reaction.Pixel-Level Kollisjon DetectionPixel-Level Collision Detection Basert på Pixel Farger
I min forrige tutorial om kollisjoner mellom en sirkel og en linje, i dekket fremspring på en linje ved hjelp av prikk-produktet av en vektor. I denne opplæringen, skal vi se på vinkel dot produktet og bruker det til å forutsi skjæringspunktet for to linjer.
Endelig resultat Forhåndsvisning
La oss ta en titt på det endelige resultatet vi skal jobbe mot. Bruk venstre og høyre piltaster for å styre skipet (trekant), og trykk opp til å øke hastigheten midlertidig. Dersom den beregnede fremtidige kollisjonspunktet er på veggen (linjen), vil en rød prikk males på den. For en kollisjon som "allerede" har skjedd (dvs ville ha skjedd i det siste, basert på gjeldende retning), vil en rød prikk fortsatt males men litt gjennomsiktig.
Du kan også museklikk og dra den svarte punkter for å bevege veggen. Vær oppmerksom på at vi ikke bare forutsi plasseringen av kollisjonen, men også tiden
Trinn 1:. Revision
Før du får inn i temaet, la oss gjøre noen revisjon. Her er prikk-produktet ligning (tidligere dekket her):
Og her er vinkelrett dot produktet definisjon hentet fra Wolfram:
Trinn 2: Vinkelrett Dot Product
nå for å hjelpe oss å danne et mentalt bilde, har jeg forberedt på bildet nedenfor. Jeg er sikker på dette punktet du er i stand til å utlede de vertikale og horisontale komponenter av en vektor, så komponentene som involverer sinus og cosinus bør ikke være en utfordring.
La oss erstatte både komponenter med tilsvarende. Jeg har brukt en med en lue å representere enhetsvektoren fra A (det vil si en vektor som peker i samme retning som A, men har en størrelse på nøyaktig 1). En annen detalj er at vinkelrett på B er faktisk riktig normal av B - mer om normaler neste trinn
Fra diagrammet ovenfor kan vi se at projeksjonen av B på A vil produsere |. B | * cos ( theta). Men hvorfor skulle projeksjonen av B normale råvarer | B |? * Sin (theta)
For å bedre forstå dette, jeg har tatt med en Flash demo nedenfor. Klikk og dra den svarte pilspiss. Som du forsiktig flytte den om, vil du legge merke til at det er vinkelrett akse følger også. Som de slår, fet røde linjene skal også være animert. Merk at disse to har samme lengde - derav ligningen for vinkel dot produktet
Trinn 3:. Normals
Normals, per definisjon, ligge på en vinkelrett linje kryssende linje med interesse. La oss prøve å forestille seg disse linjer på en geometrisk plan.
kartesisk koordinatsystem brukes i diagrammet ovenfor. B er den venstre normale og C er den riktige normale. Vi ser at x-komponenten av B er negativ (fordi det peker til venstre) og y-komponenten i C er negative (fordi det peker nedover).
Men sjekk ut likheter mellom B og C . Deres x og y-komponentene er de samme som A, bortsett stokket. Forskjellen er bare plasseringen av skiltet. Så vi kommer til en konklusjon av bildet nedenfor.
Legg merke til at vi henviser spesielt til kartesiske for å finne ut poenget med kollisjon av vektor k på planet A, skal vi koble opp hale Den røde prikken på bildet under er kollisjonspunktet. Og jeg håper du kan se lignende trekanten i figuren nedenfor. så gitt de tre komponentene ovenfor, kan vi benytte begrepet forhold for å utlede lengden mellom de røde og blå punkter. Til slutt satt vi omfanget av vektoren k til nevnte lengde og vi har vår kollisjonspunktet Så her kommer Action gjennomføring. Jeg har tatt en demo nedenfor. Prøv å flytte pilspisser, slik at begge linjene krysser hverandre. En liten svart prikk vil markere skjæringspunktet mellom linjene. Merk at disse segmentene er ikke nødvendigvis kryssende, men de uendelige linjer de representerer er. Her er skript som gjør beregningene. Sjekk ut Basic.as i kilde nedlasting for hele manuset Så jeg håper den første tilnærmingen jeg har presentert var lett å forstå. Jeg forstår ytelse i å få skjæringspunktet er viktig, så neste jeg skal gi alternative tilnærminger, selv om det vil kreve noen matematiske revisjoner. Bære med meg! Først, la oss snakke om linje ligninger. Det finnes flere former for linjeligningen, men vi må bare ta på to av dem i denne opplæringen: Jeg har tatt bildet nedenfor for å hjelpe deg å huske. De som er interessert i dette kan referere til dette innlegget på Wikipedia Før vi utføre noen manipulasjoner på to linje ligninger, må vi utlede følgende linjer ligningene først . La oss vurdere situasjonen der vi får koordinatene til to poeng p1 (a, b). og p2 (c, d). Vi kan danne en linje likning som forbinder disse to punktene fra graderinger: Deretter bruker denne ligningen, kan vi utlede konstanter A, B, og C for standard form: Neste, vi kan fortsette å løse samtidige linjer ligninger nå som vi kan danne linjer ligninger, kan fortsette å ta to linjer likninger og løse dem simutaneously. Gitt disse to linje ligninger: Jeg skal bord disse koeffisienter i henhold til den generelle formen ax + by = C. for å få verdien av y, gjør vi følgende: Og vi kommer til tabellen nedenfor. Flytte på å få x: Vi kommer på tabellen Etter at vi trekker de to ligningene ut, kommer vi til: La oss videre omorganisere y Så vi kommer til skjæringspunktet mellom x og y. Vi legger merke til at de har samme nevner nå som vi har jobbet ut matematiske operasjoner og fått resultatet, bare nappe verdier i og vi har skjæringspunktet Her er Actionscript gjennomføring. Så alle vektor operasjoner er redusert til enkle aritmetiske men det vil kreve noen algebra hjemkomsten utgangspunktet Det er selvfølgelig det samme resultat som forrige demo, bare med mindre matematikk involvert, og uten bruk av Vector2D klasse Et annet alternativ for å løse dette problemet er ved bruk av matrisen matte. Igjen, jeg invitere interesserte lesere til å dykke inn i Prof. Wildberger foredrag på ligninger av linjer. Her vil vi bare bris gjennom konseptet raskt Ifølge professor Wildberger, er det to rammer vi kan vedta. La oss gå gjennom den kartesiske først. Sjekk ut bildet nedenfor. Merk at matrisen T og S inneholder konstante verdier. Hva er igjen ukjente er A. Så omorganisere matriseligningen i form av A vil gi oss resultatet. Men vi må få den inverse matrisen til T. Her er gjennomføringen av ovennevnte med Action: Til slutt, det er parametrisk form av linjen ligningen, og vi skal forsøke å løse det gjennom matrisen matematikk igjen Vi ønsker å finne skjæringspunktet. Gitt all informasjon med unntak av u og v som vi forsøker å finne, skal vi skrive om både ligningene i matriseform og løse dem Så igjen, vi utføre matrise manipulasjoner for å komme frem til vårt resultat Så her er gjennomføringen av matriseform: Vi har dekket fire måter å løse dette lille problemet. Så hva med ytelse? Vel jeg tror jeg vil bare la denne saken til leserne å bedømme, selv om jeg tror forskjellen er ubetydelig. Føl deg fri til å utnytte denne ytelsestesting sele fra Grant Skinner. Så nå som vi har fått denne forståelsen, hva blir det neste? Bruk den Anta en partikkel beveger seg i en bane bundet til å kollidere med en vegg. Vi kan beregne tiden til å påvirke ved enkel ligning av: Velocity = Displacement /tid Tenk deg at du er inne i denne oransje runde partikkel og for hver bestått ramme og meldingen er offentliggjort på tid til å kollidere med vegg. Du vil høre: "Tid til å påvirke: 1,5 frames" - Ramme en "Tid til å påvirke: 0,5 frames" - Ramme 2 "Tid til å påvirke: -0.5 frames "- ramme 3 Når vi nå ramme 3, kollisjon med linjen allerede har skjedd (som indikert av minustegn). Du må spole tilbake tiden for å nå det punktet av kollisjonen. Tydeligvis kollisjon skulle skje en gang mellom Frames to og tre, men Flash beveger seg i intervaller ramme. Så hvis kollisjonen skjedde halvveis mellom rammer, vil en flip av skiltet til negative indikere at kollisjonen allerede har skjedd For å få negativ tid , vil vi bruke vektor dot produktet. Vi vet at når vi har to vektorer, og retningen av en ikke ligger innenfor 90 grader på hver side av den andre, vil de frembringe et negativt dot produkt. Dessuten er dot produkt er et mål på hvor parallell to vektorer er. Så når kollisjon allerede har skjedd, vil hastigheten og retning av en vektor til et punkt på veggen være negativ - og vice versa Så her er det. script (inkludert i CollisionTime.as). Jeg har også lagt dueller innenfor linjestykke her. For de som synes det er uvant, ikke referere til min tutorial på dueller mellom en sirkel og et linjestykke, trinn 6. Og for å få hjelp på styring skip, her er en annen referanse Så her er en demo av det du vil ankomme. Bruk venstre og høyre piltaster for å styre skipet (trekant), og trykker Opp for å øke hastigheten midlertidig. Dersom det forutsagte fremtidige kollisjonspunktet er på veggen (linjen), vil en rød prikk males på den. For kollisjon som har "allerede" har skjedd, vil en rød prikk fortsatt males men litt gjennomsiktig. Du kan også dra de sorte prikkene hver side av veggen for å flytte den. Så jeg håper denne opplæringen har vært lærerikt. Må dele hvis du faktisk har brukt denne ideen andre steder fra den jeg har nevnt. Jeg planlegger en kort skrive opp på å bruke den til å male laser mål - hva tror du? Takk for lesing og gi meg beskjed hvis det er noen feil.
koordinatsystem i dette eksempelet. Y-aksen av Flash koordinatsystem plass er en refleksjon av den i kartesiske, noe som resulterer i et bytte mellom venstre og høyre normal
Trinn 4:. Prosjektering Point of Kollisjon
av k med en vilkårlig punkt på planet A først. For saken nedenfor, er vektor j knytte vektor; så vi får vinkelrett projeksjon av k og j på planet A.
| k |, størrelsen på vektoren k
Lengde på j på vinkelrett på planet A
Lengde på k på vinkelrett på planet A
Trinn 5: Action Implementering
privat funksjon rekalkulering (): void {reorientere ();. /* Forklar: * v1 & v2 er vektorer for å representere både linjesegmenter * v1 tiltrer set1b (halen) til set1a (hode) - analogt til vektor k i diagrammet * v2 blir set2b (halen) til set2a (hodet) * toV2b er vektor analogt med vektor j i diagrammet * /var perp1: Number = v1.perpProduct (v2.normalise ()); Var toV2b: Vector2D = new Vector2D (set2b.x - set1b.x, set2b.y - set1b.y); Var perp2: Number = toV2b.perpProduct (v2.normalise ()); /* Forklar: * lengde beregnes fra lignende trekanter forholdet * det er senere brukt som magnitude for en vektor * som peker i v1 retning * /var Lengde: Antall = perp2 /perp1 * v1.getMagnitude (); Var length_v1: Vector2D = v1.clone (); length_v1.setMagnitude (lengde); /* Forklar * utvide for å finne den nøyaktige plasseringen av kollisjonspunktet * /intersec.x = set1b.x + length_v1.x; intersec.y = set1b.y + length_v1.y;}
Trinn 6: Linje ligninger
Generelt skjema
avsnitt ovenfor
Trinn 7:. Utlede Standard Form
Trinn 8:. løse likninger
Ex + Fy = G
Px + Qy = R
ABCEFGPQR
Multipliser gjensidige koeffisientene til x for hele ligningen
Ordne innhentet ligningen med hensyn på y.
ABCMultiply byEFGPPQRE
ABCEPFPGPPEQERE < p> Etter at vi trekker to likninger ut, kommer vi til:
y (FP - QE) = (GP - RE), som ordner til:
y = (GP - RE) /(FP - QE)
ABCMultiply byEFGQPQRF
ABCEQFQGQPFQFRF
x (EQ - PF) = (GQ - RF), som ordner til:
x = (GQ - RF) /(EQ - PF )
y = (GP -. RE) /(FP - QE)
y = (GP - RE) /- (QE - FP)
y = (RE - GP) /(QE - FP)
x = (GQ - RF). /(EQ - PF)
y = (RE - GP) /(QE - FP) < .no>
Trinn 9:. Bruk Bort Action
privat funksjon rekalkulering (). Void {reorientere (); Var E: Antall = set1b.y - set1a.y; Var F: Antall = set1a.x - set1b.x; Var G: Number = set1a.x * set1b.y - set1a.y * set1b.x; Var P: Number = set2b.y - set2a.y; Var Q: Number = set2a.x - set2b.x; Var R: Number = set2a.x * set2b.y - set2a.y * set2b.x; Var evner: Number = (E * Q - P * F); intersec.x = (G * Q - R * F) /evner; intersec.y = (R * E - G * P) /evner;}
Trinn 10: matrise alternative
parameteriserte vektor rammeverk
Trinn 11: Implementering Med AS3
privat funksjon rekalkulering (): void {reorientere (); Var E: Antall = set1b.y - set1a.y; Var F: Antall = set1a.x - set1b.x; Var G: Number = set1a.x * set1b.y - set1a.y * set1b.x; Var P: Number = set2b.y - set2a.y; Var Q: Number = set2a.x - set2b.x; Var R: Number = set2a.x * set2b.y - set2a.y * set2b.x; Var T: Matrix = ny Matrix (E, P, F, Q); T.invert (); Var S: Matrix = new Matrix (); S.à = G; S.b = R; S.concat (T); //Multiplisere matrisen intersec.x = S.à; intersec.y = Sb;}
Trinn 12: Parametrisk Form
.
Trinn 13:. Matrix Manipulasjon
Trinn 14:. implementering med AS3
rivate funksjon rekalkulering (): void {reorientere (); /* Forklar: * r, s er faktisk henviser til komponenter av v2 normalisert * p, q er faktisk henviser til komponenter av v1 normalisert * /var norm_v2: Vector2D = v2.normalise (); Var norm_v1: Vector2D = v1.normalise (); Var a_c: Number = set1b.x - set2b.x; Var b_d: Number = set1b.y - set2b.y; Var R: Matrix = ny Matrix; R.a = norm_v2.x; R.c = norm_v1.x; R.b = norm_v2.y; R.d = norm_v1.y; R.invert (); Var L: Matrix = ny Matrix; L.a = a_c; L.b = b_d; L.concat (R); intersec.x = set2b.x + L.a * norm_v2.x; intersec.y = set2b.y + La * norm_v2.y;}
Trinn 15: Ytelse
Trinn 16: Å forutsi Kollisjon Tid
Trinn 17:. Negativ Tid
Trinn 18: Action Implementering
//avgjøre om innenfor veggen segmentvar w2_collision. Vector2D = ny Vector2D (collision.x - w2.x, collision.y - w2.y); collision.alpha = 0; //når skipet er på vei til venstre wallif (w2_collision.dotProduct (v1) < 0) {t .text = "Ship er på vei til venstre av veggen";} else {//når skipet er på vei til høyre for veggen hvis (w2_collision.getMagnitude () > v1.getMagnitude ()) {t.text = "Ship er på vei til høyre for muren "} //når skipet er på vei til vegg segment annet {var ship_collision: Vector2D = new Vector2D (collision.x - ship.x, collision.y - ship.y); Var forskyvning: Number = ship_collision.getMagnitude (); if (ship_collision.dotProduct (velo) < 0) forskyvning * = 1; //Viser tekst Var tid: Number = forskyvning /velo.getMagnitude (); t.text = "Rammer til å påvirke:" + time.toPrecision (3) + "rammer \\ n."; gang /= stage.frameRate; t.appendText ( "Tid til å påvirke:" + time.toPrecision (3) + ". sekunder \\ n"); //Falle ned alpha hvis kollisjonen hadde skjedd hvis (forskyvning > 0) collision.alpha = 1; else {collision.alpha = 0,5; t.appendText ( "Collision allerede hadde skjedd.")}}}
Trinn 19: Endelig resultat
Konklusjon