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!

2 thoughts on “Tiled hitboxes

  1. Hej Erik!

    Kul att ni har hittat ett program som är så lätt att använda, bra beskrivet om hur det fungerar också!
    Jag tycker i övrigt att det är bra skrivet.
    Dock var det en något oklar och något snabb förklaring om hur textfilerna fungerar, man kanske skulle kunna ha något lite mer utförligt angående detta. Vad är det dom här siffrorna representerar till exempel? Hur fungerar sambandet mellan sambandet mellan “Tiled” och c++?

    Det jag generellt uppfattar genom din text är att du använder ganska avancerade ord. Det skulle underlätta om du använder ord som en “lekman” skulle förstå. Det skulle inte underlätta för läsaren utan det skulle underlätta för eget bruk också. Genom att skriva så “enkelt” som möjligt kan du gå tillbaka till denna post och enkelt förstå vad du faktiskt gjorde. Vilket kan ge en överblick om vad du gjorde och hur du gjorde det.

    Ett bra exempel som många erfarna programmerare använder sig av är att prata med ett gosedjur, att förklara för gosedjuret hur koden fungerar. Alltså att försöka förklara koden så “barnsligt” som möjligt, det kan göra så att man kommer ifrån de problem man fastnar med. (Det funkade för mig!).

    Som sagt i övrigt en bra och välskriven text. Kul att du löste ditt problem tillslut!.

    Like

  2. Tjena mannen

    Har lite tankar kring ert system och hur det fungerar. Saknar lite information angående hur systemet faktiskt utförs rent tekniskt. Förstod överlag hur ni har tänkt och tiled verkar vara ett effektivt program att skapa banor i. Men av det jag sett av ert spel och dess storlek så skulle det gå åt väldigt många tiles. och när ni kollar kollision så undrar jag om ni vid varje update kollar kollision mot alla tiles i hela banan vilket isåfall skulle ta onödig tid. Om jag hade varit ni hade jag laddat in delarna som har colliders på sig i olika vektorer. På så sett kan kollisionen kollas enbart mot objekt i spelarens närhet.

    Och det du skrev angående problemet med att kolla den faktiska kollisionen som skapade problem på grund av att origo för spritesen är högst uppe till vänster. Detta omöjliggör i sin tur användningen av axis aligned bounding box då den metoden räknar ut kollision baserat på centrala position av bilden med bredd och höjd som faktorer. Vi hade samma problem tills det att jag såg ganska tidigt att man kan ändra referenspunkten i spriten som positionen baseras på. Jag förstod inte exakt hur ni går till väga med det men skulle anta att AABB metoden är effektivare och mindre risk att något skulle gå fel. Så om ni har tid och känner för det så kan det vara ett alternativ värt att testa.

    Like

Leave a comment