0
votes

I'm currently creating animation with xna. I have no problem to animate spritesheet when the frame Height, Width and duration are the same between all the frames.

But i didn't find it very flexible and i'd like to animate without a spritesheet of same frameHeight/Width and more importantly without constant duration.

Is there any tutorials or code sample to learn this?

EDIT: I think of something like this but i can't make it work:

    public void Update(GameTime gameTime)
    {
        if (elapsedTime > frameTime)
        {
            currentFrame++;
            elapsedTime = 0;
        }

        sourceRect = new Rectangle(newpositionX, newpositionY, newframeWidth, newframeHeight);
        frametime = newframetime
   }
enter code here

The difficulty is how to specify accurately the new position and the new frame time for each frame.

2
What do you mean constant duration ? Animation in xna is controlled by you, you choose how slow/fast it can loop and what the duration of the animation is.Lyuben Todorov
I mean frame duration. As you said, the entire loop can be set to fast or slow easily. But the difficulty is to set a different duration for each frame in the entire loop.Pilispring

2 Answers

1
votes

It's really up to you how you animate sprite sheets.

This tutorial shows a dancing smiley with a 4x4 sprite sheet. Thus it has 16 frames :

 | 1| 2| 3| 4|
 | 5| 6| 7| 8|
 | 9|10|11|12|
 |13|14|15|16|

The loop where the animation is done (in Update()):

public void Update()
{
    currentFrame++;
    if (currentFrame == totalFrames)
        currentFrame = 0;
}

If you want to use frames with odd numbers only 1,3,5,7,9,11,13,15 but not the even number frames then instead of currentFrame++; you would use currentFrame+=2

For a sprite sheet where the frames are of different height/width you could use scaling. How you navigate through the sprite sheet is up to you, meaning you are not restricted to a sprite sheet of same height/width.

As for the duration, in the tutorial I've linked you to will update the frames of the smiley as fast at it possibly can as there is no control implemented to deal with time delays (meaning updating every second or every .5 seconds) so in its current state the Draw() method will get called 60 times a sec.

1
votes

I did with this class

public void Update(GameTime gameTime) { currentAnimation = (currentAnimation + 1) % ExtractionXml.AnimationCount;

        elapsedTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;

        if (currentFrame == animationData.Animations[currentAnimation].Frames.Length)
        {
            if (Looping == true)
            currentFrame = 0;
        }

        if (elapsedTime > animationData.Animations[currentAnimation].Frames[currentFrame].Duration*1000 && currentFrame <= animationData.Animations[currentAnimation].Frames.Length-1)
        {
            Height = animationData.Animations[currentAnimation].Frames[currentFrame].Height;
            Width = animationData.Animations[currentAnimation].Frames[currentFrame].Width;
            X = animationData.Animations[currentAnimation].Frames[currentFrame].X;
            Y = animationData.Animations[currentAnimation].Frames[currentFrame].Y;

            sourceRect = new Rectangle(X, Y, Width, Height);
            //destinationRect = new Rectangle((int)Position.X - (int)(Width * scale) / 2, (int)Position.Y - (int)(Height * scale) / 2, (int)(Width * scale), (int)(Height * scale));
            destinationRect = new Rectangle(scale* ((int)Position.X - (animationData.Animations[currentAnimation].Frames[currentFrame].Width / 2) + (animationData.Animations[currentAnimation].Frames[currentFrame].OffSetX))
                                          , scale * ((int)Position.Y - (animationData.Animations[currentAnimation].Frames[currentFrame].Height / 2) + (animationData.Animations[currentAnimation].Frames[currentFrame].OffSetY))
                                          , scale * animationData.Animations[currentAnimation].Frames[currentFrame].Width
                                          , scale * animationData.Animations[currentAnimation].Frames[currentFrame].Height);
            //destinationRect = new Rectangle(0 , 0 , animationData.Animations[currentAnimation].Frames[currentFrame].Width, animationData.Animations[currentAnimation].Frames[currentFrame].Height);
            currentFrame++;
            elapsedTime = 0;
        }
    }