Porting di giochi ActionScript su iOS con Corona SDK parte 2

Questo tutorial fornirà il porting di un gioco Flash / Flex all'SDK Corona. In particolare, eseguiremo il porting da ActionScript a Lua, con l'obiettivo finale di riprodurre in precedenza giochi solo su Flash sull'iPhone. Oltre a dimostrare differenze linguistiche e API, questa serie di tutorial terrà conto anche delle restrizioni hardware come la dimensione dello schermo e la mancanza di pulsanti fisici su iPhone.

Questo tutorial riprende da dove inizia la prima parte.

Creare la nave

Inizia facendo il porting della sintassi dal file sorgente "de / pixelate / flixelprimer / Ship.as" come descritto
nel giorno un post. In particolare, dovrai:

  • Sbarazzarsi delle dichiarazioni di pacchetto e di classe.
  • Rimuovi le dichiarazioni di tipo.
  • Aggiungi "locale" a tutte le variabili.
  • Sostituisci le parentesi condizionali con "allora" e "fine".
  • Elimina tutto il punto e virgola e commenta tutto.

Ora aggiungi la dichiarazione del modulo nella parte superiore del file in modo da poter importare il file in PlayState.
Inoltre, vai avanti e avvolgi tutto il codice con una funzione di costruzione Ship (). Il tuo codice ora dovrebbe essere organizzato in questo modo:

 module (?, package.seeall) function Ship ()? tutto il codice commentato va qui? fine

Non abbiamo flixel, quindi sbarazzarsi della dichiarazione di importazione per questo. Ora guarda le prime righe del nostro
Funzione nave ():

 function Ship () - [Embed (source = "? /? /? /? /assets/png/Ship.png")] private var ImgShip: Class - [[function Ship () -: void super (50 , 50, ImgShip) fine -]]? fine

La prima riga carica l'immagine della nave e la memorizza nella variabile ImgShip. Le prossime linee sono
il vecchio metodo di costruzione. Quando la nave è stata creata questa funzione gli ha assegnato l'immagine ImgShip e le coordinate (50, 50). Possiamo fare la stessa cosa creando una variabile Ship che contiene un'immagine. Possiamo caricare l'immagine usando il modulo display che abbiamo usato nella lezione 1. Quindi possiamo impostare le proprietà xey delle variabili su 50. Sostituire le righe precedenti per fare quanto segue:

 function Ship () locale Ship = display.newImage ("Ship.png") Ship.x = 50 Ship.y = 50? codice commentato? fine

Ora facciamo in modo che la funzione Spedisci () restituisca la Nave in modo che il nostro PlayState possa usarla.

 function Ship () locale Ship = display.newImage ("Ship.png") Ship.x = 50 Ship.y = 50? codice commentato? ritorno Fine nave

Nella nostra sorgente ActionScript, una nave viene creata in PlayState chiamando "new Ship ()". Mentre siamo a
Facciamo una nuova funzione () che restituisce Nave ().

 function Ship () locale Ship = display.newImage ("Ship.png") Ship.x = 50 Ship.y = 50? codice commentato? return Ship end function new () return Ship () end

In realtà, non c'è alcuna necessità tecnica per questo, ma rende il nostro codice un po 'più leggibile.

Tornate su PlayState.lua e richiedete il nostro modulo Ship in alto.

 module (?, package.seeall) local Ship = require ("Ship") function PlayState ()? 

Ora possiamo creare una nuova nave. Innanzitutto, sposta tutte le dichiarazioni delle variabili commentate dalla parte superiore del file alla funzione create ().

 module (?, package.seeall) local Ship = require ("Ship") function PlayState () local PlayState = ? un bel po 'di codice commentato? function create () -: void PlayState._inGame = true --local _ship --local _aliens --local _bullets --local _scoreText --local _gameOverText --local _spawnTimer --local _spawnInterval = 2.5 PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125)? ha commentato la logica create ()? fine create () fine

