ActionScript-Spiele mit dem Corona SDK auf iOS portieren Teil 3

In diesem Tutorial wird gezeigt, wie Sie ein Flash / Flex-Spiel auf das Corona SDK portieren. Konkret werden wir von ActionScript auf Lua portieren, mit dem Endziel, bisher nur Flash-Spiele auf dem iPhone zu spielen. Neben den Unterschieden in Bezug auf Sprache und API werden in dieser Lernprogrammreihe auch Hardwareeinschränkungen wie Bildschirmgröße und das Fehlen physischer Tasten auf dem iPhone berücksichtigt.

Feinde hinzufügen

Nun beginnen wir mit unserem Feind zu arbeiten: "de / pixelate / flixelprimer / Alien.as". Wie immer wird die Syntax zuerst konvertiert.

Wenn Sie damit fertig sind, fügen Sie die Moduldeklaration hinzu und wickeln Sie alle Funktionen in Alien () ein..

 module (?, package.seeall) - [Einbetten (Quelle = "? /? /? /? /assets/png/Alien.png")] private var ImgAlien: Klassenfunktion Alien (x, y) -: void super (x, y, ImgAlien) Velocity.x = -200 Funktionsaktualisierung () -: void Velocity.y = Math.cos (x / 50) * 50 Super.update () Ende

Das Alien wirkt unserer Kugel sehr ähnlich. Es erstellt ein Bild, legt x und y fest
koordiniert und gibt ihm eine Geschwindigkeit. Wir werden also auf dieselbe Weise vorgehen. Die oberen beiden Zeilen der Funktion können durch fast denselben Code ersetzt werden, den wir für das Aufzählungszeichen verwendet haben. Dieses Mal werden wir jedoch ein Bild verwenden.

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

Nachdem wir nun das Bild geladen und eingestellt haben, bewegen wir es nach links. Wieder werden wir etwas wie den update () - Code unseres Bullets erstellen. Lassen Sie die alten Zeilen in update () kommentiert.

 Modul (?, package.seeall) Funktion Alien (x, y) -: void? function update () -: ungültig wenn Alien dann wenn (Alien.x> 0 - Alien.contentWidth) dann Alien.x = Alien.x - 2 Ende? kommentierter Code? end Runtime: addEventListener ("enterFrame", Update) end

Nun machen wir eine kill () - Funktion und lassen Alien einen Alien zurückgeben.

 Modul (?, package.seeall) Funktion Alien (x, y) -: void? Funktions-Update () -: nichtig? end function Alien: kill () Alien.parent: remove (Alien) Alien = nil Ende Laufzeit: addEventListener ("enterFrame", Update) gibt Alien-Ende zurück

Jetzt können wir unser Alien töten, wenn x links vom Bildschirm ist. Wir können auch eine neue () - Funktion als Komfort hinzufügen.

 module (?, package.seeall) -Funktion Alien (x, y) -: void local Alien = display.newImage ("Alien.png") Alien.x = x Alien.y = y-Funktion update () -: void wenn Alien dann wenn (Alien.x> 0 - Alien.contentWidth), dann Alien.x = Alien.x - 2 else Alien: kill () Ende Ende Funktion Alien: kill () Alien.parent: remove (Alien) Alien = nil end Runtime: addEventListener ("enterFrame", update) gibt Alien-End-Funktion zurück. new (x, y) gibt Alien-Ende (x, y) zurück

Verwendung von Timern zur Kontrolle von Aliens

Den Alien zu kreieren war ziemlich einfach. Jetzt müssen wir sie über PlayState zum Spiel hinzufügen.

Importieren Sie zunächst das Modul in PlayState.lua.

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

Jetzt müssen wir einen Timer einrichten. Der ursprüngliche Code hatte eine Variable _spawnInterval, mit der _spawnTimer gesetzt wurde. Jedes Mal, wenn _spawnTimer 0 erreichte, wurde es auf den Wert von _spawnInterval zurückgesetzt. _SpawnInterval würde dann um .1 verringert, was dazu führt, dass Aliens schneller laichen.

Um zu beginnen, kommentieren Sie die Deklarationen der Eigenschaften _spawnInterval und _spawnTimer in create ()..

 Funktion create () -: void - Variablendeklarationen PlayState._inGame = true PlayState._background = nil PlayState._ship = nil --PlayState._aliens = nil PlayState._bullets = nil --PlayState._scoreText = nil --PlayState. _gameOverText = keine PlayState._spawnTimer = keine PlayState._spawnInterval = keine --PlayState.SoundExplosionShip = keine --PlayState.SoundExplosionAlien = keine PlayState.SoundBullet = keine? Ende

Setzen Sie nun in den Variablenzuweisungen _spawnTimer auf 0 und _spawnInterval auf 2,5. Fügen Sie auch einen Aufruf von resetSpawnTimer () hinzu. Wir werden diese Funktion in einer Sekunde erstellen.

 Funktion create () -: nichtig? - variable Zuweisungen 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 () end

Finden Sie jetzt die kommentierte Funktion resetSpawnTimer (). Es wird ungefähr so ​​aussehen.

 function resetSpawnTimer () -: void _spawnTimer = _spawnInterval _spawnInterval = _spawnInterval * 0,95 if (_spawnInterval.) < 0.1) then _spawnInterval = 0.1 end end

Erstaunlicherweise ist es genau das, was wir brauchen. Wir müssen nur die Variableneigenschaften von PlayState festlegen. Auf diese Weise weiß die Funktion, worüber _spawnInterval und _spawnTimer wir sprechen.

 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

Jetzt müssen wir etwas Code für update () hinzufügen. Im ursprünglichen Code erstellte das Spiel Aliens, auch wenn das Spiel beendet und das Schiff tot war. Um das Gleiche zu tun, setzen wir unseren Code für die Handhabung von Alien außerhalb des Bereichs, in dem wir prüfen, ob das Spiel beendet ist.

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

Dieser Code funktioniert genauso wie der Quellcode. Es zieht einen Zeitwert von 1 Frame von _spawnTimer ab. Dann wird geprüft, ob _spawnTimer kleiner als Null ist. Wenn dies der Fall ist, wird der Timer zurückgesetzt und ein neuer Alien erzeugt.

Eine andere Anzeigegruppe

Bevor wir Aliens laichen können, benötigen wir eine Anzeigegruppe, um sie hinzuzufügen. Kommentieren Sie wie _bullets die _aliens-Deklaration und ordnen Sie sie einer neuen Anzeigegruppe zu.

 function create () -: void - Variablendeklarationen PlayState._inGame = true PlayState._background = keine PlayState._ship = keine PlayState._aliens = keine PlayState._bullets = keine --PlayState._scoreText = keine --PlayState._gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = 2.5 --PlayState.SoundExplosionShip = nil --PlayState.SoundExplosionAlien = nil PlayState.SoundBullet = nil - variable Zuweisungen PlayState._background = display.newRect (0, 0, display.newRect) 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 ()? Ende

Finden Sie jetzt Ihre spawnAlien () - Funktion und entfernen Sie deren Kommentar. Es sollte ungefähr so ​​aussehen:

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

Dieser Code erstellt ein Alien rechts neben dem Bildschirm und in zufälliger Höhe. Dann fügt er den neuen Alien der Anzeigegruppe hinzu. Mit diesem Code können wir dasselbe tun:

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

Wiederherstellen der originalen Cosinuswelle für Aliens

