Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. SpriteKit
Code

Erschaffen der Weltraum-Eindringlinge mit Swift und Sprite Kit: Vollendung des Spiels

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Create Space Invaders with Swift and Sprite Kit.
Create Space Invaders with Swift and Sprite Kit: Implementing Gameplay

German (Deutsch) translation by Katharina Nevolina (you can also view the original English article)

Final product image
What You'll Be Creating

Im vorherigen Teil dieser Serie haben wir die Eindringlinge in Bewegung versetzt, den Spieler und die Eindringlinge mit Geschossen beschossen und eine Kollisionserkennung durchgeführt.  Im vierten und letzten Teil dieser Serie werden wir die Fähigkeit hinzufügen, den Spieler mit dem Beschleunigungsmesser zu bewegen, die Level zu verwalten und sicherzustellen, dass der Spieler stirbt, wenn er von einer Kugel getroffen wird.  Lassen Sie uns anfangen.

1. Vollendung der Player-Klasse

Schritt 1: Hinzufügen von Eigenschaften

Fügen Sie der Player-Klasse unterhalb der canFire-Eigenschaft die folgenden Eigenschaften hinzu.

Die invincible-Eigenschaft wird verwendet, um den Spieler vorübergehend unbesiegbar zu machen, wenn er ein Leben verliert.  Die lives-Eigenschaft ist die Anzahl der Leben, die der Spieler hat, bevor er getötet wird.

Wir verwenden die lives-Eigenschaft in der lives-Eigenschaft, die jedes Mal aufgerufen wird, wenn ihr Wert festgelegt wird.  Der didSet-Beobachter wird unmittelbar nach dem Setzen des neuen Wertes der Eigenschaft aufgerufen.  Auf diese Weise wird jedes Mal, wenn wir die lives-Eigenschaft dekrementieren, automatisch überprüft, ob lives kleiner als Null ist, und die kill-Methode aufgerufen, wenn dies der Fall ist.  Wenn der Spieler noch Leben hat, wird die respawn-Methode aufgerufen.  Property Beobachter sind sehr praktisch und können eine Menge zusätzlichen Code speichern.

Schritt 2: respawn

Die respawn-Methode macht den Spieler für kurze Zeit unbesiegbar und blendet den Spieler ein und aus, um anzuzeigen, dass er vorübergehend unbesiegbar ist.  Die Implementierung der respawn-Methode sieht folgendermaßen aus:

Wir setzen invincible auf true und erstellen eine Reihe von SKAction-Objekten.  Jetzt sollten Sie mit der Funktionsweise der SKAction-Klasse vertraut sein.

Schritt 3: die

Die die-Methode ist ziemlich einfach.  Es überprüft, ob invicible ist false und, wenn es ist, dekrementiert die lives Variable.

Schritt 4: kill

Die kill-Methode setzt invaderNum auf 1 zurück und bringt den Benutzer zurück zum StartGameScene, um ein neues Spiel zu beginnen.

Dieser Code sollte Ihnen vertraut sein, da er fast identisch mit dem Code ist, den wir verwendet haben, um vom StartGameScene zum GameScene zu gelangen.  Beachten Sie, dass wir die scene auspacken müssen, um auf die size- und scaleMode-Eigenschaften der Szene zuzugreifen.

Das schließt die Player-Klasse ab.  Wir müssen nun die Methoden die und kill in der Methode didBeginContact(_:) aufrufen.

Wir können jetzt alles testen.  Eine schnelle Methode zum Testen der die-Methode besteht darin, den moveInvaders-Aufruf in der update(_:)-Methode auszukommentieren.  Nachdem der Spieler drei Mal gestorben und neu geparkt hat, solltest du zurück zum StartGameScene gebracht werden.

Stellen Sie zum Testen der kill-Methode sicher, dass der Aufruf von moveInvaders nicht auskommentiert ist.  Setzen Sie die Eigenschaft invaderSpeed auf einen hohen Wert, z. B. 200.  Die Angreifer sollten den Player sehr schnell erreichen, was zu einem sofortigen Abbruch führt.  Ändern Sie nach dem Testen die Geschwindigkeit von inaderSpeed zurück auf 2.

2. Vollendung der Erschießung von Eindringlingen

Während das Spiel gerade steht, kann nur die untere Reihe der Eindringlinge Kugeln abfeuern.  Wir haben bereits die Kollisionserkennung für den Fall, dass eine Spielerkugel einen Eindringling trifft.  In diesem Schritt entfernen wir einen Eindringling, der von einer Kugel getroffen wird, und fügen den Eindringling eine Reihe hoch zu der Gruppe von Eindringlingen, die feuern können.  Fügen Sie der Methode didBeginContact(_:) Folgendes hinzu.

Wir haben die NSLog-Anweisung entfernt und zuerst überprüft, ob contact.bodyA.node?.parent und contact.bodyB.node?.parent nicht nil sind.  Sie werden nil sein, wenn wir diesen Kontakt bereits bearbeitet haben.  In diesem Fall kehren wir von der Funktion zurück.

Wir berechnen die invadersPerRow wie zuvor und setzen theInvader auf firstBody.node?, um ihn in einen Invader zu verwandeln.  Als nächstes erhalten wir den newInvaderRow durch Subtraktion von 1 und die newInvaderColumn, die gleich bleibt.

Wir wollen Eindringlinge nur feuern lassen, wenn newInvaderRow größer oder gleich 1 ist. Andernfalls würden wir versuchen, einen Eindringling in Zeile 0 zu setzen, um feuern zu können.  Es gibt keine Zeile 0, das würde zu einem Fehler führen.

Als nächstes zählen wir durch die Eindringlinge und suchen nach dem Eindringling, der die richtige Zeile und Spalte hat.  Sobald es gefunden ist, hängen wir es an das Array invadersWhoCanFire an und rufen stop.memory auf true auf, damit die Enumeration vorzeitig stoppt.

Wir müssen den Eindringlinge finden, der im Array InvadersWhoCanFire mit einer Kugel getroffen wurde, damit wir ihn entfernen können.  Normalerweise haben Arrays eine Art von Funktionalität wie eine indexOf-Methode oder etwas Ähnliches, um das zu erreichen.  Zum Zeitpunkt des Schreibens gibt es keine solche Methode für Arrays in der Swift-Sprache.  Die Swift-Standardbibliothek definiert eine find-Funktion, die wir verwenden könnten, aber ich habe eine Methode in den Abschnitten zu Generika im Swift-Programmiersprachen-Handbuch gefunden, die das erreichen, was wir brauchen.  Die Funktion hat den passenden Namen findIndex.  Fügen Sie am Ende von GameScene.swift Folgendes hinzu.

Wenn Sie neugierig sind, wie diese Funktion funktioniert, dann empfehle ich Ihnen, mehr über Generika im Swift Programming Language Guide zu lesen.

Nun, da wir eine Methode haben, mit der wir den Eindringling finden können, rufen wir ihn auf und übergeben das invadersWhoCanFire-Array und theInvader.  Wir prüfen, ob invaderIndex nicht gleich nil ist und entfernen den Eindringlinge aus dem Array invadersWhoCanFire mit der Methode removeAtIndex (index: Int).

Sie können jetzt testen, ob es so funktioniert, wie es sollte.  Ein einfacher Weg wäre, den Aufruf von player.die in der Methode didBeginContact(_:) zu kommentieren.  Stellen Sie sicher, dass Sie den Kommentar entfernen, wenn Sie mit dem Testen fertig sind.  Beachten Sie, dass das Programm abstürzt, wenn Sie alle Eindringlinge töten.  Wir werden das im nächsten Schritt beheben.

