summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <me@liz.coffee>2026-03-01 12:54:31 -0800
committerElizabeth Alexander Hunt <me@liz.coffee>2026-03-01 12:54:47 -0800
commit242b32050feff1d7f047e52d46daadd3ec682c14 (patch)
tree6207a3f350946ae3b1c2764b2bb9321473f6bfaa
parentc491b5cb08972ffc041fa0b968810373b9ed79a3 (diff)
downloaddyl-242b32050feff1d7f047e52d46daadd3ec682c14.tar.gz
dyl-242b32050feff1d7f047e52d46daadd3ec682c14.zip
Adding animations n stuff.
-rwxr-xr-xassets/noir/hero.pngbin0 -> 1025 bytes
-rw-r--r--assets/player.pngbin7535 -> 0 bytes
-rw-r--r--core/src/main/java/coffee/liz/dyl/DylGame.java4
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/AnimationState.java36
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/DamageGraceTime.java17
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/FacingDirection.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Force.java)6
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/graphic/AnimationGraphic.java47
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/graphic/Graphic.java5
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/graphic/TextureGraphic.java32
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/BoundingBox.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/BoundingBox.java)2
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java20
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Force.java11
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Forces.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Forces.java)8
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Gravity.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Gravity.java)2
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Jump.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Jump.java)2
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Mass.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Mass.java)2
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Solid.java5
-rw-r--r--core/src/main/java/coffee/liz/dyl/components/physics/Velocity.java (renamed from core/src/main/java/coffee/liz/ecs/common/components/physics/Velocity.java)2
-rw-r--r--core/src/main/java/coffee/liz/dyl/config/KeyBinds.java7
-rw-r--r--core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java14
-rw-r--r--core/src/main/java/coffee/liz/dyl/config/Settings.java2
-rw-r--r--core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java100
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java56
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/DamageSystem.java23
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/InputSystem.java41
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/RenderSystem.java5
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/physics/CollisionGrid.java (renamed from core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionGrid.java)30
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java125
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/physics/ForceReductionSystem.java (renamed from core/src/main/java/coffee/liz/ecs/common/systems/physics/ForceReductionSystem.java)19
-rw-r--r--core/src/main/java/coffee/liz/dyl/systems/physics/IntegrationSystem.java (renamed from core/src/main/java/coffee/liz/ecs/common/systems/physics/IntegrationSystem.java)6
-rw-r--r--core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java18
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/Collidable.java6
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/components/physics/TopCollidable.java6
-rw-r--r--core/src/main/java/coffee/liz/ecs/common/systems/physics/CollisionSystem.java107
-rw-r--r--core/src/main/java/coffee/liz/ecs/model/Entity.java13
-rw-r--r--core/src/test/java/coffee/liz/dyl/components/physics/BoundingBoxTest.java (renamed from core/src/test/java/coffee/liz/ecs/common/components/physics/BoundingBoxTest.java)2
-rw-r--r--core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java (renamed from core/src/test/java/coffee/liz/ecs/common/systems/physics/PhysicsSystemsTest.java)24
-rw-r--r--core/src/test/java/coffee/liz/ecs/common/systems/physics/CollisionGridTest.java50
-rw-r--r--lwjgl3/build.gradle1
-rw-r--r--lwjgl3/src/main/java/coffee/liz/dyl/lwjgl3/Lwjgl3Launcher.java3
40 files changed, 554 insertions, 305 deletions
diff --git a/assets/noir/hero.png b/assets/noir/hero.png
new file mode 100755
index 0000000..08e2d61
--- /dev/null
+++ b/assets/noir/hero.png
Binary files differ
diff --git a/assets/player.png b/assets/player.png
deleted file mode 100644
index 2e95386..0000000
--- a/assets/player.png
+++ /dev/null
Binary files differ
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;
}