Wenn wir den Code jetzt ausführen, funktioniert er fast wie das Original. Die Aliens erscheinen in zufälligen Höhen und sie erscheinen langsam häufiger. Wenn sie sich außerhalb des Bildschirms befinden, rufen sie kill () für sich selbst auf. Jetzt müssen wir sie nur noch dazu bringen, sich so zu bewegen, wie sie es im ursprünglichen Code getan haben. Im ursprünglichen Spiel folgten Außerirdische dem Pfad einer Kosinuswelle, die basierend auf ihrem x-Ort erzeugt wurde. Wir haben diesen Code in der Funktion aliens update () auskommentiert. Dieser Code hat etwas mitgespielt. Da wir nicht mit Velocity arbeiten können, ist es schwierig, den Originalcode zu verwenden. Dies ist die Zeit beim Portieren, wo Sie nur mit den Zahlen spielen müssen. Ich habe festgestellt, dass dieser Code dem Original am nächsten kam:

 function update () -: ungültig wenn Alien dann wenn (Alien.x> 0 - Alien.contentWidth), dann Alien.x = Alien.x - 2 Alien.y = Alien.y + math.cos (Alien.x / 10 ) * 2 else Alien: kill () Ende Ende Ende

Umgang mit Kollisionen

Da nun alle unsere Spielobjekte wie die Originale arbeiten, müssen wir auf Kollisionen zwischen den Kugeln und Außerirdischen und den Außerirdischen und dem Schiff prüfen. Im Originalcode wurden Kollisionen in der Funktion update () geprüft. Wenn eine Kollision auftrat, wurden die beiden Objekte an die Funktionen overlapAlienBullet () und overlapAlienShip () übergeben. Lassen Sie uns zuerst diese Funktionen erstellen. Wenn wir überlappendes AlienBullet () auskommentieren, haben wir Code, der wie folgt aussieht:

 Funktion overlapAlienBullet (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 () Ende

Dieser Code erstellt einen Partikelemitter, tötet beide Objekte, gibt einen Soundeffekt wieder und aktualisiert die Partitur. Die Neuerstellung des Flixel-Partikelsystems geht über den Rahmen dieses Tutorials hinaus, und wir müssen noch ein Punktesystem implementieren. Jetzt kommentieren wir diese Zeilen einfach und töten die Objekte.

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

Machen Sie dasselbe für overlapAlienShip ():

 Funktion overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () --FlxG.play (SoundExplosionShip) --_ gameOverText = neuer FlxText (0, FlxG.height / 2, FlxG.width, "GAME OVER \ nPRESS ENTER, WIEDER SPIELEN ") --_ gameOverText.setFormat (null, 16, 0xFF597137," center ") --add (_gameOverText) end

Lassen Sie uns nun den Soundeffekt für diese Funktionen erstellen. Kommentieren Sie die Deklarationen der Soundvariablen in create ()..

 function create () -: void - Variablendeklarationen PlayState._inGame = true PlayState._background = keine PlayState._ship = keine PlayState._aliens = keine PlayState._bullets = keine --PlayState._scoreText = keine --PlayState._gameOverText = nil PlayState._spawnTimer = nil PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = nil PlayState.SoundExplosionAlien = null PlayState.SoundBullet = nil? Ende

Weisen Sie sie jetzt ihren Sounds zu:

 Funktion create () -: nichtig? - variable Zuweisungen 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.ound") media.newEventSound ("ExplosionAlien.caf") PlayState._spawnTimer = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer () Ende

Das Abspielen der Sounds ist so einfach wie eine Zeile pro Funktion ()..

 Funktion overlapAlienBullet (alien, bullet) -: void alien: kill () bullet: kill () media.playEventSound (PlayState.SoundExplosionAlien) --FlxG.score = FlxG.score + 1 --_ scoreText.text = FlxG.score. toString () Endefunktion overlapAlienShip (Alien, Schiff) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) --_ gameOverText = neuer FlxText (0, FlxG.height / 2, FlxG. width, "GAME OVER \ nPRESS ENTER, WIEDER SPIELEN") --_ gameOverText.setFormat (null, 16, 0xFF597137, "center") --add (_gameOverText) end

Rollen Sie unseren eigenen Kollisionscode