Die Anwendung stürzt ab, weil wir einen SKAction repeatActionForever(_:) haben, der Angreifer dazu aufruft, Kugeln zu feuern.  Zu diesem Zeitpunkt gibt es keine Eindringlinge mehr, die Kugeln abfeuern könnten, so dass die Spiele abstürzen.  Wir können das beheben, indem wir die isEmpty-Eigenschaft im Array invadersWhoCanFire überprüfen.  Wenn das Array leer ist, ist das Level beendet.  Geben Sie in der Methode fireInvaderBullet Folgendes ein.

Die Stufe ist komplett, was bedeutet, dass wir invaderNum erhöhen, was für die Stufe verwendet wird.  Wir rufen auch levelComplete auf, das wir noch in den kommenden Schritten erstellen müssen.

3. Eine Stufe abschließen

Wir brauchen eine bestimmte Anzahl von Ebenen.  Wenn wir das nicht tun, werden wir nach mehreren Runden so viele Eindringlinge haben, dass sie nicht auf den Bildschirm passen.  Fügen Sie der GameScene-Klasse eine Eigenschaft maxLevels hinzu.

Fügen Sie nun die levelComplete-Methode am unteren Rand von GameScene.swift hinzu.

Wir überprüfen zunächst, ob invaderNum kleiner oder gleich den von uns festgelegten maxLevels ist.  Wenn dies der Fall ist, gehen wir zu LevelCompletScene über, andernfalls setzen wir invaderNum auf 1 zurück und rufen newGame auf.  LevelCompleteScene existiert noch nicht, und die newGame-Methode lässt sich in den nächsten zwei Schritten nicht einzeln angehen.

4. Implementieren der LevelCompleteScene-Klasse

Erstellen Sie eine neue Cocoa Touch-Klasse namens LevelCompleteScene, die eine Unterklasse von SKScene ist.  Die Implementierung der Klasse sieht folgendermaßen aus:

Die Implementierung ist identisch mit der StartGameScreen-Klasse, außer dass wir die name-Eigenschaft von startGameButton auf "nextlevel" setzen.  Dieser Code sollte Ihnen vertraut sein.  Wenn nicht, dann kehren Sie zum ersten Teil dieses Tutorials für eine Auffrischung zurück.

5. newGame

Die Methode newGame wechselt einfach zurück zum StartGameScene.  Fügen Sie am Ende von GameScene.swift Folgendes hinzu.

Wenn Sie die Anwendung testen, können Sie ein paar Stufen spielen oder ein paar Spiele verlieren, aber der Spieler hat keine Möglichkeit sich zu bewegen und das macht ein langweiliges Spiel.  Lassen Sie uns das im nächsten Schritt beheben.

6. Verschieben des Spielers mit dem Beschleunigungssensor

Wir werden den Beschleunigungsmesser benutzen, um den Spieler zu bewegen.  Zuerst müssen wir das CoreMotion-Framework importieren.  Fügen Sie eine Importanweisung für das Framework oben in GameScene.swift hinzu.

Wir brauchen auch ein paar neue Eigenschaften.

Als nächstes fügen Sie am unteren Rand von GameScene.swift eine Methode setupAccelerometer hinzu.

Hier setzen wir den accelerometerUpdateInterval, das ist das Intervall in Sekunden für die Bereitstellung von Updates für den Handler.  Ich fand 0.2 funktioniert gut, Sie können verschiedene Werte ausprobieren, wenn Sie es wünschen.  Innerhalb des Handlers; ein Abschluss, erhalten wir die accelerometerData.acceleration, die eine Struktur vom Typ CMAcceleration ist.

Wir sind nur an der x-Eigenschaft interessiert und verwenden die numerische Typkonvertierung, um sie für unsere accelerationX-Eigenschaft in einen CGFloat umzuwandeln.

Jetzt, da wir die accelerationX-Eigenschaft festgelegt haben, können wir den Player verschieben.  Das machen wir in der Methode didSimulatePhysics.  Fügen Sie am Ende von GameScene.swift Folgendes hinzu.

Rufen Sie setupAccelerometer in didMoveToView(_:) auf und Sie sollten den Player mit dem Beschleunigungssensor bewegen können.  Es gibt nur ein Problem.  Der Spieler kann sich außerhalb des Bildschirms zu beiden Seiten bewegen und es dauert ein paar Sekunden, um ihn zurück zu bekommen.  Wir können das beheben, indem wir die Physik-Engine und Kollisionen verwenden.  Wir machen das im nächsten Schritt.

7. Beschränken der Bewegung des Spielers 

Wie im vorherigen Schritt erwähnt, kann sich der Spieler außerhalb des Bildschirms bewegen.  Das ist ein einfacher Fehler, der die Physik-Engine von Sprite Kit verwendet.  Fügen Sie zuerst eine neue CollisionCategory namens EdgeBody hinzu.

Setzen Sie das als collisionBitMask des Spielers in seiner init-Methode.

Zuletzt erstellen wir einen PhysikBody in der Szene selbst.  Fügen Sie der Methode didMoveToView(view:SKView) in GameScene.swift Folgendes hinzu:

Wir initialisieren einen Physikkörper, indem wir init(edgeLoopFromRect:) aufrufen und frame der Szene übergeben.  Der Initialisierer erzeugt eine Kantenschleife aus dem Rahmen der Szene.  Es ist wichtig zu beachten, dass eine Kante kein Volumen oder Masse hat und immer so behandelt wird, als wäre die dynamische Eigenschaft gleich false.  Kanten können auch nur mit volumenbasierten Physikkörpern kollidieren, die unser Player ist.

Wir setzen die categoryBitMask auch auf CollisionCategories.EdgeBody.  Wenn Sie die Anwendung testen, stellen Sie möglicherweise fest, dass sich Ihr Schiff nicht mehr außerhalb des Bildschirms bewegen kann, aber manchmal dreht es sich.  Wenn ein Physikkörper mit einem anderen Physikkörper kollidiert, kann das zu einer Rotation führen.  Das ist das Standardverhalten.  Um das zu beheben, setzen wir in Player.swift allowsRotation auf false.

8. Sternfeld

Schritt 1: Erstellen des Sternfeldes

Das Spiel hat ein bewegliches Sternenfeld im Hintergrund.  Wir können das Startfeld mit der Partikel-Engine von Sprite Kit erstellen.

Erstellen Sie eine neue Datei und wählen Sie Ressource aus dem Bereich iOS.  Wählen Sie SpriteKit Particle File als Vorlage und klicken Sie auf Weiter.  Wählen Sie für die Partikelvorlage Regen und speichern Sie sie als StarFieldKlicken Sie auf Erstellen, um die Datei im Editor zu öffnen. Um die Optionen zu sehen, öffnen Sie den SKNode Inspector auf der rechten Seite.


Anstatt jede Einstellung hier zu durchlaufen, was lange dauern würde, wäre es besser, die Dokumentation zu lesen, um sich über jede einzelne Einstellung zu informieren.  Ich werde auch nicht auf die Einstellungen des Startfelds eingehen.  Wenn Sie interessiert sind, öffnen Sie die Datei in Xcode und sehen Sie sich die Einstellungen an, die ich verwendet habe.

Schritt 2: Hinzufügen des Sternfeldes zu den Szenen

Fügen Sie Folgendes zu didMoveToView(_:) in StartGameScene.swift hinzu.

Wir verwenden einen SKEmitterNode, um die StarField.sks-Datei zu laden, ihre position festzulegen und ihr eine niedrige zPosition zu geben.  Der Grund für die niedrige zPosition ist, dass der Benutzer nicht daran gehindert wird, auf die Startschaltfläche zu tippen.  Das Partikelsystem erzeugt Hunderte von Partikeln, und indem wir es wirklich niedrig setzen, überwinden wir dieses Problem.  Sie sollten auch wissen, dass Sie alle Partikeleigenschaften auf einem SKEmitterNode manuell konfigurieren können, obwohl es viel einfacher ist, den Editor zu verwenden, um eine .sks-Datei zu erstellen, und es zur Laufzeit zu laden.

