Page 1 of 1

Move object to mouse (stuttering)

Posted: Fri Nov 23, 2018 3:37 pm
by wongkj12
Hi, am new to this forum & programming in general, would kindly appreciate any help!

I'm trying to get an object to move at a constant speed towards the mouse cursor, however whenever my object reaches the cursor it starts stuttering back & forth near the cursor. (Here is a GIF: https://ibb.co/dKuFXA)

The code for the movement, in love.update():

Code: Select all

mouse_x,mouse_y = love.mouse.getPosition()

    player.xcentre = player.x + 50
    player.ycentre = player.y + 50
    
    dx = mouse_x - player.xcentre
    dy = mouse_y - player.ycentre

    distance = math.sqrt(dx*dx + dy*dy)

    dx = dx/distance 
    dy = dy/distance

    player.xspeed = dx*player.speed
    player.yspeed = dy*player.speed

    player.x = player.x + (player.xspeed*dt) 
    player.y = player.y + (player.yspeed*dt)
From what I've tested it seems that in the frames before the object touches the cursor, it seems to "over-step" the cursor, thus making it go back and forth. However, I'm not too sure what's causing this or how to fix it. Thanks in advance if you guys have any advice :)!

Re: Move object to mouse (stuttering)

Posted: Fri Nov 23, 2018 6:16 pm
by pgimeno
Welcome to the forums!

Yes, this is expected. You can think about it in one dimension for simplicity. Your player starts at some distance from the target, and it will approach the target (the mouse cursor) in more or less constant steps. It's extremely unlikely that the last step lands exactly on the target; it's much more likely that in the step prior to reaching the target it lands closer than what it will advance in the next step, causing it to overshoot. Remember that dt is fractional and fluctuates somewhat randomly.

As for the fix. the best way is to detect whether it is overshooting, and when that happens, set it to the target coordinates instead. Overshooting can be detected by using some basic vector algebra: you calculate two vectors, the vector from the target to the prior position (the position before adding the xspeed/yspeed to the player's x/y), and the vector from the target to the next position (the position after adding the speed, or more properly the velocity, to the player's position). If these two vectors point in the same direction, that means you haven't overshot yet. If they point in opposite directions, you're overshooting. And if one of them has zero length, it means it's exactly at the target.

Now, the operation that tells you whether two vectors point in the same direction, is the dot product. The dot product of two vectors is a number, not a vector, and is calculated as the sum of the products of their components. So, if A and B are two 2D vectors, their dot product is A·B = Ax*Bx + Ay*By. The sign of that number, when calculated from the two vectors described above, will tell you whether you are overshooting in this step. If the dot product of these two vectors is positive, they point in the same direction, meaning you haven't overshot yet and you can still add the speed; if negative, they point in opposite directions and you're overshooting, therefore you have to correct the position; if zero, they are either perpendicular, or at least one of them is zero, so you're basically in the same case as overshooting, because you need to stop advancing too. I don't think you can get them perpendicular in this case, or maybe you can because of rounding errors, but that doesn't really matter.

With that, hopefully you can implement overshoot detection successfully to correctly land on the target.

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 2:25 am
by wongkj12
Ah, I get it now. Thank you for such a detailed explanation!

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 6:30 am
by ivan
While Pgimeno is correct, assuming you are moving at a constant speed, I think the "overshoot" problem could be described in a simpler way:

Code: Select all

local step = player.speed*dt
if step >= distance then
  -- arrive
else
  -- keep moving
end
Also, don't forget the formula:
time = distance/speed

Further reading:
https://2dengine.com/?p=vectors#Moving_to_target

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 9:41 am
by pgimeno
ivan wrote: Sat Nov 24, 2018 6:30 am While Pgimeno is correct. Assuming you are moving at a constant speed, I think the "overshoot" problem could be described in a simpler way:

Code: Select all

local step = player.speed*dt
if step >= distance then
  -- arrive
else
  -- keep moving
end
Yes, definitely, because in this case the distance is already calculated (used to normalize the velocity vector). Thanks!

I was thinking of a more general method where you don't need to calculate the distance in order to detect whether you are overshooting, which is more expensive than the dot product, but in this case your solution is obviously simpler.

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 2:03 pm
by wongkj12
ivan wrote: Sat Nov 24, 2018 6:30 am While Pgimeno is correct, assuming you are moving at a constant speed, I think the "overshoot" problem could be described in a simpler way:

Code: Select all

local step = player.speed*dt
if step >= distance then
  -- arrive
else
  -- keep moving
end
Also, don't forget the formula:
time = distance/speed

Further reading:
https://2dengine.com/?p=vectors#Moving_to_target
Alright, that makes sense as well, and is much simpler. Thanks!

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 4:15 pm
by Ref
Sounds like over kill to me.
I like:

Code: Select all

x, y 	= (mx-x) / delay + x, (my-y) / delay + y
If delay is set to something like 6, you get a nice smooth movement to the mouse coords (mx,my).

Re: Move object to mouse (stuttering)

Posted: Sat Nov 24, 2018 5:06 pm
by pgimeno
That's framerate-dependent. https://gamasutra.com/blogs/ScottLembck ... othing.php

Also, the OP said constant speed.