Machen Sie ein Match-3-Spiel in Construct 2 Beseitigen Sie vorgefertigte Matches

Im vorigen Tutorial haben wir endlich unser Spiel in Bewegung gesetzt und den Blöcken Bewegung hinzugefügt. Darüber hinaus haben wir ein rudimentäres Schwierigkeitssystem geschaffen, um das Spiel schwieriger zu machen, je länger der Spieler spielt.

Mit diesen beiden Features im Spiel können wir das System implementieren, mit dem vorgefertigte Matches vom Board ausgeschlossen werden. Obwohl dies nicht der letzte Artikel in der Serie ist, ist dies das letzte wichtige System, das wir implementieren müssen - machen Sie es sich also bequem, denn wir haben uns die Arbeit erledigt.


Final Game Demo

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




Schnelle Korrekturen

Bevor wir mit dem Hauptteil dieses Tutorials beginnen, möchte ich eine Minute Zeit nehmen, um zwei Probleme zu beheben, die ich beim Schreiben des vorherigen Tutorials entdeckt habe.

Matching

Das erste Problem, auf das ich mich beziehe, erscheint in dem Szenario, das Sie unten sehen können:

In dieser Situation, wenn Sie ziehen Block B Auf den grünen Punkt sollte er wegen der leeren Felder unter dem Punkt fallen und schließlich an der markierten Stelle landen C. In den meisten Szenarien wird dies passieren und das Spiel wird normal funktionieren. In einigen Szenarien wird das Spiel stattdessen eine Übereinstimmung in dem kurzen Moment erkennen, in dem Block B ist neben der Gruppe EIN und es wird am Ende alle drei Blöcke zerstören.

Dieses Problem ist nicht exklusiv für dieses Szenario und kann sich auch dann darstellen, wenn Sie in dem Szenario, das ich unten hervorgehoben habe, dasselbe tun.

Wenn wir das nicht beheben, erhält der Spieler Punkte und Punkte für eine Reihe von Spielen, die er niemals beabsichtigt hatte, und könnte verwirrt sein, warum so viele Blöcke unerwartet verschwinden.

Zum Glück ist dies jedoch ein einfaches Problem, das zu beheben ist. Um dieses Problem zu lösen, erstellen wir ein neues Globale Variable namens Übereinstimmungen möglich was bestimmt, ob Übereinstimmungen gemacht werden können, und ein neues Ereignis, das erkennt, wenn ein Block "fällt" und modifiziert wird Übereinstimmungen möglich um es so zu machen, dass keine Übereinstimmungen gemacht werden können, während dies geschieht.

Zuerst erstellen wir die globale Variable:

Globale Variable: MatchesPossible Type = Number Initial Value = 1

Ihre neue Variable sollte so aussehen:

Jetzt werden wir das Ereignis erstellen, auf das beim Blockieren eines Blocks gewartet wird:

Ereignis: Bedingung: Invertieren: Blockieren> Überlappt sich beim Offset Objekt = Blockversatz X = 0 Offset Y = 8 Bedingung: Blockieren> Y-Vergleich vergleichen = Weniger oder gleich Y-Koordinate = SPAWNY Aktion: System> Wert setzen Variable = MatchesPossible Wert = 1

Dieses Ereignis bewirkt, dass ein Block leer ist, wenn ein Block unter ihm gefunden wird Übereinstimmungen möglich ist eingestellt auf 1, Bedeutungsübereinstimmungen sind nicht möglich. Sie werden auch feststellen, dass die Y-Position des Blocks überprüft wird. Dadurch wird sichergestellt, dass sich der Block nicht in der untersten Blockreihe befindet, in der sich immer ein leerer Platz befindet.

Als nächstes brauchen wir ein Ereignis, das setzt MKatchesMöglich zurück zu 0 wenn keine Blöcke einen leeren Raum unter sich haben. Dieses zweite Ereignis basiert auf einer Else-Bedingung:

Ereignis: Bedingung: System> Else Aktion: System> Wert setzen Variable = MatchesPossible Wert = 0

Stellen Sie sicher, dass dieses Ereignis unmittelbar auf das erste Ereignis folgt, damit die Else-Anweisung korrekt verwendet wird.

Ihre zwei neuen Events sollten so aussehen:

Schließlich fügen wir eine neue Bedingung hinzu CheckMatches damit es sich anschaut Übereinstimmungen möglich um festzustellen, ob eine Übereinstimmung möglich ist. Fügen Sie diese Bedingung dem ersten Funktionsaufruf des hinzu CheckMatches Veranstaltung.

