Last Blog Post

Nu är kursens slut väldigt nära och takten på projektet har ökats markant. Det har crunchat en hel del med många timmar per dag. Mycket har blivit gjort under dessa sista dagar vilket gör det svårt att välja bara en artifakt att skriva om. Det som har gjorts är mycket saker men för det mesta små saker. Det jag gjorde förra veckan som var nytt för mig, fast fortfarande inte helt nytt, var att implementera animationer på skölden när den laddas upp. Det låter inte svårt och det var det jag tänkte när jag började med det hela.

Jag hade lagt dit en placeholder rektangel som bara fyllde ut hålet i HUDen när spelaren aktiverat skölden. Den blev mindre när spelaren tog skada och spelaren tog skada på sitt hp när skölden tagit slut. Det jag behövde ändra och lägga till var hela animationen på skölden som fylls på, en timer som efter 8 sekunder fyller på hela skölden igen med samma animation som när man aktiverar skölden, tillsammans med det nollställs den timern när spelaren tar skada så att skölden fylls på 8 sekunder efter spelaren har tagit skada. När skölden har fyllts på ska även en pulserande animation spelas hela tiden och den animationen ska förminskas när spelaren tar skada.

Det första jag gjorde var att ladda in ett spritesheet med hela animationen på i vår animationsklass. Vår animationsklass laddar in alla frames i en lista av rektanglar som den väljer ut från spritesheetet och spelar upp i en viss tid per frame update. Inladdningen av animationen gick smärtfritt eftersom jag har implementerat många animationer vid det här laget. Jag behövde nu lägga till en timer som räknade lika länge som animationens längd i sekunder för att sedan byta animation till den pulserande animationen när recharge animationen spelats klart. Det här steget gick också bra av samma anledning som tidigare. Det jobbiga steget som jag inte hade gjort förut var att försöka få den pulserande animationen att förminskas i bredd när spelaren tar skada. Den tidigare lösningen jag hade gjort var att ta en 1 pixel bred bild som jag sedan kallade på funktionen setScale på och skickade in sköldens ”liv” som argument. Men det funkade inte nu eftersom animationen inte är 1 pixel bred utan den är 41 pixlar bred. Lösningen jag kom fram till som var lättast och den enda som jag kunde förstå och orkade programmera klockan 2 på natten var att skapa en rektangel som är lika bred som sköldens ”liv” och bara rita ut animationen med samma storlek som den rektangeln. Detta görs med funktionen setTextureRect som tar in en IntRect som argument. Detta löste mina problem och ritade ut animationen rätt.

Mitt program som jag kan göra gifs med funkar inte just nu så får ta min gruppmedlems bild som inte har den fina animationen som jag pratat om i detta inlägg. Den har dock den andra animationen som jag lagt in som finns på skeppet istället. 🙂97102695740e036c79fe3f1be6d6224f

Tiled hitboxes

Förra veckan spenderades mestadels med att komma på ett sätt att exportera hela vår karta från Tiled till spelet och få hitboxes att fungera. Det var inte det lättaste jag har gjort.

cave_floor

Det hela började med att grafikerna ritat upp hela kartan i programmet Tiled. Det som är väldigt trevligt med det programmet är att det funkar som ett ritprogram där man laddar in ett så kallat ”Tile sheet” som innehåller alla väggar och golv som ska vara med i kartan.

Sedan väljer man en av rutorna, våra är 32×32 pixlar, och börjar måla. Vi hade redan en design på hur kartan skulle se ut så grafikerna tog den mallen på ett lager bakom själva banan som de ritade på och bara följde linjerna. När detta blev klart så blev det väldigt snyggt, men detta var det lättaste steget.

level_1_v2

