Hvordan legge til Mouse Gesture Control for å flash Prosjekter: Multi

How til Legg Mouse Gesture Control for å flash Prosjekter: Multi-Stroke Gestures
Del
Del
9

Del

Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. . Ikke gå glipp av

I første del av denne serien, jeg introduserte en klasse til å håndtere enkelt muse slag deteksjon: MGesture. Denne opplæringen tar det et skritt videre ved å oppdage en sekvens av slag.

Vi skal bruke klassen GManager for dette, i tandem med MGesture. Etter orienteringen gjennom GManager funksjonalitet, vil en søknad demonstrere bruken utvikles.



Endelig resultat Forhåndsvisning

La oss ta en titt på det endelige resultatet vi skal jobbe mot. For å bruke Flash presentasjon nedenfor, bruke musen til å utføre bevegelsen som indikert av pilen i øvre venstre hjørne. Bevegelsen ved å trykke på venstre museknapp, flytte musen mens du holder knappen, og deretter slippe den



Trinn 1:. Recap Direction nummerering

Første trinn, en revisjon på heltall brukt å representere forskjellige retninger fra Del 1. Forhåpentligvis kan du danne et mentalt bilde av diagrammet over som vi skal referere til det tungt hele denne opplæringen



Trinn 2:. Strokes Detected

Som brukeren gjør en gest med noen pekeenheter (mus, tablett penn, osv), vektorene hell oppdaget over tid faktisk danne en serie av heltall. Se i diagrammet nedenfor

Legg merke til de unike heltall i sekvensen er 0, 4, 1. Men skal jeg si unike heltall er 0, 1. Lar innse det:. Det er vanskelig å foreta en nøyaktig slag på min Bamboo tablett, og enda mer så med en mus. Feil er uunngåelig. Vår algoritme bør da være basert på den høye repetisjon av hele tall i en kontinuerlig streng. De er 0, 1 her - 4 er sannsynligvis på grunn av unøyaktig slag. Derfor kan denne gesten være entydig identifisert som en sekvens av 0, deretter 1.

Jeg har tatt enda noen bevegelser med sine tilhørende unike sekvenser under



Trinn 3:. Presenterer GManager

Formålet med denne klassen er enkel:


    For å registrere unike slagsekvenser for å sammenligne mot

    For å fange sekvens oppdaget av nåværende gest gjort av brukeren..

    For å sammenligne sekvensen (2) mot alle slagsekvenser i (1).

    For å returnere søkeresultatet.

    har Developer å definere et sett med hjerneslag sekvenser for å oppdage i utgangspunktet. Når dette er gjort, til hendelsen lyttere fange brukerens gest under kjøring kan programmeres. Hvis gjeldende gest sekvens vellykket matcher alle en sekvens i forhåndsdefinert sett kan ulike operasjoner deretter utføres



    Trinn 4:. Variabler

    GManager har følgende variabler:
    VariableDatatypePurposegestSeqVector. <. Vector < int > > 2D array å ta opp forskjellige slag sequences.gestNameVector. < String > 1D rekke å registrere navnene på hjerneslag sequences.strokesVector. < int > 1D rekke å spille inn begrensning på gestCurrent s slag sammenlignet med hjerneslag sequence.gestCurrentVector. < int > 1D array å ta opp aktuelle slag sequence._orderBooleanDetermines om gest setter i gestSeq bør oppdages i order.orderCurrentintCurrent rekkefølge for å oppdage om _order er slått på; starter på 0.



    Trinn 5: Metoder

    Metoder i GManager er som følger:.
    MethodInputOutputDescriptionGManagervoidvoidClass initiering, gestSeq og gestName, stryker initialisedregisterVector < int >, String, intvoidRegister hjerneslag sekvens , navn og hjerneslag begrensning (valgfritt) .removeintvoidRemove valgt hjerneslag sequenceremoveAllvoidvoidRemove alle registrerte hjerneslag sequencesstartvoidvoidPrepare variabel for å registrere dagens slag sekvens, gestCurrentpopulateintvoidPopulate gestCurrent med oppdagede slag (entall) tracervoidVector. < int > Traces og utganger gestCurrent for debugging purposes.dropStrokesVector <.; int >, intVector. < int > eliminere unødvendig slag i gestCurrent. Hold strømnettet og diagonaler (0), holder bare strømnettet (1), holder bare diagonaler (2). (Del 3 vil ytterligere forklare bruken.) DropDuplicatesVector. ≪. Int >, intVector < int > Identifiser gyldig unike heltall i rekken og slippe
    duplikater. Input minste duplikater (bortsett fra selv) skal være gyldig strokecheckMatchintintChecks hvis medlem av gestSeq kamper med gestCurrentendvoidArrayReturns resultat av søk. Resultatet er Array med indeks over matchet
    sekvens i gestSeq og navnet i gestName

    Egenskaper for GManagerare som følger:
    PropertyAccessor TypesPurposeuseOrderGetter /SetterGets og sett om gestSeq er å bli oppdaget i orderlengthGetter onlyGets lengden gestSeq < hr>
    Trinn 6: Sett inn forhåndsdefinerte Stroke Sekvenser

    Som nevnt, er det første skrittet for å registrere unike slagsekvenser at angitt gest kan sammenlignes mot. Konstruktøren initierer variabler nødvendig (uthevet) og metoder som følger registre inn og fjerner fra forhåndsdefinerte slagsekvenser. Twitter /*** Constructor å initiere gestSeq, Stokes, gestName * /public funksjon GManager () {gestSeq = new Vector. ≪. Vector < int > >; gestName = new Vector. < String >; slag = new Vector < int >;} /*** Metode for å registrere et sett /sekvens av gest *param sekvens Numerisk representasjon av gest sekvens *param identifikator Navn representasjon av gest *param tillatt Stokes lov. Begge ( . 0), hoved fire (1), diagonaler (2) * /public funksjon register (sekvens: Vector < int >, navn: String, onlyStrokes: int = 0): void {gestSeq.push (sekvens); gestName.push (navn); strokes.push (onlyStrokes);} /*** Metode for å fjerne et bestemt sett av gest *param selectSet Valgt sekvens for å fjerne * /public funksjon remove (selectSet: int): void {gestSeq.splice (selectSet, 1); gestName.splice (selectSet, 1); strokes.splice (selectSet, 1);} /*** Metode for å fjerne alle forhåndsdefinerte bevegelser * /public funksjon RemoveAll (): void {gestSeq = new Vector < Vector < int > >;... gestName = new Vector. < String >; . slag = new Vector < int >;}



    Trinn 7: Egenskaper

    Nedenfor er egenskapene spesielt for sett holding hjerneslag seqeunces, gestSeq: Twitter /*** Eiendom å få totalt sett med forhåndsdefinerte bevegelser * /public funksjon get length (): int {return gestSeq.length;} /*** Eiendom å få aktuelle innstillingen på sekvensiell gest deteksjon * /offentlig funksjon får useOrder (): Boolean {return _order;} /*** Eiendom å avgjøre om sett med forhåndsdefinerte bevegelser skal påvises sekvensielt * /public funksjon satt useOrder (verdi: Boolean): void {_order = verdi;}



    Trinn 8: Record Nåværende Stroke Sequence

    Etter å ha registrert slagsekvenser for å oppdage mot, vi kan forberede gestCurrent og registrere consequtive gyldige entall slag inn i den. Metodene nedenfor vilje avsetning for det. Tracer er en metode for å spore den nåværende gest sekvens Twitter /*** Metode for å starte opptak gjeldende sett med gest gjort * /public funksjon start ():. {. GestCurrent = new Vector < int >;} void /* ** Metode for å befolke gest til gjeldende sett med gest *param gestureCode Gesture oppdaget fra MGesture * /public funksjon befolke (gestureCode: int): void {//Aksepter bare gyldig entall gest (0 ~ 8) inn i rekken if (gestureCode > -1) gestCurrent.push (gestureCode);} /*** Metode brukt for debugging. Traces gestCurrent * /public funksjon tracer (): Vector < int >. {Return gestCurrent; trace (gestCurrent);}



    Trinn 9: Ser inn gestCurrent

    Nå kan vi allerede skrive et program for å sjekke ut aktuelle gest sekvens som nevnt i trinn 2. Du kan laste ned kilde og se på klasse CheckOut2. Slå på utdatapanelet i FlashDevelop å vise sekvensen av heltall begått av din nåværende gest.

    Jeg har også tatt med en demo av det under og plassert en Textfield å vise sekvensen i stedet for utdatapanelet i FlashDevelop .



    Trinn 10: Gjennomføring av CheckOut2

    Jeg har tatt med kildekoden til checkOut2 som nedenfor. Det er ikke vanskelig å forstå logikken forutsatt at du har forstått hvordan hendelsesbehandlinger er tildelt. . (. Les denne opplæringen for å finne ut mer om hendelsesbehandlinger) Jeg har også fremhevet viktige punkter der GManager 's metoder blir brukt
    public class CheckOut2 strekker Sprite {private Var tot: MGesture; //forekomst av entall gest detectionprivate Var gesMan: GManager; //forekomst av sekvensen gest detectioprivate Var t: Textfield, offentlig funksjon CheckOut2 () {//initiere MGesture å tillate enkelt gest gjenkjenning tot = new MGesture (scene); //initiere GManager å tillate sekvensiell gest deteksjon gesMan = new GManager (); t = new Textfield () t.x = 50; hets = 50; t.autoSize = TextFieldAutoSize.LEFT; addChild (t); stage.addEventListener (MouseEvent.MOUSE_DOWN, start); stage.addEventListener (MouseEvent.MOUSE_UP, end);} private funksjon start (e: MouseEvent): void {//Start påvise entall og sekvensiell gest ges.start (); gesMan.start (); stage.addEventListener (MouseEvent.MOUSE_MOVE, sjekk); //Start tegning gest graphics.clear (); graphics.lineStyle (3); graphics.moveTo (mouseX, mousey);} private funksjonskontroll (e: MouseEvent): void {gesMan.populate (ges.evalDirections ()); //Feed entall gest til en sekvens graphics.lineTo (mouseX, mousey) //Tegning gest} privat funksjon enden (e: MouseEvent): void {stage.removeEventListener (MouseEvent.MOUSE_MOVE, sjekk); t.text = gesMan.tracer () toString ()}}



    Trinn 11:. Clean Up gestCurrent av Unødvendige Strokes

    Rydder opp slag i dagens gest er viktig, så er det:


      Strokes som gjør vanskelig påvisning av gester.

      Strokes som er duplisert

      Strokes som er ugyldige

      Jeg har delt ryddejobb i to faser, spesielt dropStrokes og dropDuplicates. dropStrokes eliminerer slag som gjorde det vanskelig å oppdage bevegelser. (Denne funksjonen vil bli forklart i detalj i del 3 når vi oppdager alfabetiske bokstaver.) DropDuplicates eliminerer duplikater og ugyldige slag.

      dropStrokes vil bare holde slag i gestCurrent ifølge den tredje paramenter, onlyStrokes, i register. Det er definert når vi registrerer bevegelsen sekvenser i utgangspunktet. For ytterligere forståelse, igjen, se opp for del 3. Men for nå, bare holde det på baksiden av hodet. Faktisk har denne opplæringen ikke gjøre bruk av denne funksjonen bare ennå /*** Metode for å kvitte irrelevante slag basert på betingelse *param strokesCondition *return Vektor av * /private funksjons dropStrokes (inputArray:.. Vector < int >, strokesCondition: int):. Vector < int > {Var xDiagonals. Vector < int > = InputArray.slice (0, inputArray.length); //Hold strømnettet bare hvis (strokesCondition == 1) {for (var i: int = 0; i < xDiagonals.length; i ++) {if (xDiagonals [i] > 3) {xDiagonals.splice (i, 1 ); I--}}} else if (strokesCondition == 2) {for (var j: int = 0; j < xDiagonals.length; j ++) {if (xDiagonals [j] < 4) {xDiagonals.splice (j , 1); j--}}} retur xDiagonals}



      Trinn 12:. Clean Up gestCurrent
      Sveip fra venstre til høyre for å gå til neste bilde

      Den andre fasen av opprydding er å kvitte duplikat og ugyldige slag som nevnt i trinn 2. Gjennomføringen er skrevet under.

      Jeg har plassert en Flash presentasjon over for å lette din forståelse av algoritmen. Lag en riktig gest ved hjelp av musen for å gå til neste bilde, ta til venstre for å gå tilbake til forrige bilde. Opp gest bringer deg til den endelige rammen, ned gest bringer deg til den første rammen. Twitter /*** Metode for å kvitte duplikater og mulige feilaktige bevegelser *param minDuplicates repetisjon for å bli betraktet som høy repetisjon *return Vector rekke m /o duplikater og mulige feilaktige bevegelser * /private funksjons dropDuplicates (inputArray:. Vector < int >, minDuplicates: int = 1):. Vector < int > {//Tilføy slutten av linjen indikator til heltall rekke Var xDuplicates. Vector < int > = InputArray.slice (0, inputArray.length); xDuplicates.push (1); //Start variabler Var count: int = 1; Var keepIndex: int = 0; //Ripping duplikater og ugyldige trekk for (var i: int = 0; i < xDuplicates.length - 1; i ++) {if (xDuplicates [i] == xDuplicates [i + 1]) teller ++ else {if ( telle > minDuplicates) {xDuplicates.splice (keepIndex, telle - 1) keepIndex ++ i = keepIndex teller = 1} else xDuplicates.splice (keepIndex, minDuplicates) I--}} xDuplicates.splice (xDuplicates.length - 1, 1); returnere xDuplicates;}



      Trinn 13: Se etter en Match

      Etter trimming ned gesCurrent, er vår neste oppgave å finne en skikkelig kamp i sett med forhåndsdefinerte bevegelsessekvenser. Vi kan bekrefte kamp mellom nåværende gest og et medlem av forhåndsdefinerte bevegelser ved hjelp checkMatch. Input indeksen for gestSeq du ønsker å sjekke kamp med gestCurrent. En retur verdi på -1 indikerer ingen match; indeksen gestSeq er matchet ellers. Twitter /*** Metode for å sjekke om gestCurrent kamper med gestSeq *param indeksen Medlem av gestSeq *return Match (1) eller ikke (-1) * /private funksjon checkMatch (indeks : int): int {//Pessimistisk søk, ikke foruts funnet utgangspunktet VAR matchet: int = 1; //ren innspill først Var rengjøres. Vector < int > = DropStrokes (gestCurrent, slag [index]); spor (renset, "xstrokes"); rengjøres = dropDuplicates (renset), spor (renset ", xduplicates") //Sjekk bare de av samme lengde if (cleaned.length == gestSeq [index] .length) {var teller: int = cleaned.length; //Rull gjennom hvert heltall valgt forhåndsdefinerte gest for (var medlem: int = 0; medlem < cleaned.length; medlem ++) {if (renset [medlem] == gestSeq [index] [medlem]) counter--; annet break; } //Hvis alle heltall matchet, matcher dagens indeks over gestSeq gestCurrent if (teller == 0) matchet = index; } Avkastning matchet;}



      Trinn 14: Output resultat

      Til slutt kan vi ut resultatet. Resultatet vil være basert på hvorvidt _order er slått på eller ikke. Vi sjekker kamp mellom gestCurrent med gjeldende gestSeq bare hvis _order er slått på, ellers må vi søke etter kamp med et medlem i gestSeq.

      Uansett søke utfallet, trenger vi å sende ut resultatet. Søkeresultatet vil være -1 hvis det ikke er vellykket kamp; hvis det er en kamp, ​​vil en rekke slag indeksen kombinert med sitt navn bli returnert. Resultatet er -2 hvis gestSeq er tom. Twitter /*** Metode for å evaluere gest i henhold til foretrukket tilnærming (i kronologisk rekkefølge eller ikke) *return Ingen forhåndsdefinerte bevegelser (-2), ingen kamp gest (-1 ), array med indeks på kamp og dens beskrivelse * /public funksjon end (): Array {//Pessimistisk søk, -2 indikerer at det ikke er forhåndsdefinert gest Var resultat: Array = [-2, "Ingen forhåndsdefinerte gester"]; //Hvis det er forhåndsdefinerte bevegelser if (gestSeq.length > 0) {//Finn kampen for if (_order) {if (checkMatch (orderCurrent) > -1) {resultat = [orderCurrent, gestName [orderCurrent] ]; orderCurrent ++; }} //Finn en kamp i ingen spesiell rekkefølge else if (_order!) {//Bla gjennom alle bevegelser for (var i: int = 0; i < gestSeq.length; i ++) {if (checkMatch (i) > -1) {resultat = [i, gestName [i]]; }}} //Håndtak når skrånende finner else {resultat = [-1, "Gesture er ugyldig."]}} Avkastning resultat}



      Trinn 15: Forbered Grafiske Eiendeler i Flash

      Med Steg 14 vi fullført GManager. Vi må lage grafiske eiendeler neste. Jeg har laget de grafiske eiendeler i Flash Pro og vil eksportere dem i .swc format. Trykk Ctrl + Shift + F12 til pop Publiser Stille vinduet ut i Flash og sjekke "Export SWC" under Flash-kategorien. Jeg har gjort mine eiendeler tilgjengelig for nedlasting, men gjerne utvikle din egen



      Trinn 16:. Importere eiendeler i FlashDevelop

      Ta med SWC inn FlashDevelop s lib mappe som vist ovenfor. Lag en klasse som heter "Main2" i FlashDevelop og instantiate MovieClip som holder grafikken. Jeg har fremhevet den aktuelle Action nedenfor
      private Var tot: MGesture; privat Var gesMan. GManager; privat Var en: piler, private Var seq: Boolean = false; offentlig funksjon Main2 () {//Importere grafikk i skjemaet av MovieClip a = nye piler (); a.stop (); a.x = 50; a.y = 50; addChild (a);



      Trinn 17: Registrer Tilsvar Gestures

      Vi skal registrere våre gest sekvenser i den rekkefølgen grafikk er ordnet i vår publisert MovieClip. Vi gjør det for å gjøre lett rulling av rammer når resultatet er oppnådd. Merk også at jeg har markert linje 33 av gjennomføringen; du kan uncomment dette til i min kildefilen til Vis matchende gjøres for
      offentlig funksjon Main2 () {//Importere grafikk i form av MovieClip a = nye piler (.); a.stop (); a.x = 50; a.y = 50; addChild (a); //initiere MGesture å tillate enkelt gest gjenkjenning tot = new MGesture (scene); //initiere GManager å tillate sekvensiell gest deteksjon gesMan = new GManager (); //this.seq = true; //Oppdager bevegelser i rekkefølge if (seq) {a.gotoAndStop (2); gesMan.useSeq = true; } //Sett gest sekvenser i tråd med rammer //Registrer gest sekvenser i tråd med rammer gesMan.register (ny < int > [2, 1], "2 Stroke Down, CCW"); gesMan.register (ny < int > [1, 0], "2 Stroke Høyre, CCW"); gesMan.register (ny < int > [0, 3], "2 Stroke Up, CCW"); gesMan.register (ny < int > [3, 2], "2 Stroke Venstre, CCW"); gesMan.register (ny < int > [3, 2, 1], "3 Stroke Down, CCW"); gesMan.register (ny < int > [2, 1, 0], "3 Stroke Høyre, CCW"); gesMan.register (ny < int > [1, 0, 3], "3 Stroke Up, CCW"); gesMan.register (ny < int > [0, 3, 2], "3 Stroke Venstre, CCW"); gesMan.register (ny < int > [3, 0], "2 Stroke Høyre, CW"); gesMan.register (ny < int > [0, 1], "2 Stroke Down, CW"); gesMan.register (ny < int > [1, 2], "2 Stroke Venstre, CW"); gesMan.register (ny < int > [2, 3], "2 Stroke Up, CW"); gesMan.register (ny < int > [2, 3, 0], "3 Stroke Høyre, CW"); gesMan.register (ny < int > [3, 0, 1], "3 Stroke Down, CW"); gesMan.register (ny < int > [0, 1, 2], "3 Stroke Venstre, CW"); gesMan.register (ny < int > [1, 2, 3], "3 Stroke Up, CW"); gesMan.register (ny < int > [0, 3, 0, 3, 0], "Step Up"); gesMan.register (ny < int > [0, 1, 0, 1, 0], "Step Down"); gesMan.register (ny < int > [4], "South East"); gesMan.register (ny < int > [5], "South West"); gesMan.register (ny < int > [6], "North West"); gesMan.register (ny < int > [7], "North East"); gesMan.register (ny < int > [4, 5, 4, 5], "Zigzag"); stage.addEventListener (MouseEvent.MOUSE_DOWN, start); stage.addEventListener (MouseEvent.MOUSE_UP, end);}



      Trinn 18: Håndtering Resultater

      Opptak av gest sekvens følger samme tilnærming som CheckOut2. Jeg antar at leserne har gått gjennom Trinn 10. Så til slutt, vi skal utgang resultatet. Etter vellykket kamp (> -1), skal vi bla til riktig ramme. Igjen, dette er gjenstand for om du har aktivert bruk av sekvensen ved å slå på seq eller ikke
      privat funksjon enden (e: MouseEvent):. Void {stage.removeEventListener (MouseEvent.MOUSE_MOVE, sjekk); //evaluere gest og utgang resultat Var utgang: Array = gesMan.end () if (utgang [0] > -1) {if (seq) a.nextFrame (); annet a.gotoAndStop (output [0] + 2); //offset nødvendig som første rammen er tom. }}



      Trinn 19: publisere prosjekt

      Trykk Ctrl + Enter for å publisere prosjektet. Bevegelse med musen og hva som ble oppdaget. Jeg har tatt med begge prosjektene (ett ber deg å matche en gitt gest, de andre viser gesten du tegnet, om det samsvarer den vet). Ha det gøy



      Trinn 20:. Application Development

      unøyaktigheter i brukerens bevegelser er vanlig, og alle programmer som inkorporerer bevegelser bør vurdere dette. I neste del av denne opplæringen, skal jeg forsøke å bruke MGesture og GManager å utvikle et alfabet anerkjennelse program. Jeg skal peke ut flere detaljer å finpusse tilsvarende for å forbedre gest deteksjon.

      Konklusjon

      Du skal nå finne det enkelt å utvikle applikasjoner som gjenkjenner bevegelsessekvenser av en kombinasjon. Håper denne opplæringen har hjulpet deg på noen måter. La meg vite dine kommentarer, spørsmål og bugs oppstått. Terima kasih. Anmeldelser