Faceți un joc Match-3 în Construct 2 Eliminarea meciurilor pre-efectuate

În tutorialul precedent am reușit în final să ne mișcăm jocul și să adăugăm mișcare blocurilor noastre. În plus, am creat un sistem rudimentar de dificultate pentru a face jocul mai greu pe măsură ce jucătorul joacă mai mult.

Cu ambele caracteristici ale jocului, suntem gata să implementăm sistemul care va elimina meciurile pre-făcute de la bord. Deși acest lucru nu este ultimul articol din seria, acesta este ultimul sistem major pe care trebuie să-l implementăm - așa că vă simțiți confortabil, pentru că ne-am desființat munca pentru noi.


Joc final Demo

Iată o demonstrație a jocului pe care lucrăm în această serie:




Corecții rapide

Înainte de a începe cu partea principală a acestui tutorial, vreau să fac un minut pentru a repara două probleme pe care le-am descoperit în timp ce scriu tutorialul anterior.

potrivire

Prima problemă la care mă refer este scenariul pe care îl puteți vedea mai jos:

În această situație, dacă trageți Blocul B pe punctul verde, ar trebui să cadă din cauza spațiilor goale de sub punct și, eventual, să aterizeze în locurile etichetate C. În majoritatea scenariilor, acest lucru se va întâmpla și jocul va funcționa în mod normal, dar în unele scenarii jocul va detecta în schimb un meci în momentul scurt unde Blocul B este alături de grup A și se va distruge toate cele trei blocuri.

Această problemă nu este exclusă pentru acel scenariu de mai sus și se poate prezenta, de asemenea, atunci când faceți același lucru în scenariul pe care l-am subliniat mai jos.

Dacă nu rezolvăm acest lucru, jucătorul va primi credit și puncte pentru un număr de meciuri pe care nu au intenționat-o niciodată și ar putea să se confunde și despre motivul pentru care atât de multe blocuri dispar în mod neașteptat.

Din fericire, totuși, aceasta este o problemă simplă de rezolvat. Pentru a rezolva această problemă vom crea un nou Variabila globală denumit MatchesPossible care va dicta dacă pot fi făcute meciuri și un nou eveniment care va detecta când un bloc "se încadrează" și se va modifica MatchesPossible pentru a face ca astfel de meciuri să nu poată fi făcute în timp ce acest lucru se întâmplă.

Mai întâi vom crea Variabila Globală:

Variabila globală: MatchesPossible Type = Număr inițial Value = 1

Variabila nouă ar trebui să arate astfel:

Acum vom face evenimentul care va asculta când un bloc este în scădere:

Eveniment: Stare: Inversare: Bloc> Se suprapune la offset Obiect = Blocare offset X = 0 Offset Y = 8 Stare: Bloc> Comparare Y Comparație = Mai mic sau egal Y co-ordonat = SPAWNY Acțiune: Sistem> Valoare setată Variable = = 1

Acest eveniment face ca atunci când se constată că un bloc are un spațiu gol sub el MatchesPossible este setat sa 1, adică meciurile nu sunt posibile. De asemenea, veți observa că verifică poziția Y a blocului. Aceasta înseamnă că blocul nu se află pe cel mai mic rând de blocuri care va avea întotdeauna un spațiu gol sub el.

Apoi, avem nevoie de un eveniment care să se stabilească MKatchesPossible înapoi la 0 când nici un bloc nu are un spațiu gol sub ele. Acest al doilea eveniment se va baza pe o altă condiție:

Eveniment: Stare: Sistem> Altă acțiune: Sistem> Valoare setată Variable = MatchesPossible Value = 0

Asigurați-vă că acest eveniment urmează imediat primul eveniment, astfel încât instrucțiunea Else să fie utilizată corect.

Cele două noi evenimente ar trebui să arate astfel:

