Tile based movement jerky with fixed time step.

Before I moved from MDX2.0 to XNA, my tile based movement using a finite state machine was smooth. Now that I'm using a fixed time step, my old method is jerky.

I would like to redo my old method to work smoothly with the default fixed time step and am looking for ideas on how to accomplish this. The tile based movement I'm talking about is the same used in many old console rpg's (FF4/FF5/FF6) where the player moves a complete tile before accepting movement input again, yet still smoothly moves to it's destination (as opposed to jumping directly to each tile).

Here's my old method converted to XNA.

//
Vector2 position = new Vector2(32, 32);
Vector2 destination = position;
float speed = 128;

public void Update(KeyboardState keyState, float elapsed)
{
switch (state)
{
case State.Idle:
if (keyState.IsKeyDown(Keys.Up))
{
destination.Y -= 32;
state = State.MoveUp;
direction = Direction.Up;
}

else if (keyState.IsKeyDown(Keys.Down))
{
destination.Y += 32;
state = State.MoveDown;
direction = Direction.Down;
}

else if (keyState.IsKeyDown(Keys.Left))
{
destination.X -= 32;
state = State.MoveLeft;
direction = Direction.Left;
}

else if (keyState.IsKeyDown(Keys.Right))
{
destination.X += 32;
state = State.MoveRight;
direction = Direction.Right;
}
break;

case State.MoveUp:
moveUp(elapsed);
break;

case State.MoveDown:
moveDown(elapsed);
break;

case State.MoveLeft:
moveLeft(elapsed);
break;

case State.MoveRight:
moveRight(elapsed);
break;
}
}

void moveUp(float elapsed)
{
if (position.Y - speed * elapsed < destination.Y)
{
position.Y = destination.Y;
state = State.Idle;
}
else
position.Y -= speed * elapsed;
}

void moveDown(float elapsed)
{
if (position.Y + speed * elapsed > destination.Y)
{
position.Y = destination.Y;
state = State.Idle;
}
else
position.Y += speed * elapsed;
}

void moveLeft(float elapsed)
{
if (position.X - speed * elapsed < destination.X)
{
position.X = destination.X;
state = State.Idle;
}
else
position.X -= speed * elapsed;
}

void moveRight(float elapsed)
{
if (position.X + speed * elapsed > destination.X)
{
position.X = destination.X;
state = State.Idle;
}
else
position.X += speed * elapsed;
}
//

With XNA's default 16.6666 timestep, moving produces a slight pause each time the player transitions between tiles. I'm looking for a more effecient way to handle tile based movement while keeping this default timestep.

Any ideas are welcome.

[14093 byte] By [Apathy] at [2007-12-24]
# 1

Are you running the code on an Athlon X2?

If so, check out this thread, it's probably your issue: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=686308&SiteID=1

If that's the case, post how smooth your results are at Full Screen with new chipset drivers. I saw vast improvement, but it was still, unfortunately, not perfect.

DennisLackmeyer at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 2
The code looks pretty sound to me. The only thing I can see offhand is that as long as elapsed is defined in the same class that Update() is, then you don't need to pass elapsed to those other functions, you can just access it. Though I seriously doubt this would affect the speed of a loop this small.
GregHeier at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 3
I'm using an A64, so I'm sure it's not a dual core problem. The update function is in my player class, so elapsed needs to be passed to it from the game.

I've noticed even my old MDX2.0 movement is jerky if I enable vsync.

The jerky movement comes from the game and screen not being updated frequently enough. The movement is smooth when I turn off 'IsFixedTimeStep' and turn on 'SynchronizeWithVerticalRetrace'. The downside is turning off vsync causes 100% cpu usage in windowed mode.

I want to be able to have smooth movement while keeping vsync on and keeping the default fixed time step.

Apathy at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 4

Actually, I think people have had issues with standard A64 chips before as well. I'm only guessing, but your source code is perfectly sound, so the only reason that your movement would be jerky in this instance is if either the framerate was too low (unlikely) or if elapsed is reporting the wrong times.

If you want to do a test first, make a variable that tracks accumulated time spent in Update and have it break after 10 seconds. Compare when it breaks against a stopwatch. You can use a longer break time if the times seem really close. If they're off, then elapsed is being reported wrong and it's quite possibly a chipset driver issue.

When I had this problem, doing the above test I hit the breakpoint in about 7 seconds because elapsed was reporting the time since last Draw instead of since last Update which completely wrecked the movement.

DennisLackmeyer at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 5
I created a small downloadable demo here (source included) for anyone wanting to see the difference in jerky movement. Look under Game1.cs > Game_Starting() to find the comments and code needed to change between jerky movement and non jerky movement.

I noticed the spacewars demo uses no vsync or timestep so I turned them both on and noticed no jerky movement. This tells me that my tile based movment code is the problem. If anyone has a better method for tile based movement, let me know.

Apathy at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 6

Can you give this a try?

Go to http://www.amd.com/us-en/Processors/TechnicalResources/0,,30_182_871_13118,00.html

Download and install the "AMD Dual-Core Optimizer" and see if this helps your issue. This of course assumes you all are running an AMD Athlon? 64 X2

Thanks!

MichaelKlucher-MSFT at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 7
I'm using a single core A64.
Apathy at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 8
Michael Klucher - MSFT wrote:

Can you give this a try?

Go to http://www.amd.com/us-en/Processors/TechnicalResources/0,,30_182_871_13118,00.html

Download and install the "AMD Dual-Core Optimizer" and see if this helps your issue. This of course assumes you all are running an AMD Athlon? 64 X2

Thanks!

Thanks, everything working perfectly in my own app now.

vidalsasoon at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...
# 9
This tutorial deals with smooth scrolling in a tilebased game. Its well written and I personally found it very helpfull.
Dimish at 2007-10-8 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,XNA Game Studio Express...