Lasciandoli commentati, rendili proprietà di PlayState. Impostare le proprietà senza un valore su zero. Mentre ci siamo, dobbiamo fare una dichiarazione _background.

? PlayState._background = nil --PlayState._ship = nil --PlayState._aliens = nil --PlayState._bullets = nil --PlayState._scoreText = nil --PlayState._gameOverText = nil --PlayState._spawnTimer = nil --PlayState ._spawnInterval = 2.5? 

Decommenta la dichiarazione della variabile _ship e crea una nuova nave in questo modo:

 function create () -: void - dichiarazioni variabili 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 = 2.5 - assegnazioni di variabili PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171 , 204, 125) PlayState._ship = Ship.new ()? ha commentato la logica create ()? fine

Nota qui che prima assegniamo _background. Questo perché gli oggetti di visualizzazione in Corona sono ordinati
da quando vengono creati. Non saremmo in grado di vedere _ship se lo avessimo creato prima di _background.

Se esegui il codice, ora c'è una nave visualizzata a (50, 50).

Uno sguardo alle restrizioni hardware

Dobbiamo essere in grado di spostare la nave per giocare, ma come possiamo? Il gioco originale è stato creato per essere controllato da una tastiera. Un iPhone non ha una tastiera. Come possiamo aggirare questo? Questo è uno dei molti fattori che devono essere presi in considerazione quando si crea un'app per un dispositivo mobile, indipendentemente dal fatto che si stia effettuando il porting di codice esistente o la creazione di un'app da zero. Un altro che stiamo già affrontando è la dimensione dello schermo. Su un computer, i programmi sono disponibili in diverse dimensioni. Molti di questi sono ridimensionabili. Su un iPhone, le app sono tutte della stessa dimensione.

Risolvere questi problemi può essere difficile. Per aggirare queste restrizioni è necessario pensare
fuori dalla scatola. Ad esempio, potremmo controllare la nostra nave con i pulsanti sullo schermo. Potremmo anche toccare la posizione sullo schermo in cui vogliamo spostare la nave. Potremmo persino usare il dispositivo
accelerometro per controllare la nave in base all'inclinazione del dispositivo. Forse cambiamo un po 'il gameplay e facciamo controllare la nave da sola. Quindi il giocatore sarebbe solo responsabile della sparatoria. Come puoi vedere, ci sono molte possibilità per nuovi stili di gameplay su iPhone.

Creazione di pulsanti virtuali

Per quanto fossero tante quelle idee, creeremo pulsanti sullo schermo per controllare la nave. In questo modo, il gioco sarà più in linea con l'originale. Lascio a quelle altre opzioni da esplorare.

Ansca Mobile ha creato una libreria open-source per la creazione di pulsanti virtuali. Invece di
costruendo la biblioteca in Corona, l'hanno inclusa sul loro sito web come opzionale. io ho
inclusa la versione più recente al momento della stesura del codice sorgente per questo tutorial. Aggiungi il
file "ui.lua" nella cartella del progetto.

Vai al tuo file Ship.lua in modo da poter eseguire alcune impostazioni. Aggiungiamo alcune proprietà alla nostra variabile Ship. Appena sotto il codice in cui impostiamo le coordinate della nave su (50, 50) aggiungi questo:

? nave locale = display.newImage ("Ship.png") Ship.x = 50 Ship.y = 50 Ship._up = false Ship._down = false Ship._left = false Ship._right = false? 

Li useremo per dire alla nave quando muoversi. Se i valori cambiano in vero, significa che i rispettivi pulsanti vengono premuti.

Di nuovo in PlayState.lua, dobbiamo creare una nuova funzione per gestire i pulsanti di creazione. Lo gestiremo al di fuori di PlayState () perché diventerà un po 'disordinato. Prima di andare avanti,
assicurati di avere tutte le immagini dei pulsanti della sorgente incluse in questo tutorial. Ora, crea una funzione buttonHandler () sotto PlayState ().

? funzione PlayState ()? fine funzione buttonHandler (PlayState) fine

Si noti che buttonHandler () accetta un argomento: PlayState. Questo perché stiamo creando
buttonHandler () al di fuori della funzione PlayState (). Se ricordi dalla prima lezione, questo significa
that buttonHandler () non ha idea di cosa sia la variabile PlayState, perché PlayState è locale al
Funzione PlayState (). Chiameremo buttonHandler () dall'interno di PlayState (). Passando
PlayState to buttonHandler (), stiamo permettendo a buttonHandler () di vedere e modificare tutto PlayState e le sue proprietà. Poiché _ship è una proprietà di PlayState, buttonHandler () sarà in grado di impostare
_ship_up, _ship._down, ecc.

Stiamo per importare il modulo ui.lua nella nostra funzione buttonHandler anziché nella parte superiore di
PlayState.lua. Vedrai perché dopo.

? funzione PlayState ()? end function buttonHandler (PlayState) local ui = require ("ui") end

Ora diventerà un po 'disordinato. Creeremo due funzioni per ogni pulsante. Uno
per quando viene premuto il pulsante e uno per quando viene rilasciato il pulsante. Quando vengono chiamati, impostano le proprietà della nave su true o false.

 function buttonHandler (PlayState) local ui = require ("ui") function upPressed () PlayState._ship._up = true end function upReleased () PlayState._ship._up = false end function downPressed () PlayState._ship._down = true end function downReleased () PlayState._ship._down = false end function leftPressed () PlayState._ship._left = true end function leftReleased () PlayState._ship._left = false end function rightPressato () PlayState._ship._right = true end function rightEsercitato () PlayState._ship._right = false end end

Perché stiamo passando PlayState a buttonHandler (), e _ship e tutte le proprietà appartengono a
PlayState, possiamo cambiarli da vero a falso e viceversa. Ora dobbiamo creare i pulsanti reali. Con il modulo ui importato, possiamo usare uno dei suoi metodi: newButton. Questo ha qualche sintassi interessante, quindi tieni duro.

 PlayState._upButton = ui.newButton defaultSrc = "up.png", defaultX = "50", defaultY = "50", overSrc = "up.png", overX = "50", overY = "50", onPress = upPressed, onRelease = upReleased, id = "_upButton"

Questo codice chiama newButton e assegna il risultato a _upButton (una proprietà di PlayState). All'inizio,
ti starai chiedendo perché ci sono parentesi. Questa non è un'eccezione alle regole della sintassi lua.
In realtà, le parentesi contengono una serie di parametri che vengono passati al metodo newButton. Ci sono molti parametri qui, quindi esaminiamoli uno alla volta. Il primo, defaultSrc è la posizione dell'immagine da utilizzare quando il pulsante non viene premuto. defaultX e defaultY sono le dimensioni dell'immagine. overSrc è la posizione dell'immagine da visualizzare quando si preme il pulsante. In questo caso, useremo la stessa immagine. overX e overY funzionano proprio come defaultX e defaultY, ma sono le dimensioni di overSrc. onPress è la funzione da chiamare quando viene premuto il pulsante. Questa è una delle funzioni che abbiamo creato in precedenza. onRelease è uguale a onPress, ma viene richiamato all'uscita del pulsante. id è una stringa denominata per distinguere questo pulsante dagli altri. Ogni pulsante ha una x e una y come gli altri oggetti di visualizzazione che possono essere regolati in qualsiasi momento.

Ora che sappiamo come funzionano i pulsanti, facciamo il resto. Aggiungi questo alla fine di
ButtonHandler ():

 function buttonHandler ()? PlayState._upButton = ui.newButton defaultSrc = "up.png", defaultX = "50", defaultY = "50", overSrc = "up.png", overX = "50", overY = "50", onPress = upPressed, onRelease = upReleased, id = "_upButton" PlayState._upButton.x = display.contentWidth - 100 PlayState._upButton.y = display.contentHeight - 100 PlayState._downButton = ui.newButton defaultSrc = "down.png", defaultX = "50", defaultY = "50", overSrc = "down.png", overX = "50", overY = "50", onPress = downPressed, onRelease = downReleased, id = "_downButton" PlayState._downButton. x = display.contentWidth - 100 PlayState._downButton.y = display.contentHeight - 50 PlayState._leftButton = ui.newButton defaultSrc = "left.png", defaultX = "50", defaultY = "50", overSrc = "sinistra .png ", overX =" 50 ", overY =" 50 ", onPress = leftPressed, onRelease = leftReleased, id =" _leftButton " PlayState._leftButton.x = display.contentWidth - 150 PlayState._leftButton.y = display.contentHeight - 75 PlayState._rightButton = ui.new Button defaultSrc = "right.png", defaultX = "50", defaultY = "50", overSrc = "right.png", overX = "50", overY = "50", onPress = rightPressed, onRelease = rightReleased, id = "_rightButton" PlayState._rightButton.x = display.contentWidth - 50 PlayState._rightButton.y = display.contentHeight - 75 end

Se aggiungiamo una chiamata a buttonHandler () nella funzione create () di PlayState (), ne avremo quattro
frecce posizionate in basso a destra dello schermo.

 funzione PlayState ()? funzione create ()? PlayState._ship = Ship.new () buttonHandler (PlayState)? fine

Il ciclo di gioco

Ora abbiamo bisogno di creare un loop per gestire il gameplay. Nel codice originale, è stata utilizzata la funzione update () per questo scopo. Faremo lo stesso con il nostro codice. Proprio come abbiamo fatto con la funzione create (), decommentare la funzione update () e inserire i commenti a riga singola prima di tutte le righe interne.

 function update () -: void --FlxU.overlap (_aliens, _bullets, overlapAlienBullet) --FlxU.overlap (_aliens, _ship, overlapAlienShip) --if (FlxG.keys.justPressed ("SPACE") e _ship.dead == false) then - spawnBullet (_ship.getBulletSpawnPosition ()) --end --if (FlxG.keys.ENTER e _ship.dead) quindi - FlxG.state = new PlayState (); --end --_ spawnTimer = _spawnTimer - FlxG.elapsed --if (_spawnTimer < 0) then -- spawnAlien() -- resetSpawnTimer() --end --super.update() end

Ascoltando gli eventi

Per ottenere la funzione update () chiamata ripetutamente come in flixel, è necessario aggiungere un evento
ascoltatore. Questa riga di codice imposterà update () per essere chiamata ogni nuovo frame. Aggiungilo nel create ()
funzione.

 function create () -: void? buttonHandler (PlayState) Runtime: addEventListener ("enterFrame", aggiornamento)? fine

Verifica se il gioco è finito

Controlliamo se il gioco è ancora in esecuzione prima di lasciar andare il ciclo di gioco. Ricorda questa variabile
"PlayState._inGame"? Lo useremo per verificare se il gioco è finito. Quindi circonda il codice di aggiornamento () commentato con questa affermazione.

 function update () -: void if PlayState._inGame then? codice commentato? fine fine

Movimentazione della nave

Per far muovere la nave, dobbiamo far funzionare la funzione update () di Ship.lua. Come prima, cambia i commenti in modo che la dichiarazione della funzione non sia più commentata, ma tutto il resto lo è. Aggiungi lo stesso listener di eventi subito prima della fine di Ship ().

 funzione Nave ()? Runtime: addEventListener ("enterFrame", update) return Ship end

Dobbiamo anche verificare che la variabile "Nave" esista e che non sia nulla. Avvolgi il commento
codice con questa istruzione if.

 aggiornamento della funzione () se Spedisci allora? codice commentato? fine fine

Ora, iniziamo a lavorare sulle righe commentate. I primi due impostano la velocità della nave a 0.
Corona non ha velocità come fa flixel, quindi finiremo per lavorare con le xey della nave
direttamente. Le otto linee successive controllano se i tasti freccia sinistra o destra sono premuti sulla tastiera. Noi
può sostituire questo con controlli per le variabili _left e _right. Dal momento che non abbiamo velocità per
con, imposteremo il valore x della nave su più o meno 5.

 se (Ship._left) quindi Ship.x = Ship.x - 5 elseif (Ship._right) quindi Ship.x = Ship.x + 5 end

Lo stesso vale per su e giù.

 se (Ship._up) quindi Ship.y = Ship.y - 5 elseif (Ship._down) quindi Ship.y = Ship.y + 5 end

È possibile eliminare "super.update ()"

Mantenere il gioco in un confine

Se dovessi eseguire il gioco ora, la nave si muoverà correttamente. Il problema è che volerà
direttamente dallo schermo o nei controlli se lo permettiamo. Anche il gioco originale aveva questo problema. Così,
le prossime righe di codice nella funzione update () impediscono alla nave di lasciare un confine. esso
realizza ciò controllando se la nave è fuori dal limite dopo che tutte le modifiche x e y
sono attraverso. Se la nave è all'esterno, viene rimandata al valore massimo consentito. Faremo la stessa cosa, e possiamo usare lo stesso display.contentWidth e contentHeight come con lo sfondo per trovare le dimensioni dello schermo.

 se (Ship.x> display.contentWidth-Ship.contentWidth-16), quindi Ship.x = display.contentWidth-Ship.contentWidth-16 elseif (Ship.x < Ship.contentWidth+16) then Ship.x = Ship.contentWidth+16 end if(Ship.y > display.contentHeight-Ship.contentHeight-150) quindi Ship.y = display.contentHeight-Ship.contentHeight-150 elseif (Ship.y < Ship.contentHeight+16) then Ship.y = Ship.contentHeight+16 end

Ho modificato un po 'i numeri in modo che la nave non si sovrapponesse ai pulsanti.

Elenchi puntati e gruppi di visualizzazione

Ora dobbiamo far sparare la nostra nave. Diamo un'occhiata a "de / pixelate / flixelprimer / Bullet.as". Partire
attraverso il normale processo di conversione della sintassi. Fortunatamente questo è veramente facile. Elimina tutto tranne il costruttore Bullet (). Aggiungi la dichiarazione del modulo e salvala come Bullet.lua nella cartella del tuo progetto.

Ora abbiamo una funzione Bullet () che accetta un valore X e un valore Y. Crea un rettangolo verde a quelli
coordinate, e imposta la sua velocità a 1000.

Creiamo il rettangolo che funge da proiettile nello stesso modo in cui abbiamo creato lo sfondo nel primo
lezione.

 module (?, package.seeall) function Bullet (x, y) -: void local Bullet = display.newRect (x, y, 16, 4) --super (x, y) --createGraphic (16, 4, 0xFF597137) --velocity.x = 1000 end

Questo codice crea un quadrato di 16 x 4 pixel e imposta le sue coordinate X e Y sui numeri passati a Bullet (x, y). Ora cambiamo il colore di riempimento del proiettile. # 587137 convertito in RGB è (89, 113, 55).

 module (?, package.seeall) bullet Bullet (x, y) -: void local Bullet = display.newRect (x, y, 16, 4) Bullet: setFillColor (89, 113, 55) --velocity.x = 1000 fine

Aggiungiamo una nuova funzione () per comodità come abbiamo fatto con Ship.lua.

 module (?, package.seeall) bullet Bullet (x, y) -: void local Bullet = display.newRect (x, y, 16, 4) Bullet: setFillColor (89, 113, 55) --velocity.x = 1000 return Bullet end function nuovo (x, y) return Bullet (x, y) end

Quel codice accetta solo un valore X e un valore Y e restituisce un nuovo proiettile in quella posizione. Assicurati che
aggiungi "Bullet di ritorno" alla fine di Bullet () in modo che PlayState sia in grado di usarlo.

