Create a Plane slåssespill i Corona: Ferdigstilling Gameplay
36
Del
6
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. Mer GameplayWhat du skal lage
Innledning
I den fjerde og siste del av denne serien, vi fortsetter der vi slapp av i forrige tutorial. Vi vil opprette fiendtlige fly spilleren trenger for å unngå eller skyte, og vi vil også lage et game over skjermen.
1. generateEnemys
generateEnemys funksjonen genererer et tall mellom tre Anmeldelser og sju
, og kaller generateEnemyPlane funksjon hver to sekunder
for imidlertid mange ganger numberOfEnemysToGenerate er lik. Skriv inn følgende kode i gamelevel.lua
.
Funksjons generateEnemys () numberOfEnemysToGenerate = Math.random (3,7) timer.performWithDelay (2000, generateEnemyPlane, numberOfEnemysToGenerate) end
Vi trenger også å påkalle denne funksjonen i enterScene metoden som vist nedenfor
funksjon scene. enterScene (hendelse) --SNIP-- Spilletid: addEventListener ("enterframe", gameLoop) startTimers () generateEnemys () end
La oss se hva gjennomføringen av generateEnemyPlane ser ut.
2. generateEnemyPlane
generateEnemyPlane funksjonen genererer én fiendens fly. Det er tre typer av fiendtlige fly i dette spillet.
, flytter nedover skjermen i en rett linje
Waver
, beveger seg i et bølgemønster på x-aksen
Chaser
, jager spillerens flyet
funksjon generateEnemyPlane () if (Gameover ~ = sant) da lokale randomGridSpace = matematikk. tilfeldig (11) lokal randomEnemyNumber = Math.random (3) lokale tempEnemy if (planeGrid [randomGridSpace] ~ = 0) så generateEnemyPlane () returnerer else if (randomEnemyNumber == 1) deretter tempEnemy = display.newImage ("enemy1.png" (randomGridSpace * 65) -28, -60) tempEnemy.type = "vanlige" ElseIf (randomEnemyNumber == 2) deretter tempEnemy = display.newImage ("enemy2.png", display.contentWidth /2 -playerWidth /2, - 60) tempEnemy.type = "vakle" annet tempEnemy = display.newImage ("enemy3.png", (randomGridSpace * 65) -28, -60) tempEnemy.type = "chaser" end planeGrid [randomGridSpace] = 1 table.insert (enemyPlanes, tempEnemy) planeGroup: sett (tempEnemy) numberOfEnemysGenerated = numberOfEnemysGenerated + 1; end if (numberOfEnemysGenerated == numberOfEnemysToGenerate) så numberOfEnemysGenerated = 0; resetPlaneGrid () timer.performWithDelay (2000, generateEnemys, 1) endendend
Vi først sjekke at spillet er ikke over ennå. Vi deretter generere en randomGridSpace, et tall mellom 1 Hotell og 11
, og en tilfeldig randomEnemyNumber, et tall mellom 1 Hotell og 3
. Den randomGridSpace brukes til å plassere flyet i en av elleve spalter på toppen av skjermen på x-aksen. Hvis du tenker på spillområdet blir delt inn i elleve seksjoner, da vi bare ønsker å plassere nye fly i et spor som ikke har blitt tatt ennå av en annen planet. Den planeGrid Tabellen inneholder elleve 0-er og når vi plassere en ny planet i et av sporene, setter vi tilsvarende posisjon i tabellen til en for å vise at sporet har blitt tatt av et fly.
sjekke om indeksen for randomGridSpace i tabellen er ikke lik 0. Hvis det ikke er, vi vet at sporet er i dag tatt og vi bør ikke fortsette, så vi kaller generateEnemyPlane og returnere fra funksjonen.
Deretter sjekker vi hva randomEnemyNumber er lik og sette tempEnemy til en av de tre fiendebilder, vi også gi den en egenskap av enten vanlig, vakle, eller jeger. Fordi Lua er et dynamisk språk, kan vi legge nye egenskaper til et objekt under kjøring. Vi satt hva indeksen er lik randomGridSpace til 1 i planeGrid tabellen.
Vi setter tempEnemy inn i enemyPlanes bord for senere referanse og øke numberOfEnemysGenerated. Hvis numberOfEnemysGenerated er lik numberOfEnemysToGenerate, vi null numberOfEnemysGenerated til 0, påberope resetPlaneGrid, og sette en timer som vil kalle generateEnemys igjen etter to sekunder. Denne prosessen gjentas så lenge spillet er ikke over.
3. moveEnemyPlanes
Som du kanskje har gjettet, er moveEnemyPlanes funksjon ansvarlig for flytting av fiendtlige fly. Avhengig av flyets typen, er den aktuelle funksjonen kalles
funksjons moveEnemyPlanes () if (#enemyPlanes > 0). Deretter for i = 1, #enemyPlanes gjøre hvis (enemyPlanes [i] .type == "vanlig") deretter moveRegularPlane (enemyPlanes [i]) ElseIf (enemyPlanes [i] .type == "vakle") så moveWaverPlane (enemyPlanes [i]) ellers moveChaserPlane (enemyPlanes [i]) end end Sluttslutt
Denne funksjonen må påberopes i gameLoop funksjonen.
funksjon gameLoop () --SNIP-- checkFreeLifesOutOfBounds () checkPlayerCollidesWithFreeLife () moveEnemyPlanes () end
4. moveRegularPlane
moveRegularPlane flytter bare flyet nedover skjermen over y-aksen.
funksjon moveRegularPlane (fly) plane.y = plane.y + 4end
5. moveWaverPlane
moveWaverPlane funksjon flytter flyet nedover skjermen over y-aksen, og i en bølge mønster, over x-aksen. Dette oppnås ved hjelp av cos funksjon av Lua matematikk bibliotek.
Hvis dette konseptet er fremmed for deg, skrev Michael James Williams en flott introduksjon til Sinus Motion. De samme begrepene gjelder, den eneste forskjellen er at vi bruker cosinus
. Du bør tenke sinus
når du arbeider med y-aksen og cosinus
når du arbeider med x-aksen.
Funksjon moveWaverPlane (fly) plane.y = plane.y + 4 plane.x = (display.contentWidth /2) + 250 * math.cos (numberOfTicks * 0,5 * math.pi /30) end
I ovennevnte tekstutdrag, bruker vi numberOfTicks variabel. Vi trenger å øke dette hver gang gameLoop funksjonen kalles.
Funksjon gameLoop legge følgende som den aller første linjen i gameLoop funksjon. () NumberOfTicks = numberOfTicks + 1end
6. moveChaserPlane
moveChaserPlane funksjonen har flyet jage
spilleren. Den beveger seg nedover langs y-aksen med en konstant hastighet, og det beveger seg mot spillerens posisjon på x-aksen. Ta en titt på gjennomføringen av moveChaserPlane for avklaring
funksjon moveChaserPlane (fly) hvis. (Plane.x < player.x) så plane.x = plane.x 4 end if (plane.x > spiller. x) så plane.x = plane.x - 4 slutten plane.y = plane.y + 4end
Hvis du teste spillet nå, bør du se flyene beveger seg nedover skjermen
7.. fireEnemyBullets
Hver så ofte, vil vi fiendtlige fly å skyte en kule. Vi ønsker ikke alle av dem å skyte på samme tid, men så velger vi bare et par fly til brann
funksjons fireEnemyBullets () if (#enemyPlanes > = 2). Deretter lokal numberOfEnemyPlanesToFire = math.floor (# enemyPlanes /2) lokale tempEnemyPlanes = table.copy (enemyPlanes) lokal funksjon fireBullet () lokale randIndex = Math.random (#tempEnemyPlanes) lokal tempBullet = display.newImage ("bullet.png", (tempEnemyPlanes [randIndex] .x + playerWidth /2) + bulletWidth, tempEnemyPlanes [randIndex] .Y + playerHeight + bulletHeight) tempBullet.rotation = 180 planeGroup: Stikk (tempBullet) table.insert (enemyBullets, tempBullet); table.remove (tempEnemyPlanes, randIndex) slutten for i = 0, numberOfEnemyPlanesToFire gjøre fireBullet () end Sluttslutt
Vi først sjekke at den enemyPlanes tabellen har mer enn to plan i det. Hvis den gjør det, får vi numberOfEnemyPlanes å skyte ved å ta lengden på enemyPlanes bordet, dele det med to, og runde det ned. Vi lager også en kopi av enemyPlanes bordet, slik at vi kan manipulere det separat.
fireBullet funksjonen velger et fly fra tempEnemyPlanes bordet og gjør flyet brann en kule. Vi genererer et tilfeldig tall på grunnlag av lengden av tempEnemyPlanes bordet, skape en kule bilde, og plassere den ved hjelp av hvilken planet er på randIndex i tempEnemyPlanes tabellen. Vi fjerner da at flyet fra den midlertidige tabellen for å sikre at det ikke vil bli valgt på nytt neste gang fireBullet kalles.
Vi gjentar denne prosessen imidlertid mange ganger numerOfEnemyPlanesToFire er lik og ringe fireBullet funksjonen.
Vi må starte tidtakeren som kaller denne funksjonen hver så ofte. For å oppnå dette, legger følgende til startTimers funksjonen.
Funksjons startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) generateFreeLifeTimer = timer.performWithDelay (7000, generateFreeLife, - 1) fireEnemyBulletsTimer = timer.performWithDelay (2000, fireEnemyBullets, -1) end
8. moveEnemyBullets
Vi trenger også å flytte fiendens kuler som står på skjermen. Dette er ganske enkelt ved hjelp av følgende kode
funksjons moveEnemyBullets () if (#enemyBullets > 0). Deretter for i = 1, # enemyBullets gjøre enemyBullets [i]. y = enemyBullets [i] .Y + 7 slutten Sluttslutt
Påkall denne funksjonen i gameLoop funksjonen.
funksjon gameLoop () --SNIP-- checkPlayerCollidesWithFreeLife () moveEnemyPlanes () moveEnemyBullets () end
9. checkEnemyBulletsOutOfBounds
I tillegg til å flytte fiendens kuler, må vi sjekke når fiendens kuler har gått av skjermen, og fjerne dem når de gjør. Gjennomføringen av checkEnemyBulletsOutOfBounds skulle være kjent nå
funksjons checkEnemyBulletsOutOfBounds () if (#enemyBullets > 0). Deretter for i = # enemyBullets, 1, -1 gjøre hvis (enemyBullets [i] .Y > display.contentHeight) så enemyBullets [i]. removeSelf () enemyBullets [i] = null table.remove (enemyBullets, i) end end Sluttslutt
Påkall denne funksjonen i gameLoop funksjon
funksjon gameLoop () - SNIP-- moveEnemyBullets () checkEnemyBulletsOutOfBounds () end
10. checkEnemyPlanesOutOfBounds
Vi bør også sjekke om de fiendtlige fly har flyttet off-screen
funksjons checkEnemyPlanesOutOfBounds () hvis (# enemyPlanes > 0). deretter for i = # enemyPlanes, 1, -1 gjøre hvis (enemyPlanes [i] .Y > display.contentHeight) så enemyPlanes [i]: removeSelf () enemyPlanes [i] = null table.remove (enemyPlanes, i) end end Sluttslutt
Påkall denne funksjonen i gameLoop funksjon
funksjon gameLoop () --SNIP-- moveEnemyBullets () checkEnemyBulletsOutOfBounds () checkEnemyPlanesOutOfBounds () end
11. checkPlayerBulletsCollideWithEnemyPlanes
checkPlayerBulletCollidesWithEnemyPlanes funksjonen bruker hasCollided funksjon for å sjekke om noen av spillerens kuler har kollidert med noen av de fiendtlige fly
funksjons checkPlayerBulletsCollideWithEnemyPlanes () if (#playerBullets >. 0 og #enemyPlanes > 0), så for i = # playerBullets, 1, -1 gjøre for j = # enemyPlanes, 1, -1 gjøre hvis (hasCollided (playerBullets [i], enemyPlanes [J])) så playerBullets [i]: removeSelf () playerBullets [i] = null table.remove (playerBullets, i) generateExplosion (enemyPlanes [j] .x, enemyPlanes [j] .Y) enemyPlanes [j]: removeSelf () enemyPlanes [j] = null table.remove (enemyPlanes, j ) lokal eksplosjon = audio.loadStream ("explosion.mp3") lokale backgroundMusicChannel = audio.play (eksplosjon, {fadein = 1 000}) end end end Sluttslutt
Denne funksjonen bruker to nestet for løkker for å sjekke om gjenstandene har kollidert . For hver av de playerBullets, kjører vi gjennom alle flyene i enemyPlanes bordet og ringe hasCollided funksjonen. Hvis det er en kollisjon, fjerner vi kula og planet, ring generateExplosion funksjon, og laste inn og spille en eksplosjon lyd
Påkall denne funksjonen i gameLoop funksjon
funksjon gameLoop ().. - -SNIP-- checkEnemyBulletsOutOfBounds () checkEnemyPlanesOutOfBounds () checkPlayerBulletsCollideWithEnemyPlanes () end
12. generateExplosion
generateExplosion funksjonen bruker Corona SpriteObject klasse. Sprites tillate animerte sekvenser av rammer som ligger på bildet eller Sprite blad. Ved å gruppere bilder til ett enkelt bilde, kan du trekke visse rammer fra det bildet og lage en animasjonssekvens.
Funksjon generateExplosion (xPosition, yPosition) lokale alternativer = {width = 60, height = 49, numFrames = 6} lokal explosionSheet = graphics.newImageSheet ("explosion.png", opsjoner) lokal sequenceData = {{name = "eksplosjon", start = 1, teller = 6, tid = 400, loopCount = 1}} lokale explosionSprite = display.newSprite (explosionSheet, sequenceData) explosionSprite.x = xPosition explosionSprite.y = yPosition explosionSprite: addEventListener ("sprite", explosionListener) explosionSprite: play () end
newImageSheet metoden tar som parametre banen til bildet og en tabell med alternativer for Sprite Ark. Alternativene vi stiller er bredden, høyden, og de numFrames, hvor mange enkeltbilder utgjør dette arket. Det er seks separate eksplosjon bilder som vises i bildet nedenfor.
Deretter setter vi opp en tabell, sequenceData, som er nødvendig av SpriteObject. Vi setter starten eiendom til en, telle til seks, og tid til 400. Starten Eiendommen er rammen som animasjonen vil starte på, er den teller hvor mange rammer animasjonen inneholder, og tiden eiendommen er hvor lenge animasjonen tar å spille gjennom.
Vi deretter opprette SpriteObject bestått i explosionSheet og sequenceData, angi x- og y-posisjoner, og legge en lytter til sprite. Lytteren skal brukes til å fjerne sprite når den er ferdig sin animasjon.
13. explosionListener
Er explosionListener funksjonen brukes til å fjerne sprite. Hvis hendelsens fase eiendom er lik ended, så vet vi spriten er ferdig med sin animasjon og vi kan fjerne det.
Funksjon explosionListener (hendelse) if (event.phase == "endte") da lokale eksplosjon = hendelse. Målet eksplosjon: removeSelf () eksplosjon = nil Sluttslutt
14. checkEnemyBulletsCollideWithPlayer
checkEnemyBulletsCollideWithPlayer sjekker for å se om noen av fiendens kuler har kollidert med spillerens flyet
funksjon checkEnemyBulletsCollideWithPlayer () hvis. (#enemyBullets > 0) så for i = # enemyBullets, 1, -1 gjøre hvis (hasCollided (enemyBullets [i], spiller)) så enemyBullets [i]: removeSelf () enemyBullets [i] = null table.remove (enemyBullets, i) if (playerIsInvincible == false) da killPlayer () end end end Sluttslutt
Vi sløyfe gjennom enemyBullets bordet og sjekke om noen av dem har kollidert med spilleren. Hvis sant, fjerner vi det bestemt punkt, og hvis playerIsInvincible er falsk, påberope vi killPlayer.
Påkall denne funksjonen i gameLoop funksjonen.
Funksjon gameLoop () --SNIP-- checkEnemyPlanesOutOfBounds () checkPlayerBulletsCollideWithEnemyPlanes () checkEnemyBulletsCollideWithPlayer () end
15. killPlayer
killPlayer funksjonen er ansvarlig for å sjekke hvorvidt spillet er over og gyting en ny spiller dersom det ikke er
funksjon killPlayer () numberOfLives = numberOfLives- en.; if (numberOfLives == 0) deretter GAME = true doGameOver () else spawnNewPlayer () hideLives () showLives () playerIsInvincible = true Sluttslutt
første redusere trinnvis numberOfLives etter en, og, hvis det er lik 0, kaller vi det Gameover funksjon. Det spilleren har liv igjen, vi kaller spawnNewPlayer, etterfulgt av hideLives, showLives, og satt playerIsInvincible til sann.
16. doGameOver
doGameOver funksjonen forteller storyboard for å gå til game
scene.
funksjon doGameOver () storyboard.gotoScene ("gameover") end
17. spawnNewPlayer
spawnNewPlayer funksjonen er ansvarlig for gyting en ny spiller etter at den er død. Spillerens flyet blinker i noen sekunder for å vise at det er midlertidig uovervinnelig
funksjon spawnNewPlayer () lokal numberOfTimesToFadePlayer = 5 lokale numberOfTimesPlayerHasFaded = 0 lokal funksjon fadePlayer () player.alpha = 0.; transition.to (spiller, {tid = 200, alfa = 1}) numberOfTimesPlayerHasFaded = numberOfTimesPlayerHasFaded + 1 if (numberOfTimesPlayerHasFaded == numberOfTimesToFadePlayer) så playerIsInvincible = false end end timer.performWithDelay (400, fadePlayer, numberOfTimesToFadePlayer) end
For å gjøre spillerens flyet blink, vi visne den inn og ut fem ganger. I fadePlayer funksjonen, setter vi flyets alpha eiendom til 0, noe som gjør det gjennomsiktig. Vi bruker overgangen biblioteket å falme alfa tilbake til en over en periode på 200 millisekunder. Den til metoden for overgangen objektet tar en tabell av alternativer. I vårt eksempel alternativ tabellen inkluderer en tid i millisekunder og eiendommen vi ønsker å animere, alfa, og ønsket verdi, 1.
øke numberOfTimesThePlayerHasFaded og sjekk om det er lik antall ganger vi ønsket spilleren å falme. Vi satt playerIsInvincible til false. Vi bruker en timer for å ringe fadePlayer funksjonen men mange ganger numberOfTimerToFadePlayer er lik.
Det er en måte å gjøre alt dette uten å bruke timer og det er ved hjelp av overgangen er gjentakelser eiendom i kombinasjon med sin onComplete handler . Les gjennom dokumentasjonen for å lære mer om dette alternativ tilnærming.
18. checkEnemyPlaneCollidesWithPlayer
Det er ett mer kollisjon sjekk vi bør gjøre og det er å se om en fiende fly kolliderer med spillerens flyet
funksjon checkEnemyPlaneCollideWithPlayer () if (#enemyPlanes > 0). deretter for i = # enemyPlanes, 1, -1 gjøre hvis (hasCollided (enemyPlanes [i], spiller)) så enemyPlanes [i]: removeSelf () enemyPlanes [i] = null table.remove (enemyPlanes, i) if (playerIsInvincible == false) deretter killPlayer () end end end Sluttslutt
Vi sløyfe gjennom fiendens fly og se om noen av dem kolliderer med spillerens flyet. Hvis det stemmer, fjerner vi at fiendens fly og ringe killPlayer. Hvis du tror det gjør spillet mer interessant, kan du også generere en eksplosjon her.
19. exitScene
Når spillet er over, vi overgangen til game
scene. Husker fra tidligere i opplæringen, er exitScene funksjon der du fjerne eventuelle hendelsen lyttere, stopp timere, og stoppe lyd som spilles
funksjon scene. ExitScene (hendelse) lokal gruppe = self.view rectUp: removeEventListener ("touch" , movePlane) rectDown: removeEventListener ("touch", movePlane) rectLeft: removeEventListener ("touch", movePlane) rectRight: removeEventListener ("touch", movePlane) audio.stop (planeSoundChannel) audio.dispose (planeSoundChannel) Spilletid: removeEventListener (" enterframe ", gameLoop) cancelTimers () endscene: addEventListener (" exitScene ", scene)
Vi er i utgangspunktet å angre hva vi gjorde i enterScene funksjonen. Vi kaller kast-metoden på audio-objektet for å frigi minnet forbundet med audiokanalen. Ringe stop alene fritar ikke minnet.
20. cancelTimers
Som navnet indikerer, den cancelTimers funksjonen ikke det motsatte av startTimers, oppheves alle tidtakerne.
funksjons cancelTimers () timer.cancel (firePlayerBulletTimer) timer.cancel (generateIslandTimer) timer.cancel ( fireEnemyBulletsTimer) timer.cancel (generateFreeLifeTimer) end
21. Game Over Scene
Det er på tide å lage den game
scene. Begynn med å legge en ny Lua fil til prosjektet navnet gameover.lua
, og legge til følgende kode i den.
Lokale dreiebok = require ("storyboard") lokale scenen = storyboard.newScene () lokal gameOverTextlocal newGameButtonreturn scene
22. createScene
Legg til følgende i gameover.lua
ovenfor retur scene. Herfra ut, bør alle koden plasseres over avkastningen scene uttalelse
funksjon scene. CreateScene (hendelse) lokal gruppe = self.view lokal bakgrunn = display.newRect (0, 0, display.contentWidth, display.contentHeight ) bakgrunn: setFillColor (0, 0,39, 0,75) gruppe: sett (bakgrunn) gameOverText = display.newText ("Game Over", display.contentWidth /2400, native.systemFont, 16) gameOverText: setFillColor (1, 1, 0) gameOverText.anchorX = 0,5 gameOverText.anchorY = 0,5 gruppen: sett (gameOverText) newGameButton = display.newImage ("newgamebutton.png", 264670) gruppe: sett (newGameButton) newGameButton.isVisible = false slutten
Som vi gjorde i de to foregående scener, vi gir game
scene en blå bakgrunn. Vi deretter opprette en TextObject eksempel ved å ringe newText utstilt. Den newText metoden tar noen alternativer, teksten for objektet, sin posisjon, og skriften å bruke. Vi gir det en gul farge ved å påberope setFillColor, passerer i RGB-verdier som prosent. Til slutt lager vi en knapp og skjule det for tiden.
23. enterScene
Når dreieboken har fullt overført til game
scene, er enterScene metode som kalles.
I enterScene, fjerner vi den forrige scene fra dreieboken. Vi bruker det praktiske metoden scaleTo fra Transition Library å skalere gameOverText med en faktor på 4. vi legge til en onComplete lytteren til overgangen som kaller
showButton funksjon når overgangen er fullført. Til slutt legger vi en kran hendelse lytteren til spillet knappen som påkaller startNewGame funksjon
funksjon scene. EnterScene (hendelse) lokal gruppe = self.view storyboard.removeScene ("gamelevel") transition.scaleTo (gameOverText {XScale = 4.0, ySkala = 4.0, tid = 2000, onComplete = showButton}) newGameButton: addEventListener ("tap", startNewGame) end
24. showButton
showButton funksjonen skjuler gameOverText og viser newGameButton.
funksjon showButton () gameOverText.isVisible = false newGameButton.isVisible = true end
25. startNewGame
startNewGame funksjonen forteller storyboardet til overgangen til gamelevel
scene.
funksjon startNewGame () storyboard.gotoScene ("gamelevel") end
26. exitScene
Vi må gjøre noen opprydding når vi forlater game
scene. Vi fjerner springen arrangementet lytteren vi lagt tidligere til newGameButton
funksjon scene. ExitScene (hendelse) lokal gruppe = self.view newGameButton: removeEventListener ("tap", startNewGame) end
27. Legg Scene Lyttere
Den siste brikken i puslespillet er å legge til scene hendelsen lyttere vi snakket om tidligere. For å gjøre dette, addd følgende kodebiten til gameover.lua
scene. AddEventListener ("createScene", scene) scenen: addEventListener ("enterScene", scene) scenen: addEventListener ("exitScene" , scene)
Konklusjon
Vi har kommet til slutten av denne serien, og nå har en fullt funksjonell plan slåssespill. Jeg håper du har funnet disse veiledningene nyttig og har lært noe underveis. Takk for lesing.