Kast objekter ved å lage en PanAndThrow-klasse

I denne opplæringen vil vi komme til å mocking og avslutte en panne og kaste klassen som vil tillate oss å legge til denne effekten til ethvert element vi ønsker. For å oppnå dette, vil vi opprette en bildeviser - men ikke din gjennomsnittlige seer. Her skal vi zoome, kaste, panorere ... Nesten høres ut som en ninja-app, hei?


Trinn 1: Introduksjon

Pan and Throw Class vil tillate deg å legge til panne og kaste funksjonalitet til hvilken som helst ActionScript-objekt du vil ha. Selv om denne opplæringen er spesifikt for Flex, kan selve klassen brukes hvor som helst ActionScript er. Jeg hadde sett denne effekten på flere nettsteder, deretter i Photoshop CS4 og bestemte meg for at jeg ønsket dette på mine prosjekter også.

Det er mange applikasjoner for denne effekten; Den som vi skal bruke for denne opplæringen, er en bildeviser som lar deg zoome inn og ut av bildet og endre friksjonen som kasteffekten bruker. Denne veiledningen handler imidlertid ikke egentlig om bildeviseren, det handler om å lage en panne og kaste klassen. Så la oss komme i gang med det. Åpne din favoritt Flex editor og få et prosjekt å gå; For informasjon om å gjøre dette i Flex Builder, se Adobe LiveDocs. Når prosjektet ditt er opprettet, åpner du MXML-filen. Vi må legge til noe kode for dette før vi lager vår klasse.


Trinn 2: Vår MXML

Siden dette ikke er den store delen av opplæringen, skal jeg ikke bruke mye tid her. Hvis du har spørsmål om denne delen som ikke er dekket, kan du spørre i kommentarene nedenfor. For det første, her er MXML-objektene som skal legges inn i søknaden:

            

Du vil legge merke til de fire funksjonene som kalles i kodene: init (), changeDecay (), smoothImage () og zoom (). Vi må skrive opp disse funksjonene. Dette er koden mellom tags:

 importere mx.states.SetStyle; importere mx.effects.Move; importere mx.containers.HBox; importere mx.containers.Box; private var imageWidth: Number = 0; privat var imageHeight: Number = 0; privat var mover: Move = new Move (); // dette vil bli kalt når programmet laster privat funksjon init (): void // Denne hendelsen vil legge til muligheten til å skjule og vise våre kontroller med et klikk. control.addEventListener (MouseEvent.CLICK, controlClick); mover.target = control;  // Denne funksjonen vil zoome inn og ut av bildet vårt i henhold til verdien av zoomskyderen. privatfunksjon zoom (): void inside.width = (imageWidth * hSlider.value) / 100; inside.height = (imageHeight * hSlider.value) / 100;  // dette blir kalt når bildet endres størrelse. privat funksjon smoothImage (ev: Event): void // sett bildeutjevning slik at bildet ser bedre ut når det blir transformert. var bmp: Bitmap = ev.target.content som Bitmap; bmp.smoothing = true; imageWidth = inside.width; imageHeight = inside.height;  // vi vil ikke bruke denne, men likevel private funksjonen changeDecay (): void // dette vil forandre nedbrytningsverdien av vår klasse når vi kommer dit.  privatfunksjonskontrollKlikk (e: MouseEvent): void mover.play (); // denne funksjonen gjemmer / viser kontrollene på klikk hvis (control.y! = -5) mover.stop (); mover.yTo = -5; mover.play ();  annet hvis (e.target == kontroll) mover.stop (); mover.yTo = (control.height - 10) * -1; mover.play (); 

Når du har din MXML, må du opprette en mappe som heter "klasser" i samme mappe som din MXML-fil. (Hvis du bruker Flash, må mappen være i samme dir som din FLA-fil.) Dette er vår klassepakke og er der filen PanAndThrow.as vil gå. I Flex Builder lager du en ny klasse, legger den i klassepakken, og kaller den PanAndThrow; Dette vil opprette klassen din - standard stil.


