Having circle center coordinates (cx, cy)
, you can calculate squared distance from circle center to rectangle.
dx = Max(Abs(cx - rect.center.x) - rect.width / 2, 0)
dy = Max(Abs(cy - rect.center.y) - rect.height / 2, 0)
SquaredDistance = dx * dx + dy * dy
When circle is outside of rectangle initially, it is possible to remove Max
call.
dx = Abs(cx - rect.center.x) - rect.width / 2
dy = Abs(cy - rect.center.y) - rect.height / 2
Also we can remove Abs
for known initial position (note - upto moment of sign change!)
if cx >= rect.center.x:
dx = cx - rect.center.x - rect.width / 2
else:
dx = - cx + rect.center.x - rect.width / 2
To avoid a lot od different cases, we can virtually put player in the first quadrant relative to rectangle center and correspondingly change coordinates and velocity components
if cx0 < 0:
cx0 = - cx0
vx = -vx
if cy0 < 0:
cy0 = - cy0
vy = -vy
To register collision moment, you have to substitute coordinates with parametric equations using start point and velocity vector components (vx, vy)
cx = cx0 + vx * t
cy = cy0 + vy * t
and solve (quadratic) equation for t
SquaredDistance - Radius^2 = 0
(cx0 + vx * t - rect.center.x - rect.width/2)^2 +
(cy0 + vy * t - rect.center.y - rect.height/2)^2 -
Radius^2 = 0
Ater that you can get zero (no collision), one (touch event) or two roots (moment of collision and moment of exit).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…