Creëer een Space Invaders Game in Corona Finishing Gameplay

Wat je gaat creëren

In het vorige deel van deze serie kregen we het schip van de speler in beweging, kregen de indringers beweging en ontdekten ze dat een speler-kogel een indringer had geraakt. In dit laatste deel van de serie zullen we de indringers de speler laten aanvallen, levels hanteren en de speler de mogelijkheid geven om te sterven.

1. Kogels afvuren

Af en toe vuurt een van de indringers een kogel af. We zullen een timer gebruiken om dit te bereiken. Voeg de volgende code toe aan gamelevel.lua.

function fireInvaderBullet () if (#invadersWhoCanFire> 0) dan local randomIndex = 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 deze functie controleren we eerst of het invadersWhoCanFire tabel bevat minstens één element. Als dat het geval is, voeren we de code uit in de if-instructie. Anders betekent dit dat het niveau voorbij is en we roepen het level voltooid functie.

Er zal altijd tenminste één indringer zijn die een kogel kan afvuren tot je de laatste indringer doodt, op welk moment de invadersWhoCanFire tafel zal leeg zijn.

Binnen de if-instructie genereren we een willekeurig getal randomIndex afhankelijk van hoeveel items in de invadersWhoCanFire tafel. We kiezen vervolgens dat item, randomInvader, van de invadersWhoCanFire tafel.

We maken een opsommingsteken, geef het een naam zodat we het later kunnen identificeren, in de scène kunnen invoegen en dezelfde eigenschappen kunnen instellen als bij de kogel van de speler. Ten slotte voegen we de kogel in de invaderBullets tafel zodat we er later naar kunnen verwijzen.

We moeten nu de timer instellen. Voeg het volgende toe aan de scène: toon methode.

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

Elke 1500 milliseconden fireInvaderBullet wordt aangeroepen. Merk op dat de laatste parameter die we doorgeven is -1, wat betekent dat de timer voor altijd herhaalt. Telkens wanneer u een timer maakt die voor altijd wordt herhaald, moet u deze uiteindelijk annuleren. We doen dit in descène: verberg functie zoals hieronder getoond.

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

2. Kogels verwijderen

Net als de kogels van de speler zullen de kogels van de indringers buiten het scherm bewegen en blijven bewegen, waardoor ze waardevolle herinneringen opnemen. Om dit te verhelpen, verwijderen we ze net als bij de kogels van de speler.

functie checkInvaderBulletsOutOfBounds () if (#invaderBullets> 0) en dan voor i = # invaderBullets, 1, -1 do if (invaderBullets [i] .y> display.contentHeight) en dan invaderBullets [i]: removeSelf () invaderBullets [i] = nul table.remove (invaderBullets, i) einde end end end

Deze code lijkt sterk op het controleren of de kogels van de speler buiten de grenzen vallen, dus ik zal de implementatie ervan niet in detail bespreken.

3. Een hit detecteren

Stap 1: botsingsdetectie

De volgende stap is om te detecteren of de kogel van een indringer de speler heeft geraakt. Voeg de volgende code toe aan de onCollision functie.

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

Net als voorheen weten we niet welk object event.object1 en event.object2 zal zo zijn dat we twee if-statements gebruiken om beide situaties te controleren. We verwijderen de kogel van de indringer van de invaderBullets tafel, verwijder het van het display en stel het in op nul. Als de speler niet onoverwinnelijk is, doden we het.

Stap 2: De speler doden

Wanneer we de speler doden, geven we hem een ​​korte tijd van onoverwinnelijkheid. Dit geeft de gebruiker de tijd om zich weer op het spel te concentreren. Als het numberOfLives variabele is gelijk aan 0, we weten dat het spel voorbij is en gaan over op de begin scène waar de gebruiker een nieuw spel kan beginnen.

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

Stap 3: Een nieuwe speler voortbrengen

De spawnNewPlayer functie maakt de speler een paar seconden lang in- en uitfaden. Het is een leuk effect om de gebruiker te laten weten dat het schip tijdelijk onoverwinnelijk is.

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

We gebruiken een lokale functie, fadePlayer, die de overgangsbibliotheek gebruikt om de alpha waarde van de speler. We houden bij hoeveel keer de speler is in en uit vervaagd en de onoverwinnelijkheid van de speler ingesteld vals zodra we de numberOfTimesToFadePlayer. We gebruiken een timer om het te bellen fadePlayer functie voor vele keren numberOfTimesToFadePlayer is gelijk aan.

Start het spel om dit uit te testen. De speler zou moeten sterven als de kogel van een indringer het schip raakt. Als drie kogels het schip raken, moet u naar de begin scène waarin u een nieuw spel kunt starten.

Om dit gemakkelijker te testen, geeft u een commentaar op de aanroep moveInvaders in de gameLoop functie zoals hieronder getoond.

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

4. Een niveau voltooien

Als je elke indringer hebt vermoord, zou het spel het level voltooid functie, die nog niet bestaat. Laat dat oplossen. Voeg het volgende codeblok toe.

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

We verhogen gameData.invaderNum en, als het minder is dan gameData.maxLevels, we gaan over naar de spel is over tafereel. Anders heeft de speler elk niveau voltooid en zijn we gereset gameData.invaderNum naar 1. We gaan over naar de begin scène waarin de speler een nieuw spel kan beginnen.

Een eenvoudige manier om dit te testen, is door de oproep aan te geven moveInvaders in de gameLoop functie en gebruik de knoppen om het schip te verplaatsen. Als dat nog steeds te moeilijk is, dan kun je ook de twee oproepen aan commentaart killPlayer in de onCollision methode.

5. Spel voorbij

Voeg de volgende code toe aan gameover.lua om het spel over scène te implementeren.

local composer = require ("composer") local scene = composer.newScene () local starFieldGenerator = require ("starfieldgenerator") local pulsatingText = require ("pulsatingtext") local nextLevelButton lokale starGenerator functiescène: 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) group: insert (nextLevelButton) functie van einde-functie: show (event) local phase = event.phase composer .removeScene ("gamelevel") if (phase == "did") then nextLevelButton: addEventListener ("tap", startNewGame) Runtime: addEventListener ("enterFrame", starGenerator) eindscènescène: hide (gebeurtenis) lokale fase = gebeurtenis .fase als (fase == "zal") dan Runtime: removeEventListener ("enterF rame ", starGenerator) nextLevelButton: removeEventListener (" tap ", startNewGame) end-end-functie startNewGame () composer.gotoScene (" gamelevel ") eindscène: addEventListener (scène" create ", scène): addEventListener (" show ", scène) scène: addEventListener (scène "verbergen", scène) retourneert scène

Deze code lijkt veel op de begin scène, zodat je er nu bekend mee bent.

6. In botsing komen met een indringer

De laatste botsingcontrole die we moeten uitvoeren, is een botsing tussen de speler en een van de indringers. Voeg het volgende codeblok toe aan de onCollision methode die we eerder zagen.

function onCollision (event) --SNIP-- if (event.phase == "started") then --SNIP-- if (event.object1.name == "player" en event.object2.name == "invader" ) vervolgens numberOfLives = 0 killPlayer () einde if (event.object1.name == "invader" en event.object2.name == "player") dan numberOfLives = 0 killPlayer () end end

Zoals gewoonlijk moeten we beide botsingssituaties controleren. We hebben de numberOfLives naar 0 en bel killPlayer. Door in te stellen numberOfLives naar 0 en aanroepen killPlayer, het spel is voorbij en het spel gaat over naar de begin tafereel.

7. Meer functies

Hiermee is onze game voltooid, maar ik raad aan om de game uit te breiden met een paar extra functies. U kunt bijvoorbeeld de levens van de speler in een HUD weergeven.

Ik heb ook een UFO-afbeelding opgenomen in de bronbestanden. Je zou kunnen proberen om een ​​UFO willekeurig te laten verschijnen en als de speler hem met een kogel raakt, geef hem een ​​extra leven.

Als je hulp nodig hebt met deze concepten, bekijk dan mijn Plane Fighting Game-serie over Tuts+.

Conclusie

Als je deze serie hebt gevolgd, zou je nu een volledig functioneel spel moeten hebben dat lijkt op het originele Space Invaders. Breid het uit en maak het uw eigen. Ik hoop dat je deze tutorial nuttig hebt gevonden en wat nieuwe technieken hebt geleerd. Bedankt voor het lezen.