Lag en Plane slåssespill i Corona: Mer Gameplay

Create a Plane slåssespill i Corona: Mer Gameplay
22
Del
en
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 Opprett en Plane slåssespill i Corona.Create a Plane slåssespill i Corona. GameplayCreate a Plane slåssespill i Corona: Ferdigstilling GameplayWhat du skal lage
Innledning

I forrige tutorial av denne serien, begynte vi å implementere spillets gameplay og allerede rukket å få flyet beveger seg rundt på skjermen. I denne opplæringen, vil vi fortsette å implementere gameplay. La oss hoppe rett inn med startTimers funksjonen.

1. startTimers

Som navnet indikerer, starter startTimers funksjon tidtakerne. . Legg til følgende kode i gamelevel.lua
funksjons startTimers () end

Påkall denne funksjonen i enterScene metoden som vist nedenfor
funksjon scene. EnterScene (hendelse) lokal planeSound = audio.loadStream ("planesound.mp3") planeSoundChannel = audio.play (planeSound, {sløyfer = -1}) Spilletid: addEventListener ("enterframe", gameLoop) startTimers () end
2. . firePlayerBullet

firePlayerBullet funksjonen lager en kule for spilleren
funksjon firePlayerBullet () lokal tempBullet = display.newImage ("bullet.png", (player.x + playerWidth /2) - bulletWidth, player.y-bulletHeight) table.insert (playerBullets, tempBullet); planeGroup: innsats (tempBullet) end

Her bruker vi Skjerm objektets newImage metode for å lage kule. Vi plasserer det på en slik måte at det er i midten av flyet på x-aksen og på toppen av flyet på y-aksen. Kulen blir deretter satt inn i playerBullets bord for senere referanse og også inn i planeGroup.

3. Ringe firePlayerBullet

Vi må ringe firePlayerBullet funksjonen jevne mellomrom for å være sikker på spillerens planet blir automatisk skyte kuler. Legg inn følgende kode i startTimers funksjonen.
Funksjons startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) end

Som navnet indikerer, kaller Timer er performWithDelay metode en bestemt funksjon etter en periode tid har gått. Tiden er i millisekunder, så her er vi kalle firePlayerBullet fungere hvert sekund. Ved bestått -1 som den tredje argument, vil timeren gjenta alltid.

Hvis du teste spillet nå, bør du se at annethvert sekund en kule vises. De er imidlertid ennå ikke er i bevegelse. Vi vil ta vare på det i de neste trinnene.

4. movePlayerBullets

I movePlayerBullets, vi sløyfe gjennom playerBullets tabellen og endre y koordinat for hver kule. Vi først sjekke at den playerBullets tabellen har kuler i den. Den # før playerBullets kalles lengde
operatør og den returnerer lengden på objektet det er tilkalt. Det er nyttig å vite at # operatør fungerer også på strenger
funksjons movePlayerBullets () if (#playerBullets > 0). Deretter for i = 1, # playerBullets gjøre playerBullets [i]. y = playerBullets [i] .Y - 7 slutten Sluttslutt

Vi trenger å påberope movePlayerBullets i gameLoop funksjon som vist nedenfor
funksjon gameLoop () --SNIP-- numberOfTicks = numberOfTicks + 1 movePlayer () movePlayerBullets (. ) end
5. checkPlayerBulletsOutOfBounds

Når en kule går off-skjermen, er det ikke lenger relevant til spillet. Men de er fortsatt en del av playerBullets bordet og fortsette å bevege seg som alle andre kule i tabellen. Dette er en sløsing med ressurser, og hvis spillet skulle gå på i svært lang tid, vil det resultere i hundrevis eller tusenvis av ubrukte gjenstander.

For å overvinne dette, overvåker vi kulene, og når de flytte off-screen, fjerner vi dem fra playerBullets bordet samt fra fra displayet. Ta en titt på gjennomføringen av checkPlayerBulletsOutOfBounds
funksjons checkPlayerBulletsOutOfBounds () if (#playerBullets > 0). Deretter for i = # playerBullets, 1, -1 gjøre hvis (playerBullets [i] .Y < -18) deretter playerBullets [i]: removeSelf () playerBullets [i] = null table.remove (playerBullets, i) end end Sluttslutt

Det er viktig å merke seg at vi er looping gjennom playerBullets tabellen i baklengs. Hvis vi sløyfe gjennom tabellen fremover, da, når vi fjerner en av kulene, det ville kaste looping indeksen av og forårsaker en feil. Ved looping over bordet i omvendt rekkefølge, blir den siste kulen allerede behandlet. Den removeSelf metoden fjerner skjermen objektet og frigjør minnet. Som en beste praksis, bør du sette noen gjenstander til null etter ringer removeSelf.

Vi benytter denne funksjonen i gameLoop funksjonen.
Funksjon gameLoop () --SNIP-- movePlayer () movePlayerBullets () checkPlayerBulletsOutOfBounds () end

Hvis du vil se om denne funksjonen fungerer som den skal, kan du midlertidig sette en print ("Fjerne Bullet") uttalelse umiddelbart etter å sette skjermobjekt til null.

6. generateIsland

For å gjøre spillet mer interessant, genererer vi en øy hver så ofte, og flytt det ned på skjermen for å gi inntrykk av flyet flyr over øyene. . Legg inn følgende kode for generateIsland funksjon
funksjon generateIsland () lokal tempIsland = display.newImage ("island1.png", Math.random (0, display.contentWidth - islandWidth), - islandHeight) table.insert ( øyer, tempIsland) islandGroup: sett (tempIsland) end

Vi gjør bruk av newImage metoden igjen og posisjonere øya ved å sette en negativ verdi for islandHeight. For x posisjon, bruker vi Math.random metode for å generere et tall mellom 0 og skjermens contentWidth minus islandWidth. Grunnen til at vi trekker fra bredden av øya er å sørge for at øya er helt på skjermen. Hvis vi ikke ville trekke øyas bredde, ville det være en mulighet for at en del av øya ikke ville være på skjermen.

Vi må begynne en timer for å generere en øy hver så ofte. Legg til følgende tekstutdraget til startTimers funksjon vi opprettet tidligere. Som du kan se, er vi genererer en øy hver
fem sekunder. I neste trinn, vil vi sørge øyene flytte.
Funksjons startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) end
7. moveIslands

Gjennomføringen av moveIslands er nesten identisk med movePlayerBullets funksjonen. Vi sjekker om øyene tabellen inneholder noen øyer, og hvis det gjør det, vi sløyfe gjennom det og gå hver øy litt
funksjons moveIslands () if (#islands > 0). Deretter for i = 1 , #islands gjøre øyer [i] .Y = øyer [i] .Y + 3 slutten Sluttslutt
8. checkIslandsOutOfBounds

Akkurat som vi sjekke om spillerens kuler har flyttet off-screen, sjekker vi om noen av øyene hadde flyttet off-screen. Gjennomføringen av checkIslandsOutOfBounds bør derfor se kjent ut for deg. Vi sjekker om øyene y posisjon er større enn display.contentHeight og hvis det er, vet vi øya har flyttet off-screen, og kan derfor fjernes
funksjons checkIslandsOutOfBounds () if (#islands > 0). Deretter for I = # øyer, 1, -1 gjøre hvis (øyer [i] .Y > display.contentHeight) så øyene [i]: removeSelf () øyer [i] = null table.remove (øyer, i) end end Sluttslutt
9. generateFreeLife

Hver så ofte, har spilleren en sjanse til å få et fritt liv. Vi først generere et fritt liv image og hvis spilleren kolliderer med bildet de får et ekstra liv. Spilleren kan ha maksimalt seks liv
funksjon generateFreeLife () if (numberOfLives > = 6). Deretter tilbake end lokale Freelife = display.newImage ("newlife.png", Math.random (0, display.contentWidth - 40), 0); table.insert (freeLifes, Freelife) planeGroup: sett (Freelife) end

Hvis spilleren allerede har seks liv, vi gjør ingenting ved å returnere tidlig fra funksjonen. Hvis ikke, oppretter vi et nytt liv bilde og legge det til skjermen. I likhet med hvordan vi plassert øyene tidligere, setter vi bildet i en negativ y posisjon og generere en tilfeldig verdi for bildets x posisjon. Vi deretter sette den inn i freeLifes bordet for å være i stand til å referere til den senere.

Vi må kalle denne funksjonen hver så ofte. Legg til følgende tekstutdraget til startTimers funksjonen.
Funksjons startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) generateFreeLifeTimer = timer.performWithDelay (7000, generateFreeLife, - 1) end
10. moveFreeLives

Gjennomføringen av moveFreeLifes bør se kjent. Vi er looping gjennom freeLifes bordet og flytte hvert bilde i det
funksjons moveFreeLifes () if (#freeLifes > 0). Deretter for i = 1, # freeLifes gjøre freeLifes [i] .Y = freeLifes [ ,,,0],i] .Y fem slutten Sluttslutt

Alt vi trenger å gjøre er å ringe moveFreeLifes i gameLoop funksjonen.
funksjon gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () end
11. checkFreeLifesOutOfBounds

Følgende kodebiten bør også se kjent ut for deg nå. Vi sjekker om noen av bildene i freeLifes tabellen har flyttet off-screen og fjerne de som har
funksjons checkFreeLifesOutOfBounds () if (#freeLifes > 0). Deretter for i = # freeLifes, 1, -1 do if (freeLifes [i] .Y > display.contentHeight) så freeLifes [i]: removeSelf () freeLifes [i] = null table.remove (freeLifes, i) end end end end

Vi kaller denne funksjonen i gameLoop funksjon.
funksjon gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () checkFreeLifesOutOfBounds () end
12. hasCollided

Vi må være i stand til å fortelle når spill objekter kolliderer med hverandre, for eksempel spillerens flyet og de frie liv bilder, kuler og flyene, etc. Mens Corona tilbyr en meget robust fysikk motor som kan enkelt håndtere kollisjoner mellom visningsobjekter for oss, gjør dette legger litt av overhead med beregningene motoren har å gjøre hvert eneste bilde.

I forbindelse med dette spillet, vi skal bruke en enkel markeringsrammen kollisjon deteksjonssystem. Hva denne funksjonen gjør, er å sørge for at rektangler eller markeringsbokser rundt to objekter ikke overlapper hverandre. Hvis de gjør det, blir objektene kolliderer. Denne logikken er implementert i hasCollided funksjonen.
Funksjon hasCollided (obj1, obj2) if (obj1 == null) så return false end if (obj2 == null) så return false slutten lokal venstre = obj1.contentBounds.xMin < = obj2.contentBounds.xMin og obj1.contentBounds.xMax > = obj2.contentBounds.xMin lokal høyre = obj1.contentBounds.xMin > = obj2.contentBounds.xMin og obj1.contentBounds.xMin < = obj2.contentBounds. xMax lokal opp = obj1.contentBounds.yMin < = obj2.contentBounds.yMin og obj1.contentBounds.yMax > = obj2.contentBounds.yMin lokal ned = obj1.contentBounds.yMin > = obj2.contentBounds.yMin og obj1. contentBounds.yMin < = obj2.contentBounds.yMax avkastning (venstre eller høyre) og (opp eller ned) end

Jeg fant denne kodebiten på CoronaLabs nettstedet. Det fungerer veldig bra, fordi spillobjektene i spillet vårt er rektangulære. Hvis du arbeider med objekt som ikke er rektangulære, så du bedre dra nytte av Corona fysikkmotor som sin dueller er meget godt optimalisert for dette.

13. checkPlayerCollidesWithFreeLife

Vi ønsker å sjekke om spillerens fly har kollidert med et fritt liv objekt. Hvis det har, så vi belønne spilleren et fritt liv
funksjon checkPlayerCollidesWithFreeLife () if (#freeLifes > 0). Deretter for i = # freeLifes, 1, -1 gjøre hvis (hasCollided (freeLifes [i], spiller )) så freeLifes [i]: removeSelf () freeLifes [i] = null table.remove (freeLifes, i) numberOfLives = numberOfLives + 1 hideLives () showLives () end end Sluttslutt

I checkPlayerCollidesWithFreeLife funksjon, vi sløyfe gjennom den freeLives bordet bakover for samme grunn jeg beskrev tidligere. Vi kaller hasCollided funksjon og passere i det aktuelle bildet og spillerens flyet. Hvis de to objekt kolliderer, fjerner vi det frie liv image, øke de numberOfLives variabel, og kaller hideLives og showLives funksjon

Vi benytter denne funksjonen i gameLoop funksjon
funksjon gameLoop ().. - SNIP-- moveFreeLifes () checkFreeLifesOutOfBounds () checkPlayerCollidesWithFreeLife () end
14. hideLives

hideLives funksjon looper gjennom livesImages bordet og setter isVisible tilhører hvert liv bilde til falske.
funksjons hideLives () for i = 1, 6 gjøre livesImages [i] .isVisible = false Sluttslutt
15. showLives

showLives funksjon looper gjennom livesImages bordet og setter hvert bildes isVisible eiendom til sann
funksjons showLives () for i = 1, numberOfLives gjøre livesImages [i] .isVisible = sant.; Sluttslutt
Konklusjon

Dette bringer den tredje delen av denne serien til en avslutning. I neste og siste avdrag av denne serien, vil vi skape fiendtlige fly og avsluttet spillets gameplay. Takk for lesing og se deg der.