Trinn 3: Makings av en klasse

Her er vår grunnleggende PanAndThrow-klasse. Lagre det som PanAndThrow.as i den nye mappen "klasser".

 // namespace declaration pakke klasser // klasse deklarasjon offentlig klasse PanAndThrow / * dette kalles konstruktøren, denne metoden / funksjonen vil bli kalt når du lager * en forekomst av objektet, eller instantiate objektet. * For denne klassen gjør vi ingenting fordi vi skal gjøre alt * i Init-funksjonen * / offentlig funksjon PanAndThrow () 

Hvilke variabler og funksjoner trenger vi i vår PanAndThrow-klasse? For å få det, kan du spørre deg selv "Hva trenger klassen min å gjøre, hva trenger den å vite, og hva trenger den for å kunne gjøre det?" Så la oss lage noen pseudokode.

Quick Note

Da jeg først utviklet denne klassen, satte jeg alt i konstruktøren, men det førte til et problem da jeg opprettet start og stopper metoder på grunn av omfang. Jeg kunne ikke instantiere denne klassen på et globalt omfang med all nødvendig informasjon. Derfor laget jeg en init () -funksjon, slik at forekomsten kunne startes og stoppet fra utenfor klassen.


Trinn 4: Vår Pseudo-kode

"Pseudo-kode" betyr bare falsk kode, som vi kan bruke til å hjelpe oss med å tenke på hvilken ekte kode vi trenger.

 pakke klasser offentlig klasse PanAndThrow / * Disse vil være variablene vi lager. Så hva må vi vite? * anObjectToThrow; * anObjectToThrowItIn; * ObjectLocation; * PreviousObjectLocation; * Forfall; // for fysikken * disse er de åpenbare, men denne listen vil bli mye større * som vi ser nøyaktig hva vi trenger i våre funksjoner * / offentlig funksjon PanAndThrow ()  / * Så hva skal vår klasse gjøre ? * i det(); // det må starte * stoppe (); // vi vil kunne stoppe det på en eller annen måte. * start(); // Hvis vi stopper, må vi kunne starte det igjen. * pan (); * kaste (); * /

Nå som vi har noen pseudokode kan vi begynne å bygge klassen. La oss starte med init () -funksjonen. Dette vil også bringe oss inn i et av prinsippene for Objektorientert Programmering som kalles innkapsling, som omhandler tilgangen av deler av koden.

Denne koden skal gå i PanAndThrow-klassen vi nettopp har startet. (Ikke sikker på hvor? Sjekk ut Hurtig Tips fra Document Class.)

 // takket være OOP, en lavere klasse klasse og en øvre nivå klasse (en som strekker seg // klassen på lavere nivå) kan brukes. Som her, vil nesten hvert objekt du bruker, utvide // Sprite-klassen. Så jeg må bare be om et Sprite-objekt, og du kan gi en boks eller en knapp. private var targetObject: Sprite = new Sprite (); private var eventObject: Sprite = new Sprite (); private var originalDecay: Number = .9; private var buttonDown: Boolean = false; privat var moveY: Boolean = true; private var moveX: boolsk = true; private var TargetClick: Boolean = true; // Vi bruker dette for å sjekke hvor lenge musen har vært nede på et objekt uten å flytte. Privat var t: Timer; privat var timerInterval: int = 100; offentlig funksjon init (ObjectToMove: Sprite, ObjectToEventise: Sprite, DecayAmout: Number = .9, isMoveY: Boolean = true, isMoveX: Boolean = true, OnlyMoveOnTargetClick: Boolean = true): void targetObject = ObjectToMove; eventObject = ObjectToEventise; originalDecay = DecayAmount; moveX = isMoveX; moveY = isMoveY; TargetClick = OnlyMoveOnTargetClick; t = ny timer (timerintervall); start(); 

