diff options
Diffstat (limited to 'core/src/main/java/coffee/liz/ecs')
17 files changed, 423 insertions, 116 deletions
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/ecs/common/components/physics/Velocity.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java new file mode 100644 index 0000000..9b6a36b --- /dev/null +++ b/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java @@ -0,0 +1,14 @@ +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 Velocity implements Component { + 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() { } |
