0
\$\begingroup\$

I'm currently very new to XNA, and I'm trying to get a grasp on movement. Currently, I have a function that checks for keypresses, and moves my character from point A to point B instantly:

private KeyboardState currentKeyboardState;
private KeyboardState previousKeyboardState;

...

public void CaptureKeyboardInput()
{
    currentKeyboardState = Keyboard.GetState();

    // Move the character's sprite to the left on the screen. The movement
    // distance is determined based on the scale of the sprite texture.
    if (currentKeyboardState.IsKeyDown(Keys.A) && previousKeyboardState.IsKeyUp(Keys.A))
    {
        Position += new Vector2(-Scale.X, 0);
    }

    // Move the character's sprite to the right on the screen. The movement
    // distance is determined based on the scale of the sprite texture.
    if (currentKeyboardState.IsKeyDown(Keys.D) && previousKeyboardState.IsKeyUp(Keys.D))
    {
        Position += new Vector2(Scale.X, 0);
    }

    // Move the character's sprite upwards on the screen. The movement
    // distance is determined based on the scale of the sprite texture.
    if (currentKeyboardState.IsKeyDown(Keys.W) && previousKeyboardState.IsKeyUp(Keys.W))
    {
        Position += new Vector2(0, -Scale.Y);
    }

    // Move the character's sprite downwards on the screen. The movement
    // distance is determined based on the scale of the sprite texture.
    if(currentKeyboardState.IsKeyDown(Keys.S) && previousKeyboardState.IsKeyUp(Keys.S))
    {
        Position += new Vector2(0, Scale.Y);
    }

    previousKeyboardState = currentKeyboardState;
}

While this works, it looks very unclean, and feels unnatural as well. Ideally, I'd like to move it from point A to B at a certain speed. I've already looked around, and I've found this question, but I couldn't figure out how to implement it correctly. How can I implement smooth movement from point A to B in my tile-based game with what I have?

\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

You can accomplish this by using linear interpolation.

https://msdn.microsoft.com/en-us/library/bb197807.aspx

float speed = 0.1f;   //value between 0 - 1
Position = Vector2.Lerp(Position, DesiredPosition, speed);

Another way to do it is to incorporate a time value, while keeping track of the start and end positions. This ensures the movement will be the same regardless of framerate.

Vector2 StartPosition;
Vector2 EndPosition;
float Timer;
float Speed = 1;

...

void Update()
{
    var deltaTime = (float)gametime.ElapsedGameTime.TotalSeconds;

    if (Timer <= 0)
    {
        Timer += deltaTime * Speed;
        Timer = MathHelper.Min(Timer, 1);
        Position = Vector2.Lerp(StartPosition, EndPosition, Timer);
    }
}

public void CaptureKeyboardInput()
{
    currentKeyboardState = Keyboard.GetState();

    if (currentKeyboardState.IsKeyDown(Keys.A) && previousKeyboardState.IsKeyUp(Keys.A))
    {
        StartPosition = Position;
        EndPosition += new Vector2(-Scale.X, 0);
        Timer = 0;
    }

    ...
}
\$\endgroup\$
3
  • \$\begingroup\$ Are you sure MathHelper.Lerp accepts Vector2 values? I'm getting errors when I try to use it with Vector2 values. \$\endgroup\$ Commented Apr 13, 2016 at 15:28
  • \$\begingroup\$ Sorry, you should be using Vector2.Lerp() and not the MathHelper one. I will update the code. \$\endgroup\$
    – jgallant
    Commented Apr 13, 2016 at 15:29
  • \$\begingroup\$ Ah, thanks. That'd explain why I was getting errors and odd behaviours while trying to modify the individual X and Y components. \$\endgroup\$ Commented Apr 13, 2016 at 15:30
0
\$\begingroup\$

Welcome to XNA! First off, I'l strongly advise you to switch to Monogame. It uses the same bindings as XNA and your workflow will not change much. Plus it is under active maintenance.

Also, before you rush into making a game you should check out some tutorials on sprite animation and frame independent movement.

On to your question then. I've posted the correct code.

C# code:

namespace Tiled { public class Tiled : Microsoft.Xna.Framework.Game { Vector2 viewportPosition;

    public Tiled () {
        IsFixedTimeStep = true;
    }

    protected override void Update (GameTime gameTime) {
        GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
        KeyboardState keyState = Keyboard.GetState();
        float scrollx = 0, scrolly = 0;

        if (keyState.IsKeyDown(Keys.Left))
            scrollx = -1;
        if (keyState.IsKeyDown(Keys.Right))
            scrollx = 1;
        if (keyState.IsKeyDown(Keys.Up))
            scrolly = 1;
        if (keyState.IsKeyDown(Keys.Down))
            scrolly = -1;

        scrollx += gamePadState.ThumbSticks.Left.X;
        scrolly += gamePadState.ThumbSticks.Left.Y;

        float scrollSpeed = 8.0f;

        player.X += (int)(scrollx * scrollSpeed);
        player.Y -= (int)(scrolly * scrollSpeed);

        base.Update(gameTime);
    }
}

}

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think the code you posted is for realtime physics simulation, for platformers or things like that. OP is asking for smooth tile-based movement, like in the old Pokémon games for example. \$\endgroup\$ Commented Apr 13, 2016 at 9:09
  • \$\begingroup\$ There I go posting useless code. I'l post tile based code sorry about that \$\endgroup\$
    – zimspy
    Commented Apr 13, 2016 at 10:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .