Porterer ActionScript-spill til iOS med Corona SDK Del 3

Denne opplæringen vil ta en titt på å overføre et Flash / Flex-spill til Corona SDK. Spesielt vil vi overføre fra ActionScript til Lua, med sluttmål å spille tidligere Flash-bare spill på iPhone. I tillegg til å demonstrere språk- og API-forskjeller, vil denne opplæringsserien også ta hensyn til maskinvarebegrensninger som skjermstørrelse og mangel på fysiske knapper på iPhone.

Legge til fienden

Nå skal vi begynne å jobbe med fienden vår: "de / pixelate / flixelprimer / Alien.as". Syntaks blir som alltid først konvertert.

Når du er ferdig med det, legger du til moduldeklarasjonen og vikler alle funksjonene inne i Alien ().

 modul (?, package.seeall) - [Embed (source = "? /? /? /? /assets/png/Alien.png")] privat var ImgAlien: Klassifunksjon Alien (x, y) -: void super (x, y, ImgAlien) hastighet.x = -200 funksjonsoppdatering () -: void velocity.y = Math.cos (x / 50) * 50 super.update () slutten

Alien fungerer veldig lik vår kulde. Den lager et bilde, setter sin x og y
koordinater, og gir det en hastighet. Så vi nærmer oss det på samme måte. De to øverste linjene inne i funksjonen kan erstattes med nesten samme kode som vi brukte for kulen. Denne gangen bruker vi et bilde skjønt.

 modul (?, package.seeall) funksjon Alien (x, y) -: void local Alien = display.newImage ("Alien.png") Alien.x = x Alien.y = y funksjonsoppdatering () -: void ? slutten

Nå som vi har bildet lastet og satt, la oss få det til å flytte til venstre. Igjen, vil vi opprette noe som kuleoppdateringen () -koden vår. La de gamle linjene inne i oppdateringen () kommenteres.

 modul (?, package.seeall) funksjon Alien (x, y) -: void? funksjon oppdatering () -: tom hvis Alien deretter hvis (Alien.x> 0 - Alien.contentWidth) deretter Alien.x = Alien.x - 2 end-end? kommentert kode? slutt Runtime: addEventListener ("enterFrame", oppdatering) slutt

La oss nå gjøre en kill () -funksjon, og få Alien til å returnere en Alien.

 modul (?, package.seeall) funksjon Alien (x, y) -: void? funksjonsoppdatering () -: ugyldig? sluttfunksjon Alien: kill () Alien.parent: remove (Alien) Alien = null slutt Runtime: addEventListener ("enterFrame", oppdatering) return Alien end

Nå kan vi drepe () vår fremmed, hvis det er x, er utenfor skjermen til venstre. Vi kan også legge til en ny () -funksjon som en bekvemmelighet.

 modul (?, package.seeall) funksjon Alien (x, y) -: void local Alien = display.newImage ("Alien.png") Alien.x = x Alien.y = y funksjonsoppdatering () -: void hvis Alien da hvis (Alien.x> 0 - Alien.contentWidth) så Alien.x = Alien.x - 2 else Alien: kill () slutten slutten endring Alien: kill () Alien.parent: remove (Alien) Alien = null end Runtime: addEventListener ("enterFrame", oppdater) return Alien end-funksjon ny (x, y) return Alien (x, y) slutten

Bruke Timere til å kontrollere Aliens

Å lage fremmede var ganske enkelt. Nå må vi begynne å legge dem til spillet gjennom PlayState.

Først importerer du modulen til PlayState.lua.

 modul (?, package.seeall) lokale Skip = krever ("Ship") lokale Bullet = krever ("Bullet") lokale Alien = krever ("Alien") lokale knapper = krever ("knapper")

Nå må vi sette opp en timer. Den opprinnelige koden hadde en variabel _spawnInterval som ble brukt til å sette _spawnTimer. Hver gang _spawnTimer nådde 0, ville det bli tilbakestilt til verdien av _spawnInterval._spawnInterval ville da bli redusert med .1, noe som resulterte i at romvesener ble skapt raskere.

For å starte, kommenterer _spawnInterval og _spawnTimer eiendomsdekleringene i create ().

 funksjon opprette () -: void - variable deklarasjoner PlayState._inGame = true PlayState._background = null PlayState._ship = nil - PlayState._aliens = null PlayState._bullets = nil - PlayState._scoreText = null - Spillstat. _gameOverText = nil PlayState._spawnTimer = null PlayState._spawnInterval = nil - PlayState.SoundExplosionShip = nil - PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = null? slutt

Nå i de variable oppdragene, sett _spawnTimer til 0 og _spawnInterval til 2.5. Legg også til et anrop for å tilbakestilleSpawnTimer (). Vi lager denne funksjonen på et sekund.

 funksjon opprette () -: ugyldig? - variable oppgaver 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 () slutten

Finn nå kommentert funksjon resetSpawnTimer (). Det vil se noe ut som dette.

 funksjon resetSpawnTimer () -: void _spawnTimer = _spawnInterval _spawnInterval = _spawnInterval * 0.95 hvis (_spawnInterval < 0.1) then _spawnInterval = 0.1 end end

Utrolig nok, det er akkurat det vi trenger. Vi trenger bare å gjøre variablene til PlayState. På den måten vil funksjonen vite hva _spawnInterval og _spawnTimer vi snakker om.

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

Nå må vi legge til noe kode for å oppdatere (). I den opprinnelige koden skapte spillet romvesener selv om spillet var over og skipet var dødt. For å gjøre det samme, la oss sette vår fremmede håndteringskode utenfor der vi sjekker om spillet er over.

 funksjon oppdatering () PlayState._spawnTimer = PlayState._spawnTimer - (30/1000) hvis (PlayState._spawnTimer < 0) then spawnAlien() resetSpawnTimer() end if PlayState._inGame then? end end

Denne koden fungerer akkurat som kildekoden. Den trekker 1 ramme er verdt tid fra _spawnTimer. Det kontrollerer deretter om _spawnTimer er mindre enn null. Hvis det er, resetter det tidtakeren og gis en ny fremmed.

En annen skjermgruppe

Før vi kan hevne utlendinger, trenger vi en visningsgruppe for å legge dem til. Akkurat som _bullets, uncomment _aliens decleration og tilordne dem til en ny skjermgruppe.

 funksjon opprette () -: void - variable deklarasjoner PlayState._inGame = true PlayState._background = null PlayState._ship = null PlayState._aliens = null PlayState._bullets = nil - PlayState._scoreText = nil - PlayState._gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = 2.5 - PlayState.SoundExplosionShip = nil - PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = null - variable oppgaver 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 ()? slutt

Finn nå din spawnAlien () -funksjon og unkent den. Det skal se slik ut:

 funksjon spawnAlien () -: void local x = FlxG.width lokal y = Math.random () * (FlxG.height - 100) + 50 _aliens.add (ny Alien (x, y)) slutten

Denne koden skaper en fremmed rett til høyre på skjermen og i tilfeldig høyde. Deretter legger den den nye alien til skjermgruppen. Vi kan gjøre det samme med denne koden:

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

Rekreasjon Original Cosine Wave Based Motion For Aliens

Hvis vi kjører koden nå, virker den nesten som original. Utlendingene vises i tilfeldige høyder, og de vises sakte oftere. Når de kommer utenfor skjermen, kaller de kill () på seg selv. Nå trenger vi bare å få dem til å flytte slik de gjorde i den opprinnelige koden. I det opprinnelige spillet fulgte romvesen banen til en cosinabølge som ble generert basert på deres x-plassering. Vi har denne koden kommentert i utlendingsoppdateringen () funciton. Denne koden tok litt å spille med. Fordi vi ikke har hastighet til å jobbe med, er det vanskelig å bruke originalkoden. Dette er tiden i porting hvor du bare må spille med tallene. Jeg fant denne koden fungerte nærmest originalen:

 funksjon oppdatering () -: ugyldig hvis Alien deretter hvis (Alien.x> 0 - Alien.contentWidth) deretter Alien.x = Alien.x - 2 Alien.y = Alien.y + math.cos (Alien.x / 10 ) * 2 andre Alien: kill () slutten slutten

Håndteringskollisjoner

Nå som vi har alle våre spillobjekter som fungerer som originaler, må vi sjekke for kollisjoner mellom kuler og romvesener, og romvesen og skipet. I den opprinnelige koden ble kollisjoner sjekket i oppdateringen () -funksjonen. Hvis en kollisjon oppstod, ble de to objektene overført til funksjonene overlapAlienBullet () og overlapAlienShip (). La oss lage disse funksjonene først. Hvis vi uncomment overlapAlienBullet (), har vi kode som ser slik ut:

 funksjon overlapAlienBullet (alien, bullet) -: void local emitter = createEmitter () emitter.at (alien) alien.kill () bullet.kill () FlxG.play (SoundExplosionAlien) FlxG.score = FlxG.score + 1 _scoreText. tekst = FlxG.score.toString () slutten

Denne koden oppretter en partikkelemitter, dreper begge objektene, spiller en lydeffekt, og oppdaterer poengsummen. Å gjenoppta flixelpartikkelsystemet er utenfor omfanget av denne opplæringen, og vi har ennå ikke implementert et poengsum. For nå, la oss bare kommentere disse linjene og drepe objekter.

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

Gjør det samme for overlapAlienShip ():

 funksjonen overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () --FlxG.play (SoundExplosionShip) --_ gameOverText = ny FlxText (0, FlxG.height / 2, FlxG.width, "GAME OVER \ nPRESS ENTER TO PLAY AGAIN ") --_ gameOverText.setFormat (null, 16, 0xFF597137," senter ") --add (_gameOverText) slutten

La oss nå lage lydeffekten for bruk i disse funksjonene. Uncent de lydvariabeldeklarasjonene i create ().

 funksjon opprette () -: void - variable deklarasjoner PlayState._inGame = true PlayState._background = null PlayState._ship = null PlayState._aliens = null PlayState._bullets = nil - PlayState._scoreText = nil - PlayState._gameOverText = nil PlayState._spawnTimer = null PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = null PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = null? slutt

Tilordne dem nå til lydene sine:

 funksjon opprette () -: ugyldig? - variable oppgaver 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 () slutten

Spille lydene er like enkelt som en linje per funksjon ().

 funksjon overlapAlienBullet (alien, bullet) -: void alien: kill () bullet: kill () media.playEventSound (PlayState.SoundExplosionAlien) --FlxG.score = FlxG.score + 1 --_ scoreText.text = FlxG.score. toString () sluttfunksjon overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) --_ gameOverText = ny FlxText (0, FlxG.height / 2, FlxG. bredde, "GAME OVER \ nPRESS ENTER TIL SPILL IGJEN") --_ gameOverText.setFormat (null, 16, 0xFF597137, "senter") --add (_gameOverText) end

Rull vår egen kollisjonskode

Nå som vi har våre overlappingsfunksjoner på plass, må vi sjekke for kollisjoner hver ramme. I Corona har vi ikke en enkel måte å se etter overlappende visningsobjekter. Vi må gjøre kontrollene manuelt. Dette er et ganske enkelt konsept, men blir ganske rotete i implementering. La oss tenke på dette i et sekund. Hva definerer en overlapping? Ditt første instinkt kan være å kontrollere om et objekt er inne i en annen. Dette ville fungere, men i dette tilfellet kan en overlapping bare være deler av objektene. Et objekt trenger ikke å være helt inne i et annet for å overlappe. Hvordan ser dette ut i kode? Alt vi trenger å gjøre er å sjekke om maksimum x-verdien av et utkast er større enn minumum x
verdien av det andre objektet. Deretter sjekker vi om det samme objektets minimum x-verdi er mindre enn de andre objektene maksimale x-verdien. Dette vil returnere sant for hver overlapping. Deretter utfører vi de samme kontrollene på objektets y-verdier. Hvis vi løp gjennom alle gjenstandene i skjermgruppene vi opprettet tidligere, bør vi ha et fungerende kollisjonssystem.

La oss prøve dette med kuler og romvesener. Vi må bare utføre disse kontrollene i spillet. Så sett denne koden inne i den riktige delen av oppdateringen () -funksjonen:

 funksjonsoppdatering () -: ugyldig? hvis PlayState._inGame deretter hvis PlayState._shoot == true og PlayState._ship deretter lokale p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) avslutt hvis PlayState._bullets.numChildren> 0 og PlayState._aliens.numChildren> 0 da for b = 1, PlayState._bullets.numChildren gjør lokale bulletXMax = PlayState._bullets [b] .contentBounds.xMax lokale bulletXMin = PlayState._bullets [b] .contentBounds.xMin lokale bulletYMax = PlayState._bullets [b] .contentBounds.yMax local bulletYMin = PlayState._bullets [b] .contentBounds.yMin for a = 1, PlayState._aliens.numChildren gjør om (PlayState._aliens [a] .contentBounds.xMin <= bulletXMax) then if (PlayState._aliens[a].contentBounds.xMax >= bulletXMin) så hvis (PlayState._aliens [a] .contentBounds.yMin <= bulletYMax) then if (PlayState._aliens[a].contentBounds.yMax >= bulletYMin) så overlapAlienBullet (PlayState._aliens [a], PlayState._bullets [b]) slutten på enden av enden på enden

Som jeg sa, ser denne koden litt rotete ut, men den fungerer. Så hva gjør dette? Først sjekker det om en kule eller en fremmed selv eksisterer. Denne koden kan bli veldig minneintensiv, så vi må sjekke alt. Vi vil ikke kaste bort tid hvis vi ikke engang har begge typer objekter. Når den koden går, starter vi en forløp. Denne sløyfen setter en variabel ("b" oppkalt etter "kuler") til 1 og kjører resten av koden for hvert punkt i _bullets. De neste fire kodelinjene oppretter en lokal kopi av min- og maxverdiene i punktet. Som jeg sa før, må vi lagre minne her. Vi trenger ikke å beregne kulene x og y verdier igjen og igjen hvis de ikke endres. Neste linje starter enda en gang for sløyfe. Denne gjentas for alle utlendingene i _aliens. Koden innsiden av den andre for sløyfen utfører bare kontrollene vi snakket om tidligere. Er kulaets maksimale x-verdi større enn utlendingens min x-verdi? Jeg kan ikke stresse minnet nok her, det
er derfor vi sjekker hver tilstand i en separat hvis erklæring. Hvis en av disse testene feiler, kan vi bare slippe ut av løkken. Det er ikke nødvendig å fortsette å sjekke om det ikke er noen kollisjon. Til slutt, i selve senteret, hvis alle disse sjekkene passerer, kaller vi vår overlapAlienBullet () -funksjon med kolliderende kule og fremmed.

Puh. Det var mye kode. Nå trenger vi bare å gjøre det samme for skipet.

 funksjonsoppdatering () -: ugyldig? hvis PlayState._inGame deretter hvis PlayState._shoot == true og PlayState._ship deretter lokalt p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) avslutte? hvis PlayState._aliens.numChildren> 0 så lokalt skipXMax = PlayState._ship.contentBounds.xMax lokalt skipXMin = PlayState._ship.contentBounds.xMin lokalt skipYMax = PlayState._ship.contentBounds.yMax lokalt skipYMin = PlayState._ship.contentBounds.yMin for a = 1, PlayState._aliens.numChildren gjør om (PlayState._aliens [a] .contentBounds.xMin <= shipXMax) then if (PlayState._aliens[a].contentBounds.xMax >= shipXMin) så hvis (PlayState._aliens [a] .contentBounds.yMin <= shipYMax) then if (PlayState._aliens[a].contentBounds.yMax >= shipYMin) så overlapAlienShip (PlayState._aliens [a], PlayState._ship) slutten enden slutten ende ende ende ende

Denne koden er identisk med kule- og fremmedkode. Den eneste forskjellen er at vi bare har ett skip. Vi vet at det er et skip, ellers ville PlayState._inGame være feil. Vi trenger ikke å gå gjennom en skjermgruppe av skip fordi vi bare har en.

Før vi kan teste denne koden, må vi gjøre kampen slutt i overlapAlienShip (). Endre _inGame til false.

 funksjonen overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false --_ gameOverText = ny FlxText (0, FlxG.height / 2, FlxG .width, "GAME OVER \ nPRESS ENTER Å SPILL IGJEN") --_ gameOverText.setFormat (null, 16, 0xFF597137, "senter") --add (_gameOverText) slutten

Kjører koden viser nå at vårt harde arbeid har lønnet seg. Vi har nå en fullt fungerende havn i det opprinnelige spillet. Vi trenger fortsatt å gjenskape poengsummen, og vi må kunne starte spillet på nytt, men den harde portingen er ferdig.

Implementere et score system

La oss starte med poengsystemet. Dette er like enkelt som å lage en tekstetikett, og oppdatere den når poenget endres. Uncomment _scoreText-linjen og legg til en ny _score-egenskap i opprettelsen () -deklarasjonen.

 funksjon opprett () -: void - variable deklarasjoner PlayState._inGame = true PlayState._background = null PlayState._ship = null PlayState._aliens = null PlayState._bullets = null PlayState._score = null PlayState._scoreText = null - Spillstat ._gameOverText = nil PlayState._spawnTimer = null PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = null PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = null? slutt

Nå må vi tilordne dem noen verdier. _score kan bare settes til 0. _scoreText må tilordnes et nytt tekstobjekt plassert øverst til venstre på skjermen.

 funksjon opprette () -: ugyldig? - variable oppgaver 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, null, 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 () slutten

NewText API er enkelt: display.newText ("tekst å vise", x posisjon, y posisjon, skrift, størrelse). "PlayState._scoreText: setTextColor (89, 113, 55)" setter bare fyllfarge til samme grønne farge som kulene. Alt vi trenger nå er å oppdatere poengsummen i overlapAlienBullet ():

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

Dette legger ganske enkelt 1 til _score-eiendommen når en fremmed blir drept av en kule. Deretter endres tekstegenskapen til _scoreText til verdien av poengsummen.

Spillet er slutt

Før vi pakker opp dette spillet, trenger vi en måte å tilbakestille den på. På den måten kan brukeren starte når de dør. Vi må gjøre dette i to trinn. Først må vi stoppe alt som brukeren kan kontrollere så snart skipet dør. Da må vi nullstille alt annet når brukeren taper for å starte et nytt spill.

La oss slå av alle knappene i funksjonen overlapAlienShip (). La oss også fjerne skipets eiendom. Vi kan gjøre dette ved å sette alle verdiene til null.

 funksjonen overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = null PlayState._upButton.onPress = null PlayState._upButton. onRelease = null PlayState._downButton.onPress = null PlayState._downButton.onRelease = null PlayState._leftButton.onPress = null PlayState._leftButton.onRelease = null PlayState._rightButton.onPress = null PlayState._rightButton.onRelease = null PlayState._shootButton.onPress = nil PlayState._shootButton.onRelease = nil --_ gameOverText = ny FlxText (0, FlxG.height / 2, FlxG.width, "GAME OVER \ nPRESS ENTER TIL SPILL IGJEN") --_ gameOverText.setFormat (null, 16, 0xFF597137 , "senter") --add (_gameOverText) slutten

Denne koden tilordner bare alle onPress og onRelease-verdiene til null. Knappene vil fortsatt
display, men de vil ikke ringe noen kode når de trykkes.

Spill over melding

Vi ser nå at den opprinnelige funksjonen overlapAlienShip () viste en tekstetikett for å fortelle brukeren at spillet var over. Vi vil gjøre det samme. Først uncomment vår _gameOverText eiendom i create () -funksjonen.

 funksjon opprett () -: void - variable declarations PlayState._inGame = ekte PlayState._background = null PlayState._ship = null PlayState._aliens = null PlayState._bullets = null PlayState._score = null PlayState._scoreText = null PlayState._gameOverText = null PlayState._spawnTimer = null PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = null PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = null? slutt

Tilbake i overlapAlienShip (), må vi erstatte kommentert kode med disse linjene.

 funksjonen overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = null PlayState._upButton.onPress = null PlayState._upButton. onRelease = null PlayState._downButton.onPress = null PlayState._downButton.onRelease = null PlayState._leftButton.onPress = null PlayState._leftButton.onRelease = null PlayState._rightButton.onPress = null PlayState._rightButton.onRelease = null 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) ende

Dette er den samme koden vi pleide å lage og fylle ut poengsummen. Posisjonen endres for å sentrere teksten på skjermen, og teksten sier "TAP TO PLAY AGAIN" i stedet for "PRESS ENTER TO PLAY AGAIN".

Legg til en trykklytter

Siden vi skal trykke på for å starte spillet på nytt, må vi legge til en ny hendelselytter. Vi kan gjøre dette på samme måte som vi legger til enterFrame-lytteren, men denne gangen er hendelsen vi lytter etter, "trykk". Vi må også legge til en funksjon for lytteren å ringe. På bunnen av overlapAlienShip () legg til denne hendelseslytteren:

 funksjonen overlapAlienShip (alien, skip) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = null PlayState._upButton.onPress = null PlayState._upButton. onRelease = null PlayState._downButton.onPress = null PlayState._downButton.onRelease = null PlayState._leftButton.onPress = null PlayState._leftButton.onRelease = null PlayState._rightButton.onPress = null PlayState._rightButton.onRelease = null 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 ("trykk", trykk) slutt

Denne koden kontrollerer et trykk hvor som helst på skjermen. Når et "trykk" oppstår, kalles det funksjonstasten (). La oss lage en tom trykk () funciton for at den skal ringe. Sett det like over create ().

? funksjonstast (hendelse) - vi trenger bare dette som en plassholder for nå sluttfunksjonen skape ()? slutt

Rengjør alt opp

La oss gjøre en fjern () -funksjon for å håndtere å rydde opp alle spillobjektene. Sett denne funksjonen over vår nye tap () -funksjon.

? funksjon fjern () - sluttfunksjonstrykk (hendelse) - vi trenger bare dette som plassholder for nå sluttfunksjon opprett ()? slutt

Fjerne skjermobjekter og grupper

Til å begynne med, bør vi drepe alle de gjenværende romvesenene og kulene. For å gjøre dette kan vi bare gå gjennom de respektive skjermgruppene. Dette er den riktige måten å fjerne objekter i Corona på:

 funksjonen fjern () for i = PlayState._bullets.numChildren, 1, -1 gjør PlayState._bullets [i]: kill () end for i = PlayState._aliens.numChildren, 1, -1 gjør PlayState._aliens [i]: drepe () slutte PlayState._bullets: removeSelf () PlayState._bullets = null PlayState._aliens: removeSelf () PlayState._aliens = null end

Disse løkkene fungerer på en spesiell måte. Hver sløyfe starter med "i" satt til det siste objektet i skjermgruppene. Så dreper løkken det objektet og trekker 1 fra "jeg". Sløyfen gjentas til "jeg" er lik 1. Grunnen til at vi trekker fra "jeg" er at hver gang vi dreper et objekt fjerner det seg fra skjermgruppen. Dette betyr at det er et mindre objekt i skjermgruppen. Hvis vi skulle legge til 1 til "jeg", ville vi ende opp med å kalle drep () på objekter som ikke eksisterer lenger. For å fikse dette teller vi bakover hver gang vi fjerner et objekt.

Når alle objektene er fjernet fra gruppene, fjerner vi gruppene. Vi satte også egenskapene som holdt gruppene til null. Nå kan de brukes igjen.

Null-ing Out Variables For Garbage Collector

La oss sette alle brukte variabler til null. På denne måten kan søppelsamleren frigjøre minnet. Dette vil også sørge for at alle variablene tilbakestilles før vi starter et nytt spill. Fjern alle knappene først:

 funksjonen fjern () for i = PlayState._bullets.numChildren, 1, -1 gjør PlayState._bullets [i]: kill () end for i = PlayState._aliens.numChildren, 1, -1 gjør PlayState._aliens [i]: drepe () slutte PlayState._bullets: removeSelf () PlayState._bullets = null PlayState._aliens: removeSelf () PlayState._aliens = null PlayState._upens: removeSelf () PlayState._upButton = null PlayState._downButton: removeSelf () PlayState._downButton = null PlayState._leftButton: removeSelf () PlayState._leftButton = null PlayState._rightButton: removeSelf () PlayState._rightButton = null PlayState._shootButton: removeSelf () PlayState._shootButton = null end

Vi må først fjerne dem fra skjermen og sette dem til null. La oss ta vare på våre lyder nå.

 funksjonen fjern () for i = PlayState._bullets.numChildren, 1, -1 gjør PlayState._bullets [i]: kill () end for i = PlayState._aliens.numChildren, 1, -1 gjør PlayState._aliens [i]: drepe () slutte PlayState._bullets: removeSelf () PlayState._bullets = null PlayState._aliens: removeSelf () PlayState._aliens = null PlayState._upens: removeSelf () PlayState._upButton = null PlayState._downButton: removeSelf () PlayState._downButton = null PlayState._leftButton: removeSelf () PlayState._leftButton = null PlayState._rightButton: removeSelf () PlayState._rightButton = null PlayState._shootButton: removeSelf () PlayState._shootButton = null PlayState.SoundExplosionShip = null PlayState.SoundExplosionAlien = nil PlayState. SoundBullet = null slutt