Jetzt, da wir unsere Überlappungsfunktionen eingerichtet haben, müssen wir jeden Frame auf Kollisionen prüfen. In Corona haben wir keine einfache Möglichkeit, auf überlappende Anzeigeobjekte zu prüfen. Wir müssen die Prüfungen manuell durchführen. Dies ist ein ziemlich einfaches Konzept, wird jedoch bei der Implementierung ziemlich chaotisch. Lassen Sie uns eine Sekunde darüber nachdenken. Was zeichnet eine Überlappung aus? Ihr erster Instinkt kann sein, zu prüfen, ob sich ein Objekt in einem anderen Objekt befindet. Dies würde funktionieren, aber in diesem Fall kann eine Überlappung nur Teile der Objekte sein. Ein Objekt muss sich nicht vollständig in einem anderen Objekt befinden, um sich zu überlappen. Wie sieht das im Code aus? Alles, was wir tun müssen, ist zu prüfen, ob der maximale x-Wert eines Objekts größer als das Minimum x ist
Wert des anderen Objekts. Dann prüfen wir, ob der minimale x-Wert desselben Objekts unter dem maximalen x-Wert der anderen Objekte liegt. Dies wird für jede Überlappung true zurückgeben. Als nächstes führen wir die gleichen Überprüfungen der y-Werte der Objekte durch. Wenn wir alle Objekte in den zuvor erstellten Anzeigegruppen durchlaufen, sollten wir ein funktionierendes Kollisionssystem haben.

Versuchen wir es mit den Kugeln und Außerirdischen. Wir müssen diese Prüfungen nur im Spiel durchführen. Fügen Sie diesen Code in den richtigen Teil der Funktion update () ein:

 Funktions-Update () -: nichtig? wenn PlayState._inGame dann, wenn PlayState._shoot == true und PlayState._ship ist, dann local p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) endet, wenn PlayState._bullets.numChildren> 0 und PlayState._aliens.numChildren> 0 sind b = 1, PlayState._bullets.numChildren tun local bulletXMax = PlayState._bullets [b] .contentBounds.xMax local bulletXMin = PlayState._bullets [b] .contentBounds.xMin local bulletYMax = PlayState._bullets bulletYMin = PlayState._bullets [b] .contentBounds.yMin für a = 1, PlayState._aliens.numChildren tun if (PlayState._aliens [a] .contentBounds.xMin.) <= bulletXMax) then if (PlayState._aliens[a].contentBounds.xMax >= bulletXMin) dann if (PlayState._aliens [a] .contentBounds.yMin <= bulletYMax) then if (PlayState._aliens[a].contentBounds.yMax >= bulletYMin), dann ÜberlappenAlienBullet (PlayState._aliens [a], PlayState._bullets [b]) Ende Ende Ende Ende Ende Ende Ende

Wie ich schon sagte, sieht dieser Code etwas unordentlich aus, aber er funktioniert. Also, was macht das? Zunächst wird geprüft, ob überhaupt eine Kugel oder ein Alien existiert. Dieser Code kann sehr speicherintensiv werden, daher müssen wir alles überprüfen. Wir wollen keine Zeit verschwenden, wenn wir nicht beide Arten von Objekten haben. Sobald der Code durchgelaufen ist, starten wir eine for-Schleife. Diese Schleife setzt eine Variable ("b" mit dem Namen "Aufzählungszeichen") auf 1 und führt den Rest des Codes für jedes Aufzählungszeichen in _bullets aus. Die nächsten vier Codezeilen erstellen eine lokale Kopie der minimalen und maximalen Werte des Aufzählungszeichens. Wie ich schon sagte, müssen wir hier das Gedächtnis speichern. Wir müssen die x- und y-Werte der Aufzählungszeichen nicht immer wieder berechnen, wenn sie sich nicht ändern. Die nächste Zeile beginnt noch eine for-Schleife. Dies wiederholt sich für alle Ausländer in _aliens. Der Code in der zweiten for-Schleife führt nur die Überprüfungen durch, über die wir zuvor gesprochen haben. Ist der maximale x-Wert der Kugel größer als der minim-x-Wert des Aliens? Ich kann das Gedächtnis hier nicht genug betonen
Deshalb prüfen wir jede Bedingung in einer separaten if-Anweisung. Wenn einer dieser Tests fehlschlägt, können wir einfach die Schleife verlassen. Es muss nicht weiter geprüft werden, ob keine Kollision vorliegt. Wenn alle diese Prüfungen bestanden werden, rufen wir schließlich unsere überlappende Funktion AlienBullet () mit dem kollidierenden Geschoss und dem Alien auf.

