Excerpt |
---|
Denne oppgaven er en videreføring av de tidligere spilloppgavene TicTacToe, Sokoban, Sudoku og Battleship, hvor en skal gjøre rutenettet observerbart og implementere et par grensesnitt, så spillogikken kan kobles til et ferdig skrevet grafisk brukergrensesnitt. I tillegg skal spillet utvides med ekstra funksjonalitet. |
I denne oppgaven skal spillogikken og (det innkapslede) rutenettet fra tidligere spill kobles til et ferdig skrevet grafisk brukergrensesnitt (GUI). Dette er en videreføring av de samme brukergrensesnittene som ble utdelt i tidligere utgaver av spilloppgavene. Nytt for brukergrensesnittet utdelt i denne oppgaven er at de nå også skal ha mulighet for å registrere seg som lyttere på spillklassen, for å legge til rette for oppdatering av skjermbildet når det skjer endringer i tilstanden.
Filene som er nødvendig for å knytte ditt spill opp mot vårt GUI er tilgjengelig i Del 2 av denne oppgaven.
ObservableGrid- og GridListener-grensesnittene
Det første grensesnittet er knyttet til rutenettdata og heter ObservableGrid. Tanken er at GUI-et må kunne registrere seg som lytter, slik at det holdes oppdatert når rutenettet endres. Dette er observert-delen av observatør-observert-teknikken. Observatør-delen av observatør-observert-teknikken utgjøres av GridListener-grensesnittet, og siden det er GUI-et som skal holdes oppdatert, så er det den ferdigimplementerte GUI-klassen som må implementere GridListener. GUI-klassen utdelt i Del 2 av denne oppgaven implementerer allerede GridListener, så det er kun nødvendig å la din spillklasse implementere ObservableGrid og samt skrive logikken for å varsle registrerte GridListener-objekter når det skjer endringer i rutenettet.
| ObservableGrid har følgende metoder for lytterhåndtering:
Lytterne må implementere GridListener og dermed følgende metode:
Hvis f.eks. metoden kalles med x=1, y=2, w=2 og h=1, så angir det at rutene 1,2 og 2,2 er endret. Det er opp til rutenett-klassen å avgjøre om endringer av flere ruter rapporteres med ett eller flere kall til gridChanged-metoden. Så endringer i rutene 1,2 og 2,2 kan også rapporteres med to kall, ett hvor x=1, y=2 og ett hvor x=2, y=2, med w=1 og h=1 for begge. Så selv om en kaller denne metoden, så er det ikke dermed sagt at alle rutene i det angitte rektangelet er endret (strengt tatt trenger ingen å være det).
|
For denne delen av oppgaven trenger du følgende filer: imagegrid/GridListener.java og imagegrid/ObservableGrid.java
GridGame- og GridOutput-grensesnittene
ObservableGrid og GridListener er grensesnitt som fokuserer på tilstanden til rutenettet, men ikke på hvordan tilstanden endres eller den overordned gangen i spillet, f.eks. oppstart eller brukerens kommandoer. De gir heller ingen mulighet til å styre hvordan rutenettet vises til brukeren eller vise annen type status for spillet. Dette er fokuset for GridGame- og GridOutput-grensesnittene.
| Spillets livssyklusDet er GUI-et som lager en instans av spillklassen og styrer oppstart og utvikling av spillet, dvs. laster inn et nytt nivå eller bra, setter spillet igang og driver det fremover ved å ta imot input fra brukeren og videreformidle det til spillet. Spillklassen din må innordne seg hvordan GUI-et gjør dette, ved å tilby et standard sett med metoder definert i GridGame-grensesnittet. De viktigste metodene er knyttet til den overordnede livssyklusen til spillet:
Meldinger til brukerenDen viktigste logikken i spillet ligger typisk i doCommand-metoden, siden den håndterer input fra brukeren. Effekten vil typisk være at spillet endrer rutenettet, og dette fanges opp av GUI-et, som lytter til rutenettendringer, slik at den grafisk visningen kan oppdateres. I tillegg kan spillet gi meldinger og statusoppdateringer til brukeren vha. GameOutput-objektet som ble gitt til run-metoden, da spillet startet. Det er derfor dette objektet må lagres unna, slik at det er tilgjengelig for doCommand-metoden. GameOutput-objektet tilbyr tre metoder, for meldinger av ulik alvorlighetsgrad:
Akkurat hvordan meldingen vises er opp til GUI-et, som implementerer metodene, men tanken er når alvorlighetsgraden øker, så blir meldinger mer tydelig og påtrengende. F.eks. kan info oppdatere en statuslinje, mens error åpner en meldingsdialog. Visning av rutenett-elementGridGame har i tillegg til metodene angitt over to metoder for å angi hvordan elementene i rutenettet vises. Tanken er at hver rute i rutenettet kan vises med tekst og/eller bilde og at GUI-et for hver rute spør om disse med følgende metoder:
Begge disse metodene tar et Object-argumentet, og disse er alle hentet med ObservableGrid sin getGridElement-metode. Siden argument-typen er Object, så kan det tenkes at du må bruke cast til den typen du vet ligger i rutenettet, for å kunne hente ut data som ligger inni dette objektet. Håndtering av ikke-tekstlig inputdoCommand-metoden beskrevet over, brukes for tekstlig input tilsvarende et kommandlinje-basert spill. For å gjøre spillet bedre egnet til å styres av et GUl så har GridGame i tillegg følgende metoder for å ta imot input:
For begge disse tolkes returverdien som for doCommand, og effekten kan, som for doCommand, være en kombinasjon av oppdatering av rutenettet eller tekstlig output til brukeren vha. GameOutput.
|
Eksempler på bruk av GUI-et
Det kan være litt vanskelig å skjønne hvordan instanser av din spillklasse brukes av GUI-et, så under så forklarer vi GUI-et og hvordan ulike type bruk trigger kallsekvenser hvor spillklassen inngår.
GUI-et har tre deler, fra øverst til nederst:
|
Når brukeren trykker "init and run"-knappen vil GUI-et ta innholdet i det øverste tekstfeltet og gi det som argument til spillklassen sin init-metode. Deretter vil den be om å få rutenettet vha. getObservableGrid()-metoden. Dette objektet vil så spørres om antall kolonner (getGridWidth()) og rader (getGridHeight()) og selve innholdet (getGridElement(...)), slik at den kan tegne rutenettet. Akkurat hvilken tekst og hvilket bilde som vises pr. rute bestemmes av svaret fra getTextFor(...) og getImageFor(...). Til slutt vil GUI-et registrere seg som lytter, slik at den kan reagrere på fremtidige endringer i rutenett. Til slutt startes selve spillet med et kall til run(...) og denne metoden vil typisk gi oppstartsinfo til brukeren med info(...)-metoden. |
Når brukeren trykker "doCommand"-knappen vil GUI-et ta innholdet i det nederste tekstfeltet og gi det som argument til spillklassen sin doCommand-metode. Dette vil typisk trigge en endring i rutenettet, som gir beskjed til lytterne, inkl. GUI-et, om endringen. GUI-et vil hente innholdet i ruten(e) som ble endret med getGridElement(...) og hvilken tekst og hvilket bilde som skal vises med getTextFor(...). Det kan også hende at statusen til spillet oppdateres med info(...)-metoden. |
Kjøring av spillet
Som forklart over, så skal spillet kobles til en ferdigskrevet GUI-klasse. I tillegg trenger du noen andre filer... Her er hele lista med filer du må laste ned:
- GridGameGUI: program/GridGameGUI.java.
- GameGridPane: program/GameGridPane.java.
- ProgramBuilderFactory.java: program/ProgramBuilderFactory.java
- GridGameGUI.fxml (må legges i samme mappe som GridGameGUI.java): program/GridGameGUI.fxml
Del 2: Utvidelse av spillet
I denne deloppgaven skal spillet utvides med ny funksjonalitet. Hva denne funksjonaliteten består i avhenger av hvilket spill du har valgt å implementere. Dette er beskrevet på egne sider for hvert spill:
- Sokoban - Del 3
- Sudoku - Del 3
- TicTacToe - Del 3
- Battleship - Del 3
- Selvvalgt spill: gjør en utvidelse av spillet ditt med en arbeidsmengde omtrent tilsvarende utvidelsen av de andre spillene.
Filene som er nødvendige for å kjøre det forhåndsskrevne GUI-et er tilgjengelig på disse ulike oppgavesidene. Siden det er GUI-et som styrer showet, så er det GridGameGUI som klassen <spill>FX.java som skal startes ved kjøring av spillet ditt. GridGameGUI har en main-metode som tar spillklassen sitt navn som argument. Det enkleste er å lage en main-metoden i din egen spillklasse, som følger (bytt ut DinSpillklasse med navnet på din egen spillklasse):
...
.
...