Bygg et gridbasert puslespill som minesveiper i enhet interaksjon

Vi fortsetter å bygge vårt nettbaserte puslespillspill ved å koble sammen flisene til hverandre, få dem til å lyse opp med musemarkøren og legge til muligheten til å plassere flagg.

I den siste delen av denne opplæringen opprettet vi et felt av fliser som danner grunnlaget for vårt puslespill. I denne delen vil vi gjøre det mulig å spille. Denne opplæringen følger direkte fra siste del, så les det før du starter dette.

Belysning Fliser Up på Mouseover

Når musen er over en flis, vil vi at den skal lyse opp. Dette er en kul funksjon som gir enkle, enkle handlinger (for eksempel flytte musepekeren) øyeblikkelig tilbakemelding.

Vi bruker Onmouseover () funksjon for å oppnå dette. Den blir automatisk kalt når musepekeren beveger seg over objektet koden er knyttet til. Legg til disse variablene i Tile manus:

offentlig var materialeIdle: Materiale; offentlig var materialLightup: Materiale;

Tilordne deretter ditt grunnleggende flisemateriale til materialIdle slot. Vi trenger også en lyse opp materiale, som burde ha samme farge, men bruker en annen skygge. Mens det grunnleggende materialet kan ha en diffuse shader ...

... lysbildematerialet kunne ha en speil shader. Mange spill bruker også en ekstra rim shader for den effekten. De kommer ikke med Enhet, men hvis du kan finne ut hvordan du får en, kan du bruke det i stedet!

Ikke glem å faktisk tildele materialene til Materiale slots på flis prefab, slik at de kan brukes.

Legg deretter til dette Onmouseover () funksjon til Tile manus

funksjon OnMouseOver () renderer.material = materialLightup; 

Prøv det! Når du beveger musepekeren over flisene, bør de endre utseendet deres.

Det du kanskje har lagt merke til er at flisene endrer utseendet deres når musen er over dem, men endrer seg ikke tilbake. For det må vi bruke OnMouseExit () funksjon:

funksjon OnMouseExit () renderer.material = materialIdle; 

Og voilá; Vi har nå fliser som lyser opp og gjør spillet mye mer interessant.

Tilordne IDer til fliser

For å få flisene kommuniserer med hverandre (for å finne ut hvor mange gruver er i nærheten), må hver fliser kjenne sine nabobilder. En måte å oppnå som bruker ID, som hver flis vil bli tildelt.

Begynn med å tilpasse Tile-koden for å inkludere en ID variabel. Legg også til en variabel for å holde antall fliser per rad, som vi skal bruke i denne beregningen:

offentlig var ID: int; offentlige var fliserPerRow: int;

Endre deretter instantiate-kommandoen i gridkoden for å se ut som følgende utdrag. (Den nye linjen tildeler IDer til fliser som de blir opprettet.)

var newTile = Instantiate (tilePrefab, Vector3 (transform.position.x + xOffset, transform.position.y, transform.position.z + zOffset), transform.rotation); newTile.ID = fliserCreated; newTile.tilesPerRow = fliserPerRow;

Den første flisen vil få ID 0, den neste vil bli tildelt ID 1, og så videre. Du kan sjekke dem ved å klikke på flisene under kjøretid, og se hvilket nummer de har blitt tildelt.

Å få nabobilder

Nå ønsker vi at hver flis skal vite om sine nabobilder. Når vi utfører en handling på en flis (for eksempel å avdekke den), må vi ta hensyn til nabostaten.

I vårt tilfelle betyr dette å telle gruvene som ligger ved siden av flisen vi bare har avdekket, og muligens avdekke andre fliser også, men vi kommer til det senere.

Dette kan også brukes til å si om tre eller flere fliser er ved siden av hverandre i et Match-3-spill.

Begynn med å legge til disse variablene i fliseskriptet:

offentlige var fliser: fliser; offentlige var fliserLower: Tile; offentlige var fliser: flis; offentlig var tile rett: flis; offentlig var tileUpperRight: Tile; offentlig var tileUpperLeft: Tile; offentlig var tileLowerRight: Tile; offentlige var fliserLowerLeft: Tile;

Disse vil holde alle nabofliser. De er offentlige slik at vi kan sjekke i løpet av kjøretiden at de faktisk har blitt tildelt riktig.

