This commit is contained in:
2025-09-25 15:02:15 +08:00
parent 659827bcc3
commit 10238fa953
10 changed files with 234 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
package uno.mloluyu.characters;
public enum Action {
IDLE, WALK, JUMP, FALL,
ATTACK1, ATTACK2, ATTACK3, ATTACK4,
HIT, DEFEND,
SPECIAL1, SPECIAL2,
DEATH
}

View File

@@ -0,0 +1,82 @@
package uno.mloluyu.characters;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import uno.mloluyu.util.SimpleFormatter;
import java.util.EnumMap;
public class FighterAnimationManager {
private EnumMap<Action, Animation<TextureRegion>> animations = new EnumMap<>(Action.class);
private EnumMap<Action, Float> frameDurations = new EnumMap<>(Action.class);
private TextureAtlas atlas;
private float scaleX = 1.0f;
private float scaleY = 1.0f;
public FighterAnimationManager(TextureAtlas atlas) {
this.atlas = atlas;
for (Action action : Action.values()) {
frameDurations.put(action, 0.1f);
}
}
public void loadAnimation(Action action, String prefix, int count, boolean loop) {
Array<TextureRegion> frames = new Array<>();
for (int i = 0; i < count; i++) {
String regionName = prefix + SimpleFormatter.addLeadingZeros(i, 3);
TextureRegion region = atlas.findRegion(regionName);
if (region == null) {
throw new IllegalArgumentException("未找到区域: " + regionName);
}
frames.add(region);
}
Animation<TextureRegion> animation = new Animation<>(frameDurations.get(action), frames);
animation.setPlayMode(loop ? Animation.PlayMode.LOOP : Animation.PlayMode.NORMAL);
animations.put(action, animation);
}
public void loadLooping(Action action, String prefix, int count) {
loadAnimation(action, prefix, count, true);
}
public void loadOneShot(Action action, String prefix, int count) {
loadAnimation(action, prefix, count, false);
}
public void setFrameDuration(Action action, float duration) {
frameDurations.put(action, duration);
Animation<TextureRegion> anim = animations.get(action);
if (anim != null) anim.setFrameDuration(duration);
}
public boolean isFinished(Action action, float stateTime) {
Animation<TextureRegion> anim = animations.get(action);
return anim != null && anim.isAnimationFinished(stateTime);
}
public void render(SpriteBatch batch, Action action, float stateTime, Rectangle hitbox, boolean isFacingRight) {
Animation<TextureRegion> anim = animations.get(action);
if (anim == null) return;
TextureRegion frame = anim.getKeyFrame(stateTime, anim.getPlayMode() == Animation.PlayMode.LOOP);
if (frame == null) return;
float frameWidth = frame.getRegionWidth() * scaleX;
float frameHeight = frame.getRegionHeight() * scaleY;
float drawX = hitbox.x + (hitbox.width - frameWidth) / 2;
float drawY = hitbox.y;
boolean wasFlippedX = frame.isFlipX();
frame.flip(!isFacingRight && !wasFlippedX, false);
frame.flip(isFacingRight && wasFlippedX, false);
batch.draw(frame, drawX, drawY, frameWidth / 2, frameHeight / 2, frameWidth, frameHeight, 1f, 1f, 0f);
frame.flip(wasFlippedX != frame.isFlipX(), false);
}
public void dispose() {
if (atlas != null) atlas.dispose();
}
}

View File

@@ -0,0 +1,72 @@
package uno.mloluyu.characters.character;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import uno.mloluyu.characters.Fighter;
import uno.mloluyu.characters.Action;
/**
* Alice角色类继承自Fighter父类定义其专属属性和动画
*/
public class Alice extends Fighter {
private static final String ATLAS_PATH = "src/main/resources/character/alice/精灵1.2.atlas";
public Alice() {
super("Alice", new TextureAtlas(Gdx.files.internal(ATLAS_PATH)));
speed = 350f;
maxHealth = 90;
health = maxHealth;
attackPower = 12;
}
@Override
protected void loadAnimations() {
animationManager.loadLooping(Action.IDLE, "stand/stand", 15);
animationManager.loadLooping(Action.WALK, "walkFront/walkFront", 9);
animationManager.loadOneShot(Action.JUMP, "jump/jump", 8);
animationManager.loadOneShot(Action.FALL, "hitSpin/hitSpin", 5);
animationManager.loadOneShot(Action.ATTACK1, "attackAa/attackAa", 6);
animationManager.loadOneShot(Action.ATTACK2, "attackAb/attackAb", 6);
animationManager.loadOneShot(Action.ATTACK3, "attackAc/attackAc", 6);
animationManager.loadOneShot(Action.ATTACK4, "attackAd/attackAd", 6);
animationManager.loadOneShot(Action.HIT, "hitSpin/hitSpin", 5);
// animationManager.loadOneShot(Action.DEATH, "death/death", 8);
// 可选特殊动作(如资源存在可启用)
// animationManager.loadOneShot(Action.SPECIAL1, "special/special1", 6);
// animationManager.loadOneShot(Action.SPECIAL2, "special/special2", 6);
animationManager.setFrameDuration(Action.IDLE, 0.04f);
animationManager.setFrameDuration(Action.WALK, 0.08f);
animationManager.setFrameDuration(Action.ATTACK1, 0.07f);
animationManager.setFrameDuration(Action.SPECIAL2, 0.06f);
}
@Override
protected void handleMoveState() {
if (currentAction != Action.ATTACK1 &&
currentAction != Action.ATTACK2 &&
currentAction != Action.ATTACK3 &&
currentAction != Action.ATTACK4 &&
currentAction != Action.SPECIAL1 &&
currentAction != Action.SPECIAL2 &&
currentAction != Action.DEFEND &&
currentAction != Action.JUMP &&
currentAction != Action.FALL) {
changeAction(Action.WALK);
}
}
@Override
protected boolean canAttack() {
return super.canAttack() || currentAction == Action.JUMP || currentAction == Action.FALL;
}
public int getHp() {
return health;
}
}

View File

@@ -0,0 +1,10 @@
package uno.mloluyu.characters.character;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
public class FighterList {
public static final TextureAtlas aliceAtlas = new TextureAtlas(Gdx.files.internal("src\\main\\resources\\character\\alice\\alice.atlas"));
}