summaryrefslogtreecommitdiff
path: root/core/src/main/java/coffee
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/coffee')
-rw-r--r--core/src/main/java/coffee/liz/dyl/FrameState.java16
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/BoundingBox.java21
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java4
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java6
-rw-r--r--core/src/main/java/coffee/liz/dyl/config/KeyBinds.java21
-rw-r--r--core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java12
-rw-r--r--core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java26
-rw-r--r--core/src/main/java/coffee/liz/dyl/screen/GameScreen.java9
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/InputSystem.java69
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/IntegrationSystem.java32
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java14
-rw-r--r--core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java25
-rw-r--r--core/src/main/java/coffee/liz/ecs/DAGWorld.java74
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java34
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java6
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java12
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java20
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java11
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java14
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java11
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java6
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java (renamed from core/src/main/java/coffee/liz/dyl/components/Velocity.java)7
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java65
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java107
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java55
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java25
-rw-r--r--core/src/main/java/coffee/liz/ecs/model/QueryBuilder.java4
-rw-r--r--core/src/main/java/coffee/liz/ecs/model/System.java25
-rw-r--r--core/src/main/java/coffee/liz/ecs/model/World.java56
29 files changed, 528 insertions, 259 deletions
diff --git a/core/src/main/java/coffee/liz/dyl/FrameState.java b/core/src/main/java/coffee/liz/dyl/FrameState.java
deleted file mode 100644
index 7d70cde..0000000
--- a/core/src/main/java/coffee/liz/dyl/FrameState.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package coffee.liz.dyl;
-
-import coffee.liz.dyl.config.Settings;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.function.Predicate;
-
-@Builder
-@Getter
-@RequiredArgsConstructor
-public class FrameState {
- private final Settings settings;
- private final Predicate<Integer> isKeyPressed;
-}
diff --git a/core/src/main/java/coffee/liz/dyl/components/BoundingBox.java b/core/src/main/java/coffee/liz/dyl/components/BoundingBox.java
deleted file mode 100644
index 481e91e..0000000
--- a/core/src/main/java/coffee/liz/dyl/components/BoundingBox.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package coffee.liz.dyl.components;
-
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.model.Component;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-
-@AllArgsConstructor
-@Getter
-@Setter
-public class BoundingBox implements Component, Comparable<BoundingBox> {
- private Vec2<Float> position;
- private Vec2<Integer> dimensions;
- private int z;
-
- @Override
- public int compareTo(final BoundingBox other) {
- return Integer.compare(z, other.getZ());
- }
-}
diff --git a/core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java b/core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java
index c70b382..7075755 100644
--- a/core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java
+++ b/core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java
@@ -1,6 +1,6 @@
package coffee.liz.dyl.components.graphic;
-import coffee.liz.dyl.components.BoundingBox;
+import coffee.liz.ecs.common.components.physics.BoundingBox;
import coffee.liz.ecs.model.Component;
import com.badlogic.gdx.graphics.g2d.Batch;
@@ -9,5 +9,7 @@ public interface Graphic extends Component {
return Graphic.class;
}
+ int getZ();
+
void draw(final Batch batch, final BoundingBox boundingBox);
}
diff --git a/core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java b/core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java
index 6f29759..c2718b5 100644
--- a/core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java
+++ b/core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java
@@ -1,6 +1,6 @@
package coffee.liz.dyl.components.graphic;
-import coffee.liz.dyl.components.BoundingBox;
+import coffee.liz.ecs.common.components.physics.BoundingBox;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
@@ -10,6 +10,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public class TextureGraphic implements Graphic {
+ private int z;
private Color color;
private Texture texture;
@@ -18,8 +19,7 @@ public class TextureGraphic implements Graphic {
batch.setColor(color);
batch.draw(texture,
boundingBox.getPosition().getX(), boundingBox.getPosition().getY(),
- 0, 0,
- boundingBox.getDimensions().getX(), boundingBox.getDimensions().getY()
+ boundingBox.getSize().getX(), boundingBox.getSize().getY()
);
}
}
diff --git a/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java b/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java
index 762dc48..0b33b26 100644
--- a/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java
+++ b/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java
@@ -1,4 +1,5 @@
package coffee.liz.dyl.config;
+
import com.badlogic.gdx.Input;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -16,26 +17,24 @@ import java.util.function.Predicate;
@Getter
public class KeyBinds {
@Builder.Default
- private Set<Integer> moveUpKeys = Set.of(Input.Keys.K, Input.Keys.UP, Input.Keys.W);
- @Builder.Default
- private Set<Integer> moveDownKeys = Set.of(Input.Keys.J, Input.Keys.DOWN, Input.Keys.S);
- @Builder.Default
private Set<Integer> moveLeftKeys = Set.of(Input.Keys.H, Input.Keys.LEFT, Input.Keys.A);
@Builder.Default
private Set<Integer> moveRightKeys = Set.of(Input.Keys.L, Input.Keys.RIGHT, Input.Keys.D);
+ @Builder.Default
+ private Set<Integer> jumpKeys = Set.of(Input.Keys.W, Input.Keys.UP, Input.Keys.SPACE);
public Set<Action> filterActiveActions(final Predicate<Integer> isDown) {
final Set<Action> actions = new HashSet<>();
- Map.of(moveUpKeys, Action.MOVE_UP, moveDownKeys, Action.MOVE_DOWN, moveRightKeys, Action.MOVE_RIGHT,
- moveLeftKeys, Action.MOVE_LEFT).forEach((keys, action) -> {
- if (keys.stream().anyMatch(isDown)) {
- actions.add(action);
- }
- });
+ Map.of(moveLeftKeys, Action.MOVE_LEFT, moveRightKeys, Action.MOVE_RIGHT, jumpKeys, Action.JUMP)
+ .forEach((keys, action) -> {
+ if (keys.stream().anyMatch(isDown)) {
+ actions.add(action);
+ }
+ });
return actions;
}
public enum Action {
- MOVE_UP, MOVE_LEFT, MOVE_DOWN, MOVE_RIGHT;
+ MOVE_LEFT, MOVE_RIGHT, JUMP;
}
}
diff --git a/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java b/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java
new file mode 100644
index 0000000..b0b1a31
--- /dev/null
+++ b/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java
@@ -0,0 +1,12 @@
+package coffee.liz.dyl.config;
+
+public final class PhysicsConstants {
+ public static final float GRAVITY = 9.8f;
+ public static final float MOVE_SPEED = 5.0f;
+ public static final float JUMP_INITIAL_VEL = 8.0f;
+ public static final float JUMP_ACC = 15.0f;
+ public static final long MAX_JUMP_MS = 150L;
+
+ private PhysicsConstants() {
+ }
+}
diff --git a/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java b/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java
index 54c5df7..a982bb9 100644
--- a/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java
+++ b/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java
@@ -1,8 +1,15 @@
package coffee.liz.dyl.entities;
import coffee.liz.dyl.components.Controllable;
-import coffee.liz.dyl.components.Velocity;
import coffee.liz.dyl.components.graphic.TextureGraphic;
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.common.components.physics.Collidable;
+import coffee.liz.ecs.common.components.physics.Forces;
+import coffee.liz.ecs.common.components.physics.Gravity;
+import coffee.liz.ecs.common.components.physics.Jump;
+import coffee.liz.ecs.common.components.physics.Mass;
+import coffee.liz.ecs.common.components.physics.Velocity;
+import coffee.liz.ecs.math.Vec2f;
import coffee.liz.ecs.model.Entity;
import coffee.liz.ecs.model.World;
import com.badlogic.gdx.Gdx;
@@ -15,16 +22,23 @@ public class PlayerFactory {
private static final int PENGUIN_FRAMES_Y = 4;
private static final int PENGUIN_FRAMES_X = 8;
private static final FileHandle FILE = Gdx.files.internal("player.png");
- private static Texture texture = new Texture(FILE);;
+ private static Texture texture = new Texture(FILE);
- public static Entity addTo(final World<?> world) {
+ public static Entity addTo(final World world) {
final TextureRegion[][] tmp = TextureRegion.split(texture, texture.getWidth() / PENGUIN_FRAMES_X,
texture.getHeight() / PENGUIN_FRAMES_Y);
return world.createEntity()
- .add(new TextureGraphic(Color.PINK, tmp[0][0].getTexture()))
+ .add(new TextureGraphic(0, Color.PINK, tmp[0][0].getTexture()))
.add(new Controllable())
- .add(new Velocity());
+ .add(new BoundingBox(new Vec2f(2f, 2f), new Vec2f(1f, 1f)))
+ .add(new Velocity(Vec2f.ZERO))
+ .add(new Mass(1f))
+ .add(new Forces())
+ .add(new Gravity(20f))
+ .add(new Jump(false, 0L))
+ .add(new Collidable());
}
- private PlayerFactory() { }
+ private PlayerFactory() {
+ }
}
diff --git a/core/src/main/java/coffee/liz/dyl/screen/GameScreen.java b/core/src/main/java/coffee/liz/dyl/screen/GameScreen.java
index 39017c5..0797e3e 100644
--- a/core/src/main/java/coffee/liz/dyl/screen/GameScreen.java
+++ b/core/src/main/java/coffee/liz/dyl/screen/GameScreen.java
@@ -1,9 +1,7 @@
package coffee.liz.dyl.screen;
import coffee.liz.dyl.DylGame;
-import coffee.liz.dyl.FrameState;
import coffee.liz.dyl.world.DylGameWorld;
-import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import lombok.RequiredArgsConstructor;
@@ -13,20 +11,15 @@ public class GameScreen implements Screen {
private final DylGame game;
private DylGameWorld dylGameWorld;
- private FrameState frameState;
@Override
public void show() {
dylGameWorld = new DylGameWorld(game);
- frameState = FrameState.builder()
- .settings(game.getSettings())
- .isKeyPressed(Gdx.input::isKeyPressed)
- .build();
}
@Override
public void render(final float delta) {
- dylGameWorld.update(frameState, Math.min(delta, MAX_DELTA_SECONDS));
+ dylGameWorld.update(Math.min(delta, MAX_DELTA_SECONDS));
}
@Override
diff --git a/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java b/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java
index 1519b3e..d5acbaf 100644
--- a/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java
+++ b/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java
@@ -1,42 +1,65 @@
package coffee.liz.dyl.systems;
-import coffee.liz.dyl.FrameState;
-import coffee.liz.dyl.components.BoundingBox;
-import coffee.liz.dyl.components.Velocity;
+import coffee.liz.dyl.components.Controllable;
import coffee.liz.dyl.config.KeyBinds;
-import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.common.components.physics.Force;
+import coffee.liz.ecs.common.components.physics.Forces;
+import coffee.liz.ecs.common.components.physics.Jump;
+import coffee.liz.ecs.common.components.physics.Mass;
+import coffee.liz.ecs.common.components.physics.Velocity;
import coffee.liz.ecs.math.Vec2f;
-import coffee.liz.ecs.math.Vec2i;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
+import lombok.RequiredArgsConstructor;
+import java.time.Instant;
import java.util.Collection;
-import java.util.Map;
import java.util.Set;
+import java.util.function.Supplier;
+
+import static coffee.liz.dyl.config.PhysicsConstants.JUMP_ACC;
+import static coffee.liz.dyl.config.PhysicsConstants.JUMP_INITIAL_VEL;
+import static coffee.liz.dyl.config.PhysicsConstants.MAX_JUMP_MS;
+import static coffee.liz.dyl.config.PhysicsConstants.MOVE_SPEED;
+
+@RequiredArgsConstructor
+public class InputSystem implements System {
+ private final Supplier<Set<KeyBinds.Action>> activeActions;
-public class InputSystem implements System<FrameState> {
@Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
+ public Collection<Class<? extends System>> getDependencies() {
return Set.of();
}
@Override
- public void update(final World<FrameState> world, final FrameState state, final float deltaSeconds) {
- final Set<KeyBinds.Action> currentlyActive = state.getSettings().getKeyBinds()
- .filterActiveActions(state.getIsKeyPressed());
+ public void update(final World world, final float deltaSeconds) {
+ final Set<KeyBinds.Action> actions = activeActions.get();
- final Vec2<Float> momentum = currentlyActive.stream().map(movementVectors::get)
- .reduce(Vec2::plus)
- .orElse(Vec2f.ZERO);
+ world.queryable().allOf(Controllable.class, Velocity.class).forEach(entity -> {
+ final Velocity velocity = entity.get(Velocity.class);
- world.queryable().allOf(Velocity.class, BoundingBox.class)
- .forEach(e -> e.get(Velocity.class).setVelocity(momentum));
- }
+ float dx = 0f;
+ if (actions.contains(KeyBinds.Action.MOVE_LEFT)) dx = -MOVE_SPEED;
+ if (actions.contains(KeyBinds.Action.MOVE_RIGHT)) dx = MOVE_SPEED;
+
+ float newDy = velocity.getVelocity().getY();
- private static Map<KeyBinds.Action, Vec2<Float>> movementVectors = Map.of(
- KeyBinds.Action.MOVE_UP, Vec2i.NORTH.floatValue(),
- KeyBinds.Action.MOVE_DOWN, Vec2i.SOUTH.floatValue(),
- KeyBinds.Action.MOVE_LEFT, Vec2i.WEST.floatValue(),
- KeyBinds.Action.MOVE_RIGHT, Vec2i.EAST.floatValue()
- );
+ if (entity.has(Jump.class) && entity.has(Mass.class) && entity.has(Forces.class)) {
+ final Jump jump = entity.get(Jump.class);
+ final Mass mass = entity.get(Mass.class);
+
+ if (actions.contains(KeyBinds.Action.JUMP)) {
+ if (jump.isCanJump()) {
+ newDy = JUMP_INITIAL_VEL;
+ jump.setCanJump(false);
+ jump.setJumpStartMs(Instant.now().toEpochMilli());
+ } else if (Instant.now().toEpochMilli() - jump.getJumpStartMs() < MAX_JUMP_MS) {
+ entity.get(Forces.class).add(new Force(new Vec2f(0f, mass.getMass() * JUMP_ACC)));
+ }
+ }
+ }
+
+ velocity.setVelocity(new Vec2f(dx, newDy));
+ });
+ }
}
diff --git a/core/src/main/java/coffee/liz/dyl/systems/IntegrationSystem.java b/core/src/main/java/coffee/liz/dyl/systems/IntegrationSystem.java
deleted file mode 100644
index cd7d7b1..0000000
--- a/core/src/main/java/coffee/liz/dyl/systems/IntegrationSystem.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package coffee.liz.dyl.systems;
-
-import coffee.liz.dyl.FrameState;
-import coffee.liz.dyl.components.BoundingBox;
-import coffee.liz.dyl.components.Velocity;
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.model.System;
-import coffee.liz.ecs.model.World;
-import lombok.extern.log4j.Log4j2;
-
-import java.util.Collection;
-import java.util.List;
-
-@Log4j2
-public class IntegrationSystem implements System<FrameState> {
- @Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return List.of(InputSystem.class);
- }
-
- @Override
- public void update(final World<FrameState> world, final FrameState state, final float deltaSeconds) {
- world.queryable().allOf(Velocity.class, BoundingBox.class)
- .forEach(e -> {
- final Vec2<Float> velocity = e.get(Velocity.class).getVelocity();
- final BoundingBox box = e.get(BoundingBox.class);
- final Vec2<Float> position = box.getPosition()
- .plus(velocity.scale(deltaSeconds, deltaSeconds));
- box.setPosition(position);
- });
- }
-}
diff --git a/core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java b/core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java
index 86c18fd..15e1f30 100644
--- a/core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java
+++ b/core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java
@@ -1,8 +1,8 @@
package coffee.liz.dyl.systems;
-import coffee.liz.dyl.FrameState;
import coffee.liz.dyl.components.graphic.Graphic;
-import coffee.liz.dyl.components.BoundingBox;
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.common.systems.physics.CollisionSystem;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
import com.badlogic.gdx.graphics.Color;
@@ -14,7 +14,7 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
-public class RenderSystem implements System<FrameState> {
+public class RenderSystem implements System {
private final Batch batch;
private final OrthographicCamera camera;
private final Viewport viewport;
@@ -26,12 +26,12 @@ public class RenderSystem implements System<FrameState> {
}
@Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return Set.of(IntegrationSystem.class);
+ public Collection<Class<? extends System>> getDependencies() {
+ return Set.of(CollisionSystem.class);
}
@Override
- public void update(final World<FrameState> world, final FrameState state, final float deltaSeconds) {
+ public void update(final World world, final float deltaSeconds) {
viewport.apply();
camera.update();
@@ -40,7 +40,7 @@ public class RenderSystem implements System<FrameState> {
batch.setColor(Color.WHITE);
world.queryable().allOf(BoundingBox.class, Graphic.class).stream()
- .sorted(Comparator.comparing(e -> e.get(BoundingBox.class)))
+ .sorted(Comparator.comparingDouble(e -> e.get(Graphic.class).getZ()))
.forEach(e -> {
final BoundingBox boundingBox = e.get(BoundingBox.class);
final Graphic graphic = e.get(Graphic.class);
diff --git a/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java b/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java
index a52ea0f..7f1cb62 100644
--- a/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java
+++ b/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java
@@ -1,26 +1,31 @@
package coffee.liz.dyl.world;
import coffee.liz.dyl.DylGame;
-import coffee.liz.dyl.FrameState;
-import coffee.liz.dyl.components.BoundingBox;
+import coffee.liz.dyl.config.PhysicsConstants;
import coffee.liz.dyl.entities.PlayerFactory;
import coffee.liz.dyl.systems.InputSystem;
-import coffee.liz.dyl.systems.IntegrationSystem;
import coffee.liz.dyl.systems.RenderSystem;
import coffee.liz.ecs.DAGWorld;
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.common.components.physics.TopCollidable;
+import coffee.liz.ecs.common.systems.physics.CollisionSystem;
+import coffee.liz.ecs.common.systems.physics.ForceReductionSystem;
+import coffee.liz.ecs.common.systems.physics.IntegrationSystem;
import coffee.liz.ecs.math.Vec2f;
-import coffee.liz.ecs.math.Vec2i;
+import com.badlogic.gdx.Gdx;
-public class DylGameWorld extends DAGWorld<FrameState> {
+public class DylGameWorld extends DAGWorld {
public DylGameWorld(final DylGame game) {
super(
- new InputSystem(),
+ new InputSystem(() -> game.getSettings().getKeyBinds().filterActiveActions(Gdx.input::isKeyPressed)),
+ new ForceReductionSystem(PhysicsConstants.GRAVITY),
new IntegrationSystem(),
+ new CollisionSystem(PhysicsConstants.GRAVITY),
new RenderSystem(game.getBatch(), game.getViewport())
);
- for (int i = 0; i < 2_000; i++) {
- PlayerFactory.addTo(this)
- .add(new BoundingBox(new Vec2f(i / 200f, i/ 200f), new Vec2i(1, 1), 1));
- }
+ PlayerFactory.addTo(this);
+ createEntity()
+ .add(new BoundingBox(new Vec2f(-50f, -1f), new Vec2f(200f, 1f)))
+ .add(new TopCollidable());
}
}
diff --git a/core/src/main/java/coffee/liz/ecs/DAGWorld.java b/core/src/main/java/coffee/liz/ecs/DAGWorld.java
index 0cc7d5d..f941dba 100644
--- a/core/src/main/java/coffee/liz/ecs/DAGWorld.java
+++ b/core/src/main/java/coffee/liz/ecs/DAGWorld.java
@@ -8,7 +8,6 @@ import coffee.liz.ecs.model.QueryBuilder;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
-import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import java.util.ArrayList;
@@ -26,20 +25,17 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;
-/** World that updates in {@link System#getDependencies()} topological order. */
@Log4j2
-@RequiredArgsConstructor
-public class DAGWorld<T> implements World<T> {
+public class DAGWorld implements World {
private final Set<Entity> entities = Collections.synchronizedSet(new HashSet<>());
private final ComponentCache componentCache = new ComponentCache();
private final Consumer<EntityEvent> entityEventConsumer = componentCache::onEntityEvent;
private final AtomicInteger nextEntityId = new AtomicInteger(0);
- protected final Map<Class<? extends System<T>>, System<T>> systems;
- private final List<System<T>> systemExecutionOrder;
- private final QueryBuilder<T> queryBuilder = new QueryBuilder<>(this);
+ protected final Map<Class<? extends System>, System> systems;
+ private final List<System> systemExecutionOrder;
+ private final QueryBuilder queryBuilder = new QueryBuilder(this);
- @SafeVarargs
- public DAGWorld(final System<T>... systems) {
+ public DAGWorld(final System... systems) {
this.systems = singletonClazzMap(systems);
this.systemExecutionOrder = buildExecutionOrder(Arrays.asList(systems));
log.info("Executing in order: {}", systemExecutionOrder);
@@ -72,18 +68,18 @@ public class DAGWorld<T> implements World<T> {
}
@Override
- public QueryBuilder<T> queryable() {
+ public QueryBuilder queryable() {
return queryBuilder;
}
@Override
- public void update(final T state, final float deltaSeconds) {
- systemExecutionOrder.forEach(system -> system.update(this, state, deltaSeconds));
+ public void update(final float deltaSeconds) {
+ systemExecutionOrder.forEach(system -> system.update(this, deltaSeconds));
}
@SuppressWarnings("unchecked")
@Override
- public <S extends System<T>> S getSystem(final Class<S> system) {
+ public <S extends System> S getSystem(final Class<S> system) {
return (S) systems.get(system);
}
@@ -98,7 +94,6 @@ public class DAGWorld<T> implements World<T> {
if (components.isEmpty()) {
return Collections.emptySet();
}
-
final Set<Entity> matches = new HashSet<>();
components.forEach(componentType -> matches.addAll(componentCache.entitiesWith(componentType)));
return matches;
@@ -108,10 +103,8 @@ public class DAGWorld<T> implements World<T> {
if (components.isEmpty()) {
return entities;
}
-
final Set<Entity> excluded = new HashSet<>();
components.forEach(componentType -> excluded.addAll(componentCache.entitiesWith(componentType)));
-
final Set<Entity> result = new HashSet<>();
entities.forEach(entity -> {
if (!excluded.contains(entity)) {
@@ -121,41 +114,35 @@ public class DAGWorld<T> implements World<T> {
return result;
}
- private List<System<T>> buildExecutionOrder(final Collection<System<T>> systems) {
+ private List<System> buildExecutionOrder(final Collection<System> systems) {
if (systems.isEmpty()) {
return Collections.emptyList();
}
- final Map<Class<?>, System<T>> systemMap = systems.stream()
+ final Map<Class<?>, System> systemMap = systems.stream()
.collect(Collectors.toMap(System::getClass, system -> system, (_sys, b) -> b, LinkedHashMap::new));
final Map<Class<?>, Integer> inDegree = new LinkedHashMap<>();
final Map<Class<?>, Set<Class<?>>> adjacencyList = new LinkedHashMap<>();
systems.forEach(system -> {
- final Class<?> systemClass = system.getClass();
- inDegree.put(systemClass, 0);
- adjacencyList.put(systemClass, new HashSet<>());
- });
-
- systems.forEach(system -> {
- system.getDependencies().forEach(dependency -> {
- if (systemMap.containsKey(dependency)) {
- adjacencyList.get(dependency).add(system.getClass());
- inDegree.merge(system.getClass(), 1, Integer::sum);
- }
- });
+ inDegree.put(system.getClass(), 0);
+ adjacencyList.put(system.getClass(), new HashSet<>());
});
- // Kahn's algorithm
- final List<System<T>> result = new ArrayList<>();
+ systems.forEach(system -> system.getDependencies().forEach(dependency -> {
+ if (systemMap.containsKey(dependency)) {
+ adjacencyList.get(dependency).add(system.getClass());
+ inDegree.merge(system.getClass(), 1, Integer::sum);
+ }
+ }));
+ final List<System> result = new ArrayList<>();
final Queue<Class<?>> queue = new LinkedList<>(
- inDegree.entrySet().stream().filter(entry -> entry.getValue() == 0).map(Map.Entry::getKey).toList());
+ inDegree.entrySet().stream().filter(e -> e.getValue() == 0).map(Map.Entry::getKey).toList());
while (!queue.isEmpty()) {
final Class<?> currentClass = queue.poll();
result.add(systemMap.get(currentClass));
-
adjacencyList.getOrDefault(currentClass, Collections.emptySet()).forEach(dependent -> {
final int newInDegree = inDegree.get(dependent) - 1;
inDegree.put(dependent, newInDegree);
@@ -174,23 +161,24 @@ public class DAGWorld<T> implements World<T> {
@Override
public void dispose() {
- for (final System<T> system : systemExecutionOrder) {
- system.dispose();
- }
+ systemExecutionOrder.forEach(System::dispose);
entities.forEach(entity -> entity.unsubscribe(entityEventConsumer));
componentCache.clear();
entities.clear();
}
@SuppressWarnings("unchecked")
- private static <T> Map<Class<? extends T>, T> singletonClazzMap(final T... singletons) {
- final boolean areSingletons = Arrays.stream(singletons).map(t -> (Class<? extends System<T>>) t.getClass())
- .distinct().count() == singletons.length;
+ private static Map<Class<? extends System>, System> singletonClazzMap(final System... singletons) {
+ final boolean areSingletons = Arrays.stream(singletons)
+ .map(Object::getClass)
+ .distinct()
+ .count() == singletons.length;
if (!areSingletons) {
throw new IllegalArgumentException("Only one instance may be used per clazz");
}
-
- return Arrays.stream(singletons).map(t -> Map.entry((Class<? extends T>) t.getClass(), t))
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ return Arrays.stream(singletons)
+ .collect(Collectors.toMap(
+ s -> (Class<? extends System>) s.getClass(),
+ s -> s));
}
}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java
new file mode 100644
index 0000000..7a31cae
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java
@@ -0,0 +1,34 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.model.Component;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@AllArgsConstructor
+@Getter
+@Setter
+public class BoundingBox implements Component {
+ private Vec2<Float> position;
+ private Vec2<Float> size;
+
+ public float getTop() {
+ return position.getY() + size.getY();
+ }
+
+ public float getRight() {
+ return position.getX() + size.getX();
+ }
+
+ public boolean isCollidingWith(final BoundingBox other) {
+ return getRight() > other.getPosition().getX()
+ && position.getX() < other.getRight()
+ && getTop() > other.getPosition().getY()
+ && position.getY() < other.getTop();
+ }
+
+ public boolean isAbove(final BoundingBox other) {
+ return position.getY() >= other.getTop();
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java
new file mode 100644
index 0000000..166428a
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java
@@ -0,0 +1,6 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+
+public class Collidable implements Component {
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java
new file mode 100644
index 0000000..7d5dab1
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java
@@ -0,0 +1,12 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.model.Component;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Getter
+public class Force implements Component {
+ private final Vec2<Float> force;
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java
new file mode 100644
index 0000000..f6c9ee8
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java
@@ -0,0 +1,20 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+public class Forces implements Component {
+ private final List<Force> forces = new ArrayList<>();
+
+ public void add(final Force force) {
+ forces.add(force);
+ }
+
+ public void clear() {
+ forces.clear();
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java
new file mode 100644
index 0000000..44d5caf
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java
@@ -0,0 +1,11 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Getter
+public class Gravity implements Component {
+ private final float terminalVelocity;
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java
new file mode 100644
index 0000000..5224b32
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java
@@ -0,0 +1,14 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@AllArgsConstructor
+@Getter
+@Setter
+public class Jump implements Component {
+ private boolean canJump;
+ private long jumpStartMs;
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java
new file mode 100644
index 0000000..f38ccc0
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java
@@ -0,0 +1,11 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Getter
+public class Mass implements Component {
+ private final float mass;
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java
new file mode 100644
index 0000000..76185bd
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java
@@ -0,0 +1,6 @@
+package coffee.liz.ecs.common.components.physics;
+
+import coffee.liz.ecs.model.Component;
+
+public class TopCollidable implements Component {
+}
diff --git a/core/src/main/java/coffee/liz/dyl/components/Velocity.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java
index f31e861..9b6a36b 100644
--- a/core/src/main/java/coffee/liz/dyl/components/Velocity.java
+++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java
@@ -1,17 +1,14 @@
-package coffee.liz.dyl.components;
+package coffee.liz.ecs.common.components.physics;
import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.math.Vec2f;
import coffee.liz.ecs.model.Component;
import lombok.AllArgsConstructor;
import lombok.Getter;
-import lombok.NoArgsConstructor;
import lombok.Setter;
@AllArgsConstructor
-@NoArgsConstructor
@Getter
@Setter
public class Velocity implements Component {
- private Vec2<Float> velocity = Vec2f.ZERO;
+ private Vec2<Float> velocity;
}
diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java b/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java
new file mode 100644
index 0000000..94202b4
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java
@@ -0,0 +1,65 @@
+package coffee.liz.ecs.common.systems.physics;
+
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2i;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class CollisionGrid {
+ private final Map<Vec2i, Set<Integer>> cells = new HashMap<>();
+ private Vec2<Float> origin;
+ private Vec2<Float> cellSize;
+
+ public void setOrigin(final Vec2<Float> origin) {
+ this.origin = origin;
+ }
+
+ public void setCellSize(final Vec2<Float> cellSize) {
+ this.cellSize = cellSize;
+ }
+
+ public void clear() {
+ cells.clear();
+ }
+
+ public void insert(final int entityId, final BoundingBox bb) {
+ final int minCx = cellX(bb.getPosition().getX());
+ final int minCy = cellY(bb.getPosition().getY());
+ final int maxCx = cellX(bb.getRight());
+ final int maxCy = cellY(bb.getTop());
+ for (int cx = minCx; cx <= maxCx; cx++) {
+ for (int cy = minCy; cy <= maxCy; cy++) {
+ cells.computeIfAbsent(new Vec2i(cx, cy), _ -> new HashSet<>()).add(entityId);
+ }
+ }
+ }
+
+ public Set<Integer> getNeighborIds(final BoundingBox bb) {
+ final Set<Integer> neighbors = new HashSet<>();
+ final int minCx = cellX(bb.getPosition().getX());
+ final int minCy = cellY(bb.getPosition().getY());
+ final int maxCx = cellX(bb.getRight());
+ final int maxCy = cellY(bb.getTop());
+ for (int cx = minCx; cx <= maxCx; cx++) {
+ for (int cy = minCy; cy <= maxCy; cy++) {
+ final Set<Integer> cell = cells.get(new Vec2i(cx, cy));
+ if (cell != null) {
+ neighbors.addAll(cell);
+ }
+ }
+ }
+ return neighbors;
+ }
+
+ private int cellX(final float x) {
+ return (int) Math.floor((x - origin.getX()) / cellSize.getX());
+ }
+
+ private int cellY(final float y) {
+ return (int) Math.floor((y - origin.getY()) / cellSize.getY());
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java b/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java
new file mode 100644
index 0000000..14f0a2b
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java
@@ -0,0 +1,107 @@
+package coffee.liz.ecs.common.systems.physics;
+
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.common.components.physics.Collidable;
+import coffee.liz.ecs.common.components.physics.Force;
+import coffee.liz.ecs.common.components.physics.Forces;
+import coffee.liz.ecs.common.components.physics.Gravity;
+import coffee.liz.ecs.common.components.physics.Jump;
+import coffee.liz.ecs.common.components.physics.Mass;
+import coffee.liz.ecs.common.components.physics.TopCollidable;
+import coffee.liz.ecs.common.components.physics.Velocity;
+import coffee.liz.ecs.math.Vec2f;
+import coffee.liz.ecs.math.Vec2i;
+import coffee.liz.ecs.model.Entity;
+import coffee.liz.ecs.model.System;
+import coffee.liz.ecs.model.World;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+@RequiredArgsConstructor
+@AllArgsConstructor
+public class CollisionSystem implements System {
+ private final float gravity;
+ private float cellSize = 64f;
+ private final CollisionGrid grid = new CollisionGrid();
+
+ @Override
+ public Collection<Class<? extends System>> getDependencies() {
+ return Set.of(IntegrationSystem.class);
+ }
+
+ @Override
+ public void update(final World world, final float deltaSeconds) {
+ final Set<Entity> collidableEntities = world.queryable().allOf(BoundingBox.class, Collidable.class);
+ final Set<Entity> surfaceEntities = world.queryable().allOf(BoundingBox.class, TopCollidable.class);
+
+ if (collidableEntities.isEmpty() || surfaceEntities.isEmpty()) {
+ return;
+ }
+
+ final Map<Integer, Entity> entityMap = new HashMap<>();
+ collidableEntities.forEach(e -> entityMap.put(e.getId(), e));
+ surfaceEntities.forEach(e -> entityMap.put(e.getId(), e));
+
+ float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE;
+ for (final Entity e : entityMap.values()) {
+ final BoundingBox bb = e.get(BoundingBox.class);
+ minX = Math.min(minX, bb.getPosition().getX());
+ minY = Math.min(minY, bb.getPosition().getY());
+ }
+
+ grid.clear();
+ grid.setOrigin(new Vec2f(minX, minY));
+ grid.setCellSize(new Vec2f(cellSize, cellSize));
+ entityMap.forEach((id, e) -> grid.insert(id, e.get(BoundingBox.class)));
+
+ final Set<Vec2i> checkedPairs = new HashSet<>();
+
+ for (final Entity entityA : collidableEntities) {
+ if (!entityA.has(Velocity.class)) {
+ continue;
+ }
+ final BoundingBox bbA = entityA.get(BoundingBox.class);
+ final Velocity velocity = entityA.get(Velocity.class);
+
+ for (final int idB : grid.getNeighborIds(bbA)) {
+ final int idA = entityA.getId();
+ if (idB == idA) {
+ continue;
+ }
+ if (!checkedPairs.add(new Vec2i(Math.min(idA, idB), Math.max(idA, idB)))) {
+ continue;
+ }
+
+ final Entity entityB = entityMap.get(idB);
+ if (entityB == null || !entityB.has(TopCollidable.class)) {
+ continue;
+ }
+
+ final BoundingBox bbB = entityB.get(BoundingBox.class);
+ if (!bbA.isCollidingWith(bbB)) {
+ continue;
+ }
+ if (velocity.getVelocity().getY() > 0 || bbA.isAbove(bbB)) {
+ continue;
+ }
+
+ bbA.setPosition(new Vec2f(bbA.getPosition().getX(), bbB.getTop()));
+ velocity.setVelocity(new Vec2f(velocity.getVelocity().getX(), 0f));
+
+ if (entityA.has(Jump.class)) {
+ entityA.get(Jump.class).setCanJump(true);
+ }
+ if (entityA.has(Gravity.class) && entityA.has(Forces.class) && entityA.has(Mass.class)) {
+ entityA.get(Forces.class).add(new Force(new Vec2f(0f, entityA.get(Mass.class).getMass() * gravity)));
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java b/core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java
new file mode 100644
index 0000000..4a51ba8
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java
@@ -0,0 +1,55 @@
+package coffee.liz.ecs.common.systems.physics;
+
+import coffee.liz.ecs.common.components.physics.Force;
+import coffee.liz.ecs.common.components.physics.Forces;
+import coffee.liz.ecs.common.components.physics.Gravity;
+import coffee.liz.ecs.common.components.physics.Jump;
+import coffee.liz.ecs.common.components.physics.Mass;
+import coffee.liz.ecs.common.components.physics.Velocity;
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2f;
+import coffee.liz.ecs.model.System;
+import coffee.liz.ecs.model.World;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Collection;
+import java.util.Set;
+
+@RequiredArgsConstructor
+public class ForceReductionSystem implements System {
+ private final float gravity;
+
+ @Override
+ public Collection<Class<? extends System>> getDependencies() {
+ return Set.of();
+ }
+
+ @Override
+ public void update(final World world, final float deltaSeconds) {
+ world.queryable().allOf(Forces.class, Mass.class, Velocity.class).forEach(entity -> {
+ final Forces forces = entity.get(Forces.class);
+ final Mass mass = entity.get(Mass.class);
+ final Velocity velocity = entity.get(Velocity.class);
+
+ if (entity.has(Gravity.class)) {
+ final Gravity gravityComponent = entity.get(Gravity.class);
+ if (velocity.getVelocity().getY() > -gravityComponent.getTerminalVelocity()) {
+ forces.add(new Force(new Vec2f(0f, -mass.getMass() * gravity)));
+ }
+ }
+
+ Vec2<Float> netForce = Vec2f.ZERO;
+ for (final Force f : forces.getForces()) {
+ netForce = netForce.plus(f.getForce());
+ }
+ forces.clear();
+
+ final Vec2<Float> acceleration = netForce.scale(1f / mass.getMass(), 1f / mass.getMass());
+ velocity.setVelocity(velocity.getVelocity().plus(acceleration.scale(deltaSeconds, deltaSeconds)));
+
+ if (entity.has(Jump.class) && acceleration.getY() < 0) {
+ entity.get(Jump.class).setCanJump(false);
+ }
+ });
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java b/core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java
new file mode 100644
index 0000000..ba38b70
--- /dev/null
+++ b/core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java
@@ -0,0 +1,25 @@
+package coffee.liz.ecs.common.systems.physics;
+
+import coffee.liz.ecs.common.components.physics.BoundingBox;
+import coffee.liz.ecs.common.components.physics.Velocity;
+import coffee.liz.ecs.model.System;
+import coffee.liz.ecs.model.World;
+
+import java.util.Collection;
+import java.util.Set;
+
+public class IntegrationSystem implements System {
+ @Override
+ public Collection<Class<? extends System>> getDependencies() {
+ return Set.of(ForceReductionSystem.class);
+ }
+
+ @Override
+ public void update(final World world, final float deltaSeconds) {
+ world.queryable().allOf(Velocity.class, BoundingBox.class).forEach(entity -> {
+ final BoundingBox bb = entity.get(BoundingBox.class);
+ final Velocity velocity = entity.get(Velocity.class);
+ bb.setPosition(bb.getPosition().plus(velocity.getVelocity().scale(deltaSeconds, deltaSeconds)));
+ });
+ }
+}
diff --git a/core/src/main/java/coffee/liz/ecs/model/QueryBuilder.java b/core/src/main/java/coffee/liz/ecs/model/QueryBuilder.java
index eba5021..bc7c4f7 100644
--- a/core/src/main/java/coffee/liz/ecs/model/QueryBuilder.java
+++ b/core/src/main/java/coffee/liz/ecs/model/QueryBuilder.java
@@ -5,8 +5,8 @@ import lombok.RequiredArgsConstructor;
import java.util.Set;
@RequiredArgsConstructor
-public class QueryBuilder<T> {
- private final World<T> world;
+public class QueryBuilder {
+ private final World world;
@SafeVarargs
public final Set<Entity> allOf(final Class<? extends Component>... components) {
diff --git a/core/src/main/java/coffee/liz/ecs/model/System.java b/core/src/main/java/coffee/liz/ecs/model/System.java
index f16cdba..e9e0729 100644
--- a/core/src/main/java/coffee/liz/ecs/model/System.java
+++ b/core/src/main/java/coffee/liz/ecs/model/System.java
@@ -2,29 +2,10 @@ package coffee.liz.ecs.model;
import java.util.Collection;
-/**
- * Updates the {@link World} state.
- *
- * @param <T>
- * is the state of the stuff outside the {@link World}.
- */
-public interface System<T> {
- /**
- * {@link System} clazzes that must run before this system.
- *
- * @return {@link Collection} of dependencies.
- */
- Collection<Class<? extends System<T>>> getDependencies();
+public interface System {
+ Collection<Class<? extends System>> getDependencies();
- /**
- * @param world
- * Is the {@link World}.
- * @param state
- * Is the {@link T} state outside the {@param world}.
- * @param deltaSeconds
- * Is the timestamp.
- */
- void update(final World<T> world, final T state, final float deltaSeconds);
+ void update(World world, float deltaSeconds);
default void dispose() {
}
diff --git a/core/src/main/java/coffee/liz/ecs/model/World.java b/core/src/main/java/coffee/liz/ecs/model/World.java
index 82e01a7..63335c8 100644
--- a/core/src/main/java/coffee/liz/ecs/model/World.java
+++ b/core/src/main/java/coffee/liz/ecs/model/World.java
@@ -1,63 +1,21 @@
package coffee.liz.ecs.model;
-import java.time.Duration;
import java.util.Set;
-/**
- * The game world.
- *
- * @param <T>
- * is the state of the stuff outside the world.
- */
-public interface World<T> {
- /**
- * Create unique {@link Entity} in the {@link World}.
- *
- * @return created {@link Entity}.
- */
+public interface World {
Entity createEntity();
- /**
- * Remove an entity from the {@link World}.
- *
- * @param entity
- * to remove.
- */
- void removeEntity(final Entity entity);
+ void removeEntity(Entity entity);
- /**
- * Get entities with {@link Component}s.
- *
- * @param query
- * to query.
- * @return All entities satisfying {@param query}.
- */
- Set<Entity> resolve(final Query query);
+ Set<Entity> resolve(Query query);
- default QueryBuilder<T> queryable() {
- return new QueryBuilder<>(this);
+ default QueryBuilder queryable() {
+ return new QueryBuilder(this);
}
- /**
- * Integrate the {@link World}.
- *
- * @param state
- * Is the state outside the world.
- * @param deltaSeconds
- * Is the time step.
- */
- void update(T state, float deltaSeconds);
+ void update(float deltaSeconds);
- /**
- * Get world {@link System}.
- *
- * @param system
- * is the Clazz.
- * @param <S>
- * is the {@link System} type.
- * @return {@link System} instance of {@param system}.
- */
- <S extends System<T>> S getSystem(final Class<S> system);
+ <S extends System> S getSystem(Class<S> system);
default void dispose() {
}