Maak een Match-3-game in Construct 2 Chaining en Game Overs

Het is eindelijk zover: we zijn bijna klaar met onze game en zijn klaar om de laatste gameplay-monteur te implementeren. Dit artikel zal zich richten op het maken van een combo-systeem dat de speler meer punten geeft voor het maken van ketens die meerdere groepen blokken na slechts één ruil vernietigen.

Daarbovenop zullen we het verlies scenario implementeren en een Game Over scherm toevoegen. Ten slotte zal ik het hebben over dingen waar je in je eigen tijd aan kunt werken om het spel verder te verbeteren en uit te breiden dan wat we hebben besproken. Dus, zonder verder oponthoud, laten we beginnen ...


Final Game Demo

Hier is een demo van de game waaraan we hebben gewerkt en die we aan het einde van dit deel van de serie hebben gebouwd:




Zoeken naar overeenkomsten

Voordat we verder gaan met het hoofdartikel, wil ik een kleine wijziging aanbrengen in wanneer FindMatches wordt gebeld.

Tijdens het werken aan dit artikel heb ik een probleem ontdekt dat u hieronder in de GIF kunt zien:

Zoals je kunt zien in deze eerste GIF, wanneer een blok op slechts één blokafstand valt om te proberen een overeenkomst te vormen met een groep blokken aan de onderkant van de val, werkt het perfect.

In deze tweede GIF wordt het echter duidelijk dat wanneer een blok een grotere afstand in hetzelfde scenario laat vallen, het de match niet kan detecteren totdat we een nieuwe swap uitvoeren. De reden hiervoor is dat het spel niet vaak genoeg naar wedstrijden zoekt.

Op dit moment zoekt het spel alleen naar matches na een ruil, maar vanwege de hoeveelheid tijd die een blok nodig heeft om van deze afstand te vallen, is de overeenkomstdetectie al beëindigd wanneer het blok de grond raakt en dus wordt de match pas gevonden het wordt opnieuw geïnitieerd.

Om dit op te lossen, zullen we wijzigen wanneer we een FindMatches controleren.

Ga eerst naar de SwapBlocks functie en verwijder de laatste gebeurtenis uit de functie zodat deze niet belt FindMatches helemaal niet.

SwapBlocks zou er nu zo uit moeten zien:

Op dit moment is er geen gebeurtenis FindMatches. We lossen dit op door een nieuwe actie aan het evenement toe te voegen die detecteert wanneer overeenkomsten mogelijk zijn. Zoek dit evenement en voeg deze actie toe aan het einde van het Else-evenement:

Actie: Functie> Oproepfunctie Name = "FindMatches"

Uw evenement zou er nu als volgt uit moeten zien:

Neem ook deze kans om beide te verplaatsen MatchesPossible Gebeurtenissen tot het einde van de spelcode, als je dat nog niet hebt gedaan. Als u dit doet, zorgt u ervoor dat deze helemaal niet worden aangeroepen voor de code die vooraf gemaakte overeenkomsten uitsluit.

Als je het spel nu uitvoert, zou je het scenario dat ik hierboven heb gepresenteerd zonder probleem moeten kunnen uitvoeren.


chaining

Met dat probleem opgelost, gaan we het chaining systeem, waardoor de speler extra punten krijgt voor wedstrijden die worden veroorzaakt door de vernietiging van een andere wedstrijd.

U ziet een voorbeeld van het soort situatie dat ik hieronder bedoel:

In het bovenstaande scenario verplaatst de speler het groene blok en maakt een overeenkomst. Vervolgens zorgt de vernietiging van de groene blokken ervoor dat de blauwe blokken vallen en een moment later een andere wedstrijd creëren.

Ik wil de speler bonuspunten geven om zoiets te bereiken. Specifiek wil ik een vermenigvuldiger toepassen op het aantal punten dat de speler ontvangt voor elke wedstrijd, en de vermenigvuldiger verhogen met elke opeenvolgende overeenkomst die is gemaakt.

Het laten werken

Om dit systeem te laten werken, gaan we een nieuwe variabele maken genaamd Keten, en maak vervolgens een paar kleine wijzigingen in de bestaande functies. Dus, maak eerst een nieuwe globale variabele:

Global Variable: Chain Type = Number Initial Value = 0

Uw variabele zou er als volgt uit moeten zien:

Deze variabele fungeert als een vermenigvuldiger voor de punten om aan te geven hoe lang een ketting is gegaan.

Ga nu naar het Evenement waardoor de blokken vallen en verwijder de Else-gebeurtenis die de. Roept FindMatches functie.

Ga nu naar FindMatches zelf en vind de locaties waar u de FloatingPointsText voorwerpen. Wijzig de Set Text-instructies zodat ze een nieuwe formule gebruiken:

Actie: FloatingPointsText> Tekst instellen Text = NumMatchesFound * 10 * Chain

Deze wijziging zorgt ervoor dat de zwevende tekst op dezelfde manier wordt aangepast als de punten zelf uiteindelijk zullen worden.

Ga vervolgens naar de sectie van FindMatches waar je belt FindMatches opnieuw aan het einde van de gebeurtenis en verwijder deze functieaanroep en de wachtinstructie. Waarom? Omdat, als we deze niet hebben verwijderd, dan FindMatches zou uiteindelijk te vaak gebeld worden en de ketens zouden nooit correct geïnitieerd kunnen worden.

(Vanwege de wijzigingen die we eerder in dit artikel hebben aangebracht, FindMatches wordt opgeroepen wanneer alle blokken in het raster staan ​​en er geen een meer valt. Meerdere gebieden hebben waar we naar bellen FindMatches zou ervoor zorgen dat meerdere instanties van de functie op hetzelfde moment worden uitgevoerd en het puntensysteem zouden kunnen verknoeien.)

Ten slotte zullen we nog een andere wijziging in deze functie aanbrengen. Ga naar het einde van de functie en voeg deze actie toe nadat je hebt ingesteld PointsGiven naar 0:

Actie: Systeem> Toevoegen aan variabele = "Ketting" -waarde = 1

Telkens wanneer het spel overeenkomsten vindt, geeft het de speler punten, vernietigt het de blokken, en verhoogt dan de Chain-waarde.

De nieuwe versie van FindMatches zou er als volgt uit moeten zien:

Ga vervolgens naar de GivePoints functioneer en wijzig beide Acties die de waarde van de Score verhogen, zodat ze rekening houden met de Ketenwaarde:

Actie: Systeem> Toevoegen aan variabele = scorewaarde = 10 * ketting

Met deze verandering, GivePoints zou er nu als volgt uit moeten zien:

De ketting opnieuw instellen

We hebben de variabele keten geïmplementeerd als een vermenigvuldiger voor de punten die de speler ontvangt (en het aantal punten dat wordt weergegeven in de zwevende tekstobjecten), maar er is nog een ding dat we moeten doen: we moeten een verklaring toevoegen Hiermee wordt de waarde van Chain opnieuw ingesteld, zodat deze niet alleen oneindig toeneemt.

We gaan deze verklaring toevoegen aan de Op DragDrop Start Gebeurtenis, zodat wanneer de speler een nieuw blok begint te slepen, dit als een nieuwe ketting wordt beschouwd. De andere reden dat we het hier doen is omdat het voorkomt dat de Chain-waarde voortijdig wordt gereset, waardoor alle matches in het laatste deel van een Chain minder waardevol zijn.

Ga naar de Op DragDrop Start Evenement en voeg deze actie toe aan de lijst met acties:

Actie: Systeem> Waarde instellen Variabel = Kettingwaarde = 1

Uw evenement zou er nu als volgt uit moeten zien:

Als je het spel op dit punt test, zou je moeten zien dat als je een ketting maakt zoals die eerder in het gif is gedemonstreerd, je 90 punten krijgt in plaats van 60 punten.

Met dat werken, is het kettingsysteem compleet en zou je in staat moeten zijn om zo uitgebreid een ketting te maken als je wilt zonder problemen.


Vaststelling van vallen