Tiled har en funktion i sig som är mycket användbar för programmerare och folk som vill göra spel som är byggda på tiles. Det funkar genom att man kan exportera hela banan som en .csv fil eller .tmx fil. Detta är ungefär som textfiler som skriver ut siffror. Massa siffror. Närmare sagt 17050 siffror, eftersom vår bana är 155×110 tiles. Det man gör som programmerare då är att ta denna ofantligt stora textfil och laddar in den i c++ med den inbyggda funktionen fstream. Den tar en fil och läser varje rad och lägger in raderna i en lista. Denna lista konverteras sedan till en integerlista som tolkas av c++. Hur kan den tolka siffrorna? Jo den tar siffrorna i listan och samtidigt laddas ”tile sheet” in tillsammans och alla tiles i den bilden har ett id. Dessa id nummer är samma nummer som hamnar i den mycket stora listan. Så nu kan c++ associera siffrorna i listan med en tile i bilden som laddades in. Nästa steg är att rita ut dessa tiles i rätt ordning med rätt bild tillsammans så kartan syns. Detta görs genom att göra en loop som kollar igenom den långa listan, som är en 2D array, och placerar ut alla tiles på sin position. Tile nummer 5 som på vår karta har id nummer 9 placeras på pixel nummer 32*5 (32 pga. tiles bredd) vilket blir 160, så c++ ritar ut en tile nr 9 på plats 160 etc.

När detta är klart så ritas kartan ut rätt, problemet är att det inte finns någon kollision. Jag själv hade mycket svårt att greppa hur jag skulle kunna få till kollision eftersom man inte ska kolla kollision på alla tiles på hela kartan för det skulle ta alldeles för mycket minne på samma gång och spelet skulle spela väldigt segt. Så tanken är att kolla kollision med endast de tiles som finns i närheten av spelaren, helst endast de som spelaren ser på skärmen. För att lista ut det så tog jag positionen av spelaren i x subtraherade hälften av bredden på skärmen och dividerade med 32 för att få vilken tile som låg längst till vänster. Jag gjorde samma sak på y led men subtraherade hälften av höjden istället. Nu hade jag ett minsta x värde och ett minsta y värde på tilesen som spelaren ser. För att vara säker så tog jag minus en tile så att hitboxes kollas precis utanför skärmen. Nästa steg är att ta reda på de tiles som ligger utanför till höger och neråt, det gör man enkelt på samma sätt som innan men ändrar ekvationen till spelarens position i x adderat med hälften av skärmens bredd och dividerat med 32 och såklart samma som tidigare med y led.

minX = (shipPos.x – viewSize.width) / 32;

maxX = (shipPos.x + viewSize.width) / 32;

Samma för y led.

För debugging syfte så kan man rita ut rektanglar runt dessa fyrkanter som visar ifall hitboxes räknas ut korrekt. Om allt har blivit korrekt så kan man börja ge kommandon till spelaren när den träffar denna box. Boxen som vi har som är vägg är id nummer 9, så det är dessa som kollar ifall spelaren nuddar, varje update i spelet. Jag tänkte först att lättaste sättet att veta ifall spelaren nuddar en box uppifrån eller nerifrån eller från sidan är att kolla hur vinklad spelarens skepp är. Så ifall spelarens skepp är vinklad mellan 0 och 180 grader så pekar spelaren neråt, pga. C++ som läser 0 från höger Rotation-differences, eller om vinkeln är mellan 0 och -180 så pekar spelaren uppåt. Samma sak med sidorna mellan -90 och 90 så pekar den åt höger eller vänster.

Men så lätt var det inte eftersom 76 grader är både emellan 0 och 180 och -90 och 90 så skeppet flyttades runt oberäkneligt på skärmen. Efter ett tag gav jag upp och frågade en kompis som hjälpte mig att förstå hur det borde utföras. Om spelarens x position subtraherat med tiles x position är positivt så vet vi att spelaren är på höger sida. Detta eftersom c++ räknar origo högst uppe till vänster och positiva x är till höger och positiva y är neråt. Samma sak ifall vi får ut ett negativt tal så vet vi att spelaren befinner sig på vänster sida. I y led är det inte annorlunda, ifall differensen blir positiv befinner sig spelaren under tilesen och ifall differensen blir negativ befinner spelaren sig över. Nu visste jag exakt vart spelaren träffar tilen och kan, från den fina intersect funktionen få ett return värde som berättar hur mycket två boxar träffar i bredd och höjd och putta tillbaka spelaren eller flytta den i motsatta riktningen som den träffar tilen.

Vi hörs nästa vecka!

Animations

Betan nalkas och grupp 6 kämpar vidare för att klara målen.

