libGDX 精灵 sheet 二维动画
libGDX sprite sheet 2d animation
我正在尝试使用 libGDX 在 Java 中创建简单的 2d 游戏。
我坚持从 PNG 文件中的精灵 sheet 创建 2d 动画。
我有 AbstractScreen class,它为每个屏幕保存 'things'。
GameScreen class 用于绘制我的游戏和带有动画代码的 Player class。
玩家class来自https://github.com/libgdx/libgdx/wiki/2D-Animation例子。
首先我创建了 AbstractScreen 和 MainMenuScreen(基于 AbstractScreen)。它可以工作,但现在我正在尝试用我的动画播放器创建 GameScreen。出了点问题,因为我没有任何错误,并且播放器在应用程序屏幕上不可见。如何为我的应用程序的骨架正确实现 sprite sheet 动画?
我的游戏画面:
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();
}
}
我的抽象屏幕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);
}
}
我的播放器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);
}
}
更新 1
忍者游戏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));
}
}
对您的播放器进行小的修改class,以便它绘制播放器动画帧。您需要重载Actor 的draw
方法并绘制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());
}
}
编辑
您需要根据您的设备屏幕宽度和高度调整舞台视口的大小,因此覆盖 resize
方法,也无需调用 spritebatch 的 begin
和 end
。您正在使用拥有 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);
}
}
编辑 2
private void initPlayer() {
player = new Player();
player.setSize(100,150);
player.setDebug(true);
stage.addActor(player);
}
我正在尝试使用 libGDX 在 Java 中创建简单的 2d 游戏。 我坚持从 PNG 文件中的精灵 sheet 创建 2d 动画。
我有 AbstractScreen class,它为每个屏幕保存 'things'。
GameScreen class 用于绘制我的游戏和带有动画代码的 Player class。
玩家class来自https://github.com/libgdx/libgdx/wiki/2D-Animation例子。
首先我创建了 AbstractScreen 和 MainMenuScreen(基于 AbstractScreen)。它可以工作,但现在我正在尝试用我的动画播放器创建 GameScreen。出了点问题,因为我没有任何错误,并且播放器在应用程序屏幕上不可见。如何为我的应用程序的骨架正确实现 sprite sheet 动画?
我的游戏画面:
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();
}
}
我的抽象屏幕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);
}
}
我的播放器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);
}
}
更新 1
忍者游戏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));
}
}
对您的播放器进行小的修改class,以便它绘制播放器动画帧。您需要重载Actor 的draw
方法并绘制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());
}
}
编辑
您需要根据您的设备屏幕宽度和高度调整舞台视口的大小,因此覆盖 resize
方法,也无需调用 spritebatch 的 begin
和 end
。您正在使用拥有 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);
}
}
编辑 2
private void initPlayer() {
player = new Player();
player.setSize(100,150);
player.setDebug(true);
stage.addActor(player);
}