Permalänk

Kollisions detektion

Håller på att göra ett litet plattformsspel, har klarat av kollisions detektionen och allting fungerar bra. Men en tanke slog mig, då jag byggt upp kollisionerna med hjälp av loopar och listor. Typ kolla om spelaren krockar med en solid eller om ett skott träffar en fiende. Saken är att jag kollar om spelaren krockar med alla solider på banan eller om skotten kolliderar med alla fiender på banan. Det är ju väldigt slöseri med resurser, även fast det inte är ett problem intresserar jag mig ändå för hur man bygger en fungerande kollisions detektion utan att kolla alla solider.

Hade en tanke om att när man står på en plattform sluta loopa då jag ju vet att den står på en plattform så det är onödigt att fortsätta kolla om den krockar med andra. Problemet då är att jag alltid måste kolla om spelaren flyttats från soliden vilket leder till en annan loop som måste köras.

Jag läste att i de äldre super Mario så kollar spelet bara blocken i närheten av spelaren och inte alla block på hela banan och samma sak med fienderna.

Hur bygger man en algoritm som bara kollar de närmaste solider? Eller finns det något annat sätt? Tycker detta är ett intressant ämne så länka gärna om någon vet någon bra sida där man kan läsa lite mer om kollisions detektion eller andra optimeringar man kan göra. Jag jobbar i Java om någon undrar.

Permalänk
Medlem
Skrivet av xxstaticz:

Håller på att göra ett litet plattformsspel, har klarat av kollisions detektionen och allting fungerar bra. Men en tanke slog mig, då jag byggt upp kollisionerna med hjälp av loopar och listor. Typ kolla om spelaren krockar med en solid eller om ett skott träffar en fiende. Saken är att jag kollar om spelaren krockar med alla solider på banan eller om skotten kolliderar med alla fiender på banan. Det är ju väldigt slöseri med resurser, även fast det inte är ett problem intresserar jag mig ändå för hur man bygger en fungerande kollisions detektion utan att kolla alla solider.

Hade en tanke om att när man står på en plattform sluta loopa då jag ju vet att den står på en plattform så det är onödigt att fortsätta kolla om den krockar med andra. Problemet då är att jag alltid måste kolla om spelaren flyttats från soliden vilket leder till en annan loop som måste köras.

Jag läste att i de äldre super Mario så kollar spelet bara blocken i närheten av spelaren och inte alla block på hela banan och samma sak med fienderna.

Hur bygger man en algoritm som bara kollar de närmaste solider? Eller finns det något annat sätt? Tycker detta är ett intressant ämne så länka gärna om någon vet någon bra sida där man kan läsa lite mer om kollisions detektion eller andra optimeringar man kan göra. Jag jobbar i Java om någon undrar.

http://games.greggman.com/game/programming_m_c__kids/ känns som en trevlig artikel som ger lite insikt i hur man kunde lösa saker på NES-tiden.

Är alltid lite intressant så ska nog läsa själv men kan inte uttala mig om några slutsatser utifrån artikeln (eller lova att den faktiskt besvarar just det du undrade)

Visa signatur

AMD Ryzen9 5900X || Gigabyte X570 Ultra || RTX 3090 FE || Gskill Trident Z 3600 64GB || Samsung 950 Pro 512GB || Samsung 960 Pro 1024GB || XB270HU 1440p IPS G-Sync

Permalänk

Hur algoritmen kan utformas beror helt enkelt på hur datastrukturen där du lagrar dina "solids" ser ut.
Man skulle ju till exempel kunna ha koll på vilka block man redan "har gått förbi" om de ligger lagrade från vänster till höger eller liknande, och sen bara kolla fram till första blocket som man inte krockar i för att det är för långt till höger. Då kollar man enbart blocken som är i närheten vågrätt, liknande kan göras lodrätt.

Lycka till

Permalänk
Medlem
Skrivet av Stormfisken:

Hur algoritmen kan utformas beror helt enkelt på hur datastrukturen där du lagrar dina "solids" ser ut.
Man skulle ju till exempel kunna ha koll på vilka block man redan "har gått förbi" om de ligger lagrade från vänster till höger eller liknande, och sen bara kolla fram till första blocket som man inte krockar i för att det är för långt till höger. Då kollar man enbart blocken som är i närheten vågrätt, liknande kan göras lodrätt.

Lycka till

För att ytterligare förtydliga(?) så är väl avsikten med första meningen egentligen att "du kanske ska använda en annan datastruktur för att kunna lösa det här effektivt", bara så att ingen läser det extremt bokstavligt och ser deras kanske naiva val som något som kan hållas fast vid och bara hitta en algoritm som passar.

Visa signatur

AMD Ryzen9 5900X || Gigabyte X570 Ultra || RTX 3090 FE || Gskill Trident Z 3600 64GB || Samsung 950 Pro 512GB || Samsung 960 Pro 1024GB || XB270HU 1440p IPS G-Sync

Permalänk
Skrivet av evil penguin:

För att ytterligare förtydliga(?) så är väl avsikten med första meningen egentligen att "du kanske ska använda en annan datastruktur för att kunna lösa det här effektivt", bara så att ingen läser det extremt bokstavligt och ser deras kanske naiva val som något som kan hållas fast vid och bara hitta en algoritm som passar.

Väldigt intressanta idéer ska ta mig en titt ikväll på hur jag skulle kunna bygga upp listan utifrån vart spelaren befinner sig på banan

Permalänk
Medlem

Jag antar att varje objekt och spelare har någon form av kordinat-position. Har de detta kan du väl jämföra med alla inom ett visst intervall, kanske spelarens position +- ett lagom värde.

Jag vet inget om din nivå men tänkte på att Collisionen bör även vara en separat metod som kallas på från gameloopen vare sig du står still på plattformen eller vad du än gör. Du kanske vill lägga till att fienden kan skjuta tillbaka? Elller någon annan spelare skjuter dig i framtiden? Eller kanske en boss-fight? Planera framåt! CollisionsDetectorn bör gås igenom varje gång positionen förändras för både skott, fiender och spelare, men bara nära dig (dvs intervallet spelare+-något). Självklart kan strukturer se ut hur som helst, och det finns oändligt med kombinationer, men detta är en idé.

Jag använder XNA Game Studio med C# just nu, men språk spelar inte så stor roll.

Visa signatur

Speldator: Antec 1200 | i7-930 @ 4.3Ghz+ | GTX 480 | 3x2GB RAM
Kylning: Koolance 360 @ CPU, Koolance VID-GTX480 @ GPU, XPCS RX480x2 Radiatorer, DCP 4,0 mm.
Ljud: Asus Xonar Essence STX + Sennheiser PC 360

Permalänk
Skrivet av Sethai:

Jag antar att varje objekt och spelare har någon form av kordinat-position. Har de detta kan du väl jämföra med alla inom ett visst intervall, kanske spelarens position +- ett lagom värde.

Jag vet inget om din nivå men tänkte på att Collisionen bör även vara en separat metod som kallas på från gameloopen vare sig du står still på plattformen eller vad du än gör. Du kanske vill lägga till att fienden kan skjuta tillbaka? Elller någon annan spelare skjuter dig i framtiden? Eller kanske en boss-fight? Planera framåt! CollisionsDetectorn bör gås igenom varje gång positionen förändras för både skott, fiender och spelare, men bara nära dig (dvs intervallet spelare+-något). Självklart kan strukturer se ut hur som helst, och det finns oändligt med kombinationer, men detta är en idé.

Jag använder XNA Game Studio med C# just nu, men språk spelar inte så stor roll.

Så som det ser ut nu har jag en lista med solider med olika x,y värden som bestämmer var den finns. Jag kollar varje frame vart spelaren befinner sig och om den kolliderar med alla solider i listan.

Tänkte om man hade två listor istället där den ena innehöll alla solider och den andra fylls med solider från den första beroende på olika checkpoints. Så när du når en ny checkpoint så töms lista nummer två och fylls på med ett nytt antal solider som motsvarar solider fram till nästa checkpoint. Då får man även in att kan hålla koll på checkpoints som man sedan kan respawna vid.

Kommer det spara datorkraft om man gör på detta sätt eller finns det ännu något annat alternativ som skulle fungera bättre?

Skickades från m.sweclockers.com

Permalänk
Medlem

Det här är ett sätt att strukturera upp sina solider som är ganska enkelt och förstå, det finns massor av andra sätt som alla har sina fördelar och nackdelar. Bäst fungerar det om soliderna ligger hyfsat jämnt utspridda i x-led, dom är ungefär lika stora och det inte är så många solider ovanpå varandra i y-led.

Du sorterar alla soliderna enligt deras x-position och stoppar in i en Array. Sen om du vill veta om spelaren kolliderar kollar du bara mot dom solider som ligger i samma x som spelaren.

Så om din bana är 10 000 pixlar bred i x-led skulle du kunna ha en array med 1000 element. En solid som ligger på x = 13 lägger du i x / 10 avrundat till heltal, dvs array[1]. En som ligger på x = 9321 lägger du i array[932] och så vidare.

Eftersom du säkert har flera saker på samma x-position behöver varje element i arrayen vara en lista. Dvs i mitt exempel blir det ArrayList array[] = new ArrayList[1000].

Sedan när du vill kontrollera om spelaren kolliderar med något behöver du veta hur bred spelaren är och hur bred din bredaste solid är. Låt säga att spelaren är 16 pixlar bred och den bredaste soliden 40 pixlar. Spelaren befinner sig på x = 200. Alltså måste du kolla från x = 200-16-40 = 144 pixlar och x = 200+16+40 = 256 pixlar. I arrayen blir det alltså alla element mellan 144/10 = 14 och 256/10 = 26.

Varje gång en solid flyttar sig behöver du komma ihåg att även uppdatera arrayen så att soliden ligger på rätt ställe. Om just 1000 är rätt storlek på arrayen beror på hur stor dina banor är, hur många solider det finns och hur stora dom kan vara. Ju större array ju mer minne går åt, och ju fler array-element kan du behöva gå igenom. Samtidigt vill du inte att det ska ligga för många solider i ett array-element. Enklast är att börja på ett värde du tror är bra och sedan testa dig fram om det inte funkar.

Visa signatur

AK47s for everyone! - Angry mob
Since NaN /= NaN, I think, we should decipher 'NaN' as 'Not a NaN' - Miguel Mitrofanov
(Varför är människan så benägen att tro på Gud?) Antagligen har det lönat sig och evolutionen har drivit fram sådana hjärnor. - Anon

Permalänk

En intressant datastruktur att titta på är kanske

http://en.wikipedia.org/wiki/Binary_space_partitioning

Den funkar lite som det VB skrev om men istället för att sortera bara i x led kan man sortera i flera dimensioner samtidigt... typ.