The Math og Action av Curves: Stigninger og Normals
Del
Del
10
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Vi har taklet å tegne kurver, og finne sine kvadratiske og kubiske røtter, samt praktiske programmer for å bruke kvadratiske røtter i spill. Nå, som lovet, vil vi se på programmer for å finne kubikk La oss ta en titt én praktisk bruk av dette regnestykket: I denne demoen, den "skipet" spretter av kantene på SWF og kurven. Den gul prikk representerer det nærmeste punktet til skipet som ligger på kurven. Du kan justere formen på kurven ved å dra de røde prikkene, og justere bevegelsen av skipet ved hjelp av piltastene La oss vurdere situasjonen der et punkt ligger i nærheten av en kvadratisk kurve. Hvordan kan du beregne den korteste avstanden mellom punktet og kurven? Vel, la oss starte med Pythagoras teorem. \\ [ Du kan se at vi har byttet \\ (y_c \\) med den kvadratiske ligningen. På et øyeblikk, kan vi se den høyeste makt er 4. Dermed har vi en kvar Men før det, må vi forstå gradienter på en kurve .. . Før vi ser på problemet med å minimere en kvar ligningen, la oss prøve å forstå graderinger av en kurve. En rett linje har bare en gradient. Men en kvadratisk kurvens stigning er avhengig av hvilket punkt på kurven viser vi til. Sjekk ut Flash presentasjon under: Dra de røde prikkene rundt for å endre kvadratisk kurve. Du kan også spille med glidebryteren håndtak for å endre plasseringen av blå prikken langs x. Som den blå prikken endringer, så vil gradienten trukket Det er der kalkulus vil komme godt med. Du har kanskje gjettet at differensiere en kvadratisk likning vil gi deg gradient av kurven. \\ [ Så \\ (\\ frac {df (x)} {dx} \\) er gradienten til en kvadratisk kurve, og det er avhengig av den \\ (x \\) koordinat. Vel, bra vi har en metode for å håndtere dette: diff1. (X: Number) vil returnere verdien etter en enkelt differensiering For å trekke gradient, vil vi trenge en ligning for å representere linjen \\ (y = mx + c \\). Koordinaten til det blå punktet \\ ((x_p, y_p) \\) vil bli byttet ut i \\ (x \\), og \\ (y \\), og gradienten av linjen funnet gjennom differensiering vil gå inn \\ (m \\). Dermed y-skjæringslinje, \\ (c \\) kan beregnes gjennom noen algebra arbeid Sjekk ut AS3. Husk alltid av den omvendte y -akse av Flash koordinere plass som vist på bildet nedenfor. Ved første øyekast kan diagrammet på høyre virke som en negativ gradient - men på grunn av invertert y-aksen, det er faktisk en positiv gradient Det samme gjelder for minimumspunktet som angitt nedenfor.. På grunn av den omvendt Y-aksen, den minimumspunktet i kartesisk koordinatsystem plass (ved (0,0)) ser ut som et maksimum i Flash-koordinaten plass. Men ved å henvise til plasseringen av opprinnelse i Flash koordinere plass i forhold til den kvadratiske kurve, det er faktisk et minimumspunkt Nå la oss si Jeg er interessert i å finne den laveste punkt på en kurve - hvordan går jeg frem? Sjekk ut bildet nedenfor (begge tall er i samme koordinatsystem plass). For å få minimumspunktet, vil vi bare likestille \\ (\\ frac {df (x)} {dx} = 0 \\), siden per definisjon vi leter etter et punkt hvor gradienten er null. Men som vist ovenfor, viser det seg at den maksimale punkt på en kurve også tilfredsstiller denne betingelse. Så hvordan skal vi skille mellom disse to sakene? La oss prøve differensiering av andre grad. Det vil gi oss den frekvensen av endring av graderingen. \\ [ Jeg skal forklare med henvisning til bildet nedenfor (trukket i kartesisk koordinatsystem plass). Vi kan se at, som vi øke langs x-aksen, gradientsignalene endringer fra negativ til positiv. Så endringstakten bør være en positiv Vi kan også se at når \\ (\\ frac {df ^ 2 (x)} {dx ^ 2} \\) er positiv Det er et minimum punkt på kurven. Omvendt hvis kursen er negativ, er et maksimumspunktet stede Nå er vi klar til å løse problemet presenteres i trinn 1. Hent quartic ligning (hvor den høyeste grad er 4) vi ankom: \\ [ Det samme quartic ligningen, plottet Husk, vi er interessert i å finne bunnpunktet på denne kurven, fordi tilsvarende punkt på den opprinnelige kvadratisk kurve vil være punktet som er på minimum avstand fra den røde prikken. Så, la oss differensiere quartic funksjonen for å komme til gradient av denne kurven, og deretter sidestiller gradient av denne kvar funksjonen til null. Du vil se at gradienten er faktisk en kubisk funksjon. Jeg vil henvise interesserte lesere til Wolfram side; for denne opplæringen, vil jeg bare nappe et resultat av deres algebra hjemkomsten: \\ [ Løs for røttene til denne (ganske rotete) kubisk funksjon, og vi vil komme frem til koordinatene av de tre blå punktene som angitt ovenfor. Deretter hvordan filtrerer vi våre resultater for minimumspunktet? Husker fra forrige trinn som et minimumspunkt har en endringstakt som er positive. For å få denne omstillingstakt, differensiere kubisk funksjon som representerer gradient. Hvis frekvensen av endring for den gitte blå punktet er positiv, er det en av Som du samhandler med Flash-presentasjon, kan det være ganger hvor tre gule prikker vises på en gang. To av disse, falmet ut, se røttene innhentet fra beregningen, men avvist fordi de ikke er de nærmeste punkter på kurven til den blå prikken Først av alt, må vi trekke den kvadratiske kurve. Merk at matrisen m2 vil bli henvist til for videre beregning Og her er den som implementerer matematisk begrep forklart. c1 refererer til et punkt tilfeldig plassert på scenen. La oss gjøre bruk av dette konseptet til oppdage overlapping mellom en sirkel og en kurve Ideen er enkel:. hvis avstanden mellom den blå prikken og den gule prikken er mindre enn blå prikk radius, har vi en kollisjon. Sjekk ut demo nedenfor. De interaktive elementer er de røde prikkene (å kontrollere kurve) og den blå prikken. Hvis den blå prikken er å kollidere med kurven, vil det visne ut litt Vel, er koden ganske enkel. Sjekk ut hele kilde i CollisionDetection.as Så nå som vi vet når kollisjonen vil skje, la oss prøve å programmere noen kollisjon respons. Hva med retur av overflaten? Sjekk ut Flash presentasjon under. Du kan se skipet (trekant), er omgitt av en sirkel (gjennomskinnelig blå). Når sirkelen kolliderer med kurven, vil skipet sprette av overflaten Her er den Action å styre skipet Du kan se at tastaturkontrollene oppdaterer flagg for å indikere om venstre, opp, høyre eller ned tastene blir trykket. Disse flaggene vil bli fanget av enterframe hendelseshåndterer og oppdatere størrelse og retning av skipet Jeg har allerede dekket vektoren beregningen refleksjon vektor i dette innlegget. Her skal jeg bare dekke hvordan du skaffer normal vektor fra gradient. \\ [ Så Action nedenfor vil gjennomføre matematisk begrep forklart i forrige trinn. Sjekk ut de markerte linjene: Vel, takk for din tid! Hvis du har funnet dette nyttig, eller har noen spørsmål, ikke la noen kommentarer. Anmeldelser
røtter, samt kurver 'gradienter og normaler, som å lage gjenstander sprette av krumme flater. La oss gå
Eksempel
Trinn 1:. Korteste avstand til en Curve
Let \\ i \\ punktet \\ være \\ (x_p, \\ y_p) \\\\ Hotell og \\ samtale \\ i \\ nærmeste \\ punkt \\ på \\ i \\ kurve \\ (x_c, \\ y_c) \\\\
Deretter: \\\\
z ^ 2 = x ^ 2 + y ^ 2 \\\\
z ^ 2 = (x_c-x_p) ^ 2 + (y_c-y_p) ^ 2 \\\\
Gitt \\ y_c = ax_c ^ 2 + bx_c + c, \\\\
z ^ 2 = (x_c-x_p) ^ 2 + [(ax_c ^ 2 + bx_c + c) -y_p] ^ 2
\\]
ligningen. Alt vi trenger å gjøre er å finne en minimumspunktet i denne ligningen til å gi oss den korteste avstanden fra et punkt til et kvadratisk kurve.
Trinn 2: Gradient av en Curve
Trinn 3:. Gradient Gjennom Kalkulus
f (x) = ax ^ 2 + bx + c \\\\
\\ frac {df (x)} {dx} = 2ax + b
\\]
Var x: Number = s.valuevar y: Number = quadratic_equation.fx_of (s.value) point.x = x; point.y = y; /** * y = mx + c; * C = y - mx; < == bruke dette til å finne c * /var m: Number = quadratic_equation.diff1 (x); Var c: Number = y - m * x; graphics.clear (); graphics.lineStyle (1, 0xff0000); grafikk .moveTo (0, c), graphics.lineTo (stage.stageWidth, m * stage.stageWidth + c);
Trinn 4: Koordinatsystemer
Trinn 5:. Rate of Change for Gradient
\\ frac {df (x)} {dx} = 2ax + b \\\\
\\ frac {df ^ 2 (x)} {dx ^ 2} = 2a
\\]
verdi.
Trinn 6:. Tilbake til problemet
z ^ 2 = (x_c-x_p) ^ 2 + [(ax_c ^ 2 + bx_c + c) -y_p] ^ 2
\\]
\\ frac {d (z ^ 2)} {dx} =
2 (x_c-x_p) + 2 (ax_c ^ 2 + bx_c + c - y_p) (2ax_c + b) \\\\
\\ frac {d (z ^ 2)} {dx} = 2a ^ 2 (x_c) ^ 3 + 3ab (x_c) ^ 2 + (b ^ 2 + 2ac-2ay_p + 1) (x_c) + (bc-by_p-x_p) \\\\
Equate \\ gradient \\ til \\ 0\\\\
\\frac{d(z^2)}{dx}=0\\\\
2a^2(x_c)^3+3ab(x_c)^2+(b^2+2ac-2ay_p+1)(x_c)+(bc-by_p-x_p)=0\\\\
Compare\\ med \\ kubikk \\ ligningen \\\\
Ax ^ 3 + Bx ^ 2 + Cx + D = 0 \\\\
A = 2a ^ 2 \\\\
B = 3ab \\\\
C = b ^ 2 + 2ac-2ay_p + 1 \\\\
D = bc-by_p-x_p
\\]
minste poeng. For å få den
minimumspunktet, den som vi er interessert i, velger poenget med den høyeste frekvensen av endring
Trinn 7:. Eksempel på Output
< p> Så her er et eksempel implementering av ideen forklart ovenfor. Du kan dra de røde prikkene rundt for å tilpasse kvadratisk kurve. Den blå prikken kan også bli dratt. Når du flytter blå prikk, vil den gule flyttes slik at avstanden mellom de blå og gule prikker vil være minimum blant alle punkter på kurven.
Trinn 8:. Action Gjennomføring
< p> Så her er Action gjennomføringen av ovennevnte. Du finner hele manuset i Demo2.as.
privat funksjon redraw_quadratic_curve (): void {var cmd:.. Vector < int > = New Vector. ≪ int >; . Var coord: Vector < Number > Antall >;; = new Vector <. //tegne kurve; m1 = nye Matrix3d (curve_points [0] .x * curve_points [0] .x, curve_points [0] .x, 1, 0, curve_points [1] .x * curve_points [1] .x, curve_points [1] .x , 1, 0, curve_points [2] .x * curve_points [2] .x, curve_points [2] .x, 1, 0, 0,0,0,1); m2 = new Matrix3d (curve_points [0] .Y, 0, 0, 0, curve_points [1] .Y, 0, 0, 0, curve_points [2] .Y, 0, 0, 0, 0,0,0, 1) m1.invert (); m2.append (m1); quadratic_equation.define (m2.n11, m2.n21, m2.n31); for (var i: int = 0; i < stage.stageWidth; i + = 2) {if (i == 0) cmd.push (1); annet cmd.push (2); coord.push (i, quadratic_equation.fx_of (i)); } Graphics.clear (); graphics.lineStyle (1); graphics.drawPath (cmd, koord);}
privat funksjon recalculate_distance (): void {var a: Number = m2.n11; Var b: Number = m2.n21; Var c: Number = m2.n31; /* f (x) = Ax ^ 3 + Bx ^ 2 + Cx + D * /var A: Number = 2 * a * a Div B: Number = 3 * b * en VAR C: Number = b * b + 2 * c * a - 2 * a * c1.y 1 Div D: Number = c * b - b * c1.y - c1.x quartic_gradient = new EqCubic (); quartic_gradient.define (A, B, C, D); quartic_gradient.calcRoots (); røtter = quartic_gradient.roots_R; Var valgt: Antall = røtter [0]; hvis {//beregne gradient og frekvensen av gradient av all fast røtter Var quartic_rate (isNaN (røtter [1]) &; & isNaN (røtter [2])!). Vector < Number > Antall >;; = new Vector <. for (var i: int = 0; i < roots.length, jeg ++) (! isNaN (røtter [i])) {if quartic_rate.push (quartic_gradient.diff1 (røtter [i])); annet roots.splice (i, 1); } //Velge roten som skal produsere den korteste distansen for (var j: int = 1; j < roots.length; j ++) {//frekvensen som tilsvarer med roten må være den høyeste positiv verdi //fordi det vil korrespondere med minimumspunktet if (quartic_rate [j] > quartic_rate [j - 1]) {valgt = røtter [J]; }} //Plassere ekstra røtter i demo position_extras (); } Else {//fjerne de ekstra røtter i demo kill_extras (); } Intersec_points [0] .x = valgte intersec_points [0] .Y = quadratic_equation.fx_of (valgt);}
Trinn 9: Eksempel: Collision Detection
Trinn 10:. Action Implementering
graphics.moveTo (intersec_points [0] .x, intersec_points [0] .Y); graphics.lineTo (c1.x, c1.y); Var avstand. Number = Math2.Pythagoras (intersec_points [0] .x, intersec_points [0] .Y, c1.x, c1.y) if (avstand < c1.radius) c1.alpha = 0,5; annet c1.alpha = 1,0; t. text = distance.toPrecision (3);
Trinn 11: Bouncing Off the Curve
Trinn 12:.. Styre Ship
offentlig funksjon CollisionDetection2 () {/** * forekomst av skipet & sin blå-ish sirkulært område * /skip = new Triangle (); addChild (skip); ship.x = Math.random () * stage.stageWidth; ship.y = stage.stageHeight * 0,8; c1 = new Circle (0x0000ff, 15); addChild (c1); c1.alpha = 0,2; /** * Skipets hastighet * /velo = new Vector2D (0, 1); updateShip (); stage.addEventListener (KeyboardEvent.KEY_DOWN, handleKey); stage.addEventListener (KeyboardEvent.KEY_UP, handleKey); stage.addEventListener (Event.EXIT_FRAME, handleEnterFrame); /** * Kurven og beregningene * /quadratic_equation = new EqQuadratic (); curve_points = new Vector. < Circle >; befolker (curve_points, 0xff0000, 3); intersec_points = new Vector. < Circle >; befolke (intersec_points, 0xffff00, 3, false); redraw_quadratic_curve ();} private funksjon handleKey (e: KeyboardEvent): void {if (e.type == "keyDown") {if (e.keyCode == Keyboard.UP) ISUP = true; else if (e.keyCode == Keyboard.DOWN) isDown = true; if (e.keyCode == Keyboard.LEFT) isLeft = true; else if (e.keyCode == Keyboard.RIGHT) isright = true; } If (e.type == "keyUp") {if (e.keyCode == Keyboard.UP) ISUP = false; else if (e.keyCode == Keyboard.DOWN) isDown = false; if (e.keyCode == Keyboard.LEFT) isLeft = false; else if (e.keyCode == Keyboard.RIGHT) isright = false; }} privat funksjon handleEnterFrame (e: Hendelses): void {/** * Styr omfanget * /if (ISUP) velo.setMagnitude (Math.min (velo.getMagnitude () + 0,2, 3)); else if (isDown) velo.setMagnitude (Math.max (velo.getMagnitude () - 0,2, 1)); /** * Styr retningen * /if (isright) velo.setAngle (velo.getAngle () + 0,03); else if (isLeft) velo.setAngle (velo.getAngle () - 0,03); recalculate_distance (); if (avstand < c1.radius) bounce (); updateShip ();} /** * Oppdater skipets posisjon, orientering og det er området (den blå-ish sirkel) * /private funksjon updateShip (): void {ship.x + = velo.x; ship.y + = velo.y; ship.rotation = Math2.degreeOf (velo.getAngle ()); c1.x = ship.x; c1.y = ship.y; if (ship.x > stage.stageWidth || ship.x < 0) velo.x * = 1; if (ship.y > stage.stageHeight || ship.y < 0) velo.y * = 1;}
Trinn 13:. Beregne Reflection Vector
\\ frac {df (x)} {dx} = gradient \\\\
linje \\ gradient = \\ frac {y} {x} \\\\
Anta \\ gradient = 0,5 \\\\
y = 0,5 \\\\
x = 1 \\\\
Vector \\ av \\ venstre \\ normal =
\\ begin {bmatrix} -1 \\\\ 0.5 \\ end {bmatrix} \\\\
Vector \\ av \\ right \\ normal =
\\ begin {bmatrix} 1 \\\\ - 0.5 \\ end {bmatrix}
\\]
Trinn 14: Action Gjennomføring
privat funksjon sprett (): void {var gradient: Number = quadratic_equation.diff1 (intersec_points [0] x); Var grad_vec: Vector2D = new Vector2D (1, gradient); Var left_norm: Vector2D = grad_vec.getNormal (false); Var right_norm: Vector2D = grad_vec.getNormal (); Var chosen_vec: Vector2D; if (velo.dotProduct (left_norm) > 0) chosen_vec = left_norm annet chosen_vec = right_norm Var chosen_unit: Vector2D = chosen_vec.normalise (); Var proj: Number = velo.dotProduct (chosen_unit); chosen_unit.scale (-2 * proj); velo = velo.add (chosen_unit);}
Konklusjon