Reputation: 3190
I implemented the following function:
function moveTowards(start, target, speed) {
if (Math.abs(target.x - start.x) < config.COLLISION_RADIUS
&& Math.abs(target.y - start.y) < config.COLLISION_RADIUS) {
return target
}
const newX = target.x - start.x
const newY = target.y - start.y
const angle = Math.atan2(newY, newX)
const x = speed * Math.cos(angle)
const y = speed * Math.sin(angle)
return {
x: start.x + x,
y: start.y + y
}
}
It is expected to be called in a games update loop and returns a position that slowly moves towards the target position.
It works fine however when I set a speed greater than 1 the function never actually meets the target position but returns positions in the area around the target.
I took the math from here: https://stackoverflow.com/a/20762210/5547718
The solutions there dont contain a speed parameter, rather a "magnitude".
How could I implement a variable speed without never arriving at the target?
(I tried just accepting values that are "close enough" but the greater the speed the higher differences I must tolerate which doesnt work out practicly)
Upvotes: 0
Views: 111
Reputation: 3190
Using @Balazs's and @Michael's advice I did the following and it worked out perfectly:
function moveTowards(start, target, speed) {
const newX = target.x - start.x
const newY = target.y - start.y
const angle = Math.atan2(newY, newX)
const x = speed * Math.cos(angle)
const y = speed * Math.sin(angle)
if (newX*newX <= x*x && newY*newY <= y*y)
return target
return {
x: start.x + x,
y: start.y + y
}
}
Upvotes: 0
Reputation: 2875
Your code does a lot of unnecessary calculations every frame. For example, you should only have these calculations:
const angle = Math.atan2(newY, newX);
const x = speed * Math.cos(angle);
const y = speed * Math.sin(angle);
Done once at the beginning of the movement as opposed to every single frame (the angle deosn't change between frames).
What you could have every frame, however, is a check to see whether the distance from start to target is less than the projected distance with speed, in which case simply place the object at the target position.
if (newX <= x && newY <= y) {
return target;
}
Upvotes: 2