Het volgende dat ik wil bespreken, is een probleem dat ik heb gevonden met het Block Fall-systeem. Als je veel tijd besteedt aan het spelen van ons Match-3-spel in de huidige staat, heb je mogelijk een probleem opgemerkt waarbij een blok af en toe valt, ook al is er geen blok eronder.

Je kunt zien wat ik bedoel in de afbeelding hieronder:


Ondanks dat er geen blok onder het gele blok is, is het nog steeds niet gelukt om in de lege ruimte te vallen. Dit is een zeldzaam probleem, maar als het niet wordt behandeld, kan het toch iemands score verknoeien en voorkomen dat ze een ketting ontvangen die ze hebben ingesteld, of zelfs veroorzaken dat ze verliezen zodra we de Game Over-functie toevoegen.

Het probleem komt van de variabele BlockBeingMoved, die wordt gebruikt door de gebeurtenis die bepaalt wanneer blokken moeten vallen om ervoor te zorgen dat er geen blokken worden verplaatst wanneer een blok wordt aangegeven om een ​​lege ruimte in te vullen. In sommige scenario's, wanneer de speler een blok verplaatst, wordt deze variabele nooit opnieuw ingesteld en vallen de blokken niet totdat een ander blok wordt verplaatst en het correct wordt gereset. Om dit op te lossen, gaan we een paar gebeurtenissen toevoegen die deze variabele correct instellen en resetten, en we zullen de huidige acties verwijderen die de variabele instellen, omdat ze niet correct werken.

Ga eerst naar de OnDragDrop Start en Over DragDrop Drop Evenementen en verwijder alle acties die betrekking hebben op de BlockBeingMoved variabele van deze evenementen. Er moet één actie per evenement zijn die moet worden verwijderd.

Ga vervolgens naar de gebeurtenis die detecteert wanneer er een lege ruimte onder een blok is. We gaan de voorwaarden van dit evenement wijzigen. Controleer eerst of de voorwaarde die controleert of BlockBeingMoved is gelijk aan 0 staat aan het begin. Voeg vervolgens een andere voorwaarde toe aan het einde van de gebeurtenis, die controleert of er geen blokken worden verplaatst.

Dit is de voorwaarde die u zult toevoegen:

Voorwaarde: omkeren: blokkeren> slepen

Uw evenement zou er nu als volgt uit moeten zien:


Ten slotte voegen we aan het einde van de cursus nog twee gebeurtenissen toe Evenementblad die de. zal behandelen BlockBeingMoved variabel. Ga naar het einde van je Evenementblad en voeg deze evenementen toe:

Gebeurtenis: Voorwaarde: blokkeren> slepen Actie: systeem> variabele instellen Naam = BlockBeingMoved-waarde = 1
Gebeurtenis: Voorwaarde: Systeem> Anders Actie: Systeem> Stel variabele in Name = BlockBeing Moved Value = 0

Je nieuwe evenementen zouden er als volgt uit moeten zien:


Deze evenementen zullen effectief veranderen BlockBeingMoved van 0 naar 1 en van 1 naar 0 wanneer een blok wordt verplaatst of wordt verplaatst niet worden verplaatst, respectievelijk. Als je de game op dit punt test, zou je in staat moeten zijn om zo vaak als je wilt te spelen zonder problemen te ondervinden met Block falling.


Spel is over

Nu ons kettingsysteem op zijn plaats zit, voegen we het verliesscenario en een spel over-scherm toe.

Het eerste dat we moeten doen is een nieuwe lay-out toevoegen die zal fungeren als ons speloverzichtscherm:

  1. Klik aan de rechterkant van het scherm met de rechtermuisknop lay-outs map en selecteer Layout toevoegen.
  2. kiezen Voeg evenementenblad toe.
  3. Ga naar de nieuwe lay-out en maak een nieuwe BG Tile voorwerp.
    1. Kies de afbeelding GameOverBGTile.png van de BG-afbeeldingen map in het grafische pakket dat u tijdens de eerste zelfstudie hebt gedownload.
    2. Stel de Positie naar -6, -7.
    3. Stel de Grootte naar 613, 619.
  4. Maak een nieuw sprite voorwerp.
    1. Kies de afbeelding GameOverText.png van het grafische pakket.
    2. Stel de Positie naar 303, 200.
  5. Maak een nieuw Knop voorwerp.
    1. Stel de Naam naar RestartButton.
    2. Stel de Positie naar 262, 410.
    3. Stel de Grootte naar 100, 30.
    4. Stel de Tekst naar Herstarten.

Nu je Game-over-scherm hebt ingesteld, ga je terug naar je oorspronkelijke lay-out, Layout 1, en voeg een nieuw item toe aan dat scherm:

  1. Maak op Lay-out 1 een nieuw sprite voorwerp.
  2. Gebruik de Verfemmer hulpmiddel om deze sprite helemaal rood te schilderen.
  3. Sluit de animatie-editor.
  4. Stel de Naam naar GameOverArea.
  5. Stel de Positie naar 196, -30.
  6. Stel de Grootte naar 344, 150.
  7. Stel de ondoorzichtigheid naar 0.

Je moet opmerken dat deze sprite zich op dezelfde positie en dezelfde grootte bevindt, als het bovenste deel van het speelveld. We gaan dit sprite-object gebruiken om te detecteren wanneer de speler heeft verloren door te detecteren wanneer een blok ermee in botsing komt. Ga naar Evenementblad 1 dus we kunnen beginnen met het implementeren hiervan.

De blokken aan de bovenkant stoppen

Voordat we het verliesscenario gaan detecteren, moeten we een nieuwe variabele toevoegen die we gebruiken om de blokken te stoppen wanneer ze de GameOverArea voorwerp zodat ze niet meer bewegen. Dit zal de speler duidelijk maken dat ze verloren zijn.

Global Variable: MovementPossible Type = Number Initial Value = 0

Ga nu naar het Evenement waar je de blokken verplaatst en voeg deze voorwaarde toe:

Voorwaarde: Systeem> Variabele vergelijken Variable = MovementPossible Comparison = Equal to Value = 0

Je bewegingsevenement zou er nu als volgt uit moeten zien:

Nu de beweging onze nieuwe variabele gebruikt, voegen we de gebeurtenis toe die de verliesconditie detecteert:

 Gebeurtenis: Voorwaarde: Blok> overlapt een ander object Object = GameOverArea Voorwaarde: Omkeren: Blokkeren> IsDragging Actie: Functie> Oproep Functienaam = "Spel over"

De gebeurtenis die we zojuist hebben gemaakt zal de functie Game Over roepen zodra een blok de. Overlapt GameOverArea. Nu zullen we het echt maken Spel is over functie.

 Gebeurtenis: Voorwaarde: Functie> Aan functie Naam = "Spelovergang" Actie: Blokkeren> Ingesteld inschakelen Status = Uitgeschakeld Actie: Systeem> Stel waarde in Variabel = BewegingMogelijk Waarde = 1 Actie: Systeem> Wacht seconden = 1.5 Actie: Systeem> Ga naar lay-out Layout = Layout 2

Je twee nieuwe evenementen zouden er als volgt uit moeten zien:


De reden dat we een afzonderlijke functie hebben gemaakt in plaats van deze acties uit te voeren in het evenement die het spel daadwerkelijk detecteren, is dat dit evenement alleen naar bepaalde blokken kijkt vanwege de gebeurtenissen die het activeren. Zoals je kunt zien in de functie die we hebben gemaakt, schakelen we de slepende functies van het blok uit om te voorkomen dat de speler doorgaat met het maken van wedstrijden nadat het spel is gedetecteerd. Als we dit deden in de gebeurtenis die het spel detecteert, zou het alleen de blokken uitschakelen die het spel hebben veroorzaakt, en elk ander blok zou nog steeds kunnen worden gesleept.

Ga nu naar Evenementblad 2; we gaan wat functionaliteit toevoegen aan de RestartButton object dat we eerder hebben gemaakt. Voeg een nieuwe gebeurtenis toe aan Evenementblad 2:

Gebeurtenis: Voorwaarde: RestartButton> Klikken Actie: Systeem> Ga naar lay-out Lay-out = Lay-out 1

Uw evenement zou er als volgt uit moeten zien:

De waarden opnieuw instellen

Als je het spel nu speelt, een spel krijgt en vervolgens opnieuw start, zou je moeten opmerken dat het teruggaat naar de oorspronkelijke lay-out, maar de blokken bewegen niet. De reden hiervoor is dat alle variabelen die we hebben gebruikt globale variabelen zijn, dus sommige worden niet automatisch opnieuw ingesteld wanneer we de lay-out opnieuw starten.

Om ze te resetten, moeten we een actie toevoegen aan onze Aan het begin van de lay-out Gebeurtenis die ze handmatig voor ons zal resetten.

Ga naar de Aan het begin van de lay-out Evenement en voeg deze actie toe aan de eerste gebeurtenis voordat de For-lussen worden genoemd:

Actie: Systeem> Algemene variabelen opnieuw instellen

Uw evenement zou er nu als volgt uit moeten zien:

Als u opnieuw test, zou u dit probleem niet langer moeten hebben.


Wat moet je doen Volgende?

Op dit punt hebben we alle functies besproken die ik wilde behandelen in het kader van deze zelfstudies.

Je zult merken dat je spel dat nog steeds niet is precies hetzelfde als in de bovenstaande demo, met als grootste verschil dat je game geen startscherm heeft. Ik heb ervoor gekozen om niet te beginnen met het maken van het startscherm, omdat het bijna precies hetzelfde is als het maken van het scherm Spel over - ik laat dit als een oefening voor jou.

In plaats daarvan bespreek ik enkele functies die je zou kunnen overwegen toe te voegen aan je spel, waardoor deze beter of interessanter zou kunnen worden.


Speciale blokken

Het eerste dat ik wil bespreken, is speciale blokken - blokken die de speler bonussen geven of een unieke functie vervullen.

De meeste Match-3-spellen bevatten speciale blokken om de actie te verbreken en de game spannender te maken. In zijn huidige vorm kan het spel in theorie eeuwig doorgaan, maar de gameplay verandert nooit. Door zo nu en dan speciale bloktypen te introduceren, kan het spel interessanter worden als het al een tijdje bezig is.

Als u een speciaal blok wilt integreren, moet u de manier wijzigen waarop blokken worden gegenereerd, zodat wanneer een blok wordt gemaakt, er een willekeurige kans is dat het een speciaal blok wordt. Er zijn een aantal manieren om dit te doen, maar over het algemeen is het het beste om gewoon een willekeurig getal tussen 1 en 100 te genereren en alleen een speciaal blok te genereren wanneer het de willekeurige waarde tussen 95 en 100 is, of een ander bereik dat u kiest.

Je doel moet zijn om Specialty Blocks zeldzaam te maken, maar niet te zeldzaam. Op deze manier krijgt de speler ze regelmatig genoeg om het spel leuker te maken, maar niet zo vaak dat het de balans van het spel vernietigt.

Bomb Blocks

Als het gaat om speciale blokken heb je veel opties; een van de meest voorkomende is een bomblok.

Bomblokken zorgen ervoor dat extra blokken worden vernietigd wanneer ze worden vernietigd. Ze verschillen in elk spel: in sommige games vernietigen ze alle blokken die er omheen liggen; in andere vernietigen ze een hele rij of kolom met blokken.

In de onderstaande afbeelding ziet u twee typen bomblokken uit het populaire spel Candy Crush Saga:


Bomblokken zijn over het algemeen vrij eenvoudig te integreren:

  • Begin met een evenement dat luistert naar de vernietiging van eventuele bommenblokken.
  • Wanneer iemand wordt vernietigd, moet het zijn positie doorgeven aan een functie die dan alle blokken vindt en vernietigt die ook door dat bomblok zouden worden vernietigd.
  • Als je bomblok bijvoorbeeld alle omliggende blokken zou vernietigen, zou je de positie van het bomblok doorgeven aan een functie die naar elk van de omliggende posities zou kijken om te zien of er daar blokken zijn.
  • Als het blokken in deze posities vindt, vernietigt het ze.