Ora abbiamo bisogno di ricreare la velocità. Creiamo una funzione update () come abbiamo fatto per la nave.

? funzione Bullet (x, y) -: void Bullet locale = display.newRect (x, y, 16, 4) Bullet: setFillColor (89, 113, 55) update della funzione () se Bullet then Bullet.x = Bullet.x + 10 end-end Runtime: addEventListener ("enterFrame", update) restituisce Bullet end? 

Ora il proiettile si sposta di dieci pixel a destra ogni fotogramma.

Codice pulsante Refactoring: aggiunta di un pulsante di fuoco

Ora, avremo bisogno di un metodo per sparare i proiettili. Aggiungiamo un altro pulsante. Innanzitutto, abbiamo bisogno di una variabile per tenere traccia se il pulsante è premuto o meno. Invece di gestirlo nel file Ship.lua, rendi questa variabile nella funzione create () in PlayState.lua nella parte inferiore del
dichiarazioni variabili.

? function create () -: void - dichiarazioni variabili 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 = 2.5 PlayState._shoot = nil? fine? 

Vai avanti e impostalo su falso sotto la nuova linea di nave nelle assegnazioni di variabile.

? function create () -: void? - assegnazioni variabili PlayState._background = display.newRect (0, 0, display.contentWidth, display.contentHeight) PlayState._background: setFillColor (171, 204, 125) PlayState._ship = Ship.new () PlayState._shoot = false ? fine? 

Ora dobbiamo aggiungere alcune righe alla nostra funzione buttonHandler (). Abbiamo bisogno di altre due funzioni per gestire la pressione e il rilascio del nuovo pulsante. Aggiungi queste due funzioni dopo rightPressed () e
rightReleased ().

? function buttonHandler (PlayState)? function leftPressed () PlayState._ship._left = true end function leftReleased () PlayState._ship._left = false end function rightPressed () PlayState._ship._right = true end function rightReleased () PlayState._ship._right = false end function shootPremuto () PlayState._shoot = true end function shootReleased () PlayState._shoot = false end? fine? 

Ora carica il pulsante come prima.

? function buttonHandler (PlayState)? PlayState._shootButton = ui.newButton defaultSrc = "shoot.png", defaultX = "100", defaultY = "100", overSrc = "shoot.png", overX = "100", overY = "100", onRelease = shootReleased, onPress = shootPressed, id = "_shootButton" PlayState._shootButton.x = 75 PlayState._shootButton.y = display.contentHeight - 75 end? 

Il nostro codice pulsante sta diventando un po 'confuso. Spostiamo tutto buttonHandler () in un nuovo file chiamato
Buttons.lua. Non dimenticare la declinazione del modulo.

Importa il nuovo modulo Button nella parte superiore di PlayState. Mentre siamo lì, importiamo anche Bullet.

 module (?, package.seeall) local Ship = require ("Ship") Bullet locale = require ("Bullet") Pulsanti locali = require ("Buttons") function PlayState ()? 

Modificare la linea buttonHandler () in create () per chiamare la funzione del modulo.

 function create () -: void? PlayState._ship = Ship.new () PlayState._shoot = false Buttons.buttonHandler (PlayState)? fine

Immissione di proiettili relativi alla spedizione

Ora abbiamo bisogno di ricreare alcune delle funzioni di gestione dei proiettili. Diamo un'occhiata a getBulletSpawnPosition ()
in Ship.lua.

 --[[function getBulletSpawnPosition () -: FlxPoint local p = new FlxPoint (x + 36, y + 12) return p end -]]

La funzione originale era un metodo di istanza della nave. Ha restituito un valore X e un valore Y per creare un nuovo punto elenco. Dal momento che dovrebbe essere un metodo di istanza, dobbiamo farlo funzionare come tale. Facciamo in modo che la variabile Ship lo possieda.

 funzione Nave: getBulletSpawnPosition () -: FlxPoint local p = new FlxPoint (x + 36, y + 12) ritorno p end

