[JAVA] Simpel jävla kollision?

Permalänk

[JAVA] Simpel jävla kollision?

VARJE gång jag ska göra något spel i Java har jag problemet. Jag kan bara inte lösa kollisionen på ett snyggt sätt.

I mitt senaste projekt trodde jag att jag äntligen löst det men efter lite mer test så inser jag att jag inte kommit ett dugg närmre.

Problemet är inte att upptäcka kollisionerna (Jag låter spelaren extenda Rectangle och använder metoden intersects(object)) utan att göra så att man inte kan hamna i den. Jag vill dessutom att det ska funka för ALLA block jag sätter ut på spelplanen (Har en ArrayList med block) så när jag lägger till ett block i listan vill jag att det automatiskt ska funka utan att jag ska behöva lägga till förutsättningar.

Om vi tar kollisioner ovanifrån så ser mitt tänk ut såhär:
1. Skapa ett nytt block som har samma X-värde som spelaren men spelarens Y-värde + spelarens Y-hastighet.
2. Kolla om det nya blocket kolliderar med något block i ArrayListen blocks
3. Om 2 är true så får spelaren det undre blockets Y-värde MINUS dess höjd (Spelaren har samma höjd som blocken)

Så jag kollar liksom på nästa "frame" i alla riktningar och ser om det kommer ske någon kollision. Om det gör det så placerar jag ut spelaren precis ovanför/under/bredvid blocket.

Om vi tar rent kodmässigt så ser det ut såhär:

public void collision() { Block dB = new Block(this.x, this.y + addVelY, width, height); //Det nya blocket som kollar nedåt Block uB = new Block(this.x, this.y - addVelY, width, height); //Det nya blocket som kollar uppåt Block rB = new Block(this.x + addVelX, this.y, width, height); //Det nya blocket som kollar höger Block lB = new Block(this.x - addVelX, this.y, width, height); //Det nya blocket som kollar vänster for(int i = 0; i < Main.blocks.size(); i++) { if(dB.intersects((Block)Main.blocks.get(i))) { this.setLocation(x, (int)((Block)Main.blocks.get(i)).getY() - height); velY = 0; Main.setGravity(0); } if(uB.intersects((Block)Main.blocks.get(i))) { this.setLocation(x, (int)((Block)Main.blocks.get(i)).getY() + height); } if(lB.intersects((Block)Main.blocks.get(i))) { this.setLocation((int)((Block)Main.blocks.get(i)).getX() + width, y); velX = 0; } if(rB.intersects((Block)Main.blocks.get(i))) { this.setLocation((int)((Block)Main.blocks.get(i)).getX() - width, y); velX = 0; } } }

gravity har jag för att velY alltid ska öka med gravity om den inte står ovanpå ett block.
addVel är hastigheten den har i respektive riktning

Det den här koden gör är:
1) Om du kommer ovanifrån så hamnar du precis under blocket du ska stå på
2) Om du kommer från sidan hamnar du precis under blocket du ska vara bredvid
3) Kommer du underifrån får du en stor hastighet till vänster?!

Om någon vet hur man löser det här (Du behöver inte veta hur man ska få min metod att funka, går lika bra att bara förklara hur jag borde göra istälet!) så kommer jag älska den personen för evigt. Har som sagt det här problemet VARJE gång jag ska göra något spel :/

Visa signatur

| Sony A580 | Sigma 10-20/4-5.6 | Tamron 17-50/2.8 | Sigma 70/2.8 Macro | Konica Minolta 50/1.7 | Konicha Minolta 75-300/4.5-5.6 |

Permalänk
Medlem

"Jag låter spelaren extenda Rectangle"
Gör inte det.

Två av blocken du genererar runt spelaren är nonsens och de andra två berättar bara halva sanningen. Skapa bara ett block och lägg på "hastigheten" för både x och y. Kolliderar den får du därefter avgöra vad du egentligen vill göra med spelaren.

Visa signatur

"Some poor, phoneless fool is probably sitting next to a waterfall somewhere, totally unaware of how angry and scared he's supposed to be." - Duncan Trussell

Permalänk
Skrivet av gibbon_:

"Jag låter spelaren extenda Rectangle"
Gör inte det.

Två av blocken du genererar runt spelaren är nonsens och de andra två berättar bara halva sanningen. Skapa bara ett block och lägg på "hastigheten" för både x och y. Kolliderar den får du därefter avgöra vad du egentligen vill göra med spelaren.

Varför ska jag inte extenda rectangle? Tycker metoden intersects är rätt mysig!

Som du säger går det nog att "förkorta" min kollisionsmetod. Ska testa det!

Visa signatur

| Sony A580 | Sigma 10-20/4-5.6 | Tamron 17-50/2.8 | Sigma 70/2.8 Macro | Konica Minolta 50/1.7 | Konicha Minolta 75-300/4.5-5.6 |

Permalänk
Medlem
Skrivet av Son of Qwerty:

Varför ska jag inte extenda rectangle? Tycker metoden intersects är rätt mysig

För en spelare är inte en rektangel. Den må vara rektangulär på skärmen eller i dina fysiska beräkningar, men en spelare är inte en rektangel.
Bättre vore om den hade tex en rektangel som fysisk representation.

Visa signatur

"Some poor, phoneless fool is probably sitting next to a waterfall somewhere, totally unaware of how angry and scared he's supposed to be." - Duncan Trussell

Permalänk
Skrivet av gibbon_:

För en spelare är inte en rektangel. Den må vara rektangulär på skärmen eller i dina fysiska beräkningar, men en spelare är inte en rektangel.
Bättre vore om den hade tex en rektangel som fysisk representation.

Jo, det är ju alltid det där problemet med hitbox. Det här är ett projekt i programmering c så jag hade tänkt låta spelaren vara en kub helt enkelt.

Den nya kollisionshanteringen är BRA mycket kortare och funkar perfekt nedåt. Uppåt så hamnar man fortfarande precis ovanför blocket och i sidled fungerar inte kollisionen alls :/

Block colBlock = new Block (this.x + addVelX, this.y + addVelY, width, height); for(int i = 0; i < Main.blocks.size(); i++) { if(colBlock.intersects((Block)Main.blocks.get(i))) { velX = 0; velY = 0; double dx = ((Block)Main.blocks.get(i)).getX() - this.x; double dy = ((Block)Main.blocks.get(i)).getY() - this.y; dx = Math.sqrt(Math.pow(dx, 2)); dy = Math.sqrt(Math.pow(dy, 2)); System.out.println(dx + ", " + dy); move(x, (int)(y + dy) - height); velY = Main.getGravity(); Main.resetGravity(); } }

Stort tack för att du tar dig tid!

EDIT: Kom på nu att sidled funkar inte för att jag tog bort det.
När jag hade:
move((x + dx) - width, (y + dy) - height);
så flög den bara åt vänster hela tiden. Tog jag bort det så fungerade nedåtkollision iaf.

Visa signatur

| Sony A580 | Sigma 10-20/4-5.6 | Tamron 17-50/2.8 | Sigma 70/2.8 Macro | Konica Minolta 50/1.7 | Konicha Minolta 75-300/4.5-5.6 |

Permalänk
Hedersmedlem

När jag gjorde ett spel tidigare fick min spelare ha en variabel Sprite som jag använde för att kolla kollision.

Permalänk
Medlem

Jag hade en metod som anropades varje gång spelaren kolliderade med något. I den metoden så hade jag en while loop som kollade om spelaren skulle kollidera med något om man flyttade upp den 1px, sedan höger, vänster och neråt. När den tillslut hade hittat vilket håll som det går att flytta spelaren åt så returneraders den nya positionen.

Tänk på att du kan använda dig av enums för att avgöra olika kollisionstyper. Exempelvis att metoden jag beskrev returnerar en enum av typen högerkollision. Sen är det bara bygga på logiken: vad händer om det blir en högerkollision?

Visa signatur

8700K | MAXIMUS X HERO | 1080TI | 960 EVO | 16GB 3600 G.SKILL | PG279Q

Permalänk

Har lyckast få upp det på en hemsida nu också:

http://pwtt.se

Som sagt, det är BARA nedåtkollision som fungerar vettigt.

Ska kolla på det du sa RFRFRF och se om jag kan göra något liknande.

Tänkte bara att det måste finnas något "ultimat" sätt. Det har ju gjorts oändligt många platformsspel som löst just det här problemet...

Visa signatur

| Sony A580 | Sigma 10-20/4-5.6 | Tamron 17-50/2.8 | Sigma 70/2.8 Macro | Konica Minolta 50/1.7 | Konicha Minolta 75-300/4.5-5.6 |

