Rogue101/SEM-1_DEL-C.md
2018-03-01 00:22:38 +01:00

14 KiB
Raw Blame History

Semesteroppgave 1: “Rogue One oh one” Del C: Videreutvikling

Videreutvikling av Rogue-101

Vi overlater nå ansvaret for utviklingen til deg du finner noen forslag under som du kan jobbe ut ifra, eller så kan du finne på din egen utvikdelse av koden. For å få maks poengsum på oppgaven må du gjøre to av forslagene, eventuelt erstatte ett eller begge med noe du kommer på selv, som er tilsvarende stort i omfang.

Når du nå er ferdig med Del A og B skal du ha et dungeon crawler (evt. rabbit hopping) spill med en spiller som kan

  • bevege seg rundt på kartet
  • se synlige ting rundt seg
  • plukke opp ting
  • bære én ting
  • legge fra seg ting
  • angripe

Du har også gulrøtter som kan plukkes opp, og kaniner som kan spise gulrøtter og angripe ting.

Herfra kan du enten fortsette å legge på funksjonalitet på koden du har, eller brette opp ermene og lage ditt eget spill med andre klasser enn de vi har gitt her det kanskje mest aktuelt å bytte ut item-klassene. Du kan gjerne skrive en “intro” til spillet, og “flavour” i displayMessage. Uansett om du vil bruke klassene vi har gitt deg eller lage dine egne, må du huske å levere klassene du jobbet med i del A og B.

