Search code examples
animationlibgdxtexturepacker

Animating sprites using single sprite sheet


I was previously animating different states of a sprite (standing/walking/jumping) by having a separate .png and a textureAtlas file for each of those state. It was working fine. Now I went and combined those seperate sheets into a single png and generated a single .pack file. Now I can access these states by region but they no longer animate? only the first sprite of each state gets drawn, not the entire animation.

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;

public class MyGdxGame extends ApplicationAdapter implements InputProcessor {
    private SpriteBatch batch;
    private TextureAtlas textureAtlas;
    private TextureAtlas textureAtlas2;
    private Animation animation;
    private Animation animation2;
    private Animation currentAnimation;
    private float elapsedTime = 0;

    @Override
    public void create() {
        batch = new SpriteBatch();
        textureAtlas = new TextureAtlas(Gdx.files.internal("Wolverine.txt"));
        animation = new Animation(1/7f, textureAtlas.findRegion("Standing"));
        animation2 = new Animation(1/7f, textureAtlas.findRegion("Walking"));
        currentAnimation = animation;

        Gdx.input.setInputProcessor(this);
    }

    @Override
    public void dispose() {
        batch.dispose();
        textureAtlas.dispose();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.begin();
        //sprite.draw(batch);
        elapsedTime += Gdx.graphics.getDeltaTime();
        batch.draw(currentAnimation.getKeyFrame(elapsedTime, true), 0, 0);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public boolean keyDown(int keycode) {
        if (keycode == Input.Keys.LEFT) {
            currentAnimation = animation2;
        }
            return true;

    }

    @Override
    public boolean keyUp(int keycode) {
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        return false;
    }
}

This is the data file I'm using with the spritesheet

Wolverine.png
size: 256, 256
format: RGBA8888
filter: Linear,Linear
repeat: none
Standing
  rotate: false
  xy: 0, 0
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 1
Standing
  rotate: false
  xy: 64, 0
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 2
Standing
  rotate: false
  xy: 128, 0
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 3
Walking
  rotate: false
  xy: 192, 0
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 1
Walking
  rotate: false
  xy: 0, 64
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 2
Walking
  rotate: false
  xy: 64, 64
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 3
Walking
  rotate: false
  xy: 128, 64
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 4
Walking
  rotate: false
  xy: 192, 64
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 5
Walking
  rotate: false
  xy: 0, 128
  size: 64, 64
  orig: 64, 64
  offset: 0, 0
  index: 6

Solution

  • The problem is that you are providing to the Animation constructor just one animation frame. To be precise you are using this constructor:

        public Animation(float frameDuration, TextureRegion... keyFrames)
    

    with only one frame. You need to pass to the Animation all frames that you want to be inside your animation.

    Inside your textureAtlas all Standing or Walking sprites are being name just Standing or Walking when actually they should be named for example

        Standing0
        Standing1
        Standing2
        ...
    

    and

        Walking0
        Walking1
        Walking2
        Walking3
        ...
    

    with order of they are in animation. Rename files of your animation like this before packing them into texture atlas or as a hot-fix you can just rename them inside your .pack file.

    Then you can use

        public Array<TextureAtlas.AtlasRegion> findRegions(java.lang.String name)
    

    method to get all Standing/Walking like frames to pass them to the Animation so:

        textureAtlas.findRegions("Standing")