Permalänk
Skrivet av Son of Qwerty:

Har lyckast få upp det på en hemsida nu också:

http://pwtt.se

Som sagt, det är BARA nedåtkollision som fungerar vettigt.

Ska kolla på det du sa RFRFRF och se om jag kan göra något liknande.

Tänkte bara att det måste finnas något "ultimat" sätt. Det har ju gjorts oändligt många platformsspel som löst just det här problemet...

Fungerar inte för mig :/ . Kör chrome

Visa signatur
Permalänk
Skrivet av Kebabhyvlarn:

Fungerar inte för mig :/ . Kör chrome

Har upptäckt att det verkar spöka rätt mycket. För mig fungerar det bra men för många andra går det inte alls. Har något att göra med vilken jdk jag kompilerat med... tror jag. Ska försöka fixa't när jag har tid!

Visa signatur

| Sony A580 | Sigma 10-20/4-5.6 | Tamron 17-50/2.8 | Sigma 70/2.8 Macro | Konica Minolta 50/1.7 | Konicha Minolta 75-300/4.5-5.6 |

Permalänk
Medlem
Skrivet av Son of Qwerty:

Har upptäckt att det verkar spöka rätt mycket. För mig fungerar det bra men för många andra går det inte alls. Har något att göra med vilken jdk jag kompilerat med... tror jag. Ska försöka fixa't när jag har tid!

Funkar med java 7 IE9

Permalänk
Medlem

Jag är tyvärr inte riktigt hemma på kollisionshantering, men det borde ju gå att hitta ganska enkelt i någon tutorial eller bok. Däremot så skulle du kunna förbättra koden genom följande:

for(int i = 0; i < Main.blocks.size(); i++) { //kod }

-->>

for(Block block : Main.blocks) { // kod }

Detta gör att du slipper alla casts. Du nämnde att du har en Arraylist där du lagrar dina "Block". Om du deklarerar den genom

List<Block> blocks = new ArrayList<Block>();

Så kommer du också slippa kasta ut objekten i din collection. Måste även påpeka att det är lite konstigt att ha block-listan som publik variabel i Main (eller du kanske har koden ovan i main?).

Sen beroende på hur många block du har kan det också vara ganska ineffektivt att loopa genom alla. Kanske kan en HashMap<String, Block> vara något? Kanske kan man inte kollidera från olika håll samtidigt? Dvs om man kolliderar från höger sida så är det omöjligt att kollidera från något annat håll? Eller kanske rent av omöjligt att kollidera med något mer block övht då?

Isåfall skulle en nästad

//loop { if(statement) { //kod break;} else if(statement2) {//kod break;} }

vara mer effektiv. Lycka till!

Visa signatur

AMD 5700X@Vatten | asus prime x370pro | Asus 2080 Strix | 2x16GB Kingston Fury Renegade RGB DDR4 3.6GHZ | Lian Li O11d EVO + 2x240 EKWB RAD + 6 Lian Li AL120 | CoolerMaster V850 | NVME 2TB Seagate Firecuda 510 + NVME 1TB WD BLACK + 3 SSD | Samsung Odyssey 49" G9| DELL 2713HM | Varmilo VA69 Clear/brown | Logitech G502 2016.

Phenom X6 1045T | Corsair TWIN2X PC6400C4DHX 2x2GB + Crucial Ballistix Sport 2x2GB | Gigabyte ma785gmt-us2h | Silverstone Temjin 08 | Corsair VX450

Permalänk
Medlem

Det är ganska bra att ha kollision och annan fysik skild från den grafiska representationen. Den enklaste kollisionen är att ge varje objekt en bound circle, räkna ut längden mellan cirklarnas mitt och kolla ifall radienen för båda objekten är mindre eller större än denna längd.Funkar bra för projektiler men är inte så bra för tex platforms spel.

I platforms spel kan man tex ha spelaren i olika states, där tex i vissa states så påverkas spelaren inte av gravitation(när man står på ett block) vilket kan underlätta. Det här problemet med att sätta position efter kollision kan man lösa genom att spara undan objektets tidigare position innan kollisionen skedde, har man en väldigt hög uppdateringshastighet i spelet kan man direkt sätta värdet till det föregående, men man kan också utgå från det gamla värdet till att räkna ut en ny position.