Siden nå har hver flis en ID, antall fliser som vises i en kolonne, og tilgang til det statiske oppsettet som har alle fliser lagret i Nett klasse, kan vi beregne posisjonene til nabostaten etter at de er opprettet.

Den delen ser slik ut:

tileUpper = Grid.tilesAll [ID + tilesPerRow]; tileLower = Grid.tilesAll [ID - tilesPerRow]; tileLeft = Grid.tilesAll [ID - 1]; tileRight = Grid.tilesAll [ID + 1]; tileUpperRight = Grid.tilesAll [ID + tilesPerRow + 1]; tileUpperLeft = Grid.tilesAll [ID + tilesPerRow - 1]; tileLowerRight = Grid.tilesAll [ID - tilesPerRow + 1]; tileLowerLeft = Grid.tilesAll [ID - tilesPerRow - 1];

Med ID og antall fliser per rad, kan vi beregne hvilke fliser i nærheten. Anta at flisen gjør beregningene har ID 3, og at det er fem fliser per rad. Flisen over den vil ha ID 8 (den valgte flisens ID pluss antall fliser per rad); flisen til høyre vil ha ID 6 (den valgte flisens ID pluss en), og så videre.

Dessverre er dette ikke nok. Koden kontrollerer riktig tallene, men når den spør allTiles array for å returnere fliser, kan det be om indeksnumre som er utenfor rekkevidde, og produserer en lang liste over feil. 

For å fikse dette må vi kontrollere at indeksen vi ber om fra arrayet, faktisk er gyldig. Den mest effektive måten å gjøre dette på er med en ny på banen () funksjon. Legg det til flisene:

privat funksjon iBounds (inputArray: Array, targetID: int): boolean if (targetID < 0 || targetID >= inputArray.length) returnere false; ellers returnere sant; 

Nå må vi sjekke at alle mulige nabofliser ligger innenfor grensene til matrisen som holder alle fliser, før vi faktisk prøver å få det fra matrisen:

hvis (inBounds (Grid.tilesAll, ID + tilesPerRow)) tileUpper = Grid.tilesAll [ID + tilesPerRow]; hvis (inBounds (Grid.tilesAll, ID - tilesPerRow)) tileLower = Grid.tilesAll [ID - tilesPerRow]; hvis (inBounds (Grid.tilesAll, ID - 1) && ID% tilesPerRow! = 0) tileLeft = Grid.tilesAll [ID - 1]; hvis (inBounds (Grid.tilesAll, ID + 1) && (ID + 1)% tilesPerRow! = 0) tileRight = Grid.tilesAll [ID + 1]; hvis (inBounds (Grid.tilesAll, ID + tilesPerRow + 1) && (ID + 1)% tilesPerRow! = 0) tileUpperRight = Grid.tilesAll [ID + tilesPerRow + 1]; hvis (inBounds (Grid.tilesAll, ID + tilesPerRow - 1) && ID% tilesPerRow! = 0) tileUpperLeft = Grid.tilesAll [ID + tilesPerRow - 1]; hvis (inBounds (Grid.tilesAll, ID - tilesPerRow + 1) && (ID + 1)% tilesPerRow! = 0) tileLowerRight = Grid.tilesAll [ID - tilesPerRow + 1]; hvis (inBounds (Grid.tilesAll, ID - tilesPerRow - 1) && ID% tilesPerRow! = 0) tileLowerLeft = Grid.tilesAll [ID - tilesPerRow - 1];

Den koden blokkerer alle mulighetene. Det kontrollerer også om en flis ligger på kanten av feltet. En flis på høyre kant av rutenettet har trods alt ikke noen fliser til sin Ikke sant.

Prøv det! Kontroller noen få fliser og se om du har hentet alle nabostaten riktig. Det skal se slik ut:

Siden flisen i dette skjermbildet er en flis på høyre kant av feltet, har den ingen naboer til høyre, øverst til høyre eller nedre til høyre. Variablene uten tildelte fliser er riktig tomme, og en test viser at de resterende har blitt tildelt riktig også.

Til slutt, når vi har sørget for at dette virker, legger vi alle nabosteg i en matrise, slik at vi kan få tilgang til dem alle med en gang senere. Vi må deklarere denne gruppen i begynnelsen:

public var adjacentTiles: Array = new Array ();

Du kan deretter tilpasse hver linje i algoritmen vi opprettet over for å gå inn i hver nærliggende flis i den gruppen, eller legg til denne blokken etterpå:

hvis (tileUpper) adjacentTiles.Push (tileUpper); hvis (tileLower) adjacentTiles.Push (tileLower); if (tileLeft) adjacentTiles.Push (tileLeft); hvis (tileRight) adjacentTiles.Push (tileRight); hvis (tileUpperRight) adjacentTiles.Push (tileUpperRight); hvis (tileUpperLeft) adjacentTiles.Push (tileUpperLeft); hvis (tileLowerRight) adjacentTiles.Push (tileLowerRight); hvis (tileLowerLeft) adjacentTiles.Push (tileLowerLeft);

Teller nærliggende miner

Etter at alle fliser er blitt opprettet, har alle gruver blitt tildelt, og hver flis har hentet naboene sine, vi må da sjekke om hver av disse nabostaten er utvannet eller ikke.

Grid-koden tildeler allerede spesifisert antall gruver til tilfeldig valgte fliser. Nå trenger vi bare hver flis for å sjekke naboene sine. Legg til denne koden i begynnelsen av Tile script, slik at vi har et sted å lagre mengden av gruver:

offentlig var tilstedeMines: int = 0;

For å telle dem, løper vi gjennom matrisen som vi tidligere har lagt til alle nabolagene, og kontroller hver oppføring i sin tur for å se om den er utvunnet. I så fall øker vi verdien av adjacentMines med 1.

funksjon CountMines () adjacentMines = 0; for hver (var currentTile: Tile in adjacentTiles) hvis (currentTile.isMined) adjacentMines + = 1; displayText.text = adjacentMines.ToString (); if (adjacentMines <= 0) displayText.text = ""; 

Denne funksjonen setter også tekstelementet i flisen for å vise antall miner i nærheten. Hvis det ikke er noen gruver, viser det ingenting (heller enn 0).

Spore statusen til hvert mine

La oss legge til en stat til hver flis. På denne måten kan vi holde oversikt over hvilken stat den er inne i-tomgang, avdekket, eller flaggede. Avhengig av hvilken tilstand flisen er i, vil den reagere annerledes. Legg til det nå, siden vi bruker det på et øyeblikk.

offentlig var stat: String = "tomgang";

Legge til flagg

Vi ønsker å kunne markere fliser som flaggede. En flagget flis har et lite lite flagg på toppen av det. Hvis vi høyreklikker på flagget vil det forsvinne igjen. Hvis alle gruver fliser er flagget, og ingen feil merket fliser forbli, er spillet vunnet.

Start med å lage et flaggobjekt, og legg det til flisen (du finner et flaggmask i kildefilene).

Vi trenger også en variabel for å få tilgang til flagget. Legg til denne koden:

offentlig var displayFlag: GameObject;

Husk å dra flagget som er en del av flisen på displayFlag slot.

Legg også til dette i start() funksjon av flisen:

displayFlag.renderer.enabled = false; displayText.renderer.enabled = false;

Dette vil deaktivere flagget og teksten i begynnelsen. Senere kan vi da aktivere et flagg, noe som gjør det synlig igjen, effektivt å sette det der. Alternativt, hvis vi avdekke en flis, vi gjør teksten synlig igjen.

Plassere og fjerne flagg

Vi skriver en funksjon som håndterer både plassering og fjerning av flagg:

funksjon SetFlag () hvis (tilstand == "tomgang") state = "flagged"; displayFlag.renderer.enabled = true;  annet hvis (tilstand == "flagget") state = "idle"; displayFlag.renderer.enabled = false; 

Når du har lagt til det, legger du også til koden for å håndtere et klikkhendelse. For å gjøre dette, må du tilpasse Onmouseover () funksjon vi må allerede sjekke for et museklikk:

funksjon OnMouseOver () if (state == "idle") renderer.material = materialLightup; hvis (Input.GetMouseButtonDown (1)) SetFlag ();  annet hvis (tilstand == "flagget") renderer.material = materialLightup; hvis (Input.GetMouseButtonDown (1)) SetFlag (); 

Dette vil gjenkjenne et høyreklikk (knapp 1) og aktivere SetFlag () funksjon. Det vil da enten aktivere eller deaktivere flagget på den aktuelle flisen. Prøv det!

Konklusjon

Vi har utvidet vårt puslespill med flere viktige funksjoner, gjort det visuelt mer interessant, og har gitt spilleren muligheten til å påvirke spillefeltet.

Neste gang legger vi til avdekking av fliser, gjør et enkelt grensesnitt, og gjør dette til et riktig spill.