Search code examples
androidanimationlibgdx

Loop animation once in LibGDX


I have an explosion animation i need to loop once and then dissapear, but is not working, This part its supposed to do the trick: birdAnimationHit.setPlayMode(Animation.NORMAL);

But it only shows the last image of the loop. Don't know what is wrong, here is my code

AssetLoader.java

public static void load() {
    texture = new Texture(Gdx.files.internal("data/texture.png"));
    texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

    dustHit1 = new TextureRegion(texture, 930, 154, 140, 158);
    dustHit1.flip(false, true);

    dustHit2 = new TextureRegion(texture, 1079, 154, 187, 158);
    dustHit2.flip(false, true);

    dustHit3 = new TextureRegion(texture, 1274, 154, 149, 158);
    dustHit3.flip(false, true);

    dustHit4 = new TextureRegion(texture, 1430, 154, 153, 158);
    dustHit4.flip(false, true);

    dustHit5 = new TextureRegion(texture, 1590, 154, 155, 158);
    dustHit5.flip(false, true);

    TextureRegion[] birdsHit = { dustHit1, dustHit2, dustHit3, dustHit4, dustHit5 };
    birdAnimationHit = new Animation(0.06f, birdsHit);
    birdAnimationHit.setPlayMode(Animation.NORMAL);
}

GameRenderer.java

private void drawBirdHit(float runTime) {

    batcher.draw(birdAnimationHit.getKeyFrame(runTime), bird.getX(),
            bird.getY(), bird.getWidth() / 2.0f,
            bird.getHeight() / 2.0f, bird.getWidth(), bird.getHeight(),
            1.4f, 1.4f, bird.getRotation());

}

Solution

  • You need to sum up the runTime inside of that logic. Else you always get the same frame. Take a look at the getKeyFrame method: (Marked the importend part for you)

    public TextureRegion getKeyFrame (float stateTime) {
        int frameNumber = getKeyFrameIndex(stateTime);
        return keyFrames[frameNumber];
    }
    
    public int getKeyFrameIndex (float stateTime) {
        if (keyFrames.length == 1) return 0;
    
        int frameNumber = (int)(stateTime / frameDuration); //this will always produce the same picture if you dont sum up the time!
        switch (playMode) {
        case NORMAL:
        frameNumber = Math.min(keyFrames.length - 1, frameNumber);
        break;
        case LOOP:
        frameNumber = frameNumber % keyFrames.length;
        break;
        case LOOP_PINGPONG:
        frameNumber = frameNumber % ((keyFrames.length * 2) - 2);
        if (frameNumber >= keyFrames.length) frameNumber = keyFrames.length - 2 - (frameNumber - keyFrames.length);
        break;
        case LOOP_RANDOM:
        frameNumber = MathUtils.random(keyFrames.length - 1);
        break;
        case REVERSED:
        frameNumber = Math.max(keyFrames.length - frameNumber - 1, 0);
        break;
        case LOOP_REVERSED:
        frameNumber = frameNumber % keyFrames.length;
        frameNumber = keyFrames.length - frameNumber - 1;
        break;
        }
        return frameNumber;
    }
    

    So hold somewhere a timer where you sumup the deltatimes

    and change your code to something like this:

    private void drawBirdHit(float runTime) {
        sum += runTime;
        batcher.draw(birdAnimationHit.getKeyFrame(sum), bird.getX(),
                bird.getY(), bird.getWidth() / 2.0f,
                bird.getHeight() / 2.0f, bird.getWidth(), bird.getHeight(),
                1.4f, 1.4f, bird.getRotation());
    }
    

    The Animation itself does not have a timer for that. You can just request the right keyframe depending on the past time, not on the current deltatime.