Machen Sie ein Match-3-Spiel in Construct 2 Match Detection

Bisher wurden in dieser Serie die Grundlagen für die Einrichtung eines Match-3-Spiels und die Implementierung der ersten Gameplay-Elemente wie Block-Swapping behandelt. In diesem Tutorial bauen wir darauf auf und beginnen zu erkennen, wann der Spieler ein Match gemacht hat.


Final Game Demo

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




1. Ein Match finden

Im Moment werden wir nur eine Basisversion des Abgleichsystems implementieren, wobei wir uns darauf konzentrieren, herauszufinden, wann Übereinstimmungen vorhanden sind, und übereinstimmende Blöcke zerstören. In späteren Artikeln werden wir das System weiterentwickeln und weiterentwickeln.

Spitze: Sie sollten wissen, wie eine rekursive Funktion funktioniert, wenn Sie es noch nicht wissen. Im Wesentlichen ist es eine Funktion, die sich selbst aufruft. Rekursive Funktionen können ähnlich wie Schleifen funktionieren. Da sie jedoch auch Variablen aufnehmen und zurückgeben können, haben sie viel mehr Einsatzmöglichkeiten als Schleifen.

Wie beim vorherigen Tutorial möchte ich zuerst die Funktionsweise des Systems besprechen und dann versuchen, es zu erstellen.

  • Das Match-System durchläuft jede Instanz von Block Objekt.
  • Für jeden Block, Er übergibt die Farbe und Position des Blocks, den er betrachtet, an eine rekursive Funktion, die den horizontalen oder vertikalen Nachbarn betrachtet und bestimmt, ob sie dieselbe Farbe haben.
  • Wird eine Übereinstimmung gefunden, wird die Funktion erneut mit der Position und Farbe des neuen Blocks anstelle des ursprünglichen Blocks aufgerufen.
  • Dies wird solange fortgesetzt, bis keine Übereinstimmung gefunden wird. An diesem Punkt wird geprüft, wie viele Übereinstimmungen gefunden wurden.
  • Wenn drei oder mehr Übereinstimmungen gefunden wurden, werden alle Blöcke angezeigt, die als gerade angesehen wurden Abgestimmt mit dem Ist abgestimmt Instanzvariable, die wir in einem der vorherigen Tutorials erstellt haben; sonst tut es nichts.
  • Sobald alle Blöcke geprüft wurden, wird die Funktion jeden Block, der als Übereinstimmung markiert ist, zerstören.

Erstens brauchen wir ein Ereignis, das jedes durchlaufen kann Block. So wie ich das System aufgebaut habe, durchläuft es tatsächlich die Blöcke zweimal: einmal für vertikale Übereinstimmungen und einmal für horizontale Übereinstimmungen. Abhängig von der Prüfung wird eine andere Funktion verwendet, um tatsächlich nach dem Treffer zu suchen.

Das allererste, was wir tun müssen, ist eine Globale Variable Um zu verfolgen, wie viele passende Blöcke wir in einer bestimmten Iteration gefunden haben:

Globaler Variablenname: "NumMatchesFound" Type = Number Value = 0

Jetzt machen wir das Veranstaltung das wird durch die Blöcke iterieren:

Ereignis: Funktion> Ein Funktion Name: "FindMatches" Unterereignis: System> Für jedes Objekt: Block Aktion: System> Wert setzen NumMatchesFound = 1 Aktion: Funktion> Aufruf Funktion Name: "CheckMatchesX" Parameter 0: Block.X Parameter 1 : Block.Y Parameter 2: Block.Color-Unterereignis: System> Compare Variable NumMatchesFound> = 3 Aktion: Blockieren> Set Boolean IsMatched = True Unterereignis: System> Für jedes Objekt: Block Aktion: System> Wert setzen NumMatchesFound = 1 Aktion: Funktion> Funktion aufrufen Name: "CheckMatchesY" Parameter 0: Block.X Parameter 1: Block.Y Parameter 2: Block.Color Unterereignis: System> Compare Variable NumMatchesFound> = 3 Aktion: Block> Set Boolean IsMatched = True Unterereignis: Block> Ist eine boolesche Instanzvariable festgelegt System> Wait Second = 0.1 Block> Destroy

Ihr Code sollte so aussehen:


In diesem Fall durchlaufen wir jeden Block und senden ihn in CheckMatchesX oder CheckMatchesY, die Funktionen, die prüfen, ob der benachbarte Block übereinstimmt.

