移动和待机动画
This commit is contained in:
@@ -17,10 +17,15 @@ public class GameCore implements ApplicationListener {
|
|||||||
public void create() {
|
public void create() {
|
||||||
alice1.create();
|
alice1.create();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
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();
|
alice1.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,112 +1,179 @@
|
|||||||
package uno.mloluyu.desktop.character;
|
package uno.mloluyu.desktop.character;
|
||||||
|
|
||||||
|
import uno.mloluyu.util.SimpleFormatter;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.Input;
|
import com.badlogic.gdx.Input;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
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.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
public class Alice {
|
public class Alice {
|
||||||
private SpriteBatch batch;
|
private SpriteBatch batch;
|
||||||
private Sprite playerSprite;
|
private Animation<TextureRegion> walkAnimation; // 行走动画
|
||||||
private Texture playerTexture;
|
private Animation<TextureRegion> idleAnimation; // idle动画
|
||||||
|
private TextureRegion currentFrame; // 当前显示的帧
|
||||||
|
private float stateTime; // 动画播放时间
|
||||||
|
|
||||||
private String path = "character/alice/";
|
private String path = "character/alice/";
|
||||||
private String textureFileName = "attackAa000.png";
|
|
||||||
private final float MOVEMENT_SPEED = 200f;
|
private final float MOVEMENT_SPEED = 200f;
|
||||||
private Vector2 position;
|
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();
|
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();
|
position = new Vector2();
|
||||||
setSpriteToCenter(playerSprite);
|
|
||||||
|
|
||||||
// 设置精灵的原点为中心
|
// 加载动画帧
|
||||||
playerSprite.setOriginCenter();
|
loadAnimations();
|
||||||
|
|
||||||
|
// 初始化位置(屏幕中心)
|
||||||
|
setToCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSpriteToCenter(Sprite sprite) {
|
/**
|
||||||
if (sprite == null) return; // 防止空指针
|
* 加载动画帧序列
|
||||||
|
*/
|
||||||
|
private void loadAnimations() {
|
||||||
|
try {
|
||||||
|
// 1. 加载静止动画
|
||||||
|
Array<TextureRegion> 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));
|
||||||
|
}
|
||||||
|
|
||||||
float x = (Gdx.graphics.getWidth() - sprite.getWidth()) / 2f;
|
idleAnimation = new Animation<>(0.1f, idleFrames, Animation.PlayMode.LOOP); // 每帧时间
|
||||||
float y = (Gdx.graphics.getHeight() - sprite.getHeight()) / 2f;
|
|
||||||
sprite.setPosition(x, y);
|
// 2. 加载行走动画
|
||||||
|
Array<TextureRegion> 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);
|
position.set(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新逻辑和动画
|
||||||
|
*/
|
||||||
public void update(float deltaTime) {
|
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 moveX = 0;
|
||||||
float moveY = 0;
|
float moveY = 0;
|
||||||
|
isMoving = false;
|
||||||
|
|
||||||
|
// 方向键控制
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
||||||
moveY += MOVEMENT_SPEED * deltaTime;
|
moveY += MOVEMENT_SPEED * deltaTime;
|
||||||
|
isMoving = true;
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
|
||||||
moveY -= MOVEMENT_SPEED * deltaTime;
|
moveY -= MOVEMENT_SPEED * deltaTime;
|
||||||
|
isMoving = true;
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
|
||||||
moveX += MOVEMENT_SPEED * deltaTime;
|
moveX += MOVEMENT_SPEED * deltaTime;
|
||||||
|
isMoving = true;
|
||||||
|
isFacingRight = true; // 朝右
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
|
||||||
moveX -= MOVEMENT_SPEED * deltaTime;
|
moveX -= MOVEMENT_SPEED * deltaTime;
|
||||||
|
isMoving = true;
|
||||||
|
isFacingRight = false; // 朝左
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新位置并限制在屏幕内
|
||||||
position.add(moveX, moveY);
|
position.add(moveX, moveY);
|
||||||
clampPosition();
|
clampPosition();
|
||||||
playerSprite.setPosition(position.x, position.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制在屏幕范围内
|
||||||
|
*/
|
||||||
private void clampPosition() {
|
private void clampPosition() {
|
||||||
if (playerSprite == null) return;
|
float maxX = Gdx.graphics.getWidth() - width;
|
||||||
|
float maxY = Gdx.graphics.getHeight() - height;
|
||||||
float maxX = Gdx.graphics.getWidth() - playerSprite.getWidth();
|
|
||||||
float maxY = Gdx.graphics.getHeight() - playerSprite.getHeight();
|
|
||||||
position.x = Math.max(0, Math.min(position.x, maxX));
|
position.x = Math.max(0, Math.min(position.x, maxX));
|
||||||
position.y = Math.max(0, Math.min(position.y, maxY));
|
position.y = Math.max(0, Math.min(position.y, maxY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染角色和动画
|
||||||
|
*/
|
||||||
public void render() {
|
public void render() {
|
||||||
if (batch == null || playerSprite == null) return; // 资源未准备好则不渲染
|
if (batch == null || currentFrame == null) return;
|
||||||
|
|
||||||
batch.begin();
|
batch.begin();
|
||||||
playerSprite.draw(batch);
|
batch.draw(currentFrame, position.x, position.y);
|
||||||
batch.end();
|
batch.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放资源
|
||||||
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (batch != null) {
|
if (batch != null) {
|
||||||
batch.dispose();
|
batch.dispose();
|
||||||
batch = null;
|
batch = null;
|
||||||
}
|
}
|
||||||
if (playerTexture != null) {
|
if (idleAnimation != null) {
|
||||||
playerTexture.dispose();
|
for (TextureRegion region : idleAnimation.getKeyFrames()) {
|
||||||
playerTexture = null;
|
region.getTexture().dispose();
|
||||||
}
|
}
|
||||||
playerSprite = null;
|
}
|
||||||
|
if (walkAnimation != null) {
|
||||||
|
for (TextureRegion region : walkAnimation.getKeyFrames()) {
|
||||||
|
region.getTexture().dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/main/java/uno/mloluyu/util/SimpleFormatter.java
Normal file
19
src/main/java/uno/mloluyu/util/SimpleFormatter.java
Normal file
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
BIN
target/classes/uno/mloluyu/util/SimpleFormatter.class
Normal file
BIN
target/classes/uno/mloluyu/util/SimpleFormatter.class
Normal file
Binary file not shown.
Reference in New Issue
Block a user