Bedingung: System> Variable vergleichen Variable = MatchesPossible Vergleich = Equal to Vale = 0

Mit der Bedingung hinzugefügt, Ihre CheckMatches Das Event sollte jetzt so aussehen:

Im Gegensatz zu den meisten Problemen, auf die wir bisher gestoßen sind, wird dieses Problem ziemlich inkonsistent dargestellt. Dies bedeutet, dass wir nicht wirklich testen können, ob wir das Problem behoben haben. Wir können nur testen, ob andere Probleme aufgetreten sind. Wenn Sie das Spiel jetzt spielen, sollten Sie feststellen, dass durch diese Bedingung keine neuen Probleme verursacht wurden.

Punkte

Das zweite Problem, das ich beheben wollte, bevor wir etwas Neues hinzufügen, bezieht sich auf das Punktesystem.

Während der Arbeit an dem Projekt für dieses Lernprogramm bemerkte ich, dass das Punktesystem aufgrund meines Verhaltens etwas seltsam war und dem Spieler vier oder fünf Mal so viele Punkte gab, wie er für jedes Spiel erhalten sollte. Obwohl ich nicht feststellen konnte, welche Änderung ich veranlasst hatte, war dies der Grund für das Problem GivePoints Funktion wurde tatsächlich mehrfach aufgerufen, da die Blöcke nicht sofort zerstört wurden. Glücklicherweise kann dies wie unsere letzte Ausgabe leicht behoben werden.

Um dies zu beheben, erstellen wir eine neue Variable, die dem System mitteilt, ob es Punkte geben kann. Dann, wann immer wir das benutzen wollen GivePoints Funktion ändern wir auch die Variable, um sicherzustellen, dass das Ereignis nur einmal ausgelöst wird. Sobald die Punkte vergeben sind, werden wir die Variable noch einmal ändern, damit beim nächsten Versuch, Punkte zu vergeben, kein Problem mehr auftritt.

Erstellen Sie zuerst eine aufgerufene globale Variable Punkte gegeben:

Globale Variable: PointsGiven Type = Number Initial Value = 0

Deine Variable sollte folgendes mögen:

Als nächstes werden wir den Teil von ändern FindMatches Funktion, die tatsächlich die Punkte durch Hinzufügen einer neuen Bedingung und zwei neuen Aktionen ergibt.

Bedingung: System> Variable vergleichen Variable = PunkteGegebener Vergleich = Gleichwertig = 0

Fügen Sie nun diese Aktion am Anfang der Aktionsliste hinzu:

Aktion: System> Wert setzen Variable = PointsGiven Value = 1

Fügen Sie diese Aktion am Ende der Aktionsliste hinzu:

Aktion: System> Wert setzen Variable = PointsGiven Value = 0

Das Event sollte jetzt so aussehen:

Mit diesen Änderungen haben wir es so geschafft, das Event anzurufen GivePoints läuft nur wenn der Punkte gegeben Variable ist 0. Da setzen wir sofort den Wert auf 1 Wenn wir das Event starten, verhindert dies, dass das Event mehr als einmal ausgelöst wird, und stellt sicher, dass der Spieler die korrekte Anzahl an Punkten erhält.

Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, sollten Sie für jedes Spiel, das Sie machen, die richtige Anzahl an Punkten erhalten, auch wenn Sie dieses Problem noch nicht hatten.


Eliminierung vorgefertigter Übereinstimmungen

Nun, da wir diese Korrekturen aus dem Weg geräumt haben, können wir mit dem Erstellen eines Systems fortfahren, das Übereinstimmungen beseitigt, die vom System erzeugt werden, wenn es den von ihm erstellten Blöcken zufällig Farben zuweist.

Das Problem, das wir jetzt haben, ist, dass die Blockfarben völlig zufällig sind. Daher ist es nicht ungewöhnlich, dass Sie das Spiel starten und sofort eine Reihe von Übereinstimmungen sehen. Dies ist ein Problem, weil dies die ersten Sekunden des Spiels für jemanden, der noch nie zuvor gespielt hat, sehr verwirrend machen kann und weil es dem Spieler Punkte gibt, die er nicht verdient hat.

