Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Excerpt

Mange typer spill er basert på et rutenett, hvor det som logisk sett finnes i hver rute visualiseres med et passende ikoner/bilde. På denne siden viser vi hvordan dette gjøres enkelt med JavaFX.

 

Rutenett-

...

baserte spill

Veldig mange spill er basert på et rutenett som "spillverden". Opplagte eksempler er brikke-/brettspill som sjakk, othello og , 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, Boulderdash og og Boulderdash. Til og med Tetris kan lages som et rutenettspill, selv om hver enkelt fallende brikke dekker flere ruter.

 

Felles for alle disse (kanskje utenom Tetris) er at

  • Rutenettet har en fast størrelse (størrelse endres i hvertfall ikke underveis i spillet).
  • Hver rute inneholder nokså enkel informasjon, f.eks. et tall, tegn eller tekst som svarer til et begrenset sett med brikker eller spill-objekter.
  • For hver ruteverdi så kan en nokså enkelt bestemme hvilket av et (begrenset) sett ikoner/bilder som skal illustrere rute-innholdet.
  • Styringen av spillet er nokså enkel, f.eks. med enkel klikking i ruter, styring av spiller med piltastene eller dra-og-spill av brikker.

Programmering av rutenett-baserte spill

Når en skal programmere et slikt rutenett-basert spill, så vil kodingen tilsvarende følge et mønster:

  • Rutenettet initialiseres i henhold til størrelsen og reglene for spillet, evt. innlasting av brett/nivå (level). Hvis spillet inneholder en spiller-figur, så må gjerne den plasseres i rutenettet.
  • En må lage logikk for å velge ikon/bilde, og dette kan ofte gjøres enkelt ved strategisk navngiving av bilde-filene.
  • En lager enkle metoder/funksjoner for å oppdatere rutenettet i henhold til reglene for spillet, 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.

Hver av disse punktene blir til et sett felt og/eller metoder, som vi kort skisserer under.

Representasjon og initialisering

Først må en finne hva slags type data som egner seg for å lagre informasjonen om hver rute. Hvis en har et begrenset antall brikker eller spill-elementer, så kan tall (int), tegn (char) eller tekst (String) egne seg. Siden ruter ofte kan være tomme, så kan en bruke en naturlig "null"-verdi for å angi det, f.eks. -1 eller 0 for int, '\0' eller ' ' (mellomrom) for char og null eller "" for String. En kan evt. bruke objekttypen for tall og tegn, altså Integer og Character, for å kunne bruke null for tom rute. For hver brikketype bestemmer en seg for tilsvarende verdi, og ofte har en allerede konvensjoner for dette. F.eks. har en i sjakk standardbokstaver som brukes for å angi flytt, så da kan en like gjerne bruke dem.

Ved valg av verdi, så kan det være lurt å tenke på to ting:

  • Hvis en skal lese nivå fra fil, så er det greit å velge verdier som er lette å skrive/lese til/fra et linjebasert format.
  • En må siden (skrive kode for å) velge ikon/bilde for verdien, og derfor bør en unngå spesialtegn som ikke passer i (bilde)filnavn.

Rutenettet kan lagres i en to-dimensjonal tabell (array) eller en-dimensjonal tabell eller liste, hvor en legger ut radene/kolonnene etter hverandre. Ved å lage egne metoder for å lese/endre rutenettverdier, f.eks. getCell(x, y) og setCell(x, y, value), så er det lett å bytte representasjon siden. Det kan også være lurt å ha en egen metode som sier om x, y er lovlige, dvs. faller innenfor rutenettet, f.eks. boolean isValid(x, y).

Initialisering skjer gjerne ved blanke ut alle rutene (fylle med verdien for tom rute) og plassere evt. brikker i utgangsposisjonen.

Hvis spillet har en figur som beveger seg rundt, så må en gjerne ha felt for x- og y-koordinater, som er heltall (int), f.eks. int playerX, playerY.

Rutenettet initialiseres i henhold til størrelsen og reglene for spillet, evt. innlasting av brett/nivå (level). Hvis spillet inneholder en spiller-figur, så må gjerne den plasseres i rutenettet.

Logikk for valg av ikon/bilde

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.

 

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

En lager enkle metoder/funksjoner for å oppdatere rutenettet i henhold til reglene for spillet, 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.

 

 

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.