Usually when I animate I do it in two stages:
1. I setup everything in a tile-based system. Gridlock so to speak.
2. I setup an array that corresponds to the position and size of the animations needed. For example, if I am using variable-size sprites, I setup a multidimensional array that has the first dimension being the sprite, and then the second being the ((DIRECTION * ANIMATIONS_PER_DIRECTION) + CURRENT_ANIMATION_FRAME).
Here is an example I am using in C++ with DirectX:
RECT gPlayerAnimationSources [1][16] = {{{0, 0, 32, 48},{32, 0, 64, 48},{64, 0, 96, 48},{96, 0, 128, 48},
{0, 48, 32, 96},{32, 48, 64, 96},{64, 48, 96, 96},{96, 48, 128, 96},
{0, 96, 32, 144},{32, 96, 64, 144},{64, 96, 96, 144},{96, 96, 128, 144},
{0, 144, 32, 192},{32, 144, 64, 192},{64, 144, 96, 192},{96, 144, 128, 192}}};
This is used with the directions as follows:
0 = Down,
1 = Left,
2 = Right,
3 = Up
In order to do smooth-gridlock movement I setup two vectors in DirectX:
D3DXVECTOR3 gPlayerPosition = D3DXVECTOR3(0, 0, 0), gPlayerPositionDisplay = D3DXVECTOR3(0, 0, 0);
Then, to update it, I merely check for the difference in one vector versus the other.
// Update their X position based on whether they are ahead of or behind the real position.
if (gPlayerPosition.x > gPlayerPositionDisplay.x)
gPlayerPositionDisplay.x += factor;
else if (gPlayerPosition.x < gPlayerPositionDisplay.x)
gPlayerPositionDisplay.x -= factor;
// Update their Y position based on whether they are ahead of or behind the real position.
if (gPlayerPosition.y > gPlayerPositionDisplay.y)
gPlayerPositionDisplay.y += factor;
else if (gPlayerPosition.y < gPlayerPositionDisplay.y)
gPlayerPositionDisplay.y -= factor;
This gives a smooth-feeling movement, as I can merely update the "Real" location. Then to draw the animation, I merely check which pixel they are on corresponding to their tile.
// Are they going left or right? Or Up or down? Setup the tile for them.
if (gPlayerDirection == 1 || gPlayerDirection == 2)
gCurrentTileAnimation = ((4 * gPlayerDirection) + ((int)gPlayerPositionDisplay.x / 4 % 4));
else
gCurrentTileAnimation = ((4 * gPlayerDirection) + ((int)gPlayerPositionDisplay.y / 4 % 4));
The animation get's called with:
&gPlayerAnimationSources[SPRITE][gCurrentTileAnimation]
And thus, I get fairly decent smooth animation. (I also use this technique in C# when I use XNA.)
Thanks,
EBrown