Dato che FlxPoint è un tipo esclusivo di Flixel, restituiamo invece un array.

 function Ship: getBulletSpawnPosition () local p = x = Ship.x + 36, y = Ship.y + 2 return p end

Questo codice aggiunge 36 al valore X della nave e 2 (ho usato 2 invece di 12 per aggiustare il proiettile
posizione per Corona) al valore Y della nave. Questi sono memorizzati in un array associativo. Ora possiamo
accedere a ciascun numero con p.x e p.y.

Nel codice originale, una variabile nel PlayState chiamato _bullets conteneva tutte le istanze del proiettile.
Possiamo fare la stessa cosa con un gruppo di visualizzazione. Un gruppo di visualizzazione in Corona contiene semplicemente un gruppo di oggetti di visualizzazione e li visualizza. Questo è utile per tenere traccia di un gruppo dello stesso tipo di
oggetto. Quando gli oggetti vengono aggiunti ai gruppi di visualizzazione, vengono visualizzati nell'ordine in cui viene visualizzato
i gruppi sono creati Ad esempio, se abbiamo un mucchio di proiettili e un gruppo di alieni e vogliamo che tutti gli alieni siano in cima, potremmo creare un gruppo di visualizzazione di proiettili e quindi un gruppo di display alieno. Se aggiungiamo tutte le istanze di proiettili e alieni ai loro gruppi, verranno sempre visualizzati nell'ordine corretto. Ciò accadrà anche se, per esempio, un proiettile viene creato dopo un alieno. Lo straniero sarà in cima perché il gruppo di visualizzazione controlla l'ordine di visualizzazione.

Decommentare la riga "--PlayState._bullets = nil" nella funzione create () in PlayState.lua.

 function create () -: void - dichiarazioni variabili 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 = 2.5 PlayState._shoot = nil? fine

Rendi _bullets un nuovo gruppo di visualizzazione nei compiti delle variabili.

 function create () -: void? PlayState._ship = Ship.new () PlayState._shoot = false PlayState._bullets = display.newGroup () Buttons.buttonHandler (PlayState)? fine

Ora dai un'occhiata a spawnBullet ().

 --[[function spawnBullet (p) -: void local bullet = new Bullet (p.x, p.y) _bullets.add (bullet) FlxG.play (SoundBullet) end -]]

Questo codice è in realtà abbastanza vicino a ciò che vogliamo. Assomigli a questo:

 function spawnBullet (p) -: void local _bullet = Bullet.new (p.x, p.y) PlayState._bullets: insert (_bullet) PlayState._shoot = false --FlxG.play (SoundBullet) end

Quando viene creato il punto elenco, _shoot deve essere impostato su false. In questo modo, l'utente deve sollevare
il loro dito prima di sparare di nuovo.

Gestione dei suoni di base

Corona ha un'API di base per la riproduzione di brevi effetti sonori. Per usarlo, dobbiamo usare il suono .caf
File. La versione convertita degli effetti sonori MP3 originali è inclusa nel sorgente per questo
lezione.

Per prima cosa dobbiamo creare variabili per contenere i suoni. Ci sono tre linee nella parte superiore di PlayState.
Spostali alle dichiarazioni variabili in create ().

 function create () -: void - dichiarazioni variabili 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 = 2.5 PlayState._shoot = nil - [Incorpora (fonte = "? /? /? /? /assets/mp3/ExplosionShip.mp3")] var privata SoundExplosionShip: Class - [Embed (source = "? /? /? /? /Assets/mp3/ExplosionAlien.mp3")] private var SoundExplosionAlien: Class - [Embed (source = "? /? /? /? / assets / mp3 / Bullet.mp3 ")] private var SoundBullet: Class? fine