Time-Slow of Time-Stop Blocks

Een ander type specialiteitsblok dat je in veel games vindt, is een type dat vertraagt ​​hoe snel de blokken bewegen of stopt ze volledig.

Blokken zoals deze zijn heel eenvoudig te maken.

  • Net als bij bomblokken, heb je een evenement nodig dat luistert wanneer een van deze blokken wordt vernietigd.
  • Wanneer dit gebeurt, moet u ofwel wijzigen MovementsPossible naar 1 zodat de blokken stoppen, of wijzigen snelheid zodat de blokken heel langzaam bewegen.
  • Vervolgens moet u een timer starten die een korte tijd duurt, misschien 10 - 15 seconden. Zodra die timer eindigt, stelt u de snelheid van de blokken opnieuw in en gaat u gewoon verder.

U moet onthouden dat u rekening moet houden met de speler die een time-stop-blok activeert, terwijl een ander time-stop-blok al actief is. In dit scenario moet u de timer opnieuw starten of de standaardlengte van de timer toevoegen aan de bestaande timer en normaal doorgaan.


Andere speltypen

Je zou ook kunnen overwegen om andere spelmodi toe te voegen voor wanneer de speler zich verveelt van de eindeloze modus die we hebben gemaakt.

Tijdmodus

De gemakkelijkste spelmodus die u kunt toevoegen, is er een waarbij de speler een tijdslimiet heeft, met als doel om zoveel mogelijk punten te verzamelen voordat de tijd om is.

In dit scenario zou je alle spelcode ongewijzigd laten, behalve om een ​​tweede verliesconditie toe te voegen aan het spel, waardoor het spel eindigt wanneer de timer afloopt (en ook wanneer de blokken de bovenkant van het scherm raken).

Wanneer het spel begint, zou je een timer starten gedurende de tijd dat de modus duurt, en wanneer de timer eindigt, zou je het spel beëindigen op dezelfde manier als nu.

Puzzle-modus

In deze spelmodus zou je de speler een heel specifiek spelbord geven dat je van tevoren ontwerpt en hen vragen om alle blokken in zo min mogelijk swaps te verwijderen.

(Waarschijnlijk wil je de blokbeweging uitschakelen, want als de blokken in beweging komen, worden er ook nieuwe blokken toegevoegd in de loop van de tijd.)

In deze modus moet je een specifiek blokraster kunnen instellen, dus je moet een systeem hebben waarmee je een specifieke blokinstelling kunt doorgeven wanneer het spel begint, in plaats van er één geheel willekeurig te genereren zoals we nu doen.

Bovendien, terwijl deze spelmodus relatief eenvoudig te implementeren is, zou je veel handmatig puzzels moeten maken, zodat je veel unieke puzzels kunt maken voor de speler om te proberen en op te lossen.

Het toevoegen van een dergelijke spelmodus kan behoorlijk tijdrovend zijn vanwege de vereiste contentcreatie, maar er zijn veel spelers die er plezier aan zouden beleven. Het kan echt goed werken als je er tijd in steekt.


Conclusie

In de loop van deze tutorialserie hebben we van begin tot eind een compleet match-3-spel gebouwd. Er is veel meer dat je met deze game kunt doen als je de tijd neemt en de verbeelding spreekt, maar er zijn ook veel manieren waarop je de ideeën die ik heb gepresenteerd kan gebruiken om je te helpen met andere spelprojecten.

Blijf aan je spel werken en blijf nieuwe ideeën ontdekken, want je weet nooit wanneer iets dat je hier hebt geleerd later van pas kan komen.

Ik hoop dat je, of je nu de hele serie hebt doorlopen of gewoon hebt overgeslagen naar de delen die je niet alleen kon doen, hier iets van hebt geleerd. Als u problemen of opmerkingen heeft, laat ons dit weten in de discussies hieronder elk artikel - Ik hoor graag van u en zie welke wendingen u toevoegt. In ieder geval bedankt voor het lezen en veel succes met je games!