Bare et par ting jeg vil påpeke. I funksjonen for init har jeg satt noen få argumenter til å være lik en verdi. Det betyr at jeg gir dem en standardverdi, slik at de blir valgfrie. Når du angir standardverdier for argumentene til en funksjon, må de være de siste parameterne - du kan ikke ha en nødvendig variabel etter en valgfri. Grunnen til at jeg la til standardvariabler er å få anropet kortere hvis vi bruker standardinnstillingene. Jeg kan ringe PanAndThrow (mover, eventer); og gjøres, i stedet for PanAndThrow (mover, enventer, decayer, yVal, ...) og så videre.

Har du noen gang lurt på hva den "private" eller "offentlige" foran funksjoner og variabler betyr? Det er eksponeringen av objektet. Et "offentlig" objekt kan nås av en hvilken som helst annen klasse; et "privat" objekt kan kun ses av de andre medlemmene av denne klassen; et "beskyttet" objekt er skjult for alt unntatt klasser som er i samme pakke.

Vi ønsker å kunne endre forfallet fra vår MXML, slik at vi trenger en offentlig krok for å komme til vår private variabel; Dette er hvor getter og setterfunksjoner kommer inn:

 private var originalDecay: Number = .9; offentlig funksjon få forfall (): tall return originalDecay; 

Det er en "getter" -funksjon. Det betyr at, til utenfor klasser, ser det ut som at PanAndThrow-klassen har en offentlig variabel kalt "forfall". Når de prøver å få tilgang til det, returnerer vi dem til verdien av vår (private) originalDecay-variabel.

Setter-funksjoner er nesten det samme, men lar de utenfor klassene å endre verdien av vår "falske" offentlige variabel:

 offentlig funksjon sett forfall (verdi: tall): void originalDecay = value; 

Disse er nyttige fordi du kan sette logikk inn i en setter for å begrense det som kommer inn i din private var. For eksempel, hvis du setter et nummer i MXML-taggen for en boks, får du en sett høyde; hvis du setter en% (gjør tallet en streng) får du en prosenthøyde. Det er bygget inn i koden for boksens høyde setter. Nå som vi har vår getter og setter kan du få tilgang til nedbrytningsvariabelen som dette fra utenfor klassen:

 var pt: PanAndThrow = ny PanAndThrow (); pt.init (mål, foreldre); pt.decay = .7;

Trinn 5: Start, Hør, Stopp

Vi har vår klasse, noen lokale variabler og en init () -funksjon. La oss gjøre noe nå. På slutten av init () -funksjonen kalte vi "start ();" så la oss starte startfunksjonen. For det meste er det bare en mengde lyttere:

 offentlig funksjonstart (): void // Med musen nede ser vi på å starte vår pan-handling, men vi må kunne // for å sjekke vår OnlyMoveOnTargetClick som vi tilordnet til vårt globale felt TargetClick targetObject.addEventListener (MouseEvent. MOUSE_DOWN, handleOverTarget); eventObject.addEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); // Når vi kaller panelen, bruker den en musebevegelseslytter, som betyr at den blir kalt hver gang // musen beveger seg, så vi må se hvordan du begrenser når målobjektet beveger seg. eventObject.addEventListener (MouseEvent.MOUSE_MOVE, moveIt); // dette er å kaste objektet etter en panne, dette er litt vanskelig fordi funksjonen throwIt () kaller en annen lytter. targetObject.addEventListener (MouseEvent.MOUSE_UP, throwIt); eventObject.addEventListener (MouseEvent.MOUSE_UP, throwIt); // throwItOut-metoden gjør at objektet fungerer som om vi slipper museknappen, men det blir sparket når / / musen forlater foreldreobjektet targetObject.addEventListener (MouseEvent.MOUSE_OUT, throwItOut); eventObject.addEventListener (MouseEvent.MOUSE_OUT, throwItOut); // dette er timeren lytteren, dette vil sjekke for å se om du har holdt musen nede litt, vil jeg / / forklare behovet for dette når vi kommer til timerOut () funksjonen t.addEventListener (TimerEvent. TIMER, timerOut); t.start (); 

Stopp () -funksjonen er nesten den samme, men vi fjerner lytterne.

 offentlig funksjonstopp (): void targetObject.removeEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); eventObject.removeEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); eventObject.removeEventListener (MouseEvent.MOUSE_MOVE, moveIt); targetObject.removeEventListener (MouseEvent.MOUSE_UP, throwIt); eventObject.removeEventListener (MouseEvent.MOUSE_UP, throwIt); targetObject.removeEventListener (MouseEvent.MOUSE_OUT, throwItOut); eventObject.removeEventListener (MouseEvent.MOUSE_OUT, throwItOut); t.removeEventListener (TimerEvent.TIMER, timerOut); t.stop (); 

Nå kan vi lytte til hva som skjer, la oss gå gjennom hver av disse lytterfunksjonene.


Trinn 6: MouseEvent.MOUSE_DOWN

Vi skal se på handleOverTarget hendelse handler.

 privat funksjon handleOverTarget (e: MouseEvent): void buttonDown = true; arMousePrevX = MousePrevX = MouseCurrX = eventObject.mouseX; arMousePrevY = MousePrevY = MouseCurrY = eventObject.mouseY; hvis (e.currentTarget == targetObject ||! TargetClick) overTarget = true;  annet hvis (e.target.toString (). søk (targetObject.toString ()) < 0)  overTarget = false;  

Denne funksjonen blir kalt når det er en MOUSE_DOWN-hendelse på enten hendelsesobjektet eller målobjektet. Det er veldig viktig å merke seg at hvis jeg setter en lytter på en forelderobjekt, vil håndtereren selv bli kalt når hendelsen oppstår på et barn. I dette tilfellet er mitt målobjekt et barn av hendelsesobjektet. Når jeg klikker på målobjektet, kalles denne metoden to ganger: Først for musen nede på barnet, så sekund for musen nede på foreldrene. Det er veldig viktig for dette fordi vi skal avgjøre om musen ned vil kunne flytte måletobjektet, slik at vi virkelig må kunne vite om den musen var nede på barnet eller ikke.

Den første utsagnet er ganske grei: sett vår klassevariable knappDown til true.

De neste to er ganske enkle også, bortsett fra at jeg har introdusert et par nye variabler som må settes inn i klassevariabelen: MousePrevX, MousePrevY, arMousePrevX, arMousePrevY, MouseCurrX og MouseCurrY. Disse vil bli brukt mye i dra og pan-funksjonene, så jeg vil vente med å snakke om dem til da.

If-setningen kontrollerer for å se om objektet klikket er målobjektet. Husk at TargetClick ble satt til argumentet vi passerte til init (), OnlyMoveOnTargetClick; Hvis dette er feil, ønsker vi å behandle hvert barnobjekt som målobjektet når det klikkes. Det er derfor vi har "||! TargetClick" sjekk.

Det er den enkle delen. Neste del er litt vanskeligere.

E.currentTarget returnerer objektet som utløste hendelsen. E.target vil returnere objektet som var det faktiske målet. Så jeg kunne si dette, riktig?

 hvis (e.target == targetObject ||! TargetClick) overTarget = true;  ellers overTarget = false; 

Det er enkelt nok, men det er feil. Hva om mitt målobjekt har barn? Da kan e.currentTarget være måletObject, men e.target er targetObjects barn og vil ikke matche. Vi vil at dette skal bevege seg selv om vi smelter ned på et barnobjekt.

Så her kommer String.search til redning. Hvis vår nåværendeTarget ikke er vårt målObject, bruker vi et "annet hvis" for å se om vi kan finne vårt målobjekt i målet. e.target.toString () vil produsere noe som dette: "application2.eventobject3.targetobject2.targetchild4" for vårt målobjekt der targetObject.toString () vil produsere noe som dette "application2.eventobject3.targetobject2" alt jeg trenger å gjøre for å finn ut om målet vårt er et barn av vårt målObject er av dette:

 e.target.toString (). søk (targetObject.toString ())

