Portie van ActionScript-spellen naar iOS met de Corona SDK deel 3

In deze zelfstudie wordt gekeken naar het overbrengen van een Flash / Flex-spel naar de Corona SDK. Specifiek zullen we porten van ActionScript naar Lua, met als einddoel het spelen van voorheen Flash-only games op de iPhone. Naast het aantonen van taal- en API-verschillen, houdt deze tutorialreeks ook rekening met hardwarebeperkingen zoals schermgrootte en gebrek aan fysieke knoppen op de iPhone.

Vijanden toevoegen

Nu gaan we samenwerken met onze vijand: "de / pixelate / flixelprimer / Alien.as". Zoals altijd wordt de syntaxis eerst omgezet.

Als je daarmee klaar bent, voeg je de module-decleratie toe en pak je alle functies in Alien ().

 module (?, package.seeall) - [Embed (source = "? /? /? /? /assets/png/Alien.png")] private var ImgAlien: Class function Alien (x, y) -: void super (x, y, ImgAlien) velocity.x = -200 functie update () -: void velocity.y = Math.cos (x / 50) * 50 super.update () end end

Het buitenaardse wezen lijkt erg op onze kogel. Het maakt een afbeelding, stelt de x en y in
coördineert en geeft het een snelheid. Dus we zullen het op dezelfde manier benaderen. De bovenste twee regels binnen in de functie kunnen worden vervangen door bijna dezelfde code als die we voor de opsomming hebben gebruikt. Deze keer zullen we echter een afbeelding gebruiken.

 module (?, package.seeall) functie Alien (x, y) -: void local Alien = display.newImage ("Alien.png") Alien.x = x Alien.y = y functie update () -: void ? einde

Nu we de afbeelding hebben geladen en ingesteld, laten we deze naar links verplaatsen. Nogmaals, we zullen zoiets als de update-code () van onze bullet maken. Laat de oude regels in update () staan.

 module (?, package.seeall) functie Alien (x, y) -: void? functie update () -: void if Alien then if (Alien.x> 0 - Alien.contentWidth) then Alien.x = Alien.x - 2 end end? commentaarcode? einde Runtime: addEventListener ("enterFrame", update) einde

Laten we nu een kill () -functie maken en Alien een Alien laten retourneren.

 module (?, package.seeall) functie Alien (x, y) -: void? functie update () -: void? eindfunctie Alien: kill () Alien.parent: remove (Alien) Alien = nil end Runtime: addEventListener ("enterFrame", update) return Alien end

Nu kunnen we onze alien doden () als x van het scherm links is. We kunnen ook een nieuwe () functie toevoegen als een gemak.

 module (?, package.seeall) functie Alien (x, y) -: void local Alien = display.newImage ("Alien.png") Alien.x = x Alien.y = y functie update () -: void if Alien then if (Alien.x> 0 - Alien.contentWidth) then Alien.x = Alien.x - 2 else Alien: kill () end end end function Alien: kill () Alien.parent: remove (Alien) Alien = nul einde Runtime: addEventListener ("enterFrame", update) return Alien eindfunctie nieuw (x, y) return Alien (x, y) einde

Timers gebruiken om buitenaardse wezens te besturen

Het buitenaards wezen opvoeden was vrij eenvoudig. Nu moeten we ze beginnen toevoegen aan het spel via PlayState.

Importeer eerst de module in PlayState.lua.

 module (?, package.seeall) local Ship = require ("Ship") local Bullet = require ("Bullet") local Alien = require ("Alien") local Buttons = require ("Buttons")

Nu moeten we een timer instellen. De originele code had een variabele _spawnInterval die werd gebruikt om _spawnTimer in te stellen. Telkens wanneer _spawnTimer 0 bereikte, zou het worden teruggezet op de waarde van _spawnInterval._spawnInterval zou dan worden verlaagd met .1, waardoor aliens sneller uit de spa worden gehaald.

