add move support
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.10" tiledversion="1.11.1-99-gec89c545" name="objects" tilewidth="64" tileheight="64" tilecount="1" columns="0">
|
||||
<tileset version="1.10" tiledversion="1.11.0" name="objects" tilewidth="64" tileheight="64" tilecount="1" columns="0">
|
||||
<grid orientation="orthogonal" width="1" height="1"/>
|
||||
<tile id="0">
|
||||
<properties>
|
||||
<property name="animation" value="WALK"/>
|
||||
<property name="atlasAsset" value="OBJECTS"/>
|
||||
<property name="speed" type="float" value="5"/>
|
||||
<property name="speed" type="float" value="2"/>
|
||||
</properties>
|
||||
<image source="objects/hero.png" width="64" height="64"/>
|
||||
<objectgroup draworder="index" id="3">
|
||||
|
||||
@@ -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.math.Vector2;
|
||||
|
||||
public class Move implements Component {
|
||||
public static final ComponentMapper<Move> MAPPER = ComponentMapper.getFor(Move.class);
|
||||
|
||||
private float maxSpeed;
|
||||
private final Vector2 direction;
|
||||
|
||||
public Move(float maxSpeed) {
|
||||
this.maxSpeed = maxSpeed;
|
||||
this.direction = new Vector2();
|
||||
}
|
||||
|
||||
public float getMaxSpeed() {
|
||||
return maxSpeed;
|
||||
}
|
||||
|
||||
public Vector2 getDirection() {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,9 @@ 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.PhysicMoveSystem;
|
||||
import io.github.com.quillraven.system.PhysicSystem;
|
||||
import io.github.com.quillraven.system.RenderSystem;
|
||||
import io.github.com.quillraven.system.TestSystem;
|
||||
import io.github.com.quillraven.tiled.TiledAshleySpawner;
|
||||
@@ -33,9 +34,10 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld);
|
||||
|
||||
// add ECS systems
|
||||
this.engine.addSystem(new PhysicMoveSystem());
|
||||
this.engine.addSystem(new PhysicSystem(physicWorld, 1 / 60f));
|
||||
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 TestSystem(this.tiledService));
|
||||
this.engine.addSystem(new PhysicDebugRenderSystem(this.physicWorld, game.getCamera()));
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package io.github.com.quillraven.system;
|
||||
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.EntityListener;
|
||||
import com.badlogic.ashley.core.EntitySystem;
|
||||
import com.badlogic.gdx.physics.box2d.Body;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
|
||||
public class CleanupSystem extends EntitySystem implements EntityListener {
|
||||
|
||||
@Override
|
||||
public void addedToEngine(Engine engine) {
|
||||
super.addedToEngine(engine);
|
||||
engine.addEntityListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedFromEngine(Engine engine) {
|
||||
super.removedFromEngine(engine);
|
||||
engine.removeEntityListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityAdded(Entity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityRemoved(Entity entity) {
|
||||
// !!! Important !!!
|
||||
// This does not work if the Physic component gets removed from an entity
|
||||
// because the component is no longer accessible here.
|
||||
// This ONLY works when an entity with a Physic component gets removed entirely from the engine.
|
||||
Physic physic = Physic.MAPPER.get(entity);
|
||||
if (physic != null) {
|
||||
Body body = physic.getBody();
|
||||
body.getWorld().destroyBody(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
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.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.Body;
|
||||
import io.github.com.quillraven.component.Facing;
|
||||
import io.github.com.quillraven.component.Move;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
|
||||
public class PhysicMoveSystem extends IteratingSystem {
|
||||
private static final Vector2 TMP_VEC2 = new Vector2();
|
||||
|
||||
public PhysicMoveSystem() {
|
||||
super(Family.all(Physic.class, Move.class, Facing.class).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processEntity(Entity entity, float deltaTime) {
|
||||
Move move = Move.MAPPER.get(entity);
|
||||
Physic physic = Physic.MAPPER.get(entity);
|
||||
Body body = physic.getBody();
|
||||
if (move.getDirection().isZero()) {
|
||||
// no direction given -> stop movement
|
||||
body.setLinearVelocity(0f, 0f);
|
||||
return;
|
||||
}
|
||||
|
||||
float maxSpeed = move.getMaxSpeed();
|
||||
TMP_VEC2.set(move.getDirection()).nor();
|
||||
body.setLinearVelocity(maxSpeed * TMP_VEC2.x, maxSpeed * TMP_VEC2.y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package io.github.com.quillraven.system;
|
||||
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.EntityListener;
|
||||
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.World;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
import io.github.com.quillraven.component.Transform;
|
||||
|
||||
public class PhysicSystem extends IteratingSystem implements EntityListener {
|
||||
|
||||
private final World world;
|
||||
private final float interval;
|
||||
private float accumulator;
|
||||
|
||||
public PhysicSystem(World world, float interval) {
|
||||
super(Family.all(Physic.class, Transform.class).get());
|
||||
this.world = world;
|
||||
this.interval = interval;
|
||||
this.accumulator = 0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addedToEngine(Engine engine) {
|
||||
super.addedToEngine(engine);
|
||||
engine.addEntityListener(getFamily(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedFromEngine(Engine engine) {
|
||||
super.removedFromEngine(engine);
|
||||
engine.removeEntityListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float deltaTime) {
|
||||
this.accumulator += deltaTime;
|
||||
|
||||
while (this.accumulator >= this.interval) {
|
||||
this.accumulator -= this.interval;
|
||||
super.update(interval);
|
||||
this.world.step(interval, 6, 2);
|
||||
}
|
||||
world.clearForces();
|
||||
|
||||
float alpha = this.accumulator / this.interval;
|
||||
for (int i = 0; i < getEntities().size(); ++i) {
|
||||
this.interpolateEntity(getEntities().get(i), alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processEntity(Entity entity, float deltaTime) {
|
||||
Physic physic = Physic.MAPPER.get(entity);
|
||||
physic.getPrevPosition().set(physic.getBody().getPosition());
|
||||
}
|
||||
|
||||
private void interpolateEntity(Entity entity, float alpha) {
|
||||
Transform transform = Transform.MAPPER.get(entity);
|
||||
Physic physic = Physic.MAPPER.get(entity);
|
||||
|
||||
transform.getPosition().set(
|
||||
MathUtils.lerp(physic.getPrevPosition().x, physic.getBody().getPosition().x, alpha),
|
||||
MathUtils.lerp(physic.getPrevPosition().y, physic.getBody().getPosition().y, alpha)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityAdded(Entity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityRemoved(Entity entity) {
|
||||
// !!! Important !!!
|
||||
// This does not work if the Physic component gets removed from an entity
|
||||
// because the component is no longer accessible here.
|
||||
// This ONLY works when an entity with a Physic component gets removed entirely from the engine.
|
||||
Physic physic = Physic.MAPPER.get(entity);
|
||||
if (physic != null) {
|
||||
Body body = physic.getBody();
|
||||
body.getWorld().destroyBody(body);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,12 +6,7 @@ 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.component.Move;
|
||||
import io.github.com.quillraven.tiled.TiledService;
|
||||
|
||||
public class TestSystem extends EntitySystem {
|
||||
@@ -24,46 +19,30 @@ public class TestSystem extends EntitySystem {
|
||||
|
||||
@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());
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.W)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Move.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);
|
||||
Move.MAPPER.get(entity).getDirection().set(0f, 1f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.S)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Move.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Facing.MAPPER.get(entity).setDirection(FacingDirection.DOWN);
|
||||
Animation2D.MAPPER.get(entity).setType(Animation2D.AnimationType.IDLE);
|
||||
Move.MAPPER.get(entity).getDirection().set(0f, -1f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.A)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Move.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Move.MAPPER.get(entity).getDirection().set(-1f, 0f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.D)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Move.class).get());
|
||||
for (Entity entity : entities) {
|
||||
Move.MAPPER.get(entity).getDirection().set(1f, 0f);
|
||||
}
|
||||
} else if (Gdx.input.isKeyJustPressed(Input.Keys.Q)) {
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Animation2D.class).get());
|
||||
ImmutableArray<Entity> entities = getEngine().getEntitiesFor(Family.all(Move.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);
|
||||
Move.MAPPER.get(entity).getDirection().setZero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ 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.Move;
|
||||
import io.github.com.quillraven.component.Physic;
|
||||
import io.github.com.quillraven.component.Transform;
|
||||
|
||||
@@ -110,25 +111,34 @@ public class TiledAshleySpawner {
|
||||
|
||||
private void spawnEntityOf(TiledMapTileMapObject tileMapObject) {
|
||||
Entity entity = this.engine.createEntity();
|
||||
TiledMapTile tile = tileMapObject.getTile();
|
||||
TextureRegion textureRegion = tile.getTextureRegion();
|
||||
|
||||
TextureRegion textureRegion = tileMapObject.getTile().getTextureRegion();
|
||||
addEntityTransform(
|
||||
tileMapObject.getX(), tileMapObject.getY(),
|
||||
textureRegion.getRegionWidth(), textureRegion.getRegionHeight(),
|
||||
tileMapObject.getScaleX(), tileMapObject.getScaleY(),
|
||||
entity);
|
||||
addEntityPhysic(
|
||||
tileMapObject.getTile().getObjects(),
|
||||
tile.getObjects(),
|
||||
BodyType.DynamicBody,
|
||||
Vector2.Zero,
|
||||
entity);
|
||||
addEntityAnimation(tileMapObject.getTile(), entity);
|
||||
addEntityAnimation(tile, entity);
|
||||
addEntityMove(tile, entity);
|
||||
entity.add(new Facing(FacingDirection.DOWN));
|
||||
entity.add(new Graphic(textureRegion, Color.WHITE.cpy()));
|
||||
|
||||
this.engine.addEntity(entity);
|
||||
}
|
||||
|
||||
private void addEntityMove(TiledMapTile tile, Entity entity) {
|
||||
float speed = tile.getProperties().get("speed", 0f, Float.class);
|
||||
if (speed == 0f) return;
|
||||
|
||||
entity.add(new Move(speed));
|
||||
}
|
||||
|
||||
private void addEntityAnimation(TiledMapTile tile, Entity entity) {
|
||||
String animationStr = tile.getProperties().get("animation", "", String.class);
|
||||
if (animationStr.isBlank()) {
|
||||
@@ -179,7 +189,7 @@ public class TiledAshleySpawner {
|
||||
Body body = this.physicWorld.createBody(bodyDef);
|
||||
body.setUserData(userData);
|
||||
for (MapObject object : mapObjects) {
|
||||
FixtureDef fixtureDef = TiledPhysics.fixtureDefOfMapObject(object, scaling, relativeTo);
|
||||
FixtureDef fixtureDef = TiledPhysics.fixtureDefOf(object, scaling, relativeTo);
|
||||
body.createFixture(fixtureDef);
|
||||
fixtureDef.shape.dispose();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class TiledPhysics {
|
||||
// relativeTo is necessary for map objects that are directly placed on a layer (like rectangles for trigger).
|
||||
// Their x/y is equal to the position of the object, but we need it relative to 0,0 like it
|
||||
// is in the collision editor of a tile.
|
||||
public static FixtureDef fixtureDefOfMapObject(MapObject mapObject, Vector2 scaling, Vector2 relativeTo) {
|
||||
public static FixtureDef fixtureDefOf(MapObject mapObject, Vector2 scaling, Vector2 relativeTo) {
|
||||
if (mapObject instanceof RectangleMapObject rectMapObj) {
|
||||
return rectangleFixtureDef(rectMapObj, scaling, relativeTo);
|
||||
} else if (mapObject instanceof EllipseMapObject ellipseMapObj) {
|
||||
|
||||
@@ -20,19 +20,19 @@ public class Lwjgl3Launcher {
|
||||
private static Lwjgl3ApplicationConfiguration getDefaultConfiguration() {
|
||||
Lwjgl3ApplicationConfiguration configuration = new Lwjgl3ApplicationConfiguration();
|
||||
configuration.setTitle("mystictutorial");
|
||||
//// Vsync limits the frames per second to what your hardware can display, and helps eliminate
|
||||
//// screen tearing. This setting doesn't always work on Linux, so the line after is a safeguard.
|
||||
// Vsync limits the frames per second to what your hardware can display, and helps eliminate
|
||||
// screen tearing. This setting doesn't always work on Linux, so the line after is a safeguard.
|
||||
configuration.useVsync(true);
|
||||
//// Limits FPS to the refresh rate of the currently active monitor, plus 1 to try to match fractional
|
||||
//// refresh rates. The Vsync setting above should limit the actual FPS to match the monitor.
|
||||
// Limits FPS to the refresh rate of the currently active monitor, plus 1 to try to match fractional
|
||||
// refresh rates. The Vsync setting above should limit the actual FPS to match the monitor.
|
||||
configuration.setForegroundFPS(Lwjgl3ApplicationConfiguration.getDisplayMode().refreshRate + 1);
|
||||
//// If you remove the above line and set Vsync to false, you can get unlimited FPS, which can be
|
||||
//// useful for testing performance, but can also be very stressful to some hardware.
|
||||
//// You may also need to configure GPU drivers to fully disable Vsync; this can cause screen tearing.
|
||||
// If you remove the above line and set Vsync to false, you can get unlimited FPS, which can be
|
||||
// useful for testing performance, but can also be very stressful to some hardware.
|
||||
// You may also need to configure GPU drivers to fully disable Vsync; this can cause screen tearing.
|
||||
|
||||
configuration.setWindowedMode((int) (GdxGame.WORLD_WIDTH * 70), (int) (GdxGame.WORLD_HEIGHT * 70));
|
||||
//// You can change these files; they are in lwjgl3/src/main/resources/ .
|
||||
//// They can also be loaded from the root of assets/ .
|
||||
// You can change these files; they are in lwjgl3/src/main/resources/ .
|
||||
// They can also be loaded from the root of assets/ .
|
||||
configuration.setWindowIcon("libgdx128.png", "libgdx64.png", "libgdx32.png", "libgdx16.png");
|
||||
return configuration;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user