I den tidligere opplæringen av denne serien begynte vi å implementere spillets spill og klarte allerede å få flyet til å bevege seg rundt på skjermen. I denne opplæringen fortsetter vi å implementere spillingen. La oss dykke rett inn i startTimers
funksjon.
startTimers
Som navnet antyder, er startTimers
funksjonen starter timeren. Legg til følgende kode til gamelevel.lua.
funksjon startTimers () slutten
Oppgi denne funksjonen i enterScene
metode som vist nedenfor.
funksjonsscene: enterScene (event) lokalplanSound = audio.loadStream ("planesound.mp3") planetSoundChannel = audio.play (planetSound, loops = -1) Runtime: addEventListener ("enterFrame", gameLoop) startTimers
firePlayerBullet
De firePlayerBullet
funksjonen skaper en kulde for spilleren.
funksjon firePlayerBullet () local tempBullet = display.newImage ("bullet.png", (player.x + playerWidth / 2) - bulletWidth, player.y-bulletHeight) table.insert (playerBullets, tempBullet); planeGroup: sett inn (tempBullet) ende
Her bruker vi Display-objektet newImage
metode for å skape kule. Vi posisjonerer den på en slik måte at den er i midten av flyet på x-aksen og øverst på planet på y-aksen. Kulen settes deretter inn i playerBullets
bord for senere referanse og også inn i planeGroup
.
firePlayerBullet
Vi må ringe firePlayerBullet
fungere med jevne mellomrom for å sikre at spillerens plan automatisk skyver kuler. Legg til følgende kodestykke i startTimers
funksjon.
funksjon startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) slutten
Som navnet antyder, er timeren performWithDelay
Metoden kaller en spesifisert funksjon etter at en tidsperiode er gått. Tiden er i millisekunder, så her ringer vi på firePlayerBullet
Funksjon hvert 2. sekund. Ved å passere -1
Som det tredje argumentet vil timeren gjenta for alltid.
Hvis du tester spillet nå, bør du se at hvert eneste sekund vises en kule. Imidlertid beveger de seg ikke ennå. Vi vil ta vare på det i de neste trinnene.
movePlayerBullets
I movePlayerBullets
, vi løp gjennom playerBullets
bord og endre y
koordinat av hvert punktum. Vi kontrollerer først for å sikre at playerBullets
bordet har kuler i den. De #
før playerBullets
kalles lengde operatør og det returnerer lengden på objektet det er påkalt. Det er nyttig å vite at #
operatør jobber også på strenger.
funksjon movePlayerBullets () hvis (#playerBullets> 0) så for i = 1, # playerBullets gjør playerBullets [i]. y = playerBullets [i] .y - 7 slutten slutten
Vi må påberope movePlayerBullets
i gameLoop
fungere som vist nedenfor.
funksjon gameLoop () --SNIP-- numberOfTicks = numberOfTicks + 1 movePlayer () movePlayerBullets () ende
checkPlayerBulletsOutOfBounds
Når en kule går på skjermen, er den ikke lenger relevant for spillet. Imidlertid er de fortsatt en del av playerBullets
bord og fortsett å bevege seg som alle andre kuler i bordet. Dette er spild av ressurser, og hvis spillet skulle fortsette i svært lang tid, ville det resultere i hundrevis eller tusenvis av ubrukte objekter.
For å overvinne dette overvåker vi kulene, og når de beveger seg på skjermen, fjerner vi dem fra playerBullets
bord samt fra fra displayet. Ta en titt på implementeringen av checkPlayerBulletsOutOfBounds
.
funksjonskontrollPlayerBulletsOutOfBounds () hvis (#playerBullets> 0) så for i = # playerBullets, 1, -1 gjør hvis (playerBullets [i] .y < -18) then playerBullets[i]:removeSelf() playerBullets[i] = nil table.remove(playerBullets,i) end end end end
Det er viktig å merke seg at vi løper gjennom playerBullets
bord i bakover. Hvis vi går gjennom bordet fremover, da, når vi fjerner en av kulene, vil den kaste loopingsindeksen av og forårsake en feil. Ved å løfte over bordet i omvendt rekkefølge, er den siste kulen allerede behandlet. De removeSelf
Metoden fjerner skjermobjektet og frigjør dets minne. Som en god praksis bør du stille inn noen objekter nil
etter å ha ringt removeSelf
.
Vi påberoper denne funksjonen i gameLoop
funksjon.
funksjon gameLoop () --SNIP-- movePlayer () movePlayerBullets () kontrollerBlitterBulletsOutOfBounds () ende
Hvis du vil se om denne funksjonen fungerer som den skal, kan du midlertidig sette inn en print ("Fjerner Bullet")
uttalelse umiddelbart etter at skjermobjektet er satt til nil
.
generateIsland
For å gjøre spillet mer interessant, genererer vi en øy hver så ofte, og flytter den nedover skjermen for å gi utseendet til flyet som flyr over øyene. Legg til følgende kodestykke for generateIsland
funksjon.
funksjon generereIsland () lokal tempIsland = display.newImage ("island1.png", math.random (0, display.contentWidth - islandWidth), - islandHeight) table.insert (øyer, tempIsland) islandGroup: insert (tempIsland) end
Vi benytter oss av newImage
metode igjen og plassere øya ved å sette en negativ verdi for islandHeight
. For x
stilling, bruker vi math.random
metode for å generere et tall mellom 0
og vise
's contentWidth
minus islandWidth
. Grunnen til at vi trekker bredden på øya er å sørge for at øya er helt på skjermen. Hvis vi ikke ville trekke øyas bredde, ville det være en sjanse for at en del av øya ikke ville være på skjermen.
Vi må starte en timer for å generere en øy hver så ofte. Legg til følgende utdrag til startTimers
funksjonen vi opprettet tidligere. Som du kan se, genererer vi en øy hverfem sekunder. I neste trinn vil vi gjøre øyene flytte.
funksjon startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) end
moveIslands
Gjennomføringen av moveIslands
er nesten identisk med movePlayerBullets
funksjon. Vi sjekker om øyer
Bordet inneholder noen øyer, og hvis det gjør det, går vi gjennom det og flytter hver øy litt.
funksjon flytterlands () hvis (#islands> 0) da for i = 1, #islands øyene [i] .y = øyene [i] .y + 3 endeenden
checkIslandsOutOfBounds
Akkurat som vi kontrollerer om spillernes kuler har flyttet på skjermen, kontrollerer vi om noen av øyene hadde flyttet på skjermen. Gjennomføringen av checkIslandsOutOfBounds
bør derfor se deg kjent. Vi sjekker om øyene y
posisjonen er større enn display.contentHeight
og hvis det er, vet vi at øya har beveget seg på skjermen og derfor kan fjernes.
FunksjonskontrollIslandsOutOfBounds () hvis (#islands> 0) så for i = # øyer, 1, -1 gjør hvis (øyene [i] .y> display.contentHeight) deretter øyene [i]: removeSelf () øyene [i] = nil table.remove (øyer, i) endeendens ende ende
generateFreeLife
Hver så ofte har spilleren en sjanse til å få et fritt liv. Vi genererer først et gratis livsbilde, og hvis spilleren kolliderer med bildet, får de et ekstra liv. Spilleren kan ha maksimalt seks liv.
funksjon generateFreeLife () hvis (numberOfLives> = 6) og deretter returnere ende lokal freeLife = display.newImage ("newlife.png", math.random (0, display.contentWidth - 40), 0); table.insert (freeLifes, freeLife) planeGroup: sett inn (freeLife) ende
Hvis spilleren allerede har seks liv, gjør vi ingenting ved å returnere tidlig fra funksjonen. Hvis ikke, oppretter vi et nytt livsbilde og legger det til på skjermen. I likhet med hvordan vi plasserte øyene tidligere, satte vi bildet på et negativt y
posisjon og generere en tilfeldig verdi for bildet x
stilling. Vi legger det inn i freeLifes
bord for å kunne referere det senere.
Vi må ringe denne funksjonen så ofte. Legg til følgende utdrag til startTimers
funksjon.
funksjon startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) generateFreeLifeTimer = timer.performWithDelay (7000, generateFreeLife, - 1) ende
moveFreeLives
Gjennomføringen av moveFreeLifes
bør se kjent ut. Vi løper gjennom freeLifes
bord og flytte hvert bilde i det.
funksjon moveFreeLifes () hvis (#freeLifes> 0) then for i = 1, # freeLifes gjør freeLifes [i] .y = freeLifes [i] .y +5 endeendens ende
Alt vi trenger å gjøre er å ringe moveFreeLifes
i gameLoop
funksjon.
funksjon gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () slutten
checkFreeLifesOutOfBounds
Følgende kodestykke skal også bli kjent med deg nå. Vi sjekker om noen av bildene i freeLifes
bordet har flyttet på skjermen og fjern de som har.
funksjonen checkFreeLifesOutOfBounds () hvis (#freeLifes> 0) så for i = # freeLifes, 1, -1 gjør hvis (freeLifes [i] .y> display.contentHeight) then freeLifes [i]: removeSelf () freeLifes [i] = nil table.remove (freeLifes, i) endeendens ende ende
Vi kaller denne funksjonen i gameLoop
funksjon.
funksjon gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () checkFreeLifesOutOfBounds () slutten
hasCollided
Vi må kunne fortelle når spillobjekter kolliderer med hverandre, for eksempel spillerenes plan og de frie livbildene, kulene og flyene, etc. Mens Corona tilbyr en meget robust fysikkmotor som lett kan håndtere sammenstøt mellom displayobjekter for oss, gjør det, legger litt overhead med beregningene motoren må gjøre hver ramme.
I dette spillet vil vi bruke et enkelt kollisjonsdeteksjonssystem for avgrensningsboks. Hva denne funksjonen gjør, er å sørge for at rektanglene eller grensekassene rundt to objekter ikke overlapper. Hvis de gjør det, kolliderer gjenstandene. Denne logikken er implementert i hasCollided
funksjon.
funksjonen harCollided (obj1, obj2) hvis (obj1 == nil) deretter returnere falsk ende hvis (obj2 == nil) deretter returnere falsk ende lokal venstre = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin lokal høyre = obj1.contentBounds.xMin> = obj2.contentBounds.xMin og obj1.contentBounds.xMin <= obj2.contentBounds.xMax local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin lokal ned = obj1.contentBounds.yMin> = obj2.contentBounds.yMin og obj1.contentBounds.yMin <= obj2.contentBounds.yMax return (left or right) and (up or down) end
Jeg fant denne kodestykket på CoronaLabs nettsted. Det fungerer veldig bra, fordi spillobjektene i spillet vårt er rektangulære. Hvis du jobber med objekter som ikke er rektangulære, kan du bedre dra nytte av Coronas fysikkmotor, da kollisjonsdeteksjonen er svært godt optimalisert for dette.
checkPlayerCollidesWithFreeLife
Vi ønsker å sjekke om spillerens fly har kollidert med et gratis livsobjekt. Hvis den har, gir vi spilleren et fritt liv.
FunksjonskontrollPlayerCollidesWithFreeLife () hvis (#freeLifes> 0) så for i = # freeLifes, 1, -1 gjør hvis (hasCollided (freeLifes [i], spiller)) then freeLifes [i]: removeSelf () freeLifes [i] = null table.remove (freeLifes, i) numberOfLives = numberOfLives + 1 hideLives () showLives () endeendens ende ende
I checkPlayerCollidesWithFreeLife
funksjon, vi løp gjennom freeLives
Tabell bakover av samme grunn som jeg beskrev tidligere. Vi kaller hasCollided
fungere og passere i det aktuelle bildet og spillerens plan. Hvis de to objektene kolliderer, fjerner vi det gratis livbildet, øker numberOfLives
variabel og ring til hideLives
og showLives
funksjon.
Vi påberoper denne funksjonen i gameLoop
funksjon.
funksjon gameLoop () --SNIP - moveFreeLifes () checkFreeLifesOutOfBounds () checkPlayerCollidesWithFreeLife () slutten
hideLives
De hideLives
funksjonsløkker gjennom livesImages
bord og setter isVisible
egenskapen til hvert livs bilde til falsk
.
funksjon hideLives () for i = 1, 6 do livesImages [i] .isVisible = false end-end
showLives
De showLives
funksjonsløkker gjennom livesImages
bord og angir hvert bilde isVisible
eiendom til ekte
.
funksjon showLives () for i = 1, numberOfLives gjør livesImages [i] .isVisible = true; slutten
Dette bringer den tredje delen av denne serien til slutt. I neste og siste utgave av denne serien vil vi skape fiendens fly og fullføre spillets spill. Takk for at du leser og ser deg der.