Simulate prosjektil Motion med Actionscript 3.0
3
Del
Del
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 You Do The Math.Quick. Tips: Trigonometri for Flash Game DevelopersCreating generativ kunst med HYPE
I denne opplæringen kommer jeg til å ta deg gjennom prosessen simulere grunnleggende prosjektil bevegelse ved hjelp av Flash og Actionscript. Vår simulering vil dynamisk animere den første banen til et prosjektil, og den påfølgende spretter mot bakken.
Det endelige resultatet
Her er en rask forhåndsvisning av hva vi skal jobbe mot:
Innledning
Et av elementene som gjør moderne videospill så realistisk er deres fysikk simulering. Ved å anvende begreper i klassisk mekanikk til våre Flash-animasjoner, kan vi skape fantastiske visuelle effekter som forbedrer den totale brukeropplevelsen.
I denne opplæringen kommer jeg til å ta deg gjennom prosessen med å simulere grunnleggende prosjektil bevegelse ved hjelp av Flash og Actionscript. Vår simulering vil dynamisk animere den første banen til et prosjektil, og den påfølgende spretter mot bakken. For å holde ting enkelt jeg har ikke tatt med luftmotstand, slik eksempelet prosjektil vil bare oppleve én kraft; tyngdekraften. Denne opplæringen forutsetter at du har noen grunnleggende kunnskaper om objektorientert programmering og Actionscript. Du kan også dra nytte av å ha noen erfaring med kvadratiske funksjoner, og grunnleggende begreper i bevegelse som akselerasjon Hotell og hastighet Klassisk mekanikk er den grenen fysikk basert på Newtons bevegelseslover. I denne opplæringen skal vi se på to begrepene klassisk mekanikk: prosjektil bevegelse, og koeffisienten til restitusjon. Prosjektil bevegelse beskriver banen (banen) av et objekt med en første hastighet, mens opplever akselerasjon fra tyngdekraften (og i de fleste tilfeller luftmotstand). Du er sikkert kjent med historien om Newton formulere sin teori om tyngdekraften mens du sitter under et epletre. Gravity spiller en stor rolle i prosjektil bevegelse, siden det legger en konstant akselerasjon på -9,8 m /s 2 i y-retning. Et godt eksempel på prosjektil bevegelse er et baseball blir kastet i luft. Når du kaster en baseball, den har en utgangshastighet og retning i det øyeblikket den forlater hånden. Disse to egenskapene gjør opp ballens utgangshastighet. Etter at ballen forlater hånden, følger det en bue formet bane, også kjent som sin bane. Den generelle banen til et prosjektil kan beskrives ved en kvadratisk funksjon: Denne funksjonen gir oss posisjonen av et prosjektil med hensyn til tid ( d (t) For å bruke denne funksjonen vi trenger å vite:. Banen til et prosjektil i x- og y-retningene er uavhengige. Dette betyr at for å beregne posisjonen i en to-dimensjonale rommet, må vi bruke funksjonen to ganger. Det andre konseptet vi skal se på er noe som heter koeffisient restitusjon For eksempel, hvis du sprette en basketball mot gulvet, høyden den spretter avtar med hver påfølgende sprett. Denne endringen i høyden (direkte relatert til endringen i hastighet), er konstant og kan derfor beskrives ved koeffisient restitusjon Her v 1 Siden koeffisient av restitusjon La oss begynne å bygge denne tingen! Åpne opp Flash, og opprette et nytt dokument. I eksempelet vil jeg bruke dimensjonene standard av 550 x 400, og en bildefrekvens på 50 FPS. Lagre denne filen under et annet navn. Deretter må vi opprette et dokument klasse. Opprett en ny Actionscript-fil, og legge til følgende: Lagre denne filen i samme katalog som vår FLA. Kall det Main.as Det siste vi trenger å gjøre er å knytte dokumentet klasse med FLA. Inne i FLA, finn Egenskaper For mer informasjon om bruk av et dokument klasse, kan du se i denne hurtig Tip. Nå som vår flash dokumentet er satt opp, kan vi starte koding. Det første vi må gjøre er å lage en løkke som vil kjøre på et fast tidsintervall. Generelt sett er det to tankerekker om tidsbestemt loops: ved hjelp av ENTER_FRAME Vi må begynne ved å importere to klasser:. Timer Anmeldelser klasse, og dets respektive Timerevent Før vi setter opp Timer Nå kan vi sette opp Timer! Vi kommer til å begynne med å legge to eiendommer til klassen: masterTimer Neste vi skal for å fylle disse egenskapene inne i vårt konstruktør metode, Hoved Timer genererer en TimerEvent.TIMER Det eneste gjenværende er å starte Timer Hvis vi spore currentTime Test filmen. Output log bør se omtrent slik ut: Siden vi vet Timer fungerer, vi kan fjerne spor uttalelse Vårt neste skritt er å lage en klasse som representerer et prosjektil (basketball). Opprett et annet Actionscript-fil, og nok en gang legge vår grunnleggende klassestrukturen. Lagre denne filen som Projectile.as Vi kommer til å begynne med å legge noen egenskaper for å holde oversikt over prosjektil egenskaper. Jeg vil forklare animasjon bestemte egenskaper senere. Resten bør du kjenne igjen fra ligningene i starten av opplæringen Siden dette Prosjektet bruker mye av beregninger, er det fornuftig å skrive et sett av praktiske metoder for de kjedelige beregninger som vil bli utført mange ganger. Nedenfor er seks dagligvare metoder som vil bli referert i hele resten av opplæringen Den første metoden, solveQuadratic Den andre metoden, getComponents Den tredje metoden, getPosition Den fjerde metoden, getTimes Den femte metoden, getVelocity Den sjette metoden, getVelocityDirection I trinn 4, la vi en haug med egenskaper til prosjektilet klassen. Hvis du lagt merke til, alle disse egenskapene er privat. Jeg gjorde dette fordi vi ikke ønsker å få tilgang til noen av dem direkte. Vi trenger fortsatt en vei å sette og preform de nødvendige beregninger på disse egenskapene, så vi kommer til å legge en init Navnene på de ulike parametrene bør være ganske opplagt. velocityDirection Jeg nevnte tidligere at vi har å gjøre med komponenter, bare godtar imidlertid vår init Nå vi har en matrise inneholdende de individuelle komponentene av vektorene. Vi kan nå lagre dem til sine tilsvarende egenskaper trenger poengene for utgangsposisjonen ikke trenger å endres Før vi fortsetter, jeg trenger å forklare animasjon spesifikke egenskaper vi opprettet i trinn 4. Jeg skal begynne med flytte Anmeldelser eiendom. Siden vår prosjektil har en hviletilstand, bruker vi den bevegelige eiendommen som et flagg så loopen bare animerer når prosjektilet er i bevegelse. Starttime Våre kontrollmetoder, i mangel av et bedre ord, vil for det meste, kalles fra i sløyfen. Disse tre første metodene er veldig enkelt, og brukes til å samhandle med animasjon spesifikke egenskaper Den siste metoden vi kommer til å legge fortjener det meste av vår oppmerksomhet. Som navnet antyder, positionAtTime Hvis du ser inne i denne metoden, bør du legge merke til et par ting. Denne første er bruken av en relativeTime Lagre prosjektilet klassen. Anmeldelser Før vi kan animere, trenger vi noe å animere. Hvis du lagt merke til, vår Prosjektil Åpne hovedblitsen dokumentet (FLA), og tegn en sirkel på scenen. Ikke bekymre deg for mye om størrelsen, siden vi kommer til å skalere det ned senere i kode. Deretter konvertere sirkelen til en MovieClip Nå må vi knytte vår Prosjektil klasse med MovieClip. I biblioteket høyreklikk (Kontroll klikk på Mac) din MovieClip og velger Heis ... Merk av i boksen ved siden av Eksporter for Action Klikk på OK Til slutt lagre dokumentet Vi har en loop, vi har skrevet vår Prosjektil klasse, og vi har koblet det med en MovieClip. Nå er det på tide å animere prosjektilet! Til å begynne, åpner vår dokument klasse, Main.as Vi skal begynne med å legge til noen flere eiendommer Formålet med disse egenskapene er ganske grei. skala Inne i konstruktør-metoden, kommer vi til å legge til følgende linjer i setup vår . Ball objekt Hvis du tester filmen, din Ballen skal vises i nederste venstre hjørne av scenen. Neste vi trenger å kjøre init Parametere for utgangsstilling krever noen enkle beregninger før de sendes videre til metoden. Prosjektilet metoder alle bruke meter som enhet av avstand, så vi må bruke vår målestokk. initialPositionY Nå som vår prosjektil er konfigurert, kan vi sette startFlag La oss gå videre til å sette opp sløyfen. Det første vi må gjøre er å legge en betinget utsagn som sjekker for startFlag Det er et par ting som er verdt å merke seg. Hvis du husker, vi allerede laget en variabel som heter currentTime Det ville være meningsløst for loopen til å beregne posisjonen til prosjektilet om det er i ro, så vi må legge til en annen betinget utsagn som sjekker om prosjektilet er flytting. Inne i denne uttalelsen kan vi gjennomføre selve animasjonen. Det første vi må gjøre er å få prosjektilet posisjon Når vi vet posisjonen, vi bare oppdaterer MovieClip Vi har endelig nådd en milepæl! Hvis du tester filmen nå, kan du se den grunnleggende effekt Vi har animert banen vår prosjektil, men du kan se ballen fortsetter å bevege på ubestemt tid. For å forbedre denne simuleringen, skal vi lage en bakken Vår tilnærming her innebærer implementering av dueller. Generelt sett har vi to alternativer for vår dueller: rammebaserte og prediktiv. Til syvende og sist er vi kommer til å bruke predicative dueller, men jeg tror det er verdt å forklare teorien bak hvert alternativ: Ideen bak rammebasert kollisjonsvarsling er enkel. Inne i loop, ville vi sjekke om ballens y-posisjon er under bakken er y-posisjon. Hvis betingelsen er oppfylt, har en kollisjon skjedd ... høres bra ut ikke sant? Ikke egentlig. Sjansen er at en kollisjon vil ikke skje på en eksakt Timer Selve kollisjonen ville ha funnet sted i mellom de to rammene. Men vår rammebasert dueller code ville bare har oppdaget at kollisjonen i den andre rammen, når prosjektilet skal allerede være på sin nye bane. Vi kan løse dette problemet ved hjelp av prediktiv dueller. Det kan være litt mer utfordrende å gjennomføre, men det gir oss et mer nøyaktig simulering. Predictive dueller fungerer som følger. Vi først beregne på forhånd, det nøyaktige tidspunktet at prosjektilet vil kollidere med jorden. Innenfor sløyfen vi sjekke om denne tiden har gått. Hvis det har, setter vi prosjektilet på en ny bane, som starter på det eksakte tidspunktet for kollisjonen. Første ting først, må vi legge noen flere metoder til vår Prosjektil (Husk, getTimes Vi er også nødt til å vite omfanget og retningen av vår hastighet på denne gangen, så legg disse to metodene for å beregne det også Før vi ender opp med denne klassen, jeg ønsker å legge til én metode som kalles getStartTime Lagre prosjektilet klasse og gå tilbake til dokumentet klassen.. Det første vi må gjøre er å legge til et par av eiendommer. En collisionTime Det første vi trenger å gjøre er å sette vår cor Nå for den morsomme delen! Inne i våre viktigste loop, må vi gjennomføre våre hoppende metoder. For det første finner betingelsen for startFlag Neste finne den tilstanden som sjekker ball.isMoving () Inside at kollisjonstilfelle, må vi utføre sprett. Dette oppnår vi ved å sette prosjektilet på en ny bane, som starter på collisionTime Neste vi trenger for å kjøre de riktige metodene for å sette den nye banen. For timeOfCollision Vi har nådd en milepæl! Hvis du tester filmen, bør du se hoppende effekt Hvis du tar en titt på eksempelet ovenfor, ballen aldri kommer til en fullstendig stopp. Mot slutten ser det ut til å ha en rask, nervøs bevegelse. Dette fenomenet skyldes følgende linje: Jeg skal forklare. Forutsatt cor Her er hvordan. Siden cor Hver en Herfra vi kan bruke formelen for summen av en uendelig geometrisk rekke å beregne vår stoppe tid: Formelen er enkel. a 1 Så vidt gjennomføringen går, vil vi begynne med å legge to flere eiendommer til dokumentet klassen Vi trenger å vite når den første sprett skjer, slik at sprett Deretter legger du til følgende på slutten av vår kollisjonstilfelle Hver gang det oppstår en kollisjon vi trenger for å sjekke om stoppingTime Det er det! Takk for lesing!
. Selv om jeg stort sett kommer til å være som dekker anvendelsen av disse begrepene som de gjelder for Flash og Actionscript, vil jeg først ta litt tid å kort forklare dem som de gjelder for klassisk mekanikk.
er den posisjon etter t Anmeldelser sekunder har passert). Den lille trekanten betyr "endring i", slik at At
betyr "antall sekunder bestått"
, av prosjektilet;
innledende hastighet (hastighet i en bestemt retning), v 1
, av prosjektilet;
Den opprinnelige posisjon, d 1
, av prosjektilet.
. Koeffisienten til restitusjon er et forholdstall for å beskrive forskjellen i et objekts hastighet før og etter en kollisjon.
. Beregning koeffisienten til restitusjon for et bevegelig objekt og et stødig underlag er enkel:
er hastigheten på ballen like før den treffer bakken, og < em> v 2
er hastigheten på ballen like etter den treffer bakken og begynner å sprette opp igjen.
er forskjellig for hver kombinasjon av objekter, må du finne din egen, avhengig av hva du simulere
Trinn 1:. Sette opp FLA Document
pakke {import flash.display.MovieClip; public class Hoved strekker MovieClip {offentlig funksjon main (): void {}}}
.
panel. Ved siden av Dokument klasse
, skriver du inn navnet på dokumentet klassen, Hoved
.
Trinn 2: Opprette hoved Loop
hendelse, eller bruker AS3 Timer
klasse. Begge metodene har ulike fordeler og ulemper, men for dette eksempelet jeg kommer til å bruke Timer
klasse
klasse. Inne Main.as
legge til følgende linjer
import flash.utils.Timer;. Import flash.events.TimerEvent;
, jeg vil ha å legge til en annen metode som kalles, mainLoop
til dokumentet klassen. Som navnet antyder, vil denne metoden fungere som vår sløyfe
offentlig funksjon mainLoop. (Event: Timerevent): void {}
, og intervall
. Den masterTimer formål bør være opplagt, men intervallet eiendommen vil bli brukt til å lagre lengden (i sekunder) av en Timer intervall
offentlig Var masterTimer. Timer; offentlig Var intervall: Number;
. I trinn 1 setter vi vår dokumentets bildefrekvens til 50 FPS. Denne bildefrekvens kan refereres med stage.frameRate
, og vil bli brukt som grunnlag for beregning av Timer intervallet
//Få dokumentets rammen ratevar fps. Int = stage.frameRate; //Timeren intervall i secondsinterval = 1 /fps; //Opprett en ny forekomst av timeren, første parameter krever intervallet i millisecondsmasterTimer = new Timer (1000 /fps);
hendelse hver intervall (i vårt tilfelle, 50 ganger i sekundet, eller en gang hver 20 millisekunder). Ved å legge til en hendelse lytteren til Timer, kan vi driver vår mainLoop
metode hver gang dette arrangementet er generert, og dermed skape vår loop.
//Koble vår sløyfe-metode til timer.masterTimer.addEventListener ( TimerEvent.TIMER, mainLoop);
//Start TimermasterTimer.start ();
Trinn 3:. Testing hoved Loop
< p> Hvis vi teste filmen som er, vil ingenting skje. Siden vi ønsker å vite om løkken fungerer, skal vi legge til en linje i mainLoop metode som utganger hvor lenge SWF har kjørt. Som standard Timer kan bare returnere den nåværende antall intervaller som har gått. Siden vi allerede beregnet lengden av et intervall, vi bare multiplisere de to verdier for å få tid. Vær oppmerksom på at jeg er avrunding resultatet for å unngå problemer med flyttall aritmetikk
//Beregn dagens timevar currentTime. Number = int ((event.target.currentCount * intervall) * 1000) /1000;
, vi kan se Timer arbeider
//Test løkken ved å spore den nåværende timetrace ("Klokken akkurat nå:" + currentTime);.
Trinn 4:. Projectile.as Opprette Class
pakke {import flash.display.MovieClip.; public class Prosjektil strekker MovieClip {offentlig funksjon prosjektil (): void {}}}
//Initial Velocityprivate Var V1x: Number; private Var V1Y. Antall; //Accelerationprivate Var aX: Number; private Var Ay: Number; //Initial Positionprivate Var D1X: Number; private Var d1Y: Number; //Animation-specificprivate Var Starttime: Number; privat Div flytting: Boolean;
Trinn 5: Projectile.as Convenience Metoder
, returnerer røttene til en kvadratisk funksjon (i standard form. Ax 2 + Bx + C, denne metoden vil returnere verdien av x) ved hjelp av kvadratiske formelen
privat funksjon solveQuadratic (a. Antall, b: Antall, c: Number): Array {//Metode paramters format: Ax² + Bx + C Var løsning: Array = new Array (2); Var diskriminant: Nummer = (b * b) - (4 * a * c); //B ^ 2 - 4ac løsning ["root1"] = ((-1 * b) + Math.sqrt (diskriminant)) /(2 * a); //(-b + Squareroot (b ^ 2 - 4ac)) /2a løsning ["root2"] = ((-1 * b) - Math.sqrt (diskriminant)) /(2 * a); //(-b - Squareroot (b ^ 2 - 4ac)) /2a retur løsning;}
, returnerer en matrise med de enkelte x- og y-komponentene av en vektor .
private funksjons getComponents (angleDegrees: Antall, omfang: Number): Array {var komponenter: Array = new Array (2); //Trogonometriske krever vinkler i radianer (1 radianer = PI /180 grader) komponenter ["x"] = magnitude * Math.cos (angleDegrees * Math.PI /180); komponenter ["y"] = magnitude * tak i Math.sin (angleDegrees * Math.PI /180); returnere komponenter;}
, vil returnere stilling ved et gitt tidspunkt. Vi bruker posisjonen formelen fra innføringen; Dette er d (t)
privat funksjon getPosition (tid: Antall, akselerasjon: Antall, initialVelocity: Antall, initialPosition: Number): Antall {var posisjon. Antall; //D (t) = (1/2) * a * (t ^ 2) + v_1 * t + d_1 stilling = (0,5 * akselerasjons * tid * tid) + (initialVelocity * tid) + (initialPosition); returnere posisjon;}
, er det motsatte av getPosition
. Den returnerer den tiden det tar for prosjektilet å nå en gitt posisjon
private funksjons getTimes (finalPosition: Antall, initialPosition: Antall, akselerasjon: Antall, initialVelocity: Number): Array {var tid:. Array; //Løs kvadratisk stilling funksjon: 0 = (1/2) * a * (t ^ 2) + v_1 * t + d1-d2 tid = solveQuadratic (0,5 * akselerasjon, initialVelocity, initialPosition - finalPosition); tilbake gang;}
, bruker den første deriverte av vår posisjon funksjonen til å returnere hastigheten av prosjektilet på et gitt tidspunkt
privat funksjon getVelocity (akselerasjon: Antall,. initialVelocity: Antall, tid: Number): Antall {var hastighet: Number; //Velocity funksjonen er første deriverte av posisjon funksjon: d '= a * t + v1 hastighet = akselerasjon * tid + initialVelocity retur hastighet;}
, returnerer retning (vinkel ) av hastigheten på et gitt tidspunkt. Med andre ord, returnerer den retning at prosjektilet beveger seg inn på et bestemt øyeblikk
privat funksjon getVelocityDirection. (AccelerationX: Antall, accelerationY: Antall, initialVelocityX: Antall, initialVelocityY: Antall, tid: Number): Antall {var vinkel: Number; Var velocityX: Number = getVelocity (accelerationX, initialVelocityX, tid); Var velocityY: Number = getVelocity (accelerationY, initialVelocityY, tid); vinkel = Math.atan2 (velocityY, velocityX) * 180 /Math.PI; returnere vinkel;}
Trinn 6: Projectile.as initialisering Metode
metode for å gjøre det
offentlig funksjon init (velocityDirection. Antall, initialVelocity: Antall , initialPositionX: Antall, initialPositionY: Antall, akselerasjon: Antall = 0, accelerationDirection: Antall = 0, gravitasjon: Number = -9,8): void {}
parameter tar vinkelen på initialVelocity
i grader. Akselerasjons parametre er valgfrie. Hvis du angir en verdi for akselerasjon
, må du gi en egen verdi for accelerationDirection
som vi gjorde med velocityDirection.
metoden en vektor (størrelse og retning). Det er der våre dagligvare metoder som også spiller inn
//Få komponenter for våre hastighet og akselerasjon vectorsvar vComponents: Array = getComponents (velocityDirection, initialVelocity); Var aComponents:. Array = getComponents (accelerationDirection, akselerasjon);
//Oppbevar disse vektorer i tilsvarende propertiesv1X = vComponents ["x"];. V1Y = vComponents ["y"], AX = aComponents ["x"]; y = aComponents ["y"] + gravitasjon; //Det er her vi legger ekstra tyngdekraften i y-retningen
//Oppbevar den innledende positiond1X = initialPositionX;. D1Y = initialPositionY;
Trinn 7: Projectile.as kontrollmetoder
eiendom brukes til å gjøre rede for forskjellen mellom den globale tiden av Timer, og den lokale tiden av prosjektilet posisjon funksjon. Ingenting er for komplisert.
offentlig funksjon begynne (currentTime: Number):. Void {Starttime = currentTime; flytting = true;} offentlig funksjon slutten (): void {flytte = false;} offentlig funksjon isMoving (): Boolean {return flytte;}
metoden returnerer posisjonen til prosjektilet på et gitt tidspunkt. Vi kan bruke denne posisjonen innenfor sløyfen å animere vår MovieClip på scenen
offentlig funksjon positionAtTime (currentTime: Number): Array {var relativeTime. Number = int ((currentTime - Starttime) * 1000) /1000; Var posisjoner: Array = new Array (2); posisjon ["x"] = getPosition (relativeTime, øks, V1x, D1X); posisjon ["y"] = getPosition (relativeTime, ay, V1Y, d1Y); returnere posisjon;}
variabel. Jeg nevnte tidligere at vi trenger å ta hensyn til forskjellen i tid mellom Timer Hotell og prosjektil
. Begynnelsen av prosjektilets bane starter på en relativ tid fra 0, så vi er bare interessert i hvor mye tid som har gått på Timer siden denne banen begynte. Dette er grunnen til at vi lagrer Starttime
. Den andre tingen er bruken av vår getPosition
metode fra trinn 5. Vi bruker denne metoden to ganger for å beregne posisjonen til prosjektil i begge akser.
Trinn 8: Projectile.as Linking til en MovieClip
klasse utvider MovieClip
klasse, noe som betyr at vi kan koble den til en MovieClip
i vårt bibliotek.
. Den MovieClip skal vises i biblioteket, når den gjør det, slette det fra scenen siden vi kommer til å legge det programmatisk i neste trinn.
. Skriv inn Ball
for Class
, og Prosjektil
for Base klasse
.
. Du kan se en dialogboks som forteller deg at en klassedefinisjon ikke ble funnet, og at man vil bli generert automatisk. Klikk på OK
igjen
Trinn 9:..! Animere
offentlig Var skala:.. Int; offentlig Var ball: ball; offentlig Var startFlag: Boolean;
eiendom skal representere en skala mellom Flash er pixel posisjon og vår beregnede meter posisjon. ball
eiendom representerer MovieClip vi opprettet i forrige trinn. Du vil kanskje legge merke til at denne typen er satt til Ball
, dette er klassenavnet vi satt i forrige trinn. Endelig startFlag
eiendommen blir brukt som et flagg for å fortelle sløyfen når vår prosjektilet skal begynne sin bane.
//1 meter = "scale" pixelsscale = 100; //i.e. 100 piksler = én meter, 1 pixel = 1cm //Opprett en ny forekomst av Ballball = new Ball (); //Sett størrelsen på ballen, i dette tilfellet er det 0.5mx 0.5mball.height = 0,5 * skala; ball .width = 0,5 * skala; //Plasser ballen på stageball.x = 50; ball.y = 350; //Legg ballen til stagestage.addChild (ball);
metoden fra trinn 6. Hvis du ser på den metoden erklæringen, vil du se at det krever et minimum av 4 paramters: velocityDirection
, initialVelocity
, initialPositionX
, og initialPositionY
. Bor i konstruktør-metoden, la oss sette dem opp
//Kjør prosjektilet init-metoden for å sette egenskapene til vår projectileball.init (80, 7, ball.x /skala, (stage.stageHeight - ball.y) /skala);
krever et ekstra trinn. Siden Flash opprinnelse eksisterer i øverste venstre hjørne, og økende y beveger ned
skjermen, må vi trekke vår y-posisjon fra stage.stageHeight
, å flytte vår opprinnelse til nederst til venstre og la økende y å flytte opp
skjermen.
.
//Sett starter flagget, så sløyfen setter ballen i motionstartFlag = true;
.
//Begynn bevegelse hvis flagget har blitt flaggedif (startFlag == true) {ball.begin (currentTime); startFlag = false;}
i trinn 3. Også, siden vi bare ønsker å ringe begynne
metoden en gang, vi setter startFlag Anmeldelser eiendommen tilbake til false
.
//Animate hvis ballen er i motionif (ball.isMoving () == true) {}
//Få dagens positionvar currentPosition. Array = ball.positionAtTime (currentTime);
posisjon. Ligner på init
metoden, må vi ta hensyn til vår skala, og Flash opprinnelse
//Flytt vår custom MovieClipball.x = currentPosition ["x"] * skala;. Ball.y = stage.stageHeight - currentPosition ["y"] * skala;
Trinn 10: Making the Ball Bounce
hvor ballen kan sprette. For enkelhets skyld, skal vi gjøre vårt bakken
en tenkt linje, på bunnen av scenen.
intervall. Dette betyr at tiden og posisjonen til returmeldingen vil bli unøyaktig. Tenk på dette diagrammet:
klasse. Vi begynner med timeOfCollision
offentlig funksjon timeOfCollision (ground: Number): Antall {var tid: Number;. Var ganger: Array; ganger = getTimes (jord, d1Y, Ay, V1Y); //Vi ønsker ikke den negative tid resultat, så bruker du den store tid tid = Math.max (ganger ["root1"], tider ["root2"]); //Vi må vurdere starttid samt siden vi sjekker løkken tid = tid + starttid retur tid;}
returnerer tidspunktet prosjektilet vil være på et angitt posisjon. Det vil faktisk komme tilbake to ganger, en negativ og en positiv, fordi disse er røttene til en kvadratisk likning.)
offentlig funksjon velocityAtTime (currentTime: Number): Antall {var relativeTime. Number = int ((currentTime - Starttime) * 1000) /1000; Var hastighet: Number; Var velocityX: Number = getVelocity (AX, V1x, relativeTime); Var velocityY: Number = getVelocity (Ay, V1Y, relativeTime); //Pythagoras teorem hastighet = Math.sqrt (velocityX * velocityX + velocityY * velocityY); returnere hastighet;} offentlig funksjon velocityDirectionAtTime (currentTime: Number): Antall {var relativeTime: Number = int ((currentTime - Starttime) * 1000) /1000; Var vinkel: Number; vinkel = getVelocityDirection (AX, ay, V1x, V1Y, relativeTime); returnere vinkel;}
. Vi skal bruke det i neste trinn
offentlig funksjon getStartTime (): Antall {return starttid;}
eiendom, og en cor
eiendom for å representere vår koeffisient av restitusjon
offentlig Var collisionTime. Nummer, offentlig Var cor: Number;
. Vi kan sette dette i konstruktør-metoden. Jeg har plukket 0,8, men gjerne eksperimentere med ulike verdier for å se effekten.
//Sett koeffisienten til restitusjon. Må være en verdi mellom 0 og 1 Kor = 0,8;
. Inne legge til følgende linje. Dette vil beregne vår første kollisjonen tid.
//Siden stillingen er midtpunktet av ballen, er y-posisjonen til bakken faktisk til halve høyden av ball.collisionTime = ball.timeOfCollision ((ball. høyde /2) /skala);
. Vi kommer bare til å sjekke for kollisjoner hvis ballen er i bevegelse, så vi skal sette våre dueller uttalelser der inne. Legg til følgende til toppen av tilstanden
//Sjekk om en kollisjon happenedif (currentTime > = collisionTime). {}
. Det første vi må gjøre er å beregne retningen og størrelsen av hastigheten på collisionTime
Var newVelocityDirection: Number = -1 * ball.velocityDirectionAtTime (collisionTime); Var newVelocity. Number = ball. velocityAtTime (collisionTime) * cor;
metoden, må vi sette vår bakken
y-posisjon til halvparten av høyden på ballen. Vi gjør dette fordi y-posisjonen til ballen er faktisk på sitt midtpunkt, ikke sin base
//Sett den nye trajectoryball.init (newVelocityDirection, newVelocity, ball.x /skala, (stage.stageHeight -. Ball .Y) /skala), ball.begin (collisionTime); collisionTime = ball.timeOfCollision ((ball.height /2) /skala);
Trinn 11:.! Men hopp aldri stopper
Var newVelocity: Number = ball.velocityAtTime (collisionTime) * cor;
er ikke lik 0 eller 1, vår prosjektilets hastighet vil bare tilnærming
null, blir tregere og tregere, men aldri faktisk nå det. Siden realiteten er at vår prosjektil kommer til å hvile, må vi implementere en løsning på dette problemet.
er konstant, kan vi se på de spretter som en geometrisk rekke:
a 1: Tiden det tar for første sprett
a 2: Tiden det tar for andre sprett
a 3: Tiden det tar for tredje sprett
...
term i sekvensen representerer hvor lang tid for en sprett. Vi viser til den kumulative tid tatt slik:
S 1: Tiden det tar for første sprett
S 2: Tiden det tar for første sprett og Selge andre sprett
S 3: Tiden det tar for de tre første spretter, totalt
...
variabel, representerer det første leddet i serien, i vårt tilfelle, lengden på den første sprett. r
variabel representerer seriens ratio, i vårt tilfelle, cor
.
offentlig Var stoppingTime: Number; offentlig Var sprett. int;
eiendommen vil bli brukt som en enkel teller . Inne loop startFlag
tilstand (dette if-setning: if (startFlag == true) {
) legge følgende etter vår erklæring om cor Bilde:
//Tilbake spretten countbounce = 0;
//Øk antall bouncesbounce ++;. //Beregn stoppe tiden på første bounceif (sprett == 1) { //Sum av uendelig geometrisk rekke: S = a_1 /1 - r stoppingTime = (collisionTime - ball.getStartTime ()) /(1 - cor) + ball.getStartTime ();}
har gått. Hvis det har vi kan få prosjektilet til å hvile, ved å ringe ende
metoden. Sløyfen er fortsatt kommer til å flytte ballen en siste gang, så vi trenger å sette ballen til riktig endelige posisjon. Sløyfen allerede satt prosjektilet på en ny bane, så vi kommer til å komme rundt dette ved å sette currentTime
til ball.getStartTime ()
.
//Hvis vi nå stoppe tiden, avslutter motionif (sprett > 1 & & collisionTime > stoppingTime) {ball.end (); //Siden ballen er allerede på en ny bane, tvinge den til sin startposisjon currentTime = ball.getStartTime ();}