Bygg en klassisk Snake spillet i AS3

Build en klassisk Snake spillet i AS3
Del
Del
11
Del
Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I denne opplæringen vil jeg gjerne vise deg hvor enkelt det er å lage en klassisk "Snake" spill i Flash. Jeg vil prøve å forklare alt lett, steg for steg, slik at du kan utvikle spillet videre til dine behov! Spillet vil bli utviklet i AS3, og jeg vil bruke FlashDevelop IDE.




Innledning

Spillet vil ikke være komplisert. Når vi treffer en vegg, vil den starte spillet. Etter å ha spist et eple slangen vil vokse, og en "ny" Apple vil vises. (Egentlig vil det være det samme eple, men jeg skal forklare dette senere.)

En av de viktigste aspektene av spillet er koden reaksjon på KEY_DOWN hendelser. Slangen vil bare da endre sin retning etter et flått har gått, ikke anbefale umiddelbart etter et tastetrykk. Dette betyr at dersom slangen går rett, og du trykker ned og venstre veldig fort, vil slangen gå ned, ikke ned og venstre. Uten denne "funksjonen" slangen ville tillate oss å gå til venstre mens vi går rett, noe som ville bety det slo seg selv.



La oss se på spillet allerede!

La oss se en titt på det endelige resultatet vi skal jobbe mot:



Trinn 1: Opprette prosjekt

I FlashDevelop, opprette et nytt prosjekt, og inne i "src" mappen oppretter en 'com' mappe. .. I 'com' mappe opprette en ny klasse, og kaller det "Element.as '

Angi dimensjonene i prosjektet til 600x600px



Trinn 2: Vent .. . Hva er et element?

Slangen er utgjør av blå firkanter, som jeg kaller elementer. Vi vil skape et element i klasse, som trekker elementet. Den røde eplet kommer til å være et element også, så vi vil forlenge kode med noen flere linjer.

Derfor vil vi ikke lage en ny klasse for eplet. (Men hvis du virkelig vil, du kan.)



Trinn 3: Skrive Element Class

The Element klassen skaper en firkant. Det trenger ikke å trekke det på scenen, det bare skaper det. Registreringen poenget med element - posisjonen referert til av x- og y-koordinater - er i øverste venstre