Hvis det er en kamp, ​​vil den returnere den første indeksen til kampen, eller hvis det ikke er en kamp, ​​vil den returnere en -1, så vi kan bare se om den er større enn -1 og viola, vi har funnet om objektet å bli klikket på er et barn av måletObject.

(Vi kunne sjekke barn eller foreldre (e) av objektet via getChildAt () -funksjonen og foreldreiendommen, men dette er et pent alternativ.)


Trinn 7: TimerOut og Pan

Timerfunksjonen er ganske enkel også, spesielt siden vi har gjort dette før. Vel, nesten gjort dette før. Når vi har slått rundt vårt lille målObject litt og bestemmer oss for at vi ikke vil la det gå, elsker vi det for mye, og plutselig stopper musen, hva ville skje hvis du slipper museknappen på det tidspunktet? Vel, hva tror du ville skje? Jeg skal ikke svare på det for deg, jeg skal bare hjelpe deg med koden for å få det til å skje. I den endelige koden, kommentere disse tre linjene. Dette burde se veldig kjent ut, vi har nettopp brukt dette i knappen nedoverbehandler, bortsett fra en variabel, MouseDragged. Vi skal bruke det når vi kaller vår andre funksjon:

 privatfunksjon timerOut (e: TimerEvent): void MouseDragged = false; arMousePrevX = MousePrevX = MouseCurrX = eventObject.mouseX; arMousePrevY = MousePrevY = MouseCurrY = eventObject.mouseY; 

Så, hvis du spør hvorfor vi trenger denne timeren, prøvde du sannsynligvis ikke og tok det ut for å se hva som skjedde. Så gjør det.

Denne neste funksjonen er en av våre hovedfunksjoner; det er pan-funksjonen. Det er mye involvert, så la oss dykke inn i vår pseudokode:

 privat funksjon moveIt (e: MouseEvent): void / * ok, så hva trenger vi denne funksjonen å gjøre? * det må panorere vårt målobjekt * så kan vi se om vi er over vårt målobjekt * / // hvis (vi er over vårt målobjekt) // // hvilke verktøy skal vi panorere? // vel, kanskje vi bør sjekke for å se om knappen er nede // hvis (knappen er nede) // // vi må kanskje sette ned knappen variabel. buttonDown = true; // og hvis vi er i denne funksjonen på dette punktet, er knappen vår nede og / / musen har flyttet - det er en dra: så MouseDragged = true; // Hvis vi flytter objektet i henhold til musen flyttes, bør vi // sikkert vite hvor musen vår er: MouseCurrX, Y = nåværende MouseX, Y; // dette er en introduksjon til vår kunstige mus prev, som vil bli forklart // i neste funksjon. Ar står for 'kunstig' eller 'etter utgivelse', // avhengig av hva du foretrekker. Det må settes til vår faktiske tidligere muspos. // arMousePrevX = MousePrevX; // arMousePrevY = MousePrevY; // da må vi faktisk flytte targetObject, // men husk våre variabler, moveX og moveY, så: // hvis moveX flytte x; // hvis moveY flytte y; // vi trenger å tilbakestille vår forfall (friksjon) tilbake til den opprinnelige tilstanden: // Decay = originalDecay; // som skal fullføre hvis // // hva mer? // // vi setter vår buttonDown til sant før, så vi kan sette den til falsk her. // buttonDown = false; // Hvis dette ikke er et målklikk, bør vi sette overTarget til feil slik: // hvis (! TargetClick) // overTarget = false; // det er det. // // det er noen ting vi vil skje uavhengig av forholdene. // Først må vi sette musenPrevX, Y variabel - FØR musen er // flyttet igjen! // MousePrevX = eventObject.mouseX; // MousePrevY = eventObject.mouseY; // Her er to variabler for å holde oversikt over: xOpposideEdge og yOppositeEdge // vi tester for å se hva størrelsen på vårt målobjekt er i forhold // til vårt arrangement objekt; hvis en er større må vi endre opptreden av studsen. // if (targetObject.width> eventObject.width) xOppositeEdge = true; // // xOppositeEdge = false; // hvis (targetObject.height> eventObject.height) yOppositeEdge = true; // annet yOppositeEdge = false; // og til slutt må vi stoppe og starte opp timeren vår. //t.stop (); //t.start (); //