Du må selv bestemme hva mer som skal legges til av funksjonalitetet, og hva du evt. vil gjøre for å gi spillet litt mer stemning (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.

Siden vi ikke vet hva slags lure ting dere kommer på å implementere, skriver vi de følgende forslagene ut ifra koden vi har gitt dere. Du står fritt til å i stedet lage tilsvarende funksjonalitet for klasser i spillet du lager selv. Når vi skriver “spilleren”, kan det altså være at du vil bruke en annen klasse enn Player-klassen, eller at du vil gi denne funksjonaliteten til en INonPlayer.

Følgende er forslag til hva du kan gjøre, ikke nødvendigvis i den rekkefølgen.

C1: Ting/items som påvirker spillet

Spilleren vår vil gjerne kunne finne andre ting i labyrinten enn gulrøtter. I denne delen kan du lage flere ting, for eksempel noe som gjør spilleren flinkere til å angripe, eller øker helsen den har. Du kan lage “healings potions” som øker helsepoengene til spilleren. Dersom du vil at spilleren skal kunne slåss bedre, kan du lage våpen, for eksempel av typen langkost. Dersom du angriper en kanin med en langkost gir det deg kanskje en høyere attack score enn uten. (Du kan selv velge hvordan type ting påvirker angrep, helsepoeng, og kanskje også hverandre).

Det kan være at tingen tar effekt når du plukker den opp, eller kanskje spilleren må trykke på en tast (klassiske roguelikes bruker gjerne q for “quaff a potion” eller w for “wield a weapon”).

For å implementere disse tingene må du lage klasser for dem og extende IItem. De vil likne på gulrot-klassen. Du må selv finne ut hvordan de skal tegnes. Se styling-seksjonen for tips til grafikk.

C2: Inventory - bærenett

Dersom spilleren kan finne flere forskjellige typer ting i labyrinten, er det kjekt å kunne bære mer enn én ting av gangen. Hvis labyrinten enda bare har gulrøtter, vil spilleren kanskje kunne samle mange av dem, og bære dem med seg og alt du trenger å holde rede på er antall gulrøtter. Men for varierende typer ting, trenger vi en bedre løsning.

I objektorientering er vi opptatt av abstraksjon og forståelig kode, så selv om vi kunne ha latt spilleren få flere feltvariabler for å holde styr på alle tingene den bærer, så vil vi heller implementere en egen klasse for en samling (eller Collection) av ting. Java har standard lister, men her trenger vi kanskje noe litt annet: det bør jo gjerne ha en begrensning på hvor mye man kan bære med seg.

  • Samlingen bør lagre IItem-objekter, eventuelt at den er generisk med <T extends IItem>.
  • Du kan velge om begrensningen er på antall elementer, eller på total størrelse (getSize()) for alle elementene i samlingen.
  • Du må ha metoder for å putte noe inn i samlingen, hente noe ut, sjekke om det er ledig plass, osv. Du trenger ikke ha indekser det holder å kunne putte inn og hente ut.
  • Hvis noen prøver å putte noe inn i en full samling (eller noe det ikke er plass til i samlingen) bør du kaste en exception.

For tips til implementasjon av samling kan du se på IList/MyList-listene fra tidligere labber. Du kan gjerne bruke Java sitt standard-bibliotek for samlinger i implementasjonen (legg merke til at du trenger en konkret implementasjon av interfacet, for eksempel en ArrayList).

  • For litt mer solid INF101-design, bør du gjerne designe et eget grensesnitt, f.eks. IContainer<T extends IItem> da kan du også ha flere varianter av samlinger (som f.eks. virker på forskjellig måte).
  • Spilleren (og kaninene) kan bruke samlingen du har laget som bærenett eller ryggsekk til å lagre items som blir plukket opp. Brukeren vil antakelig ha lyst til å ha oversikt over hva som er i “sekken” det er ledig plass på skjermen hvor du kan vise mer informasjon se på metodene getPrinter() (du kan skrive ting på skjermen med printAt(x,y, text)), getFreeTextAreaBounds() og clearFreeTextArea().
  • En mer avansert og artig bruk av IContainer er å la den også utvide IItem. Da kan du putte ting i sekken din, og legge sekken på bakken eller putte en kanin inn i en hatt inn i en sekk inn i en koffert og plukke opp og sette fra deg kofferten.

C3 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. Hvis du implementer getPrintSymbol() så kan du bruke et eget tegn til grafikk-visningen (hvis du bruker bokstaven i getSymbol() til noe fancy fabrikk, f.eks.).

Fancy vegger

(Du kan selvfølgelig gjøre tilsvarende med andre ting enn vegger)

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.

En annen mulighet for fancy vegg er å la veggene tilpasse seg omgivelsene. Det krever litt samarbeid mellom Game og Wall f.eks. kan du finne alle veggene (enten i beginTurn() eller når du setter opp kartet) og kalle en ny metode som du lager (f.eks. setup(IGame game)). Veggen kan så utforske naboene sine, og finne ut hvilke av dem som er vegger, og velge riktig box-tegn enten en av BLOCK_*-tegnene fra BlocksAndBoxes, eller med Box-drawing characters (disse var mye brukt på gamle DOS-datamaskiner, men det er nå en standard del av Unicode-tegnsettet, og Printer-klassen støtter dem uavhengig av hvilken font du bruker.). Du kan paste box-tegn (og block-tegn) rett inn i koden din (så lenge Eclipse er riktig satt opp med UTF-8), eller bruke \uXXXX escape-koder i strengen. F.eks., "╣" er "\u2563".

Emojis

Hvis du bytter font vil du kunne bruke en haug med praktiske symboler. Du kan sette fonten i start() metoden i Main-klassen. “Symbola” inneholder standard Unicode emojis i tillegg til vanlige bokstaver. Du kan laste den ned herfra.

  • Hvis du putter Symbola.ttf i src/inf101/v18/gfx/fonts/, skal du kunne kjøre printer.setFont(Printer.FONT_SYMBOLA); i start(), og så bruke f.eks. "☺️" ("\u263a") som symbol for spilleren.
  • Merk at en del mer obskure Unicode-emojis, som "🦆" må skrives med to escape koder ("\ud83e\udd86") og er ikke nødvendigvis med i fonten du bruker.
  • Vanlige bokstaver ser dessverre ikke så veldig fine ut i Symbola-fonten, siden grafikken vår baserer seg på monospaced tekst (det går foreløpig ikke an å bruke mer enn én font i systemet).
  • Hvis du prøver deg med andre fonter (som du selvfølgelig må oppgi kilde til og ha rettigheter til å bruke og finne ut hvordan du setter de opp med Printer), vil de gjerne ikke passe så veldig godt på skjermen. Det går an å justere størrelse og posisjon på bokstavene med inf101.v18.gfx.textmode.TextFondAdjuster.

Farger

Du kan lage farger med ANSI escape-koder. For eksempel "\u001b[31m" + "@" + "\u001b[0m" for å lage et rødt @-tegn. "\u001b[31m" velger rød tekstfarge og "\u001b[0m" skifter tilbake til standard (hvis du ikke har med den så blir all teksten rød).

Skilpaddegrafikk

Alternativet til tekstgrafikken er å bruke ITurtle/TurtlePainter, som du har sett litt i bruk på forelesningene for å lage frosker og ender. Gulroten er tegnet slik hvis du implementerer draw()-metoden for et item, og lar den returnere true blir teksten ikke tegnet. Du kan se på gulrot-eksempelet, og på koden fra forelesningene for eksempler.

  • Les mer om skilpaddegrafikk her
  • Draw metoden får bredden og høyden til kartcellen som parametre. Som standard er ting laget til slik at bredde og høyde er 32 selv om skjermen viser smale tegn (16x32). Hvis du trenger kontroll over bredden, is stedet for at tegningen blir “skvist” til halv bredde, kan du sette Main.MAP_AUTO_SCALE_ITEM_DRAW til false.
  • Foreløpig støtter grafikksystemet ikke at du kan bruke egne bilder (i jpg eller png filer, f.eks.) men det er mulig vi kan legge til dette etterhvert.

C5: Meldingsvindu

  • lage meldings"vindu"

C6: Win condition

Det går foreløpig ikke an å vinne spillet her må du eventuelt være kreativ selv. F.eks. at spilleren vinner når alle gulrøttene er samlet i det ene hjørnet eller når spilleren er alene igjen eller noe helt annet.

C?: Noe du finner på / noe annet vi finner på

  • Du står fritt til å finne på ting selv; og det kan også være vi legger ut litt flere ideer underveis.

Diverse

Åpne kilder til grafikk / lyd / media

Foreløpig støtter grafikksystemet ikke at du kan bruke egne bilder (i jpg eller png filer, f.eks.) men det er mulig vi kan legge til dette etterhvert. Du kan uansett tegne med skilpaddegrafikken (TurtlePainter). Det ligger heller ikke med kode for å spille av lyd men det kan være vi har noe slikt på lur til når du har kommet skikkelig i gang med ting.

  • Om du ikke er flink til å tegne selv, kan du finne glimrende grafikk på OpenGameArt 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 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 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 lisens).
  • Tidligere INF101-student Øyvind Aandalen har litt musikk han har laget på SoundCloud som han sier dere kan bruke som dere vil.

Gå videre til Innlevering