În cele din urmă, vom adăuga o nouă condiție CheckMatches astfel încât să se uite la MatchesPossible pentru a determina dacă se poate face un meci. Adăugați această condiție la apelul inițial al funcției CheckMatches Eveniment.

Stare: Sistem> Compară variabila Variable = MatchesCompunere posibilă = Equal to Vale = 0

Cu condiția adăugată, dvs. CheckMatches Evenimentul ar trebui să arate astfel:

Spre deosebire de cele mai multe dintre problemele pe care le-am întâlnit până acum, această problemă apare pe o bază destul de incoerentă. Acest lucru înseamnă că nu putem testa cu adevărat să vedem dacă am rezolvat problema, putem testa doar dacă am cauzat alte probleme. Dacă jucați acum jocul, trebuie să observați că nu au fost cauzate de această condiție noi probleme.

puncte

Cea de-a doua problemă pe care am vrut să o rezolv înainte de a adăuga ceva nou se referă la sistemul Points.

În timp ce lucram la proiect pentru acest tutorial, am observat că ceva ce l-am făcut a făcut ca sistemul Points să se comporte ciudat și să dea jucătorului patru sau cinci ori mai multe puncte pe care ar trebui să le obțină pentru fiecare meci. Deși nu am putut determina ce schimbare am făcut ca aceasta să se întâmple, am descoperit că rădăcina problemei a fost că GivePoints funcția a fost de fapt apel numit de mai multe ori, deoarece blocurile nu au fost distruse imediat. Din fericire, ca și ultima noastră problemă, aceasta poate fi rezolvată cu ușurință.

Pentru a repara acest lucru vom crea o nouă variabilă care va spune sistemului dacă poate da puncte. Apoi, ori de câte ori suntem pe cale să folosim GivePoints vom modifica variabila pentru a ne asigura că evenimentul se declanșează o singură dată. În cele din urmă, odată ce punctele au fost date, vom schimba încă o dată variabila, astfel încât nu va mai fi o problemă data viitoare când încercăm să dăm puncte.

Mai întâi, creați o variabilă globală numită PointsGiven:

Variabila globală: PointsGiven Type = Număr inițial Value = 0

Variabila dvs. ar dori acest lucru:

Apoi vom modifica partea din FindMatches funcție care dă efectiv punctele adăugând o nouă condiție și două noi acțiuni.

Stare: Sistem> Comparați variabila Variable = PointsGiven Comparison = Equal to Value = 0

Acum adăugați această acțiune la începutul listei de acțiuni:

Acțiune: Sistem> Valoare setată Variable = PointsGiven Value = 1

În final, adăugați această acțiune la sfârșitul listei de acțiuni:

Acțiune: Sistem> Valoare setată Variable = PointsGiven Value = 0

Evenimentul ar trebui să arate astfel:

Cu aceste schimbări am făcut-o astfel încât evenimentul care îl cheamă GivePoints se va executa numai atunci când PointsGiven este variabilă 0. Deoarece setăm imediat valoarea la 1 când începem evenimentul, acest lucru împiedică evenimentul să tragă mai mult de o dată și asigură jucătorului să primească numărul corect de puncte.

Dacă rulați jocul în acest moment, trebuie să primiți numărul corect de puncte pentru fiecare meci pe care îl faceți, chiar dacă nu ați avea această problemă să începeți cu.


Eliminarea meciurilor Pre-Made

Acum, când am reușit să rezolvăm aceste soluții, putem trece la crearea sistemului care va elimina potrivirile care sunt generate de sistem atunci când atribuie aleatoriu culori blocurilor pe care le creează.

Problema pe care o avem acum este că, din moment ce culorile blocului sunt complet aleatoare, nu este neobișnuit să începeți jocul și să vedeți o grămadă de meciuri făcute imediat. Aceasta este o problemă, deoarece ar putea face primele câteva secunde ale jocului foarte confuze pentru cineva care nu a mai jucat până acum și pentru că oferă jucătorului puncte pe care nu le-au câștigat.

