0 votes

Hi all,

I have a bat sprite trying to match the Y pos of the mouse.

Here is the basics:

#check if the mouse is above or below the bat
if bat.get_pos().y > mousePos.y:
    game.direction = -1 #moving up
    moveBat(delta, batSpeed)
elif bat.get_pos().y < mousePos.y:
    game.direction = 1 #moving down
    moveBat(delta, batSpeed)
    game.direction = 0 #not moving

...here is moveBat()

func moveBat(delta, batspeed):

    #get the bat's current position
    var curPosition = bat.get_pos()
    var newPosition = batspeed

    #make the new position
    if game.direction == -1:
        newPosition = -batspeed
    elif game.direction == 1:
        newPosition = batspeed

    #make the bat move in the correct direction

The functions work well. I move the mouse, the bat moves to meet the mouse at the speed I've set in batSpeed.

Often though, when the mouse is still (hand not on it, totally stationary), the bat will jitter for EXACTLY 3 pixels up and down outside of the range of the mouse's Y position. As though it's not quite sure which Y pixel it should be settled on.

Is there a way to smooth this out?

in Engine by (825 points)

3 Answers

+2 votes
Best answer

There are two easy solutions;

Either you could just check abs(bat.get_pos().y - mousePos.y) < closeEnough and then not move the bat - obviously define closeEnough to some static value ( e.g 5 )

or you could use lerp (documentation) to interpolate between the current and last value - this will make the bat sligthly more sluggish to react tho

by (366 points)
selected by

You've all given me much to consider. I marked this as correct as it was first and it was very informative.

I used:

var closeEnough = 3

if (lerp(bat.get_pos().y, bat.get_pos().y-closeEnough, 50*delta) >= mousePos.y:
    #do stuff

I'm confused RE the lerp 50*delta but I'll ask in another thread to keep it specific.

I ended up trying lots of things.
- Lerp
- Easing (my math is just too poor at the moment which is a shame, as easing would be great).
- ABS (couldn't get it smooth enough)

Easing would be the winner, but I'm just not there ye.=t.

Thank you to everyone.

+1 vote

Jitter happens because the following happens:

1) Bat is above mouse, go down
2) Bat is below mouse now, so go up
3) Bat is above mouse, go down
4) Bat is below mouse, go up
5) Bat is above mouse, go down
6) Bat is below mouse, go up

If you want to make the bat stay at its position without having to use a lerp to smooth it out, you can add another check when the bat moves:

If the bat moves, but then crosses the Y line of the mouse, set its position to the mouse directly, so you will actually reach the case where both Y are the same.

If the bat still jitters, you can add a tiny margin in your check, because positions are float numbers and you will inevitably accumulate small errors. Testing if a calculated float is equal to something is always fishy^^

by (28,789 points)

Thank you, much appreciated. It makes sense more now.

+1 vote

The a.y > b.y is a common mistake when not working with integers, you need to check the distance (or squared distance) between them (@guppy42 solution).

More options:

Lerp (already mentioned too).

If movement > distance to mouse position, then do not move or stick the object to the mouse position.
The second option may need some extra work and both do movement calculations when not needed.

Create a small area for your moving object and stop movement (or alter the movement mechanic, like, to lerp) when mouse is inside that area.

by (7,894 points)

Thank you, these are great suggestions. Much appreciated.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.