Vogliamo solo che i nomi siano gli stessi. Rendi le loro proprietà di PlayState e impostale su zero.
Rimuovi il commento dall'ultima riga.

 function create () -: void - dichiarazioni variabili 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 = 2.5 PlayState._shoot = nil --PlayState.SoundExplosionShip = nil --PlayState.SoundExplosionAlien: Class = nil PlayState.SoundBullet = nil? fine

Ora useremo il modulo multimediale per caricare un nuovo suono. Metti questo in fondo ai compiti:

 function create () -: void? PlayState._ship = Ship.new () PlayState._shoot = false PlayState._bullets = display.newGroup () PlayState.SoundBullet = media.newEventSound ("Bullet.caf") Buttons.buttonHandler (PlayState)? fine

Tornando a spawnBullet (). Possiamo sostituire l'ultima riga per riprodurre il nostro nuovo suono.

 function spawnBullet (p) -: void local _bullet = Bullet.new (p.x, p.y) PlayState._bullets: insert (_bullet) PlayState._shoot = false media.playEventSound (PlayState.SoundBullet) end

Ora dobbiamo solo modificare la nostra funzione update () per ottenere alcuni proiettili da tiro. Controlla se _shoot è
vero e se _ship esiste. In tal caso, chiama il nostro metodo di istanza getBulletSpawnPosition () per la nostra nave
e spawnBullet () in quella posizione.

 aggiornamento della funzione () se PlayState._inGame, quindi se PlayState._shoot == true e PlayState._ship allora locale p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) end? fine fine

Gestione della memoria di base

In Flixel, la memoria è stata curata per noi. In Corona, dovremo ripulire gli oggetti
sono finiti. Aggiungiamo un metodo di istanza kill () a ciascun punto elenco per aiutarci. kill () è il
funzione che flixel chiama automaticamente quando un oggetto non è più necessario. Aggiungi questo a Bullet.lua:

 funzione Bullet (x, y)? aggiornamento della funzione ()? end function Bullet: kill () Bullet.parent: remove (Bullet) Bullet = nil end? fine

Questo è il modo corretto per ripulire un oggetto in Corona. Innanzitutto, abbiamo rimosso tutti i legami rimuovendo
dal gruppo di visualizzazione. Quindi impostiamo la variabile Bullet su zero. Facciamo la stessa cosa per la nave.
Aggiungi questo sotto getBulletSpawnPosition () in Ship.lua:

 function Ship: kill () Ship: removeSelf () Ship = nil Runtime: removeEventListener ("enterFrame", update) fine

Si noti che abbiamo interrotto l'aggiornamento dall'essere chiamato ogni frame (poiché la nave non esiste
più).

Gestione di proiettili fuori campo

Tornando in Bullet.lua, aggiungiamo un controllo ad ogni frame per vedere se il proiettile si trova all'esterno del display.
Attualmente, il nostro codice continua a disegnare proiettili anche mentre non possono essere visti. Questo è uno spreco delle risorse limitate del dispositivo. Sostituisci update () con questo:

 funzione update () se Bullet then if (Bullet.x < display.contentWidth) then Bullet.x = Bullet.x + 10 else Bullet:kill() end end end

Ora, il proiettile si sposta solo a destra se può essere visto. Altrimenti, chiamerà il nostro utile
funzione kill ().

Raccolta dei rifiuti

Lua ha un garbage collecter automatico che gestisce il cestino come variabili inutilizzate, oggetti di visualizzazione che sono stati rimossi dal display e qualsiasi altra cosa che non è più necessaria. Possiamo dire a Lua di raccogliere rifiuti aggiungendo questa riga alla fine della creazione nel nostro PlayState:

 funzione create ()? collectgarbage ("collect") fine

Conclusione

Questo sta cominciando a sembrare un gioco ora. La nostra nave può muoversi sullo schermo e sparare proiettili. Il
i proiettili si prendono cura di se stessi quando non sono più necessari. Ora abbiamo solo bisogno di alcuni nemici.