diff --git a/src/main/java/uno/mloluyu/desktop/GameCore.java b/src/main/java/uno/mloluyu/desktop/GameCore.java index db55da6..ce02cd9 100644 --- a/src/main/java/uno/mloluyu/desktop/GameCore.java +++ b/src/main/java/uno/mloluyu/desktop/GameCore.java @@ -16,11 +16,16 @@ public class GameCore implements ApplicationListener { @Override public void create() { alice1.create(); + } @Override public void render() { + Gdx.gl.glClearColor(150, 150, 150, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + alice1.update(Gdx.graphics.getDeltaTime()); alice1.render(); } diff --git a/src/main/java/uno/mloluyu/desktop/character/Alice.java b/src/main/java/uno/mloluyu/desktop/character/Alice.java index 8f47777..a88613c 100644 --- a/src/main/java/uno/mloluyu/desktop/character/Alice.java +++ b/src/main/java/uno/mloluyu/desktop/character/Alice.java @@ -1,112 +1,179 @@ package uno.mloluyu.desktop.character; +import uno.mloluyu.util.SimpleFormatter; + import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; public class Alice { private SpriteBatch batch; - private Sprite playerSprite; - private Texture playerTexture; + private Animation walkAnimation; // 行走动画 + private Animation idleAnimation; // idle动画 + private TextureRegion currentFrame; // 当前显示的帧 + private float stateTime; // 动画播放时间 + private String path = "character/alice/"; - private String textureFileName = "attackAa000.png"; private final float MOVEMENT_SPEED = 200f; private Vector2 position; + private float width; // 角色宽度 + private float height; // 角色高度 + private boolean isMoving = false; // 是否在移动 + private boolean isFacingRight = true; // 是否面朝右 - public void create(){ + public void create() { batch = new SpriteBatch(); - - // 验证文件是否存在 - String fullPath = path + textureFileName; - if (!Gdx.files.internal(fullPath).exists()) { - Gdx.app.error("Alice", "图片文件不存在: " + fullPath); - Gdx.app.error("Alice", "请检查文件是否放在 assets/" + fullPath); - return; - } - - try { - // 加载纹理并添加错误处理 - playerTexture = new Texture(Gdx.files.internal(fullPath)); - Gdx.app.log("Alice", "成功加载纹理: " + fullPath); - } catch (Exception e) { - Gdx.app.error("Alice", "加载纹理失败: " + e.getMessage()); - e.printStackTrace(); - return; - } - - // 从纹理创建精灵 - playerSprite = new Sprite(playerTexture); - - // 初始化位置向量 position = new Vector2(); - setSpriteToCenter(playerSprite); - - // 设置精灵的原点为中心 - playerSprite.setOriginCenter(); + + // 加载动画帧 + loadAnimations(); + + // 初始化位置(屏幕中心) + setToCenter(); } - private void setSpriteToCenter(Sprite sprite) { - if (sprite == null) return; // 防止空指针 - - float x = (Gdx.graphics.getWidth() - sprite.getWidth()) / 2f; - float y = (Gdx.graphics.getHeight() - sprite.getHeight()) / 2f; - sprite.setPosition(x, y); + /** + * 加载动画帧序列 + */ + private void loadAnimations() { + try { + // 1. 加载静止动画 + Array idleFrames = new Array<>(); + for (int i = 0; i < 16; i++) { + Texture texture = new Texture(Gdx.files.internal(path + "stand" + SimpleFormatter.addLeadingZeros(i,3) + ".png")); //文件路径 + System.out.println(texture); + idleFrames.add(new TextureRegion(texture)); + } + + idleAnimation = new Animation<>(0.1f, idleFrames, Animation.PlayMode.LOOP); // 每帧时间 + + // 2. 加载行走动画 + Array walkFrames = new Array<>(); + for (int i = 0; i < 5; i++) { + Texture texture = new Texture(Gdx.files.internal(path + "walkFront" + SimpleFormatter.addLeadingZeros(i,3) + ".png")); + System.out.println("调试代码"+texture); + walkFrames.add(new TextureRegion(texture)); + } + walkAnimation = new Animation<>(0.1f, walkFrames, Animation.PlayMode.LOOP); + + // 设置角色尺寸 + width = idleFrames.get(0).getRegionWidth(); + height = idleFrames.get(0).getRegionHeight(); + + Gdx.app.log("Alice", "动画加载成功"); + + } catch (Exception e) { + Gdx.app.error("Alice", "动画加载失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 设置角色到屏幕中心 + */ + private void setToCenter() { + float x = (Gdx.graphics.getWidth() - width) / 2f; + float y = (Gdx.graphics.getHeight() - height) / 2f; position.set(x, y); } + /** + * 更新逻辑和动画 + */ public void update(float deltaTime) { - if (playerSprite == null) return; // 资源未加载则不更新 - + if (idleAnimation == null) return; + + stateTime += deltaTime; + + handleMovement(deltaTime); + + if (isMoving) { + currentFrame = walkAnimation.getKeyFrame(stateTime); + } else { + currentFrame = idleAnimation.getKeyFrame(stateTime); + } + + if ((isFacingRight && currentFrame.isFlipX()) || + (!isFacingRight && !currentFrame.isFlipX())) { + currentFrame.flip(true, false); + } + } + + /** + * 处理移动逻辑 + */ + private void handleMovement(float deltaTime) { float moveX = 0; float moveY = 0; + isMoving = false; + // 方向键控制 if (Gdx.input.isKeyPressed(Input.Keys.UP)) { moveY += MOVEMENT_SPEED * deltaTime; + isMoving = true; } if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) { moveY -= MOVEMENT_SPEED * deltaTime; + isMoving = true; } if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { moveX += MOVEMENT_SPEED * deltaTime; + isMoving = true; + isFacingRight = true; // 朝右 } if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { moveX -= MOVEMENT_SPEED * deltaTime; + isMoving = true; + isFacingRight = false; // 朝左 } + // 更新位置并限制在屏幕内 position.add(moveX, moveY); clampPosition(); - playerSprite.setPosition(position.x, position.y); } + /** + * 限制在屏幕范围内 + */ private void clampPosition() { - if (playerSprite == null) return; - - float maxX = Gdx.graphics.getWidth() - playerSprite.getWidth(); - float maxY = Gdx.graphics.getHeight() - playerSprite.getHeight(); + float maxX = Gdx.graphics.getWidth() - width; + float maxY = Gdx.graphics.getHeight() - height; position.x = Math.max(0, Math.min(position.x, maxX)); position.y = Math.max(0, Math.min(position.y, maxY)); } + /** + * 渲染角色和动画 + */ public void render() { - if (batch == null || playerSprite == null) return; // 资源未准备好则不渲染 - + if (batch == null || currentFrame == null) return; batch.begin(); - playerSprite.draw(batch); + batch.draw(currentFrame, position.x, position.y); batch.end(); } + /** + * 释放资源 + */ public void dispose() { if (batch != null) { batch.dispose(); batch = null; } - if (playerTexture != null) { - playerTexture.dispose(); - playerTexture = null; + if (idleAnimation != null) { + for (TextureRegion region : idleAnimation.getKeyFrames()) { + region.getTexture().dispose(); + } + } + if (walkAnimation != null) { + for (TextureRegion region : walkAnimation.getKeyFrames()) { + region.getTexture().dispose(); + } } - playerSprite = null; } } diff --git a/src/main/java/uno/mloluyu/util/SimpleFormatter.java b/src/main/java/uno/mloluyu/util/SimpleFormatter.java new file mode 100644 index 0000000..74b697b --- /dev/null +++ b/src/main/java/uno/mloluyu/util/SimpleFormatter.java @@ -0,0 +1,19 @@ +package uno.mloluyu.util; +public class SimpleFormatter { + /** + * 简化版:数字补前导零 + * @param number 要格式化的数字(如1, 10) + * @param digits 保留的位数(如3位) + * @return 带前导零的字符串(1→"001",10→"010") + */ + public static String addLeadingZeros(int number, int digits) { + return String.format("%0" + digits + "d", number); + } + + // 测试 + public static void main(String[] args) { + for (int i = 1; i <= 15; i++) { + System.out.println(addLeadingZeros(i, 3)); + } + } +} diff --git a/target/classes/uno/mloluyu/desktop/GameCore.class b/target/classes/uno/mloluyu/desktop/GameCore.class index d97bbc1..67bd962 100644 Binary files a/target/classes/uno/mloluyu/desktop/GameCore.class and b/target/classes/uno/mloluyu/desktop/GameCore.class differ diff --git a/target/classes/uno/mloluyu/desktop/character/Alice.class b/target/classes/uno/mloluyu/desktop/character/Alice.class index a0fecfa..353d489 100644 Binary files a/target/classes/uno/mloluyu/desktop/character/Alice.class and b/target/classes/uno/mloluyu/desktop/character/Alice.class differ diff --git a/target/classes/uno/mloluyu/util/SimpleFormatter.class b/target/classes/uno/mloluyu/util/SimpleFormatter.class new file mode 100644 index 0000000..8c9bab2 Binary files /dev/null and b/target/classes/uno/mloluyu/util/SimpleFormatter.class differ