Crea un gioco di Space Invaders in Corona Finishing Gameplay

Cosa starai creando

Nella parte precedente di questa serie, abbiamo spostato la nave del giocatore, fatto muovere gli invasori e rilevato quando un proiettile giocatore ha colpito un invasore. In questa parte finale della serie, otterremo gli invasori che attaccano il giocatore, gestiscono i livelli e aggiungono l'abilità per il giocatore di morire.

1. Sparare i proiettili

Ogni tanto uno degli invasori spara un proiettile. Useremo un timer per realizzare questo. Aggiungere il seguente codice a gamelevel.lua.

function fireInvaderBullet () if (#invadersWhoCanFire> 0) then randomIndex locale = math.random (#invadersWhoCanFire) local randomInvader = invadersWhoCanFire [randomIndex] local tempInvaderBullet = display.newImage ("laser.png", randomInvader.x, randomInvader.y + invaderSize / 2) tempInvaderBullet.name = "invaderBullet" scene.view: insert (tempInvaderBullet) physics.addBody (tempInvaderBullet, "dynamic") tempInvaderBullet.gravityScale = 0 tempInvaderBullet.isBullet = true tempInvaderBullet.isSensor = true tempInvaderBullet: setLinearVelocity (0,400) table.insert (invaderBullets, tempInvaderBullet) else levelComplete () end end

In questa funzione, per prima cosa controlliamo se il invadersWhoCanFire tabella ha almeno un elemento in esso. Se questo è il caso, eseguiamo il codice nella dichiarazione if. Altrimenti significa che il livello è finito e invochiamo il livello completato funzione.

Ci sarà sempre almeno un invasore che può sparare un proiettile finché non uccidi l'ultimo invasore, a quel punto il invadersWhoCanFire il tavolo sarà vuoto.

All'interno dell'istruzione if, generiamo un numero casuale randomIndex a seconda di quanti oggetti ci sono in invadersWhoCanFire tavolo. Quindi selezioniamo quell'elemento, randomInvader, dal invadersWhoCanFire tavolo.

Creiamo un'immagine bullet, diamo a nome proprietà in modo che possiamo identificarlo in seguito, inserirlo nella scena e impostare le stesse proprietà che abbiamo fatto sul proiettile del giocatore. Infine, inseriamo il proiettile nel invaderBullets tabella in modo che possiamo fare riferimento in seguito.

Ora dobbiamo impostare il timer. Aggiungi il seguente al scena: spettacolo metodo.

function scene: show (event) if (phase == "did") then --SNIP-- Runtime: addEventListener ("collision", onCollision) invaderFireTimer = timer.performWithDelay (1500, fireInvaderBullet, -1) end end

Ogni 1500 millisecondi fireInvaderBullet è invocato. Si noti che l'ultimo parametro che passiamo è -1, il che significa che il timer si ripete per sempre. Ogni volta che crei un timer che si ripete per sempre, dovresti eventualmente cancellarlo. Lo facciamo nelscena: nascondere funzione come mostrato di seguito.

function scene: hide (event) if (phase == "will") then --SNIP-- Runtime: removeEventListener ("collision", onCollision) timer.cancel (invaderFireTimer) end end

2. Rimozione dei proiettili

Come i proiettili del giocatore, i proiettili degli invasori si spostano fuori dallo schermo e continuano a muoversi, occupando una memoria preziosa. Per rimediare, li rimuoviamo proprio come abbiamo fatto con i proiettili del giocatore.

function checkInvaderBulletsOutOfBounds () if (#invaderBullets> 0) quindi per i = # invaderBullets, 1, -1 do if (invaderBullets [i] .y> display.contentHeight) quindi invaderBullets [i]: removeSelf () invaderBullets [i] = nil table.remove (invaderBullets, i) end end end end

Questo codice è molto simile al controllo se i proiettili del giocatore sono fuori limite, quindi non discuterò la sua implementazione in dettaglio.

3. Rilevare un colpo

Passaggio 1: rilevamento collisione

Il passo successivo è quello di rilevare se il proiettile di un invasore ha colpito il giocatore. Aggiungi il seguente codice al onCollision funzione.

function onCollision (event) if (event.phase == "begin") then --SNIP-- if (event.object1.name == "player" ed event.object2.name == "invaderBullet") then table.remove (invaderBullets, table.indexOf (invaderBullets, event.object2)) event.object2: removeSelf () event.object2 = nil if (playerIsInvincible == false) then killPlayer () end return end if (event.object1.name == " invaderBullet "e event.object2.name ==" player ") then table.remove (invaderBullets, table.indexOf (invaderBullets, event.object1)) event.object1: removeSelf () event.object1 = nil if (playerIsInvincible == false ) then killPlayer () end return end end end

Come prima, non sappiamo quale oggetto event.object1 e event.object2 sarà così che useremo due istruzioni if ​​per verificare entrambe le situazioni. Rimuoviamo il proiettile dell'invasore dal invaderBullets tabella, rimuoverlo dal display e impostarlo su zero. Se il giocatore non è invincibile, lo uccidiamo.

Passaggio 2: uccisione del giocatore

Quando uccidiamo il giocatore, gli diamo un breve periodo di invincibilità. Questo dà all'utente il tempo di riguadagnare l'attenzione sul gioco. Se la numberOfLives la variabile è uguale a 0, sappiamo che il gioco è finito e la transizione al inizio scena in cui l'utente può iniziare una nuova partita.

function killPlayer () numberOfLives = numberOfLives- 1; se (numberOfLives <= 0) then gameData.invaderNum = 1 composer.gotoScene("start") else playerIsInvincible = true spawnNewPlayer() end end

Passaggio 3: generazione di un nuovo giocatore

Il spawnNewPlayer la funzione fa sbiadire il lettore per alcuni secondi. È un buon effetto per far sapere all'utente che la nave è temporaneamente invincibile.

function spawnNewPlayer () local numberOfTimesToFadePlayer = 5 local numberOfTimesPlayerHasFaded = 0 local function fadePlayer () player.alpha = 0; transition.to (player, time = 400, alpha = 1,) numberOfTimesPlayerHasFaded = numberOfTimesPlayerHasFaded + 1 if (numberOfTimesPlayerHasFaded == numberOfTimesToFadePlayer) then playerIsInvincible = false end end fadePlayer () timer.performWithDelay (400, fadePlayer, numberOfTimesToFadePlayer) end

Usiamo una funzione locale, fadePlayer, che usa la libreria di transizione per modificare il alfa valore del giocatore. Teniamo traccia di quante volte il giocatore è sbiadito dentro e fuori e ha impostato l'invincibilità del giocatore a falso una volta raggiunto il numberOfTimesToFadePlayer. Usiamo un timer per chiamare il fadePlayer funzione per comunque molte volte numberOfTimesToFadePlayer è uguale a.

Esegui il gioco per testare questo. Il giocatore dovrebbe morire quando il proiettile di un invasore colpisce la nave. Se tre proiettili colpiscono la nave, dovresti essere portato al inizio scena in cui è possibile iniziare una nuova partita.

Per rendere più semplice il test, commentare la chiamata a moveInvaders nel gameLoop funzione come mostrato di seguito.

function gameLoop () checkPlayerBulletsOutOfBounds () --moveInvaders () checkInvaderBulletsOutOfBounds () end

4. Completamento di un livello

Se sei riuscito a uccidere ogni invasore, il gioco avrebbe chiamato il livello completato funzione, che non esiste ancora. Lascia che risolvi quello Aggiungi il seguente blocco di codice.

function levelComplete () gameData.invaderNum = gameData.invaderNum + 1 if (gameData.invaderNum <= gameData.maxLevels) then composer.gotoScene("gameover") else gameData.invaderNum = 1 composer.gotoScene("start") end end

Aumentiamo gameData.invaderNum e, se è inferiore a gameData.maxLevels, passiamo al gioco finito scena. Altrimenti, il giocatore ha completato tutti i livelli e noi resettiamo gameData.invaderNum a 1. Passiamo al inizio scena in cui il giocatore può iniziare una nuova partita.

Un modo semplice per testare questo è commentando la chiamata a moveInvaders nel gameLoop funzione e utilizzare i pulsanti per spostare la nave. Se è ancora troppo difficile, puoi anche commentare le due chiamate killPlayer nel onCollision metodo.

5. Game Over

Aggiungere il seguente codice a gameover.lua per implementare il gioco sulla scena.

compositore locale = require ("compositore") local scene = composer.newScene () local starFieldGenerator = require ("starfieldgenerator") local pulsatingText = require ("pulsatingtext") local nextLevelButton local starGenerator function scene: create (event) local group = self .view starGenerator = starFieldGenerator.new (200, group, 5) local invadersText = pulsatingText.new ("LEVEL COMPLETE", display.contentCenterX, display.contentCenterY-200, "Conquest", 20, group) invadersText: setColor (1, 1, 1) invadersText: pulsate () nextLevelButton = display.newImage ("next_level_btn.png", display.contentCenterX, display.contentCenterY) gruppo: insert (nextLevelButton) end function scene: show (evento) local phase = event.phase compositore .removeScene ("gamelevel") if (phase == "did") then nextLevelButton: addEventListener ("tap", startNewGame) Runtime: addEventListener ("enterFrame", starGenerator) end end function scene: hide (evento) local phase = evento .phase if (phase == "will") then Runtime: removeEventListener ("enterF rame ", starGenerator) nextLevelButton: removeEventListener (" tap ", startNewGame) end end function startNewGame () compositer.gotoScene (" gamelevel ") end scene: addEventListener (" crea ", scena) scena: addEventListener (" mostra ", scena) scena: addEventListener ("nascondi", scena) restituisce la scena

Questo codice è molto simile al inizio scena quindi dovresti averne già familiarità.

6. Scontrarsi con un invasore

L'ultimo controllo di collisione che dobbiamo eseguire è una collisione tra il giocatore e gli invasori. Aggiungere il seguente blocco di codice al onCollision metodo che abbiamo visto prima.

function onCollision (event) --SNIP-- if (event.phase == "begin") then --SNIP-- if (event.object1.name == "player" ed event.object2.name == "invader" ) then numberOfLives = 0 killPlayer () end if (event.object1.name == "invader" e event.object2.name == "player") then numberOfLives = 0 killPlayer () end end

Come al solito, dobbiamo controllare entrambe le situazioni di collisione. Abbiamo impostato il numberOfLives a 0 e chiama killPlayer. IMPOSTANDO numberOfLives a 0 e invocando killPlayer, il gioco è finito e il gioco passa a inizio scena.

7. Altre caratteristiche

Questo completa il nostro gioco, ma ti suggerisco di provare ad espandere il gioco con alcune funzionalità aggiuntive. Ad esempio, potresti visualizzare le vite del giocatore in un HUD.

Ho anche incluso un grafico UFO nei file sorgente. Potresti provare a far apparire un UFO in modo casuale e se il giocatore lo colpisce con un proiettile dà loro una vita extra.

Se hai bisogno di aiuto con questi concetti, dai un'occhiata alla mia serie di Plane Fighting Game su Tuts+.

Conclusione

Se hai seguito questa serie, ora dovresti avere un gioco completamente funzionale simile agli Space Invaders originali. Espandilo e rendilo tuo. Spero che questo tutorial sia stato utile e abbia imparato alcune nuove tecniche. Grazie per la lettura.