Om te beginnen, uncomment de _spawnInterval en _spawnTimer eigenschap decleraties in create ().

 function create () -: void - variable declarations PlayState._inGame = true PlayState._background = nil PlayState._ship = nil - PlayState._aliens = nil PlayState._bullets = nil - PlayState._scoreText = nil - PlayState. _gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = nil - PlayState.SoundExplosionShip = nil - PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = nihil? einde

Stel nu in de variabele toewijzingen _spawnTimer in op 0 en _spawnInterval op 2.5. Voeg ook een aanroep toe om ResetPawnTimer () te resetten. We zullen deze functie binnen een seconde creëren.

 function create () -: void? - variabele toewijzingen PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125) PlayState._ship = Ship.new () PlayState._shoot = false PlayState._bullets = display.newGroup () PlayState.SoundBullet = media.newEventSound ("Bullet.caf") PlayState._spawnTimer = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer () einde

Zoek nu de functie met de opmerking resetSpawnTimer (). Het zal er ongeveer zo uitzien.

 function resetSpawnTimer () -: void _spawnTimer = _spawnInterval _spawnInterval = _spawnInterval * 0.95 if (_spawnInterval < 0.1) then _spawnInterval = 0.1 end end

Verbazingwekkend genoeg is dat precies wat we nodig hebben. We moeten alleen de eigenschappen van de variabelen van PlayState maken. Op die manier weet de functie wat _spawnInterval en _spawnTimer bedoelen.

 function resetSpawnTimer () -: void PlayState._spawnTimer = PlayState._spawnInterval PlayState._spawnInterval = PlayState._spawnInterval * 0.95 if (PlayState._spawnInterval < 0.1) then PlayState._spawnInterval = 0.1 end end

Nu moeten we een code toevoegen om bij te werken (). In de originele code creëerde het spel aliens, zelfs als het spel voorbij was en het schip dood was. Om hetzelfde te doen, laten we onze buitenaardse afhandelingscode buiten plaatsen waar we controleren of het spel afgelopen is.

 function update () PlayState._spawnTimer = PlayState._spawnTimer - (30/1000) if (PlayState._spawnTimer < 0) then spawnAlien() resetSpawnTimer() end if PlayState._inGame then? end end

Deze code werkt net als de broncode. Het trekt de tijd van 1 frame af van _spawnTimer. Vervolgens wordt gecontroleerd of _spawnTimer kleiner is dan nul. Als dit het geval is, wordt de timer gereset en wordt een nieuw alien geboren.

Een andere weergavegroep

Voordat we buitenaardse wezens kunnen spawnen, hebben we een weergavegroep nodig om ze toe te voegen. Voeg net als _bullets de _aliens-decleratie toe en wijs deze toe aan een nieuwe weergavegroep.

 function create () -: void - variable declarations PlayState._inGame = true PlayState._background = nil PlayState._ship = nil PlayState._aliens = nihil PlayState._bullets = nil - PlayState._scoreText = nil - PlayState._gameOverText = nihil PlayState._spawnTimer = nihil PlayState._spawnInterval = 2.5 - PlayState.SoundExplosionShip = nil - PlayState.SoundExplosionAlien = nihil PlayState.SoundBullet = nihil - variabele toewijzingen PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125) PlayState._ship = Ship.new () PlayState._shoot = false PlayState._aliens = display.newGroup () PlayState._bullets = display.newGroup () PlayState. SoundBullet = media.newEventSound ("Bullet.caf") PlayState._spawnTimer = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer ()? einde

Zoek nu je spawnAlien () -functie en reageer er niet op. Het zou er ongeveer zo uit moeten zien:

 function spawnAlien () -: void local x = FlxG.width local y = Math.random () * (FlxG.height - 100) + 50 _aliens.add (nieuw Alien (x, y)) einde

Deze code maakt een buitenaards wezen net rechts van het scherm en op willekeurige hoogte. Vervolgens wordt de nieuwe alien toegevoegd aan de weergavegroep. We kunnen hetzelfde doen met deze code:

 function spawnAlien () -: void local x = display.contentWidth local y = math.random () * (display.contentHeight - 240) + 50 PlayState._aliens: insert (Alien.new (x, y)) einde

Originele Cosine Wave-gebaseerde beweging voor buitenaardse wezens herscheppen

Als we de code nu uitvoeren, werkt deze bijna als het origineel. De aliens verschijnen op willekeurige hoogtes en ze verschijnen langzaam vaker. Wanneer ze buiten het scherm komen, noemen ze kill () voor zichzelf. Nu moeten we ze gewoon laten bewegen zoals ze deden in de originele code. In het oorspronkelijke spel volgden aliens het pad van een cosinusgolf die werd gegenereerd op basis van hun x-locatie. We hebben deze code becommentarieerd in de aliens update () funciton. Deze code duurde wat spelen met. Omdat we geen snelheid hebben om mee te werken, is het moeilijk om de originele code te gebruiken. Dit is de tijd in de portering waarin je alleen met de nummers hoeft te spelen. Ik vond dat deze code het dichtst bij het origineel werkte:

 functie update () -: void if Alien then if (Alien.x> 0 - Alien.contentWidth) then Alien.x = Alien.x - 2 Alien.y = Alien.y + math.cos (Alien.x / 10 ) * 2 else Alien: kill () end end end

Omgaan met aanvaringen

Nu dat al onze game-objecten werken zoals de originelen, moeten we controleren op botsingen tussen de kogels en buitenaardse wezens, en de aliens en het schip. In de oorspronkelijke code werden botsingen gecontroleerd in de update () -functie. Als er een botsing plaatsvond, werden de twee objecten doorgegeven aan de functies overlap AlienBullet () en overlappen AlienShip (). Laten we eerst die functies maken. Als we overlappingAlienBullet () uncomment, hebben we code die er als volgt uitziet:

 function overlapping AlienBullet (alien, bullet) -: void local emitter = createEmitter () emitter.at (alien) alien.kill () bullet.kill () FlxG.play (SoundExplosionAlien) FlxG.score = FlxG.score + 1 _scoreText. text = FlxG.score.toString () einde

Deze code maakt een deeltjes-emitter, doodt beide objecten, speelt een geluidseffect en werkt de score bij. Het recreëren van het flixel-deeltjessysteem valt buiten het bestek van deze tutorial en we moeten nog een scoresysteem implementeren. Laten we voorlopig alleen die lijnen uitspreken en de objecten doden.

 function overlapAlienBullet (alien, bullet) -: void alien: kill () bullet: kill () --FlxG.play (SoundExplosionAlien) --FlxG.score = FlxG.score + 1 --_ scoreText.text = FlxG.score. toString () einde

Doe hetzelfde voor overlappingAlienShip ():

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () --FlxG.play (SoundExplosionShip) --_ gameOverText = new FlxText (0, FlxG.height / 2, FlxG.width, "GAME OVER \ nDRINK GAAT OPNIEUW OPNIEUW SPELEN ") --_ gameOverText.setFormat (null, 16, 0xFF597137," center ") --add (_gameOverText) einde

Laten we nu het geluidseffect maken voor gebruik in die functies. Maak een opmerking over de klante variabele verklaringen in create ().

 function create () -: void - variable declarations PlayState._inGame = true PlayState._background = nil PlayState._ship = nil PlayState._aliens = nihil PlayState._bullets = nil - PlayState._scoreText = nil - PlayState._gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = nihil PlayState.SoundExplosionAlien = nihil PlayState.SoundBullet = nihil? einde

Wijs ze nu toe aan hun geluiden:

 function create () -: void? - variabele toewijzingen PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125) PlayState._ship = Ship.new () PlayState._shoot = false PlayState._aliens = display.newGroup () PlayState._bullets = display.newGroup () PlayState.SoundBullet = media.newEventSound ("Bullet.caf") PlayState.SoundExplosionShip = media.newEventSound ("ExplosionShip.caf") PlayState.SoundExplosionAlien = media.newEventSound ("ExplosionAlien.caf") PlayState._spawnTimer = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer () einde

De geluiden afspelen is net zo eenvoudig als één regel per functie ().

 function overlapAlienBullet (alien, bullet) -: void alien: kill () bullet: kill () media.playEventSound (PlayState.SoundExplosionAlien) --FlxG.score = FlxG.score + 1 --_ scoreText.text = FlxG.score. toString () eindfunctie overlapAlienShip (alien, schip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) --_ gameOverText = new FlxText (0, FlxG.height / 2, FlxG. breedte, "SPEL OVER \ nDRUK GAAT WEER OPNIEUW SPELEN") --_ gameOverText.setFormat (null, 16, 0xFF597137, "center") --add (_gameOverText) einde

Rol onze eigen aanvalscode

Nu we onze overlapfuncties op zijn plaats hebben, moeten we elk frame controleren op botsingen. In Corona hebben we geen eenvoudige manier om te controleren op overlappende weergaveobjecten. We zullen de controles handmatig moeten uitvoeren. Dit is een vrij eenvoudig concept, maar wordt behoorlijk rommelig bij de implementatie. Laten we hier even over nadenken. Wat definieert een overlapping? Je eerste instinct is misschien om te controleren of een object zich in een ander bevindt. Dit zou werken, maar in dit geval kan een overlapping slechts een deel van de objecten zijn. Een object hoeft niet volledig in een ander te overlappen te zijn. Hoe ziet dit eruit in code? We hoeven alleen maar te controleren of de maximale x-waarde van een object groter is dan de minimumwaarde x
waarde van het andere object. Vervolgens controleren we of de minimum x-waarde van hetzelfde object kleiner is dan de maximale x-waarde van de andere objecten. Dit wordt voor elke overlap waar. Vervolgens voeren we dezelfde controles uit op de y-waarden van de objecten. Als we alle objecten in de weergavegroepen die we eerder hebben gemaakt, doorlopen, zouden we een werkend botsingssysteem moeten hebben.

Laten we dit proberen met de kogels en aliens. We moeten deze controles alleen in het spel uitvoeren. Dus zet deze code in het juiste deel van de update () functie:

 functie update () -: void? als PlayState._inGame dan als PlayState._shoot == true en PlayState._ship dan local p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) end if PlayState._bullets.numChildren> 0 and PlayState._aliens.numChildren> 0 then for b = 1, PlayState._bullets.numChildren do local bulletXMax = PlayState._browets [b] .contentBounds.xMax local bulletXMin = PlayState._browets [b] .contentBounds.xMin local bulletYMax = PlayState._browets [b] .contentBounds.yMax lokaal bulletYMin = PlayState._browets [b] .contentBounds.yMin voor a = 1, PlayState._aliens.numChildren do if (PlayState._aliens [a] .contentBounds.xMin <= bulletXMax) then if (PlayState._aliens[a].contentBounds.xMax >= bulletXMin) en vervolgens if (PlayState._aliens [a] .contentBounds.yMin <= bulletYMax) then if (PlayState._aliens[a].contentBounds.yMax >= bulletYMin) then overlapping AlienBullet (PlayState._aliens [a], PlayState._bullets [b]) einde end end end end end end end

Zoals ik al zei, ziet deze code er een beetje rommelig uit, maar hij werkt. Dus wat doet dit? Ten eerste, het controleert of een kogel of een alien zelfs bestaat. Deze code kan echt geheugenintensief worden, dus we moeten alles controleren. We willen geen tijd verspillen als we niet eens beide soorten objecten hebben. Zodra die code is doorgegeven, starten we een lus. Deze lus zet een variabele ("b" met de naam "bullets") op 1 en voert de rest van de code uit voor elke opsomming in _bullets. De volgende vier coderegels maken een lokale kopie van de min- en max-waarden van de opsommingsteken. Zoals ik al eerder zei, we moeten hier geheugen besparen. We hoeven de kogels x- en y-waarden niet steeds opnieuw te berekenen als ze niet veranderen. De volgende regel start nog een andere lus. Deze herhaalt zich voor alle buitenaardse wezens in _aliens. De code in de tweede for-lus voert alleen de controles uit waar we het eerder over hadden. Is de max x -waarde van de bullet groter dan de minimumwaarde van de alien? Ik kan hier niet voldoende geheugen benadrukken
Daarom controleren we elke voorwaarde in een afzonderlijke if-instructie. Als een van die tests faalt, kunnen we gewoon uit de kring vallen. Het is niet nodig om door te gaan met controleren of er geen botsing is. Uiteindelijk, in het centrum, als al die controles passeren, noemen we onze overlapAlienBullet () -functie met de botsende kogel en alien.

Oef. Dat was veel code. Nu moeten we gewoon hetzelfde doen voor het schip.

 functie update () -: void? als PlayState._inGame dan als PlayState._shoot == true en PlayState._ship dan lokale p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) eindigen? als PlayState._aliens.numChildren> 0 dan local shipXMax = PlayState._ship.contentBounds.xMax local shipXMin = PlayState._ship.contentBounds.xMin local shipYMax = PlayState._ship.contentBounds.yMax local shipYMin = PlayState._ship.contentBounds.yMin voor a = 1, PlayState._aliens.num Kinderen doen if (PlayState._aliens [a] .contentBounds.xMin <= shipXMax) then if (PlayState._aliens[a].contentBounds.xMax >= shipXMin) en vervolgens if (PlayState._aliens [a] .contentBounds.yMin <= shipYMax) then if (PlayState._aliens[a].contentBounds.yMax >= shipYMin) overlappen dan AlienShip (PlayState._aliens [a], PlayState._ship) end end end end end end end

Deze code is identiek aan de kogel- en buitenaardse code. Het enige verschil is dat we maar één schip hebben. We weten dat er een schip is, anders is PlayState._inGame fout. We hoeven niet door een schermgroep van schepen te lopen omdat we er maar één hebben.

Voordat we deze code kunnen testen, moeten we het spel laten eindigen in overlappingAlienShip (). Verander _inGame in false.

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false --_ gameOverText = new FlxText (0, FlxG.height / 2, FlxG .width, "GAME OVER \ nDRUK OPNIEUW ENTER ENTER") --_ gameOverText.setFormat (null, 16, 0xFF597137, "center") --add (_gameOverText) einde

De code nu laten zien dat ons harde werk heeft vruchten afgeworpen. We hebben nu een volledig werkende poort van het originele spel. We moeten nog steeds het scoresysteem opnieuw maken en we moeten het spel opnieuw kunnen starten, maar de harde overdracht is voltooid.

Een scorestelsel implementeren

Laten we beginnen met het scoringssysteem. Dit is net zo eenvoudig als het maken van een tekstlabel en het bijwerken wanneer de score verandert. Maak de regel _scoreText uncomment en voeg een nieuwe _score-eigenschap toe in de create () -verklaringen.

 function create () -: void - variable declarations PlayState._inGame = true PlayState._background = nil PlayState._ship = nil PlayState._aliens = nil PlayState._bullets = nil PlayState._score = nil PlayState._scoreText = nil - PlayState ._gameOverText = nil PlayState._spawnTimer = nihil PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = nihil PlayState.SoundExplosionAlien = nihil PlayState.SoundBullet = nihil? einde

Nu moeten we ze een aantal waarden toewijzen. _score kan gewoon op 0 worden gezet. _scoreText moet een nieuw tekstobject aan de linkerbovenzijde van het scherm worden toegewezen.

 function create () -: void? - variabele toewijzingen PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125) PlayState._ship = Ship.new () PlayState._shoot = false PlayState._aliens = display.newGroup () PlayState._bullets = display.newGroup () PlayState._score = 0 PlayState._scoreText = display.newText ("0", 10, 8, nil, 32) PlayState._scoreText: setTextColor (89 , 113, 55) PlayState.SoundBullet = media.newEventSound ("Bullet.caf") PlayState.SoundExplosionShip = media.newEventSound ("ExplosionShip.caf") PlayState.SoundExplosionAlien = media.newEventSound ("ExplosionAlien.caf") PlayState._spawnTimer = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer () einde