Förra veckan tillbringades till att lägga in animationer, ljud och hitboxes för kartans väggar. Denna bloggpost kommer handla om animationerna som jag lagt in i programmet och den svarar på frågorna hur och varför jag gjort som jag gjort.

Vi hade inte tid att lägga in animationerna till alla assets i spelet i ett tidigare stadie men jag har kollat lite snabbt igenom tutorialen på githubs hemsida för att kunna uppskatta hur mycket tid det behövs för att implementera. Förra veckan började det närma sig betan och det var en bra tid att börja lägga in animationerna.

Jag tog tag i github’s tutorial och följde stegen. Efter att jag implementerat båda klasserna som tutorialen visade och laddat in spritesheetet som jag fått av Peter så, såklart funkade det inte, det ritades ut en stillastående bild. När jag kollar runt i koden märker jag hur mycket jag har snöat in mig i detta och hur tutorialen blev väldigt komplicerad när den applicerades i vår kod. Efter många timmar av trial and error så frågade jag hur en annan grupp hade löst sina animationer. Anton Olin hjälpte mig med att förklara deras animationmanagers så att jag kunde använda samma teknik i vår kod. Det gick mycket bättre och den koden var väldigt mycket enklare att förstå än tutorialen jag följde. Allt som behövdes göras var att ladda in spritesheet’s koordinater i en lista och sedan lägga in hur lång tid varje frame skulle spelas upp sen skapas en texturerect som har regionen av texturen och en texture som har texturen av spritesheet. Sedan ritas den ut och animationen spelas upp.

Jag tog beslutet med att inte använda githubs tutorial för att jag kände att jag snöade in mig i all kod och allt blev bara krångligare ju mer jag försökte fixa. Det bästa med att ta hjälp av en annan grupp som fixat samma problem är att man börjar om på nytt och får en genomgång på hur de fick det att funka, vad för fel de stötte på och hur man kan undvika dessa i framtiden, så det blir nästan garanterat att det funkar för andra projekt också.

När animationen fungerade för idle/walking så ska den ändra animation när den kommer tillräckligt nära för att attackera spelaren. När spritesheets etc. för attacking var inlagt så försökte jag ändra animationen, men då kraschade programmet för att spriten blir NULL. Jag har inte löst detta än men det känns mer som ett slarvfel från mig som jag kan lösa fort om jag sätter mig ner och tänker lite. Jag gick vidare och la till animationerna till spiderlingen som också lades till. Jag gjorde likadant som med den första fienden.

81a944556ae77755262af39b677ed531

Making a HUD work

Efter att vår Alfa-presentation fick kompletteringar att göra så har jag suttit och jobbat med dessa. Det vi fick komplettering på var att man ska kunna döda fienden som fanns och att ha en fungerande HUD.

Det jag satt med mest var vår Heads Up Display, aka HUD, som spelaren ser när han eller hon spelar spelet. Den kan representera hur mycket skada spelaren tål eller hur mycket skott kvar spelaren har att skjuta. Just vår HUD, för tillfället, visar bara hur mycket skada spelaren kan ta samt hur mycket den har tagit med hjälp av en mätare. Saker som ska tillkomma är en sköld, så spelaren kan ta extra mycket skada, den genereras dessutom när spelaren inte tagit skada på ett tag, samt en räknare för hur mycket skott som spelaren har kvar på sitt andra vapen. Men som sagt så har jag hittills bara lagt till en livmätare.

Det första jag behövde tänka på var hur jag skulle få mätaren att kunna röra på sig. Min tanke var att skapa en grön rektangel bakom den genomskinliga tuben som Peter har ritat. Så jag skapade en klass till HUDen och började med att lägga in bilden på den och rektangeln som skulle föreställa livet. Sedan kollade jag så jag blev nöjd med hur den såg ut i spelet. Det lätta med detta är att det handlar om väldigt lite kod att skriva, allt som görs som sagt är att lägga in en bild och att skapa en rektangel. Men det första jobbiga jag kom på var hur jag skulle kunna rita ut bilden på spelets view, som är det man ser av spelplanen. Jag började med att rita ut den bara på spelbanan, vilket gjorde att den ritades ut högst upp i vänstra delen av spelplanen, såklart. Så jag ritade ut den på spelarens position och subtraherade hälften av bredden på skärmen och addera med hälften av höjden, eftersom spelaren befinner sig i mitten av skärmen. Detta gjorde att HUD-bilden betedde sig konstigt och rörde sig runt lite grann när man körde med skeppet. Min lösning var att rita ut det på en ny view som läggs ovanpå spelets view, men som också följer efter spelarens rörelser. Detta löste även problemet med att jag ritar ut en svart bild ovanpå hela spelet för att rita ut ljuset som fick HUDen att bli synlig endast när man lös på den.

12655805_1032024530192444_601659818_n

Nu till det verkliga problemet, hur ska jag få rektangeln att bli mindre när spelaren skadas? Jag kollade runt i rektangelklassens egna funktioner och två stycken verkade funka för mig: scale() och setScale(). Jag började med scale som fungerar att den tar in två värden, ett x och ett y värde som sedan multiplicerar värdena med den originella storleken på rektangeln. Det jobbiga med detta, som jag kom på, är att om spelaren tar 10 i skada (spelaren har 100 i liv) så är det 100*0.9, men nästa gång spelaren skadas så är inte 0.9 * 90 = 10 utan 9 etc. Så min lösning blev tillslut att ha ett maxlife och ett currentlife. Maxlife är alltid 100 och currentlife ändras när spelaren tar skada. Jag ändrade också till setScale istället som fungerar så att den tar två värden som scale men den multiplicerar original värdet med det nya värdet. Så ifall rektangeln är 100 i längd och jag använder setScale(2,1) så multipliceras 100 med 2. Jag ändrade också rektangeln till en pixel bred och satte setScale(100, 1). Koden som ändrar storleken på rektangeln:

void HeadsUp::GotHit(float damage)
{
currentlife -= damage;
hSprite.setScale(currentlife, 1);
}

currentlife är likamycket som maxlife vilket är 100. Nu skadas spelaren 10 skada istället så damage blir 10 istället för 0,9. Detta fungerade mycket bra och jag gjorde samma uträkning för att få tillbaka liv men adderar heal istället för att subtrahera damage från currentlife.

Desolate Echo – Game Development Week 4

Förra veckan var inlämning av Gamedesign document som alla jobbade hårt på för att göra klart det som inte var färdigt än. En ändring vi gjorde med projektet var att byta namn från Colossal Core till Desolate Echo. Vi ansåg att Colossal Core inte längre stämde överens med vad vi gjort spelet till. Tidigare hade spelet fokuserat bara på kolossala bossar som man ska slåss mot i kärnan av en planet, vi ändrade båda dessa delar av spelet och samtidigt namnet. Det nya namnet handlar mer om att vara ensam i ett mörkt och trångt utrymme och endast höra ekot av sig själv. Från att handla om att döda kolossala bossar ändrade vi det till att döda en boss per bana och en massa små fiender längs vägen dit. Vi utökade också kartan med en del och har nu mycket mer små gångar och delar att utforska.

I programmeringsväg har jag själv suttit och jobbat med att kanonen på taket av skeppet ska följa musens position, det har gått sådär. Logiken är inte jätte svår, ta positionen på musen relativt till fönstret, ta positionen av skeppet och räkna ut vinkeln emellan dessa. Min första tanke var att använda sin, cos och tan för att få ut vinklarna. Jag ritade upp en fin bild som demonstrerar min tanke:Untitled

Så i klartext för att räkna ut vinkel c behöver man använda väldigt basic gymnasiematte. tan(c) = sidey/sidex, vilket i mitt exempel blir tan(c) = 3/5, tan^-1(3/5) = 80. Jag la till detta i projektet. Musens position updateras rätt relativt till fönstret och kanonen rör sig efter musen. Problemet jag hade först var att jag hade tagit positionen av skeppet på hela kartan, vilket ändras när man flyttar på sig. Så istället för det så hämtade jag hälften av fönstrets x och y värden för att räkna ut avståndet och vinkeln till musen därifrån istället. Jag gick ut på internet för att hitta ett alternativ på hur man kan lösa problemet. Några sa att kanonens sprite måste peka höger för setRotation()’s noll är till höger inte uppåt. Men det löste ju inget såklart. Sedan sa folk att jag skulle använda mig utav