Um den Block in die Funktion zu senden, übergeben wir den Funktionen drei verschiedene Parameter:

  • Parameter 0 ist die X-Position des Blocks
  • Parameter 1 ist die Y-Position des Blocks
  • Parameter 2 ist die Farbe.

Nachdem jeder Block an eine der Funktionen gesendet wurde und die Funktion abgeschlossen ist, wird geprüft NumMatchesFound um zu sehen, ob drei oder mehr übereinstimmende Blöcke gefunden wurden, und beschriftet die Blöcke dann mit Abgestimmt wenn es tat.

Zum Schluss jeder Block, der als Sein markiert ist Abgestimmt Wird nach 0,1 Sekunden zerstört. Diese warten Eine Anweisung gibt dem Spiel die Möglichkeit, die Bilder für die Blöcke auf das Bild umzuschalten, das angibt, dass sie übereinstimmen, und dem Spieler einen Moment zu geben, um diese Änderung zu bemerken.

(Während Sie das entfernen konnten warten Eine Aussage ohne negativen Einfluss auf das Gameplay, macht das Abgleichen für den Spieler leichter verständlich und verlangsamt das Spiel gerade so weit, dass der Spieler leicht den Überblick behalten kann.)


2. Die zwei Kontrollfunktionen

Als nächstes müssen wir das machen CheckMatchesX und CheckMatchesY Funktionen. Diese Funktionen funktionieren ähnlich wie die oben beschriebenen Iteratoren, da es eine Version gibt, um horizontale Übereinstimmungen zu überprüfen, CheckMatchesX, und eine für vertikale Übereinstimmungen, CheckMatchesY.

Horizontale Prüfungen

Lassen Sie uns zunächst die horizontale Überprüfungsfunktion erstellen:

Ereignis: Funktion> Ein Funktion Name: "CheckMatchesX" Unterereignis: Bedingung: Block> Compare XX = Function.Param (0) + (Block.Width + 2) Bedingung: Block> Compare YY = Function.Param (1) Bedingung : Block> Vergleiche Instanzvariable Color = Function.Param (2) Aktion: System> Zu Variable hinzufügen = NumBlocks Wert = 1 Aktion: Funktion> Funktion aufrufen Name: "CheckMatchesX" Parameter 0: Function.Param (0) + (Block. Width + 2) Parameter 1: Function.Param (1) Parameter 2: Function.Param (2) Unterereignis: System> Compare Variable NumMatchesFound> = 3 Aktion: Blockieren> Set Boolean IsMatched = True

Ihr Code sollte so aussehen:


Also, was macht diese Funktion??

  • Zunächst wird geprüft, ob links neben dem Block, den wir übergeben haben, sogar ein Nachbarblock vorhanden ist.
  • Sobald die Funktion bestätigt, dass sich an der benachbarten Stelle ein Block befindet, prüft sie, ob sie dieselbe Farbe wie der Block hat, den wir übergeben haben.
  • Wenn ja, steigt es NumMatchesFound um eins, und übergibt den neu gefundenen Block genau wie beim Original an die Funktion.
  • Dies wird fortgesetzt, bis ein Block gefunden wird, der nicht die gleiche Farbe wie das Original hat. An diesem Punkt wird geprüft, ob genügend passende Blöcke gefunden wurden, um eine Gruppe zu erstellen, und die Blöcke werden als übereinstimmend bezeichnet.

Vertikale Prüfungen

Lassen Sie uns nun eine andere Version dieser Funktion erstellen, die dasselbe für vertikale Übereinstimmungen tut. Das wird unser sein CheckMatchesY Funktion. Sie können entweder die ursprüngliche Funktion kopieren und alle entsprechenden Änderungen vornehmen oder einfach von Grund auf neu erstellen. In beiden Fällen sehen Sie, wie Ihre Funktion aussehen soll, wenn sie fertig ist:

Ereignis: Funktion> Ein Funktion Name: "CheckMatchesY" Unterereignis: Bedingung: Block> Compare XX = Function.Param (0) Bedingung: Block> Compare YY = Function.Param (1) + (Block.Width + 2) Bedingung : Block> Vergleiche Instanzvariable Color = Function.Param (2) Aktion: System> Zu Variable hinzufügen = NumBlocks Wert = 1 Aktion: Funktion> Funktion aufrufen Name: "CheckMatchesY" Parameter 0: Function.Param (0) Parameter 1: Funktion .Param (1) + (Block.Width + 2) Parameter 2: Function.Param (2) Unterereignis: System> Compare Variable NumMatchesFound> = 3 Aktion: Blockieren> Set Boolean IsMatched = True

