Machen Sie ein Match-3-Spiel in Construct 2 Punkte, Matching und Schwerkraft

Im vorherigen Tutorial haben wir ein grundlegendes Match-Detection-System in unser Match-3-Spiel integriert. Obwohl wir uns auf dem Weg zu einem spielbaren Spiel befinden, gibt es noch einige wichtige Spielelemente, die wir brauchen, bevor wir wirklich das nennen können, was wir ein "Spiel" haben. Dieser Artikel wird sich darauf konzentrieren, einige dieser fehlenden Details auszufüllen und uns unserem Endprodukt viel näher zu bringen.


Final Game Demo

Hier ist eine Demo des Spiels, an dem wir in dieser Serie arbeiten:




1. Punkte vergeben

Wir werden Punkte besprechen, bevor wir mit der Verbesserung des Übereinstimmungssystems beginnen, denn es ist viel einfacher, die erste Ausgabe in unserem aktuellen Übereinstimmungssystem zu sehen, wenn ein Punktesystem implementiert ist.

Das Punktesystem in unserem Spiel wird sehr einfach sein. Für jeden Block, aus dem eine Gruppe gebildet wird, erhält der Spieler 10 Punkte. In einem späteren Tutorial werden wir auch ein System hinzufügen, das es dem Spieler ermöglicht, durch das Aneinanderreihen mehrerer Gruppen mehr Punkte zu erzielen. Im Moment konzentrieren wir uns jedoch darauf, ein einfaches Punktesystem für den Spieler einzuführen.

Bevor wir mit dem Bearbeiten der Ereignisse beginnen, müssen wir eine Punkteanzeige hinzufügen Layout 1 und mache folgendes:

  1. Ein neues einfügen Sprite Objekt.
    1. Öffnen Sie das Bild Spielfeldbilder / ScoreArea.png aus dem Grafikpaket.
    2. Schließen Sie den Animationseditor.
    3. Stellen Sie die Position auf 491, 383.
  2. Ein neues einfügen Text Objekt.
    1. Stellen Sie das ein Schriftart zu Calibri, Bold, 22 mit der Dropdown-Liste.
    2. Stellen Sie das ein Name zu ScoreText
    3. Stellen Sie das ein Farbe zu Weiß oder 255, 255, 255
    4. Stellen Sie das ein Position zu 419, 398.
    5. Stellen Sie das ein Größe zu 200, 50.
    6. Stellen Sie das ein Text zu 0.

Layout 1 sollte jetzt so aussehen:

Nachdem wir dem Spieler nun etwas zu sagen haben, was der Punktetext bedeutet, und ein Textobjekt, mit dem die Punktzahl des Spielers angezeigt wird, können wir dem Spieler tatsächlich Punkte geben. Gehe zu Veranstaltungsblatt 1 und ein neues erstellen Globale Variable.

Globaler Variablenname: "Score" Typ = Number Value = 0

Die Variable sollte so aussehen:

Dies ist die Variable, die wir ändern, wenn wir dem Spieler Punkte geben. Als Nächstes erstellen wir eine neue Funktion, die beim Aufruf ermittelt, wie viele Blöcke der Spieler in Gruppen abgeglichen hat, und ihnen die entsprechende Anzahl von Punkten gibt.

Ereignis: Bedingung: Funktion> Ein Funktionsname = "GivePoints" Bedingung: System> Für jedes Objekt = Block Bedingung: Block> Ist boolesche Instanzvariable gesetzt Instanzvariable = IsMatched Aktion: System> Zu Variable hinzufügen = Score Wert = 10 Aktion: ScoreText > Set text Text = Ergebnis

Ihr Code sollte so aussehen:

Um dies zu wiederholen, betrachtet dieses Ereignis jeden einzelnen Block. Immer wenn es einen Block findet der was hat Ist abgestimmt einstellen wahr - Das heißt, es wurde bestätigt, Teil einer Gruppe zu sein - es gibt dem Spieler 10 Punkte für diesen Block und aktualisiert den Score-Text.

Wenn Sie Ihr Spiel zu diesem Zeitpunkt testen, scheint die Funktion nicht zu funktionieren. Der Grund dafür ist, dass wir die Funktion nirgendwo im Code aufgerufen haben, also die Punkte niemals inkrementiert werden und der Text niemals aktualisiert wird. Gehen Sie zu Ihrem FindMatches Funktion und fügen Sie am Anfang des letzten Unterereignisses für diese Funktion eine neue Aktion hinzu.

Aktion: Funktion> Aufruf Funktion Name = "GivePoints"

Ihre FindMatches Funktion sollte jetzt so aussehen:

Hinweis: Stellen Sie sicher, dass Sie diese neue Aktion zu Beginn des Unterereignisses hinzugefügt haben. Wenn Sie diese Aktion am Ende hinzufügen, funktioniert sie nicht, da alle übereinstimmenden Blöcke vor dem zerstört wurden GivePoints Funktion wird aufgerufen. Das bedeutet, dass bei der Suche nach übereinstimmenden Blöcken keine gefunden werden und der Spieler keine Punkte erhält.

An diesem Punkt können Sie Ihr Spiel erneut testen, und Sie sollten die Aktualisierung des Punktetextes sehen und dass der Spieler für jedes Spiel die richtige Anzahl Punkte erhält.


2. Verbesserung der Übereinstimmungserkennung

Nun, da wir das Punktesystem haben, möchte ich, dass Sie das Spiel ausführen und das unten gezeigte Szenario erstellen.


Tauschen Sie nun die hier hervorgehobenen Blöcke aus und beobachten Sie Ihre Punktzahl, um zu sehen, wie viele Punkte Sie gewinnen.


Wenn Sie dieses Match gebildet haben, sollten Sie gesehen haben, dass Sie 50 Punkte gewonnen haben. Dies liegt daran, dass das Punktesystem dem Spieler derzeit 10 Punkte für jeden Block gibt, der als markiert ist Ist abgestimmt, im Gegensatz dazu, dem Spieler 10 Punkte für jeden Block zu geben gebraucht in jedem Spiel, wie das oben beschriebene System.

Wenn das Punktesystem korrekt funktioniert, erhält der Spieler 60 Punkte: 30 für die vertikale Gruppe von drei Blöcken und 30 für die horizontale Gruppe von drei Blöcken. Dieses Problem rührt von der Tatsache her, dass das Übereinstimmungssystem keine Möglichkeit hat, zu markieren, wenn ein Block sowohl horizontal als auch übereinstimmt und vertikal; es weiß nur, ob der Block überhaupt übereinstimmt.

Um dieses Problem zu lösen, fügen wir zuerst zwei neue hinzu Instanzvariablen zu unserem Blockobjekt, MatchedX und MatchedY.

Instanzvariable: Name = MatchedX Type = Boolean-Anfangswert = false Instanzvariable: Name = MatchedY-Typ = Boolean-Initialwert = False

Ihre Variablen sollten so aussehen:


Diese Variablen werden in Verbindung mit verwendet Ist abgestimmt Um dem System mitzuteilen, wenn der Block Teil einer horizontalen Gruppe oder X-Gruppe ist und wenn der Block Teil einer vertikalen Gruppe oder Y-Gruppe ist. Nun, da wir die Variablen haben, werden wir das ändern CheckMatches Funktion damit, wenn es einen Block beschriftet Ist abgestimmt Da er eine ausreichend große Gruppe gefunden hat, wird dieser Block auch als Teil einer X- oder Y-Gruppe bezeichnet, je nachdem, ob Parameter 3 oder Parameter 4 den Wert 1 hat.

Gehe zum CheckMatches Funktion und ersetzen Sie das Original NumMatchesFound Überprüfen Sie mit diesen beiden neuen Unterereignissen:

Unterereignis: Bedingung: System> Zwei Werte vergleichen Erster Wert = Function.Param (3) Vergleich = Gleicher zweiter Wert = 1 Bedingung: System> Variable vergleichen Variable = NumMatchesFound Vergleich = Größer oder gleich Wert = 3 Aktion: Blockieren> Setzen Boolean-Instanzvariable = IsMatched-Wert = True Aktion: Blockieren> Boolean-Instanzvariable setzen = MatchedX-Wert = True Unterereignis: Bedingung: System> Zwei Werte vergleichen Erster Wert = Function.Param (4) Vergleich = Gleicher zweiter Wert = 1 Bedingung : System> Variable vergleichen Variable = NumMatchesFound Vergleich = Größer oder gleich Wert = 3 Aktion: Blockieren> Boolean-Instanzvariable festlegen = IsMatched-Wert = True Aktion: Blockieren> Boolean-Instanzvariable festlegen = MatchedY-Wert = True

Ihre CheckMatches Funktion sollte jetzt so aussehen:


Also die neue Version von CheckMatches funktioniert auf die gleiche Weise wie die vorherige, mit der Ausnahme, dass jetzt auch geprüft wird, ob der Block in einer vertikalen Gruppe oder einer horizontalen Gruppe gefunden wurde, und er den Block entsprechend mit den neuen Variablen beschriftet MatchedX und MatchedY.

Zwei zusätzliche Punkte für Blöcke, die zweimal übereinstimmen

Jetzt haben wir eine Möglichkeit, zu bestimmen, wann ein Block vertikal, horizontal und in beiden Richtungen übereinstimmt, anstatt nur zu wissen, dass er in einer Gruppe gefunden wurde. Nun müssen wir dem Ereignis ein Unterereignis hinzufügen GivePoints Diese Funktion verteilt 10 zusätzliche Punkte für einen Block, der beide enthält MatchedX und MatchedY auf wahr setzen.

Gehe zum GivePoints Funktion und fügen Sie dieses Unterereignis hinzu:

Unterereignis: Bedingung: Block> ist boolesche Instanzvariable gesetzt Instanzvariable = MatchedX Bedingung: Block> ist boolesche Instanzvariable gesetzt Instanzvariable = MatchedY Aktion: System> Zu Variable hinzufügen = Bewertung Wert = 10 Aktion: Text> Text setzen Wert = Ergebnis

Ihre GivePoints Funktion sollte jetzt so aussehen:


Wenn Sie Ihr Spiel ausführen und das oben dargestellte Szenario erneut erstellen, sollte Ihre Punktzahl jetzt korrekt um 60 Punkte erhöht werden.


3. Schwerkraft hinzufügen

Nachdem wir ein Punktesystem implementiert haben und das Matching-System aktualisiert haben, werden wir einen weiteren wichtigen Aspekt des Gameplays verbessern. Wenn Sie bis jetzt mit dem Spiel gespielt haben, wissen Sie, dass eines der größten Probleme darin besteht, dass bei der Zerstörung von Blöcken den darüber liegenden Blöcken nichts passiert. Insbesondere die Blöcke über leeren Feldern füllen diese Felder nicht aus.

Dies ist in den Tests in Ordnung, aber in der endgültigen Version wäre es für das Gameplay nachteilig, die Dinge so zu belassen, dass wir als Nächstes "Schwerkraft" hinzufügen werden, was dazu führt, dass die Blöcke fallen und sich füllen Leerzeichen, wenn andere Blöcke zerstört werden.

Wie wir dieses System implementieren werden, ist eigentlich ganz einfach. Wir werden eine Überprüfung mit dem durchführen Block> Überlappt sich beim Offset Ereignis, um zu sehen, ob es einen Block unterhalb des Blocks gibt, den wir betrachten. Wenn wir feststellen, dass es keinen Block gibt, verschieben wir den Block, den wir betrachten, nach unten, um den leeren Raum auszufüllen. sonst werden wir nichts tun.

Damit dies funktioniert, erstellen wir ein neues Event:

Ereignis: Bedingung: INVERT> Block> Überlappt sich beim Offset Objekt = Blockversatz X = 0 Offset Y = 8 Aktion: Blockieren> Bewegen im Winkel Winkel = 90 Abstand = (Blockbreite + 2) / 2

Ihr Code sollte so aussehen:


Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, werden Sie feststellen, dass alle Blöcke vom Moment des Spielbeginns vom Bildschirm fallen! Der Grund dafür ist, dass wir nichts in den Code eingefügt haben, um zu sagen, wo der "Boden" des Spielfelds liegen würde.

Im Wesentlichen erkennen die Blöcke in der unteren Reihe, dass sich keine Blöcke darunter befinden, und fallen entsprechend. Sobald die unterste Reihe von Blöcken gefallen ist, werden in der untersten Reihe jetzt keine Blöcke unter ihnen angezeigt, und auch sie fallen ab. Dieser Vorgang wird fortgesetzt, bis alle Blöcke gefallen sind und der Bildschirm vollständig leer ist.

Im Folgenden sehen Sie eine etwas verlangsamte Version davon in der GIF:


Um dies zu beheben, fügen wir dem Ereignis eine zweite Bedingung hinzu.

Ereignis: Bedingung: Block> Vergleiche Y-Vergleich = Weniger oder gleich Y = SPAWNY - 1

Ihr Code sollte jetzt so aussehen:


Durch das Hinzufügen dieser neuen Bedingung stellen wir sicher, dass nur Blöcke, die sich oberhalb der Y-Position der untersten Reihe befinden, von unserer "Schwerkraft" beeinflusst werden. Trotz dieses Updates haben wir noch einige Probleme.

Umgang mit dem Ziehen

Das Hauptproblem ist, dass das Ereignis, das nach einem leeren Feld unter einem Block sucht, nichts zu sagen hat, dass es inaktiv ist, wenn der Spieler einen Block zieht. Wenn Sie also einen Block zu weit ziehen, ohne ihn loszulassen, fallen die Blöcke an der Position, an der Sie sie gezogen haben, in den Bereich, den der Block, den Sie gezogen haben, verlassen haben. Darüber hinaus hat der Block, den Sie ziehen, auch ein Problem, wenn Sie ihn aus dem Spielfeld holen, und er beginnt sich vom Mauszeiger zu lösen, da sich keine Blöcke darunter befinden.

Um dieses Problem zu beheben, müssen Sie eine neue globale Variable hinzufügen, um das System mitzuteilen, wenn Sie einen Block verschieben, eine neue Aktion für das Ziehen und Ablegen von Ereignissen, um diese globale Variable festzulegen, und eine dritte Bedingung für das Schwerkraftereignis diese Variable vor der Aktivierung berücksichtigen.

Zuerst machen wir die globale Variable:

Globale Variable: Name = BlockBeingMoved Type = Number Anfangswert = 0

Ihre Variable sollte so aussehen:


Gehen Sie jetzt zum Bei DragDrop ziehen Sie den Start Ereignis und fügen Sie eine neue Aktion hinzu:

Aktion: System> Set Value Variable = BlockBeingMoved Value = 1

Gehen Sie auch zum Beim DragDrop-Drop Ereignis und fügen Sie dem primären Ereignis eine neue Aktion hinzu:

Aktion: System> Set Value Variable = BlockBeingMoved Value = 0

Nachdem die Zeilen hinzugefügt wurden, sollten Ihre DragDrop-Ereignisse jetzt so aussehen:


Gehen Sie zum Gravitationsereignis und fügen Sie eine neue Bedingung hinzu:

Bedingung: System> Variable vergleichen Variable = BlockBeingMoved Vergleich = Gleichwert = 0

Ihr Gravitationscode sollte jetzt so aussehen:


Die neue Variable, die wir erstellt haben, BlockBeingMoved, wird verwendet, um dem System mitzuteilen, wenn ein Block vom Player verschoben wird. Wenn die Variable gleich ist 0 Dies bedeutet, dass kein Block verschoben wird und er die Schwerkraftskripts normal ausführen kann. Wenn die Variable gleich ist 1, es bedeutet einen Block ist verschoben werden und die Gravitationsskripte sollten nicht ausgeführt werden.

Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, werden Sie feststellen, dass unabhängig davon, wo Sie den Block verschieben, während Sie ihn ziehen, keine Probleme auftreten.

Nach neuen Übereinstimmungen suchen

Jetzt haben wir nur noch eine letzte Ausgabe, die sich mit dem Schwerkraftsystem befassen muss. Führen Sie das Spiel aus und erstellen Sie ein ähnliches Szenario:


Machen Sie jetzt den Swap, den ich in diesem nächsten Bild hervorgehoben habe.


Sie sollten feststellen, dass bei der Zerstörung der Gruppe der Grün- / Sternblöcke ein Orange / Sechseckblock fällt und eine Gruppe von drei Blöcken bildet, die jedoch nicht zerstört werden.