Jeg innrømmer at dette er litt mer psuedo-y enn det siste; det er to grunner: en, du vet ikke hva som kommer, og to, jeg er bare veldig spent på å komme til koden:

 privat funksjon moveIt (e: MouseEvent): void // i vår pseudokode dette var to forhold, men vi kan kombinere til en, // vi tester for å se om hendelsen var en knapp nede, og hvis vi er over vår mål, // hvis vi lar oss flytte målobjektet. hvis (e.buttonDown && overTarget) buttonDown = true; MouseDragged = true; MouseCurrX = eventObject.mouseX; MouseCurrY = eventObject.mouseY; // her er kunstig / etter utgivelse en. igjen, vel til det. arMousePrevX = MousePrevX; arMousePrevY = MousePrevY; / * Dette er viktig, i vår pseudo var det "flytte målobjektet", * så vi må oversette det. For å hjelpe oss skal vi opprette en lokal variabel * Topper for toppen, og Side for siden. * så la oss se på Topper (det samme gjelder Sider). * eventObject.mouseY ser på hvor musen er inne i eventObject. * Vi tar vår MousePrev vekk fra det, og det vil gi oss hvor mye objektet * skal reise, slik at Y kan reise 2 piksler, eller -2 piksler avhengig av * retning, så vi tar den forandringen og legger den til målets nåværende * posisjon, men det skjer ikke ennå, dette er bare en var. * / var Topper: int = (eventObject.mouseY - MousePrevY) + targetObject.y; var Sider: int = (eventObject.mouseX - MousePrevX) + targetObject.x; // her er hvor det skjer, hvis moveY (husk fra pseudokoden) så kan vi // angi posisjonen til målet. hvis (moveY) targetObject.y = Topper; hvis (moveX) targetObject.x = Sider; // så egentlig bruker vi bare Topper og Sider til midlertidig lagring der // målobjektet skal flyttes til Decay = originalDecay ;  ellers buttonDown = false; hvis (! TargetClick) overTarget = false;  MousePrevX = eventObject.mouseX; MousePrevY = eventObject.mouseY; hvis (targetObject.width> eventObject.width) xOppositeEdge = true; else xOppositeEdge = false; hvis (targetObject.height> eventObject.height) yOppositeEdge = true; annet yOppositeEdge = false; t.stop ); t.start (); 

Og nå panorerer vi.


Trinn 8: Kast, det, ut, gjentakeren!

Dette er den andre store funksjonen og med dette vil vi ha vår klasse bygget! Klar til å panorere og kaste ethvert objekt du ser hensiktsmessig! Det er to funksjoner vi må adressere først: throwIt (), som vi satt som en handler til MOUSE_UP-hendelsen, og throwItOut (), som vi satt som en handler til MOUSE_OUT-hendelsen.

 privat funksjon kasteIt (e: MouseEvent): void buttonDown = false; hvis (MouseDragged) eventObject.addEventListener (Event.ENTER_FRAME, theRepeater);  privat funksjon kasteItOut (e: MouseEvent): void buttonDown = false; hvis (e.relatedObject == null || e.relatedObject == eventObject.parent) eventObject.addEventListener (Event.ENTER_FRAME, theRepeater); 

Disse to funksjonene er nesten det samme (de gjør jo det samme, bare på forskjellige tidspunkter). I dem stiller vi knappen Ned til falsk, fordi dette er en mus opphendelse, og sjekk for å se om musen ble trukket, ved hjelp av enten MouseDragged (som vi satt inn i siste funksjon) eller ved å sjekke "e.relatedObject"; objektet som musen bare flyttet ut av.

