add animated water ripple tile and a trap trigger
This commit is contained in:
@@ -3,6 +3,7 @@ package io.github.com.quillraven.asset;
|
||||
public enum SoundAsset {
|
||||
SWORD_HIT("sword_hit.wav"),
|
||||
LIFE_REG("life_reg.wav"),
|
||||
TRAP("trap.wav"),
|
||||
;
|
||||
|
||||
private final String path;
|
||||
|
||||
@@ -68,10 +68,6 @@ public class Animation2D implements Component {
|
||||
return playMode;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setSpeed(float speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.github.com.quillraven.component;
|
||||
|
||||
import com.badlogic.ashley.core.Component;
|
||||
import com.badlogic.ashley.core.ComponentMapper;
|
||||
import com.badlogic.gdx.maps.MapObject;
|
||||
|
||||
public class Tiled implements Component {
|
||||
public static final ComponentMapper<Tiled> MAPPER = ComponentMapper.getFor(Tiled.class);
|
||||
|
||||
private final int id;
|
||||
private final MapObject mapObjectRef;
|
||||
|
||||
public Tiled(MapObject mapObjectRef) {
|
||||
this.id = mapObjectRef.getProperties().get("id", -1, Integer.class);
|
||||
this.mapObjectRef = mapObjectRef;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public MapObject getMapObjectRef() {
|
||||
return mapObjectRef;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.github.com.quillraven.component;
|
||||
|
||||
import com.badlogic.ashley.core.Component;
|
||||
import com.badlogic.ashley.core.ComponentMapper;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
|
||||
public class Trigger implements Component {
|
||||
public static final ComponentMapper<Trigger> MAPPER = ComponentMapper.getFor(Trigger.class);
|
||||
|
||||
private final String name;
|
||||
private Entity triggeringEntity;
|
||||
|
||||
public Trigger(String name) {
|
||||
this.name = name;
|
||||
this.triggeringEntity = null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setTriggeringEntity(Entity triggeringEntity) {
|
||||
this.triggeringEntity = triggeringEntity;
|
||||
}
|
||||
|
||||
public Entity getTriggeringEntity() {
|
||||
return triggeringEntity;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,4 @@ public class IdleControllerState implements ControllerState {
|
||||
@Override
|
||||
public void keyDown(Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyUp(Command command) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ import io.github.com.quillraven.system.PhysicDebugRenderSystem;
|
||||
import io.github.com.quillraven.system.PhysicMoveSystem;
|
||||
import io.github.com.quillraven.system.PhysicSystem;
|
||||
import io.github.com.quillraven.system.RenderSystem;
|
||||
import io.github.com.quillraven.tiled.TiledAshleySpawner;
|
||||
import io.github.com.quillraven.system.TriggerSystem;
|
||||
import io.github.com.quillraven.tiled.TiledAshleyConfigurator;
|
||||
import io.github.com.quillraven.tiled.TiledService;
|
||||
import io.github.com.quillraven.ui.model.GameViewModel;
|
||||
import io.github.com.quillraven.ui.view.GameView;
|
||||
@@ -43,7 +44,7 @@ public class GameScreen extends ScreenAdapter {
|
||||
private final Viewport uiViewport;
|
||||
private final TiledService tiledService;
|
||||
private final Engine engine;
|
||||
private final TiledAshleySpawner tiledAshleySpawner;
|
||||
private final TiledAshleyConfigurator tiledAshleyConfigurator;
|
||||
private final World physicWorld;
|
||||
private final KeyboardController keyboardController;
|
||||
private final AudioService audioService;
|
||||
@@ -55,11 +56,11 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.skin = game.getAssetService().get(SkinAsset.DEFAULT);
|
||||
this.viewModel = new GameViewModel(game);
|
||||
this.audioService = game.getAudioService();
|
||||
this.tiledService = new TiledService(game.getAssetService());
|
||||
this.physicWorld = new World(Vector2.Zero, true);
|
||||
this.physicWorld.setAutoClearForces(false);
|
||||
this.tiledService = new TiledService(game.getAssetService(), this.physicWorld);
|
||||
this.engine = new Engine();
|
||||
this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld, this.game.getAssetService());
|
||||
this.tiledAshleyConfigurator = new TiledAshleyConfigurator(this.engine, this.physicWorld, this.game.getAssetService());
|
||||
this.keyboardController = new KeyboardController(GameControllerState.class, engine, null);
|
||||
|
||||
// add ECS systems
|
||||
@@ -67,6 +68,7 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.engine.addSystem(new PhysicSystem(physicWorld, 1 / 60f));
|
||||
this.engine.addSystem(new FacingSystem());
|
||||
this.engine.addSystem(new FsmSystem());
|
||||
this.engine.addSystem(new TriggerSystem(audioService));
|
||||
this.engine.addSystem(new LifeSystem(this.viewModel));
|
||||
this.engine.addSystem(new AnimationSystem(game.getAssetService()));
|
||||
this.engine.addSystem(new CameraSystem(game.getCamera()));
|
||||
@@ -83,12 +85,12 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.stage.addActor(new GameView(stage, skin, this.viewModel));
|
||||
|
||||
Consumer<TiledMap> renderConsumer = this.engine.getSystem(RenderSystem.class)::setMap;
|
||||
Consumer<TiledMap> ashleySpawnerConsumer = this.tiledAshleySpawner::loadMapObjects;
|
||||
Consumer<TiledMap> cameraConsumer = this.engine.getSystem(CameraSystem.class)::setMap;
|
||||
Consumer<TiledMap> audioConsumer = this.audioService::setMap;
|
||||
this.tiledService.setMapChangeConsumer(
|
||||
renderConsumer.andThen(ashleySpawnerConsumer).andThen(cameraConsumer).andThen(audioConsumer)
|
||||
);
|
||||
this.tiledService.setMapChangeConsumer(renderConsumer.andThen(cameraConsumer).andThen(audioConsumer));
|
||||
this.tiledService.setLoadTriggerConsumer(tiledAshleyConfigurator::onLoadTrigger);
|
||||
this.tiledService.setLoadObjectConsumer(tiledAshleyConfigurator::onLoadObject);
|
||||
this.tiledService.setLoadTileConsumer(tiledAshleyConfigurator::onLoadTile);
|
||||
|
||||
TiledMap startMap = this.tiledService.loadMap(MapAsset.MAIN);
|
||||
this.tiledService.setMap(startMap);
|
||||
|
||||
@@ -7,11 +7,17 @@ import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.systems.IteratingSystem;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.physics.box2d.Body;
|
||||
import com.badlogic.gdx.physics.box2d.Contact;
|
||||
import com.badlogic.gdx.physics.box2d.ContactImpulse;
|
||||
import com.badlogic.gdx.physics.box2d.ContactListener;
|
||||
import com.badlogic.gdx.physics.box2d.Manifold;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
import io.github.com.quillraven.component.Player;
|
||||
import io.github.com.quillraven.component.Transform;
|
||||
import io.github.com.quillraven.component.Trigger;
|
||||
|
||||
public class PhysicSystem extends IteratingSystem implements EntityListener {
|
||||
public class PhysicSystem extends IteratingSystem implements EntityListener, ContactListener {
|
||||
|
||||
private final World world;
|
||||
private final float interval;
|
||||
@@ -22,6 +28,7 @@ public class PhysicSystem extends IteratingSystem implements EntityListener {
|
||||
this.world = world;
|
||||
this.interval = interval;
|
||||
this.accumulator = 0f;
|
||||
world.setContactListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,4 +93,42 @@ public class PhysicSystem extends IteratingSystem implements EntityListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginContact(Contact contact) {
|
||||
Object userDataA = contact.getFixtureA().getBody().getUserData();
|
||||
Object userDataB = contact.getFixtureB().getBody().getUserData();
|
||||
|
||||
if (!(userDataA instanceof Entity entityA) || !(userDataB instanceof Entity entityB)) {
|
||||
return;
|
||||
}
|
||||
|
||||
playerTriggerContact(entityA, entityB);
|
||||
}
|
||||
|
||||
private static void playerTriggerContact(Entity entityA, Entity entityB) {
|
||||
Trigger trigger = Trigger.MAPPER.get(entityA);
|
||||
boolean isPlayer = Player.MAPPER.get(entityB) != null;
|
||||
if (trigger != null && isPlayer) {
|
||||
trigger.setTriggeringEntity(entityB);
|
||||
return;
|
||||
}
|
||||
|
||||
trigger = Trigger.MAPPER.get(entityB);
|
||||
isPlayer = Player.MAPPER.get(entityA) != null;
|
||||
if (trigger != null && isPlayer) {
|
||||
trigger.setTriggeringEntity(entityA);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endContact(Contact contact) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSolve(Contact contact, Manifold oldManifold) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postSolve(Contact contact, ContactImpulse impulse) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
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.ashley.utils.ImmutableArray;
|
||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.badlogic.gdx.utils.Timer;
|
||||
import io.github.com.quillraven.asset.SoundAsset;
|
||||
import io.github.com.quillraven.audio.AudioService;
|
||||
import io.github.com.quillraven.component.Animation2D;
|
||||
import io.github.com.quillraven.component.Life;
|
||||
import io.github.com.quillraven.component.Tiled;
|
||||
import io.github.com.quillraven.component.Trigger;
|
||||
|
||||
public class TriggerSystem extends IteratingSystem {
|
||||
private final AudioService audioService;
|
||||
|
||||
public TriggerSystem(AudioService audioService) {
|
||||
super(Family.all(Trigger.class).get());
|
||||
this.audioService = audioService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processEntity(Entity entity, float deltaTime) {
|
||||
Trigger trigger = Trigger.MAPPER.get(entity);
|
||||
if (trigger.getTriggeringEntity() == null) return;
|
||||
|
||||
fireTrigger(trigger.getName(), trigger.getTriggeringEntity());
|
||||
trigger.setTriggeringEntity(null);
|
||||
}
|
||||
|
||||
private Entity getByTiledId(int tiledId) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Tiled.class).get());
|
||||
for (Entity entity : entities) {
|
||||
if (Tiled.MAPPER.get(entity).getId() == tiledId) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void fireTrigger(String triggerName, Entity triggeringEntity) {
|
||||
switch (triggerName) {
|
||||
case "trap_trigger" -> trapTrigger(triggeringEntity);
|
||||
default -> throw new GdxRuntimeException("Unsupported trigger: " + triggerName);
|
||||
}
|
||||
}
|
||||
|
||||
private void trapTrigger(Entity triggeringEntity) {
|
||||
Entity trapEntity = getByTiledId(15);
|
||||
if (trapEntity != null) {
|
||||
// play trap animation
|
||||
Animation2D animation2D = Animation2D.MAPPER.get(trapEntity);
|
||||
animation2D.setSpeed(1f);
|
||||
animation2D.setPlayMode(Animation.PlayMode.NORMAL);
|
||||
audioService.playSound(SoundAsset.TRAP);
|
||||
// reset animation
|
||||
Timer.schedule(new Timer.Task() {
|
||||
@Override
|
||||
public void run() {
|
||||
animation2D.setSpeed(0f);
|
||||
animation2D.setType(Animation2D.AnimationType.IDLE);
|
||||
}
|
||||
}, 2.5f);
|
||||
|
||||
// damage player
|
||||
Life life = Life.MAPPER.get(triggeringEntity);
|
||||
if (life.getLife() > 2) {
|
||||
life.addLife(-2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,10 @@ import com.badlogic.gdx.graphics.g2d.Animation;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
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;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
@@ -21,7 +18,6 @@ import com.badlogic.gdx.physics.box2d.Body;
|
||||
import com.badlogic.gdx.physics.box2d.BodyDef;
|
||||
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
|
||||
import com.badlogic.gdx.physics.box2d.FixtureDef;
|
||||
import com.badlogic.gdx.physics.box2d.PolygonShape;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import io.github.com.quillraven.GdxGame;
|
||||
@@ -39,10 +35,12 @@ import io.github.com.quillraven.component.Life;
|
||||
import io.github.com.quillraven.component.Move;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
import io.github.com.quillraven.component.Player;
|
||||
import io.github.com.quillraven.component.Tiled;
|
||||
import io.github.com.quillraven.component.Transform;
|
||||
import io.github.com.quillraven.component.Trigger;
|
||||
|
||||
public class TiledAshleySpawner {
|
||||
private static final Vector2 DEFAULT_SCALING = new Vector2(1f, 1f);
|
||||
public class TiledAshleyConfigurator {
|
||||
private static final Vector2 DEFAULT_PHYSIC_SCALING = new Vector2(1f, 1f);
|
||||
|
||||
private final Engine engine;
|
||||
private final World physicWorld;
|
||||
@@ -50,7 +48,7 @@ public class TiledAshleySpawner {
|
||||
private final Vector2 tmpVec2;
|
||||
private final AssetService assetService;
|
||||
|
||||
public TiledAshleySpawner(Engine engine, World physicWorld, AssetService assetService) {
|
||||
public TiledAshleyConfigurator(Engine engine, World physicWorld, AssetService assetService) {
|
||||
this.engine = engine;
|
||||
this.physicWorld = physicWorld;
|
||||
this.tmpMapObjects = new MapObjects();
|
||||
@@ -58,120 +56,49 @@ public class TiledAshleySpawner {
|
||||
this.assetService = assetService;
|
||||
}
|
||||
|
||||
public void loadMapObjects(TiledMap tiledMap) {
|
||||
for (MapLayer layer : tiledMap.getLayers()) {
|
||||
if (layer instanceof TiledMapTileLayer tileLayer) {
|
||||
loadTileLayer(tileLayer);
|
||||
} else if ("objects".equals(layer.getName())) {
|
||||
loadObjectLayer(layer);
|
||||
} else if ("trigger".equals(layer.getName())) {
|
||||
loadTriggerLayer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
spawnMapBoundary(tiledMap);
|
||||
public void onLoadTile(TiledMapTile tile, float x, float y) {
|
||||
createBody(tile.getObjects(),
|
||||
new Vector2(x, y),
|
||||
DEFAULT_PHYSIC_SCALING,
|
||||
BodyDef.BodyType.StaticBody,
|
||||
Vector2.Zero,
|
||||
"environment");
|
||||
}
|
||||
|
||||
private void spawnMapBoundary(TiledMap tiledMap) {
|
||||
// create four boxes for the map boundary (left, right, bottom and top edge)
|
||||
int width = tiledMap.getProperties().get("width", 0, Integer.class);
|
||||
int tileW = tiledMap.getProperties().get("tilewidth", 0, Integer.class);
|
||||
int height = tiledMap.getProperties().get("height", 0, Integer.class);
|
||||
int tileH = tiledMap.getProperties().get("tileheight", 0, Integer.class);
|
||||
float mapW = width * tileW * GdxGame.UNIT_SCALE;
|
||||
float mapH = height * tileH * GdxGame.UNIT_SCALE;
|
||||
float halfW = mapW * 0.5f;
|
||||
float halfH = mapH * 0.5f;
|
||||
float boxThickness = 0.5f;
|
||||
|
||||
BodyDef bodyDef = new BodyDef();
|
||||
bodyDef.type = BodyType.StaticBody;
|
||||
bodyDef.position.setZero();
|
||||
bodyDef.fixedRotation = true;
|
||||
Body body = physicWorld.createBody(bodyDef);
|
||||
|
||||
// left edge
|
||||
PolygonShape shape = new PolygonShape();
|
||||
shape.setAsBox(boxThickness, halfH, new Vector2(-boxThickness, halfH), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// right edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(boxThickness, halfH, new Vector2(mapW + boxThickness, halfH), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// bottom edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(halfW, boxThickness, new Vector2(halfW, -boxThickness), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// top edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(halfW, boxThickness, new Vector2(halfW, mapH + boxThickness), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
}
|
||||
|
||||
private void loadTileLayer(TiledMapTileLayer tileLayer) {
|
||||
for (int y = 0; y < tileLayer.getHeight(); y++) {
|
||||
for (int x = 0; x < tileLayer.getWidth(); x++) {
|
||||
TiledMapTileLayer.Cell cell = tileLayer.getCell(x, y);
|
||||
if (cell == null) continue;
|
||||
|
||||
TiledMapTile tile = cell.getTile();
|
||||
createBody(tile.getObjects(),
|
||||
new Vector2(x, y),
|
||||
DEFAULT_SCALING,
|
||||
BodyType.StaticBody,
|
||||
Vector2.Zero,
|
||||
"environment");
|
||||
}
|
||||
public void onLoadTrigger(String triggerName, MapObject mapObject) {
|
||||
if (mapObject instanceof RectangleMapObject rectMapObj) {
|
||||
Entity entity = this.engine.createEntity();
|
||||
Rectangle rect = rectMapObj.getRectangle();
|
||||
addEntityTransform(
|
||||
rect.getX(), rect.getY(), 0,
|
||||
rect.getWidth(), rect.getHeight(),
|
||||
1f, 1f,
|
||||
0,
|
||||
entity);
|
||||
addEntityPhysic(
|
||||
rectMapObj,
|
||||
BodyDef.BodyType.StaticBody,
|
||||
tmpVec2.set(rect.getX(), rect.getY()).scl(GdxGame.UNIT_SCALE),
|
||||
entity);
|
||||
entity.add(new Trigger(triggerName));
|
||||
entity.add(new Tiled(rectMapObj));
|
||||
this.engine.addEntity(entity);
|
||||
} else {
|
||||
throw new GdxRuntimeException("Unsupported map object type for trigger: " + mapObject.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTriggerLayer(MapLayer triggerLayer) {
|
||||
for (MapObject mapObject : triggerLayer.getObjects()) {
|
||||
if (mapObject instanceof RectangleMapObject rectMapObj) {
|
||||
Entity entity = this.engine.createEntity();
|
||||
Rectangle rect = rectMapObj.getRectangle();
|
||||
addEntityTransform(
|
||||
rect.getX(), rect.getY(),
|
||||
rect.getWidth(), rect.getHeight(),
|
||||
1f, 1f,
|
||||
0,
|
||||
entity);
|
||||
addEntityPhysic(
|
||||
rectMapObj,
|
||||
BodyType.StaticBody,
|
||||
tmpVec2.set(rect.getX(), rect.getY()).scl(GdxGame.UNIT_SCALE),
|
||||
entity);
|
||||
this.engine.addEntity(entity);
|
||||
} else {
|
||||
throw new GdxRuntimeException("Unsupported trigger: " + mapObject.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadObjectLayer(MapLayer objectLayer) {
|
||||
for (MapObject mapObject : objectLayer.getObjects()) {
|
||||
if (mapObject instanceof TiledMapTileMapObject tileMapObject) {
|
||||
spawnEntityOf(tileMapObject);
|
||||
} else {
|
||||
throw new GdxRuntimeException("Unsupported object: " + mapObject.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnEntityOf(TiledMapTileMapObject tileMapObject) {
|
||||
public void onLoadObject(TiledMapTileMapObject tileMapObject) {
|
||||
Entity entity = this.engine.createEntity();
|
||||
TiledMapTile tile = tileMapObject.getTile();
|
||||
TextureRegion textureRegion = getTextureRegion(tile);
|
||||
String classType = tile.getProperties().get("type", "", String.class);
|
||||
float sortOffsetY = tile.getProperties().get("sortOffsetY", 0, Integer.class);
|
||||
sortOffsetY *= GdxGame.UNIT_SCALE;
|
||||
int z = tile.getProperties().get("z", 1, Integer.class);
|
||||
|
||||
addEntityTransform(
|
||||
tileMapObject.getX(), tileMapObject.getY(),
|
||||
tileMapObject.getX(), tileMapObject.getY(), z,
|
||||
textureRegion.getRegionWidth(), textureRegion.getRegionHeight(),
|
||||
tileMapObject.getScaleX(), tileMapObject.getScaleY(),
|
||||
sortOffsetY,
|
||||
@@ -190,6 +117,7 @@ public class TiledAshleySpawner {
|
||||
entity.add(new Facing(FacingDirection.DOWN));
|
||||
entity.add(new Fsm(entity));
|
||||
entity.add(new Graphic(textureRegion, Color.WHITE.cpy()));
|
||||
entity.add(new Tiled(tileMapObject));
|
||||
|
||||
this.engine.addEntity(entity);
|
||||
}
|
||||
@@ -258,8 +186,9 @@ public class TiledAshleySpawner {
|
||||
AtlasAsset atlasAsset = AtlasAsset.valueOf(atlasAssetStr);
|
||||
FileTextureData textureData = (FileTextureData) tile.getTextureRegion().getTexture().getTextureData();
|
||||
String atlasKey = textureData.getFileHandle().nameWithoutExtension();
|
||||
float speed = tile.getProperties().get("animationSpeed", 0f, Float.class);
|
||||
|
||||
entity.add(new Animation2D(atlasAsset, atlasKey, animationType, Animation.PlayMode.LOOP, 1f));
|
||||
entity.add(new Animation2D(atlasAsset, atlasKey, animationType, Animation.PlayMode.LOOP, speed));
|
||||
}
|
||||
|
||||
private void addEntityPhysic(MapObject mapObject, @SuppressWarnings("SameParameterValue") BodyType bodyType, Vector2 relativeTo, Entity entity) {
|
||||
@@ -305,7 +234,7 @@ public class TiledAshleySpawner {
|
||||
}
|
||||
|
||||
private static void addEntityTransform(
|
||||
float x, float y,
|
||||
float x, float y, int z,
|
||||
float w, float h,
|
||||
float scaleX, float scaleY,
|
||||
float sortOffsetY,
|
||||
@@ -318,7 +247,7 @@ public class TiledAshleySpawner {
|
||||
position.scl(GdxGame.UNIT_SCALE);
|
||||
size.scl(GdxGame.UNIT_SCALE);
|
||||
|
||||
entity.add(new Transform(position, 0, size, scaling, 0f, sortOffsetY));
|
||||
entity.add(new Transform(position, z, size, scaling, 0f, sortOffsetY));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +1,43 @@
|
||||
package io.github.com.quillraven.tiled;
|
||||
|
||||
import com.badlogic.gdx.maps.MapLayer;
|
||||
import com.badlogic.gdx.maps.MapObject;
|
||||
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.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.Body;
|
||||
import com.badlogic.gdx.physics.box2d.BodyDef;
|
||||
import com.badlogic.gdx.physics.box2d.PolygonShape;
|
||||
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.AssetService;
|
||||
import io.github.com.quillraven.asset.MapAsset;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TiledService {
|
||||
private final AssetService assetService;
|
||||
private Consumer<TiledMap> mapChangeConsumer;
|
||||
private final World physicWorld;
|
||||
|
||||
private TiledMap currentMap;
|
||||
|
||||
public TiledService(AssetService assetService) {
|
||||
private Consumer<TiledMap> mapChangeConsumer;
|
||||
private BiConsumer<String, MapObject> loadTriggerConsumer;
|
||||
private Consumer<TiledMapTileMapObject> loadObjectConsumer;
|
||||
private LoadTileConsumer loadTileConsumer;
|
||||
|
||||
public TiledService(AssetService assetService, World physicWorld) {
|
||||
this.assetService = assetService;
|
||||
this.physicWorld = physicWorld;
|
||||
this.mapChangeConsumer = null;
|
||||
this.loadTriggerConsumer = null;
|
||||
this.loadObjectConsumer = null;
|
||||
this.loadTileConsumer = null;
|
||||
this.currentMap = null;
|
||||
}
|
||||
|
||||
@@ -29,6 +53,7 @@ public class TiledService {
|
||||
}
|
||||
|
||||
this.currentMap = tiledMap;
|
||||
loadMapObjects(tiledMap);
|
||||
if (this.mapChangeConsumer != null) {
|
||||
this.mapChangeConsumer.accept(tiledMap);
|
||||
}
|
||||
@@ -37,4 +62,116 @@ public class TiledService {
|
||||
public void setMapChangeConsumer(Consumer<TiledMap> mapChangeConsumer) {
|
||||
this.mapChangeConsumer = mapChangeConsumer;
|
||||
}
|
||||
|
||||
public void setLoadObjectConsumer(Consumer<TiledMapTileMapObject> loadObjectConsumer) {
|
||||
this.loadObjectConsumer = loadObjectConsumer;
|
||||
}
|
||||
|
||||
public void setLoadTriggerConsumer(BiConsumer<String, MapObject> loadTriggerConsumer) {
|
||||
this.loadTriggerConsumer = loadTriggerConsumer;
|
||||
}
|
||||
|
||||
public void setLoadTileConsumer(LoadTileConsumer loadTileConsumer) {
|
||||
this.loadTileConsumer = loadTileConsumer;
|
||||
}
|
||||
|
||||
public void loadMapObjects(TiledMap tiledMap) {
|
||||
for (MapLayer layer : tiledMap.getLayers()) {
|
||||
if (layer instanceof TiledMapTileLayer tileLayer) {
|
||||
loadTileLayer(tileLayer);
|
||||
} else if ("objects".equals(layer.getName())) {
|
||||
loadObjectLayer(layer);
|
||||
} else if ("trigger".equals(layer.getName())) {
|
||||
loadTriggerLayer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
spawnMapBoundary(tiledMap);
|
||||
}
|
||||
|
||||
private void spawnMapBoundary(TiledMap tiledMap) {
|
||||
// create four boxes for the map boundary (left, right, bottom and top edge)
|
||||
int width = tiledMap.getProperties().get("width", 0, Integer.class);
|
||||
int tileW = tiledMap.getProperties().get("tilewidth", 0, Integer.class);
|
||||
int height = tiledMap.getProperties().get("height", 0, Integer.class);
|
||||
int tileH = tiledMap.getProperties().get("tileheight", 0, Integer.class);
|
||||
float mapW = width * tileW * GdxGame.UNIT_SCALE;
|
||||
float mapH = height * tileH * GdxGame.UNIT_SCALE;
|
||||
float halfW = mapW * 0.5f;
|
||||
float halfH = mapH * 0.5f;
|
||||
float boxThickness = 0.5f;
|
||||
|
||||
BodyDef bodyDef = new BodyDef();
|
||||
bodyDef.type = BodyDef.BodyType.StaticBody;
|
||||
bodyDef.position.setZero();
|
||||
bodyDef.fixedRotation = true;
|
||||
Body body = physicWorld.createBody(bodyDef);
|
||||
|
||||
// left edge
|
||||
PolygonShape shape = new PolygonShape();
|
||||
shape.setAsBox(boxThickness, halfH, new Vector2(-boxThickness, halfH), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// right edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(boxThickness, halfH, new Vector2(mapW + boxThickness, halfH), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// bottom edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(halfW, boxThickness, new Vector2(halfW, -boxThickness), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
// top edge
|
||||
shape = new PolygonShape();
|
||||
shape.setAsBox(halfW, boxThickness, new Vector2(halfW, mapH + boxThickness), 0f);
|
||||
body.createFixture(shape, 0f).setFriction(0f);
|
||||
shape.dispose();
|
||||
}
|
||||
|
||||
private void loadTileLayer(TiledMapTileLayer tileLayer) {
|
||||
if (loadTileConsumer == null) return;
|
||||
|
||||
for (int y = 0; y < tileLayer.getHeight(); y++) {
|
||||
for (int x = 0; x < tileLayer.getWidth(); x++) {
|
||||
TiledMapTileLayer.Cell cell = tileLayer.getCell(x, y);
|
||||
if (cell == null) continue;
|
||||
|
||||
loadTileConsumer.accept(cell.getTile(), x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTriggerLayer(MapLayer triggerLayer) {
|
||||
if (loadTriggerConsumer == null) return;
|
||||
|
||||
for (MapObject mapObject : triggerLayer.getObjects()) {
|
||||
if (mapObject.getName() == null || mapObject.getName().isBlank()) {
|
||||
throw new GdxRuntimeException("Trigger must have a name: " + mapObject);
|
||||
}
|
||||
|
||||
if (mapObject instanceof RectangleMapObject rectMapObj) {
|
||||
loadTriggerConsumer.accept(mapObject.getName(), rectMapObj);
|
||||
} else {
|
||||
throw new GdxRuntimeException("Unsupported trigger: " + mapObject.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadObjectLayer(MapLayer objectLayer) {
|
||||
if (loadObjectConsumer == null) return;
|
||||
|
||||
for (MapObject mapObject : objectLayer.getObjects()) {
|
||||
if (mapObject instanceof TiledMapTileMapObject tileMapObject) {
|
||||
loadObjectConsumer.accept(tileMapObject);
|
||||
} else {
|
||||
throw new GdxRuntimeException("Unsupported object: " + mapObject.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LoadTileConsumer {
|
||||
void accept(TiledMapTile tile, float x, float y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class GameViewModel extends ViewModel {
|
||||
public void setLifePoints(int lifePoints) {
|
||||
if (this.lifePoints != lifePoints) {
|
||||
this.propertyChangeSupport.firePropertyChange(LIFE_POINTS, this.lifePoints, lifePoints);
|
||||
if (this.lifePoints < lifePoints) {
|
||||
if (this.lifePoints != 0 && this.lifePoints < lifePoints) {
|
||||
audioService.playSound(SoundAsset.LIFE_REG);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user