Der Grund, warum diese Blöcke nicht zerstört werden, liegt darin, dass wir das nie aufgerufen haben FindMatches Funktion ein zweites Mal, um zu sehen, ob neue Übereinstimmungen gebildet wurden, als die Blöcke fielen, um die leeren Felder auszufüllen. Um dieses Problem zu beheben, gehen Sie zu dem Ereignis, das nach leeren Feldern unter Blocks sucht, und fügen Sie dieses Else-Ereignis hinzu:

Ereignis: Bedingung: System> Else Action: Funktion> Aufruf Funktion Name = "FindMatches"

Ihr Code sollte so aussehen:


Diese else-Anweisung bedeutet, dass immer dann, wenn keine leeren Felder gefunden werden, überprüft wird, ob Gruppen vorhanden sind, die gelöscht werden sollen. Dieses Ereignis wird automatisch ausgeführt, wenn Blöcke in neue Positionen geraten, da es von einer Else-Anweisung aktiviert wird, die mit dieser Prüfung verbunden ist, und wird nur ausgelöst, wenn alle Blöcke sicher eingesteckt sind.

Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, werden Sie feststellen, dass Sie jetzt Ketten von Blöcken erstellen können, indem Sie Blöcke so zerstören, dass Gruppen gebildet werden, wenn die verbleibenden Blöcke fallen. Darüber hinaus werden Sie feststellen, dass beim ersten Start des Spiels alle zuerst erstellten Gruppen ebenfalls zerstört werden. Wie ich bereits im vorherigen Tutorial gesagt habe, werden wir letztendlich vorgefertigte Spiele eliminieren, sodass dieses Problem am Ende keine Rolle spielt.

Blöcke aus dem ursprünglichen Layout entfernen

Schließlich müssen wir noch etwas tun, bevor wir unser Schwerkraftsystem als vollständig betrachten können. Je nachdem, wo Sie das ursprüngliche Block-Sprite platziert haben, als Sie das erste Lernprogramm abgeschlossen haben, stellen Sie möglicherweise fest, dass es beim Starten des Spiels fällt und sichtbar wird.

Wenn Sie nicht wissen, was ich meine, gehen Sie zu Layout 1, Stellen Sie die Position Ihres Block-Sprites auf 521, -32, und führe das Spiel aus. Wenn Sie das Spiel spielen, sollten Sie das ursprüngliche Blockland an der Position sehen, die ich im Bild unten hervorgehoben habe:


Wie Sie im obigen Bild sehen können, fällt der ursprüngliche Block aus seiner Position außerhalb des Bildschirms und wird sichtbar. Wir wollen das nicht, weil es uns später nur Probleme bereiten wird. Um dieses kleine Problem zu lösen, fügen wir dem Projekt eine Aktion hinzu Beim Start des Layouts Ereignis, bei dem Blöcke gelöscht werden, die sich beim ersten Laden im Layout befinden.

Aktion: Blockieren> Zerstören

Ihre Veranstaltung sollte jetzt so aussehen:


Wenn Sie jetzt das Spiel ausführen, sollten Sie den Block nicht mehr sehen. Sie fragen sich vielleicht, warum wir den Block nicht einfach aus dem Layout gelöscht haben, so dass wir uns überhaupt nicht um dieses Problem kümmern müssen. Der Grund, warum wir dies nicht getan haben, ist, dass Construct 2 keine Kopien eines beliebigen Objekttyps mit Ereignissen erstellen kann, es sei denn, es gibt bereits eine Instanz dieses Objekttyps im Spiel, wenn er zum ersten Mal geladen wird. Wenn Sie es innerhalb eines Ereignisses löschen, wird es entfernt, sodass es später nicht mehr zum Problem wird, und wir können so viele Blöcke erzeugen, wie wir durch Code benötigen.


Fazit

Wir haben in diesem Tutorial viele Themen behandelt, und obwohl wir noch mehr tun können, ist es meiner Meinung nach wichtig, eine Pause einzulegen und diese Informationen einsinken zu lassen. In der nächsten Folge werden wir ein paar kleine Probleme beheben Der fantastische Fließkomma-Text, den Sie möglicherweise bemerkt haben, befindet sich in der endgültigen Demo und richtet das Verkettungssystem ein.

Ich hoffe, Sie haben viel aus diesem Teil der Serie herausgeholt und ich sehe Sie nächste Woche wieder hier.