Im vorherigen Teil dieser Serie haben wir an vielen Systemen, die wir für unser Match-3-Spiel entwickelt haben, einige kleine, aber wichtige Änderungen vorgenommen. Mit diesen Verbesserungen werden wir jetzt wieder auf Kurs kommen und eines der letzten beiden Hauptsysteme für das Spiel implementieren: das Block Movement-System.
In diesem Lernprogramm werden Sie durch die gesamte Entwicklung des Systems geführt, mit dem die Blöcke bis zum oberen Rand des Bildschirms aufsteigen können. Außerdem werden alle kleineren Systeme beschrieben, die zur Unterstützung des Bewegungssystems implementiert werden müssen. Die Themen, die ich in diesem Tutorial behandele, sind zwar nicht zu komplex, aber es gibt noch viel zu besprechen.
Hier ist eine Demo des Spiels, an dem wir in dieser Serie arbeiten:
Bevor wir die Blöcke verschieben, müssen wir eine kleine Änderung an den Ereignissen vornehmen, die die Blöcke erzeugen. Gehe zum System> Beim Start des Layouts Ereignis und ändern Sie das Y zum
Schleife, um von zu gehen 0
zu 3
, statt von 0
zu 7
wie es ursprünglich tat.
Die Veranstaltung sollte jetzt so aussehen:
Der Grund, warum wir diese Änderung vorgenommen haben, ist, dass das Spiel mit weniger Blöcken auf dem Bildschirm beginnen soll, damit es nicht so schnell endet, wenn wir im nächsten Tutorial ein Game Over hinzufügen.
Als Nächstes erstellen wir eine Variable, die die Geschwindigkeit der Blöcke darstellt:
Globale Variable: Name = CurrentSpeed-Typ = Zahlenwert = 0,2
Jetzt erstellen wir das Ereignis, das die Blöcke tatsächlich bewegt:
Ereignis: Bedingung: System> Alle X Sekunden Intervall (Sekunden) = CurrentSpeed Aktion: Blockieren> Bewegen im Winkel Winkel = -90 Entfernung = 1
Die Veranstaltung sollte so aussehen:
Wenn Sie das Spiel nach dem Hinzufügen dieses Ereignisses ausführen, sollten Sie als Erstes feststellen, dass die Blöcke aufgrund der Schwerkraft, die wir in einem früheren Lernprogramm implementiert haben, fallen. Danach sollten die Blöcke langsam aufsteigen, bis sie sich in ihrer ursprünglichen Position befinden, und dann wieder fallen. Dies wird unendlich wiederholt, solange Sie nichts mit den Blöcken tun.
Dies geschieht, weil sich die Blöcke an dem Punkt bewegen, an dem die Schwerkraft eintreten soll, und sie entdecken, dass sich unter ihnen keine Blöcke befinden, die dazu führen, dass sie alle fallen. Obwohl dies ein Problem ist, ist es nicht das erste, das ich mir ansehen möchte.
Führe das Spiel aus und versuche, einen beliebigen Swap zu machen. Wenn Sie dies tun, sollten Sie sehen, dass die Blöcke hintereinander stecken, an Positionen hängen bleiben, die nicht am Raster ausgerichtet sind, und sich im Allgemeinen nur schlecht benehmen. Es gibt zwei Gründe für dieses Problem.
Das erste Problem ist, dass wir, obwohl wir die Blöcke selbst bewegen, die Blöcke nicht bewegen LeftBlock
, RightBlock
, TopBlock
, und BottomBlock
Objekte mit ihnen, was bedeutet, dass die Blöcke, die Sie zum Erkennen von Swaps verwenden, sich nicht mit dem Blockraster bewegen - sie sitzen nur in der Position, in der sie beim ersten Aufnehmen eines Blocks eingestellt sind.
Wenn Sie also versuchen, einen Swap durchzuführen, werden die Blöcke verschoben, da sich die Swap-Erkennungsblöcke überhaupt nicht an das Raster angepasst haben. (Dies ist auch der Grund für das zweite Problem, das wir haben, dh, wir ändern nicht die Positionen, die wir in der Datenbank gespeichert haben Blockpositionen
Array entweder.)
Die folgende GIF veranschaulicht dieses Problem:
Wie Sie in der GIF sehen können, bewegen sich die Swap-Erkennungsblöcke nicht, obwohl die Blöcke selbst sind.
Um beide Probleme zu lösen, fügen wir dem soeben erstellten Ereignis ein paar weitere Aktionen hinzu:
Aktion: BottomBlock> Bewegen im Winkel Winkel = -90 Abstand = 1 Aktion: LeftBlock> Bewegen im Winkel Winkel = -90 Abstand = 1 Aktion: RightBlock> Bewegen im Winkel Winkel = -90 Abstand = 1 Aktion: TopBlock> Bewegen im Winkel Winkel = -90 Entfernung = 1 Aktion: Blockpositionen> Setzen bei XY X = 0 Y = 1 Wert = Blockpositionen.At (0,1) - 1 Aktion: Blockpositionen> Setzen bei XY X = 1 Y = 1 Wert = Blockpositionen.At ( 1,1) - 1
Das Event sollte jetzt so aussehen:
Die ersten vier Aktionen, die wir gerade hinzugefügt haben, passen die Positionen von an LeftBlock
, TopBlock
, RightBlock
, und BottomBlock
Objekte, so dass sie mit dem Blockraster in Linie bleiben. Die zweiten beiden Ereignisse passen die Y-Werte an, die wir in gespeichert haben Blockpositionen
Array, so dass sie auch mit dem Blockraster inline bleiben.
Wenn Sie das Spiel zu diesem Zeitpunkt noch einmal testen, sollte der Austausch weitgehend behoben sein.
An diesem Punkt gibt es noch ein weiteres Problem, mit dem wir uns befassen müssen, damit der Austausch korrekt funktioniert. Führen Sie das Spiel aus und versuchen Sie, mit einem der Blöcke in der unteren Reihe einen Abwärtswechsel vorzunehmen, während sich diese Reihe teilweise unterhalb des unteren Bereichs des Spielfelds befindet:
Machen Sie den Swap, während sich die Blöcke hinter dem Rand befinden, wie die hervorgehobenen im obigen Bild.Wenn Sie dies richtig gemacht haben, sollten Sie feststellen, dass nichts passiert ist und die Blöcke nicht ausgetauscht wurden. Wenn Sie zu lange gewartet haben, sind die Blöcke möglicherweise vertauscht, weil sie sich wieder über die Grenze des Spielfelds bewegt haben. Wenn dies passiert, versuchen Sie es erneut, sobald sie fallen, und Sie sollten dieses Problem sehen.
Dieses Problem ist ziemlich einfach zu lösen und zu verstehen. Wenn Sie sich den Code für Abwärts-Swaps ansehen, sollten Sie das Ereignis finden, das wir im vorherigen Lernprogramm hinzugefügt haben. Dadurch wird verhindert, dass der Spieler Abwärts-Swaps vornimmt, die dazu führen, dass der Block vom unteren Rand des Spielfelds fällt. Da diese Aussage den Spieler daran hindert, abwärts zu tauschen, wenn der BottomBlock
Das Objekt ist niedriger als die anfängliche Y-Position des Blocks. Es verhindert, dass die Blöcke ausgetauscht werden, sobald sie gefallen sind, und ermöglicht erst dann einen erneuten Swap, wenn sie wieder über ihre ursprüngliche Position hinausgefahren sind.
Um diese Aussage zu korrigieren, nehmen wir eine kleine Änderung an der Bedingung vor:
Bedingung: BottomBlock> Y-Vergleich vergleichen = Weniger oder gleich Y-Koordinate = SPAWNY + ((Block.Width + 2) / 2)
Die Bedingung sollte jetzt so aussehen:
Diese Modifikation bedeutet, dass ein Abwärts-Swap nur während der BottomBlock
Das Objekt befindet sich höchstens einen halben Block unterhalb der Y-Position, in der die Blöcke beginnen. Dies bedeutet auch, dass, wenn wir neue Blockreihen erzeugen und sie von unten auf den Bildschirm schieben, diese Blöcke nur noch eingelagert werden können auf diese Weise ist mindestens die Hälfte des Blocks sichtbar.
Wir werden auch eine ähnliche Einschränkung in alle unsere Tauschereignisse aufnehmen, um sicherzustellen, dass alle zur gleichen Zeit nutzbar werden und ein Block erst dann ausgetauscht werden kann, wenn mindestens die Hälfte davon sichtbar ist. Auch dies hilft, wenn wir das System integrieren, das neue Blockreihen erzeugt. Dazu fügen wir jedem der drei verbleibenden Swap-Events eine neue Bedingung hinzu.
Die Bedingungen, die wir hinzufügen, stimmen exakt mit denen überein, die wir gerade geändert haben BottomBlock
Ereignis, außer dass sie auf das verweisen TopBlock
, RightBlock
, und LeftBlock
Objekte statt der BottomBlock
Objekt, abhängig davon, in welchem Ereignis es sich befindet.
Die neue Bedingung für die TopBlock
Veranstaltung sollte sein:
Bedingung: TopBlock> Y-Vergleich vergleichen = Weniger oder gleich Y-Koordinate = SPAWNY + ((Block.Width + 2) / 2)
Die neue Bedingung für die LeftBlock
Veranstaltung sollte sein:
Bedingung: LeftBlock> Y-Vergleich vergleichen = Weniger oder gleich Y-Koordinate = SPAWNY + ((Block.Width + 2) / 2)
Die neue Bedingung für die RightBlock
Veranstaltung sollte sein:
Bedingung: RightBlock> Vergleiche Y-Vergleich = Weniger oder gleich Y-Koordinate = SPAWNY + ((Block.Width + 2) / 2)
Dein ganzes Beim DragDrop-Drop Das Event sollte jetzt so aussehen:
Mit diesen neuen Bedingungen haben wir unsere Tauschmechanik korrigiert und mit der Vorbereitung der vorhandenen Systeme für das nächste System begonnen, das wir hinzufügen: das System, das neue Blockreihen erzeugen wird.
Jetzt, da sich die Blöcke mit einer konstanten Geschwindigkeit nach oben bewegen, müssen wir die neuen Blockreihen zum richtigen Zeitpunkt auftauchen lassen und den Spieler so lange spielen lassen, wie er möchte. Wir werden eine Funktion verwenden, um die neuen Blockreihen zu erzeugen, und wir werden ein Ereignis verwenden, das erkennt, wann die Blöcke inline sind SPAWNY
um diese Funktion auszulösen.
Also machen wir zuerst die Funktion selbst.
Ereignis: Bedingung: Funktion> Ein Funktion Name = "SpawnNewBlocks" Bedingung: System> Für Name = "X" Startindex = 0 Ende Index = 7 Aktion: System> Objekt erstellen Objekt = Block Layer = 1 X = SPAWNX + (loopIndex ( "X")) * (Block.Width + 2) Y = SPAWNY + (Block.Width + 2) Aktion: Blockieren> Wert setzen Instanzvariable = Farbe Wert = Stock (Zufällig (1,7)) Aktion: System> Hinzufügen auf Variable = NumBlocks Wert = 1
Ihre neue Veranstaltung sollte so aussehen:
Bei Verwendung erstellt diese Funktion eine Reihe von Blöcken unterhalb der untersten Blockreihe im Spielfeld. Wie es jetzt aussieht, verwenden wir diese Funktion jedoch zu keinem Zeitpunkt, also machen wir das Ereignis, das dies tut:
Ereignis: Bedingung: System> Alle X Sekunden Intervall (Sekunden) = CurrentSpeed Bedingung: Block> Y-Vergleich vergleichen = Gleich Y = SPAWNY Bedingung: Invertieren: Blockieren> Wird gezogen Aktion: Funktion> Aufruf Funktionsname = "SpawnNewBlocks"
Ihre neue Veranstaltung sollte so aussehen:
Das soeben erstellte Event prüft bei jeder Bewegung die Y-Position der Blöcke. Wenn es Blöcke findet, die inline sind SPAWNY
, es löst das aus SpawnNewBlocks ()
Funktion wie zuvor besprochen. Außerdem wird überprüft, ob der Block, den er findet, nicht vom Block gezogen wird.
Wenn Sie Ihr Spiel zu diesem Zeitpunkt testen, funktioniert es, aber Sie sollten ein merkwürdiges Problem feststellen. Sobald Sie mit dem Spiel beginnen, werden Ihre Blöcke so fallen, als ob keine Blöcke darunter wären, aber danach funktioniert alles perfekt und neue Blöcke werden immer dann erzeugt, wenn sie benötigt werden.
Dies geschieht, weil beim Start des Spiels der Gravitationscode verarbeitet wird Vor der Code, der neue Blockreihen erzeugt. Um dies zu beheben, nehmen wir eine kleine Anpassung des Codes vor, der die ursprüngliche Gruppe von Blöcken erzeugt, so dass sie unterhalb des Punktes erscheinen, an dem eine neue Zeile benötigt wird. Dadurch kann der Gravitationscode nicht sofort ausgeführt werden, und es kann die neue Blockreihe erstellt werden, sobald sich die vorhandenen Blöcke am richtigen Ort befinden.
Gehen Sie zu dem Ereignis, das die ursprüngliche Gruppe von Blöcken erzeugt, und ändern Sie die Aktion, die den Block tatsächlich erstellt. Ändern Sie die Aktion dazu:
Aktion: System> Objekt erstellen Objekt = Blockebene = 1 X = SPAWNX + (loopIndex ("X")) * (Block.Width + 2) Y = SPAWNY - (LoopIndex ("Y")) * (Block.Width + 2) + 5
Das Event sollte jetzt so aussehen:
Diese Änderung bedeutet, dass die Blöcke fünf Pixel darunter erscheinen SPAWNY
. Dies bedeutet, dass die Blöcke tatsächlich fünfmal nach oben verschoben werden müssen, bevor eine neue Reihe erscheint und unser Problem gelöst wird.
Zu diesem Zeitpunkt bewegen sich unsere Blöcke, und es werden neue Zeilen erstellt. Denken Sie außerdem daran, dass der Player früher keinen Block verwendet hat, bis mindestens die Hälfte des Blocks sichtbar ist. Obwohl dies eine gute Funktion ist, kann der Spieler nicht verstehen, warum ein Block nicht sofort verwendet werden kann, wenn er sichtbar wird, auch wenn zu diesem Zeitpunkt nicht viel davon sichtbar ist.
Aufgrund dieses potenziellen UI-Problems wird jeder Block das graue Blocksprite (am Anfang der Animationsframes des Blocks) verwenden, wenn er sich in diesem unbrauchbaren Zustand befindet. Dadurch wird dem Spieler klar, wann ein Block nutzbar wird, und wir haben die Chance, unser letztes Block-Image endlich zu verwenden.
Sie können ein Beispiel sehen, wie es aussehen wird, wenn die Blöcke im GIF unten inaktiv werden und aktiv werden:
Das von uns erstellte Ereignis enthält auch eine zweite Bedingung, die überprüft, ob der gesuchte Block nicht gezogen wird. Diese Bedingung ermöglicht es uns sicherzustellen, dass der Spieler, wenn er einen Block unter den Punkt zieht, an dem Blöcke verwendet werden können, sein Bild nicht grau ändert und die Farbe behält, die es sein soll.
Damit diese Animation funktioniert, müssen wir zuerst ein neues Ereignis hinzufügen:
Ereignis: Bedingung: Block> Vergleiche Y-Vergleich = Größer als Y = SPAWNY + ((Block.Width + 2) / 2) Bedingung: Umkehren: Blockieren> Wird gezogen Aktion: Blockieren> Frame setzen Frame-Nummer = 0
Das neue Event sollte so aussehen:
Sie sollten jetzt in der Lage sein, Ihr Spiel zu testen, und Sie sollten sehen, dass die Blöcke das graue Bild verwenden, wenn sie unter dem Punkt liegen, an dem sie verwendbar sind.
Wenn Sie das Spiel jetzt ausführen, werden Sie feststellen, dass die Blöcke zwar grau sind, die Blöcke jedoch nicht gegeneinander ausgetauscht werden können, die grauen Blöcke jedoch immer noch gezogen und manipuliert werden können. Dies liegt daran, dass wir die Drag / Drop-Funktionen des Blocks niemals deaktiviert haben, wenn der Player nicht mit ihnen ausgetauscht wurde.
Um zu verhindern, dass die grauen Blöcke verschoben werden können, ändern wir das im vorherigen Abschnitt erstellte Ereignis. Zuerst fügen wir eine neue Aktion hinzu, die das Ziehen abschaltet, wenn sich der Block unterhalb des verwendbaren Punkts befindet.
Fügen Sie diese Aktion dem zuvor erstellten Ereignis hinzu:
Aktion: Blockieren (DragDrop)> Aktiviert setzen = Deaktiviert
Wir werden auch eine Else-Anweisung für dieses Ereignis hinzufügen, mit der der Block erneut gezogen werden kann, sobald er über dem Punkt liegt, an dem der Block verwendbar ist:
Ereignis: Bedingung: Sonst Aktion: Blockieren (DragDrop)> Aktiviert setzen = Aktiviert
Bei beiden Änderungen sollte das Ereignis so aussehen:
Wenn Sie das Spiel zu diesem Zeitpunkt testen, sollten die Blöcke bei grauem Hintergrund nicht mehr verwendbar sein und auf dieselbe Weise funktionieren, wie sie es immer tun, wenn sie nicht sind.
Das letzte, was ich in diesem Artikel behandeln möchte, ist das System, mit dem wir die Geschwindigkeit des Spiels im Laufe der Zeit ändern können. Dies ist insbesondere das System, das die Blöcke schneller bewegt, wenn der Spieler mehr von ihnen entfernt.
Das System, das wir erstellen werden, ist relativ einfach: Jedes Mal, wenn der Spieler einige Punkte erhält, erhöht sich die Geschwindigkeit des Spiels, basierend auf einem Modifikator, den wir erstellen werden, und der Anzahl der Punkte, die der Spieler erhalten muss Die nächste Geschwindigkeitssteigerung wird basierend auf einem zweiten Modifikator geändert.
Bevor wir mit dem Erstellen der Ereignisse für dieses System beginnen können, erstellen wir einige globale Variablen, um die neuen Funktionen für uns zu handhaben:
Globale Variable: SPEEDMOD-Typ = Zahl Anfangswert = 0,8 Konstante = Ja Globale Variable: PointsForSpeedUp-Typ = Zahl Anfangswert = 400 Konstante = Nein Globale Variable: PointsBetweenSpeedUps Typ = Zahl Anfangswert = 400 Konstante = Nein Globale Variable: POINTSFORSPEEDUPMOD Typ = Zahl Anfang Wert = 1,4 Konstante = Ja
Ihre neuen Variablen sollten folgendermaßen aussehen:
Jetzt, da wir die Variablen haben, werde ich erklären, was jede tut.
SPEEDMOD
ist die Variable, mit der wir die Geschwindigkeit multiplizieren, um sie zu ändern, sobald der Spieler die Anzahl der Punkte erreicht hat, die er für eine Erhöhung der Geschwindigkeit benötigt.PointsForSpeedUp
ist die Anzahl der Punkte, die der Spieler benötigt, um die nächste Geschwindigkeit zu erreichen.PointsBetweenSpeedUps
stellt dar, wie viel die PointsForSpeedUp
Die Variable erhöht sich, wenn der Spieler beschleunigt wird, um ihn so anzupassen, dass die nächste Beschleunigung noch mehr Punkte bringt. Im Moment sind es 400, wie PointsForSpeedUp
, Wenn der Spieler tatsächlich beschleunigt wird, wird er mit multipliziert PUNKTEFORSPEEDUPMOD
bevor es hinzugefügt wird PointsForSpeedUp
.PUNKTEFORSPEEDUPMOD
ist die Variable, die wir verwenden werden, um die Anzahl der Punkte zu ändern, die der Spieler benötigt, um seine Geschwindigkeit um ein anderes Mal als das, was er zuletzt erreicht hat, zu erhöhen.Neben dem Einrichten der Variablen müssen wir auch ein neues Sprite-Objekt erstellen, das als Warnung für den Spieler fungiert, wenn die Geschwindigkeit zunimmt.
Gehe zu Layout 1 Führen Sie die folgenden Schritte aus, um das neue Sprite zu erstellen:
SpeedIncImage.png
. SpeedIncreaseIndicator
.Spielfeld
.188, 329
.Unsichtbar
. Nein
.2,5
.Nein
.Ihr Layout sollte jetzt so aussehen:
Jetzt erstellen wir das Ereignis, das die Geschwindigkeit ändert:
Ereignis: Bedingung: Funktion> Ein Funktion Name = "CheckForSpeedUp" Bedingung: System> Variable vergleichen Variable = Ergebnisvergleich = Größer oder gleich Wert = PointsForSpeedUp Aktion: SpeedIncreaseIndicator> Sichtbare Sichtbarkeit einstellen = Sichtbar Aktion: SpeedIncreaseIndicator> Start Fade Action System> Wert setzen Variable = CurrentSpeed-Wert = CurrentSpeed * SPEEDMOD-Aktion System> Wert setzen Variable = PointsBetweenSpeedUp-Wert = PointsBetweenSpeedUp * POINTSFORSPEEDUPMOD Aktion: System> Zu Variable hinzufügen = PointsForSpeedUp-Wert = PointsBetweenSpeedUp
Ihre Veranstaltung sollte so aussehen:
Wenn diese Funktion aufgerufen wird, wird geprüft, ob der Spieler genügend Punkte gesammelt hat, um eine Erhöhung der Geschwindigkeit zu gewährleisten. Wenn ja, dann:
Wenn diese Funktion abgeschlossen ist, müssen wir nur sicherstellen, dass sie aufgerufen wird. Gehe zum GivePoints ()
funktionieren und fügen Sie diese Aktion am Ende des primären Ereignisses und des Unterereignisses hinzu:
Aktion: Funktion> Aufruf Funktion Name = "CheckForSpeedUp"
Das GivePoints ()
Funktion sollte jetzt so aussehen:
Wenn das Event abgeschlossen ist, sollten Sie in der Lage sein, Ihr Spiel zu testen und das Beschleunigungssystem in Aktion zu sehen.
Spitze: Als ich mehr damit spielte, fand ich heraus, dass sich diese Werte etwas abnahmen, daher empfehle ich Ihnen, sich etwas Zeit zu nehmen, um mit dem System zu experimentieren und die Werte zu finden, mit denen Sie sich am wohlsten fühlen.
Wir haben in diesem Artikel viele verschiedene Themen behandelt, aber alles, was wir behandelten, hatte direkt oder indirekt damit zu tun, dass das Bewegungssystem so funktioniert, wie wir es wollten. Es hat zwar einige Zeit gedauert und wir mussten mehr Systeme erstellen, als wir am Anfang erwartet hätten, aber die Auszahlung hat sich gelohnt, und am Ende hatten wir ein sehr starkes System.
Ich denke, dass dies ein guter Ort ist, um diesen Artikel zu beenden. Der nächste Artikel sollte das letzte Tutorial in dieser Serie sein. Wir werden viele kleinere Themen behandeln, aber das größte, was wir behandeln, ist definitiv die Beseitigung von vorgefertigten Spielen.
Wenn Sie herausfinden möchten, wie wir sie beseitigen werden, schauen Sie sich an, wie wir Übereinstimmungen erkennen. Das System, das wir erstellen, ist diesem System sehr ähnlich, außer dass es die gefundenen Übereinstimmungen auf eine andere Weise verwendet. Denken Sie darüber nach und sehen Sie, was Sie sich vorstellen können, und ich sehe Sie nächstes Mal wieder beim letzten großen Tutorial der Serie.