aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/elf.pngbin3849 -> 0 bytes
-rw-r--r--assets/sprites/forest.pngbin0 -> 95274 bytes
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/Theme.java1
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java11
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java43
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java18
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java12
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java79
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java8
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/settings/SettingsInstruction.java16
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java80
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/entity/PlayerFactory.java27
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java9
-rw-r--r--core/src/main/java/coffee/liz/ecs/DAGWorld.java10
-rw-r--r--core/src/main/java/coffee/liz/ecs/math/Vec2i.java10
-rw-r--r--core/src/test/java/coffee/liz/ecs/DAGWorldTest.java45
20 files changed, 294 insertions, 89 deletions
diff --git a/assets/elf.png b/assets/elf.png
deleted file mode 100644
index 699603a..0000000
--- a/assets/elf.png
+++ /dev/null
Binary files differ
diff --git a/assets/sprites/forest.png b/assets/sprites/forest.png
new file mode 100644
index 0000000..10e9be8
--- /dev/null
+++ b/assets/sprites/forest.png
Binary files differ
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java b/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
index 097eabb..8c418af 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
@@ -1,7 +1,7 @@
package coffee.liz.abstractionengine.app;
import coffee.liz.abstractionengine.app.screen.ScrollLogo;
-import coffee.liz.abstractionengine.app.settings.SettingsInstruction;
+import coffee.liz.abstractionengine.app.config.Settings;
import coffee.liz.ecs.math.Vec2;
import coffee.liz.ecs.math.Vec2f;
import com.badlogic.gdx.Game;
@@ -22,7 +22,7 @@ public class AbstractionEngineGame extends Game {
public BitmapFont font;
public FitViewport viewport;
public ShapeRenderer shapeRenderer;
- public SettingsInstruction settings = SettingsInstruction.builder().build();
+ public Settings settings = Settings.builder().build();
/**
* Game initialization hook.
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java b/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
index ae2a159..bc653fd 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
@@ -2,6 +2,7 @@ package coffee.liz.abstractionengine.app;
import com.badlogic.gdx.graphics.Color;
+// TODO: Make this part of the {@link Settings}
public final class Theme {
public static final Color BG = Color.valueOf("2d2523");
public static final Color BG_PATTERN = Color.valueOf("241e1c");
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
index 8013735..ab3fcbb 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
@@ -1,7 +1,7 @@
package coffee.liz.abstractionengine.app.actor;
-import coffee.liz.abstractionengine.app.AbstractionEngineGame;
import coffee.liz.abstractionengine.app.Theme;
+import coffee.liz.abstractionengine.app.config.Settings;
import coffee.liz.abstractionengine.app.life.CellState;
import coffee.liz.abstractionengine.app.life.LifeInput;
import coffee.liz.abstractionengine.grid.component.GridPosition;
@@ -31,7 +31,7 @@ public class LifeGridActor extends Actor {
private final ShapeRenderer shapeRenderer;
private final World<LifeInput> world;
private final Vec2<Integer> gridDimensions;
- private final AbstractionEngineGame game;
+ private final Settings settings;
private final Color cellColor = new Color();
@Setter
@@ -54,7 +54,7 @@ public class LifeGridActor extends Actor {
final Vec2<Float> cellSize = computeCellSize();
final Set<Vec2<Integer>> forcedAlive = computeForcedAlive(cellSize);
- world.update(new LifeInput(forcedAlive, game.settings), Duration.ofMillis((int) (delta * 1000)));
+ world.update(new LifeInput(forcedAlive, settings), Duration.ofMillis((int) (delta * 1000)));
}
/**
@@ -75,7 +75,7 @@ public class LifeGridActor extends Actor {
shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
- drawCells();
+ drawCells(computeCellSize());
shapeRenderer.end();
batch.begin();
@@ -97,8 +97,7 @@ public class LifeGridActor extends Actor {
.collect(Collectors.toSet());
}
- private void drawCells() {
- final Vec2<Float> cellSize = computeCellSize();
+ private void drawCells(final Vec2<Float> cellSize) {
world.query(Set.of(GridPosition.class, CellState.class)).forEach(entity -> {
final CellState state = entity.get(CellState.class);
final Vec2<Integer> gridPos = entity.get(GridPosition.class).getPosition();
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java b/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java
new file mode 100644
index 0000000..598e1a8
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java
@@ -0,0 +1,43 @@
+package coffee.liz.abstractionengine.app.config;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+
+@Builder
+@AllArgsConstructor
+@RequiredArgsConstructor
+@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);
+
+ 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);
+ }
+ });
+ return actions;
+ }
+
+ public enum Action {
+ MOVE_UP, MOVE_LEFT, MOVE_DOWN, MOVE_RIGHT;
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java b/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java
new file mode 100644
index 0000000..3d8be7a
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java
@@ -0,0 +1,18 @@
+package coffee.liz.abstractionengine.app.config;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@AllArgsConstructor
+@Getter
+public class Settings {
+ @Builder.Default
+ private boolean skipIntro = true;
+ @Builder.Default
+ private boolean playMusic = true;
+
+ @Builder.Default
+ private KeyBinds keyBinds = KeyBinds.builder().build();
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
index 6f499a6..2900a96 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
@@ -22,7 +22,7 @@ public class EntropyAudioSystem implements System<LifeInput>, Disposable {
private static final int CHUNKS_X = 4;
private static final int CHUNKS_Y = 4;
private static final int NUM_CHUNKS = CHUNKS_X * CHUNKS_Y;
- private static final Duration AUDIO_THREAD_TIMEOUT = Duration.ofMillis(100);
+ private static final Duration AUDIO_THREAD_TIMEOUT = Duration.ofMillis(20);
private static final int[] PENTATONIC_INTERVALS = {0, 3, 5, 7, 10};
private static final float BASE_FREQUENCY = 110f;
@@ -63,11 +63,11 @@ public class EntropyAudioSystem implements System<LifeInput>, Disposable {
@Override
public void update(final World<LifeInput> world, final LifeInput state, final Duration dt) {
- if (!state.getGameInstructions().isPlayMusic()) {
- running = false;
- return;
- }
- running = true;
+ if (!state.getGameInstructions().isPlayMusic()) {
+ running = false;
+ return;
+ }
+ running = true;
final LifeSystem lifeSystem = world.getSystem(LifeSystem.class);
final Vec2<Integer> gridDimensions = lifeSystem.getDimensions();
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
index 8edf08d..36a1276 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
@@ -1,6 +1,6 @@
package coffee.liz.abstractionengine.app.life;
-import coffee.liz.abstractionengine.app.settings.SettingsInstruction;
+import coffee.liz.abstractionengine.app.config.Settings;
import coffee.liz.ecs.math.Vec2;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@@ -11,5 +11,5 @@ import java.util.Set;
@Data
public class LifeInput {
private final Set<Vec2<Integer>> forceAliveCells;
- private final SettingsInstruction gameInstructions;
+ private final Settings gameInstructions;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
index fc6d2e6..40f0d99 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
@@ -2,28 +2,43 @@ package coffee.liz.abstractionengine.app.screen;
import coffee.liz.abstractionengine.AbstractionEngineGridWorld;
import coffee.liz.abstractionengine.app.AbstractionEngineGame;
+import coffee.liz.abstractionengine.app.Theme;
+import coffee.liz.abstractionengine.entity.EntityFactory;
+import coffee.liz.abstractionengine.entity.EntityType;
import coffee.liz.abstractionengine.grid.component.GridInputState;
-import coffee.liz.ecs.DAGWorld;
+import coffee.liz.abstractionengine.grid.component.GridPosition;
import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2f;
import coffee.liz.ecs.math.Vec2i;
-import coffee.liz.ecs.model.World;
+import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.badlogic.gdx.utils.ScreenUtils;
import lombok.RequiredArgsConstructor;
-import java.util.Map;
+import java.time.Duration;
+import java.util.Set;
@RequiredArgsConstructor
public class GameScreen implements Screen {
private final AbstractionEngineGame game;
private static final Vec2<Integer> GAME_GRID_SIZE = Vec2i.builder().x(30).y(30).build();
- private final World<GridInputState> gameWorld = new AbstractionEngineGridWorld(GAME_GRID_SIZE);
+ private final static Duration GRID_INTERPOLATION_TIME = Duration.ofMillis(60);
+
+ private final AbstractionEngineGridWorld gameWorld = new AbstractionEngineGridWorld(GAME_GRID_SIZE);
+ private Duration sinceUpdate = Duration.ZERO;
/**
* Screen lifecycle hook.
*/
@Override
public void show() {
- // gameWorld.
+ EntityFactory.populateRect(GAME_GRID_SIZE, gameWorld, EntityFactory.Wall::addToWorld);
+ EntityFactory.Player.addToWorld(gameWorld, Vec2i.builder().y(20).x(10).build());
+ EntityFactory.Abstraction.addToWorld(gameWorld, Vec2i.builder().y(20).x(12).build());
+ EntityFactory.Abstraction.addToWorld(gameWorld, Vec2i.builder().y(20).x(13).build());
+ EntityFactory.Abstraction.addToWorld(gameWorld, Vec2i.builder().y(20).x(14).build());
}
/**
@@ -34,7 +49,54 @@ public class GameScreen implements Screen {
*/
@Override
public void render(final float delta) {
+ game.viewport.apply();
+ sinceUpdate = sinceUpdate.plus(Duration.ofMillis((int) (delta * 1000)));
+ if (GRID_INTERPOLATION_TIME.compareTo(sinceUpdate) > 0) {
+ return;
+ } else {
+ sinceUpdate = Duration.ZERO;
+ }
+
+ ScreenUtils.clear(Theme.BG);
+
+ final GridInputState state = GridInputState.builder().movement(getMovementVector()).build();
+ gameWorld.update(state);
+
+ final Vec2<Float> cellSize = computeCellSize();
+ game.shapeRenderer.setProjectionMatrix(game.batch.getProjectionMatrix());
+ game.shapeRenderer.setTransformMatrix(game.batch.getTransformMatrix());
+ game.shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
+ gameWorld.query(Set.of(GridPosition.class, EntityType.class)).forEach(entity -> {
+ final EntityType type = entity.get(EntityType.class);
+ final GridPosition position = entity.get(GridPosition.class);
+
+ final Vec2<Float> drawPos = position.getPosition().floatValue().scale(cellSize);
+ game.shapeRenderer.setColor(getEntityColor(type));
+ game.shapeRenderer.rect(drawPos.getX(), drawPos.getY(), cellSize.getX(), cellSize.getY());
+ });
+ game.shapeRenderer.end();
+ }
+
+ private Vec2<Integer> getMovementVector() {
+ return game.settings.getKeyBinds().filterActiveActions(Gdx.input::isKeyPressed).stream().reduce(Vec2i.ZERO,
+ (movement, action) -> {
+ final Vec2<Integer> velocity = switch (action) {
+ case MOVE_UP -> Vec2i.NORTH;
+ case MOVE_DOWN -> Vec2i.SOUTH;
+ case MOVE_LEFT -> Vec2i.WEST;
+ case MOVE_RIGHT -> Vec2i.EAST;
+ };
+ return movement.plus(velocity);
+ }, Vec2::plus);
+ }
+ private Color getEntityColor(final EntityType type) {
+ return switch (type) {
+ case WALL -> Theme.BORDER;
+ case PLAYER -> Theme.PRIMARY;
+ case ABSTRACTION -> Theme.SECONDARY;
+ default -> Color.GREEN;
+ };
}
/**
@@ -47,7 +109,7 @@ public class GameScreen implements Screen {
*/
@Override
public void resize(final int width, final int height) {
-
+ game.viewport.update(width, height);
}
/**
@@ -81,4 +143,9 @@ public class GameScreen implements Screen {
public void dispose() {
}
+
+ private Vec2<Float> computeCellSize() {
+ return Vec2f.builder().x(game.viewport.getWorldWidth() / GAME_GRID_SIZE.getX())
+ .y(game.viewport.getWorldHeight() / GAME_GRID_SIZE.getY()).build();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
index 45775ea..076e93f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
@@ -53,7 +53,7 @@ public class MainMenu implements Screen {
stage = new Stage(game.viewport, game.batch);
world.getSystem(EntropyAudioSystem.class).start();
- lifeGridActor = new LifeGridActor(game.shapeRenderer, world, GRID_DIMENSIONS, game);
+ lifeGridActor = new LifeGridActor(game.shapeRenderer, world, GRID_DIMENSIONS, game.settings);
lifeGridActor.setViewport(game.viewport);
stage.addActor(lifeGridActor);
@@ -98,8 +98,10 @@ public class MainMenu implements Screen {
game.viewport.apply();
ScreenUtils.clear(Theme.BG);
+
updateParallax();
stage.act(delta);
+
stage.draw();
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
index 610bb4e..bb8aef2 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
@@ -86,10 +86,10 @@ public class ScrollLogo implements Screen {
public void render(final float delta) {
game.viewport.apply();
ScreenUtils.clear(Theme.BG);
- if (game.settings.isSkipIntro()) {
- requestTransition();
- return;
- }
+ if (game.settings.isSkipIntro()) {
+ requestTransition();
+ return;
+ }
stage.act(delta);
stage.draw();
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/settings/SettingsInstruction.java b/core/src/main/java/coffee/liz/abstractionengine/app/settings/SettingsInstruction.java
deleted file mode 100644
index 6fe9d88..0000000
--- a/core/src/main/java/coffee/liz/abstractionengine/app/settings/SettingsInstruction.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package coffee.liz.abstractionengine.app.settings;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-
-@Builder
-@AllArgsConstructor
-@Getter
-public class SettingsInstruction {
- @Builder.Default
- private boolean skipIntro = true;
-
- @Builder.Default
- private boolean playMusic = true;
-}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java
new file mode 100644
index 0000000..99a6eb7
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java
@@ -0,0 +1,80 @@
+package coffee.liz.abstractionengine.entity;
+
+import coffee.liz.abstractionengine.grid.component.GridControllable;
+import coffee.liz.abstractionengine.grid.component.GridPosition;
+import coffee.liz.ecs.math.Mat2;
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.model.Entity;
+import coffee.liz.ecs.model.World;
+
+import java.util.List;
+import java.util.function.BiFunction;
+
+public final class EntityFactory {
+ private EntityFactory() {
+ }
+
+ /**
+ * {@link EntityType#PLAYER} factory.
+ */
+ public final class Player {
+ private Player() {
+ }
+
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(new GridControllable())
+ .add(EntityType.PLAYER).add(new EntityTypeGridCollidable());
+ }
+ }
+
+ /**
+ * {@link EntityType#WALL} factory.
+ */
+ public final class Wall {
+ private Wall() {
+ }
+
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(EntityType.WALL)
+ .add(new EntityTypeGridCollidable());
+ }
+ }
+
+ /**
+ * {@link EntityType#ABSTRACTION} factory.
+ */
+ public final class Abstraction {
+ private Abstraction() {
+ }
+
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(EntityType.ABSTRACTION)
+ .add(new EntityTypeGridCollidable());
+ }
+ }
+
+ /**
+ * Populates entities on the border of a rectangle of defined dimensions.
+ *
+ * @param dimensions
+ * are the world dimensions.
+ * @param world
+ * is the world to populate
+ * @param factory
+ * accepts the world and position in the world and creates the
+ * entity.
+ * @return 2d matrix of entities at each position in the world of populated
+ * entities.
+ */
+ public static List<List<Entity>> populateRect(final Vec2<Integer> dimensions, final World<?> world,
+ final BiFunction<World<?>, Vec2<Integer>, Entity> factory) {
+ return Mat2.init(dimensions, pos -> {
+ final boolean isXBorder = pos.getX() == 0 || pos.getX() == dimensions.getX() - 1;
+ final boolean isYBorder = pos.getY() == 0 || pos.getY() == dimensions.getY() - 1;
+ if (isXBorder || isYBorder) {
+ return factory.apply(world, pos);
+ }
+ return null;
+ });
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/entity/PlayerFactory.java b/core/src/main/java/coffee/liz/abstractionengine/entity/PlayerFactory.java
deleted file mode 100644
index 240a94e..0000000
--- a/core/src/main/java/coffee/liz/abstractionengine/entity/PlayerFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package coffee.liz.abstractionengine.entity;
-
-import coffee.liz.abstractionengine.grid.component.GridControllable;
-import coffee.liz.abstractionengine.grid.component.GridPosition;
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.model.Entity;
-import coffee.liz.ecs.model.World;
-
-/** Factory for creating player {@link Entity}s. */
-public final class PlayerFactory {
- private PlayerFactory() {
- }
-
- /**
- * Create a player entity.
- *
- * @param world
- * the {@link World} to create in
- * @param position
- * the starting {@link Vec2} position
- * @return created player {@link Entity}
- */
- public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
- return world.createEntity().add(new GridPosition(position)).add(new GridControllable()).add(EntityType.PLAYER)
- .add(new EntityTypeGridCollidable());
- }
-}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
index 61044f6..4af8be0 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
@@ -25,7 +25,7 @@ public abstract class BaseGridIndexSystem<T> implements System<T> {
public BaseGridIndexSystem(final Vec2<Integer> dimensions) {
this.dimensions = dimensions;
- this.rows = Mat2.init(dimensions, pos -> new HashSet<>());
+ this.rows = Mat2.init(dimensions, _ -> new HashSet<>());
}
@Override
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
index 9d07b59..33c86c8 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
@@ -31,7 +31,6 @@ public class GridCollisionPropagatationSystem implements System<GridInputState>
@Override
public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
- final GridIndexSystem indexSystem = world.getSystem(GridIndexSystem.class);
world.query(Set.of(GridMomentum.class, GridPosition.class, GridCollidable.class)).forEach(pusher -> {
final Vec2<Integer> velocity = pusher.get(GridMomentum.class).getVelocity();
if (velocity.equals(Vec2i.ZERO)) {
@@ -81,12 +80,8 @@ public class GridCollisionPropagatationSystem implements System<GridInputState>
.min(Comparator.comparing(e -> e.getValue().getPriority())).orElseThrow();
switch (behavior.getValue().getCollisionBehaviorType()) {
- case PROPAGATE -> {
- nextRay.add(behavior.getKey());
- }
- case SWALLOW -> {
- swallows.add(Map.entry(behavior.getKey(), push));
- }
+ case PROPAGATE -> nextRay.add(behavior.getKey());
+ case SWALLOW -> swallows.add(Map.entry(behavior.getKey(), push));
case WALL -> {
return new CollisionRayResult.Blocked();
}
diff --git a/core/src/main/java/coffee/liz/ecs/DAGWorld.java b/core/src/main/java/coffee/liz/ecs/DAGWorld.java
index 716808a..f3ad30b 100644
--- a/core/src/main/java/coffee/liz/ecs/DAGWorld.java
+++ b/core/src/main/java/coffee/liz/ecs/DAGWorld.java
@@ -84,10 +84,11 @@ public class DAGWorld<T> implements World<T> {
@Override
public void update(final T state, final Duration duration) {
- refreshComponentCache();
systemExecutionOrder.forEach(system -> {
+ refreshComponentCache();
system.update(this, state, duration);
});
+ refreshComponentCache();
}
@SuppressWarnings("unchecked")
@@ -98,11 +99,8 @@ public class DAGWorld<T> implements World<T> {
private void refreshComponentCache() {
componentCache.clear();
- entities.forEach(entity -> {
- entity.getComponentMap().keySet().forEach(componentType -> {
- componentCache.computeIfAbsent(componentType, k -> new HashSet<>()).add(entity);
- });
- });
+ entities.forEach(entity -> entity.getComponentMap().keySet().forEach(
+ componentType -> componentCache.computeIfAbsent(componentType, _ -> new HashSet<>()).add(entity)));
}
private List<System<T>> buildExecutionOrder(final Collection<System<T>> systems) {
diff --git a/core/src/main/java/coffee/liz/ecs/math/Vec2i.java b/core/src/main/java/coffee/liz/ecs/math/Vec2i.java
index c7f9c83..b07e481 100644
--- a/core/src/main/java/coffee/liz/ecs/math/Vec2i.java
+++ b/core/src/main/java/coffee/liz/ecs/math/Vec2i.java
@@ -57,9 +57,9 @@ public final class Vec2i implements Vec2<Integer> {
return (float) sqrt(x * x + y * y);
}
- public static final Vec2i NORTH = new Vec2i(0, -1);
- public static final Vec2i SOUTH = new Vec2i(0, 1);
- public static final Vec2i EAST = new Vec2i(1, 0);
- public static final Vec2i WEST = new Vec2i(-1, 0);
- public static final Vec2i ZERO = new Vec2i(0, 0);
+ public static final Vec2<Integer> NORTH = new Vec2i(0, 1);
+ public static final Vec2<Integer> SOUTH = new Vec2i(0, -1);
+ public static final Vec2<Integer> EAST = new Vec2i(1, 0);
+ public static final Vec2<Integer> WEST = new Vec2i(-1, 0);
+ public static final Vec2<Integer> ZERO = new Vec2i(0, 0);
}
diff --git a/core/src/test/java/coffee/liz/ecs/DAGWorldTest.java b/core/src/test/java/coffee/liz/ecs/DAGWorldTest.java
index 2f948d0..a656d28 100644
--- a/core/src/test/java/coffee/liz/ecs/DAGWorldTest.java
+++ b/core/src/test/java/coffee/liz/ecs/DAGWorldTest.java
@@ -80,6 +80,24 @@ final class DAGWorldTest {
}
@Test
+ public void queryFindsComponentsAddedByEarlierSystemInSameTick() {
+ final List<Set<Entity>> queryResults = new CopyOnWriteArrayList<>();
+
+ final Map<Class<? extends System<String>>, System<String>> systems = new LinkedHashMap<>();
+ systems.put(ComponentAdderSystem.class, new ComponentAdderSystem());
+ systems.put(ComponentReaderSystem.class, new ComponentReaderSystem(queryResults));
+ final DAGWorld<String> world = new DAGWorld<>(systems);
+
+ final Entity entity = world.createEntity();
+ entity.add(new PositionComponent());
+
+ world.update("state", Duration.ZERO);
+
+ assertEquals(1, queryResults.size());
+ assertEquals(Set.of(entity), queryResults.getFirst());
+ }
+
+ @Test
public void circularDependencyDetectionThrowsIllegalStateException() {
final Map<Class<? extends System<String>>, System<String>> systems = new LinkedHashMap<>();
final SystemCycleA systemA = new SystemCycleA();
@@ -161,4 +179,31 @@ final class DAGWorldTest {
public void update(final World<String> world, final String state, final Duration duration) {
}
}
+
+ private static final class ComponentAdderSystem implements System<String> {
+ @Override
+ public Collection<Class<? extends System<String>>> getDependencies() {
+ return List.of();
+ }
+
+ @Override
+ public void update(final World<String> world, final String state, final Duration duration) {
+ world.query(Set.of(PositionComponent.class)).forEach(e -> e.add(new VelocityComponent()));
+ }
+ }
+
+ @RequiredArgsConstructor
+ private static final class ComponentReaderSystem implements System<String> {
+ private final List<Set<Entity>> queryResults;
+
+ @Override
+ public Collection<Class<? extends System<String>>> getDependencies() {
+ return Set.of(ComponentAdderSystem.class);
+ }
+
+ @Override
+ public void update(final World<String> world, final String state, final Duration duration) {
+ queryResults.add(world.query(Set.of(VelocityComponent.class, PositionComponent.class)));
+ }
+ }
}