Ihr Code sollte so aussehen:



3. Suche eigentlich nach Schecks

Zum Schluss müssen wir das tatsächlich anrufen FindMatches Funktion. Gehe zum SwapBlocks Funktion und fügen Sie am Ende der Funktion ein neues Unterereignis hinzu:

Ereignis: Funktion> Unterereignis: Aktion: Funktion> Funktion aufrufen Name: "FindMatches"

Sie werden feststellen, dass dieses Unterereignis keine Bedingungen hat. Wenn Sie noch nie ein Unterereignis wie dieses gemacht haben, erstellen Sie einfach ein Unterereignis mit einer beliebigen Bedingung, da Sie bei der Erstellung eines Unterereignisses eine Bedingung angeben und die Bedingung dann löschen müssen Unterereignis Auf diese Weise stellen Sie sicher, dass das Unterereignis immer ausgeführt wird.

Ihre SwapBlocks Die Veranstaltung sollte jetzt so aussehen:

Wenn Sie das Spiel zu diesem Zeitpunkt ausführen, werden Sie feststellen, dass die Blöcke bei Spielen zerstört werden. Sie werden auch bemerken, dass alle Matches, die zu Spielbeginn vorhanden sind, nicht verschwinden, bis Sie einen Tausch vornehmen. Das ist so, weil wir niemals das nennen FindMatches Funktion, nachdem wir das Blockraster erstellt haben.

Der Grund, warum wir diesen Code nicht hinzugefügt haben, ist, dass es in der endgültigen Version eine weitere Funktion gibt, die verhindert, dass Übereinstimmungen wie diese automatisch generiert werden. Es gibt also wirklich keinen Grund, sich um dieses Problem zu sorgen. (Aber bitte rufen Sie uns an FindMatches Funktion früher, wenn Sie möchten.)


4. Konsolidierung der Schecks

Zu diesem Zeitpunkt haben wir ein ziemlich starkes Abgleichsystem, aber das Problem ist, dass unser Code überflüssig ist. Derzeit haben wir zwei verschiedene Funktionen, die prüfen, ob es einen passenden Nachbarn gibt, und der einzige Unterschied besteht darin, dass eine vertikal und die andere horizontal geprüft wird.

Da die kostenlose Version von Construct 2 die Anzahl der möglichen Events begrenzt, ist dies definitiv eine Verschwendung. Um dies zu lösen, erstellen wir eine neue Version der Funktion, die beide Prüfungen durchführen kann.

Wenn Sie die Funktion betrachten, werden Sie feststellen, dass der einzige Unterschied zwischen den beiden Versionen darin besteht, dass eine hinzugefügt wird Block.Width + 2 an die x-Position des Blocks und der andere fügt ihn der y-Position des Bocks hinzu. Das Hindernis, an dem wir vorbeikommen müssen, um diese Funktion zu einer einzigen Funktion zu machen, gibt der Funktion also die Möglichkeit, sie hinzuzufügen Block.Width + 2 nur zu X, oder nur Y, ohne mit einem Ob Anweisung oder mehrere Funktionen, da dazu mehr Ereignisse ausgeführt werden müssen.

Meine Lösung dafür ist nicht sehr komplex, aber es wird leichter zu verstehen sein, wenn wir sehen, dass es zusammenkommt. Wir werden es implementieren und ich werde erklären, wie es funktioniert, sobald wir alles in Aktion sehen können.

  1. Löschen Sie die CheckMatchesY Veranstaltung.
  2. Benennen Sie das um CheckMatchesX Veranstaltung einfach, CheckMatches.
  3. In der Funktion aufrufen für CheckMatchesX unter dem FindMatches Veranstaltung:
    1. Ändern Sie den Funktionsaufruf für CheckMatches anstatt CheckMatchesX.
    2. Hinzufügen Parameter 3.
      1. Wert = 1.
    3. Hinzufügen Parameter 4.
      1. Wert = 0.
  4. In der Funktion aufrufen für CheckMatchesY unter dem FindMatches Veranstaltung:
    1. Ändern Sie den Funktionsaufruf für CheckMatches anstatt CheckMatchesY.
    2. Hinzufügen Parameter 3.
      1. Wert = 0.
    3. Hinzufügen Parameter 4.
      1. Wert = 1.