Um das Problem zu lösen, erstellen wir eine Funktion, die jeden Block betrachtet und dann prüft, ob der Block die gleiche Farbe wie seine Nachbarn hat. Wenn er dieselbe Farbe wie sein Nachbar hat, ändert er die Farbe dieses Blocks so lange, bis er mit keinem der Blöcke mehr übereinstimmt, die ihn umgeben.

Damit dieses System funktioniert, müssen wir auch mehrere Unterstützungsfunktionen und Ereignisse erstellen und der Instanz eine neue Instanzvariable hinzufügen Block Objekt.

Damit es funktioniert

Erstellen Sie zunächst eine neue Instanzvariable für die Block Objekt:

Instanzvariable: BlockID Typ = Number Anfangswert = 0

Diese Variable wird verwendet, um einen Block leicht zu identifizieren, sodass wir einige Funktionen genau angeben können, welchen Block wir betrachten möchten, unabhängig von seiner Position.

Bevor wir fortfahren, müssen wir auch diese Variable verwenden. Gehe zum Beim Start des Layouts Ereignis, das die Blöcke erstellt und eine neue Aktion vor der zunehmenden Aktion hinzufügt NumBlocks:

Aktion: Blockieren> Wert setzen Instanzvariable = BlockID Wert = NumBlocks

Ihr Block-Spawn-Event sollte jetzt so aussehen:

Als Nächstes müssen wir eine Funktion erstellen, die die X- und Y-Position eines Blocks einnimmt, und uns sagen, welche Farbe der Block hat:

Ereignis: Bedingung: Funktion> Ein Funktion Name = "GetBlockColor" Unterereignis: Bedingung: Block> X-Vergleich vergleichen = Gleich X Koordinate = Function.Param (0) Bedingung: Block> Vergleich Y = Vergleich mit Y Co -ordinate = Function.Param (0) Aktion: Funktion> Rückgabewert setzen Wert = Block.Color Unterereignis: System> Else Aktion: Funktion> Rückgabewert setzen Wert = -1

Die Funktion sollte so aussehen, wenn sie fertig ist:

Nun, da wir eine Funktion haben, die uns die Farbe eines Blocks mitteilen kann, erstellen wir die Funktion, die einen Block tatsächlich betrachtet und ermittelt, ob er benachbarte Blöcke mit derselben Farbe hat.

Die Funktionsweise dieser Funktion ist recht einfach.

  • Zuerst werden wir eine übergeben BlockID in die Funktion.
  • Wenn gerade ein Block damit ist BlockID, Die Funktion betrachtet die vier benachbarten Blöcke und bestimmt, ob der Block, den er betrachtet, die gleiche Farbe hat wie seine Nachbarn.
  • Wenn ein Nachbar der gleichen Farbe gefunden wird, ändert sich die Farbe des Blocks, den er betrachtet, und die Farbe wird solange geändert, bis der Block eine andere Farbe als seine Nachbarn hat.

Bevor wir dieses Ereignis erstellen können, müssen wir eine neue globale Variable erstellen. In der Funktion verwenden wir eine While-Schleife, um zu bestimmen, ob die Farbe des Blocks geändert werden muss. Die zu erstellende Variable ist die Variable, die die While-Schleife verwendet, um zu bestimmen, ob sie weiter ausgeführt werden muss:

Globale Variable: HasMatchingNeighbor Type = Number Initial Value = 0

Spitze:Das Event, das wir durchführen werden, enthält ein OR-basiertes Event. Wenn Sie noch nie einen Ereignisblock mit einem Oder-Attribut erstellt haben, müssen Sie den Ereignisblock wie gewohnt erstellen und dann mit der rechten Maustaste auf den gesamten Block klicken und wählen Mach 'oder' blockieren. Im Gegensatz zu einem Standard-Ereignisblock, der erfordert, dass alle Bedingungen erfüllt sind, bevor er ausgelöst wird, wird ein OR-Block ausgelöst, wenn irgendein Bedingung ist erfüllt.

Also machen wir das Event:

Ereignis: Bedingung: Funktion> Ein Funktion Name = "RemoveSpawnedMatches" Unterereignis: Bedingung: Block> Vergleiche Instanzvariable Instanzvariable = BlockID Vergleich = Gleichwertig = Function.param (0) Aktion: System> Wert setzen Variable = HasMatchingNeighbor Wert = 1 Unterereignis: Bedingung: System> While Bedingung: System> Compare variable Variable = HasMatchingNeighbor-Vergleich = Gleichwert = 1 Unterereignis: Bedingung: Block: Vergleiche Instanzvariable Instanzvariable = Farbvergleich = Gleichwert = Funktion. Aufruf ("GetBlockColor", Block.X - (Block.Width + 2), Block.Y) Aktion: Blockieren> Wert setzen Instanzvariable = Farbe Wert = Etage (Random (1,7)) Aktion: System> Wert setzen Variable = HasMatchingNeighbor Wert = 1 Unterereignis: Bedingung: System> Else Bedingung: Block> Instanzvariable vergleichen Instanzvariable = Farbvergleich = Gleichwert = Function.Call ("GetBlockColor"), Block.X + (Block.Width + 2) , Block.Y) Aktion: Blockieren> Wert setzen Instanzvariable = Farbe Wert = Boden (zufällig (1,7)) Aktion: System> Set value Variable = HasMatchingNeighbor Wert = 1 Unterereignis: Bedingung: System> Else Bedingung: Block> Instanzvariable vergleichen Instanzvariable = Farbvergleich = Gleichwertig = Function.Call ("GetBlockColor", Block.X, Block.Y - (Block.Width + 2)) Aktion: Blockieren> Wert setzen Instanzvariable = Farbe Wert = Etage (zufällig (1,7)) Aktion: System> Wert setzen Variable = HasMatchingNeighbor Wert = 1 Unterereignis: Bedingung : System> Else Bedingung: Block> Instanzvariable vergleichen Instanzvariable = Farbvergleich = Gleichwert = Function.Call ("GetBlockColor", Block.X, Block.Y + (Block.Width + 2)) Aktion: Blockieren> Setzen value Instanzvariable = Farbe Wert = Etage (zufällig (1,7)) Aktion: System> Wert setzen Variable = HasMatchingNeighbor Wert = 1 Unterereignis: Bedingung: System> Else Aktion: System> Set value Variable = HasMatchingNeighbor Wert = 0

Ihre Veranstaltung sollte so aussehen:


Wie funktioniert diese Funktion genau??

Das erste, was es tut, ist nach einem zu suchen Block mit dem BlockID dass das System eingegangen ist. Wenn es das findet Block es setzt den Wert von HasMatchingNachbarn zu 1 und führt dann die While-Schleife aus.

Da läuft die While-Schleife nur, wenn HasMatchingNachbarn ist 1, das ist der Wert, auf den es sich bezieht. Während der While-Schleife wird geprüft, ob ein Nachbar vorhanden ist Block Links, rechts, darüber oder darunter ist die gleiche Farbe wie bei Block wir schauen uns an Wenn es einen passenden findet Block im irgendein von diesen Positionen weist er zufällig eine neue Farbe zu Block und führt dann den Test erneut aus HasMatchingNachbarn ist eingestellt auf 1. Wenn es endlich eine Farbe für das findet Block das passt zu keinem seiner Nachbarn, es ändert den Wert von HasMatchingNachbarn zu 0 so dass die While-Schleife endet und das Programm weitergehen kann.

Jetzt müssen wir diese Funktion im Spiel implementieren. Dazu müssen wir zwei neue Variablen und zwei neue Funktionen erstellen. Beginnen wir mit den Variablen.

Globale Variable: CheckStartingMatches Type = Number Value = 0
Globale Variable: CheckNewestRow Type = Number Value = 0

Ihre Variablen sollten so aussehen:

Die zwei Variablen, die wir gerade erstellt haben, werden verwendet, um die zwei Ereignisse auszulösen, die wir gerade erstellen. Die Ereignisse selbst werden verwendet, um die Blöcke unmittelbar nach ihrer Erstellung zu durchlaufen und jeden Block in die Datenbank zu senden RemoveSpawnedMatches Funktion.

Der Grund, warum wir nicht nur anrufen RemoveSpawnedMatches Die Funktion unmittelbar nach dem Erstellen des Blocks besteht darin, dass das Blockraster vollständig sein muss, damit die Funktion ordnungsgemäß funktioniert. Anstatt die Funktion nur direkt beim Erstellen von Blöcken aufzurufen, lösen wir stattdessen ein Ereignis aus, das die Blöcke durchlaufen kann, und ruft die Funktion nach der Generierung des Gitters auf.

Das erste Event ist speziell für das Durchlaufen der ersten Blockgruppe gedacht:

