In case you still want it, here’s a description of some of the math for it.
A circle consists of all points a certain distance (the radius, r) from a center (c): (x - cx)2 + (y - cy)2 = r2
A line can be represented as an interpolation between two points, say p and q. Then at a given “time” t we would have
x = px + t * (qx - px), or equivalently x = (1 - t) * px + t * qx. Ditto for y.
Most of these values you will know, or can figure out. What you want is to find t. Once you have that you can plug it back in for x and y to find the final positions.
Notice that you can substitute the line equation in for x (and likewise another for y) in the circle equation above.
After doing that, and boiling everything down some, you’ll get something in the form a * t2 + b * t + c = 0. This can
be solved by the quadratic equation.
This will give you zero, one, or two times. Zero means you didn’t even have a collision: you missed, or gave it a “line”
that was really just a point (p = q). One means you grazed the circle’s edge. Finally, two means you went in one side
and out the other.
The other thing you’ll need to check is the value of t. A t < 0 means the collision was behind you, whereas > 1 means
it was in front of your second point. Whether you want these is up to you.
In code, finding the times might go something like this (untested):
function FindIntersections (px, py, qx, qy, cx, cy, r) -- (p + t \* w - C) . (p + t \* w - C) = r^2 local dx, dy = px - cx, py - cy local wx, wy = qx - px, qy - py local a = wx \* wx + wy \* wy if a \< 1e-10 then -- a near 0 means p = q, or close enough return 0 else local b = 2 \* (dx \* wx + dy \* wy) -- note that we can cancel this 2 out, but -- must adjust some of the terms that follow local c = dx^2 + dy^2 - r^2 -- A discriminant \< 0 means we missed... local disc = b^2 - 4 \* a \* c if disc \< 0 then return 0 -- ...whereas when nearly 0 means one collision... elseif disc \< 1e-10 then return 1, -b / (2 \* a) -- ...otherwise we have 2 collisions. else disc = math.sqrt(disc) return 2, (-b - disc) / (2 \* a), (-b + disc) / (2 \* a) -- note: times are in order end end end
To filter out times outside the [0, 1] range, something like this (again untested) might do:
function FixTimes (n, t1, t2) if n == 1 then if t1 \>= 0 and t1 \<= 1 then return 1, t1 end elseif n == 2 then if t1 \>= 0 then -- assumes t1 \< t2 if t2 \<= 1 then return 2, t1, t2 elseif t1 \<= 1 then return 1, t1 end elseif t2 \>= 0 and t2 \<= 1 then return 1, t2 end end return 0 end