Files
Game/src/main/java/uno/mloluyu/characters/SimpleFighter.java

223 lines
7.7 KiB
Java
Raw Normal View History

2025-09-25 14:57:01 +08:00
package uno.mloluyu.characters;
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Rectangle;
/**
* 简化版角色类仅包含移动攻击受击等基础功能
*/
public class SimpleFighter {
private String name; // 角色名称
private final Map<Integer, Float> keyPressDuration = new HashMap<>();
private Action currentAction = Action.IDLE; // 当前动作状态(待机、攻击、受击等)
private float verticalSpeed = 0f; // 垂直速度(可用于跳跃或下落)
private boolean isGrounded = true; // 是否在地面上
private Rectangle hitbox = new Rectangle(0, 0, 64, 128); // 碰撞盒,用于位置和受击判定
private Rectangle attackbox = new Rectangle(0, 0, 80, 80); // 攻击盒,用于攻击判定
private boolean isFacingRight = true; // 是否面向右侧
private float speed = 300f; // 移动速度(像素/秒)
private int health = 100; // 当前生命值
private int attackPower = 10; // 攻击力(暂未使用)
private boolean isAttacking = false; // 是否正在攻击(攻击状态标志)
private Iterable<Integer> pressedKeys = new HashMap<Integer, Float>().keySet(); // 初始化 pressedKeys
public SimpleFighter(String name) {
this.name = name; // 构造函数,初始化角色名称
2025-09-25 16:50:43 +08:00
}
private void processPressedKeys(float deltaTime) {
for (int keycode : pressedKeys) {
float currentDuration = keyPressDuration.getOrDefault(keycode, 0f);
currentDuration += deltaTime;
keyPressDuration.put(keycode, currentDuration);
handleInput(keycode, true, currentDuration);
}
2025-09-25 14:57:01 +08:00
}
public void update(float deltaTime) {
2025-09-25 16:50:43 +08:00
updateAttackbox("light"); // 默认使用普通攻击的攻击盒更新
2025-09-25 14:57:01 +08:00
// 攻击只持续一帧
if (isAttacking) {
isAttacking = false;
changeAction(Action.IDLE);
}
2025-09-25 16:50:43 +08:00
processPressedKeys(deltaTime);
2025-09-25 14:57:01 +08:00
// 垂直移动(跳跃或重力)
if (!isGrounded) {
2025-09-25 16:50:43 +08:00
verticalSpeed -= 2500 * deltaTime; // 简单重力模拟
2025-09-25 14:57:01 +08:00
hitbox.y += verticalSpeed * deltaTime;
if (hitbox.y <= 0) {
hitbox.y = 0;
verticalSpeed = 0;
isGrounded = true;
changeAction(Action.IDLE);
}
}
}
public void render(SpriteBatch batch, ShapeRenderer shapeRenderer) {
batch.end(); // 暂停 SpriteBatch 渲染,切换到 ShapeRenderer
System.out.println("人物状态" + currentAction);
boolean isAttacking = currentAction == Action.ATTACK;
shapeRenderer.begin(ShapeRenderer.ShapeType.Line); // 开始绘制线框
shapeRenderer.setColor(Color.BLUE); // 设置颜色为蓝色
shapeRenderer.rect(hitbox.x, hitbox.y, hitbox.width, hitbox.height); // 绘制碰撞盒
if (isAttacking) {
shapeRenderer.setColor(Color.RED); // 设置颜色为红色
2025-09-25 16:50:43 +08:00
shapeRenderer.rect(attackbox.x, attackbox.y, attackbox.width, attackbox.height); // 绘制攻击框
2025-09-25 14:57:01 +08:00
}
shapeRenderer.end(); // 结束 ShapeRenderer 渲染
batch.begin(); // 恢复 SpriteBatch 渲染
}
public void handleInput(int keycode, boolean isPressed, float duration) {
2025-09-25 16:50:43 +08:00
2025-09-25 14:57:01 +08:00
if (isPressed) {
if (keycode == Input.Keys.LEFT || keycode == Input.Keys.A) {
2025-09-25 16:50:43 +08:00
move(-1, Gdx.graphics.getDeltaTime());
2025-09-25 14:57:01 +08:00
} else if (keycode == Input.Keys.RIGHT || keycode == Input.Keys.D) {
2025-09-25 16:50:43 +08:00
move(1, Gdx.graphics.getDeltaTime());
2025-09-25 14:57:01 +08:00
}
2025-09-25 16:50:43 +08:00
if (isPressed && !isAttacking) {
if (keycode == Input.Keys.Z || keycode == Input.Keys.J) {
attack("light");
} else if (keycode == Input.Keys.X || keycode == Input.Keys.K) {
attack("heavy");
} else if (keycode == Input.Keys.SHIFT_LEFT || keycode == Input.Keys.SHIFT_RIGHT) {
attack("special");
} else if (keycode == Input.Keys.SPACE || keycode == Input.Keys.UP || keycode == Input.Keys.W) {
jump();
}
2025-09-25 14:57:01 +08:00
}
} else {
2025-09-25 16:50:43 +08:00
keyPressDuration.remove(keycode);
if ((keycode == Input.Keys.LEFT || keycode == Input.Keys.RIGHT || keycode == Input.Keys.A
|| keycode == Input.Keys.D) &&
getCurrentAction() == Action.MOVE) {
2025-09-25 14:57:01 +08:00
changeAction(Action.IDLE);
}
}
}
public void handleInput(int keycode, boolean isPressed) {
handleInput(keycode, isPressed, 0f); // 调用已有方法,补充默认持续时间
}
public Action getCurrentAction() {
return currentAction; // 获取当前动作状态
}
public void changeAction(Action newAction) {
this.currentAction = newAction; // 切换角色动作状态
}
public void jump() {
if (isGrounded) {
2025-09-25 16:50:43 +08:00
verticalSpeed = 1000f;
2025-09-25 14:57:01 +08:00
isGrounded = false;
2025-09-25 16:50:43 +08:00
System.out.println("跳跃高度: " + verticalSpeed);
2025-09-25 14:57:01 +08:00
changeAction(Action.JUMP);
}
}
public void move(float x, float deltaTime) {
if (x != 0) {
isFacingRight = x > 0;
hitbox.x += x * speed * deltaTime;
changeAction(Action.MOVE); // 移动时切换为 MOVE 状态
} else if (isGrounded && !isAttacking) {
changeAction(Action.IDLE); // 停止移动时恢复待机
}
}
2025-09-25 16:50:43 +08:00
private void updateAttackbox(String attackType) {
float offsetX;
float offsetY = 20; // 默认偏移量
float width = 80;
float height = 80;
switch (attackType) {
case "heavy":
offsetX = isFacingRight ? hitbox.width : -100;
offsetY = 40;
width = 100;
height = 100;
break;
case "light":
offsetX = isFacingRight ? hitbox.width - 10 : -attackbox.width + 10;
break;
case "special":
offsetX = isFacingRight ? hitbox.width + 20 : -attackbox.width - 20;
offsetY = 50;
width = 120;
height = 60;
break;
default:
offsetX = isFacingRight ? hitbox.width - 10 : -attackbox.width + 10;
}
attackbox.setPosition(hitbox.x + offsetX, hitbox.y + offsetY);
attackbox.setSize(width, height);
}
2025-09-25 14:57:01 +08:00
public void attack(String attackType) {
2025-09-25 16:50:43 +08:00
isAttacking = true;
changeAction(Action.ATTACK);
updateAttackbox(attackType); // 根据攻击类型更新攻击盒位置
2025-09-25 14:57:01 +08:00
}
public void takeHit(int damage) {
health = Math.max(0, health - damage); // 扣除生命值,最小为 0
changeAction(health > 0 ? Action.HIT : Action.DEAD); // 根据生命值切换为受击或死亡状态
}
public boolean isAlive() {
return health > 0; // 判断角色是否存活
}
public boolean isAttacking() {
return isAttacking; // 判断是否处于攻击状态
}
// 常用访问器
public Rectangle getHitbox() {
return hitbox; // 获取碰撞盒
}
public Rectangle getAttackbox() {
return attackbox; // 获取攻击盒
}
public int getHealth() {
return health; // 获取当前生命值
}
public String getName() {
return name; // 获取角色名称
}
public void setPosition(float x, float y) {
hitbox.setPosition(x, y); // 设置角色位置
}
}