Maak een Match-3-game in Construct 2 punten, overeenkomsten en zwaartekracht

In de vorige tutorial hebben we een basissysteem voor matchdetectie geïntegreerd in ons Match-3-spel. Hoewel we goed op weg zijn om een ​​speelbare game te spelen, zijn er nog een paar belangrijke game-elementen die we nodig hebben voordat we echt kunnen noemen wat we een 'game' hebben. Dit artikel gaat focussen op het invullen van enkele van die ontbrekende details en ons dichter bij ons eindproduct brengen.


Final Game Demo

Hier is een demo van de game waaraan we werken in deze serie:




1. Toekenningspunten

We gaan punten bespreken voordat we beginnen met het verbeteren van het koppelingssysteem, omdat het veel gemakkelijker zal zijn om het eerste probleem in ons huidige koppelingssysteem te zien als we een puntenstelsel hebben geïmplementeerd.

Het puntensysteem in ons spel zal heel eenvoudig zijn, voor elk blok dat wordt gebruikt om een ​​bepaalde groep te vormen, krijgt de speler 10 punten. In een latere tutorial voegen we ook een systeem toe waarmee de speler meer punten kan verdienen door meerdere groepen samen te ketenen, maar voor nu zullen we focussen op het introduceren van een simpel puntensysteem voor de speler.

Voordat we beginnen met het bewerken van de evenementen, moeten we een puntenweergave toevoegen, dus ga eerst naar Layout 1 en doe het volgende:

  1. Plaats een nieuw sprite voorwerp.
    1. Open de afbeelding Game Field Images / ScoreArea.png van het grafische pakket.
    2. Sluit de animatie-editor.
    3. Stel de positie in op 491, 383.
  2. Plaats een nieuw Tekst voorwerp.
    1. Stel de doopvont naar Calibri, Bold, 22 gebruik de drop-down.
    2. Stel de Naam naar ScoreText
    3. Stel de Kleur naar Wit of 255, 255, 255
    4. Stel de Positie naar 419, 398.
    5. Stel de Grootte naar 200, 50.
    6. Stel de Tekst naar 0.

Layout 1 zou er nu als volgt uit moeten zien:

Nu we iets hebben om de speler te vertellen wat de puntentekst betekent, en een tekstobject om de score van de speler mee weer te geven, kunnen we doorgaan om de speler punten te geven. Ga naar Evenementblad 1 en maak een nieuwe Globale variabele.

Global Variable Name: "Score" Type = Getalwaarde = 0

De variabele zou er als volgt uit moeten zien:

Dit is de variabele die we zullen aanpassen wanneer we de speler punten geven. Vervolgens zullen we een nieuwe functie maken die, wanneer deze wordt opgeroepen, zal detecteren hoeveel blokken de speler in groepen heeft gematcht, en hen het juiste aantal punten moet geven.

Gebeurtenis: Voorwaarde: Functie> Aan Functienaam = "GivePoints" Voorwaarde: Systeem> Voor elk object = Bloktoestand: Blokkeren> Is boolean-instantievariabelenset Instance Variable = IsMatched Actie: Systeem> Toevoegen aan variabele = Scorewaarde = 10 Actie: ScoreText > Tekst instellen Tekst = Scoren

Uw code zou er als volgt uit moeten zien:

Dus, nogmaals, deze gebeurtenis kijkt naar elk afzonderlijk blok. Elke keer dat het een blok vindt dat dat wel heeft IsMatched ingesteld op waar - wat betekent dat het is bevestigd deel uit te maken van een groep - het geeft de speler 10 punten voor dat blok en werkt de scoretekst bij.

Als je op dit moment je spel test, lijkt het of de functie niet werkt. De reden hiervoor is dat we de functie nergens in de code hebben genoemd, dus de punten worden nooit opgehoogd en de tekst wordt nooit bijgewerkt. Ga naar je FindMatches functie en voeg een nieuwe actie toe aan het begin van het laatste subgebeurtenis voor deze functie.

Actie: Functie> Oproepfunctie Naam = "GivePoints"

Jouw FindMatches functie zou er nu als volgt uit moeten zien:

Opmerking: zorg dat u deze nieuwe actie aan het begin van het subgebeurtenis hebt toegevoegd. Als u deze actie aan het einde toevoegt, zal deze niet werken omdat alle overeenkomende blokken vóór de. Zijn vernietigd GivePoints functie wordt aangeroepen. Dit betekent dat, wanneer het zoekt naar de overeenkomende blokken, het er geen zal vinden en dus zal de speler geen punten ontvangen.

Op dit punt kun je je spel opnieuw testen en moet je de puntentekst zien updaten en dat de speler het juiste aantal punten ontvangt voor elke wedstrijd die ze maken.


2. Verbetering van de overeenkomstdetectie

Nu we het puntensysteem hebben, wil ik dat je het spel uitvoert en het onderstaande scenario maakt.


Wissel nu de blokken die ik hier heb gemarkeerd en bekijk je score om te zien hoeveel punten je wint.


Toen je deze wedstrijd vormde, had je moeten zien dat je 50 punten hebt behaald. Dit komt omdat momenteel het puntensysteem de speler 10 punten geeft voor elk blok dat is gemarkeerd als IsMatched, in tegenstelling tot de speler 10 punten geven voor elk blok gebruikt in elke wedstrijd, zoals het systeem dat ik hierboven heb beschreven.

Als het puntensysteem correct zou werken, zou het de speler 60 punten geven: 30 voor de verticale groep van drie blokken en 30 voor de horizontale groep van drie blokken. Dit probleem komt voort uit het feit dat het koppelsysteem geen enkele manier van markeren heeft wanneer een blok zowel horizontaal wordt gekoppeld en verticaal; het weet alleen of het blok überhaupt is gematcht.

Om dit probleem op te lossen gaan we eerst twee nieuwe toevoegen Instantievariabelen naar ons Block-object, MatchedX en MatchedY.

Exemplaarvariabele: Name = MatchedX Type = Boolean Initial Value = false Instance Variable: Name = MatchedY Type = Boolean Initial Value = false

Uw variabelen moeten er als volgt uitzien:


Deze variabelen zullen worden gebruikt in combinatie met IsMatched om het systeem te vertellen wanneer het blok deel uitmaakt van horizontaal, of X, groepen, en wanneer het blok deel uitmaakt van verticale, of y, groepen. Nu we de variabelen hebben, gaan we het wijzigen CheckMatches functie zodat wanneer het een blok markeert IsMatched omdat het een groep heeft gevonden die groot genoeg is, zal het ook dat blok labelen als onderdeel van een X- of Y-groep, afhankelijk van of parameter 3 of parameter 4 1 is.

Ga naar de CheckMatches functie en vervang het origineel NumMatchesFound controleer met deze twee nieuwe sub-evenementen:

Subgebeurtenis: Voorwaarde: Systeem> Vergelijk twee waarden Eerste waarde = Functie.Param (3) Vergelijking = Gelijk aan Tweede waarde = 1 Voorwaarde: Systeem> Variabele vergelijken Variabel = NumMatchesGevonden vergelijking = Groter of gelijk Waarde = 3 Actie: Blokkeren> Instellen Boolean Instance variable = IsMatched Value = True Action: Block> Set Boolean Instance variable = MatchedX Value = True Sub-Event: Voorwaarde: Systeem> Vergelijk twee waarden Eerste waarde = Functie.Param (4) Vergelijking = Gelijk aan Tweede waarde = 1 Voorwaarde : System> Variabele vergelijken Variable = NumMatchesFound Comparison = Greater of gelijk Value = 3 Action: Block> Set Boolean Instance variable = IsMatched Value = True Action: Block> Set Boolean Instance variable = MatchedY Value = True