Wütend. Das war viel Code. Jetzt müssen wir nur noch das gleiche für das Schiff tun.

 Funktions-Update () -: nichtig? wenn PlayState._inGame dann, wenn PlayState._shoot == true und PlayState._ship, dann local p = PlayState._ship: getBulletSpawnPosition () spawnBullet (p) ende? Wenn PlayState._aliens.numChildren> 0 ist, dann local shipXMax = PlayState._ship.contentBounds.xMax local shipXMin = PlayState._ship.contentBounds.xMin local shipYMax = PlayState._ship.contentBounds.yMax localYMin = PlayState._ship.continachinach.in. a = 1, PlayState._aliens.numKinder machen if (PlayState._aliens [a] .contentBounds.xMin <= shipXMax) then if (PlayState._aliens[a].contentBounds.xMax >= shipXMin) dann if (PlayState._aliens [a] .contentBounds.yMin <= shipYMax) then if (PlayState._aliens[a].contentBounds.yMax >= shipYMin), dann overlapAlienShip (PlayState._aliens [a], PlayState._ship) Ende Ende Ende Ende Ende Ende Ende

Dieser Code ist identisch mit dem Bullet- und Alien-Code. Der einzige Unterschied ist, dass wir nur ein Schiff haben. Wir wissen, dass es ein Schiff gibt, andernfalls wäre PlayState._inGame falsch. Wir müssen nicht durch eine Anzeigegruppe von Schiffen gehen, da wir nur eines haben.

Bevor wir diesen Code testen können, müssen wir das Spiel mit OverlapAlienShip () beenden. Ändern Sie _inGame in false.

 Funktion overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false --_ gameOverText = neuer FlxText (0, FlxG.height / 2, FlxG .width, "GAME OVER \ nPRESS ENTER, WIEDER SPIELEN") --_ gameOverText.setFormat (null, 16, 0xFF597137, "center") --add (_gameOverText) end

Das Ausführen des Codes zeigt nun, dass sich unsere harte Arbeit gelohnt hat. Wir haben jetzt einen voll funktionsfähigen Port des Originalspiels. Wir müssen das Punktesystem immer noch neu erstellen, und wir müssen das Spiel neu starten können, aber die harte Portierung ist abgeschlossen.

Ein Score-System implementieren

Beginnen wir mit dem Punktesystem. Dies ist so einfach wie das Erstellen eines Textetiketts und das Aktualisieren, wenn sich die Bewertung ändert. Kommentieren Sie die _scoreText-Zeile und fügen Sie eine neue _score -Eigenschaft in die create () - Deklarationen ein.

 Funktion create () -: void - Variablendeklarationen PlayState._inGame = true PlayState._background = keine PlayState._ship = keine PlayState._aliens = keine PlayState._bullets = keine PlayState._score = keine PlayState._scoreText = keine PlayState._scoreText = nil ._gameOverText = keine PlayState._spawnTimer = keine PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = keine PlayState.SoundExplosionAlien = keine PlayState.SoundBullet = keine? Ende

Jetzt müssen wir ihnen einige Werte zuweisen. _score kann einfach auf 0 gesetzt werden. _scoreText muss ein neues Textobjekt zugewiesen werden, das sich oben links auf dem Bildschirm befindet.

 Funktion create () -: nichtig? - variable Zuweisungen 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") = 0 PlayState._spawnInterval = 2.5 resetSpawnTimer () Ende

Die neueText-API ist einfach: display.newText ("anzuzeigender Text", X-Position, Y-Position, Schriftart, Größe). "PlayState._scoreText: setTextColor (89, 113, 55)" setzt die Füllfarbe auf die gleiche grüne Farbe wie die Aufzählungszeichen. Jetzt müssen wir nur noch das Ergebnis in overlapAlienBullet () aktualisieren:

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

Dadurch wird der _score -Eigenschaft einfach 1 hinzugefügt, wenn ein Alien von einer Kugel getötet wird. Dann wird die Texteigenschaft von _scoreText in den Wert der Bewertung geändert.

Spiel ist aus

Bevor wir dieses Spiel beenden, müssen wir es zurücksetzen. Auf diese Weise kann der Benutzer von vorne beginnen, wenn er stirbt. Wir müssen dies in zwei Schritten tun. Erstens müssen wir alles stoppen, was der Benutzer steuern kann, sobald das Schiff stirbt. Dann müssen wir alles andere zurücksetzen, wenn der Benutzer ein neues Spiel startet.

Deaktivieren Sie alle Schaltflächen in der Funktion overlapAlienShip (). Lassen Sie uns auch das Schiffseigentum entfernen. Wir können dies tun, indem wir alle Werte auf null setzen.

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = keine PlayState._upButton.onPress = keine PlayState._upButton. onRack = Keine PlayState._downButton.onPress = Keine PlayState._downButton.onRelease = Keine PlayState._leftButton.onPress = Keine PlayState._leftButton.onRelease = Keine PlayState._rightButton.onPress = nil = nil PlayState._shootButton.onRelease = nil --_ gameOverText = neuer FlxText (0, FlxG.height / 2, FlxG.width, "SPIEL ÜBER \ nPRESSEN, WIEDER SPIELEN") --_ gameOverText.setFormat (null, 16, 0xFF597137 , "center") --add (_gameOverText) Ende

Dieser Code weist lediglich alle onPress- und onRelease-Werte nil zu. Die Tasten werden weiterhin angezeigt
Anzeige, sie rufen jedoch keinen Code an, wenn sie gedrückt werden.

Spiel über Nachricht

Wir sehen jetzt, dass die ursprüngliche überlappende AlienShip () - Funktion eine Textbezeichnung enthielt, um dem Benutzer mitzuteilen, dass das Spiel beendet war. Wir werden das Gleiche tun. Kommentieren Sie zunächst unsere _gameOverText -Eigenschaft in der Funktion create ().

 function create () -: void - Variablendeklarationen PlayState._inGame = true PlayState._background = keine PlayState._ship = keine PlayState._aliens = keine PlayState._bullets = keine PlayState._score = keine PlayState._scoreText = keine PlayState._scoreText = keine = keine PlayState._spawnTimer = keine PlayState._spawnInterval = 2.5 PlayState.SoundExplosionShip = keine PlayState.SoundExplosionAlien = keine PlayState.SoundBullet = keine? Ende

Zurück in OverlapAlienShip () müssen wir den kommentierten Code durch diese Zeilen ersetzen.

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = keine PlayState._upButton.onPress = keine PlayState._upButton. onRack = Keine PlayState._downButton.onPress = Keine PlayState._downButton.onRelease = Keine PlayState._leftButton.onPress = Keine PlayState._leftButton.onRelease = Keine PlayState._rightButton.onPress = nil = nil PlayState._shootButton.onRelease = nil PlayState._gameOverText = display.newText ("SPIEL ÜBER TAP, WIEDER ZU SPIELEN", 35, display.contentHeight / 2 - 50, noil, 16) PlayState._gameOverText: setTextColor, 55) ende

Dies ist derselbe Code, mit dem wir den Score-Text erstellt und gefüllt haben. Die Position wird geändert, um den Text auf dem Bildschirm zu zentrieren, und der Text sagt "TAP TO WIEDERT WIEDER" statt "DRÜCKEN SIE ENTER, WIEDER SPIELEN".

Einen Tap-Listener hinzufügen

