Tilemap-Kollision, die X-te
Übersicht

PousupBetreff: Tilemap-Kollision, die X-te |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hallo und erstmal einen nachträglichen guten Rutsch ins neue Jahr.
Ich habe mich bei einer Tilemap-Kollisions-Erklärung von Dottakopf aus diesem Thread bedient, und ihn für meine Tilemap umgeschrieben, auf der die Tiles eine Größe von 64*64 Pixel haben. Das funktioniert auf einer Map die so aufgebaut ist wunderbar: ![]() Wird die Map allerdings komplexer, so wie diese, bleibt der Spieler unweigerlich hängen: ![]() Verständlich, da der Spieler bei einer Geschwindigkeit von 5 Pixeln pro Durchlauf so gut wie nie genau auf einem Teil stehen bleibt. Und ein Pixel meines Spielers auf einem anderen Tile reicht ja schon, damit die Kollision als Kollision erkannt wird, was auch gut ist. Jetzt ging ich bei meinem Test von einer Spielergröße von 64*64 Pixeln aus, was aber aufgrund der geschilderten Probleme unsinnig ist. Ich entschied mich also dazu, meinen Spieler nur 32*32 Pixel groß zu machen, was mich vor das Problem führte, die Kollisionsabfrage umzuschreiben - und genau da scheitere ich momentan. BlitzBasic: [AUSKLAPPEN] ty1 = Floor(player_1_y/Float(64)) Wie kann ich das so umschreiben, dass mein Spieler auch als 32*32 großes Quadrat behandelt wird? Danke für die Hilfe, Pousup |
||
![]() |
Goodjee |
![]() Antworten mit Zitat ![]() |
---|---|---|
bei der abfrage für unten und für rechts findest du immer ein "+1" bei der abfrage, ob das tile passierbar ist oder nicht.
das dient dazu um bei 64x64 zu schauen. ob am rechten bzw unteren rand des players kollisionen auftreten. für 32x32 funktioniert das nicht mehr, stattdessen sollte für oben Code: [AUSKLAPPEN] If map(tx1, (player_1_y + 32+player_1_speed)/64) = 0 And map(tx2, (player_1_y + player_1_speed+32)/64) = 0 Then
funktionieren. für rechts analog dazu verfahren |
||
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/ |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du solltest beim programmieren eher Abstand zum gewohnten Dezimalsystem nehmen, und sich lieber an der Zweier-Potenz einer Zahl richten. Wenn deine Spielfigur mit einer Geschwindigkeit von 5 Pixel nicht jedes Tile genau auf Position trifft, dann nimm einfach mal 4 Pixel. Diese passt dann auf 8x8, 16x16, 32x32, 64x64... Tiles genau ![]() Oder man programmiert gleich so, dass es im grunde egal ist, wie genau die Spielfigur auf Position gelangt. Wichtig wäre dann die Bewegungspriorität zur Ausweichrichtung gegenüber seine bisherigen Geschwindigkeit bei Tastendruck. Das allerdings ist schon ein deutlich schwererer Brocken zum programmieren. Zumindest dann, wenn die Spielfigur leichte Beschleunigung beim losrennen hat und trotzdem genau in eine Seitenstraße abbiegen können soll. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Pousup |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Goodjee hat Folgendes geschrieben: bei der abfrage für unten und für rechts findest du immer ein "+1" bei der abfrage, ob das tile passierbar ist oder nicht.
das dient dazu um bei 64x64 zu schauen. ob am rechten bzw unteren rand des players kollisionen auftreten. für 32x32 funktioniert das nicht mehr, stattdessen sollte für oben Code: [AUSKLAPPEN] If map(tx1, (player_1_y + 32+player_1_speed)/64) = 0 And map(tx2, (player_1_y + player_1_speed+32)/64) = 0 Then
funktionieren. für rechts analog dazu verfahren Müsste das nicht für unten sein? Wenn ich die Tiles oben überprüfen will, muss ich doch die Geschwindigkeit abziehen, oder nicht? Und danke für die wirklich schnelle Hilfe! Edit: Klar, du hast ja auch "bei der abfrage für unten" geschrieben, sorry, falsch gelesen ![]() Edit2: Funktioniert leider immer noch nicht. Seltsamerweise wird das Quadrat immernoch wie ein 64*64 Pixel großes behandelt. |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Probier mal ein ''.0'' hinter deiner Division zu machen:
Code: [AUSKLAPPEN] If map(tx1, (player_1_y + 32+player_1_speed)/64.0) = 0 And map(tx2, (player_1_y + player_1_speed+32)/64.0) = 0 Then
|
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Goodjee |
![]() Antworten mit Zitat ![]() |
---|---|---|
ach, deine tx1 und tx2 usw müssen auch noch anders bestimmt werden
Code: [AUSKLAPPEN] ty1 = Floor(player_1_y/Float(64))
ty2 = Floorl((player_1_y+32)/Float(64)) tx1 = Floor(player_1_x/Float(64)) tx2 = Floor((player_1_x+32)/Float(64)) |
||
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/ |
Pousup |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Klappt aufjedenfall schon mal viel viel besser als vorher, vielen Dank. Allerdings gibt es immernoch ein kleines Problem - wenn ich nämlich mittig auf ein Tile "fahre", dass zwischen zwei unpassierbaren Tiles liegt und dann nach rechts will, kann der Spieler die Mauer durchfahren - nach links klappt dies nicht. Wenn ich aber ganz am linken Rand eines Tiles stehe und dann nach rechts drücken will, passiert nichts, obwohl der Spieler eigentlich noch 32 Pixel freien Platz hätte, den er begehen könnte.
Achso, nochwas. Ich habe bei den Kollisionsabfragen das +32 nicht nur bei Unten und Rechts, sondern auch noch Oben und Links eingefügt, da man sonst nach Links und Oben aus dem Bild fahren konnte, da die Kollsionsabfrage dort nicht funktioniert hatte. Keine Ahnung ob das irgendwas mit dem Problem von oben zu tun hat, dürfte aber eigentlich nicht, weil es ja garnichts mit der If-Abfrage für Keydown(Rechts) zu tun hat. Code: [AUSKLAPPEN] ty1 = Floor(player_1_y/Float(64))
ty2 = Floor((player_1_y + 32)/Float(64)) tx1 = Floor(player_1_x/Float(64)) tx2 = Floor((player_1_x + 32)/Float(64)) If KeyDown(Oben) Then If map(tx1, (player_1_y - 32 - player_1_speed)/64.0) = 0 And map(tx2, (player_1_y - 32 - player_1_speed)/64.0) = 0 Then player_1_y = player_1_y - player_1_speed Else player_1_y = player_1_y + player_1_speed player_1_y = (player_1_y/64)*64 End If End If If KeyDown(Unten) Then If map(tx1, (player_1_y + player_1_speed + 32)/64.0) = 0 And map(tx2, (player_1_y + player_1_speed + 32)/64.0) = 0 Then player_1_y = player_1_y + player_1_speed Else player_1_y = player_1_y - player_1_speed player_1_y = (player_1_y/64 + 1)*64 End If End If If KeyDown(Links) Then If map((player_1_x - 32 - player_1_speed)/64.0, ty1) = 0 And map((player_1_x - 32 - player_1_speed)/64.0, ty2) = 0 Then player_1_x = player_1_x - player_1_speed Else player_1_x = player_1_x + player_1_speed player_1_x = (player_1_x/64)*64 End If End If If KeyDown(Rechts) Then If map((player_1_x + player_1_speed + 32)/64.0, ty1) = 0 And map((player_1_x + player_1_speed + 32)/64.0, ty2) = 0 player_1_x = player_1_x + player_1_speed Else player_1_x = player_1_x - player_1_speed player_1_x = (player_1_x/64 + 1)*64 End If End If If KeyDown(59) Then player_1_x = 64 : player_1_y = 64 |
||
![]() |
SpionAtomBetreff: Alternative |
![]() Antworten mit Zitat ![]() |
---|---|---|
Vielleicht ist diese Lösung etwas übersichtlicher?
Code: [AUSKLAPPEN] Graphics 600, 600, 0, 2
SetBuffer BackBuffer() Data 10,10 Data 1,1 Data 1,1,1,1,1,1,1,1,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,1,0,1,0,1,0,1,0,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,1,0,1,0,1,0,1,0,1 Data 1,1,1,1,1,1,1,1,1,1 ;Map laden Global mapw, maph, mapg, sx, sy, sg Read mapw, maph Read sx, sy Dim map(mapw, maph) For i = 0 To mapw * maph - 1 Read map(i Mod mapw, i / mapw) Next mapg = 60 ;Map-Tile-Größe sg = 25 ;Spieler-Größe speed = 6 ;Spieler-Geschwindigkeit ;Spielerposition sx = (sx + 0.5) * mapg sy = (sy + 0.5) * mapg Repeat If KeyDown(200) Then If playerOnWall(sx, sy - speed) Then ;Bis zur Mauer gehen sy = sy / mapg * mapg + sg / 2 Else ;Einen ganzen Schritt gehen sy = sy - speed End If End If If KeyDown(208) Then If playerOnWall(sx, sy + speed) Then ;Bis zur Mauer gehen sy = (sy / mapg + 1) * mapg - 1 - sg / 2 Else ;Einen ganzen Schritt gehen sy = sy + speed End If End If If KeyDown(203) Then If playerOnWall(sx - speed, sy) Then ;Bis zur Mauer gehen sx = (sx / mapg ) * mapg + sg / 2 Else ;Einen ganzen Schritt gehen sx = sx - speed End If End If If KeyDown(205) Then If playerOnWall(sx + speed, sy) Then ;Bis zur Mauer gehen sx = (sx / mapg + 1) * mapg - 1 - sg / 2 Else ;Einen ganzen Schritt gehen sx = sx + speed End If End If Cls drawMap Color 255, 255, 0 Rect sx - sg / 2, sy - sg / 2, sg, sg Text 0, 0, playerOnWall(sx, sy) Flip() Until KeyDown(1) End ;Prüfe 4 Eckpunkte des Spielers auf Kollision mit Map() Function playerOnWall(x, y) r = sg / 2 If map((x - r) / mapg, (y - r) / mapg) = 1 Then Return True If map((x + r) / mapg, (y - r) / mapg) = 1 Then Return True If map((x - r) / mapg, (y + r) / mapg) = 1 Then Return True If map((x + r) / mapg, (y + r) / mapg) = 1 Then Return True Return False End Function Function drawMap() Color 255, 255, 255 For i = 0 To mapw - 1 For j = 0 To maph - 1 If map(i, j) Then Rect i * mapg, j * mapg, mapg, mapg, 0 Next Next End Function |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
Pousup |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Super, danke dir SpionAtom deins funktioniert einwandfrei. | ||
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Freut mich. Wichtig ist aber, dass du die Lösung nicht einfach nur hinnimmst, sondern verstehst, was da vor sich geht, und warum es funktioniert. | ||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
Pousup |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Natürlich, das vergegenwärtige ich mir immer beim umschreiben, damit es auch hundertprozentig auf meine Anwendung passt ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group