Hvis det ble trukket, legger vi til en annen lytter. ENTER_FRAME-hendelsen er en veldig kul en. Dette er grunnlaget for vår animasjon; hver gang vi går inn i en ny ramme vil kastefunksjonen bli kjørt. Det er det som gjør det mulig for oss å simulere en musdrag etter utgivelsen (husk arMousePrevX, Y-variabelen? Det er det det er for). Og det er alt kastet egentlig gjør, simulerer en musestrek, uten mus selvfølgelig. Så vi har ganske mye allerede fått den funksjonen vi trenger, bortsett fra at vi må bytte anropene til den nåværende museposisjonen til vår kunstige museposisjon.

Nesten fikk litt foran meg selv der. Så med disse to hendelsesfunksjonene, kaster du og kaster det, de gjør det samme, men det hvis i den andre funksjonen er verdt å nevne. Jeg kjempet en stund og prøvde å få denne funksjonaliteten, til jeg så på hendelsen litt nærmere. Problemet forsøkte å få målobjektet til å fungere som om jeg slett av knappen når markøren forlot hendelsesobjektet. Fortsett, prøv å gjøre dette uten e.relatedObject. Jeg hadde nesten det noen ganger, men kunne ikke få det riktig. Hva e.relatedObject gjør er, finner hvilket objekt du er på, etter at hendelsen er kalt. Det er derfor det er så kult. Når markøren slipper filmen helt, returnerer den null, ellers returnerer objektet du er på, så vi kan se om e.relatedObject er null eller er forelder til eventObject. Det gir den riktige handlingen vi leter etter.

