Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Veldig mange spill er basert på et rutenett som "spillverden". Opplagte eksempler er brikke-/brettspill som sjakk, othello, tripp-trapp-tresko, fire-på-rad og 15-puzzle (hva heter det på norsk?), men også mange spill hvor en figur beveger seg rundt i en 2D-verden er av denne typen, f.eks. Sokoban og Boulderdash. Til og med Snake og Tetris kan lages som et rutenettspill, selv om hver enkelt fallende brikke dekker flere ruter.

...

For hver type ruteverdi, så må en velge ikon/bilde, og dette kan ofte gjøres enkelt ved strategisk navngiving av bilde-filene. Hvis en f.eks. bruker tall eller tekst, så kan en bare navngi bildet ette verdien, f.eks. 1.png eller player.png. En kan også lage en oversettelsestabell som gir koblingen litt løsere, f.eks. ved å bruke java.util.Map og legge inn koblingen med put-metoden, f.eks. map.put("player", "player32x32.png"). Siden alle bildefiler gjerne ligger i samme mappe og har samme filendelse, så er det greit å lage en egen metode som legger dette til det logiske navnet, f.eks. 

Code Block
String getImageFilename(String imageName) {
   return FOLDER_NAME + "/" + imageName + IMAGE_EXT;
}

Oppdateringsmetoder for logiske handlinger i spillet

For hver lovlige handling i spillet, så lager en gjerne en En lager enkle metoder/funksjoner for å oppdatere rutenettet i henhold til reglene for spillettilsvarende. En metode for å flytte en brikke må f.eks. først blanke ut ruta som brikken flyttes fra, f.eks. flytt brikke eller spiller.

Hver gang rutenettet endres, så må en huske på å oppdatere grafikken, altså ikonene/bildene for rutene som ble endret.

Nå en mottar museklikk eller tastetrykk, så må disse "oversettes" til en av de lovlige handlingene.

 

...

. sette den til null og deretter sette ruta som brikken flyttes til. Dersom det er spilleren som flyttes, så må også koordinatene til spilleren endres. Her er et eksempel på en slik metode:

Code Block
void movePlayer(int dx, int dy) {
   setCell(playerX, playerY, null); // blanker ruta hvor spilleren sto
   playerX = playerX + dx; // juster x-koordinatet
   playerY = playerY + dy; // juster y-koordinatet
   setCell(playerX, playerY, PLAYER_VALUE); // endrer (verdien i) den nye ruta
}

For hver handling, så kan det også være praktisk å ha en egen metode som sjekker om handlingen er lov, så en kan sjekke det før handlingsmetoden kalles.

Oppdatering av grafikken

For hver endring av rutenettet, så må en passe på at grafikken også oppdateres. Hvis ikke vil ikke spilleren se det samme rutenettet som spillet holder rede på. Det er greit å lage en egen metode for dette, f.eks. kalt updateCell(x, y). Denne må hente ut ruteverdien, velge tilsvarende bilde og vise det frem. Noen ganger er det greit å kalle updateCell-metoden for hver endring av en enkeltrute, mens det andre ganger er bedre å først gjøre mange rute-endringer, før en oppdaterer de tilsvarende bildene ved gjentatte kall til updateCell. Hvis ikke brettet er alt for stort, så er det mulig å gå gjennom hele brettet for hver logiske handling, ved f.eks. å ha en updateGrid-metode som kalles nederst i hver oppdateringsmetode for de logisk handlingene. Selv om det kan være ineffektivt, så går det ofte fort nok. En mellomting er også mulig, hvor en har en updateCells(x, y, w, h)-metode som kaller updateCell(x, y) for hver rute i en del av rutenettet (angitt av en x,y-posisjon og bredde/høyre).

Akkurat hva updateCell-metoden gjør er avhengig av hvordan grafikken er utformet, men det typiske er å bruke en egen UI-komponent for rutenett, f.eks. JavaFX sin GridPane eller en egen klasse for bildebasert "flislegging" (se nedenfor). updateCell-metoden vil da bruke UI-komponenten sin(e) metode(r) for å endre innholdet og angi hvilket bilde (evt. bildefil) som skal ligge i en bestemt rute. Merk at det er viktig å skille mellom bilde-objektet (som inneholder bilde-dataene og gjerne heter Image eller lignende) og objektet som viser frem bilde-objektet (heter gjerne ImageView eller Label). En trenger bare ett bilde-objekt for hver brikke/rutetype, og så sørger en for å vise disse frem i alle tilsvarende ruter.

Oversettelse av musklikk og tastetrykk

Ved oppstart/initialisering av hele spill-appen så må en sørge for å registrere hvilke metoder som skal kalles når brukeren klikker med musa og trykker på tastene. Disse metodene tar gjerne et hendelsesobjekt som argument, og dette objektet inneholder mer informasjon om posisjonen til muspekeren og hvilken tast (eller taster) som ble trykket.

Muspekeren forholder seg til grafikk-koordinater (hver lille skjermprikk er et eget punkt) som er noe annen enn rutenettet-koordinater (hvor hver rute er et punkt), og derfor må en regne om disse.

Ved tastaturbasert styring, så må en finne ut hvilken tast som ble trykket og velge logisk spillhandling deretter, f.eks. flytte spiller-figuren opp/ned/ eller mot venstre/høyre med tilsvarende piltaster. Merk at en skiller mellom taste-koden (som oftest en int) og taste-tegnet og at ikke alle taster har et tegn. Derfor er det greiest sjekke taste-koden.

Enkle gjenbrukbare JavaFX-klasser for rutenett-baserte spill

Siden alt dette er nokså generelt og uavhengig av hvert spill, så er det ikke så vanskelig å lage litt generell kode, som kan en kan (gjen)bruke i hvert spill en lager. Dersom en bruker et objektorientert språk som Java eller C++ (forsåvidt også Python og Javascript), så kan den gjenbrukbare koden legges i en superklasse, som en så arver fra i klassene for hvert spesifikke spill. Vi har laget to slike klasser for bruk med JavaFX. Den ene heter ImageGridGame og er klassen som spill-appen skal arve fra, mens den andre heter ImageGrid og brukes for å håndtere visning av bildene i rutenettet i app-vinduet. Vi har laget to eksempelspill som bruker ImageGridGame og ImageGrid, som du kan ta som utgangspunkt for dine egne spill.

Les mer om ImageGridGame og ImageGrid her: Rutenettspill-klassene ImageGridGame og ImageGrid.

Les mer om eksempelspillene Eat og Bubble her: Eksempelspillet Eat og Eksempelspillet Bubble.