Ereignis: Bedingung: System> Variable vergleichen Instanzvariable = CheckStartingMatches Vergleich = Gleichwert = 1 Bedingung: System> Für Name = "Blöcke" Startindex = 0 Endindex = NumBlocks-1 Aktion: Funktion> Aufruf Funktionsname = "RemoveSpawnedMatches" Parameter 0 = loopindex ("Blocks") SubEvent: Bedingung: System> Zwei Werte vergleichen Erster Wert = Loopindex ("Blocks") Vergleich = Gleicher zweiter Wert = NumBlocks-1 Aktion: System> Variable setzen Instanzvariable = CheckStartingMatches Wert = 0

So sollte Ihre Veranstaltung aussehen:

Das zweite Ereignis dient speziell zum Überprüfen neuer Blockzeilen, wenn diese erstellt werden:

Ereignis: Bedingung: System> Variable vergleichen Instanzvariable = CheckNewestRow Vergleich = Gleichwert = 1 Bedingung: System> Für Name = "Blöcke" Startindex = NumBlocks-9 Ende Index = NumBlocks-1 Aktion: Funktion> Aufruf Funktionsname = " RemoveSpawnedMatches "Parameter 0 = loopindex (" Blocks ") SubEvent: Bedingung: System> Zwei Werte vergleichen Erster Wert = Loopindex (" Blocks ") Vergleich = Gleicher zweiter Wert = NumBlocks-1 Aktion: System> Variable setzen Instanzvariable = CheckNewestRow-Wert = 0

So sollte das zweite Event aussehen:

Implementierung

Wenn beide Funktionen vorhanden sind, müssen wir sie jetzt nur noch implementieren. Gehen Sie zu dem anfänglichen Ereignis, das die Blöcke bildet, das Beim Start des Layouts Veranstaltung. Wir werden diesem Ereignis ein Unterereignis hinzufügen, das der Nachricht mitteilt CheckStartingMatches Ereignis zum Aktivieren.

Unterereignis: Bedingung: System> Zwei Werte vergleichen Erster Wert = Schleifenindex ("X") Vergleich Zweiter Wert: 7 Bedingung: System> Zwei Werte vergleichen Erster Wert = Schleifenindex ("Y") Vergleich Zweiter Wert: 3 Aktion: System> Wert setzen Instanzvariable = CheckStartingMatches Wert = 1

Ihre Veranstaltung sollte jetzt so aussehen:

Dieses Unterereignis wartet darauf, wann die verschachtelte For-Schleife beendet ist, und ändert dann den Wert von CheckStartingMatches Variable, um das entsprechende Ereignis zu aktivieren.

Wir werden jetzt fast das gleiche Unterereignis machen und es mit dem verknüpfen SpawnNewBlocks Funktion.

Unterereignis: Bedingung: System> Zwei Werte vergleichen Erster Wert = Schleifenindex ("X") Vergleich Zweiter Wert: 7 Aktion: System> Wert setzen Instanzvariable = CheckNewestRow Wert = 1

SpawnNewBlocks sollte jetzt so aussehen:

Dieses Unterereignis hat dieselbe Funktion wie das vorherige, außer dass es das andere von uns erstellte Ereignis aktiviert. Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, sollten Sie feststellen, dass zu Beginn des Spiels keine Übereinstimmungen mehr auftreten.


Fazit

In diesem Tutorial haben wir nicht zu viele Änderungen am Spiel vorgenommen, aber die, die wir gemacht haben, waren sehr wichtig.

An diesem Punkt halte ich es für am besten, wenn wir jetzt aufhören und die letzten beiden Spielelemente für das nächste Tutorial speichern, wo wir Ketten / Combos und den Game Over-Bildschirm abdecken werden. Dies wird der letzte Teil der Serie sein, daher werde ich auch über einige Spielmechaniken sprechen, die wir in diesen Tutorials nicht behandeln werden, und Ihnen einen Rat geben, wie Sie diese Systeme selbst erstellen können.

Wenn Sie einen Vorsprung in die Inhalte der nächsten Woche erhalten möchten, schauen Sie sich an, wie Sie erkennen können, wann der Game Over-Bildschirm angezeigt wird, basierend auf der Position oder Höhe einiger Blöcke. Alternativ können Sie darüber nachdenken, wie Sie feststellen können, wann der Spieler eine Kettenreaktion ausführt, die dazu führt, dass mehr als eine Gruppe gebildet wird.

Was auch immer Sie tun, ich hoffe, Sie nächste Woche wieder hier zu sehen, um die letzte Folge der Serie zu sehen.