Finora, questa serie ha coperto le basi della creazione di un gioco Match-3 e implementando gli elementi di gameplay iniziali come lo scambio di blocchi. In questo tutorial, svilupperemo tutto ciò e inizieremo a rilevare quando il giocatore ha fatto una partita.
Ecco una demo del gioco a cui stiamo lavorando in questa serie:
Per ora, implementeremo solo una versione di base del sistema di matching, concentrandoci sul trovare quando esistono corrispondenze e distruggere blocchi abbinati. Negli articoli successivi continueremo a sviluppare e far progredire il sistema.
Mancia: Dovresti leggere come funziona una funzione ricorsiva, se non lo sai già; essenzialmente, è una funzione che chiama se stessa. Le funzioni ricorsive possono funzionare in modo simile ai cicli, ma dato che possono anche contenere e restituire variabili, hanno molti più usi di quanto non facciano i loop.
Come per il tutorial precedente, desidero innanzitutto discutere di come funzionerà il sistema e quindi tentare di costruirlo.
Bloccare
oggetto. Bloccare
, passerà il colore e la posizione del blocco che sta osservando in una funzione ricorsiva, che guarderà al vicino orizzontale o verticale e determinerà se sono dello stesso colore. Matched
con il IsMatched
variabile di istanza creata in uno dei tutorial precedenti; altrimenti, non fa nulla. Per prima cosa, abbiamo bisogno di un evento che possa iterare attraverso ciascuno Bloccare
. Il modo in cui ho costruito il sistema, itera effettivamente attraverso i blocchi due volte: una volta per verificare le corrispondenze verticali e una volta per verificare le corrispondenze orizzontali. A seconda di quale controllo sta facendo, userà una funzione diversa per cercare effettivamente la corrispondenza.
La prima cosa che dobbiamo fare è fare un Variabile globale per tenere traccia di quanti blocchi di corrispondenza abbiamo trovato in una determinata iterazione:
Nome variabile globale: "NumMatchesFound" Tipo = Numero Valore = 0
Ora, facciamo il Evento che itererà attraverso i blocchi:
Evento: Funzione> On function Nome: "FindMatches" Sotto-evento: Sistema> Per ogni oggetto: Block Azione: Sistema> Imposta valore NumMatchesFound = 1 Azione: Funzione> Funzione chiamata Nome: "CheckMatchesX" Parametro 0: Block.X Parametro 1 : Block.Y Parametro 2: Block.Color Evento secondario: Sistema> Confronta variabile NumMatchesFound> = 3 Azione: Blocca> Imposta Booleano IsMatched = True Sotto-evento: Sistema> Per ogni oggetto: Blocca Azione: Sistema> Imposta valore NumMatchesFound = 1 Azione: Funzione> Funzione chiamata Nome: "CheckMatchesY" Parametro 0: Block.X Parametro 1: Block.Y Parametro 2: Block.Color Evento secondario: Sistema> Confronta variabile NumMatchesFound> = 3 Azione: Block> Imposta Boolean IsMatched = True Sub-Event: Block> Is Boolean set di variabili d'istanza System> Wait Second = 0.1 Block> Destroy
Il tuo codice dovrebbe assomigliare a questo:
In questo evento, iteriamo attraverso ogni blocco e inviandoli CheckMatchesX
o CheckMatchesY
, le funzioni che controlleranno se il blocco adiacente è una corrispondenza.
Per inviare il blocco nella funzione, passiamo le funzioni tre diversi parametri:
Dopo che ciascun blocco viene inviato in una delle funzioni e la funzione termina, verifica NumMatchesFound
per vedere se ha trovato tre o più blocchi corrispondenti, quindi etichetta i blocchi come Matched
se lo facesse.
Infine, ogni blocco contrassegnato come essere Matched
viene distrutto dopo che sono trascorsi 0,1 secondi. Questo aspettare
l'affermazione è lì per permettere al gioco di cambiare le immagini dei Blocks per l'immagine che indica che sono abbinati, e di dare al giocatore un momento per notare questo cambiamento.
(Mentre si potrebbe rimuovere il aspettare
dichiarazione senza influire negativamente sul gameplay, rende più semplice la comprensione per il giocatore, e rallenta il gioco quel tanto che basta affinché il giocatore possa facilmente tenere traccia di ciò che sta accadendo.)
Quindi dobbiamo fare il CheckMatchesX
e CheckMatchesY
funzioni. Queste funzioni funzioneranno in modo simile agli iteratori sopra, in quanto ci sarà una versione per il controllo delle corrispondenze orizzontali, CheckMatchesX
, e uno per le partite verticali, CheckMatchesY
.
Per prima cosa, costruiamo la funzione di controllo orizzontale:
Evento: Funzione> On function Nome: "CheckMatchesX" Sotto-evento: Condizione: Block> Compare XX = Function.Param (0) + (Block.Width + 2) Condizione: Block> Compare YY = Function.Param (1) Condizione : Blocca> Confronta variabile di istanza Colore = Funzione.Param (2) Azione: Sistema> Aggiungi a Variabile = NumBlocks Valore = 1 Azione: Funzione> Funzione chiamata Nome: "CheckMatchesX" Parametro 0: Function.Param (0) + (Block. Width + 2) Parametro 1: Function.Param (1) Parametro 2: Function.Param (2) Sotto-evento: System> Compare Variable NumMatchesFound> = 3 Azione: Block> Set Boolean IsMatched = True
Il tuo codice dovrebbe assomigliare a questo:
Quindi, cosa sta facendo questa funzione?
NumMatchesFound
da uno, e passa il blocco appena trovato nella funzione proprio come ha fatto per l'originale.Ora, facciamo un'altra versione di questa funzione che farà la stessa cosa per le corrispondenze verticali. Questo sarà il nostro CheckMatchesY
funzione. Puoi copiare la funzione originale e apportare tutte le modifiche appropriate, o semplicemente ricostruirla da zero; in entrambi i casi, ecco come deve apparire la tua funzione quando è finita:
Evento: Funzione> On function Nome: "CheckMatchesY" Evento secondario: Condition: Block> Compare XX = Function.Param (0) Condizione: Block> Compare YY = Function.Param (1) + (Block.Width + 2) Condizione : Blocca> Confronta variabile di istanza Colore = Funzione.Param (2) Azione: Sistema> Aggiungi a Variabile = NumBlocks Valore = 1 Azione: Funzione> Funzione di chiamata Nome: "CheckMatchesY" Parametro 0: Function.Param (0) Parametro 1: Funzione .Param (1) + (Block.Width + 2) Parametro 2: Function.Param (2) Sotto-evento: Sistema> Confronta variabile NumMatchesFound> = 3 Azione: Blocco> Imposta booleano IsMatched = True
Il tuo codice dovrebbe assomigliare a questo:
Infine, dobbiamo effettivamente chiamare il FindMatches
funzione. Vai al SwapBlocks
funzione e aggiungi un nuovo sotto-evento alla fine della funzione:
Evento: Funzione> Sotto-evento: Azione: Funzione> Funzione chiamata Nome: "FindMatches"
Noterai che questo sotto-evento in realtà non ha alcuna condizione. Se non hai mai fatto un evento secondario come questo prima, crea un evento secondario con qualsiasi condizione, poiché richiede di dare una condizione quando si effettua un evento secondario, quindi eliminare la condizione, ma lasciare il sub-evento. In questo modo, ti assicuri che l'evento secondario funzioni sempre.
Il tuo SwapBlocks
l'evento dovrebbe ora assomigliare a questo:
Se esegui il gioco a questo punto, vedrai che i blocchi vengono distrutti quando si verificano le partite. Noterai anche che le partite che sono lì quando il gioco inizia non scompaiono finché non fai uno scambio di qualche tipo. Questo perché non chiamiamo mai il FindMatches
funzione dopo aver creato la griglia di blocchi.
Il motivo per cui non abbiamo aggiunto questo codice è perché nella versione finale ci sarà un'altra funzione che impedisce che le partite vengano generate automaticamente come questa, quindi non c'è davvero alcun motivo per preoccuparsi di questo problema. (Ma sentiti libero di chiamare il FindMatches
funzione in precedenza, se ti piace.)
A questo punto, abbiamo un sistema di corrispondenza abbastanza forte, ma il problema è che il nostro codice è ridondante. Attualmente, abbiamo due funzioni diverse che controllano se c'è un vicino corrispondente, e l'unica differenza tra loro è che uno controlla verticalmente, e l'altro controlla orizzontalmente.
Poiché la versione gratuita di Construct 2 limita il numero di eventi che possiamo avere, questo è sicuramente uno spreco. Per risolvere questo, creeremo una nuova versione della funzione che può fare entrambi i controlli.
Se osservi la funzione, vedrai che l'unica differenza tra le due versioni è quella che aggiunge Block.Width + 2
alla posizione x del blocco, e l'altro lo aggiunge alla posizione y della Bock. Quindi, l'ostacolo che dobbiamo superare per rendere questa una singola funzione, sta dando alla funzione un modo per aggiungere Block.Width + 2
solo X
, o solo Y
, senza usando un Se
dichiarazione o più funzioni, poiché richiedono più eventi da eseguire.
La mia soluzione a questo non è molto complessa, ma sarà più facile capire se possiamo vederla venire insieme, quindi la implementeremo e spiegherò come funziona una volta che possiamo vederlo tutto in azione.
CheckMatchesY
evento.CheckMatchesX
evento a, semplicemente, CheckMatches
.CheckMatchesX
sotto il FindMatches
evento: CheckMatches
invece di CheckMatchesX
.Parametro 3
. 1
.Parametro 4.
0
.CheckMatchesY
sotto il FindMatches
evento: CheckMatches
invece di CheckMatchesY
.Parametro 3
. 0
.Parametro 4
. 1
.Come spiegherò presto, questi parametri aggiunti diranno CheckMatches
se sta facendo un controllo orizzontale o un controllo verticale. Quando ci mandiamo 1
per Parametro 3
, e 0
per Parametro 4
, è un assegno orizzontale e quando lo spediamo 0
per Parametro 3
, e 1
per Parametro 4
, è un controllo verticale.
Ora, torna al CheckMatches
funzione, e modificare le condizioni e le azioni per assomigliare a questo:
Evento: Funzione> Funzione On Nome: Sub-evento "CheckMatches": Condizione: Blocco> Confronta XX = Funzione.Param (0) + ((Block.Width + 2) * Funzione.Param (3)) Condizione: Blocco> Confronta YY = Function.Param (1) + ((Block.Width + 2) * Function.Param (4)) Condizione: Block> Confronta la variabile di istanza Color = Function.Param (2) Azione: Block> Set Boolean IsMatched = True Action : Funzione> Funzione chiamata Nome: "CheckMatches" Parametro 0: Function.Param (0) + ((Block.Width + 2) * Function.Param (3)) Parametro 1: Function.Param (1) + ((Block. Larghezza + 2) * Funzione.Param (4)) Parametro 2: Function.Param (2) Parametro 3: Function.Param (3) Parametro 4: Function.Param (4) Sotto-evento: Sistema> Confronta variabile NumMatchesFound> = 3 Azione: Blocca> Imposta Booleano IsMatched = True
Questo è ciò che è tuo FindMatches
e CheckMatches
il codice dovrebbe ora apparire come:
Quindi, che cosa sta facendo questa nuova versione della funzione?
Bene, ogni volta che chiami CheckMatches
ora invii altri due parametri, anziché aggiungere Block.Width + 2
alla posizione x- o y, sta aggiungendo (Block.Width + 2) * Function.Param (3)
alla posizione x, e (Block.Width + 2) * Function.Param (4)
alla posizione y.
Poiché uno di questi due parametri sarà sempre 1
, e l'altro sarà sempre 0
, questo significa che la posizione x- o y sarà modificata, mai entrambe le cose!
Per esempio, se ci inoltriamo 1
per Parametro 3
, e 0
per Parametro 4
, poi aggiunge (Block.Width + 2) * 1
, che è semplicemente Block.Width + 2
, alla posizione x, e (Block.Width + 2) * 0
, che è 0
, alla posizione y.
Ecco un rapido esempio per mostrare cosa intendo e come calcola la posizione del blocco in cui controllerà la corrispondenza. Diciamo che in questo esempio il blocco originale è a (200, 200)
, e i blocchi hanno una larghezza di 40
. Quindi, se vogliamo ottenere la posizione del blocco verticale adiacente, le formule funzioneranno in questo modo:
X = 200 + ((Block.Width + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200
Y = 200 + ((Block.Width + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242
Se volessimo ottenere la posizione del blocco orizzontale vicino, le formule funzionerebbero in questo modo:
X = 200 + ((Block.Width + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242
Y = 200 + ((Block.Width + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200
Se esegui il gioco ora, dovresti vedere che il sistema di corrispondenza funziona ancora come inizialmente, ma dal nostro punto di vista, è in realtà un sistema migliore.
A questo punto la nostra funzione di rilevamento delle corrispondenze è ancora incompleta, ma abbiamo già fatto molto in questo tutorial e penso che sia importante lasciare che tutto questo si affondi prima di aggiungere qualcos'altro. Con questo in mente, ho intenzione di concludere questo articolo qui. Guarda la demo nella sua forma attuale.
Nel prossimo articolo aggiungeremo un sistema di punti, miglioreremo il sistema di corrispondenza e aggiungeremo "gravità" in modo che i blocchi cadano quando i blocchi sottostanti vengono eliminati.
Se vuoi ottenere un vantaggio sul prossimo articolo, prenditi un po 'di tempo per considerare come rileveresti quando c'è uno spazio vuoto sotto un blocco. Prova a guardare il Blocco> È sovrapposto all'offset
funzione per l'ispirazione!