It's a little buggy. Occationally you may get stuck if hitting a corner directly. Bounce around inside a shape, while remaining outside of the inner shape.
sync on
sync rate 60
backdrop on
color backdrop 0
temp = 2
wallN = 1
are = 3
null = make vector2(wallN)
null = make vector2(temp)
null = make vector2(are)
impact_strength# = 1
braking# = 1.1
type player
ang as float
acc as float
topspeed as float
x as float
z as float
fx as float
fz as float
px as float
pz as float
oldpx as float
oldpz as float
endtype
player1 as player
player1.ang = 0
player1.acc = 0.05
player1.topspeed = 5
dim points(6,2)
dim points2(6,2)
restore shape
for t = 1 to 6
read z
points(t,1) = z
read z
points(t,2) = z
next t
restore shape1
for t = 1 to 6
read z
points2(t,1) = z
read z
points2(t,2) = z
next t
player1.px = 300
player1.pz = 100
DO
gosub controls
for t = 1 to 6
t2 = t+1
if t = 6 then t2 = 1
line points(t,1),points(t,2),points(t2,1),points(t2,2)
length# = sqrt((points(t2,1)-points(t,1))^2 + (points(t2,2)-points(t,2))^2)
r# = ((points(t,2)-player1.pz)*(points(t,2)-points(t2,2)) - (points(t,1)-player1.px)*(points(t2,1)-points(t,1))) / (length#^2)
ix# = points(t,1) + r#*(points(t2,1)-points(t,1))
iy# = points(t,2) + r#*(points(t2,2)-points(t,2))
dist# = (ix#-player1.px)^2 + (iy#-player1.pz)^2
if r# >= 0.0 AND r# <= 1.0 AND dist# < 6^2
if point_line(player1.px,player1.pz,points(t,1),points(t,2),points(t2,1),points(t2,2)) <= 0
set vector2 wallN,(points(t2,2)-points(t,2)),(points(t2,1)-points(t,1))*-1
normalize vector2 wallN, wallN
wall_hit = 1
endif
endif
next t
for t = 1 to 6
t2 = t+1
if t = 6 then t2 = 1
line points2(t,1),points2(t,2),points2(t2,1),points2(t2,2)
length# = sqrt((points2(t2,1)-points2(t,1))^2 + (points2(t2,2)-points2(t,2))^2)
r# = ((points2(t,2)-player1.pz)*(points2(t,2)-points2(t2,2)) - (points2(t,1)-player1.px)*(points2(t2,1)-points2(t,1))) / (length#^2)
ix# = points2(t,1) + r#*(points2(t2,1)-points2(t,1))
iy# = points2(t,2) + r#*(points2(t2,2)-points2(t,2))
dist# = (ix#-player1.px)^2 + (iy#-player1.pz)^2
if r# >= 0.0 AND r# <= 1.0 AND dist# < 6^2
if point_line(player1.px,player1.pz,points2(t,1),points2(t,2),points2(t2,1),points2(t2,2)) >= 0
set vector2 wallN,(points2(t2,2)-points2(t,2)),(points2(t2,1)-points2(t,1))*-1
normalize vector2 wallN, wallN
wall_hit = 1
endif
endif
next t
gosub _apply_forces
gosub _position_player
set cursor 0,0
print player1.ang
print mousex()
print mousey()
print dist#
sync
loop
controls:
rem apply player's force to current movement force
if upkey()=1
player1.x = player1.x + player1.fx
player1.z = player1.z + player1.fz
endif
if downkey()=1
player1.x = player1.x / braking#
player1.z = player1.z / braking#
endif
if leftkey()=1
player1.ang = wrapvalue(player1.ang - 2)
endif
if rightkey()=1
player1.ang = wrapvalue(player1.ang + 2)
endif
RETURN
REM If player hits wall, calculate new angle of movement, and
REM new speed amount
_apply_forces:
rem player direction
dx# = cos(player1.ang)
dz# = sin(player1.ang)
rem player's force
player1.fx = dx# * player1.acc
player1.fz = dz# * player1.acc
rem player's speed
player_speed = sqrt(player1.x*player1.x + player1.z*player1.z)
rem if a wall has been hit:
if wall_hit = 1
player1.px = player1.oldpx
player1.pz = player1.oldpz
wall_hit = 0
rem wall's normal
vx# = x vector2(wallN)
vz# = y vector2(wallN)
rem reflect player's movement
set vector2 temp, player1.x,player1.z
player1.x = (player1.x - (2*vx#*dot product vector2(wallN,temp)))*impact_strength#
player1.z = (player1.z - (2*vz#*dot product vector2(wallN,temp)))*impact_strength#
endif
rem restrict player from moving backwards
`if player_speed < 0 then player1.x=0:player1.z=0
rem restrict player from moving too fast
if player_speed > player1.topspeed
player1.x = (player1.x * player1.topspeed) / player_speed
player1.z = (player1.z * player1.topspeed) / player_speed
endif
RETURN
REM update player's position
_position_player:
player1.oldpx = player1.px
player1.oldpz = player1.pz
player1.px = player1.px + player1.x
player1.pz = player1.pz + player1.z
ink rgb(255,0,0),0
circle player1.px,player1.pz,5
cx# = player1.px + cos(player1.ang)*10
cz# = player1.pz + sin(player1.ang)*10
line player1.px,player1.pz,cx#,cz#
ink rgb(255,255,255),0
RETURN
REM if point(px,py) is right or left of line segment (x1,y1),(x2,y2)
REM return negative if left, positive if right, 0 if on
function point_line(px#,py#, x1#,y1#,x2#,y2#)
dp# = (x2# - x1#) * (py# - y1#) - (px# - x1#) * (y2# - y1#)
endfunction dp#
shape:
data 150,100
data 250,100
data 300,150
data 250,200
data 150,200
data 100,150
`data 50,50
`data 250,50
`data 250,150
`data 200,150
`data 200,350
`data 50,350
shape1:
data 50,50
data 350,50
data 400,150
data 350,250
data 50,250
data 0,150
shape2:
data 300,100
data 350,150
data 350,220
data 300,340
data 200,220
"eureka" - Archimedes