Wie ich bald erklären werde, werden diese zusätzlichen Parameter sagen CheckMatches ob es sich um eine horizontale oder vertikale Prüfung handelt. Wenn wir reinschicken 1 zum Parameter 3, und 0 zum Parameter 4, Es ist ein horizontaler Check, und wenn wir einsenden 0 zum Parameter 3, und 1 zum Parameter 4, es ist eine vertikale Kontrolle.

Gehen Sie jetzt zurück zum CheckMatches funktionieren und ändern Sie die Bedingungen und Aktionen so, dass sie folgendermaßen aussehen:

Ereignis: Funktion> Ein Funktion Name: "CheckMatches" Unterereignis: Bedingung: Block> Compare XX = Function.Param (0) + ((Block.Width + 2) * Function.Param (3)) Bedingung: Block> Compare YY = Function.Param (1) + ((Block.Width + 2) * Function.Param (4)) Bedingung: Block> Instanzvariable vergleichen Color = Function.Param (2) Action: Block> Set Boolean IsMatched = True Action : Funktion> Funktion aufrufen Name: "CheckMatches" Parameter 0: Function.Param (0) + ((Block.Width + 2) * Function.Param (3)) Parameter 1: Function.Param (1) + ((Block. Width + 2) * Function.Param (4)) Parameter 2: Function.Param (2) Parameter 3: Function.Param (3) Parameter 4: Function.Param (4) Unterereignis: System> Compare Variable NumMatchesFound> = 3 Aktion: Blockieren> Set Boolean IsMatched = True

Das ist was dein FindMatches und CheckMatches Code sollte jetzt so aussehen:


Wie funktioniert das?

Also, was macht diese neue Version der Funktion tatsächlich??

Nun, wann immer Sie anrufen CheckMatches Sie senden jetzt zwei weitere Parameter und fügen nicht mehr hinzu Block.Width + 2 entweder zur x- oder zur y-Position, wird addiert (Block.Width + 2) * Function.Param (3) zur x-Position und (Block.Width + 2) * Function.Param (4) in die y-Position.

Da wird einer dieser beiden Parameter immer sein 1, und der andere wird immer sein 0, Dies bedeutet, dass entweder die x- oder die y-Position geändert wird - niemals beide!

Zum Beispiel, wenn wir reinkommen 1 zum Parameter 3, und 0 zum Parameter 4, dann fügt es hinzu (Block.Breite + 2) * 1, das ist einfach Block.Width + 2, zur x-Position und (Block.Breite + 2) * 0, welches ist 0, in die y-Position.

Hier ist ein schnelles Beispiel, um zu zeigen, was ich meine und wie es die Position des Blocks berechnet, an der er die Übereinstimmung prüfen wird. Nehmen wir an, in diesem Beispiel befindet sich der ursprüngliche Block (200, 200), und die Blöcke haben eine Breite von 40. Wenn wir also die Position des benachbarten vertikalen Blocks ermitteln wollen, würden die Formeln folgendermaßen aussehen:

  • X = 200 + ((Blockbreite + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200
  • Y = 200 + ((Blockbreite + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242

Wenn wir die Position des benachbarten horizontalen Blocks erhalten wollten, würden die Formeln folgendermaßen aussehen:

  • X = 200 + ((Blockbreite + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242
  • Y = 200 + ((Blockbreite + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200

Wenn Sie das Spiel jetzt ausführen, sollte das Spielsystem immer noch so funktionieren, wie es ursprünglich funktioniert hat, aber aus unserer Sicht ist es tatsächlich ein besseres System.


Fazit

Zu diesem Zeitpunkt ist unsere Übereinstimmungserkennungsfunktion noch unvollständig, aber wir haben in diesem Lernprogramm bereits eine Menge getan und ich denke, es ist wichtig, all das einzusinken, bevor wir etwas hinzufügen. In diesem Sinne werde ich diesen Artikel hier beenden. Schauen Sie sich die Demo in ihrer aktuellen Form an.

Im nächsten Artikel werden wir ein Punktesystem hinzufügen, das Matching-System verbessern und "Schwerkraft" hinzufügen, damit die Blöcke fallen, wenn Blöcke unter ihnen eliminiert werden.

Wenn Sie sich einen Überblick über den nächsten Artikel verschaffen möchten, sollten Sie sich überlegen, wie Sie feststellen würden, wenn sich unter einem Block ein Leerzeichen befindet. Schauen Sie sich das an Block> Überlappt sich beim Offset Funktion für die Inspiration!