Tiden er endelig kommet: Vi er nesten ferdig med spillet vårt, og er klare til å implementere den endelige spillmekanikeren. Denne artikkelen vil fokusere på å lage et kombinationssystem som gir spilleren flere poeng for å skape kjeder som ødelegger flere grupper av blokker etter bare ett bytte.
I tillegg vil vi implementere tapsscenariet og legge til et spill over skjermbilde. Til slutt vil jeg snakke om ting du kan jobbe med i din egen tid for å forbedre og utvide spillet utover det vi har dekket. Så, uten videre, la oss komme i gang ...
Her er en demonstrasjon av spillet vi har jobbet med, og som vi vil ha bygget på slutten av denne delen av serien:
Før vi går videre til hovedartikkelen, vil jeg gjøre en liten endring til når FindMatches
blir kalt.
Under arbeidet med denne artikkelen oppdaget jeg et problem som du kan se i GIF nedenfor:
Som du kan se i denne første GIF, når en blokk blir tapt bare en blokk avstand for å prøve å danne en kamp med en gruppe blokker nederst på høsten, virker det perfekt.
I denne andre GIF blir det imidlertid klart at når en blokk blir tapt en større avstand i samme scenario, feiler det ikke å oppdage kampen før vi utfører en annen bytte. Årsaken til dette er at spillet ikke leter etter kamper ofte nok.
For øyeblikket ser spillet bare etter kamper etter en bytte, men på grunn av hvor lang tid det tar en blokk å falle denne avstanden, har kampdeteksjonen allerede avsluttet når Blokken treffer bakken og så kampen er ikke funnet før det er gjenopprettet.
For å fikse dette, endrer vi når vi utfører en FindMatches
kryss av.
Først gå til SwapBlocks
funksjon og fjern den siste hendelsen fra funksjonen slik at den ikke ringer FindMatches
i det hele tatt.
SwapBlocks
skal se slik ut nå:
På dette punktet er det ingen Hendelsesoppringing FindMatches
. Vi løser dette ved å legge til en ny handling til arrangementet som oppdager når kampene er mulige. Finn denne hendelsen og legg til denne handlingen til slutten av den andre hendelsen:
Handling: Funksjon> Anropsfunksjon Navn = "FindMatches"
Din begivenhet skal nå se slik ut:
Ta også denne sjansen til å flytte begge MatchesPossible
Hendelser til slutten av spillkoden, hvis du ikke allerede har det. Å gjøre dette vil sikre at de ikke blir kalt i det hele tatt før koden, som eliminerer forhåndsdefinerte kamper.
Hvis du kjører spillet nå, bør du kunne utføre scenariet jeg presenterte ovenfor uten problem.
Med det problemet fast, skal vi implementere kjeding system, som gir spilleren ekstra poeng for kamper som er forårsaket av ødeleggelsen av en annen kamp.
Du kan se et eksempel på typen situasjon jeg mener under:
I det ovennevnte scenariet beveger spilleren den grønne blokken og oppretter en kamp. Da ødeleggelsen av de grønne blokkene får de blå blokkene til å falle og skape en annen kamp øyeblikk senere.
Jeg vil gi spilleren bonuspoeng for å oppnå noe som dette. Spesielt vil jeg bruke en multiplikator til antall poeng spilleren mottar for hver kamp, og har multiplikatorøkningen med hver sammenheng som er laget.
For å få dette systemet til å fungere, skal vi lage en ny variabel som heter Kjede
, og gjør deretter noen få små modifikasjoner til de eksisterende funksjonene. Så først opprett en ny Global Variabel:
Global Variabel: Kjede Type = Antall Initial Verdi = 0
Din variabel skal se slik ut:
Denne variabelen vil fungere som en multiplikator for punktene å fortelle hvor lenge en kjede har gått.
Gå nå til arrangementet som får blokkene til å falle, og fjern Else Event som ringer til FindMatches
funksjon.
Gå nå til FindMatches
seg selv og finn stedene hvor du lager FloatingPointsText
objekter. Endre Set-setningene slik at de bruker en ny formel:
Handling: FloatingPointsText> Angi tekst Tekst = NumMatchesFound * 10 * Chain
Denne endringen gjør at flytende tekst blir endret på samme måte som poengene selv etter hvert vil.
Deretter går du til delen av FindMatches
hvor du ringer FindMatches
igjen på slutten av hendelsen, og slett dette funksjonsanropet og ventetilstanden. Hvorfor? Fordi, hvis vi ikke fjernet disse, da FindMatches
ville ende opp med å bli kalt for mange ganger, og kjedene ville aldri bli initiert riktig.
(På grunn av endringene vi gjorde tidligere i denne artikkelen, FindMatches
vil bli kalt når alle blokker er i rutenettet og ingen faller. Å ha flere områder der vi ringer FindMatches
ville bare føre til at flere forekomster av funksjonen kjører samtidig, og kan ødelegge poengsystemet.)
Til slutt vil vi gjøre en annen endring til denne funksjonen. Gå til slutten av funksjonen og legg til denne handlingen når du har satt inn PointsGiven
til 0
:
Handling: System> Legg til Variabel = "Kjede" Verdi = 1
Nå, når spillet finner kamper, gir det spilleren poeng, ødelegger blokkene, og øker deretter kjedeverdien.
Den nye versjonen av FindMatches
skal se slik ut:
Deretter går du til GivePoints
funksjon og endre begge handlinger som øker verdien av poengsummen slik at de tar hensyn til kjedeverdien:
Handling: System> Legg til Variabel = Score Verdi = 10 * Kjede
Med denne endringen, GivePoints
skal nå se slik ut:
Vi har implementert den variable kjeden som en multiplikator for poengene spilleren mottar (og antall poeng som vises i flytende tekstobjekter), men det er fortsatt en ting vi må gjøre: vi må legge til en uttalelse som tilbakestiller verdien av kjeden slik at den ikke bare vil øke uendelig.
Vi skal legge til denne uttalelsen til På DragDrop Start Hendelse slik at når spilleren begynner å dra en ny blokk, betraktes det som en ny kjede. Den andre grunnen til at vi gjør det her, er fordi det forhindrer at kjedeværdien blir tilbakestilt for tidlig, og dermed gjør alle kampene i den siste delen av en kjede mindre verdifulle.
Gå til På DragDrop Start Hendelse og legg til denne handlingen i handlingslisten:
Handling: System> Angi verdi Variabel = Kjedeverdi = 1
Din begivenhet skal nå se slik ut:
Hvis du tester spillet på dette tidspunktet, bør du se at hvis du lager en kjede som den jeg viste i gif tidligere, får du 90 poeng i stedet for 60 poeng.
Med dette arbeidet er kjedingssystemet komplett, og du bør kunne lage en så utførlig kjede som du vil uten problem.
Det neste jeg vil dekke er et problem jeg har funnet med Block falling system. Hvis du bruker mye tid på å spille vårt Match-3-spill i sin nåværende tilstand, kan det hende du har lagt merke til et problem hvor, hver gang, vil en blokk ikke falle selv om det ikke er noen blokk under den.
Du kan se hva jeg mener i bildet nedenfor:
Til tross for at det ikke er noen blokk under den gule blokken, har den fortsatt mislyktes i det tomme rommet. Dette er et sjeldent problem, men hvis det ikke håndteres, kan det fortsatt ødelegge andres score og forhindre at de mottar en kjede de har satt opp, eller til og med at de mister når vi legger til spilloverfunksjonen.
Problemet kommer fra variabelen BlockBeingMoved
, som brukes av hendelsen som bestemmer når blokker skal falle for å sikre at det ikke er blokker flyttes når det forteller en blokk for å fylle ut et tomt rom. I noen scenarier, når spilleren beveger en blokk, tilbakestilles denne variabelen aldri, og blokkene faller ikke til en annen blokk er flyttet og den tilbakestilles på riktig måte. For å fikse dette, skal vi legge til et par hendelser som vil angi og tilbakestille denne variabelen riktig, og vi vil fjerne de gjeldende handlingene som angir variabelen, siden de ikke fungerer riktig.
Først, gå til OnDragDrop Start
og På DragDrop Drop
Hendelser, og fjern alle handlingene som omhandler BlockBeingMoved
variabel fra disse hendelsene. Det bør være en handling i hver hendelse som må slettes.
Deretter går du til hendelsen som oppdager når det er tomt plass under en blokk. Vi skal endre vilkårene for denne hendelsen. Først må du kontrollere at tilstanden som kontrollerer om BlockBeingMoved
er lik 0
er i begynnelsen. Deretter legger du til en annen betingelse til slutten av hendelsen som kontrollerer for å sikre at ingen blokker blir flyttet.
Dette er betingelsen du vil legge til:
Tilstand: Omvendt: Blokk> Skråner
Din begivenhet skal nå se slik ut:
Til slutt skal vi legge til to hendelser på slutten av Event Sheet som vil håndtere BlockBeingMoved
variabel. Gå til slutten av din Event Sheet og legg til disse hendelsene:
Hendelse: Tilstand: Blokk> Skråner Handling: System> Angi variabelnavn = BlockBeingMoved Value = 1
Hendelse: Tilstand: System> Øvrig handling: System> Angi variabelnavn = BlockBeingMoved Value = 0
Dine nye arrangementer skal se slik ut:
Disse hendelsene vil effektivt forandre seg BlockBeingMoved
fra 0
til 1
og fra 1
til 0
når en blokk blir flyttet, eller er ikke flyttes, henholdsvis. Hvis du tester spillet på dette tidspunktet, bør du kunne spille så mange ganger du vil uten å møte problemer med Block falling.
Nå som vårt kjedingssystem er på plass, vil vi legge til tapsscenariet og en Game Over-skjerm.
Det første vi må gjøre er å legge til en ny layout som vil fungere som vår spill over skjerm:
-6, -7
.613, 619
.303, 200
.RestartButton
.262, 410
.100, 30
.Omstart
.Nå som du har opprettet Game Over-skjermen, går du tilbake til den opprinnelige utformingen, Layout 1, og legg til ett nytt element på skjermen:
GameOverArea
.196, -30
.344, 150
.0
.Du bør legge merke til at denne sprite er i samme posisjon og i samme størrelse som den øverste delen av spillfeltet. Vi skal bruke dette spriteobjektet til å oppdage når spilleren har mistet ved å oppdage når en blokk kolliderer med den. Gå til Event Sheet 1 så vi kan begynne å implementere dette.
Før vi begynner å oppdage tapsscenariet, må vi legge til en ny variabel som vi skal bruke for å stoppe blokkene når de treffer GameOverArea objekt slik at de ikke lenger vil bevege seg. Dette vil gjøre det klart for spilleren at de har mistet.
Global Variabel: MovementPossible Type = Antall Initial Value = 0
Gå nå til arrangementet der du flytter blokkene og legg til denne tilstanden:
Tilstand: System> Sammenlign variabel Variabel = MovementPossible Sammenligning = Likeverdig = 0
Din bevegelseshendelse skal nå se slik ut:
Nå som bevegelsen bruker vår nye variabel, legger vi til hendelsen som oppdager tapstilstanden:
Begivenhet: Tilstand: Blokk> Overlapper en annen gjenstand Objekt = GameOverArea Tilstand: Inverter: Blokk> IsDragging Action: Funksjon> Anropsfunksjonnavn = "Spill over"
Hendelsen vi nettopp har gjort, vil ringe spilloverfunksjonen en gang en blokk overlapper GameOverArea
. Nå skal vi faktisk gjøre Spillet er slutt
funksjon.
Hendelse: Tilstand: Funksjon> På funksjon Navn = "Spill over" Handling: Blokk> Angi aktivert State = Deaktivert Handling: System> Angi verdi Variabel = MovementPossible Value = 1 Handling: System> Vent sekunder = 1.5 Handling: System> Gå til layout Layout = Layout 2
Dine to nye arrangementer skal se slik ut:
Årsaken til at vi opprettet en egen funksjon i stedet for å gjøre disse handlingene i hendelsen som faktisk oppdager spillet over, er at denne hendelsen bare ser på bestemte blokker på grunn av hendelsene som utløser den. Som du kan se i funksjonen vi har gjort, deaktiverer du slettingsfunksjonene til Blokken for å hindre at spilleren fortsetter å lage kamper etter at spillet over er oppdaget. Hvis vi gjorde dette i tilfelle som oppdager spillet over, ville det bare deaktivere blokkene som forårsaket spillet over, og hver annen blokk vil fortsatt kunne bli trukket.
Nå, gå til Event Sheet 2; Vi skal legge til noen funksjonalitet til RestartButton objekt vi laget tidligere. Legg til en ny hendelse til Event Sheet 2:
Hendelse: Tilstand: RestartButton> På klikket Handling: System> Gå til layout Layout = Layout 1
Din begivenhet skal se slik ut:
Hvis du spiller spillet nå, få et spill over, og start deretter på nytt, bør du legge merke til at det går tilbake til den opprinnelige Layout, men blokkene beveger seg ikke. Årsaken til dette er at alle variablene vi har brukt, er globale variabler, så noen av dem tilbakestilles ikke automatisk når vi starter om oppsettet.
For å tilbakestille dem må vi legge til en handling i vår Ved oppstart Event som vil tilbakestille dem manuelt for oss.
Gå til Ved oppstart Hendelse og legg til denne handlingen til den første hendelsen før For-løkkene blir kalt:
Handling: System> Tilbakestill globale variabler
Din begivenhet skal nå se slik ut:
Hvis du tester igjen, bør du ikke lenger ha dette problemet.
På dette tidspunktet har vi gått over alle funksjonene som jeg ønsket å dekke innenfor omfanget av disse opplæringsprogrammene.
Du vil legge merke til at spillet ditt fortsatt ikke er nøyaktig det samme som i demoen ovenfor, med den største forskjellen er at spillet ditt ikke har en startskjerm. Jeg valgte ikke å gå over etableringen av startskjermbildet, siden det er nesten nøyaktig det samme som å lage skjermbildet Game Over - jeg lar dette være som en øvelse for deg.
I stedet skal jeg diskutere noen funksjoner du kan vurdere å legge til i spillet ditt som kan gjøre det bedre eller mer interessant.
Det første jeg vil diskutere er spesialitetsblokker - blokker som enten gir spilleren bonuser eller utfører en unik funksjon.
De fleste Match-3-spill inkluderer spesialitetsblokker for å bryte opp handlingen og gjøre spillet mer spennende. Som det står, kan spillet teoretisk gå videre for alltid, men spillingen endres aldri. Å presentere spesielle blokktyper, kan nå bidra til å gjøre spillet mer interessant når det har gått en stund.
For å integrere en spesialitetsblokk må du endre måten blokker genereres, slik at når en blokk opprettes, er det en tilfeldig tilfeldighet at det blir en spesialitetsblokk. Det finnes flere måter å gjøre dette på, men generelt er det best å bare generere et tilfeldig tall mellom 1 og 100 og bare generere en spesialitetsblokk når den tilfeldige verdien er mellom 95 og 100, eller et annet utvalg som du bestemmer deg for.
Målet ditt bør være å gjøre spesialitet blokker sjeldne, men ikke også sjelden. På denne måten får spilleren dem regelmessig nok til å gjøre spillet morsommere, men ikke så ofte at det ødelegger balansen i spillet.
Når det gjelder spesialitet blokker har du mange alternativer; en av de vanligste er a bombeblokk.
Bombblokker forårsaker at ekstra blokker blir ødelagt når de blir ødelagt. De er forskjellige i hvert spill: i noen spill ødelegger de alle blokkene som omgir dem; i andre ødelegger de en hel rad eller kolonne av blokker.
I bildet nedenfor kan du se to av bombblokkene fra det populære spillet Candy Crush Saga:
Bombblokker er generelt ganske enkle å integrere:
En annen spesialitet blokk type du finner i mange spill er en som senker hvor raskt blokkene beveger seg, eller stopper dem helt.
Blokker som disse er veldig enkle å lage.
MovementsPossible
til 1
slik at blokkene vil stoppe, eller endre hastighet
slik at blokkene beveger seg veldig sakte.Du må huske å registrere deg for spilleren som aktiverer en stoppstansblokk mens en annen stoppblokk allerede er aktiv. I dette scenariet bør du starte timeren på nytt eller legge til standardlengden til timeren til den eksisterende timeren og fortsette normalt.
Du kan også vurdere å legge til andre spillmoduser for når spilleren blir lei av den endeløse modusen vi opprettet.
Den enkleste spillmodusen du vil legge til er en hvor spilleren har en tidsbegrensning, med målet å være å få så mange poeng som de kan før tiden går ut.
I dette scenariet vil du la alle spillkoden være uberørt bortsett fra å legge til en annen tapstilstand for spillet, hvor spillet slutter når timeren løper ut (så vel som når blokkene treffer toppen av skjermen).
Når spillet starter, starter du en timer for hvor lang tid modusen varer, og når timeren slutter, vil du avslutte spillet på samme måte som du gjør nå.
I denne spillmodusen vil du gi spilleren et veldig spesifikt spillbrett som du designer på forhånd og be dem om å eliminere alle blokkene i så få swaps som mulig.
(Du vil sannsynligvis ønske å slå av blokkbevegelsen, siden hvis blokkene beveger seg, vil det også bli lagt nye blokker over tid.)
Denne modusen vil kreve at du kan sette opp et bestemt blokkrutenett, så du må ha et system som lar deg passere i et bestemt blokkoppsett når spillet starter snarere enn å generere en helt tilfeldig som vi gjør nå.
På toppen av dette, mens denne spillmodusen er relativt enkel å implementere, vil det kreve at du gjør mye manuell puslespill, slik at du kan lage mange unike oppgaver for spilleren å prøve og løse.
Å legge til en spillmodus som dette kan være ganske tidkrevende på grunn av all nødvendig innholdsopprettelse, men det er mange spillere som vil nyte det. Det kan virkelig lønne seg bra hvis du legger inn tiden.
I løpet av denne opplæringsserien bygde vi et helt match-3-spill fra start til slutt. Det er mye mer du kan gjøre med dette spillet hvis du tar deg tid og har fantasien, men det er også mange måter du kan bruke ideene jeg presenterte for å hjelpe deg med andre spillprosjekter.
Fortsett å jobbe med spillet ditt, og fortsett å utforske nye ideer, fordi du aldri vet når noe du lærte her, kan komme til nytte senere.
Jeg håper at, uansett om du gikk gjennom hele serien eller bare hoppet over til delene du ikke kunne gjøre på egenhånd, lærte du noe fra dette. Hvis du har noen problemer eller kommentarer, gi oss beskjed i diskusjonene under hver artikkel. Jeg vil gjerne høre fra deg og se hvilke vendinger du vil legge til. Uansett, takk for lesing og lykke til med spillene dine!