add animation support
This commit is contained in:
@@ -32,6 +32,10 @@ public class AssetService implements Disposable {
|
||||
this.assetManager.load(atlasAsset.getPath(), TextureAtlas.class);
|
||||
}
|
||||
|
||||
public TextureAtlas get(AtlasAsset atlasAsset) {
|
||||
return this.assetManager.get(atlasAsset.getPath(), TextureAtlas.class);
|
||||
}
|
||||
|
||||
public boolean update() {
|
||||
return this.assetManager.update();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package io.github.com.quillraven.component;
|
||||
|
||||
import com.badlogic.ashley.core.Component;
|
||||
import com.badlogic.ashley.core.ComponentMapper;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation.PlayMode;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.github.com.quillraven.asset.AtlasAsset;
|
||||
import io.github.com.quillraven.component.Facing.FacingDirection;
|
||||
|
||||
public class Animation2D implements Component {
|
||||
public static final ComponentMapper<Animation2D> MAPPER = ComponentMapper.getFor(Animation2D.class);
|
||||
|
||||
private final AtlasAsset atlasAsset;
|
||||
private final String atlasKey;
|
||||
private AnimationType type;
|
||||
private FacingDirection direction;
|
||||
private PlayMode playMode;
|
||||
private float speed;
|
||||
private float stateTime;
|
||||
private Animation<TextureRegion> animation;
|
||||
private boolean dirty;
|
||||
|
||||
public Animation2D(AtlasAsset atlasAsset, String atlasKey, AnimationType type, PlayMode playMode, float speed) {
|
||||
this.atlasAsset = atlasAsset;
|
||||
this.atlasKey = atlasKey;
|
||||
this.type = type;
|
||||
this.playMode = playMode;
|
||||
this.speed = speed;
|
||||
this.stateTime = 0f;
|
||||
this.animation = null;
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
public void setAnimation(Animation<TextureRegion> animation, FacingDirection direction) {
|
||||
this.animation = animation;
|
||||
this.stateTime = 0f;
|
||||
this.direction = direction;
|
||||
this.dirty = false;
|
||||
}
|
||||
|
||||
public FacingDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public Animation<TextureRegion> getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
public AtlasAsset getAtlasAsset() {
|
||||
return atlasAsset;
|
||||
}
|
||||
|
||||
public String getAtlasKey() {
|
||||
return atlasKey;
|
||||
}
|
||||
|
||||
public void setType(AnimationType type) {
|
||||
this.type = type;
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
public AnimationType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public PlayMode getPlayMode() {
|
||||
return playMode;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setSpeed(float speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public void setPlayMode(PlayMode playMode) {
|
||||
this.playMode = playMode;
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
public float incAndGetStateTime(float deltaTime) {
|
||||
this.stateTime += deltaTime * speed;
|
||||
return this.stateTime;
|
||||
}
|
||||
|
||||
public enum AnimationType {
|
||||
IDLE,
|
||||
WALK;
|
||||
|
||||
private final String atlasKey;
|
||||
|
||||
AnimationType() {
|
||||
this.atlasKey = this.name().toLowerCase();
|
||||
}
|
||||
|
||||
public String getAtlasKey() {
|
||||
return atlasKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.github.com.quillraven.component;
|
||||
|
||||
import com.badlogic.ashley.core.Component;
|
||||
import com.badlogic.ashley.core.ComponentMapper;
|
||||
|
||||
public class Facing implements Component {
|
||||
public static final ComponentMapper<Facing> MAPPER = ComponentMapper.getFor(Facing.class);
|
||||
|
||||
private FacingDirection direction;
|
||||
|
||||
public Facing(FacingDirection direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public FacingDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(FacingDirection direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public enum FacingDirection {
|
||||
UP, DOWN, LEFT, RIGHT;
|
||||
|
||||
private final String atlasKey;
|
||||
|
||||
FacingDirection() {
|
||||
this.atlasKey = this.name().toLowerCase();
|
||||
}
|
||||
|
||||
public String getAtlasKey() {
|
||||
return atlasKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
public class Graphic implements Component {
|
||||
public static final ComponentMapper<Graphic> MAPPER = ComponentMapper.getFor(Graphic.class);
|
||||
|
||||
private final TextureRegion region;
|
||||
private TextureRegion region;
|
||||
private final Color color;
|
||||
|
||||
public Graphic(TextureRegion region, Color color) {
|
||||
@@ -16,6 +16,10 @@ public class Graphic implements Component {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public void setRegion(TextureRegion region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public TextureRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@@ -9,10 +9,11 @@ import com.badlogic.gdx.physics.box2d.World;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import io.github.com.quillraven.GdxGame;
|
||||
import io.github.com.quillraven.asset.MapAsset;
|
||||
import io.github.com.quillraven.system.AnimationSystem;
|
||||
import io.github.com.quillraven.system.CleanupSystem;
|
||||
import io.github.com.quillraven.system.PhysicDebugRenderSystem;
|
||||
import io.github.com.quillraven.system.RenderSystem;
|
||||
import io.github.com.quillraven.system.TiledServiceTestSystem;
|
||||
import io.github.com.quillraven.system.TestSystem;
|
||||
import io.github.com.quillraven.tiled.TiledAshleySpawner;
|
||||
import io.github.com.quillraven.tiled.TiledService;
|
||||
|
||||
@@ -32,9 +33,10 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld);
|
||||
|
||||
// add ECS systems
|
||||
this.engine.addSystem(new AnimationSystem(game.getAssetService()));
|
||||
this.engine.addSystem(new RenderSystem(game.getBatch(), game.getViewport(), game.getCamera()));
|
||||
this.engine.addSystem(new CleanupSystem());
|
||||
this.engine.addSystem(new TiledServiceTestSystem(this.tiledService));
|
||||
this.engine.addSystem(new TestSystem(this.tiledService));
|
||||
this.engine.addSystem(new PhysicDebugRenderSystem(this.physicWorld, game.getCamera()));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package io.github.com.quillraven.system;
|
||||
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.systems.IteratingSystem;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import io.github.com.quillraven.asset.AssetService;
|
||||
import io.github.com.quillraven.asset.AtlasAsset;
|
||||
import io.github.com.quillraven.component.Animation2D;
|
||||
import io.github.com.quillraven.component.Facing;
|
||||
import io.github.com.quillraven.component.Facing.FacingDirection;
|
||||
import io.github.com.quillraven.component.Graphic;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AnimationSystem extends IteratingSystem {
|
||||
private static final float FRAME_DURATION = 1 / 8f;
|
||||
|
||||
private final AssetService assetService;
|
||||
private final Map<CacheKey, Animation<TextureRegion>> animationCache;
|
||||
|
||||
public AnimationSystem(AssetService assetService) {
|
||||
super(Family.all(Animation2D.class, Graphic.class, Facing.class).get());
|
||||
this.assetService = assetService;
|
||||
this.animationCache = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processEntity(Entity entity, float deltaTime) {
|
||||
Animation2D animation2D = Animation2D.MAPPER.get(entity);
|
||||
FacingDirection facingDirection = Facing.MAPPER.get(entity).getDirection();
|
||||
final float stateTime;
|
||||
if (animation2D.isDirty() || facingDirection != animation2D.getDirection()) {
|
||||
updateAnimation(animation2D, facingDirection);
|
||||
stateTime = 0f;
|
||||
} else {
|
||||
stateTime = animation2D.incAndGetStateTime(deltaTime);
|
||||
}
|
||||
|
||||
Animation<TextureRegion> animation = animation2D.getAnimation();
|
||||
animation.setPlayMode(animation2D.getPlayMode());
|
||||
TextureRegion keyFrame = animation.getKeyFrame(stateTime);
|
||||
Graphic.MAPPER.get(entity).setRegion(keyFrame);
|
||||
}
|
||||
|
||||
private void updateAnimation(Animation2D animation2D, FacingDirection direction) {
|
||||
AtlasAsset atlasAsset = animation2D.getAtlasAsset();
|
||||
String atlasKey = animation2D.getAtlasKey();
|
||||
Animation2D.AnimationType type = animation2D.getType();
|
||||
CacheKey cacheKey = new CacheKey(atlasAsset, atlasKey, type, direction);
|
||||
Animation<TextureRegion> animation = animationCache.computeIfAbsent(cacheKey, key -> {
|
||||
TextureAtlas textureAtlas = this.assetService.get(atlasAsset);
|
||||
String combinedKey = atlasKey + "/" + type.getAtlasKey() + "_" + direction.getAtlasKey();
|
||||
Array<AtlasRegion> regions = textureAtlas.findRegions(combinedKey);
|
||||
if (regions.isEmpty()) {
|
||||
throw new GdxRuntimeException("No regions found for " + key);
|
||||
}
|
||||
return new Animation<>(FRAME_DURATION, regions);
|
||||
});
|
||||
animation2D.setAnimation(animation, direction);
|
||||
}
|
||||
|
||||
private record CacheKey(
|
||||
AtlasAsset atlasAsset,
|
||||
String atlasKey,
|
||||
Animation2D.AnimationType type,
|
||||
FacingDirection direction
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.github.com.quillraven.system;
|
||||
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.EntitySystem;
|
||||
import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.utils.ImmutableArray;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.maps.tiled.TiledMap;
|
||||
import io.github.com.quillraven.asset.MapAsset;
|
||||
import io.github.com.quillraven.component.Animation2D;
|
||||
import io.github.com.quillraven.component.Facing;
|
||||
import io.github.com.quillraven.component.Facing.FacingDirection;
|
||||
import io.github.com.quillraven.tiled.TiledService;
|
||||
|
||||
public class TestSystem extends EntitySystem {
|
||||
private final TiledService tiledService;
|
||||
|
||||
public TestSystem(TiledService tiledService) {
|
||||
super();
|
||||
this.tiledService = tiledService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float deltaTime) {
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.X)) {
|
||||
Gdx.app.debug("TiledServiceTestSystem", "Setting map to MAIN");
|
||||
TiledMap tiledMap = tiledService.loadMap(MapAsset.MAIN);
|
||||
tiledService.setMap(tiledMap);
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.C)) {
|
||||
Gdx.app.debug("TiledServiceTestSystem", "Setting map to SECOND");
|
||||
TiledMap tiledMap = tiledService.loadMap(MapAsset.SECOND);
|
||||
tiledService.setMap(tiledMap);
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.A)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Facing.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Facing.MAPPER.get(entity).setDirection(FacingDirection.LEFT);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.D)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Facing.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Facing.MAPPER.get(entity).setDirection(FacingDirection.RIGHT);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.S)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Facing.MAPPER.get(entity).setDirection(FacingDirection.DOWN);
|
||||
Animation2D.MAPPER.get(entity).setType(Animation2D.AnimationType.IDLE);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.Q)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Animation2D animation2D = Animation2D.MAPPER.get(entity);
|
||||
animation2D.setSpeed(animation2D.getSpeed() * 1.2f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.E)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Animation2D animation2D = Animation2D.MAPPER.get(entity);
|
||||
animation2D.setSpeed(animation2D.getSpeed() / 1.2f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.W)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Animation2D.MAPPER.get(entity).setPlayMode(Animation.PlayMode.LOOP_RANDOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.github.com.quillraven.system;
|
||||
|
||||
import com.badlogic.ashley.core.EntitySystem;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.maps.tiled.TiledMap;
|
||||
import io.github.com.quillraven.asset.MapAsset;
|
||||
import io.github.com.quillraven.tiled.TiledService;
|
||||
|
||||
public class TiledServiceTestSystem extends EntitySystem {
|
||||
private final TiledService tiledService;
|
||||
|
||||
public TiledServiceTestSystem(TiledService tiledService) {
|
||||
super();
|
||||
this.tiledService = tiledService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float deltaTime) {
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.X)) {
|
||||
Gdx.app.debug("TiledServiceTestSystem", "Setting map to MAIN");
|
||||
TiledMap tiledMap = tiledService.loadMap(MapAsset.MAIN);
|
||||
tiledService.setMap(tiledMap);
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.C)) {
|
||||
Gdx.app.debug("TiledServiceTestSystem", "Setting map to SECOND");
|
||||
TiledMap tiledMap = tiledService.loadMap(MapAsset.SECOND);
|
||||
tiledService.setMap(tiledMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,15 @@ package io.github.com.quillraven.tiled;
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.glutils.FileTextureData;
|
||||
import com.badlogic.gdx.maps.MapLayer;
|
||||
import com.badlogic.gdx.maps.MapObject;
|
||||
import com.badlogic.gdx.maps.MapObjects;
|
||||
import com.badlogic.gdx.maps.objects.RectangleMapObject;
|
||||
import com.badlogic.gdx.maps.tiled.TiledMap;
|
||||
import com.badlogic.gdx.maps.tiled.TiledMapTile;
|
||||
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
|
||||
import com.badlogic.gdx.maps.tiled.objects.TiledMapTileMapObject;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
@@ -19,6 +22,11 @@ import com.badlogic.gdx.physics.box2d.FixtureDef;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import io.github.com.quillraven.GdxGame;
|
||||
import io.github.com.quillraven.asset.AtlasAsset;
|
||||
import io.github.com.quillraven.component.Animation2D;
|
||||
import io.github.com.quillraven.component.Animation2D.AnimationType;
|
||||
import io.github.com.quillraven.component.Facing;
|
||||
import io.github.com.quillraven.component.Facing.FacingDirection;
|
||||
import io.github.com.quillraven.component.Graphic;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
import io.github.com.quillraven.component.Transform;
|
||||
@@ -48,6 +56,9 @@ public class TiledAshleySpawner {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTileLayer(TiledMapTileLayer tileLayer) {
|
||||
}
|
||||
|
||||
private void loadTriggerLayer(MapLayer triggerLayer) {
|
||||
for (MapObject mapObject : triggerLayer.getObjects()) {
|
||||
if (mapObject instanceof RectangleMapObject rectMapObj) {
|
||||
@@ -70,9 +81,6 @@ public class TiledAshleySpawner {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTileLayer(TiledMapTileLayer tileLayer) {
|
||||
}
|
||||
|
||||
private void loadObjectLayer(MapLayer objectLayer) {
|
||||
for (MapObject mapObject : objectLayer.getObjects()) {
|
||||
if (mapObject instanceof TiledMapTileMapObject tileMapObject) {
|
||||
@@ -97,12 +105,29 @@ public class TiledAshleySpawner {
|
||||
BodyDef.BodyType.DynamicBody,
|
||||
Vector2.Zero,
|
||||
entity);
|
||||
addEntityAnimation(tileMapObject.getTile(), entity);
|
||||
entity.add(new Facing(FacingDirection.DOWN));
|
||||
entity.add(new Graphic(textureRegion, Color.WHITE.cpy()));
|
||||
|
||||
this.engine.addEntity(entity);
|
||||
}
|
||||
|
||||
private void addEntityPhysic(MapObject mapObject, BodyDef.BodyType bodyType, Vector2 relativeTo, Entity entity) {
|
||||
private void addEntityAnimation(TiledMapTile tile, Entity entity) {
|
||||
String animationStr = tile.getProperties().get("animation", "", String.class);
|
||||
if (animationStr.isBlank()) {
|
||||
return;
|
||||
}
|
||||
AnimationType animationType = AnimationType.valueOf(animationStr);
|
||||
|
||||
String atlasAssetStr = tile.getProperties().get("atlasAsset", "", String.class);
|
||||
AtlasAsset atlasAsset = AtlasAsset.valueOf(atlasAssetStr);
|
||||
FileTextureData textureData = (FileTextureData) tile.getTextureRegion().getTexture().getTextureData();
|
||||
String atlasKey = textureData.getFileHandle().nameWithoutExtension();
|
||||
|
||||
entity.add(new Animation2D(atlasAsset, atlasKey, animationType, Animation.PlayMode.LOOP, 1f));
|
||||
}
|
||||
|
||||
private void addEntityPhysic(MapObject mapObject, @SuppressWarnings("SameParameterValue") BodyDef.BodyType bodyType, Vector2 relativeTo, Entity entity) {
|
||||
if (tmpMapObjects.getCount() > 0) tmpMapObjects.remove(0);
|
||||
|
||||
tmpMapObjects.add(mapObject);
|
||||
|
||||
Reference in New Issue
Block a user