From 3dc1e94b0f0a33adb7a4f8b45e4f4f1985b0b130 Mon Sep 17 00:00:00 2001 From: MarcinSc Date: Sun, 10 Jul 2016 16:46:34 -0700 Subject: [PATCH] Detecting hitbox overlap. Level exit portal. --- core/assets/prefabs/{ => blocks}/dirt.prefab | 6 ++ core/assets/prefabs/blocks/exitPortal.prefab | 14 +++ core/assets/prefabs/{ => blocks}/grass.prefab | 6 ++ core/assets/prefabs/{ => blocks}/stone.prefab | 6 ++ .../prefabs/levels/level-sample2.prefab | 1 + core/assets/prefabs/player.prefab | 7 ++ .../level/BlockEntityComponent.java | 6 ++ .../platformer/level/LevelEntitySystem.java | 40 +++++++++ .../jgd/platformer/logic/PlayerComponent.java | 6 ++ .../logic/hitbox/HitboxOverlapEvent.java | 16 ++++ .../logic/hitbox/HitboxOverlapSystem.java | 89 +++++++++++++++++++ .../hitbox/RectangleHitboxComponent.java | 13 +++ .../logic/physics/PlatformCollider.java | 29 ++++-- .../portal/LevelExitPortalComponent.java | 6 ++ .../logic/portal/LevelExitSystem.java | 17 ++++ 15 files changed, 256 insertions(+), 6 deletions(-) rename core/assets/prefabs/{ => blocks}/dirt.prefab (51%) create mode 100644 core/assets/prefabs/blocks/exitPortal.prefab rename core/assets/prefabs/{ => blocks}/grass.prefab (64%) rename core/assets/prefabs/{ => blocks}/stone.prefab (51%) create mode 100644 core/src/main/java/jgd/platformer/level/BlockEntityComponent.java create mode 100644 core/src/main/java/jgd/platformer/level/LevelEntitySystem.java create mode 100644 core/src/main/java/jgd/platformer/logic/PlayerComponent.java create mode 100644 core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapEvent.java create mode 100644 core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapSystem.java create mode 100644 core/src/main/java/jgd/platformer/logic/hitbox/RectangleHitboxComponent.java create mode 100644 core/src/main/java/jgd/platformer/logic/portal/LevelExitPortalComponent.java create mode 100644 core/src/main/java/jgd/platformer/logic/portal/LevelExitSystem.java diff --git a/core/assets/prefabs/dirt.prefab b/core/assets/prefabs/blocks/dirt.prefab similarity index 51% rename from core/assets/prefabs/dirt.prefab rename to core/assets/prefabs/blocks/dirt.prefab index c7c5ef6..d2e75a5 100644 --- a/core/assets/prefabs/dirt.prefab +++ b/core/assets/prefabs/blocks/dirt.prefab @@ -4,5 +4,11 @@ "texturesForParts": { "all": "blockTiles/Dirt.png" } + }, + "CollidingObjectComponent": { + "translateX": 0, + "translateY": 0, + "width": 1, + "height": 1 } } \ No newline at end of file diff --git a/core/assets/prefabs/blocks/exitPortal.prefab b/core/assets/prefabs/blocks/exitPortal.prefab new file mode 100644 index 0000000..b55abd0 --- /dev/null +++ b/core/assets/prefabs/blocks/exitPortal.prefab @@ -0,0 +1,14 @@ +{ + "BlockComponent": { + "shape": "cube", + "texturesForParts": { + "front": "blockTiles/Dirt.png" + } + }, + "BlockEntityComponent": {}, + "RectangleHitboxComponent": { + "width": 1, + "height": 1 + }, + "LevelExitPortalComponent": {} +} \ No newline at end of file diff --git a/core/assets/prefabs/grass.prefab b/core/assets/prefabs/blocks/grass.prefab similarity index 64% rename from core/assets/prefabs/grass.prefab rename to core/assets/prefabs/blocks/grass.prefab index c36da67..672e44e 100644 --- a/core/assets/prefabs/grass.prefab +++ b/core/assets/prefabs/blocks/grass.prefab @@ -6,5 +6,11 @@ "bottom": "blockTiles/Dirt.png", "sides": "blockTiles/GrassSide.png" } + }, + "CollidingObjectComponent": { + "translateX": 0, + "translateY": 0, + "width": 1, + "height": 1 } } \ No newline at end of file diff --git a/core/assets/prefabs/stone.prefab b/core/assets/prefabs/blocks/stone.prefab similarity index 51% rename from core/assets/prefabs/stone.prefab rename to core/assets/prefabs/blocks/stone.prefab index cb74eba..364bb27 100644 --- a/core/assets/prefabs/stone.prefab +++ b/core/assets/prefabs/blocks/stone.prefab @@ -4,5 +4,11 @@ "texturesForParts": { "all": "blockTiles/Stone.png" } + }, + "CollidingObjectComponent": { + "translateX": 0, + "translateY": 0, + "width": 1, + "height": 1 } } \ No newline at end of file diff --git a/core/assets/prefabs/levels/level-sample2.prefab b/core/assets/prefabs/levels/level-sample2.prefab index 62a19a4..94fd989 100644 --- a/core/assets/prefabs/levels/level-sample2.prefab +++ b/core/assets/prefabs/levels/level-sample2.prefab @@ -6,6 +6,7 @@ "2,-2,0": "grass", "0,2,0": "grass", "1,2,0": "grass", + "1,3,-1": "exitPortal", "2,2,0": "grass", "-3.5,0,0": "stone", "-4.5,0,0": "stone", diff --git a/core/assets/prefabs/player.prefab b/core/assets/prefabs/player.prefab index 79b99a1..c90a6cf 100644 --- a/core/assets/prefabs/player.prefab +++ b/core/assets/prefabs/player.prefab @@ -1,4 +1,5 @@ { + "PlayerComponent": {}, "LocationComponent": { "x": 0, "y": 0, @@ -26,6 +27,12 @@ "width": 1, "height": 1 }, + "RectangleHitboxComponent": { + "translateX": -0.5, + "translateY": 0, + "width": 1, + "height": 1 + }, "CameraFocusComponent": { "focusWeight": 1 } diff --git a/core/src/main/java/jgd/platformer/level/BlockEntityComponent.java b/core/src/main/java/jgd/platformer/level/BlockEntityComponent.java new file mode 100644 index 0000000..debdb29 --- /dev/null +++ b/core/src/main/java/jgd/platformer/level/BlockEntityComponent.java @@ -0,0 +1,6 @@ +package jgd.platformer.level; + +import com.gempukku.secsy.entity.Component; + +public interface BlockEntityComponent extends Component { +} diff --git a/core/src/main/java/jgd/platformer/level/LevelEntitySystem.java b/core/src/main/java/jgd/platformer/level/LevelEntitySystem.java new file mode 100644 index 0000000..d0e2d5b --- /dev/null +++ b/core/src/main/java/jgd/platformer/level/LevelEntitySystem.java @@ -0,0 +1,40 @@ +package jgd.platformer.level; + +import com.gempukku.gaming.asset.prefab.PrefabManager; +import com.gempukku.secsy.context.annotation.Inject; +import com.gempukku.secsy.context.annotation.RegisterSystem; +import com.gempukku.secsy.entity.EntityManager; +import com.gempukku.secsy.entity.EntityRef; +import com.gempukku.secsy.entity.dispatch.ReceiveEvent; +import com.gempukku.secsy.entity.event.AfterComponentAdded; +import com.gempukku.secsy.entity.io.EntityData; +import jgd.platformer.component.LocationComponent; + +import java.util.Map; + +@RegisterSystem +public class LevelEntitySystem { + @Inject + private PrefabManager prefabManager; + @Inject + private EntityManager entityManager; + + @ReceiveEvent + public void levelLoaded(AfterComponentAdded event, EntityRef entity, LevelComponent level) { + for (Map.Entry blockCoordinates : level.getBlockCoordinates().entrySet()) { + String locationStr = blockCoordinates.getKey(); + String prefabName = blockCoordinates.getValue(); + EntityData entityData = prefabManager.getPrefabByName(prefabName); + EntityRef blockData = entityManager.wrapEntityData(entityData); + if (blockData.hasComponent(BlockEntityComponent.class)) { + EntityRef result = entityManager.createEntity(entityData); + LocationComponent location = result.createComponent(LocationComponent.class); + String[] locationSplit = locationStr.split(","); + location.setX(Float.parseFloat(locationSplit[0])); + location.setY(Float.parseFloat(locationSplit[1])); + location.setZ(Float.parseFloat(locationSplit[2])); + result.saveChanges(); + } + } + } +} diff --git a/core/src/main/java/jgd/platformer/logic/PlayerComponent.java b/core/src/main/java/jgd/platformer/logic/PlayerComponent.java new file mode 100644 index 0000000..cd37867 --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/PlayerComponent.java @@ -0,0 +1,6 @@ +package jgd.platformer.logic; + +import com.gempukku.secsy.entity.Component; + +public interface PlayerComponent extends Component { +} diff --git a/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapEvent.java b/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapEvent.java new file mode 100644 index 0000000..a28c866 --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapEvent.java @@ -0,0 +1,16 @@ +package jgd.platformer.logic.hitbox; + +import com.gempukku.secsy.entity.EntityRef; +import com.gempukku.secsy.entity.event.Event; + +public class HitboxOverlapEvent extends Event { + private EntityRef otherEntity; + + public HitboxOverlapEvent(EntityRef otherEntity) { + this.otherEntity = otherEntity; + } + + public EntityRef getOtherEntity() { + return otherEntity; + } +} diff --git a/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapSystem.java b/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapSystem.java new file mode 100644 index 0000000..c8bccdd --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/hitbox/HitboxOverlapSystem.java @@ -0,0 +1,89 @@ +package jgd.platformer.logic.hitbox; + +import com.gempukku.secsy.context.annotation.Inject; +import com.gempukku.secsy.context.annotation.RegisterSystem; +import com.gempukku.secsy.context.system.LifeCycleSystem; +import com.gempukku.secsy.entity.EntityRef; +import com.gempukku.secsy.entity.dispatch.ReceiveEvent; +import com.gempukku.secsy.entity.event.AfterComponentAdded; +import com.gempukku.secsy.entity.event.AfterComponentUpdated; +import com.gempukku.secsy.entity.event.BeforeComponentRemoved; +import com.gempukku.secsy.entity.game.GameLoop; +import com.gempukku.secsy.entity.game.GameLoopListener; +import jgd.platformer.component.LocationComponent; + +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +@RegisterSystem +public class HitboxOverlapSystem implements GameLoopListener, LifeCycleSystem { + @Inject + private GameLoop gameLoop; + + private Map hitboxEntities = new HashMap<>(); + + @Override + public void initialize() { + gameLoop.addGameLoopListener(this); + } + + @ReceiveEvent + public void entityWithHitboxAdded(AfterComponentAdded event, EntityRef entity, RectangleHitboxComponent rectangleHitbox, LocationComponent location) { + Rectangle2D shape = createShape(rectangleHitbox, location); + hitboxEntities.put(entity, shape); + } + + @ReceiveEvent + public void entityWithHitboxModified(AfterComponentUpdated event, EntityRef entity, RectangleHitboxComponent rectangleHitbox, LocationComponent location) { + Rectangle2D shape = createShape(rectangleHitbox, location); + hitboxEntities.put(entity, shape); + } + + @ReceiveEvent + public void entityWithHitboxRemoved(BeforeComponentRemoved event, EntityRef entity, RectangleHitboxComponent rectangleHitbox, LocationComponent location) { + hitboxEntities.remove(entity); + } + + @Override + public void update() { + List eventsToFire = new LinkedList<>(); + + for (Map.Entry hitboxEntity : hitboxEntities.entrySet()) { + EntityRef entity = hitboxEntity.getKey(); + Rectangle2D shape = hitboxEntity.getValue(); + + for (Map.Entry otherHitboxEntity : hitboxEntities.entrySet()) { + EntityRef otherEntity = otherHitboxEntity.getKey(); + if (!entity.equals(otherEntity)) { + Rectangle2D otherShape = otherHitboxEntity.getValue(); + + if (shape.intersects(otherShape)) { + eventsToFire.add(new OverlapEventToFire(entity, new HitboxOverlapEvent(otherEntity))); + } + } + } + } + + for (OverlapEventToFire overlapEventToFire : eventsToFire) { + overlapEventToFire.entity.send(overlapEventToFire.hitboxOverlapEvent); + } + } + + private Rectangle2D createShape(RectangleHitboxComponent rectangleHitbox, LocationComponent location) { + return new Rectangle2D.Float(location.getX() + rectangleHitbox.getTranslateX(), location.getY() + rectangleHitbox.getTranslateY(), + rectangleHitbox.getWidth(), rectangleHitbox.getHeight()); + } + + private static class OverlapEventToFire { + private EntityRef entity; + private HitboxOverlapEvent hitboxOverlapEvent; + + public OverlapEventToFire(EntityRef entity, HitboxOverlapEvent hitboxOverlapEvent) { + this.entity = entity; + this.hitboxOverlapEvent = hitboxOverlapEvent; + } + } +} diff --git a/core/src/main/java/jgd/platformer/logic/hitbox/RectangleHitboxComponent.java b/core/src/main/java/jgd/platformer/logic/hitbox/RectangleHitboxComponent.java new file mode 100644 index 0000000..275a04b --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/hitbox/RectangleHitboxComponent.java @@ -0,0 +1,13 @@ +package jgd.platformer.logic.hitbox; + +import com.gempukku.secsy.entity.Component; + +public interface RectangleHitboxComponent extends Component { + float getTranslateX(); + + float getTranslateY(); + + float getWidth(); + + float getHeight(); +} diff --git a/core/src/main/java/jgd/platformer/logic/physics/PlatformCollider.java b/core/src/main/java/jgd/platformer/logic/physics/PlatformCollider.java index 190804a..05ef35a 100644 --- a/core/src/main/java/jgd/platformer/logic/physics/PlatformCollider.java +++ b/core/src/main/java/jgd/platformer/logic/physics/PlatformCollider.java @@ -1,6 +1,9 @@ package jgd.platformer.logic.physics; +import com.gempukku.gaming.asset.prefab.PrefabManager; +import com.gempukku.secsy.context.annotation.Inject; import com.gempukku.secsy.context.annotation.RegisterSystem; +import com.gempukku.secsy.entity.EntityManager; import com.gempukku.secsy.entity.EntityRef; import com.gempukku.secsy.entity.dispatch.ReceiveEvent; import com.gempukku.secsy.entity.event.AfterComponentAdded; @@ -10,19 +13,33 @@ import java.awt.geom.Rectangle2D; import java.util.LinkedList; import java.util.List; +import java.util.Map; @RegisterSystem public class PlatformCollider { + @Inject + private PrefabManager prefabManager; + @Inject + private EntityManager entityManager; + private List platformBlocks = new LinkedList<>(); @ReceiveEvent public void levelLoaded(AfterComponentAdded event, EntityRef entity, LevelComponent level) { - for (String blockCoordinates : level.getBlockCoordinates().keySet()) { - String[] split = blockCoordinates.split(","); - float x = Float.parseFloat(split[0]); - float y = Float.parseFloat(split[1]); - - platformBlocks.add(new Rectangle2D.Float(x, y, 1, 1)); + Map blockCoordinates = level.getBlockCoordinates(); + for (Map.Entry blockCoordinate : blockCoordinates.entrySet()) { + String location = blockCoordinate.getKey(); + String prefab = blockCoordinate.getValue(); + EntityRef prefabData = entityManager.wrapEntityData(prefabManager.getPrefabByName(prefab)); + CollidingObjectComponent collidingObject = prefabData.getComponent(CollidingObjectComponent.class); + if (collidingObject != null) { + String[] locationSplit = location.split(","); + float x = Float.parseFloat(locationSplit[0]); + float y = Float.parseFloat(locationSplit[1]); + platformBlocks.add(new Rectangle2D.Float( + x + collidingObject.getTranslateX(), y + collidingObject.getTranslateY(), + collidingObject.getWidth(), collidingObject.getHeight())); + } } } diff --git a/core/src/main/java/jgd/platformer/logic/portal/LevelExitPortalComponent.java b/core/src/main/java/jgd/platformer/logic/portal/LevelExitPortalComponent.java new file mode 100644 index 0000000..a15ece1 --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/portal/LevelExitPortalComponent.java @@ -0,0 +1,6 @@ +package jgd.platformer.logic.portal; + +import com.gempukku.secsy.entity.Component; + +public interface LevelExitPortalComponent extends Component { +} diff --git a/core/src/main/java/jgd/platformer/logic/portal/LevelExitSystem.java b/core/src/main/java/jgd/platformer/logic/portal/LevelExitSystem.java new file mode 100644 index 0000000..47f347c --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/portal/LevelExitSystem.java @@ -0,0 +1,17 @@ +package jgd.platformer.logic.portal; + +import com.gempukku.secsy.context.annotation.RegisterSystem; +import com.gempukku.secsy.entity.EntityRef; +import com.gempukku.secsy.entity.dispatch.ReceiveEvent; +import jgd.platformer.logic.PlayerComponent; +import jgd.platformer.logic.hitbox.HitboxOverlapEvent; + +@RegisterSystem +public class LevelExitSystem { + @ReceiveEvent + public void playerEnteredPortal(HitboxOverlapEvent event, EntityRef entity, PlayerComponent player) { + if (event.getOtherEntity().hasComponent(LevelExitPortalComponent.class)) { + System.out.println("Player exited"); + } + } +}