Pentru a rezolva problema, vom crea o funcție care va arăta fiecare bloc și apoi vom vedea dacă acel bloc este de aceeași culoare ca oricare dintre vecinii săi. Dacă are aceeași culoare ca vecinii săi, va continua să schimbe culoarea acelui bloc până când nu se mai potrivește cu niciunul dintre blocurile care îl înconjoară.

Pentru a face acest sistem de lucru, va trebui, de asemenea, să creăm mai multe funcții de suport și Evenimente, precum și să adăugăm o nouă variabilă de instanță la bloc obiect.

Efectuarea funcționării

Mai întâi, creați o nouă variabilă de instanță pentru bloc obiect:

Variabila instanței: Tipul blocului Type = Numărul Valoarea inițială = 0

Această variabilă este ceea ce vom folosi pentru a identifica cu ușurință un bloc astfel încât să putem spune unele dintre funcțiile pe care le vom face exact la ce bloc ne-am dori să privim, indiferent de poziția sa.

Înainte de a continua, trebuie să începem să folosim această variabilă. Mergeți la La începutul aspectului Eveniment care creează blocurile și adaugă o nouă acțiune înainte ca acțiunea să crească NumBlocks:

Acțiune: Bloc> Valoare setare Variabila instanță = Valoarea blocului de identificare = NumBlocks

Evenimentul dvs. de implicare în blocare ar trebui să arate astfel:

Apoi trebuie să facem o funcție care să ia poziția X și Y a unui bloc și să ne spună ce culoare are blocul:

Eveniment: Stare: Functie> Functie On: Nume = "GetBlockColor" Sub-Eveniment: Stare: Block> Comparare X Comparison = Egal cu X co-ordinate = Function.Param (0) -organize = Function.Param (0) Acțiune: Funcție> Valoare returnare valoare Valoare = Substrat de blocare culoare: Sistem> Altă acțiune: Funcție> Valoare returnare valoare Valoare = -1

Funcția ar trebui să arate așa cum trebuie atunci când este terminată:

Acum, că avem o funcție care ne poate spune culoarea oricărui bloc, vom crea funcția care va arăta într-adevăr un bloc și va determina dacă are blocuri învecinate care au aceeași culoare.

Modul în care funcționează această funcție este destul de simplu.

  • În primul rând, vom trece a BlockID în funcție.
  • Dacă există în prezent un bloc cu asta BlockID, funcția va privi cele patru blocuri vecine și va determina dacă blocul pe care îl privește este de aceeași culoare ca oricare dintre vecinii săi.
  • Dacă constată că există un vecin de aceeași culoare, va începe să schimbe culoarea blocului la care se uită și va continua să schimbe culoarea până când Blocul nu are o culoare diferită față de toți vecinii săi.

Înainte de a putea face acest eveniment, trebuie să facem o nouă variabilă globală. În funcție vom folosi o buclă În timp pentru a determina dacă culoarea blocului trebuie schimbată. Variabila pe care suntem pe cale să o creăm este variabila pe care Loop-ul va folosi pentru a determina dacă trebuie să continue să ruleze:

Variabila globală: HasMatchingNeighbor Type = Numărul inițial Value = 0

Bacsis:Evenimentul pe care îl vom face conține un Eveniment bazat pe Or. Dacă nu ați realizat niciodată un bloc de eveniment care are un atribut Or tot ce trebuie să faceți este să faceți Blocul de evenimente ca dvs. în mod normal, apoi faceți clic dreapta pe întregul bloc și alegeți Faceți blocul "Or". Spre deosebire de un bloc de evenimente standard care necesită îndeplinirea tuturor condițiilor înainte ca acesta să se declanșeze, un bloc de blocare va fi declanșat dacă orice condiția este îndeplinită.

Deci, să facem evenimentul:

Eveniment: Stare: Functia> Functie On> Submeniul "RemoveSpawnedMatches": Stare: Bloc> Compara variabila instanta Variabila instanta = Comparatie blocID = Egalitate = Function.param (0) = 1 Sub-Event: Stare: Sistem> În timp ce Stare: Sistem> Comparați variabila Variable = HasMatchingNeighbor Comparison = Egal cu Valoare = 1 Sub-Event: Apel: Bloc> Setare valoare variabilă instanță = Valoare culoare = etaj (Random (1,7)) Acțiune: Sistem> Valoare setare variabilă = HasMatchingNeighbor Value = 1 Sub-Event: Stare: Sistem> Stare altfel: Bloc> Compara variabila de instanta variabila de instanta = Comparatie culoare = egala cu valoarea = Function.Call ("GetBlockColor", Block.X + (Block.Width + , Block.Y) Acțiune: Bloc> Valoare setată Variabila instanță = Valoare culoare = etaj (Randament (1,7)) Acțiune: Sistem> Valoare setată Variable = HasMatchingNeighbor Value = 1 Sub-Event: Stare: System> Else Condition: Block> Block.Y - (Block.Width + 2)) Acțiune: Bloc> Valoare setată Variabilă instanță = Valoare culoare = etaj (Random (1,7)) Acțiune: Sistem> Valoare setată Variable = HasMatchingNeighbor Value = 1 Sub-Event : Sistem> Stare altfel: Bloc> Comparați variabila de instanță Variabilă instanță = Comparație culoare = Egal la valoare = Funcție.Call ("GetBlockColor", Block.X, Block.Y + (Block.Width + 2) Valoare variabilă = Valoare culoare = etaj (Random (1,7)) Acțiune: Sistem> Valoare setată Variable = HasMatchingNeighbor Value = 1 Sub-Event:

Evenimentul dvs. ar trebui să arate astfel:


Deci, cum funcționează exact această funcție?

Primul lucru pe care îl face este să verifici bloc cu BlockID că sistemul a intrat. Când localizează acest lucru bloc setează valoarea HasMatchingNeighbors la 1 și apoi execută bucla In timp.

Deoarece bucla In timp se va executa numai atunci când HasMatchingNeighbors este 1, aceasta este valoarea pe care o fixează. În timpul buclei In timp, testează pentru a vedea dacă există un vecin bloc la stânga, la dreapta, deasupra sau sub cea care are aceeași culoare ca și bloc ne uităm la. Dacă găsește o potrivire bloc în orice din aceste poziții, îi atribuie aleator o nouă culoare bloc și apoi execută din nou testul prin asigurarea HasMatchingNeighbors este setat sa 1. Când în cele din urmă găsește o culoare pentru bloc care nu se potrivește cu niciunul dintre vecinii săi, modifică valoarea HasMatchingNeighbors la 0 astfel încât bucla In timp se încheie și programul poate trece mai departe.

Acum trebuie să implementăm această funcție în joc; pentru a face acest lucru vom avea de a crea două noi variabile și două noi funcții. Să începem cu variabilele.

Variabila globală: CheckStartingMatches Type = Numărul Valoare = 0
Variabila globală: Tipul CheckNewestRow = Numărul Valoare = 0

Variabilele dvs. ar trebui să arate astfel:

Cele două variabile pe care le-am făcut vor fi folosite pentru a declanșa cele două evenimente pe care urmează să le creăm. Evenimentele în sine vor fi folosite pentru a repeta blocurile imediat după crearea acestora și pentru a trimite fiecare bloc în RemoveSpawnedMatches funcţie.

Motivul pentru care nu suntem doar să sunăm RemoveSpawnedMatches funcția imediat după crearea blocului se datorează faptului că grila bloc trebuie să fie completă pentru ca funcția să funcționeze corect. Deci, în loc de a apela doar funcția direct atunci când se fac blocuri, vom declanșa un eveniment care poate trece prin blocuri și poate apela funcția pe cont propriu după generarea rețelei.

Primul eveniment va fi special pentru iterarea prin grupul inițial de blocuri:

Eveniment: Stare: Sistem> Comparare variabilă Variabilă instanță = CheckStartingMatches Comparison = Egal la valoare = 1 Stare: System> For Name = "Blocks" Index start = 0 End index = NumBlocks- Parametru 0 = loopindex ("Blocuri") SubEvent: Stare: Sistem> Comparați două valori Prima valoare = loopindex ("Blocuri") Comparație = Egal cu a doua valoare = NumBlocks-1 Acțiune: System> Set variable Variable instanță = CheckStartingMatches Value = 0

Acesta ar trebui să arate evenimentul dvs.:

Cel de-al doilea eveniment va fi în mod special pentru a verifica noi rânduri de blocuri atunci când sunt făcute:

Eveniment: Stare: Sistem> Comparare variabilă Variabilă instanță = CheckNewestRow Comparație = Egal cu valoare = 1 Stare: Sistem> Nume = "Blocuri" Start index = NumBlocks-9 End index = RemoveSpawnedMatches "Parametru 0 = loopindex (" Blocuri ") SubEvent: Stare: Sistem> Comparați două valori Prima valoare = loopindex (" Blocuri ") Comparison = Egal cu Valoarea a doua = NumBlocks-1 Acțiune: System> Set variable Variable instanță = = 0

Acesta ar trebui să fie cel de-al doilea eveniment:

Punerea în aplicare

Cu ambele funcții în loc, acum trebuie doar să le punem în aplicare. Mergeți la evenimentul inițial care face blocurile, La începutul planului Eveniment. Vom adăuga un Sub-Eveniment la acest lucru, care va spune CheckStartingMatches Evenimentul să fie activat.

Sub-Event: Stare: Sistem> Comparați două valori Prima valoare = loopindex ("X") Comparație A doua valoare: 7 Stare: Setați valoarea variabilei instanței = CheckStartingMatches Value = 1

Evenimentul dvs. ar trebui să arate astfel:

Acest sub-eveniment ascultă când sa încheiat bucla forțată For și apoi modifică valoarea CheckStartingMatches pentru a activa evenimentul corespunzător.

Acum vom face aproape exact același Sub-Eveniment și îl vom atașa SpawnNewBlocks funcţie.

Sub-Event: Stare: Sistem> Comparați două valori Prima valoare = loopindex ("X") Comparație Valoare a doua: 7 Acțiune: Sistem> Valoare setare Valoare variabilă = Valoare checkNewestRow =

SpawnNewBlocks ar trebui să arate astfel:

Acest Sub-Eveniment face același lucru cu cel precedent, cu excepția faptului că activează celălalt Eveniment pe care l-am creat. Dacă executați jocul în acest moment, trebuie să observați că atunci când începeți jocul, nu mai există meciuri care apar automat.


Concluzie

În acest tutorial, nu am făcut prea multe schimbări în joc, dar cele pe care le-am făcut au fost foarte importante.

În acest moment, cred că este mai bine să ne oprim pentru moment și să salvăm ultimele două elemente de joc pentru tutorialul următor, unde vom acoperi lanțurile / combo-urile și ecranul Game Over. Aceasta va fi ultima parte a seriei, așa că voi vorbi și despre unele mecanisme de joc pe care nu le vom acoperi în aceste tutoriale și vă vom oferi câteva sfaturi despre cum ați putea face aceste sisteme pe cont propriu.

Dacă doriți să obțineți un start pentru conținutul săptămânii viitoare, începeți să vă uitați la modul în care ați putea detecta când trebuie să apară ecranul Game Over, în funcție de poziția sau înălțimea unora dintre blocuri. Alternativ, începeți să vă gândiți la modul în care ați putea detecta când jucătorul face o reacție în lanț care cauzează formarea mai multor grupuri.

Indiferent ce faceți, sper să vă revăd aici săptămâna viitoare pentru ultima tranșă a seriei.