De nieuwe Text-API is eenvoudig: display.newText ("weer te geven tekst", x-positie, y-positie, lettertype, grootte). "PlayState._scoreText: setTextColor (89, 113, 55)" stelt de vulkleur in op dezelfde groene kleur als de kogels. Alles wat we nu nodig hebben is om de score bij te werken in overlappingAlienBullet ():

 function overlapAlienBullet (alien, bullet) -: void alien: kill () bullet: kill () media.playEventSound (PlayState.SoundExplosionAlien) PlayState._score = PlayState._score + 1 PlayState._scoreText.text = PlayState._score end

Dit voegt simpelweg 1 toe aan de eigenschap _score wanneer een buitenaards wezen wordt gedood door een kogel. Vervolgens wordt de eigenschap text van _scoreText gewijzigd in de waarde van de score.

Spel is over

Voordat we deze game afronden, hebben we een manier nodig om hem opnieuw in te stellen. Op die manier kan de gebruiker opnieuw beginnen wanneer ze doodgaan. We zullen dit in twee stappen moeten doen. Ten eerste moeten we alles stoppen dat de gebruiker kan beheersen zodra het schip sterft. Vervolgens moeten we al het andere resetten wanneer de gebruiker tikt om een ​​nieuw spel te starten.

Laten we alle knoppen in de functie overlapAlienShip () uitschakelen. Laten we ook de eigenschap van het schip verwijderen. We kunnen dit doen door alle waarden op nul te zetten.

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = nihil PlayState._upButton.onPress = nihil PlayState._upButton. onRelease = nil PlayState._downButton.onPress = nil PlayState._downButton.onRelease = nil PlayState._leftButton.onPress = nil PlayState._leftButton.onRelease = nil PlayState._rightButton.onPress = nil PlayState._rightButton.onRelease = nil PlayState._shootButton.onPress = nihil PlayState._shootButton.onRelease = nil --_ gameOverText = new FlxText (0, FlxG.height / 2, FlxG.width, "GAME OVER \ nPRESS ENTER TO PLAY OPNIEUW") --_ gameOverText.setFormat (null, 16, 0xFF597137 , "midden") --add (_gameOverText) einde

Deze code wijst gewoon alle waarden van onPress en onRelease toe aan nul. De knoppen zullen nog steeds
display, maar ze zullen geen code bellen als ze worden ingedrukt.

Spel over bericht

We zien nu dat de originele overlapAlienShip () -functie een tekstlabel liet zien om de gebruiker te vertellen dat het spel afgelopen was. We zullen hetzelfde doen. Eerste uncomment onze _gameOverText eigenschap in de create () functie.

 functie te maken () -: void - variabele declaraties PlayState._inGame = true PlayState._background = nihil PlayState._ship = nihil PlayState._aliens = nihil PlayState._bullets = nihil PlayState._score = nihil PlayState._scoreText = nihil PlayState._gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = nihil PlayState.SoundExplosionAlien = nihil PlayState.SoundBullet = nihil? einde

Terug in overlappingAlienShip (), moeten we de code met commentaar vervangen door deze regels.

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = nihil PlayState._upButton.onPress = nihil PlayState._upButton. onRelease = nihil PlayState._downButton.onPress = nihil PlayState._downButton.onRelease = nihil PlayState._leftButton.onPress = nihil PlayState._leftButton.onRelease = nihil PlayState._rightButton.onPress = nihil PlayState._rightButton.onRelease = nihil PlayState._shootButton.onPress = nihil PlayState._shootButton.onRelease = nihil PlayState._gameOverText = display.newText ( "GAME OVER TAP om opnieuw te spelen", 35, display.contentHeight / 2-50, nihil, 16) PlayState._gameOverText: SetTextColor (89, 113, 55) einde

Dit is dezelfde code die we hebben gebruikt om de scoretekst te maken en te vullen. De positie wordt gewijzigd om de tekst op het scherm te centreren en in de tekst staat "TAP TO PLAY AGAIN" in plaats van "DRUK OP ENTER OM OPNIEUW TE SPELEN".

