Utveckling av ett 2d spel i Java Examensarbete av: Rickard Borg, EDTD13 Examensår: 2016 Opponent: Jesper Larsson Handledare: Jimmy Jansson 1
Innehållsförteckning 1. Sammanfattning 3 2. Inledning 4 3. Definition av olika termer 5 4. Handling 7 5. Spelets innehåll 8 5.1 Spelaren 8 5.2 Coin 8 5.3 Fiende(r) 9 5.4 HP 9 5.5 Gameloop 9 6. Överblick av spelet 11 7. Tillvägagångssätt 12 8. Problem och lösningar 13 8.1 Problem 13 8.2 Lösningar 14 9. Detaljer 16 9.1 Nedräknande text 16 9.2 Spelaren blinkar 16 9.3 Väggkollision 16 9.4 Hp boosten 17 9.5 Omstart av spelet 17 10. Lärdomar och frågor 18 11. Dagboken 20 12. Flödesschema 25 13. Bilaga koden 26 14. Källor 27 2
1. Sammanfattning 3 Som examensarbete har jag gjort ett 2 dimensionellt spel i programspråket Java. Spelet går ut på att samla så mycket poäng som möjligt samtidigt som du ska undvika alla fiender som rör sig på skärmen. Under tiden jag arbetat på mitt examensarbete så har det varit väldigt spännande och roligt. Jag visste från början att jag ville göra någonting som hade med programmering att göra, helst ett spel och jag hittade rätt sak! Jag har stött på en del problem som emellanåt har varit pest och pina. Men jag har lyckats lösa dessa problem. Ibland har det varit jobbigare tillfällen då jag undrat hur det skulle fungera, och ibland har det varit väldigt enkelt. Jag såg detta som en utmaning då jag tidigare inte gjort något liknande så jag visste inte alls var det skulle sluta förrän jag såg resultatet och allting var som jag hade tänkt mig. Allt efter som jag hade kommit längre med att programmera spelet så kom jag på saker för att göra det mer intressant, och jag lade därmed till lite fler funktioner som gjorde spelet roligare. I dokumentationen har jag lagt till en rubrik som heter Definition av olika termer för att förklara lite olika begrepp som jag använder mig av i texten, vilken då blir lättare att följa. 3
2. Inledning 4 I dagens moderna och välutvecklade samhälle har spel blivit allt vanligare, både på datorer och mobila enheter. Till en början var spelen väldigt simpla med enkel grafik, men under de senaste decenniet har spelen blivit allt mer krävande och realistiska. Spel idag är med andra ord ofta 3 dimensionella och karaktärer, miljöer och andra föremål ser nästan verkliga ut. Jag har skrivit ett 2 dimensionellt spel i programspråket Java som slutarbete och det har varit roligt men också utmanande! I vissa fall har allting gått som en dans, men i andra fall har jag även varit nära att slita håret av mig när ingenting fungerat som jag tänkt mig. Hursomhelst har jag lyckats med det jag tänkte och jag är väldigt nöjd! Tanken med spelet var egentligen att göra något som jag tycker om att göra och kanske till och med ha något att spela när jag har tråkigt. Jag tror dock inte att spelet är något du spelar i flera timmar, men lite nu och då kanske är kul! Spelet riktar sig mest mot unga personer, mindre barn. Då kravet på förkunskaper inte är särskilt stort. 4
3. Definition av olika termer 5 Metod Är en benämning av en funktion i java programmering (kallas funktion i t.ex. C programmering). Den utför specifika instruktioner och ser till att vissa saker blir gjorda. Klass en klass är en prototyp, eller en mall där alla variabler och metoder för en specifik enhet finns. Till exempel i klassen player finns alla nödvändiga variabler och metoder för att få spelaren att kunna röra sig och i klassen enemy finns alla nödvändiga saker för fiendens egenskaper. Referensvariabel En referensvariabel är en variabel som pekar på ett klassobjekt. Den innehåller alltså en kopia av klassen som man skapat ett objekt av och med hjälp av referensvariabeln kan man komma åt exempelvis metoder och variabler som ligger i den klassen. Interface Ett interface är något man kan använda för att sätta upp en del olika metoder. Man implementerar sedan sitt interface i den klassen som ska använda metoderna. Alla metoder i ett interface måste finnas med i klassen som implementerar det, även om alla metoder där inte används. Main (eller main metoden) Är det första som startar när man kör programmet. Det vill säga, det som ligger i main kommer att utföras först. Loop/Loopar En loop är något som inom programmering utförs om och om igen ända tills dess att ett villkor inte längre stämmer överens. Loopen avslutas så fort villkoret inte längre uppfyller de krav som är angivna. Timer Timer är en sak jag använder i HpBoost klassen. Den har i uppgift att räkna tiden till 45 sekunder innan hp enheten visas på skärmen. Swing Swing inom java, är något man kan importera i sitt program och används för att rita grafiska fönster, knappar, textrutor osv. Awt Awt är också en sak som kan importeras. Det används för att rita grafiska föremål som till exempel cirklar, rektanglar, sätta färger o.s.v. Trådar En tråd används för att kunna utföra flera saker samtidigt. Man kan t.ex. använda en tråd för att utföra en sak och en annan tråd för att utföra en annan sak. 5
Awt har en egen tråd för grafiken och därför kan ett problem uppstå när man använder en tråd i en klass som använder sig av awt. Set metoder Används för att sätta värden på variabler inom programmering. Man vill ha så mycket privata variabler och metoder som möjligt för att kapsla in koden och inte göra alla variabler tillgängliga för alla klasser. Därför används metoder ofta för att sätta värden, dessa brukar ha set framför sitt metodnamn. Privata variabler/metoder En variabel är någonting som håller reda på ett visst värde och kan sedan användas i bland annat beräkningar och dylikt. Ifall en variabel är privat innebär det att endast den klassen där den är deklarerad i kan komma åt variabeln eller metoden (beroende på om det är en variabel eller en metod). Get metoder En get metod är en metod som returnerar värdet på en viss variabel. Det vill säga ifall man har en get metod så behöver man inte komma åt den specifika variabeln när man vill göra något, utan istället kan man anropa en get metod för att få värdet på variabeln. Ett exempel kan vara player.getscore(); som skulle returna spelarens poäng. Exception Uppstår när någonting i koden blir fel, det vill säga ett felmeddelande som gör att koden inte fortsätter. 6
4. Handling 7 Spelet går ut på att du styr spelaren, som är en fyrkant som åker över skärmen och ska försöka samla ihop så mycket poäng som möjligt genom att äta en gul prick, eller coin, som jag kallar den. Pricken uppkommer på skärmen genom slumpmässiga tal. Det vill säga när du en gång har ätit pricken så kommer en metod att anropas och slumpmässigt välja x och y värdena på nytt. Samtidigt som du försöker äta pricken ska du försöka undvika de röda prickarna, som är fiender, från att kollidera med en. Ett poäng tilldelas när spelaren äter en coin och spelet avslutas när du åker in i en fiende. Vid förlust får spelaren en fråga om den vill spela igen eller inte. Ifall du trycker på den knapp som visar ja så kommer spelet att börja om på nytt, annars avslutas spelet. Antal fiender baseras på antalet poäng som spelaren har. Det vill säga för varje femte poäng så kommer en till fiende att sättas ut på skärmen för att öka svårighetsgraden. Det finns åtta fiender och alla är redan utplacerade på skärmen så det gäller att undvika dem också, de är som hinder kan man säga. En bestämd fiende kommer att börja röra sig så fort spelaren uppnår rätt poäng. Det förekommer även en annan prick som är grön. Den gröna pricken har liksom coin, i uppgift att befinna sig på endast ett ställe, stället där den gröna pricken förekommer sker också med slumpmässiga värden och visas på skärmen med ett visst intervall (45 sekunders mellanrum). När den gröna pricken visas på skärmen så kommer den att befinna sig på samma ställe ända tills spelaren åker in i denna. Den gröna pricken tilldelar ett liv till spelaren vid kollision och sedan börjar nedräkningen från 45 sekunder igen. Det kommer då ta ytterligare 45 sekunder innan den visar sig på skärmen igen. Den kan endast förekomma såvida spelaren inte har uppnåt sitt maximala liv, som är fyra. Jag kan även nämna här att spelet är optimerat för att spelas på skärmar med upplösningen 1920x1080 pixel (Full HD), eftersom de flesta skärmar idag har den upplösningen. Ifall man ska kunna spela det i en annan upplösning så måste jag ändra på variablerna för spelets bredd och höjd, samt möjligvis storleken på fiender, spelare och dylikt. Därmed har jag bestämt att ha 1920x1080 pixlars spel eftersom jag inte vet vilka dimensioner objekten skulle få om jag ändrar upplösningen. 7
5. Spelets innehåll 8 Spelet innehåller en hel del olika saker som jag tänker berätta om i de olika sektionerna nedan. Varje enhet har en speciell uppgift att utföra och därmed kan man säga att spelet är som ett pussel, där alla bitar måste placeras korrekt för att det ska fungera som man tänkt sig. 5.1 Spelaren 8 Spelaren är personen som spelar spelet och styrs med piltangenterna eller bokstäverna W, A,S och D. Spelarens uppgift är att hålla sig vid liv så länge som möjligt, samt att försöka äta en gul prick (jag kallar den för coin ) som slumpmässigt sätts ut på skärmen med hjälp av x och y värden. Så fort spelaren äter en coin anropas en metod som väljer ett nytt värde för x och y och det blir då den nya positionen för coin. 5.2 Coin 8 Coin är den enhet som befinner sig på olika ställen på skärmen och har i uppgift att tilldela poäng till spelaren när de två enheterna kolliderar. Ifall ingen kollision sker så kommer coin helt enkelt att bara befinna sig på samma ställe, och inte göra någonting ända tills en kollision sker och spelaren får ett poäng. Vid en kollision med coin så kommer en metod att anropas för att välja två nya slumpmässiga tal för var nästa coin ska hamna någonstans. Nedan visas två bilder där nya x och y värden tilldelas. Det är spawncoin som anropas när de nya värdena ska tilldelas. 8
5.3 Fiende(r) 9 En fiende har i uppgift att förflytta sig i ett visst mönster på skärmen. Till exempel om den börjar uppe i vänster hörn så kommer x och y värdet att öka hela tiden. Den flyttar sig diagonalt över skärmen och har antingen negativa eller positiva värden på x och y värdena beroende på vilken riktning de rör sig mot. Så fort fienden tar i en kant kommer x eller y värdet att ändras beroende på vilken kant som fienden kolliderar med. Ifall spelaren av misstag kolliderar med en av de fiender som finns tillgängliga så kommer spelaren förlora ett liv och spelet kommer att pågå precis som förut ända tills livet är noll och spelaren förlorar. Som jag nämnde tidigare så finns det totalt 8 fiender utplacerade på skärmen och var och en av dem rör sig när spelaren uppnår vissa poäng. 5.4 HP 9 HP (hitpoints) är ett föremål som förekommer på skärmen med ett visst intervall, nämligen 45 sekunders mellanrum, som sköts av en timer. HP har i uppgift att precis som coin endast befinna sig på ett slumpmässigt ställe ända tills en kollision sker. När en kollision med HP enheten sker ska ett extra liv tilldelas. Däremot om du redan har 4 liv (3 är standard) så kommer inte HP att existera överhuvudtaget förrän livet är tillbaka på 3 eller mindre, eftersom 4 liv är det maximala som spelaren kan ha. Hp kommer hursomhelst att kunna befinna sig på skärmen så länge som livet är under 4, så även om livet är 1, 2 eller 3 så kommer en timer räkna ner tiden tills Hp visas på skärmen! Ifall livet är 4 och du förlorar ett liv så kommer timern att starta vid kollisionen igen. Det betyder att den inte räknar över huvudtaget om livet är max. 5.5 Gameloop 9 9
Gameloop eller med andra ord, spel loopen används i main (se definition) och loopar så länge spelarens liv är mer än 0. Innanför loopen anropas en metod som i sig anropar alla move metoder (för att förflytta spelaren och fiender) så att allting hela tiden rör sig. Efter det används en inbyggd java metod som heter repaint. Vad repaint gör är helt enkelt att rita om hela skärmen så att när spelaren eller fienden har förflyttat sig så ritas de upp på sina nya positioner (denna process är väldigt snabb som du förstår). Jag kan även nämna att frågerutan som undrar om du vill spela på nytt finns här och testar ifall livet är noll så har du möjligheten att ställa tillbaka livet på tre. Därefter måste en ny metod anropas för att återställa alla värden där fienderna, spelaren och coin kommer att befinna sig. Även livet och poängen återställs till sina initieringsvärden och därmed kan loopen fortsätta. 10
6. Överblick av spelet 11 Den här bilden (förminskad) visar en överblick över hur spelet ser ut. Jag fick inte med hela bilden så alla fiender syns inte. 1 Spelaren. Den börjar alltså på mitten och så fort du rör piltangenterna eller W, A, S, D så förflyttar sig spelaren. 2 Coin. Det är denna som spelaren ska försöka ta för att samla så mycket poäng som möjligt. 3 Fienden. Den är röd för att den ska synas väl. 4 Gröna pricken som visas på skärmen med ett visst intervall så länge livet inte redan är 4. Spelaren har möjligheten att ta denna för att få ett extra liv 11
7. Tillvägagångssätt 12 Innan jag började skriva någon kod över huvudtaget så började jag med att skriva ner detaljerat i ett anteckningsblock vad spelet skulle innehålla, hur jag skulle gå tillväga för att det skulle vara så lätt som möjligt att veta vad nästa steg var att göra, samt spelets egenskaper (t.ex. färger, dimensioner och funktionalitet). Jag ritade upp ett flödesschema som visade hur spelet skulle fungera, med andra ord vad som skulle hända beroende på vissa omständigheter. Det var ett enkelt flödesschema, men det räckte till för att visualisera det jag hade tänkt göra (se rubriken flödesschema). När jag var färdig med planeringen så började jag med att rita upp rutan, eller fönstret där spelet skulle befinna sig. Jag ritade det grafiska gränssnittet med de angivna dimensioner som jag planerat i mina anteckningar och när allt var klart så valde jag färgerna. För att göra det så effektivt som möjligt så valde jag att programmera några saker åt gången och fokusera på det, istället för att göra hundra olika saker samtidigt vilket skulle ha blivit ostrukturerat. Ifall jag fastnade på ett problem så valde jag att arbeta med det ända tills det fungerade som jag hade tänkt mig. På det sättet var jag alltid insatt i vad som var problem och jag glömde inte bort vad jag gjort, eller vad jag hade tänkt göra. Ibland dokumenterade jag mitt i veckan om jag hade gjort mycket saker för att inte hamna på efterkälken med det. Jag antecknade vad jag hade gjort vilka datum, samt tiden det tog att göra, så jag behövde inte dokumentera allting i slutet med andra ord. I andra fall dokumenterade jag i slutet av veckan om jag hade gjort färre saker den veckan, eftersom det inte var allt för mycket att skriva om den veckan. Jag listade alla problem och lösningar jag stött på under veckan, samt skrev flera saker som berörde de nya funktionerna jag lagt till under rubrikerna jag hade. I slutet av examensarbetet ägnade jag så gott som all tid till att endast dokumentera mer och utöka dokumentationen som redan hade ganska mycket innehåll, eftersom jag var klar med spelet. Jag lade endast till en liten sak i spelet, nämligen den att spelaren kan styra med antingen w, a, s och d eller piltangenterna (piltangenterna var det som var standard i början). Det tog inte alls lång tid. Det enda jag gjorde var att lägga till en eller operator i metoden som avgjorde vad som skulle hända beroende på vilka knappar som trycktes ner. 12
8. Problem och lösningar 13 Här nedan följer ett antal problem och lösningar som uppstått under tidens gång. Först presenteras problemen som orsakade fel i spelet och sedan kommer en förklaring på vad problemen var och hur de löstes. 8.1 Problem 13 #001 Coin När jag hade fått coin att visas på skärmen var det naturligvis bra, men det fanns ett problem som gjorde att ingenting hände när jag kolliderade med den. Trots att jag hade skapat alla metoder för att öka poäng och skapa nya slumpvärden. #002 Livet När jag lyckats skapa en fiende som åkte över skärmen precis som den skulle, så var det dags att testa den riktiga funktionen, ifall livet minskade. Ja det gjorde det, men allt för mycket. Det var nämligen så att när spelaren och fienden kolliderade så dog spelaren direkt, trots att spelaren hade 3 liv!? Detta var förstås lite frustrerande eftersom jag inte hade räknat med det, men jag konstaterade senare att koden exekveras så snabbt så metoden som minskar livet hann anropas flera gånger. Jag visste alltså var felet låg men lösningen tog ändå ett par timmar att fixa, innan jag kom på hur jag skulle göra. #003 Hp enheten Jag hade skapat en ny klass som hette HpBoost och lagt till alla nödvändiga metoder i klassen. Jag fick den att visas på skärmen så det enda som behövde göras var att få den att visas på skärmen med ett visst intervall. Jag fick den att visas med ett intervall genom att använda en tråd. Problemet var att när jag kolliderade med enheten så fick jag en exception (läs definition) som gjorde att hela spelet stannade. Jag testade då att ändra på vissa saker i koden och det fungerade nästan men nästa problem var att när jag kolliderade med pricken så fryste spelet och enheterna på skärmen rörde sig igen efter fem sekunder (hade fem sekunders intervall när jag testade). När spelet sedan fortsatte så hade den gröna pricken redan fått nya värden och befann sig på ett annat ställe så det var inte riktigt som jag hade tänkt mig. Jag fortsatte att försöka hitta en lösning och när jag sedan fått spelet att inte frysa så förflyttade sig pricken varje gång jag åkte in i den istället så inte heller det fungerade. 13
Detta var förstås tidskrävande och till slut valde jag att göra på ett annat sätt. Jag valde därför att spelaren skulle få ett extra liv efter ett visst antal poäng (t.ex. 25) så varje gång spelaren samlat 25 poäng så skulle ett liv tilldelas. Det här fungerade. Hursomhelst kom jag på en lösning dagen efter och slopade den nya idén. #004 anrop till metod Jag skulle kunna nämna ett litet problem som uppstod. Det var när jag försökte anropa en metod via en referensvariabel till ett objekt av enemy och coin för att testa kollisionen. Det hände alltså ingenting när jag kolliderade med något av föremålen. 8.2 Lösningar 14 #001 coin Efter att ha suttit ner ett par timmar och klurat på varför det inte fungerade så kom jag på vad felet var. Jag började med att göra spelaren avlång och åkte runt på skärmen och märkte att jag fick poäng när jag inte åkte över coin, så jag visste att det hade slumpats nya värden av någon anledning. Sedan kommenterade jag ut delar av koden, var för sig för att se var problemet låg. Slutligen kom jag fram till att objektet jag skapat gav coin nya x och y värden så att coin låg kvar på samma ställe, men stället jag behövde åka över för att få poäng var på ett annat ställe än var pricken befann sig. Det hade att göra med att jag skapade ett nytt objekt av klassen i en annan klass, vilket resulterade i att jag fick poäng när jag åkte på det nya stället på skärmen (där coin inte ens befann sig). För att lösa det här problemet så använde jag referensvariabeln till huvudklassen (se definition) och via den kom jag åt referensvariabeln till klassen coin och på så sätt kunde jag anropa metoden och det fungerade utmärkt! #002 livet Jag kom på lösningen till livet på följande sätt: Livet minskade allt för snabbt, vilket resulterade i att spelaren dog. Jag testade att höja livet till 100 och då dog inte spelaren, däremot minskade livet med ungefär 7 10 åt gången. Efter ett par timmar kom jag fram till att jag kunde skapa en temporär variabel som hade värdet av vad den riktiga HP variabeln hade minus ett. Det jag gjorde sen när spelaren och fienden kolliderade var att sätta den riktiga variabelns värde till värdet av den temporära variabeln så till exempel om livet var tre från början så sattes det till två. Sedan anropade jag den metoden i kollisionstestet när de inte kolliderade. Detta resulterade i att när kollisionen var slut så sattes den temporära variabeln till ett liv mindre istället och nästa gång de kolliderade så blev den riktiga variabeln ett mindre igen. På detta sätt kunde jag förhindra att värdet på livet minskade med mer än ett vid en kollision. Bilden nedan visar metoden jag skapade för att detta skulle fungera 14
#003 hp enheten Jag kom på en lösning till hp enheten genom att använda en timer. Problemet som uppstod berodde på att jag använde mig av awt (se definition) i klassen HpBoost. Det uppkom när jag använde en tråd för att vänta en stund och således påverkade det awt tråden (se definition), så jag kunde inte använda en tråd för att bestämma intervallet. Jag läste därför om swing timers (swing används för grafiska fönster, knappar o.s.v) på oracles hemsida, eftersom jag inte hade arbetat med det tidigare (källan finns under rubriken källor). Jag gjorde om det som jag gjort dagen tidigare och det fungerade galant. Det tog endast en timme att lösa problemet som tidigare hade tagit flera timmar. Timern påverkade alltså inte det övriga spelet och därför fryste inte spelet när jag åkte in i enheten. #004 anrop till metod Det enklaste sättet jag kunde komma på för att lösa det här problemet var att ta bort det nyskapade objektet i player klassen för att se om en kollision skedde och istället använda en referensvariabel till klassen Game, som är huvudklassen. Från den referensvariabeln anropade jag i sig referensvariabeln till den klassen jag gjort ett objekt av tidigare för att komma åt metoden jag behövde använda. bilden är ett exempel på det som beskrevs i #004. 15
9. Detaljer 16 9.1 Nedräknande text 16 När jag skapade texten som räknar ner spelet så valde jag att den ska visas ungefär högst upp på mitten av skärmen. Hursomhelst, jag hade kunnat låta den vara kvar när spelet startade men istället valde jag att fixa en liten detalj. Detaljen är helt enkelt att texten försvinner när spelet går igång, och sedan visas den igen om du väljer att starta om spelet. Jag valde att skapa den lilla detaljen för att det skulle se lite bättre ut. 9.2 Spelaren blinkar 16 När jag hade kommit så långt att det var dags att skapa fiender så tyckte jag att det var bra, eftersom spelaren förlorade ett liv varje gång jag åkte in i en fiende. Däremot fick min bror testa spelet och han tyckte att det var bra, men det var svårt att se när du tappade ett liv, och du har kanske inte alltid tid att kolla till ditt liv när du fokuserar på att inte åka in i alla fiender. Även det här hade jag kunnat strunta i att fixa, men jag valde då att spelaren ska blinka vitt när fiender och spelaren kolliderar, eftersom att det är lättare att se när du förlorar ett liv. 9.3 Väggkollision 16 En annan sak som jag tyckte var lite roligt var kollisionen med väggen. Tanken var att så fort spelaren kolliderade med väggen så skulle den stanna, eftersom den stöter på ett hinder så det var vad jag började med, men jag tänkte på att vissa spel tillåter att spelaren åker in i väggen och sedan kommer ut på andra sidan och jag tyckte att det vore lite roligt att ha i mitt spel också, så jag ändrade i koden och spelaren kunde då åka från ena sidan av planen till andra sidan, medan fienderna alltid byter riktning när de träffar väggarna. Jag fick därmed titta på vilken pixel spelaren, samt fienderna befann sig på för att avgöra när spelaren ska synas på andra sidan av skärmen och även när fienderna 16
kolliderar med väggen. Det var alltså en liten detalj jag fick finslipa på för att det skulle se så verkligt ut som möjligt och att spelaren skulle röra sig mjukt över till andra sidan, så att det inte skulle se ut som ett hopp till andra sidan. 9.4 Hp boosten 17 En detalj jag fixade med enheten som tilldelar ett extra liv till spelaren var intervallet den skulle förkomma emellan. Jag valde att det skulle ta 45 sekunder mellan varje gång. Hursomhelst så gick det ungefär 3 sekunder snabbare ibland. Det hade att göra med att timern jag använde började räkna när objektet skapades (alltså när spelet startar). Det är sedan en nedräkning på 3 sekunder innan någonting händer och då blev det istället 42 sekunder innan enheten visades på skärmen från den riktiga starten av spelet. Här hade det kanske inte spelat så stor roll med några sekunder men jag ville ha det lika hela tiden så att det verkligen var korrekt så jag valde att fixa till det också. Nu är det 45 sekunder mellan varje intervall hela tiden! 9.5 Omstart av spelet 17 En bra sak jag införde var rutan som frågar ifall spelaren vill spela igen eller inte. När spelet var slut så fryste allting eftersom att villkoret till loopen som håller spelet igång inte längre var sant, vilket ledde till att spelaren måste avsluta spelet och starta det på nytt. Jag hade även kunnat välja att avsluta spelet av sig själv när spelaren dog men jag tyckte inte att det var en bra idé. Därför valde jag att anropa en frågeruta där spelaren själv väljer om spelet ska avslutas eller ifall man vill spela igen. Det gör det hela lite enklare och spelaren måste inte starta spelet på nytt varje gång den förlorar. 17
10. Lärdomar och frågor 18 Vad har jag lärt mig? Under tidens gång som jag programmerat så känner jag att det var ett bra val av mig att göra ett spel! Det kändes som en utmaning men ändå inte allt för svårt, så till en början funderade jag på hur svårt det egentligen skulle bli. När jag väl hade börjat programmera så tog jag en sak åt gången och det kändes ganska lätt. Jag fyllde bara på med de saker som skulle vara med och även ifall du tittar på koden nu så ser det ut att vara komplicerat och väldigt mycket kod. Jag har insett att det egentligen bara är som ett pussel, där alla bitar ska sättas på rätt plats för att fungera som man vill. Jag har egentligen inte lärt mig något nytt när det kommer till kodandet, förutom timern som jag aldrig hade använt förut, som jag kan ha användning för i andra spel eller applikationer som jag kommer göra i framtiden. Hursomhelst så har jag lärt mig att tänka på andra sätt när det kommer till programmering. I och med att jag har stött på en del problem som ibland kändes omöjliga att lösa så vet jag till nästa gång hur jag ska gå tillväga, varför det inte fungerar och vad som borde göras för att vissa problem inte ska uppstå. Det vill säga hur man löser vissa problem och vad man kan göra för att lösa dem. Jag har alltså lärt mig att allting inte behöver vara så komplicerat som man tror, bara man tänker efter och funderar över vad det är som orsakar problemen. Jag skulle säga att det har varit väldigt lärorikt att göra det här spelet, eftersom jag aldrig har gjort ett så här stort spel tidigare. För det första blir man väldigt glad när man löser något som man inte först trodde var möjligt, och för det andra så känns det bra att ha gjort något stort som man aldrig gjort tidigare. Jag visste helt enkelt inte var det skulle sluta, men nu när jag ser att allt är klart och fungerar som jag hade tänkt mig från början så känner jag mig stolt! Hade jag kunnat gjort något annorlunda? Den frågan har jag ställt mig själv också. Det finns säkert saker som hade kunnat gjorts på ett annat sätt, förmodligen hundra olika sätt men jag tycker att det sättet jag har gjort det på var ett bra sätt. Jag hade kanske kunnat fixa fiender på ett smidigare sätt men tyvärr hade jag inte kunskapen för att göra det. Jag misstänker att det skulle bli lite mer komplicerat än väntat om jag gjorde så och därför gjorde jag på det enkla och lite klumpigare sättet istället eftersom spelet ändå 18
inte är speciellt stort om man jämför med andra spel som finns idag. Ifall det hade varit ett sådant stort spel så hade jag varit tvungen att göra på ett annat sätt för att slippa skriva kod i åratal. Vad har varit mest givande med spelet? Jag tycker att fienderna har varit mest givande, eftersom utan dem så skulle spelet inte vara ett riktigt spel. Till en början fanns det ju bara en fiende och spelet var alltför lätt. Jag behövde bara åka och samla poäng i princip, det var så gott som omöjligt att dö. Därför tycker jag att de fiender jag lade till gjorde att spelet verkligen blev en utmaning och det finns en poäng med det. Det finns med andra ord någonting att uppnå med spelet. Det går inte att bara samla poäng utan du måste förutspå vad som kommer hända när fienderna flyger över hela skärmen. Jag skulle säga att det är rätt svårt att komma upp i höga poäng, så ifall du når exempelvis 100 så är det bra! Du måste hela tiden försöka undvika ställen som är riskabla och gör du inte det så kan det gå väldigt fort att förlora livet. Som ett litet tillägg kan jag nämna att jag testade att slå mitt nuvarande rekord som var 75. Allting gick bra och jag hade 4 liv (det mesta du kan ha). Jag hade 82 poäng men rätt som det var så förlorade jag alla fyra liv på endast några sekunder, så det gäller att passa sig! 19
11. Dagboken 20 17022016 (1,5h) Skrev ner vad jag tänkte göra, vad som ska finnas med och vad jag ska börja med, inklusive ritade ett litet flödesschema (sidan 20) för hur processen i spelet ska fungera för att ha det lättare när jag skulle börja med själva programmeringen så att jag alltid hade något att kolla på om jag funderade över något. 18022016 (1h) Skapade den grafiska rutan som spelet körs i. Jag hade i min planering redan skrivit ner mått på rutan (1920x1080), färger o.s.v för att enkelt kunna rita upp fönstret. 22022016 (3,5h) Skapade klassen Player och en del metoder och variabler så att spelaren kunde flytta sig på skärmen. Jag satt och funderade på om spelaren skulle kunna åka över från ena sidan av skärmen till den andra eller om den bara skulle kunna åka till väggarna. Jag finslipade på lite detaljer och när jag var nöjd ansåg jag att förflyttningen av spelaren var bra! Jag skapade även ett interface (se definitioner) som hade en metod för knapptryckningar som jag implementerade i player klassen. Till en början rörde sig inte spelaren när jag tryckte på knapparna så jag fick titta igenom koden några gånger och sen märkte jag att jag hade satt några variabler fel. 23022016 (1h) Började dokumentera lite över vad jag hade gjort än så länge så att jag hade en liten grund att stå på tills vidare. Jag skrev sedan om en del av dokumentationen senare för att jag tyckte att jag kunde skriva den på ett bättre sätt än så som jag hade gjort det. 03032016 (6h) Här skapade jag klassen coin. Jag började med att rita den på skärmen för att se att den visades överhuvudtaget. Sedan satte jag upp en metod för att slumpmässigt välja x och y värden, vilket fungerade. Poängen var att när spelaren åkte in i coin så skulle player tilldelas ett poäng och metoden som skapade slumpmässiga tal skulle anropas. Dock var det ett problem som gjorde att ingenting hände när jag åkte in i coin och detta tog ganska länge att lösa eftersom jag till en början inte hade någon som helst aning om vad felet var (se problem och lösningar för mer info). Jag skapade även en metod för att se till att coin inte kunde hamna under en av kanterna när den placerades på skärmen, så jag var tvungen att räkna lite pixlar och testa vad som var bäst. 20
04032016 (7,5) Skapade enemy klassen för att testa om jag kunde få en fiende i rörelse för att sedan kunna testa om kollision och liknande fungerade. Jag satte upp en metod för att testa ifall spelaren åkte in i en av väggarna, eftersom den då skulle byta riktning. Jag fick med andra ord räkna lite och se vid vilken pixel fienden skulle byta riktning. När det var färdigt ville jag testa kollisionen med spelaren så jag skrev en metod för det. Som jag nämnde i problem och lösningar så uppstod en bugg som gjorde att livet minskade allt för mycket, vilket ledde till att jag var tvungen att komma på en lösning. Jag skapade även en väldigt liten klass med endast en metod för att skapa en rektangel runt spelaren som jag sedan kunde använda för att kolla kollisionen med fienden och coin lite effektivare. 07032016 (3h) Organiserade om koden på vissa ställen där jag tyckte att jag kunde göra på ett bättre sätt eller på ett mer effektivt sätt så att koden skulle se lite snyggare ut. Jag ändrade på en del variabelnamn så att jag lättare kan se vad det är jag håller på med, samt ändrade namn på metoder som inte heller hade ett namn som jag tyckte att passade. 10032016 (2h) Tittade igenom koden ytterligare för att se om det var något som jag tyckte att borde fixas på ett annat sätt. Jag fixade till små saker som t.ex. var jag anropade vissa metoder och liknande. Jag hade även låtit min bror testa spelet och han sa att det var svårt att se ibland ifall spelaren och fienden verkligen kolliderade så jag valde att skapa en vit färg som blinkar till varje gång spelaren och fienden kolliderar, så att man lägger märke till att man har tappat ett liv. 13042016 (4h) Började dokumentera en del saker jag ansåg var viktiga. Jag dokumenterade bland annat om spelets olika enheter och hur de fungerar, samt skapade en inledning. Jag skrev ner de problem jag hittills stött på och beskrev vad problemet innebar och varför det ansågs som ett problem. Jag läste även igenom de olika delarna och gjorde ändringar där jag ansåg att det kunde skrivas på ett annat sätt. 14042016 (2h) Fortsatte att dokumentera det jag har åstadkommit hittills. Jag dokumenterade om vad jag har gjort vilka datum, lade till några begrepp under rubriken Definitioner av olika termer där man kan läsa om vad olika saker betyder och vad de är till för. Detta lade jag till för att folk som inte vet vad allt innebär ska ha en förståelse för vad jag pratar om ibland! Jag skrev också lösningarna till problemen jag har stött på under rubriken Problem och lösningar. 18042016 (2h) Här skapade jag en metod som räknar ner tiden innan spelet börjar. Jag tyckte att det kunde vara bra så att man kan förbereda sig innan fienden börjar åka över skärmen. Jag skapade även en frågeruta som visas när spelaren 21
dör. Rutan frågar ifall man vill spela igen eller om man vill avsluta spelet. Ifall spelaren väljer att spela igen så startar spelet om, annars avslutas det. För att kunna spela igen var jag tvungen att skapa ytterligare några metoder för att återställa alla variabler till sina ursprungliga värden och anropa dem ifall spelaren väljer att spela på nytt. 19042016 (5h) Planen för den här dagen var att skapa en ny klass för den så kallade hp enheten. Poängen var att denna skulle visas på skärmen med ett visst intervall och tilldela ett liv till spelaren när dessa kolliderade. Hursomhelst uppstod en bugg som beskrivs i problem och lösningar och därför valde jag istället att tilldela spelaren ett liv när spelaren fått ett visst antal poäng. Däremot ändrades min plan nästa dag! 20042016 (3,5h) Jag slopade idén med att tilldela spelaren ett liv vid ett visst antal poäng eftersom jag kom på en annan lösning för det jag egentligen tänkt göra. Jag använde istället en timer istället för en tråd när hp enheten skulle vänta en viss tid. Detta fungerade galant och tog endast en timme att lösa och därmed blev spelet som jag hade tänkt från början. Jag fixade även till koden med så kallade set och get metoder (se definitioner) när jag såg att det fungerade, samt finslipade lite på små detaljer och testade noggrant att allting fungerade. 21042016 (2h) Den här dagen ägnade jag mig endast åt att dokumentera det jag hade gjort den här veckan. Jag skapade nya rubriker och skrev lite under dem. Jag lade till några bilder som visar hur spelet ser ut och skrev om problem som uppstått inklusive lösningar. Jag utvecklade även texten under vissa rubriker där jag kände att jag kunde skriva om fler saker. 25042016 (1,5h) Här fixade jag mestadels småsaker. Bland annat flyttade jag texten som visar nedräkning innan spelet börjar, till mitten högst upp. Den hade tidigare varit på ett annat ställe eftersom jag endast satte två x och y värden som jag kom på i huvudet medan jag testade att det fungerade. Jag ändrade även lite småsaker i koden så att det blev bättre. Sedan testade jag spelet ganska noggrant för att försäkra mig om att inga onödiga buggar fanns. Jag kunde inte hitta någon bugg så allting var bra! 26042016 (3h) Objektorienterade koden så att jag skulle slippa skriva om samma sak två gånger. Det omfattade att skapa en ny klass där jag skapade metoden som jag inte ville skriva om två gånger. Metoden var helt enkelt till för att slumpmässigt välja två nya värden ifall att någon av enheterna skulle hamna utanför kanterna. Jag kunde därmed använda den här metoden för både coin, som ger poäng, samt hp enheten som ska tilldela ett liv. Jag var även tvungen att skapa några andra metoder för att det skulle fungera att använda sig av metoden i andra 22
klasser. Jag ändrade också på ställen i koden där jag hade gjort på ett mer komplicerat sätt än vad det egentligen behövde vara. Så det var exakt samma funktionalitet men lite enklare kod. 27042016 (5h) Här bestämde jag mig för att skapa flera fiender. Problemet var bara att jag inte kom på något bra sätt att göra det på. Jag visste alltså inte hur jag skulle göra riktigt för att få fler fiender på ett effektivt sätt så jag funderade länge på hur jag skulle gå tillväga. Till slut kom jag på att jag kan göra det på ett kanske mindre bra sätt men ändå ett fungerande sätt. Sättet jag gjorde på var helt enkelt att skapa åtta objekt av enemy klassen och eftersom varje referensvariabel är en kopia av objektet man skapar så kunde jag använda de olika variablerna för att anropa movemetoden som flyttar fienden. Dessutom satte jag upp variabler för var varje fiende ska befinna sig så att de flyttar sig på det sättet jag ville att de skulle göra. Sättet jag gjorde på är inte det bästa och det finns förmodligen olika sätt att göra det på men jag visste tyvärr inte hur, så jag gjorde det på ett lite klumpigare sätt eftersom det ändå är ett relativt litet spel! 28042016 (2h) Dokumenterade om veckans händelser och läste igenom hela dokumentationen för att se om den var bra. Jag skrev om text på ett annat sätt på vissa ställen och omformulerade mig på vissa ställen. 02052016 (1h) Gjorde det möjligt att styra spelaren med w, a, s och d ifall man föredrar det istället för med piltangenterna. Detta gick väldigt fort att göra. Mestadels funderade jag över om det fanns någonting jag kunde lägga till men jag kunde inte komma på något särskilt, så jag anser att spelet är klart vid det här tillfället. 03052016 (2h) Lade till två nya rubriker (detaljer, samt lärdomar och frågor). Jag dokumenterade om olika saker som jag kunde komma på. Ändrade på vissa ställen och la till lite mer text på andra ställen. Jag läste även dokumentationen till personen jag är opponent för (Jesper) och kommenterade lite saker i dokumentationen som jag tycker borde fixas till. 04052016 (2h) Funderade på vad jag skulle lägga till i min dokumentation, kom inte på något speciellt så jag fortsätter fundera över fler saker och tänker utöka texten på vissa områden. 09052016 (1,5h) Funderade ytterligare om det var något jag kunde komma på att lägga till i dokumentationen men bestämde mig för att endast justera och läsa igenom den för att göra den lite bättre. 10052016 (1,5h) Läste igenom dokumentationen och rättade till stavningar, uttryck med mera, samt skrev sammanfattningen eftersom att allting är klart. 23
11052016 (1h) Läste igenom dokumentationen ytterligare en gång för att försäkra mig om att allt var så bra som det skulle. 12052016 (4,5h) Fixade det sista på dokumentationen. Lade till en innehållsförteckning, tittade att sidnumren stämde, läste igenom dokumentationen en gång till, samt gjorde mitt flödesschema på http://www.draw.io för att det skulle se bättre ut än det som jag gjort på papper. Jag satte även färger så att det är lättare att se. Snyggade till rubriker och liknande och ställen där det var tomma ytor i dokumentationen så att det inte skulle vara så mycket tomt utrymme. 24
12. Flödesschema 25 25
13. Bilaga koden 26 26
14. Källor 27 http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html länk till swing timers, som jag behövde kolla upp för att få en viss funktion i spelet att fungera (beskrivs under problem och lösningar) http://www.draw.io Länk till draw.io som jag använde för att skapa mitt flödesschema. Jag ritade det först på ett papper men jag tyckte att det var bättre att göra det på datorn med färger så att man ser tydligare 27