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

3
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

13
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="game" />
</profile>
</annotationProcessing>
</component>
</project>

7
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

20
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

12
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

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"));
}