atan2f(rhs.y, rhs.x) * 180.0f / PI

där rhs.y och rhs.x är sidex och sidey på bilden. (* 180 / PI) är för att konvertera från radian till grader. Detta funkade mycket bra och jag kunde gå vidare.

Jag arbetade med projektilerna för skeppet också vilket gick ganska smärtfritt. Jag kopierade lite funktioner från skeppets klass och la till i projektilklassen. Sedan la jag till samma kod för kanonen som fick den att följa musen i klassen och fixade en funktion som gav projektilen en hastighet och en vinkel som räknades ut med samma funktion som innan. Projektilobjektet skapas i turretklassen när spelaren klickar på vänster musknapp och läggs i en lista så spelaren kan skjuta flera gånger.

Jag fick också hjälp av Semih med ljuset som fick det att funka så vi kan visa upp det på alfapresentationen imorgon. Mycket snällt!

Det han gjorde var att skapa ett nytt lager ovanför det befintliga som allt i spelet ritas ut på. Sedan tar han och gör det övre lagret svart och sen laddapointLightTextures en textur in som är en vit-skinande-ljus-liknande bild. Lamptexturen ritas ut med en blending som gör så att det vita i texturen blir genomskinligt. Så skapades ljuset! c924b0fc6ffefb124b7f7393b6455dc5

Game Development Week 3

Förra veckan jobbade jag mycket med kodning i bakgrunden till spelet. Jag jobbade med ScreenManager, HoverCraftTurret, InputManager, LightManager, PlayerShip, de olika menyerna som main menu, pause menu och spelfönstret och jag gjorde en soundmanager.

ScreenManager gick bra att skriva, jag kollade upp en tutorial på github som gick igenom bra hur man gjorde. Det tog ungefär en timme att bli klar med. Sedan gjorde jag även de olika fönsterna som man ser när man startar spelet och när man spelar. Det var från samma tutorial så det tog lika lång tid och lika smärtfritt. När jag var klar med screenmanager och de olika screensen så började jag att arbeta på ljusmotorn, jag kollade runt på internet efter ett bra alternativ av olika ljusmotorer och hittade en som hette Let There Be Light. Jag laddade ner koden för att se om jag skulle kunna skriva den själv men insåg fort att det skulle ta lika lång tid att skriva en ljusmotor som det skulle ta att skriva hela spelet, om inte längre. Jag började försöka implementera denna motor i spelet men märkte att det var ganska krångligt eftersom man behövde ladda ner extra bibliotek till c++ för att det skulle funka. Men jag läste forumtråden och såg att skaparen hade släppt en version 2 som fanns att ladda ner gratis, så jag gjorde det och märkte att denna var lättare att använda och man behövde bara använda SFML och inte glew som behövdes för LTBL 1. Trots att det var lättare att förstå så har jag fortfarande inte fått det att funka än, men jag kämpar för att få det implementerat i spelet.

Jag har också jobbat en del med PlayerShip tillsammans med Alfons som hade uppgiften från början men han behövde lite hjälp med matematiken på hur skeppet ska svänga, så jag hjälpte honom med den uppgiften och det gick bra. Problemet var pga. att man svänger med wasd och skeppet vänder sig mot riktningen man trycker och samtidigt får fart åt det hållet. När t.ex. skeppet pekar åt 90° vilket är knappen D och man vill åka 270° alltså till vänster, vilket är knappen A, så måste man skriva if(playership.getRotation() < 270 && playership.getRotation() >= 90) så ska skeppet rotera 1.8° per frame i klockans riktning. Detta måste man göra för alla riktningar så att man kan vända åt alla håll från alla håll utan att skeppet snurrar åt fel håll. Men matematiken löste sig ganska snabbt när jag hjälpt till och skeppet åkte mycket fint över skärmen.

Det sista jag jobbade med förra veckan var en soundmanager. Den gick väldigt bra utan några fel. Det behövdes inte många rader kod för att det skulle funka. Koden laddar in en plats från datorn i string form och gör en buffer som sedan görs till ett sound som returnas tillbaka till klassen som använder ljudet.49bf3dcc5b66552e3cf0761e189737fe