Move object to mouse (stuttering)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
wongkj12
Prole
Posts: 3
Joined: Fri Nov 23, 2018 3:15 pm

Move object to mouse (stuttering)

Post 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 :)!
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Move object to mouse (stuttering)

Post 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.
wongkj12
Prole
Posts: 3
Joined: Fri Nov 23, 2018 3:15 pm

Re: Move object to mouse (stuttering)

Post by wongkj12 »

Ah, I get it now. Thank you for such a detailed explanation!
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Move object to mouse (stuttering)

Post 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
Last edited by ivan on Sat Nov 24, 2018 11:22 am, edited 1 time in total.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Move object to mouse (stuttering)

Post 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.
wongkj12
Prole
Posts: 3
Joined: Fri Nov 23, 2018 3:15 pm

Re: Move object to mouse (stuttering)

Post 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!
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Move object to mouse (stuttering)

Post 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).
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Move object to mouse (stuttering)

Post by pgimeno »

That's framerate-dependent. https://gamasutra.com/blogs/ScottLembck ... othing.php

Also, the OP said constant speed.
Post Reply

Who is online

Users browsing this forum: No registered users and 44 guests