collision line rect; kollision linie rechteck

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Bobbleboy

Betreff: collision line rect; kollision linie rechteck

BeitragMi, Jul 28, 2010 3:15
Antworten mit Zitat
Benutzer-Profile anzeigen
was ist die effizienteste methode eine kollision zu prüfen zwischen einer linie und einem rechteck /quadrat?
bsp bei einer tile map.

bisher verwende ich folgende funktion:

hierzu benutze ich eine tilemap "map(x,y)" mit einer "1" für eine "mauer"

Code: [AUSKLAPPEN]
Function rectline(sx,sy,zx,zy)
   ;sx/sy = start x/y
   ;zx/zy = ziel x/y
   ;tx/ty = temp x/y
   ;w = winkel
   kollision = false
   w=ATan2((zy-sy),(zx-sx))
   If w =<0
      w=w+360
   End If
   i=0
   Repeat
      i=i+10
      tx = sx+Cos(w)*i
      ty = sy+Sin(w)*i
      If map(Int(tx/32),Int(ty/32))=1
         kollision=true
      End If
   Until(kollision=true Or i>=Sqr((sx-zx)^2+(sy-zy)^2))
   Return sicht
End Function


aber ich denke das es eventuell bessere lösungen gibt.
vorallem im bereich der performance, da ich bei einer entfernung von 500 pixel 50 schleifendurchgänge brauche trotz einer ungenauigkeit von 10 pixeln, was dazuführt, das die linie ecken schneidet.

ich hoffe ihr habt noch einen trick auf lager Razz

Hubsi

BeitragMi, Jul 28, 2010 9:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn es Dir in erster Linie um eine Tilemapkollision geht verwende ich diese Technik seit Jahren mit Erfolg:
BlitzBasic: [AUSKLAPPEN]
	u=map((p\x+16)/32,(p\y-2)/32,0)  ; oben / up
r=map((p\x+32)/32,(p\y+16)/32,0) ; rechts / right
d=map((p\x+16)/32,(p\y+32)/32,0) ; unten / down
l=map(p\x/32,(p\y+16)/32,0) ; links / left
m=map((p\x+16)/32,(p\y+16)/32,1) ; mitte / middle


Das ist jetzt einfach aus einem Projekt rauskopiert, der Type beinhaltet die x, bzw. y-Koordinaten des Spielers. Die Tiles sind 32 x 32 Pixel, sowie auch der Spieler. Für andere Größen ist das anzupassen.

Edit: Was vielleicht nicht auf den ersten Blick klar ist: Zurückgegeben wird die Nummer des Tiles mit welchem in entsprechender Richtung kollidiert wird und das Array ist dreidimensional, sprich ich arbeite mit 2 Layern. In Deinem Fall muß das ",0" bzw. ",1" einfach weg.
Den ganzen Doag im Bett umanandflagga und iaz daherkema und meine Hendl`n fressn...
 

Bobbleboy

BeitragMi, Jul 28, 2010 14:14
Antworten mit Zitat
Benutzer-Profile anzeigen
ja das ist ein schöner code um tiles direkt neben dem player zu prüfen, aber er hilft mir leider nicht weiter.
denn ich will wissen, ob beispielsweise eine gerade linie vom player zum mauszeiger existiert, der weiter als nur ein tile entfernt sein kann.

BladeRunner

Moderator

BeitragMi, Jul 28, 2010 14:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier könnte dir der Linienalgorithmus nach Bresenham weiterhelfen. Ermittle Start und Enttile deiner Sichtlinie anhand ihrer Koordinaten und lasse den Linienalgo alle dazwischenliegenden Tiles ablaufen, bei der ersten '1' brichst du ab.
Sollte die flotteste Lösung sein.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

Bobbleboy

BeitragMi, Jul 28, 2010 15:01
Antworten mit Zitat
Benutzer-Profile anzeigen
okay ich check ihn gleich mal sofort
 

Bobbleboy

BeitragFr, Jul 30, 2010 21:09
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzBasic: [AUSKLAPPEN]
Function rectline(sx#,sy#,zx#,zy#)

avid = 1 ;avids code als standart (zum testen von zeugs)

If KeyDown(2) ;während man 1 drückt, wechselt es
avid= 0
End If


If avid = 1 ;der code von Avid

;sx/sy startx start y
;zx/zy ziel x/y

m# = (zy-sy)/(zx-sx)
n# = sy-m*sx

;fkt1: y= mx+n
;fkt2: x= (y-n)/m

;zu Pruefenden Bereich festlegen

bx_min# = 0 ;bereich
by_min# = 0
bx_max# = 0
by_max# = 0

If sx <= zx
bx_min = sx
bx_max = zx-32
Else
bx_min = zx
bx_max = sx-32
End If
If sy <= zy
by_min = sy
by_max = zy-32
Else
by_min = zy
by_max = sy-32
End If
ink_x% = 0
ink_y% = 0

Repeat
hit_x% = Floor(bx_min/32+1+ink_x)*32
hit_y% = m*(hit_x)+n
If hit_x > bx_min
If hit_x <= bx_max+32
If hit_x/32-1>=0 And hit_x/32<=100 And Floor(hit_y/32)>=0 And Floor(hit_y/32)<=100
If map(hit_x/32-1,Floor(hit_y/32)) = 1
Return False
End If
If map(hit_x/32,Floor(hit_y/32)) = 1
Return False
End If
End If
End If
End If

ink_x = ink_x + 1
Until(ink_x*32 >= bx_max-bx_min)

Repeat
hit_y% = Floor(by_min/32+1+ink_y)*32
hit_x% = (hit_y-n)/m
If hit_y > by_min
If hit_y <= by_max+32
If Floor(hit_x/32)>=0 And Floor(hit_x/32)<=100 And hit_y/32-1>=0 And hit_y/32<=100
If map(Floor(hit_x/32),hit_y/32-1) = 1
Return False
End If
If map(Floor(hit_x/32),hit_y/32) = 1
Return False
End If
End If
End If
End If
ink_y = ink_y + 1
Until(ink_y*32 >= by_max-by_min)
Return True

Else ;der code von bobbleboy


;sx/sy startx start y
;zx/zy ziel x/y
;tx/ty temp x/y
;falls man noch original werte braucht:
sxo = sx
syo = sy
zxo = zx
zyo = zy
;start ziel koordinaten in tiles umrechnen:
sx = Floor(sx/32)
sy = Floor(sy/32)
zx = Floor(zx/32)
zy = Floor(zy/32)
sicht = True
j=0

m# = 0

dx# = zx-sx
dy# = zy-sy

tx = sx
ty = sy
If dx =0
dx = 0.1
End If
m# = (dy / dx)
g# = m#

temp# = 0

yanders = 1
xanders = 1

gespiegelt = 0


If dy<0
yanders = yanders*-1
;m=m*-1
End If

If dx<0
xanders = xanders*-1
;m = m*-1
End If

If m < 0
m=m*-1
If m>1
xanders = xanders * -1
yanders = yanders * -1
End If
End If

If m>1
m=1./m
gespiegelt = 1

End If



Repeat
temp# = temp# + m#

If temp >= 1
temp = temp -1
If gespiegelt = 1
tx = tx + yanders
Else
ty = ty + yanders
End If
End If

;Rect tx*32,ty*32,32,32,0
If map((tx),(ty))=1
sicht=False
End If

If temp >= 0
If gespiegelt = 1
ty = ty + xanders
Else
tx = tx + xanders
End If
End If

If map((tx),(ty))=1
sicht=False
End If
;Rect tx*32,ty*32,32,32,0
j = j+1
Until( sicht=False Or j^2>Floor((sx-zx)^2+(sy-zy)^2))
; Text sxo-5,syo+15," dx: " + dx + " dy: " + dy + " steigung: " + g#
; Color 255,255,0
; Text zxo-5,zyo+15,"schleifen: "+i + " entfernung: " + Floor(Sqr((sx-zx)^2+(sy-zy)^2))
; If sicht=False
; Color 255,0,0
; End If
; Rect tx*32,ty*32,32,32,0
; Color 0,0,225
; Rect zx*32,zy*32,32,32,0
;Color 255,255,255
; Line (sx*32)+16,(sy*32)+16,zxo,zyo
;Line sx*32+16,sy*32+16,tx*32+16,ty*32+16
Return sicht
End If





End Function


so jetzt benutze ich das hier, verdammt schnelles ding.
der erste code von einem freund von mir, benutzt lineae algebra, der zweite ist besenham algobresenham algo ist noch ein wenig verbuggt, aber er funktioniert ganz gut.
wer spaß daran hat, kann es sich durchlesen

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group