Hey guys, this is me first post here! I've been working on this collision detection and response program for the last day or so using line to point tangents, but sometimes the character gets stuck (very rarely, though). Can any of you suggest anything to fix this? Here's the code:
sync on : sync rate 0 : hide mouse
rem Read a level
restore secondlevel
read amline
rem Arrays for field, player, collision normal, and relative velocity
dim field(amline,2)
dim p#(1,3)
dim normcoll#(2)
dim relvel#(2)
rem Player start position
p#(1,1)=320 : p#(1,2)=80 : p#(1,3)=2
rem World Variables
grav#=0.01
fric#=1
vx#=0
vy#=0
e#=1
rem Load level into field array
for x=1 to amline
cls
read field(x,1)
print "Loading..."
next x
for x=1 to amline
cls
read field(x,2)
print "Loading..."
next x
rem Main Loop
do
cls
rem Milliseconds per frame counter
oldtime=newtime
newtime=timer()
mpf=newtime-oldtime
ink rgb(255,128,64),0
print "mpf:>",mpf
rem Movement
if leftkey()=1 and vx#>-5 then vx#=vx#-0.1
if rightkey()=1 and vx#<5 then vx#=vx#+0.1
if upkey()=1 and vy#>-5 then vy#=vy#-0.1
if downkey()=1 and vy#<5 then vy#=vy#+0.1
if spacekey()=1
p#(1,1)=320 : p#(1,2)=80
vx#=0 : vy#=0
endif
rem Apply dampening
vx#=vx#*fric#
vy#=vy#*fric#
rem Reset collision counter
coll=0
rem Accuracy Loop
for b=0 to 5
rem Position up to 2 frames ago
cx#=ox#
cy#=oy#
ox#=p#(1,1)
oy#=p#(1,2)
rem New player position
p#(1,1)=p#(1,1)+(vx#/5)
p#(1,2)=p#(1,2)+(vy#/5)
rem Collision check loop
for x=1 to amline
rem For lines 1 to amline-1
if x<amline
rem Get tangent vector
p1#=(((p#(1,1)-field(x,1)))*((field(x+1,1)-field(x,1))))+(((p#(1,2)-field(x,2)))*((field(x+1,2)-field(x,2))))
dist#=sqrt(((field(x+1,1)-field(x,1))^2)+((field(x+1,2)-field(x,2))^2))^2
if dist#>0 then u#=p1#/dist#
if u#>0 and u#<1
tx#=field(x,1)+(u#*(field(x+1,1)-field(x,1)))
ty#=field(x,2)+(u#*(field(x+1,2)-field(x,2)))
endif
rem Get distance from player to point on line using the tangent vector
lx#=p#(1,1)-tx#
ly#=p#(1,2)-ty#
rem Distance magnitude
lmag#=sqrt(lx#^2+ly#^2)
rem Magnitudes from endpoints of the line to the player
dp1#=sqrt((field(x,1)-p#(1,1))^2+(field(x,2)-p#(1,2))^2)
dp2#=sqrt((field(x+1,1)-p#(1,1))^2+(field(x+1,2)-p#(1,2))^2)
rem Is there a collision?
if lmag#<p#(1,3) or dp1#<p#(1,3) or dp2#<p#(1,3)
rem Advance collision counter
coll=coll+1
rem Set player back 2 frames ago
p#(1,1)=cx#
p#(1,2)=cy#
rem Find collision normal
normcoll#(1)=lx#
normcoll#(2)=ly#
rem Normalize the normal
normlength#=sqrt(normcoll#(1)^2+normcoll#(2)^2)
normcoll#(1)=normcoll#(1)/normlength#
normcoll#(2)=normcoll#(2)/normlength#
rem Find relative velocities (world never moves)
relvel#(1)=(vx#)*-1*(1+e#)
relvel#(2)=(vy#)*-1*(1+e#)
rem Inverse Mass Sum
ims#=(1/1)+(1/99999)
rem Calculate the impulse (numerator and denominator
rem separate to insure no division by 0)
impa#=(relvel#(1)*normcoll#(1))+(relvel#(2)*normcoll#(2))
impb#=(normcoll#(1)*(normcoll#(1)*ims#))+(normcoll#(2)*(normcoll#(2)*ims#))
if impb#=0 then impb#=0.0000000000000000000000000000000000000009
imp#=impa#/impb#
rem Adjust velocity accordingly
vx#=vx#+(normcoll#(1)*(imp#/ims#))
vy#=vy#+(normcoll#(2)*(imp#/ims#))
endif
else
rem Last line test (point amline-1 to point 1)
rem Utilizes same method for collision detection and handling as above
p1#=(((p#(1,1)-field(x,1)))*((field(1,1)-field(x,1))))+(((p#(1,2)-field(x,2)))*((field(1,2)-field(x,2))))
dist#=sqrt(((field(1,1)-field(x,1))^2)+((field(1,2)-field(x,2))^2))^2
if dist#>0 then u#=p1#/dist#
if u#>0 and u#<1
tx#=field(x,1)+(u#*(field(1,1)-field(x,1)))
ty#=field(x,2)+(u#*(field(1,2)-field(x,2)))
endif
lx#=p#(1,1)-tx#
ly#=p#(1,2)-ty#
lmag#=sqrt(lx#^2+ly#^2)
dp1#=sqrt((field(x,1)-p#(1,1))^2+(field(x,2)-p#(1,2))^2)
dp2#=sqrt((field(1,1)-p#(1,1))^2+(field(1,2)-p#(1,2))^2)
if lmag#<p#(1,3) or dp1#<p#(1,3) or dp2#<p#(1,3)
coll=coll+1
p#(1,1)=cx#
p#(1,2)=cy#
normcoll#(1)=lx#
normcoll#(2)=ly#
normlength#=sqrt(normcoll#(1)^2+normcoll#(2)^2)
normcoll#(1)=normcoll#(1)/normlength#
normcoll#(2)=normcoll#(2)/normlength#
relvel#(1)=(vx#)*-1*(1+e#)
relvel#(2)=(vy#)*-1*(1+e#)
ims#=(1/1)+(1/99999)
impa#=(relvel#(1)*normcoll#(1))+(relvel#(2)*normcoll#(2))
impb#=(normcoll#(1)*(normcoll#(1)*ims#))+(normcoll#(2)*(normcoll#(2)*ims#))
if impb#=0 then impb#=0.0000000000000000000000000000000000000009
imp#=impa#/impb#
vx#=vx#+(normcoll#(1)*(imp#/ims#))
vy#=vy#+(normcoll#(2)*(imp#/ims#))
endif
endif
next x
rem To insure no sticking and smoother movement
if coll=0 then vy#=vy#+grav#
next b
rem Render the scene
ink rgb(250,0,0),0
circle p#(1,1),p#(1,2),p#(1,3)
ink rgb(0,0,250),0
for x=1 to amline
if x<amline
line field(x,1),field(x,2),field(x+1,1),field(x+1,2)
else
line field(x,1),field(x,2),field(1,1),field(1,2)
endif
next x
sync
loop
rem Level Data
firstlevel:
data 5
data 40,600,600,200,40
data 40,40,440,440,350
secondlevel:
data 49
data 010,088,112,060,075,131,230,194,202,271
data 280,230,223,259,353,399,381,337,346,416
data 439,399,534,599,538,564,600,618,555,573
data 621,625,539,543,620,596,448,418,364,319
data 240,229,128,062,045,017,057,089,009
data 212,350,327,230,042,024,039,087,148,155
data 132,129,099,044,036,075,118,129,150,136
data 079,038,029,068,219,243,106,192,315,362
data 233,313,416,449,363,460,455,465,439,463
data 452,398,446,411,442,326,396,384,279
can anybody help out?