Help moving sprite between 2 points

I’m having an issue moving a sprite between 2 points.

You can see the behavior here:

The starting and ending points are accurate, however somehow the direction/distance are wrong, or my calculation adding to the current position is wrong.

 public void MoveTo(Point dest)
    {
        _endPos = dest.ToVector2();
        _startPos = Position.ToVector2();
        _distance = Vector2.Distance(_startPos, _endPos);
        _direction = Vector2.Normalize(_endPos - _startPos);
        _moving = true;
    }

    public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);
        if (_moving == true)
        {
            Position = (Position.ToVector2() + (_direction * Speed * _elapsed)).ToPoint();
            if (Vector2.Distance(_startPos, Position.ToVector2()) >= _distance)
            {
                Position = _endPos.ToPoint();
                _moving = false;
            }
        }
    }

For reference, Speed = 50, _elapsed = .1f.

ALl I’m trying to do is smoothly move the sprite between the two points.

Thanks in advance.

I kind of like how he hops actually…

1 Like

Why not use vectors.lerp?
Should work perfectly

PS you really should have position as a vector2 not a point as this looks like a rounding issue.

OK…
so, why does this take longer than 1 second to move? I’m telling update to update my location every 1/100 of a second. This takes like 3 seconds when I specify 1 as my “seconds” in my moveTo function.

Is update not firing that often?

public void MoveTo(Point dest, float seconds)
    {
        _endPos = dest.ToVector2();
        _startPos = Position.ToVector2();
        _lerpAdd = (1f/100f) * (1f / seconds);
        _lerp = 0;
        
        _moving = true;
    }

    public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);
        if (_moving == true)
        {
            _elapsed -= gameTime.ElapsedGameTime.TotalSeconds;
            if (_elapsed <= 0)
            {
                _elapsed = 0.01;

                if (_lerp >= 1f || Vector2.Equals(Position, _endPos))
                {
                    _moving = false;
                }
                else
                {
                    _lerp += _lerpAdd;
                }
                Position = Vector2.Lerp(_startPos, _endPos, _lerp).ToPoint();
                
                //Position = (Position.ToVector2() + (_direction * Speed * _elapsed)).ToPoint();
                //if (Vector2.Distance(_startPos, Position.ToVector2()) >= _distance)
                //{
                //    Position = _endPos.ToPoint();
                //    _moving = false;
                //}
            }
        }
    }

Nevermind… Looks like update fires 60 times a second consistently. Changing that 1/100f to 1/60f works. Thanks for the help!

I had already wrote this code before I saw your last post so thought I’d post it anyway.

private float _currentMovingTimer = 0f;

private float _totalTimeToMove;

 

private Vector2 _mobPosition = Vector2.Zero;

private Vector2 _startLocaiton, _endLocation;

float timer = 0;

 

public void StartMove(Vector2 endLocation, float timeToTake)

{

_startLocaiton = _mobPosition;

_endLocation = endLocation;

_totalTimeToMove = timeToTake;

_currentMovingTimer = timeToTake;

_startLocaiton = _mobPosition;

timer = 0;

}

 

protected override void Update(GameTime gameTime)

{

if (_currentMovingTimer > 0)

{

timer += (float)gameTime.ElapsedGameTime.TotalSeconds;

_currentMovingTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds;

float delta = MathHelper.Clamp(_currentMovingTimer / _totalTimeToMove, 0, 1);

_mobPosition = Vector2.Lerp(_startLocaiton, _endLocation, 1 - delta);

}

 

base.Update(gameTime);

}
3 Likes

Changing my post here… I saw that you are, in fact, using gameTime.ElapsedGameTime.TotalSeconds in your velocity calculations, but you’re doing something kind of weird with it.

I’m curious, why are you trying to fix your calculations to a fixed rate? Your game does just happen to run at 60 updates per second by default, but that may not always be the case as you might decide you want to change this, or things might start slowing down as you add more stuff to your game.

You should be able to simply calculate your velocity as (distance_to_travel / time_to_travel) * direction_to_travel, and then update your position position += velocity * gameTime.ElapsedGameTime.TotalSeconds.

If you’re worried about overshooting, you can always just calculate when a position change puts you past the point you wanted to reach and stop there. If you need to continue, calculate the time that is unconsumed from the previous move and add that time to the next move.

I mean, if I’ve misunderstood and you’re doing something very specific and intentional, no worries… it just looked a bit off to me and I wanted to check in that this is what you were looking to do :slight_smile:

1 Like

Massive help this - works like a charm. Thanks @Mattlekim!

Hello @Mattlekim. I hope you see this message. This code that you posted works great, but I just want to make sure if
float delta = MathHelper.Clamp(_currentMovingTimer / _totalTimeToMove, 0, 1);

and later
_mobPosition = Vector2.Lerp(_startLocaiton, _endLocation, 1 - delta);

takes in the consideration the time that has passed since the last time the update was called (so that it will not run faster on newer and slower on older machines) or should I do any multiplication here with the deltatime?

Thank you.

You don’t need to multiply the result position by the deltime. Because _currentMovingTimer already contains the time from the past frame. This code will work the same on both fast machines and slow ones because _currentMovingTimer increments the time elapsed since the last frame.

1 Like

Thank you.