It looks like you're trying to implement a MoveTowards function. Try something more like this:
def moveTowards(mover, target, maxStep):
deltaX = target.x - mover.x
deltaY = target.y - mover.y
mag = deltaX * deltaX + deltaY * deltaY
if mag < maxStep * maxStep:
mover.x = target.x
mover.y = target.y
else:
scale = maxStep / sqrt(mag)
mover.x += deltaX * scale
mover.y += deltaY * scale
Or, to stop at a fixed distance away from the object, modify like so:
def moveTowardsOrbit(mover, target, maxStep, stopDistance):
deltaX = target.x - mover.x
deltaY = target.y - mover.y
distance = sqrt(deltaX * deltaX + deltaY * deltaY)
unitScale = 1 / distance
deltaX *= unitScale
deltaY *= unitScale
onCircleX = target.x - deltaX * stopDistance
onCircleY = target.y - deltaY * stopDistance
fromStop = distance - stopDistance
if abs(fromStop) <= maxStep:
mover.x = onCircle.x
mover.y = onCircle.y
else:
if fromStop < 0:
deltaX *= -1
deltaY *= -1
mover.x += deltaX * maxStep
mover.y += deltaY * maxStep
Call this with moveTowards(obj, anchor, speed * dt, 10)
.
This version...
Picks a point on the circle
stopDistance
away from theanchor
and moves toward that - whether that takes it inward or outward along the line joiningobj
andanchor
.Moves the object at most a distance of
maxStep
per invocation.When the destination is closer than
maxStep
, it snaps the object directly to thestopDistance
circle, with no under- or over-shooting.Uses no trigonometric functions. It also handles all angles correctly, unlike the sample code (hint: you probably want
atan2
when trying to find an angle from two coordinates).
You should also consider using a fixed timestep for your game simulation, so it's not subject to variation depending on the rendering framerate.