Etter å ha åpnet Element.as vil du se noe som dette:
<. p>
pakke com {/** * ... *author Fuszenecker Zsombor * /public class Element {offentlig funksjon Element () {}}}

Først må vi dette for å forlenge Shape klasse, så vi kan bruke grafikkobjekter å trekke torget. Etter dette, lage to variabler: en for den retningen (hvis det er en del av slange), og en for poengverdi (hvis det er et eple), og deretter endre parameterne for konstruktøren funksjon:


pakke com {import flash.display.Shape; public class Element strekker Shape {beskyttet Var _direction: String; //Hvis det er en APPLE - > beskyttet Var _catchValue: Number; //farge, alpha, bredde, høyde offentlig funksjon Element (_C: uint, presentasjon: Antall, _W: Antall, _h: Number) {}}}

Nå fyller funksjonen med noen kode:


pakke com {import flash.display.Shape; public class Element strekker Shape {beskyttet Var _direction: String; //Hvis det er en APPLE - > beskyttet Var _catchValue: Number; //farge, alpha, bredde, høyde offentlig funksjon Element (_C: uint, presentasjon: Antall, _W: Antall, _h: Number) {graphics.lineStyle (0, _C, presentasjon); graphics.beginFill (_C, presentasjon); graphics.drawRect (0, 0, _W, _h); graphics.endFill (); _catchValue = 0; }}}

Nå, når vi skaper et element, vil det tegne et rektangel og setter poengsum verdien av elementet til 0 som standard. (Det vil ikke sette rektangel på scenen, det bare trekker det i seg selv. Legg merke til at vi ikke har kalt addChild () -funksjonen.)

La oss avslutte denne klassen, og da kan vi endelig teste hvor mye vi har gjort allerede:


pakke com {import flash.display.Shape; public class Element strekker Shape {beskyttet Var _direction: String; //Hvis det er en APPLE - > beskyttet Var _catchValue: Number; //farge, alpha, bredde, høyde offentlig funksjon Element (_C: uint, presentasjon: Antall, _W: Antall, _h: Number) {graphics.lineStyle (0, _C, presentasjon); graphics.beginFill (_C, presentasjon); graphics.drawRect (0, 0, _W, _h); graphics.endFill (); _catchValue = 0; } //KUN brukes i tilfelle av en del av slangen offentlig funksjon angi retning (verdi: String): void {_direction = verdi; } Offentlig funksjon get retning (): String {return _direction; } //Kun brukt i tilfelle en APPLE offentlig funksjon satt catchValue (verdi: Number): void {_catchValue = verdi; } Offentlig funksjon får catchValue (): Antall {return _catchValue; }}}

Vi skapte fire funksjoner for å endre retninger og verdien av eple. Vi oppnådde dette ved hjelp av settere og getters. Mer om settere /Getters i denne artikkelen



Trinn 4:!. Testing av Element Class

Åpne Main.as nå

Importer com.Element klasse og skape et element i init () -funksjonen:


pakke {import flash.display.Sprite; import flash.events.Event; import com.Element; public class Hoved strekker Sprite {offentlig funksjon main () {if (scene) addEventListener (Event.ADDED_TO_STAGE, init); annet init (); } Private funksjon init (e: Hendelses = null): void {var testElement: Element = new Element (0x00AAFF, 1, 10, 10); testElement.x = 50; testElement.y = 50; this.addChild (testElement); }}}

Først skaper vi testElement variabel som holder vår del. Vi skaper et nytt element og tilordne det til vår testElement variabel. Legg merke til de argumentene vi passerte: først vi gi det en farge, så alfa, bredde og høyde. Hvis du ser i Element klassens Element funksjon, kan du se hvordan den bruker disse dataene til å tegne rektangelet.

Når du har opprettet Element, vi plassere den og sette den på scenen!



Trinn 5: Sette opp Variabler

Se på følgende kode. Jeg skrev funksjonene variablene ved siden av dem (legg merke til at vi importert de nødvendige klassene også):


pakke {import flash.display.Sprite; import flash.text.TextField; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.events.Event; import com.Element; public class Hoved strekker Sprite {//Ikke gi disse Vars en verdi her! //Gi dem deres verdier i init () -funksjonen. private Var snake_vector. Vector < Element >; //slangens deler holdes her inne privat Var markers_vector. Vector < Objekt >; //markørene holdes i her privat Var timer: Timer; private Var død: Boolean; private Var min_elements: int; //innehar hvor mange deler slangen skal ha i begynnelsen private Var eple: Element; //Vår eple private Var space_value: Number; //mellomrom mellom slangens deler private Var last_button_down: UINT; //nøkkelkoder for den siste knappen trykkes privat Var flagg: Boolean; //er det lov til å endre retning? private Var bedømmelsen: Antall; private Var score_tf: Textfield; //tekstfeltet som viser resultatet offentlig funksjon main () {if (scene) addEventListener (Event.ADDED_TO_STAGE, init); annet init (); } Private funksjon init (e: Hendelses = null). Void {snake_vector = new Vector < Element >; markers_vector = new Vector. < Objekt >; space_value = 2; //Det vil være 2px mellomrom mellom hver Element timer = new Timer (50); //Hver 50. millisekund, det MOVEIT () -funksjonen vil bli skutt! Dette vil sette SPEED av slange døde = false; min_elements = 10; //Vi vil begynne med 10 elementer. eple = new Element (0xff0000, 1, 10, 10); //rødt, ikke transparent, bredde: 10, høyde: 10; apple.catchValue = 0; //ganske opplagt - poengsummen av eple last_button_down = Keyboard.RIGHT; //Den første retningen av slangen ligger i denne variabelen poengsum = 0; score_tf = new Textfield (); //dette er Textfield som viser vår score. this.addChild (score_tf); }}}

Det viktigste variabelen er den snake_vector. Vi vil sette alle Element av slange i denne Vector.

Så er det markers_vector. Vi vil bruke markører for å angi retning av slangens deler. Hvert objekt i denne vektor vil ha en stilling og en type. Typen vil fortelle oss om slangen skulle gå til høyre, venstre, opp eller ned etter "treffer" objektet. (De vil ikke kolliderer, vil bare plasseringen av markører og slangens deler sjekkes.)

Som et eksempel, hvis vi trykker NED, et objekt vil bli opprettet. X- og y av dette objektet vil være slangens hode er x og y koordinater, og hvilken type vil være "Down". Når posisjonen til en av slangens Elements er det samme som denne objektets vil slanger elementer retning settes til "ned".

Vennligst les kommentarene ved siden av variablene for å forstå hva de andre variablene gjør!



Trinn 6: Skrive attachElement () Funksjon

attachElement () -funksjonen vil ta fire parametere: den nye slangen element, x og y koordinater, og retningen på Siste del av slange


privat funksjon attachElement. (som: Element, lastXPos: Antall = 0, lastYPos: Antall = 0, dirOfLast: String = "R"): void {}

Før vi satte element på scenen skal vi plassere den. Men for dette trenger vi retning av slangens siste elementet, for å vite om den nye element må være over under eller ved siden av dette.

Etter å sjekke retningen og den aktuelle posisjonen, vi kan legge det til scenen


privat funksjon attachElement. (som: Element, lastXPos: Antall = 0, lastYPos: Antall = 0, dirOfLast: String = "R"): void {if (dirOfLast == " R ") {who.x = lastXPos - snake_vector [0] .width - space_value; who.y = lastYPos; } Else if (dirOfLast == "L") {who.x = lastXPos + snake_vector [0] .width + space_value; who.y = lastYPos; } Else if (dirOfLast == "U") {who.x = lastXPos; who.y = lastYPos + snake_vector [0] .height + space_value; } Else if (dirOfLast == "D") {who.x = lastXPos; who.y = lastYPos - snake_vector [0] .height - space_value; } This.addChild (som);}

Nå kan vi bruke denne funksjonen i init () -funksjonen:


for (var i: int = 0, jeg < min_elements; ++ jeg ) {snake_vector [i] = new Element (0x00AAFF, 1,10,10); snake_vector [i] .direction = "R"; //Start retning av slange hvis (i == 0) //først slange element {//må du plassere det første elementet på et rutenett. (nå: 0,0) //[mulig x stillinger: (snake_vector [0] .width + space_value) * < UINT > ] AttachElement (snake_vector [i], 0,0, snake_vector [i] .direction) snake_vector [0] a = 0,7; } Else {attachElement (snake_vector [i], snake_vector [i - 1] .x, snake_vector [i - 1] .Y, snake_vector [i - 1] .direction); }}

Vi skaper de første 10 Elements, og angi retning av dem til 'R' (høyre). Hvis det er det første elementet, kaller vi attachElement () og vi endre sin alfa litt (slik at "hodet" er en litt lysere farge).

Hvis du ønsker å angi posisjonen et annet sted, så kan du ha følgende i bakhodet: slangen må plasseres på et rutenett, ellers ville det ser dårlig og ville ikke fungere. Dersom du ønsker å endre x og y posisjon du kan gjøre det på følgende måte:

I for loop, sjekker vi om Apples nye x og y-stillinger er identiske med noen av snake_vectors elementer. Hvis ja, vi kaller den placeApple () -funksjonen igjen (rekursiv funksjon), og sette parameter av det å falske. (Noe som betyr at eplet ikke ble fanget, vi trenger bare å flytte den)

(apple.stage) returnerer true hvis apple er på scenen. vi bruker '!' operatøren å snu denne verdien, så hvis det ikke er på scenen, vi plassere den der.

Det siste vi trenger å gjøre er å ringe placeApple () -funksjonen på slutten av init () -funksjonen.


privat funksjon init (e: Hendelses = null): void {/*. . . * /PlaceApple (false);}

Legg merke til at vi passerer falsk som parameter. Det er logisk, fordi vi ikke ta eplet i init () -funksjonen ennå. Vi vil bare ta det i MOVEIT () -funksjonen

Nå er det bare tre flere funksjoner for å skrive:.. Den directionChanged (), MOVEIT () og Gameover () funksjoner


< h2> Trinn 8: Starte MOVEIT () Funksjon

MOVEIT () -funksjonen er ansvarlig for alt av bevegelsen. Denne funksjonen vil sjekke grensene og sjekke om det er et objekt på x og y plasseringen av slangens hode. Det vil også se etter eplet i denne posisjonen

For alt dette, vil vi bruke vår timer variabel

Legg til to linjer i slutten av init () -funksjonen..


timer.addEventListener (TimerEvent.TIMER, MOVEIT); timer.start ();

Se på kommentarer i kildekoden, for å se hvilke kodeblokk gjør hva

privat funksjon MOVEIT (e: Timerevent): void {if (snake_vector [0] .x == apple.x & & snake_vector [0] .Y == apple.y) {//Denne koden kjøres hvis slanger hoder posisjon og epler posisjon er de samme} if (snake_vector [0] .x > stage.stageWidth-snake_vector [0] .width || snake_vector [0] .x < 0 || snake_vector [0] .Y > stage.stageHeight-snake_vector [0] .height || snake_vector [0] .Y < 0) {//Denne blokken kjøres hvis slanger hodet er ute av scenen (trykket veggene)} for (var i: int = 0; i < snake_vector.length; i ++) {/* START AV FOR BLOCK Hele denne "for" blokken vil kjøre så mange ganger, så mange elementer slangen har. Hvis det er fire slangedeler, vil hele denne for syklusen drives fire ganger. * /If (snake_vector [i] = snake_vector [0] &! &Amp; (snake_vector [0] .x == snake_vector [i] .x & & snake_vector [0] .Y == snake_vector [i]. y)) {//Hvis slanger hoder posisjon er den samme som noen av de slange deler, denne blokken vil kjøre (Kontroll av kollisjon med seg selv). } If (markers_vector.length > 0) {//hvis det er retnings markører, kjører denne koden} Var RETNING: String = snake_vector [i] .direction; //får strømretningen slange element. bryteren (retning) {//Setter nye posisjonen til slanger del} /* END OF FOR BLOCK * /}}

Nå må vi kode bevegelsen. For dette hopper vi inn i bryteren blokken, som vil kjøre på hver slange del, på grunn av for loop.

Først må vi sjekke retningen på det aktuelle elementet.


bryteren (retning) {case "R": //Her må vi sette den nye x posisjonen for den aktuelle delen break; case "L": //Her må vi sette den nye x posisjonen for den aktuelle delen break; case "D": //Her må vi sette den nye y posisjon for den aktuelle delen break; case "U": //Her må vi sette den nye y posisjon for den aktuelle delen break; }

Når retning av den delen er satt til "R", for eksempel, må vi legge til noe
til sin nåværende X stilling (space_value pluss bredden av slange del).

Med dette i tankene, vi kan fylle det ut:


bryteren (retning) {case "R": snake_vector [i] .x + = snake_vector [i] .width + space_value; gå i stykker; case "L": snake_vector [i] .x - = snake_vector [i] .width + space_value; gå i stykker; case "D": snake_vector [i] .Y + = snake_vector [i] .height + space_value; gå i stykker; case "U": snake_vector [i] .Y - = snake_vector [i] .width + space_value; gå i stykker; }

Etter å ha testet koden, skal du se at slangen er i bevegelse, og går av scenen og aldri stopper. (Du må kanskje oppdatere siden - eller bare klikk her for å legge det i et nytt vindu.)

Så vi må slutte slangen



Trinn 9: Skrive Gameover () Funksjon

Denne funksjonen kommer til å være den korteste. Vi fjerner bare scenen og starter den på nytt:


privat funksjon Gameover (): void {døde = true; timer.stop (); while (this.numChildren) this.removeChildAt (0); timer.removeEventListener (TimerEvent.TIMER, MOVEIT); init ();}

Det var det. Vi setter de døde variabelen til true, stoppe bevegelsen med timeren, fjerne alle barn av klassen og kaller init () -funksjonen, som vi nettopp startet spillet.

Nå, la oss komme tilbake til MOVEIT . () -funksjonen



Trinn 10: Fortsetter MOVEIT () Funksjon

Vi vil bruke Gameover () funksjonen på to steder. Den første er når vi sjekke om hodet er utenfor banen, og den andre er når slangen treffer selv:
privat funksjon MOVEIT (e: Timerevent): void {if (snake_vector [0] .x == eple. x & & snake_vector [0] .Y == apple.y) {//Denne koden kjøres hvis slanger hoder posisjon og epler posisjon er de samme} if (snake_vector [0] .x > stage.stageWidth- snake_vector [0] .width || snake_vector [0] .x < 0 || snake_vector [0] .Y > stage.stageHeight-snake_vector [0] .height || snake_vector [0] .Y < 0) { Gameover (); } For (var i: int = 0; i < snake_vector.length; i ++) {/* START AV FOR BLOCK Hele denne "for" blokken vil kjøre så mange ganger, så mange elementer slangen har. Hvis det er fire slangedeler, vil hele denne for syklusen drives fire ganger. * /If (snake_vector [i] = snake_vector [0] &! &Amp; (snake_vector [0] .x == snake_vector [i] .x & & snake_vector [0] .Y == snake_vector [i]. y)) {//Hvis slanger hoder posisjon er den samme som noen av de slange deler, denne blokken vil kjøre Gameover (); } If (markers_vector.length > 0) {//hvis det er retnings markører, kjører denne koden} Var RETNING: String = snake_vector [i] .direction; //får strømretningen slange element. bryteren (retning) {case "R": snake_vector [i] .x + = snake_vector [i] .width + space_value; gå i stykker; case "L": snake_vector [i] .x - = snake_vector [i] .width + space_value; gå i stykker; case "D": snake_vector [i] .Y + = snake_vector [i] .height + space_value; gå i stykker; case "U": snake_vector [i] .Y - = snake_vector [i] .width + space_value; gå i stykker; } /* END OF FOR BLOCK * /}}

Dette er koden vi har nå:


pakke {import flash.display.Sprite; import flash.text.TextField; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.events.Event; import com.Element; public class Hoved strekker Sprite {//IKKE GI DEM EN VERDI HER! Gi dem en verdi i init () -funksjonen privat Var snake_vector. Vector < Element >; //slangens deler holdes her inne privat Var markers_vector. Vector < Objekt >; //markørene holdes i her privat Var timer: Timer; private Var død: Boolean; private Var min_elements: int; //innehar hvor mange deler bør slangen ha i begynnelsen private Var eple: Element; //Vår eple private Var space_value: Number; //mellomrom mellom slange deler private Var last_button_down: UINT; //nøkkelkoder for den siste knappen trykkes privat Var flagg: Boolean; //er det lov til å endre retning? private Var bedømmelsen: Antall; private Var score_tf: Textfield; //tekstfeltet som viser resultatet offentlig funksjon main () {if (scene) addEventListener (Event.ADDED_TO_STAGE, init); annet init (); } Private funksjon init (e: Hendelses = null). Void {snake_vector = new Vector < Element >; markers_vector = new Vector. < Objekt >; space_value = 2; timer = new Timer (50); //Hver 50. millisekund, det MOVEIT () -funksjonen vil bli skutt! dead = false; min_elements = 10; //Vi vil begynne med 10 elementer. apple = new Element (0xff0000, 1,10, 10); //rødt, ikke transparent, bredde: 10, høyde: 10; apple.catchValue = 0; //ganske opplagt last_button_down = Keyboard.RIGHT; //Den første retningen av slangen ligger i denne variabelen poengsum = 0; score_tf = new Textfield (); //dette er Textfield som viser vår score. this.addChild (score_tf); for (var i: int = 0, jeg < min_elements, ++ i) {snake_vector [i] = new Element (0x00AAFF, 1,10,10); snake_vector [i] .direction = "R"; //Start retning av slange hvis (i == 0) //først slange element {//må du plassere det første elementet på et rutenett. (nå: 0,0) [mulig x stillinger: (snake_vector [0] .width + space_value) * < UINT > ] AttachElement (snake_vector [i], (snake_vector [0] .width + space_value) * 20 (snake_vector [0] .height + space_value) * 10, snake_vector [i] .direction); snake_vector [0] a = 0,7; } Else {attachElement (snake_vector [i], snake_vector [i - 1] .x, snake_vector [i - 1] .Y, snake_vector [i - 1] .direction); }} PlaceApple (false); timer.addEventListener (TimerEvent.TIMER, MOVEIT); timer.start (); } Private funksjon attachElement (som: Element, lastXPos: Antall = 0, lastYPos: Antall = 0, dirOfLast: String = "R"): void {if (dirOfLast == "R") {who.x = lastXPos - snake_vector [ ,,,0],0] .width - space_value; who.y = lastYPos; } Else if (dirOfLast == "L") {who.x = lastXPos + snake_vector [0] .width + space_value; who.y = lastYPos; } Else if (dirOfLast == "U") {who.x = lastXPos; who.y = lastYPos + snake_vector [0] .height + space_value; } Else if (dirOfLast == "D") {who.x = lastXPos; who.y = lastYPos - snake_vector [0] .height - space_value; } This.addChild (som); } Private funksjon placeApple (fanget: Boolean = true): void {if (fanget) apple.catchValue + = 10; Var boundsX: int = (Math.floor (stage.stageWidth /(snake_vector [0] .width + space_value))) - 1; Var randomX: Number = Math.floor (Math.random () * boundsX); Var boundsY: int = (Math.floor (stage.stageHeight /(snake_vector [0] .height + space_value))) - 1; Var randomY: Number = Math.floor (Math.random () * boundsY); apple.x = randomX * (apple.width + space_value); apple.y = randomY * (apple.height + space_value); for (var i: uint = 0; i < snake_vector.length-1; i ++) {if (snake_vector [i] .x == apple.x & & snake_vector [i] .Y == apple.y) placeApple (falsk); } If (apple.stage!) This.addChild (eple); } Private funksjon MOVEIT (e: Timerevent): void {if (snake_vector [0] .x == apple.x & & snake_vector [0] .Y == apple.y) {//Denne koden kjøres hvis slangene hoder posisjon og epler posisjon er de samme} if (snake_vector [0] .x > stage.stageWidth-snake_vector [0] .width || snake_vector [0] .x < 0 || snake_vector [0] .Y > stage.stageHeight-snake_vector [0] .height || snake_vector [0] .Y < 0) {Gameover (); } For (var i: int = 0; i < snake_vector.length; i ++) {/* START AV FOR BLOCK Hele denne "for" blokken vil kjøre så mange ganger, så mange elementer slangen har. Hvis det er fire slangedeler, vil hele denne for syklusen drives fire ganger. * /If (snake_vector [i] = snake_vector [0] &! &Amp; (snake_vector [0] .x == snake_vector [i] .x & & snake_vector [0] .Y == snake_vector [i]. y)) {//Hvis slanger hoder posisjon er den samme som noen av de slange deler, denne blokken vil kjøre Gameover (); } If (markers_vector.length > 0) {//hvis det er retnings markører, kjører denne koden} Var RETNING: String = snake_vector [i] .direction; //får strømretningen slange element. bryteren (retning) {case "R": snake_vector [i] .x + = snake_vector [i] .width + space_value; gå i stykker; case "L": snake_vector [i] .x - = snake_vector [i] .width + space_value; gå i stykker; case "D": snake_vector [i] .Y + = snake_vector [i] .height + space_value; gå i stykker; case "U": snake_vector [i] .Y - = snake_vector [i] .width + space_value; gå i stykker; } /* END OF FOR BLOCK * /}} privat funksjon Gameover (): void {døde = true; timer.stop (); while (this.numChildren) this.removeChildAt (0); timer.removeEventListener (TimerEvent.TIMER, MOVEIT); //stage.removeEventListener(KeyboardEvent.KEY_DOWN,directionChanged); i det(); }}}



Trinn 11: directionChanged () Funksjon

Vi ønsker å lytte til tastaturet, slik at vi faktisk kan styre slangen. Til dette trenger vi å sette noen kode i init () -funksjonen og Gameover () -funksjonen

Sett dette på slutten av init () -funksjonen (sette opp lytteren funksjon).
< p>
stage.addEventListener (KeyboardEvent.KEY_DOWN, directionChanged);

Og dette på slutten av Gameover () -funksjonen:


stage.removeEventListener (KeyboardEvent.KEY_DOWN, directionChanged);

Nå opprette en ny funksjon:


privat funksjon directionChanged (e: KeyboardEvent): void {var m: Object = new Object (); //MARKER OBJECT //dette vil bli lagt til markers_vector, og har egenskapene x, y, og skriv //type eiendom vil vise oss retningen. hvis den er satt til høyre, når en slange del treffer den, //retning av at slangens delen vil bli satt rett også til if (e.keyCode == Keyboard.LEFT & &! last_button_down = e.keyCode & & last_button_down = Keyboard.RIGHT) {//Hvis vi trykket VENSTRE pil, //og det var ikke den siste nøkkelen vi trykket, //og sist trykte tast var ikke høyre pil heller ... //Så! denne blokken av koden vil kjøre} markers_vector.push (m); //vi skyver objektet inn i en vektor, så vi kan acces til det senere (i MOVEIT () -funksjonen)}

Hva går inn i hvis blokken?

retning av hodet bør skrives om.

har Markøren objekt å være riktig innstilt.

last_button variable bør settes til den siste knappen trykkes.


hvis (e.keyCode == Keyboard.LEFT & &! last_button_down = e.keyCode & & last_button_down = Keyboard.RIGHT &! & flagg) {snake_vector [0] .direction = "L"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "L"}; last_button_down = Keyboard.LEFT;}

Gjenta dette tre ganger, og vi vil ha dette:


privat funksjon directionChanged (e: KeyboardEvent): void {var m: Object = new Object ( ); //MARKER OBJECT if (e.keyCode == Keyboard.LEFT & &! Last_button_down = e.keyCode & &! Last_button_down = Keyboard.RIGHT) {snake_vector [0] .direction = "L"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "L"}; last_button_down = Keyboard.LEFT; } Else if (e.keyCode == Keyboard.RIGHT & &! Last_button_down = e.keyCode & & last_button_down = Keyboard.LEFT!) {Snake_vector [0] .direction = "R"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "R"}; last_button_down = Keyboard.RIGHT; } Else if (e.keyCode == Keyboard.UP & &! Last_button_down = e.keyCode & & last_button_down = Keyboard.DOWN!) {Snake_vector [0] .direction = "U"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "U"}; last_button_down = Keyboard.UP; } Else if (e.keyCode == Keyboard.DOWN & &! Last_button_down = e.keyCode & &! Last_button_down = Keyboard.UP) {snake_vector [0] .direction = "D"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "D"}; last_button_down = Keyboard.DOWN; } Markers_vector.push (m); }

Vi trenger en ting til å teste den. I MOVEIT () -funksjonen har vi noe sånt som dette:


if (markers_vector.length > 0) {//hvis det er retnings markører, kjører denne koden}

Her trenger vi en annen for loop, for å sjekke hver slange del mot hver markør på scenen, og sjekke om de kolliderer. Hvis de gjør det, må vi sette slangens del retning til markørens type. Hvis det er det siste slange del som kolliderer med markøren, må vi fjerne markøren fra markers_vector, også, så slange deler ikke kolliderer med det lenger.


if (markers_vector.length > 0) {for (var j: uint = 0; j < markers_vector.length; j ++) {if (snake_vector [i] .x == markers_vector [ ,,,0],j] .x & & snake_vector [i] .Y == markers_vector [j] .Y) {//sette retning snake_vector [i] .direction = markers_vector [j] .type; if (i == snake_vector.length-1) {//om sin siste snake_part markers_vector.splice (j, 1); }}}}

Nå hvis du spiller med det det ser ordentlig ut, men det er en feil i det. Husk hva jeg sa i begynnelsen av opplæringen?

For eksempel, hvis slangen går til høyre og du trykker ned venstre combo veldig fort, det vil treffe seg selv og starte spillet.

Hvordan kan vi løse dette? Vel det er enkelt. Vi har vårt flagg variabel, og vi vil bruke den for dette. Vi vil bare være i stand til å endre retninger av slange når denne er satt til true (Standard er falsk, sjekk init () -funksjonen for det).

Så vi må endre directionChanged () -funksjonen en lite. If blokker 'hoder bør endres: legg en & & flagg klausul på slutten av hver "hvis"


privat funksjon directionChanged (e: KeyboardEvent): void {var m.: Object = new Object (); //MARKER OBJECT if (e.keyCode == Keyboard.LEFT & &! Last_button_down = e.keyCode & &! Last_button_down = Keyboard.RIGHT & & flagg) {snake_vector [0] .direction = "L "; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "L"}; last_button_down = Keyboard.LEFT; flag = false; } Else if (e.keyCode == Keyboard.RIGHT & &! Last_button_down = e.keyCode & & last_button_down = Keyboard.LEFT &! &Amp; flagg) {snake_vector [0] .direction = "R"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "R"}; last_button_down = Keyboard.RIGHT; flag = false; } Else if (e.keyCode == Keyboard.UP & &! Last_button_down = e.keyCode & & last_button_down = Keyboard.DOWN &! &Amp; flagg) {snake_vector [0] .direction = "U"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "U"}; last_button_down = Keyboard.UP; flag = false; } Else if (e.keyCode == Keyboard.DOWN & &! Last_button_down = e.keyCode & & last_button_down = Keyboard.UP &! &Amp; flagg) {snake_vector [0] .direction = "D"; m = {x: snake_vector [0] .x, y: snake_vector [0] .Y skriver du: "D"}; last_button_down = Keyboard.DOWN; flag = false; } Markers_vector.push (m); }

Hvis du tester det nå, det vil ikke fungere fordi flagget er alltid falsk.

Når trenger vi å sette den til sant da?

Etter et trekk /hake vi kan tillate brukere å endre retninger, vi ønsker ikke å endre det to ganger på én hake. Så sette dette helt på slutten av MOVEIT () -funksjonen.


flagg = true;

Nå teste det, og det er ingen feil lenger



Trinn 12: Finishing the Game

Nå er det eneste vi trenger å gjøre er "eple-sjekk '

Husk dette helt i begynnelsen av MOVEIT () -funksjonen
?


if (snake_vector [0] .x == apple.x & & snake_vector [0] .Y == apple.y) {//Denne koden kjøres hvis slangens hode posisjon og Apples posisjon er de samme}

Dette er hva vi trenger å gjøre i det:

Ring placeApple () -funksjonen. (Vi setter parameteren til false; vi la den være som den er Standard er sant..)

  • Vis gjeldende poengsum

    Legg ved et nytt element til slangens siste delen.


    if (snake_vector [0] .x == apple.x & & snake_vector [0] .Y == apple.y) {//ringe placeApple () -funksjonen placeApple (); //vise gjeldende Score poengsum + = apple.catchValue; score_tf.text = "Resultat:" + String (score); //Sett på en ny slange Element snake_vector.push (nytt Element (0x00AAFF, 1,10,10)); snake_vector [snake_vector.length-1] .direction = snake_vector [snake_vector.length-2] .direction; //lastOneRichtung //attachElement (som, lastXPos, lastYPos, lastDirection) attachElement (snake_vector [snake_vector.length-1], (snake_vector [snake_vector.length-2] x), snake_vector [snake_vector.length-2] .Y, snake_vector [snake_vector.length-2] .direction); }

    Nå er alt skal fungere fint. Prøv selv:

    Her er hele hoved klassen igjen:


    pakke {import flash.display.Sprite; import flash.text.TextField; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.events.Event; import com.Element; public class Hoved strekker Sprite {//IKKE GI DEM EN VERDI HER! Gi dem en verdi i init () -funksjonen privat Var snake_vector. Vector < Element >; //slangens deler holdes her inne privat Var markers_vector. Vector < Objekt >; //markørene holdes i her privat Var timer: Timer; gå i stykker; gå i stykker; gå i stykker; gå i stykker;