Fügen Sie jetzt das Sternfeld zu GameScene.swift und LevelCompleteScene.swift hinzu.  Der Code ist genau der gleiche wie oben.

9. Implementieren der PulsatingText-Klasse

Schritt 1: Erstellen Sie die PulsatingText-Klasse

Die StartGameScene und LevelCompleteScene haben Text, der wiederholt wächst und schrumpft.  Wir werden SKLabeNode ableiten und einige SKAction-Instanzen verwenden, um diesen Effekt zu erzielen.

Erstellen Sie eine neue Cocoa Touch-Klasse, die eine Unterklasse von SKLabelNode ist, nennen Sie sie PulsatingText, und fügen Sie den folgenden Code hinzu.

Eines der ersten Dinge, die Sie vielleicht bemerkt haben, ist, dass es keinen Initialisierer gibt.  Wenn Ihre Unterklasse keinen designierten Initialisierer definiert, erbt sie automatisch alle ihre Initialen, die als Superklassen bezeichnet werden.ders.

Wir haben eine Methode setTextFontSizeAndPulsate (theText:theFontSize:), die genau das tut, was sie sagt.  Er legt die SKLabelNode-Eigenschaften text und fontSize fest und erstellt eine Reihe von SKAction-Instanzen, um den Text hoch- und dann wieder abwärts zu stellen, wodurch ein pulsierender Effekt entsteht.

Schritt 2: Fügen Sie PulsatingText zu StartGameScene hinzu

Fügen Sie zu StartGameScene.swift in didMoveToView(_:) den folgenden Code hinzu.

Wir initialisieren eine PulsatingText-Instanz, invaderText, und rufen setTextFontSizeAndPulsate (theText:theFontSize:) darauf auf.  Wir setzen dann seine position und fügen sie der Szene hinzu.

Schritt 3: Fügen Sie PulsatingText zu LevelCompleteScene hinzu

Fügen Sie LevelCompleteScene.swift in didMoveToView(_:) den folgenden Code hinzu.

Das ist genau das Gleiche wie im vorherigen Schritt.  Nur der Text, den wir passieren, ist an

10.  Das Spiel weiterführen

Das vervollständigt das Spiel.  Ich habe einige Vorschläge, wie Sie das Spiel weiter ausbauen können.  Im Bilderordner befinden sich drei verschiedene Eindringlingsbilder.  Wenn Sie der Szene Eindringlinge hinzufügen, wählen Sie nach dem Zufallsprinzip eines dieser drei Bilder aus.  Sie müssen den Initialisierer des Eindringlings aktualisieren, um ein Bild als Parameter zu akzeptieren.  Einen Hinweis finden Sie in der Bullet-Klasse.

Es gibt auch ein UFO-Bild.  Versuchen Sie, das etwa alle fünfzehn Sekunden anzuzeigen und sich über den Bildschirm zu bewegen.  Wenn der Spieler es trifft, geben Sie ihm ein zusätzliches Leben.  Vielleicht möchten Sie die Anzahl der Leben begrenzen, die sie haben können, wenn Sie dies tun.  Versuchen Sie schließlich, ein HUD für die Spieler zu erstellen.

Das sind nur einige Vorschläge.  Versuchen Sie das Spiel zu Ihrem eigenen zu machen.

Schlussfolgerung

Damit schließt sich diese Serie.  Sie sollten ein Spiel haben, das dem ursprünglichen Weltraum-Eindringlinge-Spiel sehr ähnlich ist.  Ich hoffe, Sie haben dieses Tutorial hilfreich gefunden und etwas Neues gelernt.  Danke fürs Lesen.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.