简体   繁体   中英

libGDX sprite sheet 2d animation

I'm trying to create simple 2d game in Java with libGDX. I stuck on creating 2d animation from sprite sheet in PNG file.

I have AbstractScreen class which holds 'things' for every screen.

GameScreen class for drawing my game and Player class with animation code.

Player class is from https://github.com/libgdx/libgdx/wiki/2D-Animation example.

Firstly i created AbstractScreen and MainMenuScreen (based on AbstractScreen). It's works but now i'm trying to create GameScreen with my animated player. Something is wrong because i haven't any error and player is not visible on app screen. How to properly implement sprite sheet animation for skeleton of my app?

My game screen:

class GameScreen extends AbstractScreen {
Player player;

public GameScreen(NinjaGame game) {
    super(game);
    init();
}

@Override
protected void init() {
    initPlayer();
}

private void initPlayer() {
    player = new Player();
    player.setDebug(true);
    stage.addActor(player);
}

@Override
public void render(float delta) {
    super.render(delta);
    update();
    spriteBatch.begin();
    stage.draw();
    spriteBatch.end();
}

private void update() {
    stage.act();
    }
}

My AbstractScreen class:

public abstract class AbstractScreen implements Screen {
protected NinjaGame game;
protected Stage stage;
private OrthographicCamera camera;
protected SpriteBatch spriteBatch;

public AbstractScreen(NinjaGame game) {
    this.game = game;
    createCamera();
    /* Stage for actors */
    stage = new Stage(new StretchViewport(NinjaGame.SCREEN_WIDTH, NinjaGame.SCREEN_HEIGHT, camera));
    /* Batch for sprites */
    spriteBatch = new SpriteBatch();
    /* Stage takes user inputs */
    Gdx.input.setInputProcessor(stage);
    init();
}

protected abstract void init();

private void createCamera() {
    /* Orthographic means like in CAD drawings */
    camera = new OrthographicCamera();
    camera.setToOrtho(false, NinjaGame.SCREEN_WIDTH, NinjaGame.SCREEN_HEIGHT);
    camera.update();
}

/** Clean screen on black color between render frames */
private void clearScreen() {
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}

@Override
public void render(float delta) {
    clearScreen();
    camera.update();
    spriteBatch.setProjectionMatrix(camera.combined);
    }

}

My player class:

public class Player extends Actor {
private static final int FRAME_COLS = 10, FRAME_ROWS = 1;
Animation<TextureRegion> walkAnimation;
Texture walkSheet;
private final static int STARTING_X = 50;
private final static int STARTING_Y = 50;

public Player(){
    createIdleAnimation();
    this.setPosition(STARTING_X, STARTING_Y);
}

private void createIdleAnimation() {
    walkSheet = new Texture(Gdx.files.internal("sheets/ninja-idle-sheet.png"));

    TextureRegion[][] tmp = TextureRegion.split(walkSheet,
            walkSheet.getWidth() / FRAME_COLS,
            walkSheet.getHeight() / FRAME_ROWS);

    TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
    int index = 0;
    for (int i = 0; i < FRAME_ROWS; i++) {
        for (int j = 0; j < FRAME_COLS; j++) {
            walkFrames[index++] = tmp[i][j];
        }
    }

    walkAnimation = new Animation<TextureRegion>(0.025f, walkFrames);
}

@Override
public void act(float delta) {
    super.act(delta);
}

@Override
public void draw(Batch batch, float parentAlpha) {
    super.draw(batch, parentAlpha);
    }
}

UPDATE 1

NinjaGame class

public class NinjaGame extends Game{
public final static int SCREEN_WIDTH = 800;
public final static int SCREEN_HEIGHT = 480;
public final static String GAME_NAME = "ninja vs zombie";
private boolean paused;

@Override
public void create() {
    this.setScreen(new GameScreen(this));
}
}

Make small modification in your Player class so that it draw player Animation frame. You need to overloaded draw method of Actor and draw texture of Player.

public class Player extends Actor {
    private static final int FRAME_COLS = 10, FRAME_ROWS = 1;
    Animation<TextureRegion> walkAnimation;
    Texture walkSheet;
    private final static int STARTING_X = 50;
    private final static int STARTING_Y = 50;
    TextureRegion reg;
    float stateTime;

    public Player(){
        createIdleAnimation();
        this.setPosition(STARTING_X, STARTING_Y);
    }

    private void createIdleAnimation() {
        walkSheet = new Texture(Gdx.files.internal("sheets/ninja-idle-sheet.png"));

        TextureRegion[][] tmp = TextureRegion.split(walkSheet,
                walkSheet.getWidth() / FRAME_COLS,
                walkSheet.getHeight() / FRAME_ROWS);

        TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
        int index = 0;
        for (int i = 0; i < FRAME_ROWS; i++) {
            for (int j = 0; j < FRAME_COLS; j++) {
                walkFrames[index++] = tmp[i][j];
            }
        }

        walkAnimation = new Animation<TextureRegion>(0.025f, walkFrames);
        stateTime = 0f;
        reg=walkAnimation.getKeyFrame(0);
    }

    @Override
    public void act(float delta) {
        super.act(delta);

        stateTime += delta;
        reg = walkAnimation.getKeyFrame(stateTime,true);
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);

        Color color = getColor();
        batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
        batch.draw(reg,getX(),getY(),getWidth()/2,getHeight()/2,getWidth(),getHeight(),getScaleX(),getScaleY(),getRotation());
    }
}

EDIT

You need to resize viewport of stage according to your device screen width and height so override resize method and also no need to call begin and end of spritebatch. you're using stage that having own SpriteBatch

class GameScreen extends AbstractScreen {

  Player player;

  public GameScreen(NinjaGame game) {
    super(game);
    init();
  }

  @Override
  protected void init() {
    initPlayer();
  }

  private void initPlayer() {
    player = new Player();
    player.setDebug(true);
    stage.addActor(player);
  }

  @Override
  public void render(float delta) {
    super.render(delta);

    update();
    stage.draw();
  }

  private void update() {
    stage.act();
  }

  @Override
  public void resize(int width, int height){
    stage.getViewport().update(width,height);
  }
}

EDIT 2

private void initPlayer() {
     player = new Player();
     player.setSize(100,150);
     player.setDebug(true);
     stage.addActor(player);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM