Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimatedSprite displays first region of texture atlas before animation plays #929

Open
aconstas opened this issue Aug 6, 2024 · 1 comment

Comments

@aconstas
Copy link

aconstas commented Aug 6, 2024

Link to docs: https://www.monogameextended.net/docs/features/2d-animations/animatedsprite/

I was following the documentation but I'm seeing this issue where the first region of the atlas displays before the desired animation. In my code I've defined a sleep animation that does play, but before it plays the first region of the texture atlas (atlas) displays before.

@AristurtleDev: "The problem is how the AnimatedSprite(SpriteSheet, String) constructor is done when you call it by doing _dog = new AnimatedSprite(_spriteSheet, "sleep").

That constructor takes the _spriteSheet and calls the other constructor to set that up. Since AnimatedSprite is derived from Sprite, then it has to call the base constructor and pass in a texture to use, which just defaults to the first index in the texture atlas.

For right now, you should be able to fix this by instead doing the following workaround until a fix is pushed"

_dog = new AnimatedSprite(_spriteSheet);
_dog.SetAnimation("sleep");
@dev-ISO
Copy link

dev-ISO commented Aug 17, 2024

I ran into the same issue where the first region of the Texture2DAtlas was displaying before the desired animation and even with your workaround I still was running into this issue. I ended up having to fork and modify the source code to implement a working fix.

What I did to temporarily fix this was adding a custom constructor to AnimatedSprite to overwrite the broken one:

AnimatedSprite Broken Constructor:

public AnimatedSprite(SpriteSheet spriteSheet)
    : base(spriteSheet.TextureAtlas[0])
{
    ArgumentNullException.ThrowIfNull(spriteSheet);
    _spriteSheet = spriteSheet;
}

Custom AnimatedSprite Constructor Workaround

public AnimatedSprite(SpriteSheet spriteSheet, int textureAtlasRegionIndex)
    : base(spriteSheet.TextureAtlas[textureAtlasRegionIndex])
{
    ArgumentNullException.ThrowIfNull(spriteSheet);
    _spriteSheet = spriteSheet;
}

and adding two custom methods to SpriteSheet that I use to try and get the Index of the First Texture2DRegion for my targeted Animation Frame:

public bool TryGetAnimation(string name, out SpriteSheetAnimation animation)
{
    return _animations.TryGetValue(name, out animation);
}

public void GetAnimationFirstRegion(string name, out Texture2DRegion firstTextureRegion)
{
    TryGetAnimation(name, out SpriteSheetAnimation animation);
    var firstFrame = animation.Frames[0];
    int frameIndex = firstFrame.FrameIndex;
    firstTextureRegion = TextureAtlas.GetRegion(frameIndex);
}

So now when I create an AnimatedSprite I call these two methods with the name of the defined Animation which in your case was "sleep" and in my case its stored in the animationKey variable to get the first frame's index in the Texture Atlas and pass that to the new Animated Sprite like this :

mySpriteSheet.GetAnimationFirstRegion(animationKey, out Texture2DRegion firstTextureRegion);
int textureRegionIndex = mySpriteSheet.TextureAtlas.GetIndexOfRegion(firstTextureRegion.Name);

AnimatedSprite myAnimatedSprite = new AnimatedSprite(mySpriteSheet, textureRegionIndex);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants