I'm working based on this:
http://pogopixels.com/blog/2d-polygon-collision-detection/
I've gone of the code 3 times and can't find anything wrong, yet whenever the two shapes get close to intersecting, the shape controlled by the user jumps way off course. For some reason, the value of 'minIntervalDistance#' is way larger than it should be.
The website linked above provides C# code, which I compiled and the example works fine. If anyone has time to comb through this I'd appreciate a push in the right direction.
randomize timer()
n# = (2.0-2.0^-23)*2.0^127
#CONSTANT POSITIVE_INFINITY = n#
Type Vector2D
x as float
y as float
EndType
Type PolygonCollisionResult
willIntersect as boolean
intersect as boolean
minimumTranslationVector as Vector2D
EndType
dim polygonA(6) as Vector2D
dim polygonB(7) as Vector2D
local result as PolygonCollisionResult
local v1 : v1 = make vector2(1)
local axis : axis = make vector2(2)
local translationAxis : translationAxis = make vector2(3)
local velocity : velocity = make vector2(4)
local d : d = make vector2(5)
makeRandomPolygonA(100)
makeRandomPolygonB(100)
p1x = 400
p1y = 300
p2x = 200
p2y = 200
sync on
sync rate 60
do
cls
rem controls
vx = 0
vy = 0
if upkey() and flag=0 then vy = -3
if downkey() and flag=0 then vy = 3
if rightkey() and flag=0 then vx = 3
if leftkey() and flag=0 then vx = -3
mx = mousex()
my = mousey()
`ink rgb(255,255,255),0
`line 200, 200, mx, my
`ink rgb(255,0,0),0
`line 200, 200, 200+(my-200), 200-(mx-200)
ink rgb(255,255,255),0
drawPolygonB(p2x, p2y)
rem collision
result.intersect = 1
result.willIntersect = 1
local edgeCountA : edgeCountA = array count(polygonA())
local edgeCountB : edgeCountB = array count(polygonB())
local minIntervalDistance# = POSITIVE_INFINITY
local edge as Vector2D
REM loop through all the edges of both polygons
for i = 1 to edgeCountA+edgeCountB
if i <= edgeCountA
p2 = i+1
if p2 > edgeCountA then p2 = 1
edge.x = polygonA(p2).x - polygonA(i).x
edge.y = polygonA(p2).y - polygonA(i).y
else
p2 = i+1
if p2 > edgeCountB then p2 = edgeCountA+1
edge.x = polygonB(p2).x - polygonB(i - edgeCountA).x
edge.y = polygonB(p2).y - polygonB(i - edgeCountA).y
endif
REM ==== Step 1. Find if the polygons are currently intersecting ====
REM Find the axis perpendicular to the current edge
set vector2 axis, -edge.y, edge.x
normalize vector2 axis, axis
`ink rgb(255,0,0),0
`x = p1x+polygonA(i).x
`y = p1y+polygonA(i).y
`line x, y, x+x vector2(axis)*40, y+y vector2(axis)*40
REM Find the projection of the polygon on the current axis
local minA# = 0 : local minB# = 0 : local maxA# = 0 : local maxB# = 0
REM Polygon A
set vector2 v1, p1x+polygonA(1).x, p1y+polygonA(1).y
local dotProduct# : dotProduct# = dot product vector2(axis, v1)
minA# = dotProduct#
maxA# = dotProduct#
for j = 1 to edgeCountA
set vector2 v1, p1x+polygonA(j).x, p1y+polygonA(j).y
dotProduct# = dot product vector2(v1, axis)
if dotProduct# < minA#
minA# = dotProduct#
else
if dotProduct# > maxA# then maxA# = dotProduct#
endif
next j
REM Polygon B
set vector2 v1, p2x+polygonB(1).x, p2y+polygonB(1).y
local dotProduct# : dotProduct# = dot product vector2(axis, v1)
minB# = dotProduct#
maxB# = dotProduct#
for j = 1 to edgeCountB
set vector2 v1, p2x+polygonB(j).x, p2y+polygonB(j).y
dotProduct# = dot product vector2(v1, axis)
if dotProduct# < minB#
minB# = dotProduct#
else
if dotProduct# > maxB# then maxB# = dotProduct#
endif
next j
REM Check if the polygon projections are currently intersecting
if intervalDistance(minA#, maxA#, minB#, maxB#) > 0 then result.intersect = 0
REM ==== Step 2. Find if the polygons will intersect ====
REM Project the velocity
set vector2 velocity, vx, vy
local velocityProjection# : velocityProjection# = dot product vector2(axis, velocity)
REM Get the projection of polygon A during the movement
if velocityProjection# < 0
inc minA#, velocityProjection#
else
inc maxA#, velocityProjection#
endif
REM Do same test as above for new projection
intervalDistance# = intervalDistance(minA#, maxA#, minB#, maxB#)
if intervalDistance# > 0 then result.willIntersect = 0
REM If the polygons are not intersecting and won't intersect, exit the loop
if result.intersect = 0 and result.willIntersect = 0 then exit
REM Check if the current interval distance is the minimum one.
REM If so store the interval distance and the current distance.
REM This will be used to calculate the minimum translation vector
intervalDistance# = abs(intervalDistance#)
if intervalDistance# < minIntervalDistance#
minIntervalDistance# = intervalDistance#
set vector2 translationAxis, x vector2(axis), y vector2(axis)
set vector2 d, p1x-p2x, p1y-p2y
if dot product vector2(d, translationAxis) < 0
set vector2 translationAxis, x vector2(axis)*-1, y vector2(axis)*-1
endif
endif
REM The minimum translation vector can be used to push the polygons apart.
if result.willIntersect = 1
result.minimumTranslationVector.x = x vector2(translationAxis)*minIntervalDistance#
result.minimumTranslationVector.y = y vector2(translationAxis)*minIntervalDistance#
endif
next i
if result.willIntersect
vx = vx + result.minimumTranslationVector.x
vy = vy + result.minimumTranslationVector.y
endif
p1x = p1x + vx
p1y = p1y + vy
ink rgb(255,255,255),0
rem draw the two polygon shapes
drawPolygonA(p1x, p1y)
print mousex()
print mousey()
sync
loop
function intervalDistance(minA as float, maxA as float, minB as float, maxB as float)
if minA < minB
n# = minB - maxA
exitfunction n#
endif
n# = minA - maxB
endfunction n#
function makeRandomPolygonA(radius)
a# = 360/6.0
r2 = radius/2
for i = 1 to 6
polygonA(i).x = sin(a#*i)*(rnd(r2)+r2)
polygonA(i).y = cos(a#*i)*(rnd(r2)+r2)
next i
endfunction
function drawPolygonA(x, y)
for i = 1 to 6
x1 = x + polygonA(i).x
y1 = y + polygonA(i).y
if i < 6
x2 = x + polygonA(i+1).x
y2 = y + polygonA(i+1).y
else
x2 = x + polygonA(1).x
y2 = y + polygonA(1).y
endif
line x1, y1, x2, y2
next i
endfunction
function makeRandomPolygonB(radius)
a# = 360/7.0
r2 = radius/2
for i = 1 to 7
polygonB(i).x = sin(a#*i)*(rnd(r2)+r2)
polygonB(i).y = cos(a#*i)*(rnd(r2)+r2)
next i
endfunction
function drawPolygonB(x, y)
for i = 1 to 7
x1 = x + polygonB(i).x
y1 = y + polygonB(i).y
if i < 7
x2 = x + polygonB(i+1).x
y2 = y + polygonB(i+1).y
else
x2 = x + polygonB(1).x
y2 = y + polygonB(1).y
endif
line x1, y1, x2, y2
next i
endfunction
