Hi all,
Could one of you clever folks post up a short explanation of a circle line collision? I don’t need to know the intersection point just that a collision has occurred. I know it can be done using the physics API but would like to understand the process so I can take it elsewhere. Been trying for a few days now, not the easiest thing to get your head around.
I used something along these lines in my TouchLine game:
-- each item in self.enemies is a circle with a radius
for i, v in ipairs(self.enemies) do
-- do rough distance check to avoid doing the full collision check against every circle
if v:left() < math.max(lineStart.x, lineEnd.x) and
v:right() > math.min(lineStart.x, lineEnd.x) and
v:top() > math.min(lineStart.y, lineEnd.y) and
v:bottom() < math.max(lineStart.y, lineEnd.y) then
A = v.position.x - lineStart.x
B = v.position.y - lineStart.y
C = lineEnd.x - lineStart.x
D = lineEnd.y - lineStart.y
local lineDist = math.abs(A * D - C * B) / math.sqrt(C * C + D * D)
-- lineDist is a point to line distance - you'll have to compare it to the radius of your circle and width of your line. E.g.:
if (lineDist) <= (lineWidth + v:radius()) then
... -- etc
Thanks to both of you for the reply. @Nat been searching the net for two days and not come up with anything which explained it as well as the above link did, helped a lot.
Will post the code when I’ve tidied it up a bit
Here’s what I came up with, to check for collision compare the distance of the returned vector to the circle with the circles radius
function closestPoint(startPoint, endPoint, circle)
local v1 = endPoint - startPoint
local v2 = circle - startPoint
local v1u = v1:normalize()
local proj_len = v2:dot(v1u) -- projected length onto v1
if proj_len <= 0 then
return startPoint -- closest point
end
if proj_len >= v1:len() then
return endPoint -- closest point
end
local proj_v = v1u * proj_len -- create vector from length along v1
return proj_v + startPoint -- closest point
end