Jouw CheckMatches functie zou er nu als volgt uit moeten zien:


Dus de nieuwe versie van CheckMatches functioneert op dezelfde manier als de vorige, behalve dat het nu ook controleert of het Blok gevonden werd als een overeenkomst in een verticale groep of een horizontale groep, en het Blok dienovereenkomstig labelt met de nieuwe variabelen MatchedX en MatchedY.

Extra punten toekennen aan blokken die twee keer matchen

Nu we een manier hebben om te bepalen wanneer een blok verticaal wordt gematcht, horizontaal wordt vergeleken en in beide richtingen wordt vergeleken, in tegenstelling tot alleen te weten dat het in een groep is gematcht, moeten we een subgebeurtenis aan de groep toevoegen. GivePoints functie die een extra 10 punten verdelen voor een blok dat beide heeft MatchedX en MatchedY ingesteld op waar.

Ga naar de GivePoints functie en voeg dit sub-evenement toe:

Subgebeurtenis: Voorwaarde: Blokkeren> Is Boolean-instantievariabele ingesteld Instance-variabele = MatchedX Voorwaarde: Blokkeren> Is Boolean-instantievariabelen ingesteld Instance-variabele = MatchedY Actie: Systeem> Toevoegen aan variabele = Scorewaarde = 10 Actie: Tekst> Tekst instellen Waarde = partituur

Jouw GivePoints functie zou er nu als volgt uit moeten zien:


Als je je spel uitvoert en opnieuw het scenario maakt dat ik hierboven heb geïllustreerd, zou je score nu correct moeten toenemen met 60 punten.


3. Zwaartekracht toevoegen

Nu we een Points-systeem hebben geïmplementeerd en we het matchingsysteem hebben bijgewerkt, gaan we een ander belangrijk aspect van het spel beginnen verbeteren. Als je tot nu toe met het spel hebt gespeeld, weet je dat een van de grootste problemen is dat wanneer blokken worden vernietigd, er niets met de blokken boven hen gebeurt. Met name de blokken boven lege velden vallen niet om die spaties in te vullen.

Dit is prima in de tests, maar in de definitieve versie zou het schadelijk zijn voor het spel om dingen te laten zoals ze zijn, dus het volgende dat we gaan toevoegen is "zwaartekracht" waardoor de blokken vallen en vullen lege ruimtes wanneer andere blokken worden vernietigd.

De manier waarop we dit systeem zullen implementeren is eigenlijk vrij eenvoudig. We zullen een cheque uitvoeren met behulp van de Blok> overlapt bij offset evenement om te zien of er een blok onder het blok is waar we naar kijken. Als we merken dat er geen blok is, verplaatsen we het blok waar we naar kijken om de lege ruimte in te vullen; anders zullen we niets doen.

Om dit te laten werken, zullen we een nieuw evenement maken:

Gebeurtenis: Voorwaarde: INVERT> Blokkering> Is overlappend bij offset Object = Blokkeer offset X = 0 Verschuiving Y = 8 Actie: Blokkeren> Bewegen met een hoek Hoek = 90 Afstand = (Blokkeren. Breedte + 2) / 2

Uw code zou er als volgt uit moeten zien:


Als je het spel op dit moment uitvoert, zie je dat vanaf het moment dat het spel begint, alle blokken van het scherm vallen! De reden hiervoor is dat we niets in de code hebben gestopt om te vertellen waar de "vloer" van het speelveld zou zijn.

Dus in essentie realiseren de Blokken op de onderste rij zich dat er geen Blokken onder hen zijn en vallen dienovereenkomstig. Dan, zodra de onderste rij blokken is gevallen, ziet de volgende onderste rij dat er nu geen blokken onder hen zijn en ook deze vallen. Dit proces gaat door totdat alle blokken zijn gevallen en het scherm volledig leeg is.

Je kunt een enigszins vertraagde versie hiervan in actie zien in de GIF hieronder:


Om dit te verhelpen, voegen we een tweede voorwaarde toe aan het Evenement.

Evenement: Voorwaarde: Blok> Vergelijk Y-vergelijking = Minder of gelijk Y = SPAWNY - 1

Uw code zou er nu als volgt uit moeten zien:


Door deze nieuwe voorwaarde toe te voegen, zorgen we ervoor dat alleen blokken boven de Y-positie van de onderste rij worden beïnvloed door onze "zwaartekracht". Ondanks deze oplossing hebben we nog steeds een paar problemen.

Omgaan met slepen

Het grootste probleem is dat de gebeurtenis die kijkt of er een lege ruimte onder een blok is, niets te vertellen heeft dat hij inactief is wanneer de speler een blok sleept. Dit betekent dat, als je een blok te ver sleept zonder het los te laten, de blokken in de positie boven waar je het hebt gesleept, in de ruimte vallen die is achtergelaten door het blok dat je hebt gesleept. Bovendien zal het blok dat je sleept ook een probleem hebben als je het uit het speelveld haalt, en het zal beginnen weg te vallen van de muiscursor omdat er geen blokken eronder zijn.

Om dit probleem te verhelpen, moeten we een nieuwe globale variabele toevoegen om het systeem te laten weten wanneer we een blok verplaatsen, een nieuwe actie naar het slepen en neerzetten van gebeurtenissen om deze algemene variabele in te stellen, en een derde voorwaarde voor de zwaartekrachtgebeurtenis dus deze variabele in aanmerking te nemen alvorens te activeren.

Laten we eerst de globale variabele maken:

Global Variable: Name = BlockBeingMoved Type = Number Initial Value = 0

Uw variabele zou er als volgt uit moeten zien:


Ga nu naar de Start DragDrop met slepen evenement en voeg een nieuwe actie toe:

Actie: Systeem> Waardevariabele instellen = Blokkeren Gemeste waarde = 1

Ga ook naar de Op DragDrop-drop evenement en voeg een nieuwe actie toe aan de primaire gebeurtenis:

Actie: Systeem> Waardevariabele instellen = Blokkering wijzigenWaarde = 0

Met de toegevoegde regels moeten je DragDrop-evenementen er nu als volgt uitzien:


Ga ten slotte naar het zwaartekrachtevenement en voeg een nieuwe voorwaarde toe:

Voorwaarde: Systeem> Variabele variabele vergelijken = BlockBeing Gemaskeerde vergelijking = Gelijk aan waarde = 0

Je zwaartekrachtcode zou er nu als volgt uit moeten zien:


De nieuwe variabele die we hebben gemaakt, BlockBeingMoved, wordt gebruikt om het systeem te vertellen wanneer een blok door de speler wordt verplaatst. Als de variabele gelijk is aan 0 het betekent dat geen enkel blok wordt verplaatst en dat het de zwaartekrachtscenario's normaal kan uitvoeren. Als de variabele gelijk is aan 1, het betekent een blok is worden verplaatst en de zwaartekrachtscripts niet mogen worden uitgevoerd.

Als u het spel nu uitvoert, ziet u dat ongeacht waar u het blok verplaatst terwijl u het sleept, er geen problemen optreden.

Controleren op nieuwe overeenkomsten

Nu hebben we nog maar een laatste probleem om het zwaartekrachtsysteem aan te pakken. Start het spel en maak een vergelijkbaar scenario als dit:


Maak nu de swap die ik heb gemarkeerd in deze volgende afbeelding.


Je moet opmerken dat wanneer de groep Green / Star Blocks wordt vernietigd, een oranje / hexagon blok valt en een groep van drie blokken vormt, maar niet wordt vernietigd.

