Tilemap-Kollision, die X-te

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Pousup

Betreff: Tilemap-Kollision, die X-te

BeitragSo, Jan 03, 2010 15:26
Antworten mit Zitat
Benutzer-Profile anzeigen
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:

user posted image

Wird die Map allerdings komplexer, so wie diese, bleibt der Spieler unweigerlich hängen:

user posted image

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))
ty2 = Ceil(player_1_y/Float(64))

tx1 = Floor(player_1_x/Float(64))
tx2 = Ceil(player_1_x/Float(64))

If KeyDown(Oben) Then
If map(tx1, (player_1_y - player_1_speed)/64) = 0 And map(tx2, (player_1_y - player_1_speed)/64) = 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

;UNTEN
If KeyDown(Unten) Then
If map(tx1, (player_1_y + player_1_speed)/64 + 1) = 0 And map(tx2, (player_1_y + player_1_speed)/64 + 1) = 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

;links
If KeyDown(Links) Then
If map((player_1_x - player_1_speed)/64, ty1) = 0 And map((player_1_x - player_1_speed)/64, 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

;rechts
If KeyDown(Rechts) Then
If map((player_1_x + player_1_speed)/64 + 1, ty1) = 0 And map((player_1_x + player_1_speed)/64 + 1, 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

Color 0,0,255:Rect player_1_x,player_1_y,64,64,1


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

BeitragSo, Jan 03, 2010 15:34
Antworten mit Zitat
Benutzer-Profile anzeigen
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/

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSo, Jan 03, 2010 15:36
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Wink

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

BeitragSo, Jan 03, 2010 15:45
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Smile

Edit2: Funktioniert leider immer noch nicht. Seltsamerweise wird das Quadrat immernoch wie ein 64*64 Pixel großes behandelt.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSo, Jan 03, 2010 16:33
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Jan 03, 2010 16:46
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Jan 03, 2010 17:08
Antworten mit Zitat
Benutzer-Profile anzeigen
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

SpionAtom

Betreff: Alternative

BeitragSo, Jan 03, 2010 17:37
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Jan 03, 2010 18:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Super, danke dir SpionAtom deins funktioniert einwandfrei.

SpionAtom

BeitragSo, Jan 03, 2010 19:05
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Jan 03, 2010 19:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Natürlich, das vergegenwärtige ich mir immer beim umschreiben, damit es auch hundertprozentig auf meine Anwendung passt Wink

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group