diff --git a/README.md b/README.md index cd7ad42..d663e96 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,18 @@ # [Semesteroppgave 1: “Rogue One-Oh-One”](https://retting.ii.uib.no/inf101.v18.sem1/blob/master/SEM-1.md) -**OBS: koden / oppgaveteksen er ikke helt ferdig ennå – du kan lese den og se på ting online men ikke laste den ned** - -**Innleveringsfrist: Fredag 9. mars kl 2400** (TODO: info om forlengelse) - Dette prosjektet inneholder [Semesteroppgave 1](SEM-1.md). Du kan også [lese oppgaven online](https://retting.ii.uib.no/inf101.v18.oppgaver/inf101.v18.sem1/blob/master/SEM-1.md) (kan evt. ha små oppdateringer i oppgaveteksten som ikke er med i din private kopi). +**Innleveringsfrist: Fredag 9. mars kl 2400** + +**Utsettelse:** Hvis du trenger forlenget frist kan du få det om du ber om det (spør gruppeleder – evt. foreleser/assistenter hvis det er en spesiell situasjon) + * Noen dagers utsettelse går helt fint uten begrunnelse, siden oppgaven er litt forsinket. + * Hvis du jobber med labbene fremdeles (best om du er ferdig med Lab 4), si ifra om det, og så kan du få ekstra tid til å gjøre ferdig labbene før du går i gang med semesteroppgaven. + * Om det er spesielle grunner til at du vil trenge lengre tid, så er det bare å ta kontakt, så kan vi avtale noe. Du kan også ta kontakt om du [trenger annen tilrettelegging](http://www.uib.no/student/49241/trenger-du-tilrettelegging-av-ditt-studiel%C3%B8p). + + # Fyll inn egne svar/beskrivelse/kommentarer til prosjektet under * Levert av: *NAVN* (*BRUKERNAVN*) +* Del A: [ ] helt ferdig, [ ] delvis ferdig +* Del B: [ ] helt ferdig, [ ] delvis ferdig +* Del C: [ ] helt ferdig, [ ] delvis ferdig diff --git a/SEM-1.md b/SEM-1.md index 4b8d409..0df88e1 100644 --- a/SEM-1.md +++ b/SEM-1.md @@ -11,7 +11,24 @@ ## Sjekkliste: -* [ ] Thing to do +* [ ] Gjøre Del A + * [ ] Oppdatere README.md, commit og push! +* [ ] Gjøre Del B + * [ ] Oppdatere README.md, commit og push! +* [ ] Gjøre Del C + * [ ] Commit og push ofte! + * [ ] Beskrive hva du har gjort i README.md, fortell om eventuelt idé-samarbeid + * [ ] Sørge for at du har rettigheter til evt. mediafiler du bruker +* [ ] Gjøre klar innlevering + * [ ] Sjekke at alle filer som skal være med er med når du commiter + * [ ] Sjekk *Commits* siden på Retting, og se at ting du har pushet har dukket opp + * [ ] Sjekk teststatus på https://retting.ii.uib.no:81/me + * [ ] Sjekk at du har skrevet JavaDoc for nye metoder / typer du har lagt til + * [ ] Sjekk at du har formattert koden (bruk Source → Format i Eclipse, f.eks.) + * [ ] Sjekk at all bruk av kilder, bilder, lyd, annen kode er spesifisert i README.md + * [ ] Sjekk [README.md](README.md), commit og push! +* [ ] Things to do +* [ ] More things to do ## Om semesteroppgaven diff --git a/SEM-1_DEL-A.md b/SEM-1_DEL-A.md index 058b793..7c2ecb5 100644 --- a/SEM-1_DEL-A.md +++ b/SEM-1_DEL-A.md @@ -27,7 +27,7 @@ Ting som (kanskje) er nytt: Semesteroppgaven er en naturlig videreutvikling av Labyrint-oppgaven – i stedet for å bare gå rundt i en kjedelig labyrint, skal vi nå kunne gå rundt, plukke opp ting og interagere med ting. ### Bakgrunn -Et eksempel på et slikt labyrint-spill er [Rogue](https://en.wikipedia.org/wiki/Rogue_(video_game)), som er et gammel [dungeon crawl](https://en.wikipedia.org/wiki/Dungeon_crawl)-spill med “tekst-grafikk”, der du går rundt i en labyrint, plukker opp ting og dreper monstre. De første slike spillene dukket opp på slutten av 1970-tallet; *Rogue* (1980) var et av de første, og har gitt navn til hele sjangeren ([“Roguelike”](https://en.wikipedia.org/wiki/Roguelike)). Dungeon crawls og roguelike spill har vært veldig populære opp gjennom tidene (ikke minst på grunn av fancy 2D-grafikk med tekst-symboler, som var et betydelig steg opp fra [tidligere adventure/fantasy spill](https://en.wikipedia.org/wiki/Colossal_Cave_Adventure) som hvor alt var bare tekst), inkludert gamle klassikere som [NetHack](TODO), [Moria](TODO) og [Larn](TODO). Ofte har disse spillene vært laget som hobbyprosjekter av programmører (informatikk-studenter, for eksempel) og vært mer kompliserte (og mye vanskeligere) enn spill fra kommersielle spillprodusenter, selv om de gjerne ikke har hatt spesielt fancy grafikk. +Et eksempel på et slikt labyrint-spill er [Rogue](https://en.wikipedia.org/wiki/Rogue_(video_game)), som er et gammel [dungeon crawl](https://en.wikipedia.org/wiki/Dungeon_crawl)-spill med “tekst-grafikk”, der du går rundt i en labyrint, plukker opp ting og dreper monstre. De første slike spillene dukket opp på slutten av 1970-tallet; *Rogue* (1980) var et av de første, og har gitt navn til hele sjangeren ([“Roguelike”](https://en.wikipedia.org/wiki/Roguelike)). Dungeon crawls og roguelike spill har vært veldig populære opp gjennom tidene (ikke minst på grunn av fancy 2D-grafikk med tekst-symboler, som var et betydelig steg opp fra [tidligere adventure/fantasy spill](https://en.wikipedia.org/wiki/Colossal_Cave_Adventure) som hvor alt var bare tekst), inkludert gamle klassikere som [NetHack](https://en.wikipedia.org/wiki/NetHack), [Moria](https://en.wikipedia.org/wiki/Moria_(video_game)) og [Larn](https://en.wikipedia.org/wiki/Larn_(video_game)). Ofte har disse spillene vært laget som hobbyprosjekter av programmører (informatikk-studenter, for eksempel) og vært mer kompliserte (og mye vanskeligere) enn spill fra kommersielle spillprodusenter, selv om de gjerne ikke har hatt spesielt fancy grafikk. Moderne roguelike spill (og moderne utgaver av de gamle) kommer gjerne med mer fancy grafikk og er ofte laget av uavhengige utviklere. I de litt bredere kategoriene “dungeon crawls” og “adventure” finner du en haug med vanlige, populære spill – f.eks. [Zelda-serien](https://en.wikipedia.org/wiki/The_Legend_of_Zelda_(video_game)) (startet i 1986 med “gå rundt på et 2D-grid/kart, plukk opp ting, sloss med monstre og løs puzzles”; de nyeste versjonene tilbyr en åpen 3D-verden med detaljert fysikk, grafikk og lyd). @@ -78,40 +78,41 @@ Basert på tidligere erfaringer med slike spill, samt grunding tenking og lesing ### Design – hvordan lager vi dette i Java? Basert på dette tenker vi oss følgende typer objekter: -* [IMapView](src/inf101/v18/rogue101/map/IMapView.java], [IGameMap](src/inf101/v18/rogue101/map/IGameMap.java] – spillkartet +* [IMapView](src/inf101/v18/rogue101/map/IMapView.java), [IGameMap](src/inf101/v18/rogue101/map/IGameMap.java) – spillkartet +* [IGame](src/inf101/v18/rogue101/game/IGame.java) – selve spillet, som styrer reglene i spillverdenen * [IItem](src/inf101/v18/rogue101/objects/IItem.java) – en ting. Siden både småobjekter (sverd og gulrøtter), aktører og vegger er ting som befinner seg på kartet, er det praktisk å gjøre alle til IItem. - * Wall – en IItem som ikke kan dele plass med noe annet - * IActor – en IItem som bevege seg og ikke kan dele plass med en annen IActor - * IPlayer – en IActor som styres ved at brukeren trykker på tastene - * INonPlayer – en IActor som styrer seg selv (datamaskinen styrer) + * [Wall](src/inf101/v18/rogue101/objects/Wall.java) – en IItem som ikke kan dele plass med noe annet + * [IActor](src/inf101/v18/rogue101/objects/IActor.java) – en IItem som bevege seg og ikke kan dele plass med en annen IActor + * [IPlayer](src/inf101/v18/rogue101/objects/IPlayer.java) – en IActor som styres ved at brukeren trykker på tastene + * [INonPlayer](src/inf101/v18/rogue101/objects/INonPlayer.java) – en IActor som styrer seg selv (datamaskinen styrer) Vi har også et par andre mer abstrakte ting vi bør tenke på – f.eks. koordinater. Det går an å bruke heltall som koordinater / indekser (`int x`, `int y`), men det er generelt ganske praktisk med en egen abstraksjon for grid-plasseringer; blant annet kan vi da slippe å gjøre kompliserte utregninger på koordinatene for å finne frem til andre koordinater. Vi har derfor også: -* ILocation – en lovlig (x,y)-koordinat på kartet. Hver ILocation har opptil åtte andre ILocations som naboer, og har metoder for å finne alle eller noen av naboene, og for å finne nabo i en spesifikk retning. -* GridDirection – en retning (NORTH, SOUTH, ...), til bruk sammen med ILocation -* IArea – et rektangulært sett med ILocations. Brukes f.eks. av spillkartet for å lettvint gå gjennom alle cellene/rutene i kartet. -* (IGrid og IMultiGrid – IGrid er tilsvarende til den du har brukt i labbene tidligere; IMultiGrid er et grid der hver celle er en liste av T-er. Den blir brukt av spillkartet, men du trenger neppe bruke den selv.) +* [ILocation](src/inf101/v18/grid/ILocation.java) – en lovlig (x,y)-koordinat på kartet. Hver ILocation har opptil åtte andre ILocations som naboer, og har metoder for å finne alle eller noen av naboene, og for å finne nabo i en spesifikk retning. +* [GridDirection](src/inf101/v18/grid/GridDirection.java) – en retning (NORTH, SOUTH, ...), til bruk sammen med ILocation +* [IArea](src/inf101/v18/grid/IArea.java) – et rektangulært sett med ILocations. Brukes f.eks. av spillkartet for å lettvint gå gjennom alle cellene/rutene i kartet. +* ([IGrid](src/inf101/v18/grid/IGrid.java) og [IMultiGrid](src/inf101/v18/grid/IMultiGrid.java) – IGrid er tilsvarende til den du har brukt i labbene tidligere; IMultiGrid er et grid der hver celle er en liste av T-er. Den blir brukt av spillkartet, men du trenger neppe bruke den selv.) ### Deloppgave A1: Tilstand, oppførsel og grensesnitt for objektene *Du vil sikkert finne på lurere svar på spørsmålene etterhvert som du jobber med oppgaven. Det er fint om du lar de opprinnelige svarene stå (det er helt OK om de er totalt feil eller helt på jordet) og heller gjør tilføyelser. Du kan evt. bruke ~~overstryking~~ (putt dobbel tilde rundt teksten, `~~Rabbit.java funker fordi det bor en liten kanin inni datamaskinen~~`) for å markere det du ikke lenger synes er like lurt. Alle grensesnittene beskriver hvordan du kan håndtere objekter (objekter som er av klasser som implementerer grensesnittene). Selv om tilstanden til objektene er innkapslet (du vet ikke om feltvariablene), så lar metodene deg *observere* tilstanden, så ut fra de tilgjengelige metodene kan du spekulere litt rundt hvordan tilstanden må være. -Les gjennom grensesnittene vi har nevnt over ([IGameMap](TODO), [IItem](TODO), [IActor](TODO), [INonPlayer](TODO), [IPlayer](TODO) – vent med å se på klassene) og svar på spørsmålene (skriv svarene i [README.md](README.md), det holder med én eller noen få setninger): +Les gjennom grensesnittene vi har nevnt over [IGame](src/inf101/v18/rogue101/game/IGame.java), ([IMapView](src/inf101/v18/rogue101/map/IMapView.java), [IItem](src/inf101/v18/rogue101/objects/IItem.java), [IActor](src/inf101/v18/rogue101/objects/IActor.java), [INonPlayer](src/inf101/v18/rogue101/objects/INonPlayer.java), [IPlayer](src/inf101/v18/rogue101/objects/IPlayer.java) – vent med å se på klassene) og svar på spørsmålene (skriv svarene i [README.md](README.md), det holder med én eller noen få setninger): * **1. Hva vil du si utgjør tilstanden til objekter som implementerer de nevnte grensesnittene?** *(F.eks. hvis du ser på `ILocation` så vil du gjerne se at ILocation-objekter må ha en tilstand som inkluderer `x`- og `y`-koordinater – selv om de sikkert kan lagres på mange forskjellige måter)* -* **2. Hva ser ut til å være sammenhengen mellom grensesnittene?** Flere av dem er f.eks. laget slik at de utvider (extends) andre grensesnitt. +* **2. Hva ser ut til å være sammenhengen mellom grensesnittene?** Flere av dem er f.eks. laget slik at de utvider (extends) andre grensesnitt. Hvem ser ut til å ta imot / returnere objekter av de andre grensesnittene? -* **3. Det er to grensesnitt for kart, både [IGameMap](TODO) og [IMapView](TODO). Hvorfor har vi gjort det slik?** +* **3. Det er to grensesnitt for kart, både [IGameMap](src/inf101/v18/rogue101/map/IGameMap.java) og [IMapView](src/inf101/v18/rogue101/map/IMapView.java). Hvorfor har vi gjort det slik?** -* **4. Hvorfor tror du [INonPlayer](TODO) og [IPlayer](TODO) er forskjellige? Ville du gjort det annerledes?** +* **4. Hvorfor tror du [INonPlayer](src/inf101/v18/rogue101/objects/INonPlayer.java) og [IPlayer](src/inf101/v18/rogue101/objects/IPlayer.java) er forskjellige? Ville du gjort det annerledes?** ### Deloppgave A2: Eksempler på IItem og IActor -Til denne deloppgaven kan du se først på [Carrot](TODO) og [Rabbit](TODO). Svar på spørsmålene (skriv svarene i [README.md](README.md), det holder med én eller noen få setninger): +Til denne deloppgaven kan du se først på [Carrot](src/inf101/v18/rogue101/objects/Carrot.java) og [Rabbit](src/inf101/v18/rogue101/objects/Rabbit.java). Svar på spørsmålene (skriv svarene i [README.md](README.md), det holder med én eller noen få setninger): * **5. Stemmer implementasjonen overens med hva du tenkte om tilstanden i Spørsmål 1 (over)? Hva er evt. likt / forskjellig?** -Se på [Game](TODO) og [GameMap](TODO) også. +Se på [Game](src/inf101/v18/rogue101/game/Game.java) og [GameMap](src/inf101/v18/rogue101/map/GameMap.java) også. `Rabbit` trenger å vite hvor den er, fordi den skal prøve å spise gulroten (hvis den finner en) og fordi den må finne seg et gyldig sted å hoppe videre til. * **6. Hvordan finner Rabbit ut hvor den er, hvilke andre ting som er på stedet og hvor den har lov å gå?** @@ -166,7 +167,7 @@ Prøv også å justere gulrøttene litt ([Carrot](src/inf101/v18/rogue101/exampl ### Deloppgave A5: Ting du ikke trenger å se på (0/100) * Du trenger ikke se på koden i `gfx` (grafikkbibliotek), `grid` (utvidet IGrid) eller `util` (generering av testdata). -* Hvis du lager grafikk selv, vil du gjerne komme til å *bruke* `ITurtle` (fra `gfx`), men du trenger ikke se på implementasjone. +* Hvis du lager grafikk selv, vil du gjerne komme til å *bruke* [`ITurtle`](src/inf101/v18/gfx/gfxmode/ITurtle.java) (fra `gfx`), men du trenger ikke se på implementasjone. * GameMap gjør bruk av `grid`-pakken, men du trenger antakelig ikke gjøre noe med den selv. -# Gå videre til Del B -[SEM-1_DEL-B](SEM-1–DEL-B.md) + +# Gå videre til [**DEL B**](SEM-1–DEL-B.md) diff --git a/SEM-1_DEL-B.md b/SEM-1_DEL-B.md index ca3d79e..71440dd 100644 --- a/SEM-1_DEL-B.md +++ b/SEM-1_DEL-B.md @@ -10,7 +10,7 @@ I denne delen av semesteroppgaven skal du implementere en del konkrete metoder. ### Deloppgave B1: Objekt-fabrikk * a) Se på konstruktøren i Game-klassen, og se hvordan kartet blir fylt inn. Finn metoden som lager nye objekter basert på strenger ('#', '.', 'R', osv) dette er en såkalt [factory/fabrikk-metode](https://en.wikipedia.org/wiki/Factory_method_pattern). Det er vanlig å bruke når vi har mange klasser som implementerer det samme grensesnittet, og vi vil gjøre det lett for andre deler av programmet å opprette objekter uten å kjenne til klassene. -* **b)** Lag deg en ny klasse som implementerer IItem. Du kan ta utgangspunkt i en av klassene du har fra før (f.eks. `Carrot`) og du kan velge navn selv (f.eks. `CarrotCake`). Funksjonaliteten kan (foreløpig) være helt lik. +* **b)** Lag deg en ny klasse som implementerer [IItem](src/inf101/v18/rogue101/objects/IItem.java). Du kan ta utgangspunkt i en av klassene du har fra før (f.eks. `Carrot`) og du kan velge navn selv (f.eks. `CarrotCake`). Funksjonaliteten kan (foreløpig) være helt lik. * **c)** Legg klassen til i fabrikk-metoden. Du må velge et tegn som skal representere objekter av klassen (f.eks. `"c"`). Bruk dette tegnet både i fabrikk-metoden i `Game` og i `getSymbol()`-metoden i den nye klassen din (det er ingen direkte sammenheng mellom disse, men greit om de stemmer overens). * **d)** Legg til det nye tegnet ditt i standard-kartet (ligger i [src/inf101/v18/rogue101/map/maps/level1.txt](src/inf101/v18/rogue101/map/maps/level1.txt) – eventuelt ligger det et innebygget kart i `Main`-klassen hvis vi av en eller annen grunn ikke finner kartfilen), og se at gulrotkaken (eller det du har laget) dukker opp på skjermen. @@ -20,7 +20,7 @@ Symbolene på skjermen blir hentet fra `getSymbol()` (evt. `getPrintSymbol()` om ### Deloppgave B2: Minimal Player Du er sikkert lei av at det bare er kaninene som får lov til å ha det gøy. -* **a)** Lag en klasse `Player implements IPlayer`. Du kan følge mønsteret fra de andre IItem-klassene, men du trenger litt andre metoder. Der hvor `Rabbit` har `doTurn()` skal `Player` ha `keyPressed()`. Du kan la denne være tom til å begynne med. +* **a)** Lag en klasse `Player implements` [`IPlayer`](src/inf101/v18/rogue101/objects/IPlayer.java) (putt den i `objects` eller en egen ny `player` pakke). Du kan følge mønsteret fra de andre IItem-klassene, men du trenger litt andre metoder. Der hvor `Rabbit` har `doTurn()` skal `Player` ha `keyPressed()`. Du kan la denne være tom til å begynne med. * **b)** Du må oppdatere fabrikken i `Game` så den også lager `Player`-objekter; de har tradisjonelt symboled `@` (i utlevert kode gir det deg en `ExampleItem`). * **c)** Metoden `keyPressed()` i `IPlayer` tar et `KeyCode`-object, og kalles hver gang spilleren trykker på en tast. Knappen indikeres med KeyCode-en (en for hver tast på tastaturet + at man kan sjekke f.eks. om *Ctrl*-tasten er trykket inn). F.eks. vil følgende kode sjekke om @@ -52,7 +52,7 @@ En grei løsning er å si at vi vil se den *største* tingen – alle IItems har For å fikse dette vil vi at kartet skal ha tingene liggende i sortert rekkefølge i listene for hver celle. Vi kunne sortert listen hver gang vi hentet den (f.eks. hver gang kaninen kaller `game.getLocalItems()`, slik at den største gulroten kommer først), men det er både raskere og ca. like lettvint å passe på at vi legger ting inn i sortert rekkefølge: Hvis vi skal legge et element *e* inn i listen *l*, så vil vi ha det på den første posisjonen *i* slik at *e.compareTo(l.get(i)) >= 0* (altså, sett inn *e* foran det første elementet *e* er større enn). -* **a)** Legg til alternativet for `"."` i `Game.createItem()` – den skal produsere et `Dust`-objekt. +* **a)** Legg til alternativet for `"."` i `Game.createItem()` – den skal produsere et [`Dust`-objekt](src/inf101/v18/rogue101/objects/Dust.java). * Hvis du kjører programmet nå, vil du antakelig se at mange av kaninenen “gjemmer seg” – de ligger altså under støvet (Dust-objektene; sees som litt mørkere felter). * **b)** Endre `add`-metoden i `GameMap` slik at nye items blir lagt til i sortert rekkefølge (største først). * Husk at `a.compareTo(b)` er `< 0` hvis `a` er mindre `b`, `== 0` hvis `a` er lik `b` og `> 0` hvis `a` er større `b`. @@ -60,7 +60,7 @@ For å fikse dette vil vi at kartet skal ha tingene liggende i sortert rekkeføl * Det holder å kalle `add` på listen, siden `list` refererer til samme objektet som ligger inne i kart-cellen. * `Dust`-objektene er ganske små (størrelse 1), så hvis du har gjort det riktig, vil kaninene (og spilleren) bli tegnet i stedet for støvet. * **c)** Test `add`-metoden. - * Finn testklassen [GameMapTest](TODO) og testmetoden vi har begynt på (`testSortedAdd`). + * Finn testklassen [GameMapTest](src/inf101/v18/rogue101/tests/GameMapTest.java) og testmetoden vi har begynt på (`testSortedAdd`). * Du må sette opp et test-scenario: * du trenger et nytt GameMap (det trenger ikke være fylt med noe) * du trenger også en ILocation, siden de fleste kart-metodene bruker det (kall `getLocation(x,y)` med en kjent, lovlig posisjon) @@ -74,20 +74,20 @@ Vi vil gjerne la brukeren kunne plukke opp og legge fra seg ting på kartet – * **a)** For å få til dette må du legge til flere tastetrykk til `keyPressed`-metoden i `Player` – du kan f.eks. bruke `KeyCode.P` og `KeyCode.D`. Lag gjerne egne metoder for å plukke opp/droppe ting i spilleren. * *Legg merke til:* andre metoder i `Player` er laget slik at de tar et `IGame`-argument. Det trenger du nok her også fordi du må snakke med spill-objektet for å interagere med kartet og andre ting. Du *kan* lagre `game` som en feltvariabel, så du slipper å sende den rundt som argument. Vi har latt være å gjøre det fordi: a) det er lettere å opprette og teste Player (og andre IItems/IActors) hvis man ikke trenger å lage gi dem et game-objekt (f.eks. kunne du teste GameMap/sortert add uten å bruke `Game`/`IGame` i det hele tatt); og b) det kan være litt forvirrende med sykliske avhengigheter mellom objekter (ikke minst når forholdet endrer seg – f.eks. når ting fjernes fra spillet). -* **b)** `Game` har tilsvarende `pickUp()` og `drop()` metoder du kan bruke for å plukke et objekt fra kartet og for å etterlate et objekt på kartet. Metoden `pickUp()` returnerer `null` om du av en eller annen grunn ikke kunne plukke opp tingen. Implementer “plukke opp”-funksjonaliteten. Hint: +* **b)** `Game` har tilsvarende `pickUp()` og `drop()` metoder du kan bruke for å plukke et objekt fra kartet og for å etterlate et objekt på kartet. Metoden `pickUp()` returnerer `null` om du av en eller annen grunn ikke kunne plukke opp tingen. Implementér “plukke opp”-funksjonaliteten. Hint: * `game.pickUp()` plukker opp et spesifikt objekt som ligger i kartruten du står i, så du er nødt til å finne ut *hvilket objekt* du vil prøve å plukke opp hvis det er flere mulighetre (foreløpig har brukeren ingen måte å be om et spesifikt IItem på); * du finner alle tingene som ligger i kartruten med `game.getLocalItems()`, og du kan f.eks. prøve å ta den første. Du kan også finne tingene ved å få tak i kartet (game.getMap()) og undersøke det direkte – bare pass på at spilleren ikke ender opp med å plukke opp seg selv! (getLocalItems() gir deg bare items som ikke er IActor, så den er “trygg”) * husk at ruten kan være tom, dvs at `game.getLocalItems()` gir tom liste – da kan du f.eks. gi bruken beskjed om at det ikke er noe å plukke opp. -* **c)** For å kunne legge fra deg ting må du ha lagret objektet du plukket opp, f.eks. i en feltvariabel i `Player`. Foreløpig går det greit å tenke seg at du bare kan holde på én ting, så da er det lett å vite hva dus skal legge fra deg. Implementer “dropp / legg fra deg”-funksjonaliteten. Hint: +* **c)** For å kunne legge fra deg ting må du ha lagret objektet du plukket opp, f.eks. i en feltvariabel i `Player`. Foreløpig går det greit å tenke seg at du bare kan holde på én ting, så da er det lett å vite hva dus skal legge fra deg. Implementér “dropp / legg fra deg”-funksjonaliteten. Hint: * Du kan gi en passende melding til brukeren om du ikke har noe å legge fra deg. * Pass på at når du har lagt fra deg objektet (med `game.drop()`) så sletter du det fra `Player`-objektet – ellers kan du massekopiere ting ved å plukke opp én ting og så legge den fra deg mange ganger. * `game.drop()` kan i prinsippet feile (fullt på bakken, kanskje?), i såfall returnerer den `false` og du bør *ikke* slette tingen fra `Player`-objektet * **d)** Det er praktisk for brukeren å vite hva man bærer på, så legg inn navnet på objektet i status-meldingen (fra B2.e) ### Deloppgave B5: Finne synlige ting / ting i nærheten -IGame spesifiserer en metode `getVisible()` som skal gi deg alle locations i nærheten som du kan se. Denne er foreløpig ikke skikkelig implementert. Den kaller `map.getNeighbourhood(currentLocation, dist)`, som mangler implementasjon for dist > 0. +[IGame](src/inf101/v18/rogue101/game/IGame.java) spesifiserer en metode `getVisible()` som skal gi deg alle locations i nærheten som du kan se. Denne er foreløpig ikke skikkelig implementert. Den kaller `map.getNeighbourhood(currentLocation, dist)`, som mangler implementasjon for dist > 0. -* **a)** Lag en enkel versjon av `getNeighbourhood()` som bare returnerer alle de direkte naboene til lokasjonen. ILocation har metoder som kan hjelpe deg (men du må kanskje flytte resultatet over i en liste). Med *naboer* mener vi her alle de åtte cellene som er rundt cellene i midten, *unntatt* de av naboene som er utenfor kartet (du vil uansett ikke få tak i ILocations for dissse); og med *nabolag* tenker også på naboene til naboene osv. +* **a)** Lag en enkel versjon av `getNeighbourhood()` i [GameMap](src/inf101/v18/rogue101/map/GameMap.java) som bare returnerer alle de direkte naboene til lokasjonen. ILocation har metoder som kan hjelpe deg (men du må kanskje flytte resultatet over i en liste). Med *naboer* mener vi her alle de åtte cellene som er rundt cellene i midten, *unntatt* de av naboene som er utenfor kartet (du vil uansett ikke få tak i ILocations for dissse); og med *nabolag* tenker også på naboene til naboene osv. * **b)** Det er litt dumt å bare kunne se de aller nærmeste cellene. Endre din `getNeighbourhood()` slik at den finner alle locations som er innenfor dist cellers avstand. (Dette er gjerne mye vanskeligere. Du kan sette begrensninger på dist om vil, men du bør håndtere minst 3.) * **c)** Du bør lage tester for dette også, slik som i B3. Du trenger et GameMap, og en ILocation på kartet. * Du kan sjekke at resultatet fra `getNeighbourhood()` er riktig ved å gå gjennom hele listen og så sjekke at `centre.gridDistanceTo(element) <= dist`. @@ -139,7 +139,7 @@ En grei formel for angrep er f.eks.: `attack+random.nextInt(20)+1 >= defence+10` * **c)** I en del av metodene burde vi kanskje vært litt mer presise på hva som er “forkravene” – hva må være oppfylt for at det skal gå bra å kalle denne metoden? Vi har nevnt litt at `game.move()` krever at feltet i retningen er lovlig og ledig. Se gjennom de andre metodene i `Game` og `GameMap` og se om de har spesielle antakelser rundt parameterne. Ser du noe som burde endres? F.eks., enten metoder som sjekker for ting som kan gå galt, men ikke sier noe om forutsetningene i dokument – eller metoder som *burde* sjekket parameterne sine / andre forutsetninger. F.eks., hva med `Game.addItem()` (og `drop()` også, forsåvidt) – bør den f.eks. sjekke at feltet ikke allerede er opptatt (f.eks. legge til ny IActor når det allerede er en IActor der, e.l.)? -* **d)** Det er to kart-grensesnitt, IGameMap og IMapView. Hvorfor tror du vi har gjort det slikt? +* **d)** Tenker du annerledes om noen av spørsmålene fra Del A nå? -* **e)** Tenker du annerledes om noen av spørsmålene fra Del A nå? +# Gå videre til [**DEL C**](SEM-1–DEL-C.md) diff --git a/SEM-1_DEL-C.md b/SEM-1_DEL-C.md index 26aac01..5a2666a 100644 --- a/SEM-1_DEL-C.md +++ b/SEM-1_DEL-C.md @@ -6,16 +6,46 @@ * [Del B: Gjør ferdig nødvendige komponenter](SEM-1_DEL-B.md) * [Del C: Selvvalgt del](SEM-1_DEL-C.md) +## Videreutvikling av Rogue-101 +Vi overlater nå ansvaret for utviklingen til deg – du finner noen forslag under, men du må selv bestemme hva mer som skal legges til av funksjonalitetet, og hva du evt. vil gjøre for å gi spillet litt mer “flavour” (grafikk, kanskje?). + +Som nevnt tidligere kan du velge “setting” og “storyline” som du vil – du trenger ikke å lage huleutforskning med magi, sverd, orker og hobbiter – eller med kaniner og gulrøtter. Skriv ned forklaring til det du gjør i README.md – både funksjonalitet som du legger til, og kreative ting du finner på – vi legger ikke nødvendigvis merke til alt når vi prøvekjører ting, så det er greit å vite hva vi skal se etter. + + +### Styling + +Du kan kommet et godt stykke på vei med litt kreativ bruk av tekst-symbolene. For enkel blokk-grafikk (til vegger, f.eks.) så finnes det en del forskjellige tegn du kan bruke i [BlocksAndBoxes](inf101/v18/gfx/textmode/BlocksAndBoxes.java). + +F.eks. bruker `Wall`-objektene `BlocksAndBoxes.BLOCK_FULL` som symbol. Det kan være litt tricky å få `Wall` til å variere `getSymbol()` avhengig av hvor den har andre vegger som naboer, men du kan i prinsippet lage flere varianter av wall: + * Her er det mest praktisk å bruk *arv*, f.eks.: + +``` +public class DiagonalWall extends Wall { + // Java vil bruke denne i stedet for getSymbol() fra Wall – men alle andre metoder følger + // med fra Wall. + @Override + public String getSymbol() { + return BlocksAndBoxes.DIAG_FORWARD; + } +} +``` + + * Du trenger også å legge til alle vegg-variantene i `createItem`-metoden. + * Du trenger at alle vegger har `Wall`-typen, fordi kartet bruker det til å se om et felt er opptatt (bla gjennom items på en lokasjon, sjekk om `item instanceof Wall`). Når du sier at `DiagonalWall extends Wall`, så vi alle diagonale vegger også telle som vanlige vekker. + * Alternativet ville vært å enten legge til en metode `isWall()` i `IItem`; eller si at en kartcelle er opptatt hvis det er en veldig stor ting der (`getSize()` større enn 100 eller 1000, f.eks.); eller lage et ekstra grensesnitt `IWall` (og både `Wall` og `DiagonalWall` `implements IWall`) og bruke det istedenfor der hvor man trenger å sjekke etter vegger. + * lage meldings"vindu" -# Åpne kilder til grafikk / lyd / media +# Diverse + +## Åpne kilder til grafikk / lyd / media * Om du ikke er flink til å tegne selv, kan du finne glimrende grafikk på [OpenGameArt](http://opengameart.org/) – **husk å skrive i oversiktsdokumentet hvor du har fått grafikken fra** (webside, opphavsperson, copyright-lisens – om du bruker OpenGameArt, finner du opplysningene i *License(s)* og *Copyright/Attribution Notice*). * [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) har en god del bilder og andre mediafiler tilgjengelig – du får til og med en “You need to attribute this author – show me how” instruks når du laster ned ting. * [Kevin MacLeod](https://incompetech.com/music/) er komponist og har masse musikk tilgjengelig som egner seg for spill og småfilmer; du trenger bare å kreditere ham (han bruker vanlig [CC-BY-3.0](http://creativecommons.org/licenses/by/3.0/) lisens). -* Tidligere INF101-student [Øyvind Aandalen](https://soundcloud.com/user-616269685) har litt musikk han har laget på [SoundCloud](https://soundcloud.com/user-616269685) som han sier dere kan som dere vil. +* Tidligere INF101-student [Øyvind Aandalen](https://soundcloud.com/user-616269685) har litt musikk han har laget på [SoundCloud](https://soundcloud.com/user-616269685) som han sier dere kan bruke som dere vil.