De reden dat deze blokken niet worden vernietigd, is omdat we nooit het FindMatches een tweede keer werken om te zien of er nieuwe matches werden gevormd toen de blokken vielen om de lege velden in te vullen. Om dit op te lossen, ga je naar het Evenement dat controleert op lege ruimtes onder Blokken en dit Else Evenement toevoegen:

Evenement: Voorwaarde: Systeem> Anders Actie: Functie> Oproepfunctie Name = "FindMatches"

Uw code zou er als volgt uit moeten zien:


Deze else-instructie betekent dat wanneer er wordt vastgesteld dat er geen lege spaties zijn, deze een vinkje zullen plaatsen om te zien of er groepen te vernietigen zijn. Deze gebeurtenis wordt automatisch uitgevoerd wanneer blokken in nieuwe posities vallen, omdat deze wordt geactiveerd door een Else-instructie die aan die controle is gekoppeld en pas wordt geactiveerd zodra is vastgesteld dat alle blokken op hun plaats zijn gevallen.

Als je het spel nu uitvoert, zul je merken dat je nu blokken met blokken kunt maken door blokken te vernietigen op een manier dat er groepen worden gevormd wanneer de resterende blokken vallen. Bovendien zul je ook merken dat wanneer je het spel voor het eerst start, alle groepen die in eerste instantie worden uitgezet ook worden vernietigd. Zoals ik in de vorige tutorial al zei, zullen we uiteindelijk gemaakte matches elimineren, dus dit probleem zal uiteindelijk niet van belang zijn.

Blokken verwijderen van de oorspronkelijke lay-out

Ten slotte moeten we nog een ding doen voordat we ons zwaartekrachtsysteem compleet kunnen maken. Afhankelijk van waar je de eerste Block-sprite hebt geplaatst toen je de eerste tutorial voltooide, zul je merken dat wanneer je de game start, deze valt en zichtbaar wordt.

Als je niet weet wat ik bedoel, ga dan naar Layout 1, stel de positie van uw bloksprite in in 521, -32, en voer het spel uit. Wanneer je het spel speelt, zou je het originele Blok moeten zien verschijnen in de positie die ik heb gemarkeerd in de onderstaande afbeelding:


Zoals je kunt zien in de bovenstaande afbeelding, valt het eerste blok uit zijn positie buiten het scherm en wordt zichtbaar. We willen dit niet omdat het ons later alleen maar problemen zal bezorgen. Om dit kleine probleem op te lossen gaan we een actie toevoegen aan de Aan het begin van de lay-out gebeurtenis die alle blokken vernietigt die zich in de lay-out bevinden wanneer deze in eerste instantie wordt geladen.

Actie: blokkeren> vernietigen

Uw evenement zou er nu als volgt uit moeten zien:


Wanneer u het spel nu uitvoert, zou u het blok niet langer moeten zien. U vraagt ​​zich misschien af ​​waarom we het blok niet alleen uit de lay-out hebben verwijderd, we hoeven ons dus helemaal geen zorgen te maken over dit probleem. De reden dat we dit niet hebben gedaan is omdat Construct 2 geen kopieën van elk objecttype met gebeurtenissen kan maken, tenzij er al een instantie van dat objecttype in het spel is wanneer het voor het eerst wordt geladen. Door het te verwijderen binnen een evenement, verwijderen we het zodat het later geen probleem meer wordt, en we maken het mogelijk om zoveel blokken te spawnen als we nodig hebben via code.


Conclusie

We hebben veel onderwerpen behandeld in deze zelfstudie, en hoewel er meer is dat we zouden kunnen doen, vind ik het belangrijk om een ​​pauze te nemen en deze informatie te laten inzinken. In de volgende aflevering zullen we een paar kleine problemen oplossen, maken de mooie tekst met zwevende punten die je misschien hebt opgemerkt, staat in de definitieve demo en het ketensysteem is opgezet.

Ik hoop dat je veel uit dit deel van de serie hebt gehaald, en ik zie je hier volgende week terug.