i put together this line-to-line physics demo. Part of the collision handling was taken from a circle colision demo, which is where my problem is.
When 2 circles collide, you only need to find 1 angle between them to handle the collision, when 2 lines collide you need 2 angles to handle collsion. I've tried to modify the code to use 2 angles but every time just makes it worse.
The documentation at the beginning was for me to remind myself exactly how to handle everything, so you can ignore it. The collision that i need help on are in the UpdateLynes() function.
Just use the arrow keys to make one of the lines move.
;find the % of each mass it will take based off the distance from each point
; a=line dist
; b=dist from point 1
; mass1=mass of first point
; mass2=mass of second point
; p1=percent for point 1
; p2=percent for point 2
; p2=b/a
; p1=1.0-p2
;find out the mass of the point of contact
; tmass=total mass for PoC
; tmass=p1*mass1+p2*mass2
;find the velocities of the PoC
; tvelx=total x velocity for the PoC
; tvely=total y velocity for the PoC
; p1xv/yv=x/y velocity of point 1
; p2xv/yv=x/y velocity of point 2
; tvelx=p1*p1xv+p2*p2xv
; tvely=p1*p1yv+p2*p2yv
;find the same for the other point
; tmass1=mass for other line's PoC
; tvelx1=x velocity for other line's PoC
; tvely1=y velocity for other line's PoC
;perfrom circle collision with the calculated values
;based on the offset of the x/y's and percent's, affect the points accordingly
; sx=amount tvelx shifted
; sy=amount tvely shifted
; p1xv=p1xv+sx*p1
; p1yv=p1yv+sy*p1
; p2xv=p2xv+sx*p2
; p2yv=p2yv+sy*p2
Graphics 800,600,16,2
Global linx#,liny#
Type point
Field x#,y#
Field xv#,yv#
Field fx#,fy#
Field mass#
End Type
Type lyne
Field a.point
Field b.point
Field dist#
Field tension#
Field cur_d#
End Type
a.point=CreatePoint(100,100,.99,.99,0,0,1)
b.point=CreatePoint(200,100,.99,.99,0,0,10)
CreateLyne(a,b,100,1)
For i=0 To 20
CreateLyne(CreatePoint(300+i*5,100,.99,.99,0,0,1),CreatePoint(300+i*5,200,.99,.99,0,0,1),100,1)
Next
SetBuffer BackBuffer()
While KeyHit(1)=0
Cls
If KeyDown(200)=1
;a\yv=a\yv-.1
b\yv=b\yv-.1
EndIf
If KeyDown(208)=1
;a\yv=a\yv+.1
b\yv=b\yv+.1
EndIf
If KeyDown(203)=1
;a\xv=a\xv-.1
b\xv=b\xv-.1
EndIf
If KeyDown(205)=1
;a\xv=a\xv+.1
b\xv=b\xv+.1
EndIf
UpdatePoints(1)
UpdateLynes()
Flip
Wend
Function CreatePoint.point(x#,y#,fx#,fy#,xv#,yv#,mass#)
p.point=New point
p\x=x
p\y=y
p\xv=xv
p\yv=yv
p\fx=fx
p\fy=fy
p\mass=mass
Return p
End Function
Function CreateLyne.lyne(a.point,b.point,dist#,tension#)
l.lyne=New lyne
l\a=a
l\b=b
l\dist=Sqr((a\x-b\x)*(a\x-b\x)+(a\y-b\y)*(a\y-b\y))
If dist>0 Then l\dist=dist
l\cur_d=l\dist
l\tension=tension
Return l
End Function
Function UpdatePoints(boundries=0)
For p.point=Each point
p\xv=p\xv*p\fx
p\yv=p\yv*p\fy
p\x=p\x+p\xv
p\y=p\y+p\yv
If boundries=1
If p\x<0
p\x=0
p\xv=-p\xv
EndIf
If p\x>800
p\x=800
p\xv=-p\xv
EndIf
If p\y<0
p\y=0
p\yv=-p\yv
EndIf
If p\y>600
p\y=600
p\yv=-p\yv
EndIf
EndIf
Next
End Function
Function UpdateLynes()
For l.lyne=Each lyne
d#=Sqr((l\a\x-l\b\x)*(l\a\x-l\b\x)+(l\a\y-l\b\y)*(l\a\y-l\b\y))
If d=0 Then d=.0001
diff#=((d-l\dist)/d)*l\tension
x#=(l\a\x-l\b\x)
y#=(l\a\y-l\b\y)
mass1#=l\a\mass/(l\a\mass+l\b\mass)
mass2#=l\b\mass/(l\a\mass+l\b\mass)
x0#=-x*mass2*l\a\fx*diff
l\a\x=l\a\x+x0
l\a\xv=l\a\xv+x0
y0#=-y*mass2*l\a\fy*diff
l\a\y=l\a\y+y0
l\a\yv=l\a\yv+y0
x1#=x*mass1*l\b\fx*diff
l\b\x=l\b\x+x1
l\b\xv=l\b\xv+x1
y1#=y*mass1*l\b\fy*diff
l\b\y=l\b\y+y1
l\b\yv=l\b\yv+y1
l\cur_d=d-diff
Line l\a\x,l\a\y,l\b\x,l\b\y
Next
For l.lyne=Each lyne
ll.lyne=l
While ll<>Last lyne
ll=After ll
;For ll.lyne=Each lyne
;check to see if the lines are colliding
If LinesCross(l\a\x,l\a\y,l\b\x,l\b\y,ll\a\x,ll\a\y,ll\b\x,ll\b\y)=1
d1#=Sqr((l\a\x-linx)*(l\a\x-linx)+(l\a\y-liny)*(l\a\y-liny))
d2#=Sqr((ll\a\x-linx)*(ll\a\x-linx)+(ll\a\y-liny)*(ll\a\y-liny))
;calculate the %'s of the masses and velocities based on where the point of contact is on each line
p2#=d1/l\cur_d
If p2>1.0 Then p2=1.0
p1#=1.0-p2
p4#=d2/ll\cur_d
If p4>1.0 Then p4=1.0
p3#=1.0-p4
tmass1#=p1*l\a\mass+p2*l\b\mass
tmass2#=p3*ll\a\mass+p4*ll\b\mass
tvelx1#=p1*l\a\xv+p2*l\b\xv
tvely1#=p1*l\a\yv+p2*l\b\yv
tvelx2#=p3*ll\a\xv+p4*ll\b\xv
tvely2#=p3*ll\a\yv+p4*ll\b\yv
angle#=ATan2((l\a\y+l\b\y)/2.0-(ll\a\y+ll\b\y)/2.0,(l\a\x+l\b\x)/2.0-(ll\a\x+ll\b\x)/2.0)+180
;find the how much is crossing over the other line
If d1>l\cur_d/2.0 Then d1=l\cur_d-d1
If d2>ll\cur_d/2.0 Then d2=ll\cur_d-d2
x#=Cos(angle)
y#=Sin(angle)
mass1#=tmass2/(tmass1+tmass2)
mass2#=tmass1/(tmass1+tmass2)
offset#=Sqr(d1+d2)
l\a\x=l\a\x-x*offset*p1*mass1
l\a\y=l\a\y-y*offset*p1*mass1
l\b\x=l\b\x-x*offset*p2*mass1
l\b\y=l\b\y-y*offset*p2*mass1
ll\a\x=ll\a\x+x*offset*p3*mass2
ll\a\y=ll\a\y+y*offset*p3*mass2
ll\b\x=ll\b\x+x*offset*p4*mass2
ll\b\y=ll\b\y+y*offset*p4*mass2
;-------------------------
q1# = min(p1, p2)
q2# = min(p3, p4)
qt# = q1 + q2
a1# = ATan2(l\b\y-l\a\y, l\b\x-l\a\x)
If l\b\x-l\a\x < 0 Then a1 = a1 + 180
a2# = ATan2(ll\b\y-ll\a\y, ll\b\x-ll\a\x)
If ll\b\x-ll\a\x < 0 Then a2 = a2 + 180
angle# = (a1*q1 + a2*q2) / qt - 90
x#=Cos(angle)
y#=Sin(angle)
;-------------------------
v1#=tvelx1*x+tvely1*y
v2#=tvelx2*x+tvely2*y
p#=(2.0*(v1-v2))/(tmass1+tmass2)
tvelx1=-p*tmass2*x
tvely1=-p*tmass2*y
tvelx2=p*tmass1*x
tvely2=p*tmass1*y
l\a\xv=l\a\xv+tvelx1*p1
l\a\yv=l\a\yv+tvely1*p1
l\b\xv=l\b\xv+tvelx1*p2
l\b\yv=l\b\yv+tvely1*p2
ll\a\xv=ll\a\xv+tvelx2*p3
ll\a\yv=ll\a\yv+tvely2*p3
ll\b\xv=ll\b\xv+tvelx2*p4
ll\b\yv=ll\b\yv+tvely2*p4
EndIf
;Next
Wend
Next
End Function
Function min#(x#,y#)
If x<y Then Return x
Return y
End Function
Function LinesCross(x0#,y0#,x1#,y1#,x2#,y2#,x3#,y3#)
n#=(y0-y2)*(x3-x2)-(x0-x2)*(y3-y2)
d#=(x1-x0)*(y3-y2)-(y1-y0)*(x3-x2)
If (Abs(d)<0.0001) Then Return 0
Sn#=(y0-y2)*(x1-x0)-(x0-x2)*(y1-y0)
AB#=n/d
If AB>0.0 And AB<1.0
CD#=Sn/d
If CD>0.0 And CD<1.0
linx=x0+AB*(x1-x0)
liny=y0+AB*(y1-y0)
Return 1
EndIf
EndIf
Return 0
End Function
(btw, this is 2d)
|