Da wir das Spiel neu starten müssen, müssen wir einen neuen Ereignis-Listener hinzufügen. Wir können dies auf dieselbe Weise tun, wie wir den enterFrame-Listener hinzugefügt haben, aber dieses Mal ist das Ereignis, auf das wir hören, "tippen". Außerdem müssen wir eine Funktion hinzufügen, die der Listener aufrufen kann. Fügen Sie am unteren Rand von overlapAlienShip () diesen Ereignis-Listener hinzu:

 function overlapAlienShip (alien, ship) -: void ship: kill () alien: kill () media.playEventSound (PlayState.SoundExplosionShip) PlayState._inGame = false PlayState._ship = keine PlayState._upButton.onPress = keine PlayState._upButton. onRack = Keine PlayState._downButton.onPress = Keine PlayState._downButton.onRelease = Keine PlayState._leftButton.onPress = Keine PlayState._leftButton.onRelease = Keine PlayState._rightButton.onPress = nil = nil PlayState._shootButton.onRelease = nil PlayState._gameOverText = display.newText ("SPIEL ÜBER TAP, WIEDER ZU SPIELEN", 35, display.contentHeight / 2 - 50, noil, 16) PlayState._gameOverText: setTextColor, 55) Runtime: addEventListener ("tap", tap) Ende

Dieser Code prüft, ob an einer beliebigen Stelle auf dem Bildschirm ein Tippen erfolgt. Wenn ein "Tippen" auftritt, wird die Funktion tap () aufgerufen. Lassen Sie uns eine leere tap () - Funktion für den Aufruf erstellen. Lege es einfach über create ().

? function tap (event) - wir brauchen dies nur als Platzhalter für die end-Funktion create ()? Ende

Alles aufräumen

Lassen Sie uns eine remove () - Funktion erstellen, um alle Objekte des Spiels zu bereinigen. Stellen Sie diese Funktion über unsere neue tap () - Funktion.

? Funktion remove () - Funktion beenden (Ereignis) - wir brauchen dies nur als Platzhalter für die Funktion end () (). Ende

Anzeigeobjekte und -gruppen entfernen

Zunächst sollten wir alle verbleibenden Aliens und Kugeln töten. Dazu können wir einfach die jeweiligen Anzeigegruppen durchlaufen. Dies ist der richtige Weg, um Objekte in Corona zu entfernen:

 Funktion remove () für i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () Ende für i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () end PlayState._bullets: removeSelf () PlayState._bullets = nil PlayState._aliens: removeSelf () PlayState._aliens = null Ende

Diese Schleifen arbeiten auf besondere Weise. Jede Schleife beginnt mit "i" auf das letzte Objekt in den Anzeigegruppen. Dann tötet die Schleife das Objekt und subtrahiert 1 von "i". Die Schleife wird wiederholt, bis "i" gleich 1 ist. Der Grund, warum wir von "i" subtrahieren, ist, dass wir jedes Mal, wenn wir ein Objekt töten, sich selbst aus der Anzeigegruppe entfernen. Dies bedeutet, dass sich in der Anzeigegruppe ein Objekt weniger befindet. Wenn wir "1" hinzufügen, würden wir am Ende kill () für Objekte aufrufen, die nicht mehr existieren. Um dies zu beheben, zählen wir jedes Mal rückwärts, wenn wir ein Objekt entfernen.

Nachdem alle Objekte aus den Gruppen entfernt wurden, entfernen wir die Gruppen. Wir haben auch die Eigenschaften festgelegt, die die Gruppen auf Null gesetzt haben. Jetzt können sie wieder verwendet werden.

Keine Variablen für den Garbage Collector

Setzen wir alle verwendeten Variablen auf Null. Auf diese Weise kann der Garbage Collector den Speicher freigeben. Dadurch wird auch sichergestellt, dass alle Variablen zurückgesetzt werden, bevor wir ein neues Spiel starten. Entfernen Sie zuerst alle Knöpfe:

 Funktion remove () für i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () Ende für i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () Ende PlayState._bullets: removeSelf () PlayState._bullets = nil PlayState._aliens: removeSelf () PlayState._aliens = nil PlayState._upButton: removeSelf () PlayState._upButton = nil PlayState._downButton: removeSelf () = nil PlayState._leftButton: removeSelf () PlayState._leftButton = nil PlayState._rightButton: removeSelf () PlayState._rightButton = nil PlayState._shootButton: removeSelf () PlayState._shootButton = nil end

