diff options
| author | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-03-07 08:21:41 -0800 |
|---|---|---|
| committer | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-03-07 08:21:41 -0800 |
| commit | f2135acc9accdc938035d753ee6e79c865fd44e2 (patch) | |
| tree | 1016a19e087ce7666c3e2b20a07143bb063bd9c9 | |
| parent | 19385bdee0972edcedf2a719fc5130aa32134029 (diff) | |
| download | dyl-f2135acc9accdc938035d753ee6e79c865fd44e2.tar.gz dyl-f2135acc9accdc938035d753ee6e79c865fd44e2.zip | |
Some refactoring work
18 files changed, 220 insertions, 84 deletions
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 8cca8ac..24e5109 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 @@ -3,8 +3,8 @@ package coffee.liz.dyl.components.graphic; 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 com.badlogic.gdx.graphics.g2d.TextureRegion; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -13,7 +13,7 @@ import lombok.RequiredArgsConstructor; public class TextureGraphic implements Graphic { private final int z; private final Color color; - private final Texture texture; + private final TextureRegion texture; private boolean facingLeft = false; @Override 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 index b709751..49ab7f6 100644 --- a/core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/CollisionContacts.java @@ -1,20 +1,27 @@ package coffee.liz.dyl.components.physics; +import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.model.Component; import coffee.liz.ecs.model.Entity; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import java.util.ArrayList; import java.util.Collections; import java.util.List; +@Getter public class CollisionContacts implements Component { - private final List<Entity> contacts = new ArrayList<>(); - - public void add(final Entity entity) { - contacts.add(entity); + @Getter + @RequiredArgsConstructor + public class Contact { + private final Entity contactEntity; + private final Vec2<Float> penetrationVector; } - public List<Entity> getAll() { - return Collections.unmodifiableList(contacts); + private final List<Contact> contacts = new ArrayList<>(); + + public void add(final Entity entity, final Vec2<Float> penetrationVector) { + contacts.add(new Contact(entity, penetrationVector)); } } diff --git a/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java b/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java index c49d6e1..79d2f78 100644 --- a/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Jump.java @@ -3,12 +3,16 @@ package coffee.liz.dyl.components.physics; import coffee.liz.ecs.model.Component; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.Setter; +import java.time.Instant; + +@NoArgsConstructor @AllArgsConstructor @Getter @Setter public class Jump implements Component { - private boolean canJump; - private long jumpStartMs; + private Instant jumpStart; } diff --git a/core/src/main/java/coffee/liz/dyl/components/physics/Jumpable.java b/core/src/main/java/coffee/liz/dyl/components/physics/Jumpable.java new file mode 100644 index 0000000..d35464a --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/components/physics/Jumpable.java @@ -0,0 +1,16 @@ +package coffee.liz.dyl.components.physics; + +import coffee.liz.ecs.model.Component; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.time.Instant; + +@AllArgsConstructor +@Getter +@Setter +public class Jumpable implements Component { + private boolean canPhysicallyJump = false; + private Instant jumpRequestTime; +} 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 6339a34..3019160 100644 --- a/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java +++ b/core/src/main/java/coffee/liz/dyl/config/PhysicsConstants.java @@ -1,11 +1,15 @@ package coffee.liz.dyl.config; +import java.time.Duration; + public final class PhysicsConstants { public static final float GRAVITY = 40f; + public static final float ADDITIONAL_JUMP_OVER_GRAVITY = 1.05f; 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 JUMP_INITIAL_VEL = 10.0f; + public static final Duration MAX_JUMP = Duration.ofMillis(100); + public static final Duration JUMP_BUFFER = Duration.ofMillis(400); + public static final float JUMP_CUT_FACTOR = 0.5f; public static final float DAMAGE_TIME = 0.25f; private PhysicsConstants() { } diff --git a/core/src/main/java/coffee/liz/dyl/entities/FloorFactory.java b/core/src/main/java/coffee/liz/dyl/entities/FloorFactory.java new file mode 100644 index 0000000..e6c5591 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/entities/FloorFactory.java @@ -0,0 +1,34 @@ +package coffee.liz.dyl.entities; + +import coffee.liz.dyl.components.graphic.TextureGraphic; +import coffee.liz.dyl.components.physics.BoundingBox; +import coffee.liz.dyl.components.physics.Solid; +import coffee.liz.ecs.math.Vec2f; +import coffee.liz.ecs.model.Entity; +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.TextureRegion; + +public class FloorFactory { + private static final FloorAssets ASSETS = new FloorAssets(); + public static Entity addTo(final World world) { + return world.createEntity() + .add(new TextureGraphic(0, Color.WHITE, ASSETS.textureRegion)) + .add(new Solid()) + .add(new BoundingBox(new Vec2f(5f, 0.25f), new Vec2f(1f, 0.5f))); + } + + private static class FloorAssets { + private static final FileHandle FILE = Gdx.files.internal("noir/Underground.png"); + final Texture texture; + final TextureRegion textureRegion; + + public FloorAssets() { + texture = new Texture(FILE); + textureRegion = new TextureRegion(texture, 4, 12, 8, 4); + } + } +} 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 c857d02..ffd55f6 100644 --- a/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java +++ b/core/src/main/java/coffee/liz/dyl/entities/PlayerFactory.java @@ -4,6 +4,7 @@ import coffee.liz.dyl.components.AnimationState; import coffee.liz.dyl.components.Controllable; import coffee.liz.dyl.components.FacingDirection; import coffee.liz.dyl.components.graphic.AnimationGraphic; +import coffee.liz.dyl.components.physics.Jumpable; import coffee.liz.dyl.config.PhysicsConstants; import coffee.liz.dyl.components.physics.BoundingBox; import coffee.liz.dyl.components.physics.Forces; @@ -14,6 +15,7 @@ import coffee.liz.dyl.components.physics.Velocity; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.math.Vec2i; +import coffee.liz.ecs.model.Entity; import coffee.liz.ecs.model.World; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; @@ -27,57 +29,58 @@ import java.util.Map; public class PlayerFactory { private static final PlayerAssets ASSETS = new PlayerAssets(); - public static void addTo(final World world) { + public static Entity 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() + return 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 BoundingBox(new Vec2f(1f, 1f), PlayerAssets.PLAYER_DIMS.floatValue().scale(1/6f, 1/6f))) .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)); + .add(new Gravity(-20f)) + .add(new Jumpable(false, null)); } 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"); + public static final Vec2<Integer> PLAYER_DIMS = new Vec2i(6, 7); // six sevennnnn + private static final FileHandle FILE = Gdx.files.internal("noir/Hero.png"); final Texture texture; - final TextureRegion[][] region; +// 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 int dy = texture.getHeight() / DIMS.getY(); + final int dx = texture.getWidth() / DIMS.getX(); + final int ddx = 0;// dx - PLAYER_DIMS.getX(); + final int ddy = dy - PLAYER_DIMS.getY(); final TextureRegion[] idlingTextureRegion = new TextureRegion[2]; - idlingTextureRegion[0] = region[5][0]; - idlingTextureRegion[1] = region[5][1]; + idlingTextureRegion[0] = new TextureRegion(texture, 0 * dx + ddx, 5 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); + idlingTextureRegion[1] = new TextureRegion(texture, 1 * dx + ddx, 5 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); final TextureRegion[] runningTextureRegion = new TextureRegion[2]; - runningTextureRegion[0] = region[0][0]; - runningTextureRegion[1] = region[0][1]; + runningTextureRegion[0] = new TextureRegion(texture, 0 * dx + ddx, 0 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); + runningTextureRegion[1] = new TextureRegion(texture, 1 * dx + ddx, 0 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); final TextureRegion[] damagedTextureRegion = new TextureRegion[1]; - damagedTextureRegion[0] = region[6][0]; + damagedTextureRegion[0] = new TextureRegion(texture, 0 * dx + ddx, 6 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); final TextureRegion[] jump = new TextureRegion[1]; - jump[0] = region[1][0]; + jump[0] = new TextureRegion(texture, 0 * dx + ddx, 1 * dy + ddy, PLAYER_DIMS.getX(), PLAYER_DIMS.getY()); - running = new Animation<>(0.20f, runningTextureRegion); + running = new Animation<>(0.18f, runningTextureRegion); idling = new Animation<>(0.75f, idlingTextureRegion); damaged = new Animation<>(PhysicsConstants.DAMAGE_TIME, damagedTextureRegion); jumping = new Animation<>(0.75f, jump); diff --git a/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java b/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java index 8c0d595..a932eea 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/AnimationSystem.java @@ -24,9 +24,8 @@ public class AnimationSystem implements System { 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()) { + if (entity.has(Jump.class)) { animationState.setTransition(AnimationState.State.JUMP); return; } 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 1938a50..ea0e574 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/InputSystem.java @@ -2,26 +2,22 @@ package coffee.liz.dyl.systems; import coffee.liz.dyl.components.Controllable; import coffee.liz.dyl.components.FacingDirection; +import coffee.liz.dyl.components.physics.Jumpable; import coffee.liz.dyl.config.KeyBinds; -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; import lombok.RequiredArgsConstructor; +import java.time.Duration; import java.time.Instant; import java.util.Collection; import java.util.Set; import java.util.function.Supplier; -import static coffee.liz.dyl.config.PhysicsConstants.JUMP_ACC; -import static coffee.liz.dyl.config.PhysicsConstants.JUMP_INITIAL_VEL; -import static coffee.liz.dyl.config.PhysicsConstants.MAX_JUMP_MS; -import static coffee.liz.dyl.config.PhysicsConstants.MOVE_SPEED; +import static coffee.liz.dyl.config.PhysicsConstants.*; @RequiredArgsConstructor public class InputSystem implements System { @@ -36,7 +32,7 @@ public class InputSystem implements System { public void update(final World world, final float deltaSeconds) { final Set<KeyBinds.Action> actions = activeActions.get(); - world.queryable().allOf(Forces.class, Controllable.class, Velocity.class).forEach(entity -> { + world.queryable().allOf(Controllable.class, Velocity.class).forEach(entity -> { final Velocity velocity = entity.get(Velocity.class); float dx = 0f; @@ -46,23 +42,38 @@ public class InputSystem implements System { entity.add(new FacingDirection(new Vec2f(dx / MOVE_SPEED, 0f))); } - float newDy = velocity.getVelocity().getY(); + final Instant now = Instant.now(); + final Jumpable jumpable = entity.get(Jumpable.class); + final boolean canRequestJump = jumpable.getJumpRequestTime() == null; + final boolean jumpRequested = actions.contains(KeyBinds.Action.JUMP); + final boolean hasCurrentJump = entity.has(Jump.class); - final Jump jump = entity.get(Jump.class); - final Mass mass = entity.get(Mass.class); + float dy = velocity.getVelocity().getY(); - 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))); + // buffer only fires on a released press — holding never re-triggers + final boolean withinBuffer = !canRequestJump && !jumpRequested + && Duration.between(jumpable.getJumpRequestTime(), now).compareTo(JUMP_BUFFER) <= 0; + if (jumpable.isCanPhysicallyJump() && !hasCurrentJump && (canRequestJump && jumpRequested || withinBuffer)) { + entity.add(new Jump(now)); + dy = JUMP_INITIAL_VEL; + jumpable.setJumpRequestTime(now); // mark consumed; keeps canRequestJump false while held + } else if (!jumpRequested && hasCurrentJump && dy > 0) { + dy *= JUMP_CUT_FACTOR; + } + + // record an aerial press for buffering (ground presses are recorded above on initiation) + if (!jumpable.isCanPhysicallyJump() && canRequestJump && jumpRequested && !entity.has(Jump.class)) { + jumpable.setJumpRequestTime(now); + } else if (!jumpRequested && !entity.has(Jump.class)) { + if (jumpable.isCanPhysicallyJump()) { + jumpable.setJumpRequestTime(null); // released on ground — ready for next press + } else if (!canRequestJump + && Duration.between(jumpable.getJumpRequestTime(), now).compareTo(JUMP_BUFFER) > 0) { + jumpable.setJumpRequestTime(null); // aerial, buffer expired } } - velocity.setVelocity(new Vec2f(dx, newDy)); + velocity.setVelocity(new Vec2f(dx, dy)); }); } } diff --git a/core/src/main/java/coffee/liz/dyl/systems/JumpSystem.java b/core/src/main/java/coffee/liz/dyl/systems/JumpSystem.java new file mode 100644 index 0000000..d1552f5 --- /dev/null +++ b/core/src/main/java/coffee/liz/dyl/systems/JumpSystem.java @@ -0,0 +1,43 @@ +package coffee.liz.dyl.systems; + +import coffee.liz.dyl.components.physics.CollisionContacts; +import coffee.liz.dyl.components.physics.Jump; +import coffee.liz.dyl.components.physics.Jumpable; +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 JumpSystem 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(Jumpable.class).forEach(entity -> { + entity.get(Jumpable.class).setCanPhysicallyJump(false); + }); + world.queryable().allOf(Jumpable.class, CollisionContacts.class).forEach(entity -> { + final CollisionContacts contacts = entity.get(CollisionContacts.class); + final Jumpable jumpable = entity.get(Jumpable.class); + contacts.getContacts().forEach(contact -> { + final boolean solidUnderUs = contact.getPenetrationVector().getY() <= 0; + if (!solidUnderUs) { + return; + } + jumpable.setCanPhysicallyJump(true); + + final boolean currentJumpOver = entity.has(Jump.class) && entity.has(Velocity.class) + && entity.get(Velocity.class).getVelocity().getY() <= 0; + if (currentJumpOver) { + entity.remove(Jump.class); + } + }); + }); + } +} diff --git a/core/src/main/java/coffee/liz/dyl/systems/physics/ForceReductionSystem.java b/core/src/main/java/coffee/liz/dyl/systems/physics/AccelerationSystem.java index 944ad2b..519cc3f 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/physics/ForceReductionSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/AccelerationSystem.java @@ -6,6 +6,7 @@ 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.config.PhysicsConstants; import coffee.liz.dyl.systems.InputSystem; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2f; @@ -17,7 +18,7 @@ import java.util.Collection; import java.util.Set; @RequiredArgsConstructor -public class ForceReductionSystem implements System { +public class AccelerationSystem implements System { private final float gravity; @Override @@ -33,10 +34,10 @@ public class ForceReductionSystem implements System { final Velocity velocity = entity.get(Velocity.class); if (entity.has(Gravity.class)) { - final Gravity gravityComponent = entity.get(Gravity.class); - if (velocity.getVelocity().getY() > -gravityComponent.getTerminalVelocity()) { - forces.add(new Force(new Vec2f(0f, -mass.getMass() * gravity))); - } + final float gravityMult = entity.has(Jump.class) && velocity.getVelocity().getY() < 0 + ? 1f + PhysicsConstants.ADDITIONAL_JUMP_OVER_GRAVITY + : 1f; + forces.add(new Force(new Vec2f(0f, -mass.getMass() * gravity * gravityMult))); } Vec2<Float> netForce = Vec2f.ZERO; @@ -45,12 +46,13 @@ public class ForceReductionSystem implements System { } forces.clear(); - final Vec2<Float> acceleration = netForce.scale(1f / mass.getMass(), 1f / mass.getMass()); - velocity.setVelocity(velocity.getVelocity().plus(acceleration.scale(deltaSeconds, deltaSeconds))); - - if (entity.has(Jump.class) && acceleration.getY() < 0) { - entity.get(Jump.class).setCanJump(false); - } + final Vec2<Float> dv = netForce.scale(deltaSeconds / mass.getMass(), deltaSeconds / mass.getMass()); + velocity.setVelocity(velocity.getVelocity().plus(dv).transform(x -> x, y -> { + if (entity.has(Gravity.class)) { + return Math.max(entity.get(Gravity.class).getTerminalVelocity(), y); + } + return y; + })); }); } } 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 index 8cf7a59..fb98151 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/CollisionSystem.java @@ -2,9 +2,9 @@ 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.dyl.systems.InputSystem; import coffee.liz.ecs.math.Vec2; import coffee.liz.ecs.math.Vec2f; import coffee.liz.ecs.model.Entity; @@ -22,7 +22,7 @@ public class CollisionSystem implements System { @Override public Collection<Class<? extends System>> getDependencies() { - return Set.of(IntegrationSystem.class); + return Set.of(MovementSystem.class); } @Override @@ -55,9 +55,6 @@ public class CollisionSystem implements System { continue; } - contacts(me).add(them); - contacts(them).add(me); - if (them.has(Solid.class)) { resolveCollision(me, them); } @@ -70,6 +67,8 @@ public class CollisionSystem implements System { final BoundingBox themBox = them.get(BoundingBox.class); final Vec2<Float> mtv = getPenetrationVector(meBox, themBox); + contacts(me).add(them, getPenetrationVector(themBox, meBox)); + contacts(them).add(me, mtv); meBox.setPosition(meBox.getPosition().plus(mtv)); // Cancel the velocity component pressing into the solid (normal impulse) @@ -85,11 +84,6 @@ public class CollisionSystem implements System { 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) { diff --git a/core/src/main/java/coffee/liz/dyl/systems/physics/IntegrationSystem.java b/core/src/main/java/coffee/liz/dyl/systems/physics/MovementSystem.java index 4de4dd7..77a9b9c 100644 --- a/core/src/main/java/coffee/liz/dyl/systems/physics/IntegrationSystem.java +++ b/core/src/main/java/coffee/liz/dyl/systems/physics/MovementSystem.java @@ -8,10 +8,10 @@ import coffee.liz.ecs.model.World; import java.util.Collection; import java.util.Set; -public class IntegrationSystem implements System { +public class MovementSystem implements System { @Override public Collection<Class<? extends System>> getDependencies() { - return Set.of(ForceReductionSystem.class); + return Set.of(AccelerationSystem.class); } @Override 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 b1376df..fd8e282 100644 --- a/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java +++ b/core/src/main/java/coffee/liz/dyl/world/DylGameWorld.java @@ -2,17 +2,19 @@ package coffee.liz.dyl.world; import coffee.liz.dyl.DylGame; import coffee.liz.dyl.config.PhysicsConstants; +import coffee.liz.dyl.entities.FloorFactory; 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.JumpSystem; import coffee.liz.dyl.systems.RenderSystem; import coffee.liz.ecs.DAGWorld; 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.dyl.systems.physics.AccelerationSystem; +import coffee.liz.dyl.systems.physics.MovementSystem; import coffee.liz.ecs.math.Vec2f; import com.badlogic.gdx.Gdx; @@ -20,14 +22,16 @@ public class DylGameWorld extends DAGWorld { public DylGameWorld(final DylGame game) { super( new InputSystem(() -> game.getSettings().getKeyBinds().filterActiveActions(Gdx.input::isKeyPressed)), - new ForceReductionSystem(PhysicsConstants.GRAVITY), - new IntegrationSystem(), + new AccelerationSystem(PhysicsConstants.GRAVITY), + new MovementSystem(), new CollisionSystem(), new DamageSystem(), new AnimationSystem(), - new RenderSystem(game.getBatch(), game.getViewport()) + new RenderSystem(game.getBatch(), game.getViewport()), + new JumpSystem() ); PlayerFactory.addTo(this); + FloorFactory.addTo(this); createEntity() .add(new BoundingBox(new Vec2f(-50f, -1f), new Vec2f(200f, 1f))) .add(new Solid()); diff --git a/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java b/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java index 4c285fb..885c112 100644 --- a/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java +++ b/core/src/test/java/coffee/liz/dyl/systems/physics/PhysicsSystemsTest.java @@ -21,7 +21,7 @@ class PhysicsSystemsTest { @Test public void gravityAcceleratesEntityDownwardOverTime() { - final DAGWorld world = new DAGWorld(new ForceReductionSystem(GRAVITY), new IntegrationSystem()); + final DAGWorld world = new DAGWorld(new AccelerationSystem(GRAVITY), new MovementSystem()); final Entity entity = world.createEntity(); entity.add(new Mass(1f)); entity.add(new Velocity(Vec2f.ZERO)); @@ -37,7 +37,7 @@ class PhysicsSystemsTest { @Test public void forcesAreClearedEachFrame() { - final DAGWorld world = new DAGWorld(new ForceReductionSystem(GRAVITY), new IntegrationSystem()); + final DAGWorld world = new DAGWorld(new AccelerationSystem(GRAVITY), new MovementSystem()); final Entity entity = world.createEntity(); entity.add(new Mass(1f)); entity.add(new Velocity(Vec2f.ZERO)); @@ -53,7 +53,7 @@ class PhysicsSystemsTest { @Test public void entityLandsOnPlatformAndStops() { final DAGWorld world = new DAGWorld( - new ForceReductionSystem(GRAVITY), new IntegrationSystem(), new CollisionSystem()); + new AccelerationSystem(GRAVITY), new MovementSystem(), new CollisionSystem()); final Entity player = world.createEntity(); player.add(new Mass(1f)); diff --git a/design/bugs.txt b/design/bugs.txt new file mode 100644 index 0000000..e65b3ca --- /dev/null +++ b/design/bugs.txt @@ -0,0 +1,3 @@ +Clipping into a solid gives double height: + +Jumping into a solid from the side has weird interactions. First, I can hold the direction where the vector goes into the solid and jump, and I'll get a "double jump", probably because the jump resets immediately on top collision. ~/Desktop/dyl-bugs/jump-into-solid.mov. diff --git a/design/design.txt b/design/design.txt index df8842c..74c720d 100644 --- a/design/design.txt +++ b/design/design.txt @@ -78,3 +78,7 @@ This gives the world a little bit of "depth". ---------S | (height difference is two screens' worth \ | \_______ + +Something I still need to decide on is how the camera will work. Is every chunk of the game a +room like mega man? Or is it like Terraria where the camera centers on the player and chunks +feel seemless? The former is probably easier generation-wise etc. diff --git a/design/todo.txt b/design/todo.txt new file mode 100644 index 0000000..023868e --- /dev/null +++ b/design/todo.txt @@ -0,0 +1,8 @@ +Terrain: +- [ ] Basic platforming +- [ ] First dungeon +- [ ] First overworld attempt + +Combat: +- [ ] Basic enemy +- [ ] Separate solid collision bounding box and damageable collision bounding box. Perhaps even different systems? |
