Creați un joc Space Invaders în Corona Finisarea gameplay-ului

Ce veți crea

În partea anterioară a acestei serii, am reușit să ne mișcăm nava jucătorului, să ne mișcăm invadatorii și să detectăm când un glonț a lovit un invadator. În această ultimă parte a seriei vom primi invadatorii care atacă jucătorul, se vor ocupa de niveluri și vor adăuga capacitatea jucătorului de a muri.

1. Gloanțe de foc

De câte ori unul dintre invadatori izbucnește un glonț. Vom folosi un cronometru pentru a realiza acest lucru. Adăugați următorul cod la gamelevel.lua.

funcția fireInvaderBullet () dacă (#invadersWhoCanFire> 0), apoi local randomIndex = math.random (#invadersWhoCanFire) local randomInvader = invadatoriWhoCanFire [randomIndex] local tempInvaderBullet = display.newImage ("laser.png", randomInvader.x, randomInvader.y + (2) tempInvaderBullet.name = "invaderBullet" scene.view: inserați (tempInvaderBullet) fizics.addBody (tempInvaderBullet, "dynamic") tempInvaderBullet.gravityScale = 0 tempInvaderBullet.isBullet = true tempInvaderBullet.isSensor = true tempInvaderBullet: setLinearVelocity table.insert (invaderBullets, tempInvaderBullet) altfel levelComplete () sfârșitul final

În această funcție, verificăm mai întâi dacă invadersWhoCanFire tabelul are cel puțin un element în el. Dacă este cazul, atunci vom executa codul în instrucțiunea if. În caz contrar, înseamnă că nivelul sa terminat și noi invocăm nivel complet funcţie.

Va exista întotdeauna cel puțin un invadator care poate declanșa un glonț până când ucizi ultimul invadator, moment în care invadersWhoCanFire tabelul va fi gol.

În cadrul instrucțiunii if, generăm un număr aleatoriu randomIndex în funcție de numărul de articole din invadersWhoCanFire masa. Apoi alegem articolul respectiv, randomInvader, de la invadersWhoCanFire masa.

Creăm o imagine de tip glonț, dă-i o Nume astfel încât să îl putem identifica mai târziu, să-l inserăm în scenă și să setăm aceleași proprietăți ca și noi pe glonțul jucătorului. În cele din urmă, introducem glonțul în invaderBullets astfel încât să putem face referire mai târziu.

Acum trebuie să setăm cronometrul. Adăugați următoarele la scena: spectacol metodă.

(event) dacă (faza == "a făcut") atunci --SNIP-- Runtime: addEventListener ("collision", onCollision) invaderFireTimer = timer.performWithDelay (1500, fireInvaderBullet,

La fiecare 1500 de milisecunde fireInvaderBullet este invocată. Rețineți că ultimul parametru pe care îl transmitem este -1, ceea ce înseamnă că temporizatorul se repetă pentru totdeauna. Ori de câte ori creați un cronometru care se repetă pentru totdeauna, ar trebui să îl anulați în cele din urmă. Noi facem asta înscena: ascunde după cum se arată mai jos.

funcția scena: ascunde (eveniment) dacă (faza == "va") atunci --SNIP-- Runtime: removeEventListener ("collision", onCollision) timer.cancel (invaderFireTimer)

2. Scoaterea gloantelor

Ca gloanțele jucătorului, gloanțele invadatorilor se vor mișca off-screen și vor continua să se deplaseze, preluând memorie valoroasă. Pentru a remedia acest lucru, le eliminăm la fel ca în cazul gloanțelor jucătorului.

funcția checkInvaderBulletsOutOfBounds () dacă (#invaderBullets> 0), atunci pentru i = # invaderBullets, 1, -1 dacă (invaderBullets [i] .y> display.contentHeight) invaderBullets [i]: removeSelf nil table.remove (invaderBullets, i) end end end end

Acest cod este foarte similar cu a verifica dacă gloanțele jucătorului sunt în afara limitelor, așa că nu voi discuta implementarea în detaliu.

3. Detectarea unei lovituri

Pasul 1: detectarea coliziunilor

Următorul pas este să detectezi dacă glonțul unui invadator a lovit jucătorul. Adăugați următorul cod la onCollision funcţie.

(event.phase == "started") atunci --SNIP-- dacă (event.object1.name == "player" și event.object2.name == "invaderBullet") apoi table.remove (invadareaBullets, table.indexOf (invaderBullets, event.object2)) event.object2: removeSelf () event.object2 = zero dacă (playerIsInvincible == false) invadorulBullet, event.object1)) event.object1: removeSelf () event.object1 = zero dacă (playerIsInvincible == false ), apoi killPlayer () sfârșitul capătului final al capătului de retur

Ca și înainte, nu știm ce obiect event.object1 și event.object2 va fi așa că vom folosi două declarații pentru a verifica ambele situații. Eliminăm glontul invadatorului din invaderBullets tabel, scoateți-l din afișaj și setați-l la zero. Dacă jucătorul nu este invincibil, îl omorâm.

Pasul 2: uciderea playerului

Când omoram jucătorul, îi dăm un timp scurt de invincibilitate. Acest lucru oferă utilizatorului timp pentru a-și recupera atenția asupra jocului. În cazul în care numberOfLives variabila este egală cu 0, știm că jocul sa terminat și trecerea la start scenă în care utilizatorul poate începe un nou joc.

funcția killPlayer () numberOfLives = numberOfLives-1; în cazul în care (numberOfLives <= 0) then gameData.invaderNum = 1 composer.gotoScene("start") else playerIsInvincible = true spawnNewPlayer() end end

Pasul 3: Reproducerea unui nou jucător

spawnNewPlayer funcția face ca playerul să se estompeze și să se stingă pentru câteva secunde. Este un efect frumos de a permite utilizatorului să știe că nava este temporar invincibilă.

funcția spawnNewPlayer () number localOfTimesToFadePlayer = 5 număr localOfTimesPlayerHasFaded = 0 funcție locală fadePlayer () player.alpha = 0; (player, time = 400, alpha = 1,) numărOfTimesPlayerHasFaded = numberOfTimesPlayerHasFaded + 1 dacă (numberOfTimesPlayerHasFaded == numberOfTimesToFadePlayer) apoi playerIsInvincible = sfârșitul final fadePlayer () timer.performWithDelay (400, fadePlayer, numberOfTimesToFadePlayer) end

Folosim o funcție locală, fadePlayer, care folosește biblioteca de tranziție pentru a modifica alfa valoarea jucător. Urmărim de câte ori jucător a stins și a ieșit și a stabilit invincibilitatea jucătorului fals odată ce ajungem la numberOfTimesToFadePlayer. Folosim un cronometru pentru a apela fadePlayer funcție de multe ori numberOfTimesToFadePlayer este egal cu.

Rulați jocul pentru a testa acest lucru. jucător ar trebui să moară când glonțul unui invadator lovește nava. Dacă trei gloanțe lovesc nava, ar trebui să fii dus la start unde puteți începe un nou joc.

Pentru a face acest lucru mai ușor de testat, comentează apelul către moveInvaders în gameLoop după cum se arată mai jos.

funcția gameLoop () checkPlayerBulletsOutOfBounds () --moveInvaders () checkInvaderBulletsOutOfBounds () sfârșit

4. Finalizarea unui nivel

Dacă ai reușit să omori pe fiecare invadator, jocul ar fi sunat-o nivel complet care nu există încă. Să rezolvăm asta. Adăugați următorul bloc de coduri.

funcția levelComplete () gameData.invaderNum = gameData.invaderNum + 1 dacă (gameData.invaderNum <= gameData.maxLevels) then composer.gotoScene("gameover") else gameData.invaderNum = 1 composer.gotoScene("start") end end

Noi creștem gameData.invaderNum și, dacă este mai mică decât gameData.maxLevels, trecem la joc încheiat scenă. În caz contrar, jucătorul a terminat fiecare nivel și ne reinițializăm gameData.invaderNum la 1. Trecem la start scena unde jucatorul poate incepe un nou joc.

O modalitate ușoară de a testa acest lucru este prin a comenta apelul la moveInvaders în gameLoop funcția și utilizați butoanele pentru a muta nava. Dacă este încă prea greu, puteți să comenteze și cele două apeluri killPlayer în onCollision metodă.

5. Joc peste

Adăugați următorul cod la gameover.lua pentru a implementa jocul peste scenă.

compozitor local = necesită ("compozitor") scena locală = compozitor.newScene () local starFieldGenerator = necesită ("starfieldgenerator") pulsatingText locală necesită ("pulsatingtext") local nextLevelButton star localGenerator scena funcției: .view starGenerator = starFieldGenerator.new (200, grup, 5) invadatorii localiText = pulsatingText.new ("LEVEL COMPLETE", display.contentCenterX, display.contentCenterY-200, "Conquest" 1, 1) invadersText: pulsate () nextLevelButton = display.newImage ("next_level_btn.png", display.contentCenterX, display.contentCenterY) grup: insert (nextLevelButton) .RemoveScene ("gamelevel") dacă (faza == "a făcut"), apoi nextLevelButton: addEventListener ("tap", startNewGame) Runtime: addEventListener (enterFrame, starGenerator) .phase dacă (faza == "va") apoi Runtime: removeEventListener ("enterF rame ", starGenerator) nextLevelButton: removeEventListener (" tap ", startNewGame) funcția end end startNewGame () composer.gotoScene (" gamelevel ") scena final: addEventListener (" scena: addEventListener ("ascunde", scena) scena de întoarcere

Acest cod este foarte similar cu start astfel încât ar trebui să fiți familiarizați până acum.

6. Coliziunea cu un invadator

Ultimul control de coliziune pe care trebuie să-l realizăm este o coliziune între jucător și invadatori. Adăugați următorul bloc de coduri la onCollision metoda pe care am văzut-o mai devreme.

(event.phase == "started") atunci --SNIP-- dacă (event.object1.name == "player" și event.object2.name == "invader" ), atunci numărulOfLives = 0 killPlayer () se termină dacă (event.object1.name == "invader" și event.object2.name == "player"), apoi numberOfLives = 0 killPlayer

Ca de obicei, trebuie să verificăm ambele situații de coliziune. Am setat numberOfLives la 0 și sunați killPlayer. Prin setare numberOfLives la 0 și invocând killPlayer, jocul sa terminat și jocul trece la start scenă.

7. Mai multe caracteristici

Acest lucru completează jocul nostru, dar vă sugerăm să încercați să extindeți jocul cu câteva funcții suplimentare. De exemplu, puteți afișa viața jucătorului într-un HUD.

Am inclus, de asemenea, un grafic OZN în fișierele sursă. Ai putea încerca să faci un OZN să apară la întâmplare și dacă jucătorul îl lovește cu un glonț, dă-i o viață suplimentară.

Dacă aveți nevoie de ajutor cu aceste concepte, atunci verificați seria de jocuri de luptă cu avionul pe Tuts+.

Concluzie

Dacă ați urmat această serie, atunci ar trebui să aveți acum un joc pe deplin funcțional similar cu Space Invaders. Extindeți-l și creați-vă propriul. Sper că ați găsit acest tutorial util și ați învățat câteva tehnici noi. Mulțumesc că ați citit.

Cod