Nå våre tekstobjekter:

 funksjon fjerner ()? PlayState._scoreText: removeSelf () PlayState._scoreText = null PlayState._gameOverText: removeSelf () PlayState._gameOverText = null end

Fjerner hendelseslyttere

For å fullføre opprydningen må vi fjerne hendelseslytterne våre. Deretter kan vi endelig nullstille PlayState til en tom rekkefølge:

 funksjon fjerner ()? Runtime: removeEventListener ("enterFrame", oppdatering) Runtime: removeEventListener ("trykk", trykk) PlayState = nil PlayState =  end

Restarting Game

Omstart av spillet er så enkelt som å kalle fjerne () og deretter opprette () i vår trykk () -funksjon.

 funksjonstast (hendelse) fjern () opprett () slutt

Final Tweaks

Vi er nesten ferdige. Vi trenger bare å sette noen få finish på. Begynn med å fjerne alle kommenterte linjer fra gammel kildekode. Dette vil rense våre filer opp et tonn.

Aktiverer multitouch

En annen rask tweak vi kan gjøre er å aktivere multitouch. Du vil ikke merke endringen på simulatoren, men det er fint å kunne trykke flere knapper om gangen på den aktuelle enheten. Dette er en linjejustering. Vi trenger bare at det skal skje en gang, så la oss legge den til main.lua-filen.

 lokal PlayState = krever ("PlayState") -funksjon Hoved () system.activate ("multitouch") display.setStatusBar (display.HiddenStatusBar) PlayState.PlayState () slutten Main ()

Endre UI-biblioteket for å passe våre behov

Jeg hadde også problemer med ui.lua-modulen. Knappene teller ikke med å trekke fingeren av enheten en utløsning, med mindre det siste stedet berørt var knappen. Dette virker ikke alltid riktig for dette spillet, og noen ganger ser skipet ut til å bevege seg på egenhånd fordi utgivelsesfunksjonen ikke blir kalt. Dette var en enkel løsning. Jeg fjernet sjekken for å se om knappen ble trykket når brukerens finger ble løslatt. Dette betydde bare å kommentere om og slutt setningene på linjene 91 og 98.

? hvis "endte" == fase da - bare betrakt dette som et "klikk" hvis brukeren løfter fingeren inne i knappens stadium. Bounds - er WithinBounds deretter hvis onEvent then buttonEvent.phase = "release" result = onEvent (buttonEvent) elseif onRelease deretter result = onRelease (event) end-end slutten? 

Disse endringene er inkludert i ui.lua-filen som følger med denne opplæringen.

Konklusjon

Vi er ferdige. Vi har nå en fullt fungerende kopi av det opprinnelige flashspillet. Vi har et skip som beveger seg og branner, romvesener og et poengsum. Spillet håndterer minne om alle objekter, og har muligheten til å tilbakestille og starte over. Annet enn partikkelsystemet, er dette spillet en identisk port. Nå som du har fullført denne opplæringen, bør du ha tilstrekkelig kunnskap til å port nesten alle flash / actionscript spill til iPhone.

Øvelser og ekstra funksjoner

Mange utviklere liker å legge til funksjonalitet eller forandre gameplayet litt når portene sendes til en mobil enhet. Jeg vil utfordre deg til å forbedre / endre dette spillet for å gjøre det mer som en ekte app. Du kan endre kontrollskjemaet til noen av typene vi snakket om i leksjon 2. Du kan opprette en meny med innstillinger eller flere nivåer. Du kan legge til forskjellige typer fiender. Du kan legge til et lokalt eller online høy score system. Mulighetene er endeløse. Heldigvis gjør Corona utviklingen veldig rask og veldig jevn. Jeg håper du likte denne opplæringen, og enda viktigere, lært mye. Legg igjen en kommentar nedenfor for å fortelle oss hvordan ting gikk.