Wir müssen sie zuerst vom Display entfernen und dann auf Null setzen. Kümmern wir uns jetzt um unsere Sounds.

 Funktion remove () für i = PlayState._bullets.numChildren, 1, -1 do PlayState._bullets [i]: kill () Ende für i = PlayState._aliens.numChildren, 1, -1 do PlayState._aliens [i]: kill () Ende PlayState._bullets: removeSelf () PlayState._bullets = nil PlayState._aliens: removeSelf () PlayState._aliens = nil PlayState._upButton: removeSelf () PlayState._upButton = nil PlayState._downButton: removeSelf () = nil PlayState._leftButton: removeSelf () PlayState._leftButton = keine PlayState._rightButton: removeSelf () PlayState.OrightButton = keine PlayState._shootButton: removeSelf () PlayState._shootButton = nil SoundBullet = null Ende

Nun unsere Textobjekte:

 Funktion entfernen ()? PlayState._scoreText: removeSelf () PlayState._scoreText = nil PlayState._gameOverText: removeSelf () PlayState._gameOverText = nil end

Ereignis-Listener entfernen

Um das Aufräumen abzuschließen, müssen wir unsere Event-Listener entfernen. Danach können wir PlayState endlich auf ein leeres Array zurücksetzen:

 Funktion entfernen ()? Laufzeit: removeEventListener ("enterFrame", Update) Laufzeit: removeEventListener ("tippen", tippen Sie auf) PlayState = nil PlayState =  end

Spiel neu starten

Ein Neustart des Spiels ist so einfach wie das Aufrufen von remove () und dann das Erstellen () in unserer tap () - Funktion.

 Funktion tap (Ereignis) remove () create () Ende

Letzte Tweaks

Wir sind fast fertig. Wir müssen nur noch ein paar Details hinzufügen. Beginnen Sie, indem Sie alle kommentierten Zeilen aus dem alten Quellcode entfernen. Dadurch werden unsere Dateien eine Tonne sauberer.

Aktivieren von Multitouch

Eine weitere schnelle Änderung, die wir vornehmen können, ist das Aktivieren von Multitouch. Sie werden die Änderung am Simulator nicht bemerken, aber es ist schön, wenn Sie auf dem tatsächlichen Gerät mehrere Tasten gleichzeitig drücken können. Dies ist eine einzeilige Anpassung. Wir brauchen es nur einmal, also fügen wir es der Datei main.lua hinzu.

 local PlayState = required ("PlayState") - Funktion Main () system.activate ("multitouch") display.setStatusBar (display.HiddenStatusBar) PlayState.PlayState () Ende Main ()

Ändern der UI-Bibliothek an unsere Bedürfnisse

Ich hatte auch Probleme mit dem ui.lua-Modul. Die Tasten zählen nicht, indem Sie Ihren Finger vom Gerät abziehen, es sei denn, der letzte berührte Bereich war die Taste. Dies funktioniert für dieses Spiel nicht immer richtig und manchmal scheint sich das Schiff von alleine zu bewegen, da die Release-Funktion nicht aufgerufen wird. Dies war eine einfache Lösung. Ich habe die Prüfung entfernt, um zu sehen, ob die Taste gedrückt wurde, als der Finger des Benutzers losgelassen wurde. Dies bedeutete lediglich, die if- und end-Anweisungen in den Zeilen 91 und 98 zu kommentieren.

? Wenn "beendet" == Phase dann - Betrachten Sie dies als "Klick", wenn der Benutzer den Button innerhalb der stageBounds der Schaltfläche anhebt - wenn isWithinBounds, dann wenn onEvent dann buttonEvent.phase = "release" result = onEvent (buttonEvent) elseif onRelease dann result = onRelease (event) end - end end? 

Diese Änderungen sind in der in diesem Tutorial enthaltenen Datei ui.lua enthalten.

Fazit

Wir sind fertig. Wir haben jetzt eine voll funktionsfähige Nachbildung des ursprünglichen Flash-Spiels. Wir haben ein Schiff, das sich bewegt und schießt, Außerirdische und ein Punktesystem. Das Spiel verwaltet den Speicher aller Objekte