I de ovennevnte funksjonene oppretter vi anrop til theRepeater (). Dette blir kastefunksjonen, og husk at det vil bli kalt hver gang vi går inn i en ny ramme. La oss gå gjennom denne linjen etter linje:

 privat funksjon theRepeater (e: Event): void // timeren må stoppes, prøv å fjerne dette og se hva som skjer. t.stop (); // her er en lokal variabel som holder den nåværende (falske) markørposisjonen. // vel det er bare "falskt" etter første gang. var oldxer: Number = MouseCurrX; var oldyer: Nummer = MouseCurrY; // nå, akkurat som vi gjorde før, må vi finne forskjellen mellom vår nåværende // og forrige posisjon. så hvordan er dette forskjellig fra før? Hvorfor? var xDiff: Number = MouseCurrX - arMousePrevX; var yDiff: Nummer = MouseCurrY - arMousePrevY; // Hvis knappen er nede, kommer vi ikke til å bevege seg lenger, knappen vil stoppe handlingen i dette tilfellet. hvis (! buttonDown) // ta forskjellen og ganger den ved forfallet. Dette vil gi oss den nye // forskjellen, som vil være litt mindre enn den siste, som er hvordan / / vi får friksjonseffekten med dette. // f.eks. hvis forfall er 0,5, vil avstanden flyttes halve hver ramme. xDiff = xDiff * Decay; yDiff = yDiff * Decay; // neste er en av de forvirrende delene for meg, dette beveger ikke objektet på // alt, det tester bare for å se om måletObject har nådd kanten. hvis den har, // vi må sprette den tilbake. (dette kan endres til en annen handling hvis du / vil, du kan til og med fjerne den, hva skjer hvis du gjør det? Prøv det! // i pan-funksjonen angir vi denne variabelen, OppositeEdge, dette er hvor vi skal // bruk det hvis "targetObject er større enn Event Object" som vi angir i // init () -funksjonen. Jeg skal bare gå gjennom x her fordi y er / nesten det samme (hva er forskjellig? hvorfor ? tenk på det!) hvis (xOppositeEdge) / * så først, "bredden på eventObject, - bredden på targetObject - 50", * her er bredden på targetObject større enn den for eventObject * dette vil tillate at motsatt kant av målobjektet er 50 px i fra * motsatt kant. Hvis du går til eksempelfilmen og krymper bildet til * 10% og kaster det rundt, øker du størrelsen til 200% og prøver og Legg merke til * hvilken kant gjør det, så vil du se forskjellen mellom hoppene. * Det er den beste måten å forstå denne delen. * / hvis (targetObject.x < (eventObject.width - targetObject.width - 50))  xDiff = -1 * xDiff; targetObject.x = eventObject.width - targetObject.width - 50;  // this does the same thing for the other edge. if(targetObject.x > 50) xDiff = -1 * xDiff; targetObject.x = 50;  // dette er hvis målobjektet er mindre enn eventObject. ellers / * så igjen testes kantene på targetObject mot * hendelsesobjektet. Denne gangen har vi den samme kanten (vel, * 5px utenfor kanten). Så dette vil sprette som det rammer en vegg. * / hvis (targetObject.x < -5)  xDiff = -1 * xDiff; targetObject.x = -5;  if(targetObject.x > (eventObject.width - (targetObject.width - 5))) xDiff = -1 * xDiff; targetObject.x = eventObject.width - (targetObject.width - 5);  hvis (yOppositeEdge) if (targetObject.y < (eventObject.height - targetObject.height - 50))  yDiff = -1 * yDiff; targetObject.y = eventObject.height - targetObject.height - 50;  if(targetObject.y > 50) yDiff = -1 * yDiff; targetObject.y = 50;  annet hvis (targetObject.y < -5)  yDiff = -1 * yDiff; targetObject.y = -5;  if(targetObject.y > (eventObject.height - (targetObject.height - 5))) yDiff = -1 * yDiff; targetObject.y = eventObject.height - (targetObject.height - 5);  // vel, hvis du har spørsmål om den delen, bare legg inn en kommentar om det, og jeg vil svare på dem. // her er sider og Topper vars (akkurat som de fra pan-funksjonen). var sider: int = xDiff + targetObject.x; var Topper: int = yDiff + targetObject.y; // Vi må sette dette klart for neste gang. MouseCurrX = MouseCurrX + xDiff; MouseCurrY = MouseCurrY + yDiff; // og deretter om moveX, Y (igjen som pan-funksjonen) hvis (moveY) targetObject.y = Topper; hvis (moveX) targetObject.x = sider;  // og sett nå vår kunstige mus prev arMousePrevX = oldxer; arMousePrevY = oldyer; // og hvis vi ikke er i friksjonsløs modus (OriginalDecay = 1) // skal vi trekke en liten mengde fra vårt henfall, til // gir det litt mer naturlig lettelse. if (originalDecay < 1)  Decay = Decay - .004;  // so the moving is done.  // if the button is down we need to remove the listener. else  eventObject.removeEventListener(Event.ENTER_FRAME, theRepeater);  // now we need to check if the effect is over, which is if our x and y diffs are less than 1px. if((Math.abs(xDiff) < 1 && Math.abs(yDiff) < 1))  eventObject.removeEventListener(Event.ENTER_FRAME, theRepeater);  

Og med det er vår klasse ferdig.


Trinn 9: Den fullførte klassekoden

Du kan hente den fullførte koden fra Source-koden, koblet øverst i opplæringen. Det er i PanAndThrow.as-klassen.


Trinn 10: Gjør noe med det

For å gjøre noe med dette må vi gå tilbake til MXML og legge til noen linjer med kode. Legg til vår erklæring i den globale variabelen, fyll inn nedbrytingsmetoden og ring vår pan og kaste init () -funksjonen. Med alt som er lagt til, er her den komplette MXML-filen:

               

Konklusjon

Nå har du en arbeidspanne og kaster klassen! Jeg håper du er så spent som jeg er. Det er mye her, og jeg håper jeg kunne dekke alt og ikke gjøre denne opplæringen for lenge.

Jeg håper du likte denne opplæringen, takk for å lese! Vennligst legg inn i kommentarene hvis du har spørsmål.