diff options
| author | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-03-01 12:54:31 -0800 |
|---|---|---|
| committer | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-03-01 12:54:47 -0800 |
| commit | 242b32050feff1d7f047e52d46daadd3ec682c14 (patch) | |
| tree | 6207a3f350946ae3b1c2764b2bb9321473f6bfaa | |
| parent | c491b5cb08972ffc041fa0b968810373b9ed79a3 (diff) | |
| download | dyl-242b32050feff1d7f047e52d46daadd3ec682c14.tar.gz dyl-242b32050feff1d7f047e52d46daadd3ec682c14.zip | |
Adding animations n stuff.
40 files changed, 554 insertions, 305 deletions
diff --git a/assets/noir/hero.png b/assets/noir/hero.png Binary files differnew file mode 100755 index 0000000..08e2d61 --- /dev/null +++ b/assets/noir/hero.png diff --git a/assets/player.png b/assets/player.png Binary files differdeleted file mode 100644 index 2e95386..0000000 --- a/assets/player.png +++ /dev/null diff --git a/core/src/main/java/coffee/liz/dyl/DylGame.java b/core/src/main/java/coffee/liz/dyl/DylGame.java index 1166d42..aff4066 100644 --- a/core/src/main/java/coffee/liz/dyl/DylGame.java +++ b/core/src/main/java/coffee/liz/dyl/DylGame.java @@ -15,8 +15,8 @@ import lombok.Getter; @Getter public class DylGame extends Game { - public static final float WORLD_WIDTH = 10f; - public static final float WORLD_HEIGHT = 10f; + public static final float WORLD_WIDTH = 20f; + public static final float WORLD_HEIGHT = 20f; private InputMultiplexer inputMultiplexer; private Batch batch; diff --git a/core/src/main/java/coffee/liz/dyl/components/AnimationState.java b/core/src/main/java/coffee/liz/dyl/components/AnimationState.java new file mode 100644 index 0000000..04505c5 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/AnimationState.java @@ -0,0 +1,36 @@ +package coffee.liz.dyl.components; + +import coffee.liz.dyl.components.graphic.AnimationGraphic; +import coffee.liz.ecs.model.Component; +import jakarta.annotation.Nullable; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +@RequiredArgsConstructor +public class AnimationState implements Component { + private State currentState; + private State transition; + + private final Map<State, AnimationGraphic> animationStates; + + @Nullable + public AnimationGraphic getTransitionAnimation() { + if (transition == null) { + return null; + } + return animationStates.get(transition); + } + + public enum State { + IDLE, + RUN, + JUMP, + DAMAGE + } +} diff --git a/core/src/main/java/coffee/liz/dyl/components/DamageGraceTime.java b/core/src/main/java/coffee/liz/dyl/components/DamageGraceTime.java new file mode 100644 index 0000000..8424639 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/DamageGraceTime.java @@ -0,0 +1,17 @@ +package coffee.liz.dyl.components; + +import coffee.liz.ecs.model.Component; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class DamageGraceTime implements Component { + private float duration; + + public void decrement(final float deltaTime) { + duration -= deltaTime; + } + + public boolean isOver() { + return duration <= 0; + } +} diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java b/core/src/main/java/coffee/liz/dyl/components/FacingDirection.java index 7d5dab1..d517fc1 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java +++ b/core/src/main/java/coffee/liz/dyl/components/FacingDirection.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.model.Component; @@ -7,6 +7,6 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Getter -public class Force implements Component { - private final Vec2<Float> force; +public class FacingDirection implements Component { + private final Vec2<Float> unitDirection; } diff --git a/core/src/main/java/coffee/liz/dyl/components/graphic/AnimationGraphic.java b/core/src/main/java/coffee/liz/dyl/components/graphic/AnimationGraphic.java new file mode 100644 index 0000000..43242b3 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/graphic/AnimationGraphic.java @@ -0,0 +1,47 @@ +package coffee.liz.dyl.components.graphic; + +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.ecs.math.Vec2; +import coffee.liz.ecs.math.Vec2f; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.Animation; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.time.Duration; +import java.time.Instant; + +@Getter +@RequiredArgsConstructor +public class AnimationGraphic implements Graphic { + private final Color color; + private final Animation<TextureRegion> animation; + private final int z; + private Instant lastUpdate = null; + private Vec2<Float> unitDirection = Vec2f.ZERO; + + @Override + public void setFacing(final Vec2<Float> unitDirection) { + this.unitDirection = unitDirection; + } + + @Override + public void draw(final Batch batch, final BoundingBox boundingBox) { + final Instant now = Instant.now(); + if (lastUpdate == null) lastUpdate = now; + + final float stateDuration = (float) (Duration.between(lastUpdate, now).toMillis()) / 1000f; + final float x = boundingBox.getPosition().getX(); + final float y = boundingBox.getPosition().getY(); + final float w = boundingBox.getSize().getX(); + final float h = boundingBox.getSize().getY(); + batch.setColor(color); + if (unitDirection.getX() < 0) { + batch.draw(animation.getKeyFrame(stateDuration, true), x + w, y, -w, h); + } else { + batch.draw(animation.getKeyFrame(stateDuration, true), x, y, w, h); + } + } +} 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 7075755..3e12083 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,7 @@ package coffee.liz.dyl.components.graphic; -import coffee.liz.ecs.common.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.model.Component; import com.badlogic.gdx.graphics.g2d.Batch; @@ -12,4 +13,6 @@ public interface Graphic extends Component { int getZ(); void draw(final Batch batch, final BoundingBox boundingBox); + + default void setFacing(final Vec2<Float> unitDirection) {} } 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 c2718b5..8cca8ac 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,25 +1,37 @@ package coffee.liz.dyl.components.graphic; -import coffee.liz.ecs.common.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.ecs.math.Vec2; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; @Getter -@AllArgsConstructor +@RequiredArgsConstructor public class TextureGraphic implements Graphic { - private int z; - private Color color; - private Texture texture; + private final int z; + private final Color color; + private final Texture texture; + private boolean facingLeft = false; + + @Override + public void setFacing(final Vec2<Float> unitDirection) { + this.facingLeft = unitDirection.getX() < 0; + } @Override public void draw(final Batch batch, final BoundingBox boundingBox) { + final float x = boundingBox.getPosition().getX(); + final float y = boundingBox.getPosition().getY(); + final float w = boundingBox.getSize().getX(); + final float h = boundingBox.getSize().getY(); batch.setColor(color); - batch.draw(texture, - boundingBox.getPosition().getX(), boundingBox.getPosition().getY(), - boundingBox.getSize().getX(), boundingBox.getSize().getY() - ); + if (facingLeft) { + batch.draw(texture, x + w, y, -w, h); + } else { + batch.draw(texture, x, y, w, h); + } } } diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java b/core/src/main/java/coffee/liz/dyl/components/physics/BoundingBox.java index 7a31cae..db484db 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/BoundingBox.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.model.Component; diff --git a/core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java b/core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java new file mode 100644 index 0000000..b709751 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java @@ -0,0 +1,20 @@ +package coffee.liz.dyl.components.physics; + +import coffee.liz.ecs.model.Component; +import coffee.liz.ecs.model.Entity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CollisionContacts implements Component { + private final List<Entity> contacts = new ArrayList<>(); + + public void add(final Entity entity) { + contacts.add(entity); + } + + public List<Entity> getAll() { + return Collections.unmodifiableList(contacts); + } +} diff --git a/core/src/main/java/coffee/liz/dyl/components/physics/Force.java b/core/src/main/java/coffee/liz/dyl/components/physics/Force.java new file mode 100644 index 0000000..de8b003 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Force.java @@ -0,0 +1,11 @@ +package coffee.liz.dyl.components.physics; + +import coffee.liz.ecs.math.Vec2; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class Force { + 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/dyl/components/physics/Forces.java index f6c9ee8..e90cd7f 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Forces.java @@ -1,5 +1,7 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; +import coffee.liz.ecs.math.Vec2; +import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.model.Component; import lombok.Getter; @@ -14,6 +16,10 @@ public class Forces implements Component { forces.add(force); } + public Vec2<Float> sum() { + return forces.stream().map(Force::getForce).reduce(Vec2::plus).orElse(Vec2f.ZERO); + } + 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/dyl/components/physics/Gravity.java index 44d5caf..a6e4c14 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Gravity.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.model.Component; import lombok.Getter; diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java b/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java index 5224b32..c49d6e1 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.model.Component; import lombok.AllArgsConstructor; diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java b/core/src/main/java/coffee/liz/dyl/components/physics/Mass.java index f38ccc0..19425f5 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Mass.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.model.Component; import lombok.Getter; diff --git a/core/src/main/java/coffee/liz/dyl/components/physics/Solid.java b/core/src/main/java/coffee/liz/dyl/components/physics/Solid.java new file mode 100644 index 0000000..57af1e3 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Solid.java @@ -0,0 +1,5 @@ +package coffee.liz.dyl.components.physics; + +import coffee.liz.ecs.model.Component; + +public class Solid implements Component {} diff --git a/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java b/core/src/main/java/coffee/liz/dyl/components/physics/Velocity.java index 9b6a36b..b42d3a6 100644 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Velocity.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.model.Component; 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 0b33b26..620faad 100644 --- a/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java +++ b/core/src/main/java/coffee/liz/dyl/config/KeyBinds.java @@ -2,7 +2,6 @@ package coffee.liz.dyl.config; import com.badlogic.gdx.Input; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -11,17 +10,13 @@ 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> 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); + private Set<Integer> jumpKeys = Set.of(Input.Keys.K, Input.Keys.W, Input.Keys.UP, Input.Keys.SPACE); public Set<Action> filterActiveActions(final Predicate<Integer> isDown) { final Set<Action> actions = new HashSet<>(); diff --git a/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java b/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java index b0b1a31..6339a34 100644 --- a/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java +++ b/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java @@ -1,12 +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; + public static final float GRAVITY = 40f; + public static final float MOVE_SPEED = 8.0f; + public static final float JUMP_INITIAL_VEL = 7.0f; + public static final float JUMP_ACC = 30.0f; + public static final long MAX_JUMP_MS = 200L; + public static final float DAMAGE_TIME = 0.25f; - private PhysicsConstants() { - } + private PhysicsConstants() { } } diff --git a/core/src/main/java/coffee/liz/dyl/config/Settings.java b/core/src/main/java/coffee/liz/dyl/config/Settings.java index 13fbb3c..73f39f9 100644 --- a/core/src/main/java/coffee/liz/dyl/config/Settings.java +++ b/core/src/main/java/coffee/liz/dyl/config/Settings.java @@ -12,5 +12,5 @@ public class Settings { @Builder.Default private boolean playMusic = true; @Builder.Default - private KeyBinds keyBinds = KeyBinds.builder().build(); + private KeyBinds keyBinds = new KeyBinds(); } 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 a982bb9..c857d02 100644 --- a/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java +++ b/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java @@ -1,44 +1,88 @@ package coffee.liz.dyl.entities; +import coffee.liz.dyl.components.AnimationState; import coffee.liz.dyl.components.Controllable; -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.dyl.components.FacingDirection; +import coffee.liz.dyl.components.graphic.AnimationGraphic; +import coffee.liz.dyl.config.PhysicsConstants; +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.Forces; +import coffee.liz.dyl.components.physics.Gravity; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Mass; +import coffee.liz.dyl.components.physics.Velocity; +import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2f; -import coffee.liz.ecs.model.Entity; +import coffee.liz.ecs.math.Vec2i; import coffee.liz.ecs.model.World; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import java.util.Map; + 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); - - 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(0, Color.PINK, tmp[0][0].getTexture())) - .add(new Controllable()) - .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 static final PlayerAssets ASSETS = new PlayerAssets(); + + public static void addTo(final World world) { + final var animationState = new AnimationState( + Map.of( + AnimationState.State.JUMP, new AnimationGraphic(Color.WHITE, ASSETS.jumping, 0), + AnimationState.State.DAMAGE, new AnimationGraphic(Color.valueOf("#0000000a"), ASSETS.damaged, 0), + AnimationState.State.IDLE, new AnimationGraphic(Color.WHITE, ASSETS.idling, 0), + AnimationState.State.RUN, new AnimationGraphic(Color.WHITE, ASSETS.running, 0))); + world.createEntity() + .add(animationState) + .add(animationState.getAnimationStates().get(AnimationState.State.IDLE)) + .add(new Controllable()) + .add(new BoundingBox(new Vec2f(1f, 1f), new Vec2f(1f, 1f))) + .add(new Velocity(Vec2f.ZERO)) + .add(new Mass(0.8f)) + .add(new Forces()) + .add(new FacingDirection(Vec2f.ZERO)) + .add(new Gravity(20f)) + .add(new Jump(false, 0L)); } - private PlayerFactory() { + private static class PlayerAssets { + private static final Vec2<Integer> DIMS = new Vec2i(14, 8); + private static final FileHandle FILE = Gdx.files.internal("noir/hero.png"); + final Texture texture; + final TextureRegion[][] region; + final Animation<TextureRegion> idling; + final Animation<TextureRegion> damaged; + final Animation<TextureRegion> jumping; + final Animation<TextureRegion> running; + public PlayerAssets() { + texture = new Texture(FILE); + region = TextureRegion.split(texture, + texture.getWidth() / DIMS.getX(), + texture.getHeight() / DIMS.getY() + ); + + final TextureRegion[] idlingTextureRegion = new TextureRegion[2]; + idlingTextureRegion[0] = region[5][0]; + idlingTextureRegion[1] = region[5][1]; + + final TextureRegion[] runningTextureRegion = new TextureRegion[2]; + runningTextureRegion[0] = region[0][0]; + runningTextureRegion[1] = region[0][1]; + + final TextureRegion[] damagedTextureRegion = new TextureRegion[1]; + damagedTextureRegion[0] = region[6][0]; + + final TextureRegion[] jump = new TextureRegion[1]; + jump[0] = region[1][0]; + + running = new Animation<>(0.20f, runningTextureRegion); + idling = new Animation<>(0.75f, idlingTextureRegion); + damaged = new Animation<>(PhysicsConstants.DAMAGE_TIME, damagedTextureRegion); + jumping = new Animation<>(0.75f, jump); + } } + + private PlayerFactory() { } } diff --git a/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java b/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java new file mode 100644 index 0000000..8c0d595 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java @@ -0,0 +1,56 @@ +package coffee.liz.dyl.systems; + +import coffee.liz.dyl.components.AnimationState; +import coffee.liz.dyl.components.FacingDirection; +import coffee.liz.dyl.components.graphic.AnimationGraphic; +import coffee.liz.dyl.components.graphic.Graphic; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Velocity; +import coffee.liz.dyl.systems.physics.CollisionSystem; +import coffee.liz.ecs.model.System; +import coffee.liz.ecs.model.World; + +import java.util.Collection; +import java.util.List; + +public class AnimationSystem implements System { + @Override + public Collection<Class<? extends System>> getDependencies() { + return List.of(InputSystem.class, CollisionSystem.class, DamageSystem.class); + } + + @Override + public void update(final World world, final float deltaSeconds) { + world.queryable().allOf(AnimationState.class, Velocity.class).forEach(entity -> { + final AnimationState animationState = entity.get(AnimationState.class); + final Velocity velocity = entity.get(Velocity.class); + final Jump jump = entity.get(Jump.class); + + if (!jump.isCanJump()) { + animationState.setTransition(AnimationState.State.JUMP); + return; + } + if (velocity.getVelocity().getX() != 0) { + animationState.setTransition(AnimationState.State.RUN); + return; + } + animationState.setTransition(AnimationState.State.IDLE); + }); + + world.queryable().allOf(AnimationState.class).forEach(entity -> { + final AnimationState animationState = entity.get(AnimationState.class); + final AnimationGraphic animation = animationState.getTransitionAnimation(); + if (animation == null) { + return; + } + if (entity.has(FacingDirection.class)) { + animation.setFacing(entity.get(FacingDirection.class).getUnitDirection()); + } + if (animationState.getTransition().equals(animationState.getCurrentState())) { + return; + } + + entity.add(animation); + }); + } +} diff --git a/core/src/main/java/coffee/liz/dyl/systems/DamageSystem.java b/core/src/main/java/coffee/liz/dyl/systems/DamageSystem.java new file mode 100644 index 0000000..60db760 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/systems/DamageSystem.java @@ -0,0 +1,23 @@ +package coffee.liz.dyl.systems; + +import coffee.liz.dyl.systems.physics.CollisionSystem; +import coffee.liz.ecs.model.System; +import coffee.liz.ecs.model.World; + +import java.util.Collection; +import java.util.List; + +public class DamageSystem implements System { + + @Override + public Collection<Class<? extends System>> getDependencies() { + return List.of(CollisionSystem.class); + } + + @Override + public void update(final World world, final float deltaSeconds) { +// world.queryable().allOf(CollisionContacts.class) +// world.queryable().allOf(DamageGraceTime.class).forEach() + // TODO: Set opacity + } +} 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 d5acbaf..1938a50 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java @@ -1,12 +1,13 @@ package coffee.liz.dyl.systems; import coffee.liz.dyl.components.Controllable; +import coffee.liz.dyl.components.FacingDirection; import coffee.liz.dyl.config.KeyBinds; -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.dyl.components.physics.Force; +import coffee.liz.dyl.components.physics.Forces; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Mass; +import coffee.liz.dyl.components.physics.Velocity; import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.model.System; import coffee.liz.ecs.model.World; @@ -35,27 +36,29 @@ public class InputSystem implements System { public void update(final World world, final float deltaSeconds) { final Set<KeyBinds.Action> actions = activeActions.get(); - world.queryable().allOf(Controllable.class, Velocity.class).forEach(entity -> { + world.queryable().allOf(Forces.class, Controllable.class, Velocity.class).forEach(entity -> { final Velocity velocity = entity.get(Velocity.class); float dx = 0f; - if (actions.contains(KeyBinds.Action.MOVE_LEFT)) dx = -MOVE_SPEED; - if (actions.contains(KeyBinds.Action.MOVE_RIGHT)) dx = MOVE_SPEED; + if (actions.contains(KeyBinds.Action.MOVE_LEFT)) dx -= MOVE_SPEED; + if (actions.contains(KeyBinds.Action.MOVE_RIGHT)) dx += MOVE_SPEED; + if (dx != 0) { + entity.add(new FacingDirection(new Vec2f(dx / MOVE_SPEED, 0f))); + } float newDy = velocity.getVelocity().getY(); - 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); + 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))); - } + if (actions.contains(KeyBinds.Action.JUMP)) { + final boolean applyForce = Instant.now().toEpochMilli() - jump.getJumpStartMs() < MAX_JUMP_MS; + if (jump.isCanJump()) { + newDy = JUMP_INITIAL_VEL; + jump.setCanJump(false); + jump.setJumpStartMs(Instant.now().toEpochMilli()); + } else if (applyForce) { + entity.get(Forces.class).add(new Force(new Vec2f(0f, mass.getMass() * JUMP_ACC))); } } 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 15e1f30..1624d0f 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,7 @@ package coffee.liz.dyl.systems; import coffee.liz.dyl.components.graphic.Graphic; -import coffee.liz.ecs.common.components.physics.BoundingBox; -import coffee.liz.ecs.common.systems.physics.CollisionSystem; +import coffee.liz.dyl.components.physics.BoundingBox; import coffee.liz.ecs.model.System; import coffee.liz.ecs.model.World; import com.badlogic.gdx.graphics.Color; @@ -27,7 +26,7 @@ public class RenderSystem implements System { @Override public Collection<Class<? extends System>> getDependencies() { - return Set.of(CollisionSystem.class); + return Set.of(AnimationSystem.class); } @Override diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java b/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionGrid.java index 94202b4..fb14b70 100644 --- a/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionGrid.java @@ -1,52 +1,50 @@ -package coffee.liz.ecs.common.systems.physics; +package coffee.liz.dyl.systems.physics; -import coffee.liz.ecs.common.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.BoundingBox; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2i; +import coffee.liz.ecs.model.Entity; +import lombok.Getter; +import lombok.Setter; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +@Setter +@Getter public class CollisionGrid { - private final Map<Vec2i, Set<Integer>> cells = new HashMap<>(); + private final Map<Vec2i, Set<Entity>> 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) { + public void insert(final Entity entity) { + final BoundingBox bb = entity.get(BoundingBox.class); 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); + cells.computeIfAbsent(new Vec2i(cx, cy), _ -> new HashSet<>()).add(entity); } } } - public Set<Integer> getNeighborIds(final BoundingBox bb) { - final Set<Integer> neighbors = new HashSet<>(); + public Set<Entity> getNeighbors(final BoundingBox bb) { + final Set<Entity> 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)); + final Set<Entity> cell = cells.get(new Vec2i(cx, cy)); if (cell != null) { neighbors.addAll(cell); } diff --git a/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java b/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java new file mode 100644 index 0000000..8cf7a59 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java @@ -0,0 +1,125 @@ +package coffee.liz.dyl.systems.physics; + +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.CollisionContacts; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Solid; +import coffee.liz.dyl.components.physics.Velocity; +import coffee.liz.ecs.math.Vec2; +import coffee.liz.ecs.math.Vec2f; +import coffee.liz.ecs.model.Entity; +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 CollisionSystem implements System { + private float cellSize = 3f; + 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) { + world.queryable().allOf(CollisionContacts.class) + .forEach(e -> e.remove(CollisionContacts.class)); + + final Set<Entity> allBoxEntities = world.queryable().allOf(BoundingBox.class); + if (allBoxEntities.isEmpty()) { + return; + } + + grid.clear(); + final Vec2<Float> origin = getOrigin(allBoxEntities.stream() + .map(e -> e.get(BoundingBox.class).getPosition()) + .toList()); + grid.setOrigin(origin); + grid.setCellSize(new Vec2f(cellSize, cellSize)); + for (final Entity entity : allBoxEntities) { + grid.insert(entity); + } + + for (final Entity me : world.queryable().allOf(BoundingBox.class, Velocity.class)) { + final BoundingBox meBox = me.get(BoundingBox.class); + for (final Entity them : grid.getNeighbors(meBox)) { + if (me.equals(them)) { + continue; + } + if (!meBox.isCollidingWith(them.get(BoundingBox.class))) { + continue; + } + + contacts(me).add(them); + contacts(them).add(me); + + if (them.has(Solid.class)) { + resolveCollision(me, them); + } + } + } + } + + private void resolveCollision(final Entity me, final Entity them) { + final BoundingBox meBox = me.get(BoundingBox.class); + final BoundingBox themBox = them.get(BoundingBox.class); + + final Vec2<Float> mtv = getPenetrationVector(meBox, themBox); + meBox.setPosition(meBox.getPosition().plus(mtv)); + + // Cancel the velocity component pressing into the solid (normal impulse) + final float mtvLen = mtv.length(); + final float nx = mtv.getX() / mtvLen; + final float ny = mtv.getY() / mtvLen; + + final Vec2<Float> vel = me.get(Velocity.class).getVelocity(); + final float velIntoWall = -(vel.getX() * nx + vel.getY() * ny); + if (velIntoWall > 0f) { + me.get(Velocity.class).setVelocity(new Vec2f( + vel.getX() + nx * velIntoWall, + vel.getY() + ny * velIntoWall + )); + } + + // Landing on top of a solid restores jump ability + if (me.has(Jump.class) && ny > 0f) { + me.get(Jump.class).setCanJump(true); + } + } + + private Vec2<Float> getPenetrationVector(final BoundingBox meBox, final BoundingBox themBox) { + final float fromLeft = meBox.getRight() - themBox.getPosition().getX(); + final float fromRight = themBox.getRight() - meBox.getPosition().getX(); + final float fromBottom = meBox.getTop() - themBox.getPosition().getY(); + final float fromTop = themBox.getTop() - meBox.getPosition().getY(); + + final float penetrationX = fromLeft < fromRight ? -fromLeft : fromRight; + final float penetrationY = fromBottom < fromTop ? -fromBottom : fromTop; + + final Vec2<Float> minimumTranslationVector = Math.abs(penetrationX) <= Math.abs(penetrationY) + ? new Vec2f(penetrationX, 0f) + : new Vec2f(0f, penetrationY); + return minimumTranslationVector; + } + + private CollisionContacts contacts(final Entity entity) { + if (!entity.has(CollisionContacts.class)) { + entity.add(new CollisionContacts()); + } + return entity.get(CollisionContacts.class); + } + + private Vec2<Float> getOrigin(final Collection<Vec2<Float>> positions) { + float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE; + for (final Vec2<Float> pos : positions) { + minX = Math.min(minX, pos.getX()); + minY = Math.min(minY, pos.getY()); + } + return new Vec2f(minX, minY); + } +} diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java b/core/src/main/java/coffee/liz/dyl/systems/physics/ForceReductionSystem.java index 4a51ba8..944ad2b 100644 --- a/core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/ForceReductionSystem.java @@ -1,11 +1,12 @@ -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; +package coffee.liz.dyl.systems.physics; + +import coffee.liz.dyl.components.physics.Force; +import coffee.liz.dyl.components.physics.Forces; +import coffee.liz.dyl.components.physics.Gravity; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Mass; +import coffee.liz.dyl.components.physics.Velocity; +import coffee.liz.dyl.systems.InputSystem; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.model.System; @@ -21,7 +22,7 @@ public class ForceReductionSystem implements System { @Override public Collection<Class<? extends System>> getDependencies() { - return Set.of(); + return Set.of(InputSystem.class); } @Override diff --git a/core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java b/core/src/main/java/coffee/liz/dyl/systems/physics/IntegrationSystem.java index ba38b70..4de4dd7 100644 --- a/core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/IntegrationSystem.java @@ -1,7 +1,7 @@ -package coffee.liz.ecs.common.systems.physics; +package coffee.liz.dyl.systems.physics; -import coffee.liz.ecs.common.components.physics.BoundingBox; -import coffee.liz.ecs.common.components.physics.Velocity; +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.Velocity; import coffee.liz.ecs.model.System; import coffee.liz.ecs.model.World; 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 7f1cb62..b1376df 100644 --- a/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java +++ b/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java @@ -3,14 +3,16 @@ package coffee.liz.dyl.world; import coffee.liz.dyl.DylGame; import coffee.liz.dyl.config.PhysicsConstants; import coffee.liz.dyl.entities.PlayerFactory; +import coffee.liz.dyl.systems.AnimationSystem; +import coffee.liz.dyl.systems.DamageSystem; import coffee.liz.dyl.systems.InputSystem; 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.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.Solid; +import coffee.liz.dyl.systems.physics.CollisionSystem; +import coffee.liz.dyl.systems.physics.ForceReductionSystem; +import coffee.liz.dyl.systems.physics.IntegrationSystem; import coffee.liz.ecs.math.Vec2f; import com.badlogic.gdx.Gdx; @@ -20,12 +22,14 @@ public class DylGameWorld extends DAGWorld { new InputSystem(() -> game.getSettings().getKeyBinds().filterActiveActions(Gdx.input::isKeyPressed)), new ForceReductionSystem(PhysicsConstants.GRAVITY), new IntegrationSystem(), - new CollisionSystem(PhysicsConstants.GRAVITY), + new CollisionSystem(), + new DamageSystem(), + new AnimationSystem(), new RenderSystem(game.getBatch(), game.getViewport()) ); PlayerFactory.addTo(this); createEntity() .add(new BoundingBox(new Vec2f(-50f, -1f), new Vec2f(200f, 1f))) - .add(new TopCollidable()); + .add(new Solid()); } } 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 deleted file mode 100644 index 166428a..0000000 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java +++ /dev/null @@ -1,6 +0,0 @@ -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/TopCollidable.java b/core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java deleted file mode 100644 index 76185bd..0000000 --- a/core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java +++ /dev/null @@ -1,6 +0,0 @@ -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/systems/physics/CollisionSystem.java b/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java deleted file mode 100644 index 14f0a2b..0000000 --- a/core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java +++ /dev/null @@ -1,107 +0,0 @@ -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/model/Entity.java b/core/src/main/java/coffee/liz/ecs/model/Entity.java index bbd417e..16aa37b 100644 --- a/core/src/main/java/coffee/liz/ecs/model/Entity.java +++ b/core/src/main/java/coffee/liz/ecs/model/Entity.java @@ -108,4 +108,17 @@ public class Entity extends EventBus<EntityEvent> { public Set<Class<? extends Component>> componentTypes() { return componentMap.keySet(); } + + @Override + public boolean equals(final Object other) { + if (other instanceof Entity) { + return ((Entity) other).getId() == getId(); + } + return false; + } + + @Override + public int hashCode() { + return Integer.hashCode(getId()); + } } diff --git a/core/src/test/java/coffee/liz/ecs/common/components/physics/BoundingBoxTest.java b/core/src/test/java/coffee/liz/dyl/components/physics/BoundingBoxTest.java index 2372456..c89df37 100644 --- a/core/src/test/java/coffee/liz/ecs/common/components/physics/BoundingBoxTest.java +++ b/core/src/test/java/coffee/liz/dyl/components/physics/BoundingBoxTest.java @@ -1,4 +1,4 @@ -package coffee.liz.ecs.common.components.physics; +package coffee.liz.dyl.components.physics; import coffee.liz.ecs.math.Vec2f; import org.junit.jupiter.api.Test; diff --git a/core/src/test/java/coffee/liz/ecs/common/systems/physics/PhysicsSystemsTest.java b/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java index 13a4a1c..4c285fb 100644 --- a/core/src/test/java/coffee/liz/ecs/common/systems/physics/PhysicsSystemsTest.java +++ b/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java @@ -1,15 +1,14 @@ -package coffee.liz.ecs.common.systems.physics; +package coffee.liz.dyl.systems.physics; import coffee.liz.ecs.DAGWorld; -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.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.Force; +import coffee.liz.dyl.components.physics.Forces; +import coffee.liz.dyl.components.physics.Gravity; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Mass; +import coffee.liz.dyl.components.physics.Solid; +import coffee.liz.dyl.components.physics.Velocity; import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.model.Entity; import org.junit.jupiter.api.Test; @@ -54,7 +53,7 @@ class PhysicsSystemsTest { @Test public void entityLandsOnPlatformAndStops() { final DAGWorld world = new DAGWorld( - new ForceReductionSystem(GRAVITY), new IntegrationSystem(), new CollisionSystem(GRAVITY, 32f)); + new ForceReductionSystem(GRAVITY), new IntegrationSystem(), new CollisionSystem()); final Entity player = world.createEntity(); player.add(new Mass(1f)); @@ -63,11 +62,10 @@ class PhysicsSystemsTest { player.add(new Gravity(100f)); player.add(new Jump(false, 0L)); player.add(new BoundingBox(new Vec2f(0f, 1.1f), new Vec2f(1f, 1f))); - player.add(new Collidable()); final Entity floor = world.createEntity(); floor.add(new BoundingBox(new Vec2f(-5f, 0f), new Vec2f(10f, 1f))); - floor.add(new TopCollidable()); + floor.add(new Solid()); world.update(0.1f); diff --git a/core/src/test/java/coffee/liz/ecs/common/systems/physics/CollisionGridTest.java b/core/src/test/java/coffee/liz/ecs/common/systems/physics/CollisionGridTest.java deleted file mode 100644 index d5670aa..0000000 --- a/core/src/test/java/coffee/liz/ecs/common/systems/physics/CollisionGridTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package coffee.liz.ecs.common.systems.physics; - -import coffee.liz.ecs.common.components.physics.BoundingBox; -import coffee.liz.ecs.math.Vec2f; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class CollisionGridTest { - private final CollisionGrid grid = new CollisionGrid(); - - @BeforeEach - public void setup() { - grid.setOrigin(new Vec2f(0f, 0f)); - grid.setCellSize(new Vec2f(32f, 32f)); - } - - @Test - public void insertedEntityIsFoundAsNeighbor() { - final BoundingBox bb = new BoundingBox(new Vec2f(0f, 0f), new Vec2f(1f, 1f)); - grid.insert(1, bb); - assertTrue(grid.getNeighborIds(bb).contains(1)); - } - - @Test - public void entityInDifferentCellIsNotNeighbor() { - final BoundingBox a = new BoundingBox(new Vec2f(0f, 0f), new Vec2f(1f, 1f)); - final BoundingBox b = new BoundingBox(new Vec2f(100f, 100f), new Vec2f(1f, 1f)); - grid.insert(1, a); - assertFalse(grid.getNeighborIds(b).contains(1)); - } - - @Test - public void clearRemovesAllEntities() { - final BoundingBox bb = new BoundingBox(new Vec2f(0f, 0f), new Vec2f(1f, 1f)); - grid.insert(1, bb); - grid.clear(); - assertTrue(grid.getNeighborIds(bb).isEmpty()); - } - - @Test - public void largeEntitySpanningMultipleCellsFoundByNeighborInAnyCell() { - final BoundingBox large = new BoundingBox(new Vec2f(0f, 0f), new Vec2f(64f, 64f)); - final BoundingBox corner = new BoundingBox(new Vec2f(50f, 50f), new Vec2f(1f, 1f)); - grid.insert(1, large); - assertTrue(grid.getNeighborIds(corner).contains(1)); - } -} diff --git a/lwjgl3/build.gradle b/lwjgl3/build.gradle index 33f6d9b..8417d4b 100644 --- a/lwjgl3/build.gradle +++ b/lwjgl3/build.gradle @@ -29,6 +29,7 @@ dependencies { implementation "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop" implementation "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + implementation "com.badlogicgames.gdx:gdx-lwjgl3-angle:$gdxVersion" implementation project(':core') if(enableGraalNative == 'true') { diff --git a/lwjgl3/src/main/java/coffee/liz/dyl/lwjgl3/Lwjgl3Launcher.java b/lwjgl3/src/main/java/coffee/liz/dyl/lwjgl3/Lwjgl3Launcher.java index 7f59aca..3c2990b 100644 --- a/lwjgl3/src/main/java/coffee/liz/dyl/lwjgl3/Lwjgl3Launcher.java +++ b/lwjgl3/src/main/java/coffee/liz/dyl/lwjgl3/Lwjgl3Launcher.java @@ -26,6 +26,7 @@ public class Lwjgl3Launcher { //// useful for testing performance, but can also be very stressful to some hardware. //// You may also need to configure GPU drivers to fully disable Vsync; this can cause screen tearing. + configuration.setDecorated(false); configuration.setWindowedMode(1024, 1024); //// You can change these files; they are in lwjgl3/src/main/resources/ . //// They can also be loaded from the root of assets/ . @@ -39,7 +40,7 @@ public class Lwjgl3Launcher { //// You can choose to add the following line and the mentioned dependency if you want; they //// are not intended for games that use GL30 (which is compatibility with OpenGL ES 3.0). //// Know that it might not work well in some cases. -// configuration.setOpenGLEmulation(Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20, 0, 0); + configuration.setOpenGLEmulation(Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20, 0, 0); return configuration; } |