Voeg een tikluisteraar toe

Omdat we gaan tikken om het spel opnieuw te starten, moeten we een nieuwe gebeurtenislistener toevoegen. We kunnen dit op dezelfde manier doen als we de enterFrame-luisteraar hebben toegevoegd, maar deze keer is de gebeurtenis waar we naar luisteren "tikken". We moeten ook een functie toevoegen die de luisteraar kan bellen. Voeg onderaan de overlap AlienShip () deze gebeurtenislistener toe:

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = nihil PlayState._upButton.onPress = nihil PlayState._upButton. onRelease = nihil PlayState._downButton.onPress = nihil PlayState._downButton.onRelease = nihil PlayState._leftButton.onPress = nihil PlayState._leftButton.onRelease = nihil PlayState._rightButton.onPress = nihil PlayState._rightButton.onRelease = nihil PlayState._shootButton.onPress = nil PlayState._shootButton.onRelease = nil PlayState._gameOverText = display.newText ("GAME OVER TAP TO PLAY AGAIN", 35, display.contentHeight / 2 - 50, nil, 16) PlayState._gameOverText: setTextColor (89, 113, 55) Runtime: addEventListener ("tik op", tik) einde

Deze code controleert of ergens op het scherm wordt geklikt. Wanneer een "tik" optreedt, roept het de functie aan (). Laten we een lege tik () maken om te callen. Zet het net boven create ().

? functie tap (event) - we hebben dit alleen nodig als een tijdelijke aanduiding voor nu end function create ()? einde

Alles opruimen

Laten we een remove () -functie maken om alle game-objecten op te ruimen. Zet deze functie boven onze nieuwe tik () functie.

? functie remove () - einde functie tik (event) - we hebben dit alleen nodig als tijdelijke aanduiding voor nu end function create ()? einde

Display-objecten en -groepen verwijderen

Om te beginnen moeten we alle resterende buitenaardse wezens en kogels doden. Om dit te doen, kunnen we eenvoudig door de respectieve displaygroepen bladeren. Dit is de juiste manier om objecten in Corona te verwijderen:

 functie remove () voor i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () einde voor i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () end PlayState._bullets: removeSelf () PlayState._bullets = nil PlayState._aliens: removeSelf () PlayState._aliens = nil end

Deze lussen werken op een speciale manier. Elke lus begint met "i" ingesteld op het laatste object in de displaygroepen. De kring doodt dat object en trekt 1 af van "i". De lus herhaalt totdat "i" gelijk is aan 1. De reden die we aftrekken van "i" is dat elke keer dat we een object doden, het zichzelf verwijdert uit de weergavegroep. Dit betekent dat er een minder object in de weergavegroep is. Als we 1 zouden toevoegen aan "i", zouden we eindigen met kill () op objecten die niet meer bestaan. Om dit te verhelpen, tellen we achteruit telkens wanneer we een object verwijderen.

Nadat alle objecten uit de groepen zijn verwijderd, verwijderen we de groepen. We hebben ook de eigenschappen ingesteld die de groepen tot nul hebben gehouden. Nu kunnen ze opnieuw worden gebruikt.

Nil-uit-variabelen voor de vuilnisman

Laten we alle gebruikte variabelen op nul zetten. Op deze manier kan de garbage collector het geheugen vrijmaken. Dit zorgt er ook voor dat alle variabelen worden gereset voordat we een nieuw spel beginnen. Verwijder eerst alle knoppen:

 functie remove () voor i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () einde voor i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () uiteinde PlayState._bullets: removeSelf () PlayState._bullets = nihil PlayState._aliens: removeSelf () PlayState._aliens = nihil PlayState._upButton: removeSelf () PlayState._upButton = nihil PlayState._downButton: removeSelf () PlayState._downButton = nil PlayState._leftButton: removeSelf () PlayState._leftButton = nil PlayState._rightButton: removeSelf () PlayState._rightButton = nil PlayState._shootButton: removeSelf () PlayState._shootButton = nil end

We moeten ze eerst van het scherm verwijderen en vervolgens op nul zetten. Laten we nu voor onze geluiden zorgen.

 functie remove () voor i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () einde voor i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () uiteinde PlayState._bullets: removeSelf () PlayState._bullets = nihil PlayState._aliens: removeSelf () PlayState._aliens = nihil PlayState._upButton: removeSelf () PlayState._upButton = nihil PlayState._downButton: removeSelf () PlayState._downButton = nil PlayState._leftButton: removeSelf () PlayState._leftButton = nil PlayState._rightButton: removeSelf () PlayState._rightButton = nil PlayState._shootButton: removeSelf () PlayState._shootButton = nihil PlayState.SoundExplosionShip = nihil PlayState.SoundExplosionAlien = nihil PlayState. SoundBullet = nul einde

Nu onze tekstobjecten:

 functie remove ()? PlayState._scoreText: removeSelf () PlayState._scoreText = nil PlayState._gameOverText: removeSelf () PlayState._gameOverText = nil end

Event-luisteraars verwijderen

Om het opruimen te voltooien, moeten we onze evenementluisteraars verwijderen. Daarna kunnen we PlayState eindelijk opnieuw instellen op een lege array:

 functie remove ()? Runtime: removeEventListener ("enterFrame", update) Runtime: removeEventListener ("tikken", tik op) PlayState = nil PlayState =  einde

Game herstarten

Het herstarten van de game is net zo eenvoudig als het aanroepen van remove () en dan create () in onze tik () functie.

 functie tik (event) remove () create () end

Laatste aanpassingen

We zijn bijna klaar. We hoeven alleen maar een paar afwerkingen aan te brengen. Begin met het verwijderen van alle commentaarregels uit de oude broncode. Dit zal onze bestanden een beetje opschonen.

Multitouch inschakelen

Een andere snelle aanpassing die we kunnen maken, is multitouch inschakelen. U zult de verandering op de simulator niet opmerken, maar het is prettig om meerdere knoppen tegelijk op het eigenlijke apparaat te kunnen indrukken. Dit is een aanpassing van één regel. We hoeven het maar één keer te laten gebeuren, dus laten we het toevoegen aan het main.lua-bestand.

 lokaal PlayState = require ("PlayState") functie Main () system.activate ("multitouch") display.setStatusBar (display.HiddenStatusBar) PlayState.PlayState () einde Main ()

De UI-bibliotheek aanpassen aan onze behoeften

Ik had ook wat problemen met de ui.lua-module. De knoppen tellen niet mee als je je vinger van het apparaat haalt voor een release, tenzij de laatste plaats de knop was. Dit werkt niet altijd goed voor dit specifieke spel, en soms lijkt het schip alleen te bewegen omdat de release-functie niet wordt aangeroepen. Dit was een eenvoudige oplossing. Ik heb de controle verwijderd om te zien of de knop werd ingedrukt toen de vinger van de gebruiker werd losgelaten. Dit betekende alleen maar commentaar geven op de if en eind-statements op regel 91 en 98.

? als "ended" == fase dan - beschouw dit alleen als een "klik" als de gebruiker zijn vinger binnen de stage's van de knop laat komen - als dat in bin nen is dan als onEvent dan buttonEvent.phase = "release" result = onEvent (buttonEvent) andersif onRelease dan result = onRelease (event) end-end end? 

Deze wijzigingen zijn opgenomen in het bestand ui.lua dat in deze zelfstudie is opgenomen.

Conclusie

We zijn klaar. We hebben nu een volledig werkende replica van het originele flash-spel. We hebben een schip dat beweegt en vuurt, buitenaardse wezens en een scoresysteem. De game beheert het geheugen van alle objecten en heeft de mogelijkheid om te resetten en opnieuw te beginnen. Anders dan het particle systeem, is dit spel een identieke poort. Nu je deze tutorial hebt voltooid, moet je over voldoende kennis beschikken om bijna elk Flash / Actionscript-spel naar de iPhone te sturen.

Oefeningen en extra functies

Veel ontwikkelaars v