diff --git a/core/assets/prefabs/levels/level-sample.prefab b/core/assets/prefabs/levels/level-sample.prefab index 3c771e3..31760d8 100644 --- a/core/assets/prefabs/levels/level-sample.prefab +++ b/core/assets/prefabs/levels/level-sample.prefab @@ -5,5 +5,11 @@ "1,-1,0": "grass", "2,-1,0": "grass" } + }, + "CameraBoundsComponent": { + "minX": 0, + "minY": 0, + "maxX": 10, + "maxY": 10 } } \ 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 98995a0..b0fb389 100644 --- a/core/assets/prefabs/levels/level-sample2.prefab +++ b/core/assets/prefabs/levels/level-sample2.prefab @@ -8,5 +8,11 @@ "-3,0,0": "stone", "-4,0,0": "dirt" } + }, + "CameraBoundsComponent": { + "minX": 0, + "minY": 0, + "maxX": 10, + "maxY": 10 } } \ No newline at end of file diff --git a/core/assets/prefabs/player.prefab b/core/assets/prefabs/player.prefab index 9453f0f..5142881 100644 --- a/core/assets/prefabs/player.prefab +++ b/core/assets/prefabs/player.prefab @@ -1,6 +1,6 @@ { "LocationComponent": { - "x": 2, + "x": 0, "y": 0, "z": 0 }, @@ -10,5 +10,9 @@ "texturesForParts": { "all": "blockTiles/Stone.png" } + }, + "PlayerControlledComponent": {}, + "CameraFocusComponent": { + "focusWeight": 1 } } \ No newline at end of file diff --git a/core/src/main/java/jgd/platformer/Platformer.java b/core/src/main/java/jgd/platformer/Platformer.java index f77bf9e..40c3fd7 100644 --- a/core/src/main/java/jgd/platformer/Platformer.java +++ b/core/src/main/java/jgd/platformer/Platformer.java @@ -3,6 +3,7 @@ import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.graphics.FPSLogger; import com.gempukku.gaming.rendering.RenderingEngine; +import com.gempukku.gaming.time.InternalTimeManager; import com.gempukku.secsy.context.SECSyContext; import com.gempukku.secsy.entity.game.InternalGameLoop; import jgd.platformer.level.LevelLoader; @@ -13,6 +14,7 @@ import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; +import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -20,6 +22,14 @@ public class Platformer extends ApplicationAdapter { private FPSLogger fpsLogger; private SECSyContext context; + private long lastUpdateTime; + + private Collection additionalProfiles; + + public Platformer(Collection additionalProfiles) { + this.additionalProfiles = additionalProfiles; + } + @Override public void create() { fpsLogger = new FPSLogger(); @@ -34,6 +44,8 @@ public void create() { activeProfiles.add("prefabManager"); activeProfiles.add("annotationEventDispatcher"); activeProfiles.add("simpleEntityIndexManager"); + activeProfiles.add("time"); + activeProfiles.addAll(additionalProfiles); Configuration scanBasedOnAnnotations = new ConfigurationBuilder() .setScanners(new TypeAnnotationsScanner()) @@ -53,12 +65,19 @@ public void create() { for (Object system : context.getSystems()) { System.out.println(system.getClass().getSimpleName()); } + + lastUpdateTime = System.currentTimeMillis(); } @Override public void render() { fpsLogger.log(); + long timePassed = System.currentTimeMillis() - lastUpdateTime; + lastUpdateTime += timePassed; + + context.getSystem(InternalTimeManager.class).updateTime(timePassed); + context.getSystem(InternalGameLoop.class).processUpdate(); context.getSystem(RenderingEngine.class).render(); diff --git a/core/src/main/java/jgd/platformer/logic/PlatformerTimeEntityProvider.java b/core/src/main/java/jgd/platformer/logic/PlatformerTimeEntityProvider.java new file mode 100644 index 0000000..70de66f --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/PlatformerTimeEntityProvider.java @@ -0,0 +1,28 @@ +package jgd.platformer.logic; + +import com.gempukku.gaming.time.TimeEntityProvider; +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.EntityManager; +import com.gempukku.secsy.entity.EntityRef; + +@RegisterSystem( + shared = TimeEntityProvider.class +) +public class PlatformerTimeEntityProvider implements TimeEntityProvider, LifeCycleSystem { + @Inject + private EntityManager entityManager; + + private EntityRef timeEntity; + + @Override + public void initialize() { + timeEntity = entityManager.createEntity(); + } + + @Override + public EntityRef getTimeEntity() { + return timeEntity; + } +} diff --git a/core/src/main/java/jgd/platformer/logic/controls/KeyboardSystem.java b/core/src/main/java/jgd/platformer/logic/controls/KeyboardSystem.java new file mode 100644 index 0000000..9e5b378 --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/controls/KeyboardSystem.java @@ -0,0 +1,78 @@ +package jgd.platformer.logic.controls; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; +import com.gempukku.gaming.time.TimeManager; +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.game.GameLoop; +import com.gempukku.secsy.entity.game.GameLoopListener; +import com.gempukku.secsy.entity.index.EntityIndex; +import com.gempukku.secsy.entity.index.EntityIndexManager; +import jgd.platformer.component.LocationComponent; + +@RegisterSystem( + profiles = "keyboard" +) +public class KeyboardSystem implements LifeCycleSystem, GameLoopListener { + private static final float BLOCKS_PER_MILLISECOND = (4f / 1000); + @Inject + private GameLoop gameLoop; + @Inject + private TimeManager timeManager; + @Inject + private EntityIndexManager entityIndexManager; + + private int[] leftKeys = {Input.Keys.LEFT, Input.Keys.A}; + private int[] rightKeys = {Input.Keys.RIGHT, Input.Keys.D}; + private EntityIndex controlledEntities; + + @Override + public void initialize() { + gameLoop.addGameLoopListener(this); + + controlledEntities = entityIndexManager.addIndexOnComponents(PlayerControlledComponent.class, LocationComponent.class); + } + + @Override + public void update() { + boolean leftPressed = isLeftPressed(); + boolean rightPressed = isRightPressed(); + + long timeSinceLastUpdate = timeManager.getTimeSinceLastUpdate(); + + float xDiff = 0; + + if (leftPressed && !rightPressed) { + xDiff -= timeSinceLastUpdate * BLOCKS_PER_MILLISECOND; + } else if (rightPressed && !leftPressed) { + xDiff += timeSinceLastUpdate * BLOCKS_PER_MILLISECOND; + } + + if (xDiff != 0) { + for (EntityRef entityRef : controlledEntities.getEntities()) { + LocationComponent location = entityRef.getComponent(LocationComponent.class); + location.setX(location.getX() + xDiff); + entityRef.saveChanges(); + } + } + } + + private boolean isLeftPressed() { + return isAnyPressed(leftKeys); + } + + private boolean isRightPressed() { + return isAnyPressed(rightKeys); + } + + private boolean isAnyPressed(int[] keys) { + for (int key : keys) { + if (Gdx.input.isKeyPressed(key)) + return true; + } + return false; + } +} diff --git a/core/src/main/java/jgd/platformer/logic/controls/PlayerControlledComponent.java b/core/src/main/java/jgd/platformer/logic/controls/PlayerControlledComponent.java new file mode 100644 index 0000000..25444d9 --- /dev/null +++ b/core/src/main/java/jgd/platformer/logic/controls/PlayerControlledComponent.java @@ -0,0 +1,6 @@ +package jgd.platformer.logic.controls; + +import com.gempukku.secsy.entity.Component; + +public interface PlayerControlledComponent extends Component { +} diff --git a/core/src/main/java/jgd/platformer/rendering/CameraBoundsComponent.java b/core/src/main/java/jgd/platformer/rendering/CameraBoundsComponent.java new file mode 100644 index 0000000..27e6998 --- /dev/null +++ b/core/src/main/java/jgd/platformer/rendering/CameraBoundsComponent.java @@ -0,0 +1,13 @@ +package jgd.platformer.rendering; + +import com.gempukku.secsy.entity.Component; + +public interface CameraBoundsComponent extends Component { + float getMinX(); + + float getMaxX(); + + float getMinY(); + + float getMaxY(); +} diff --git a/core/src/main/java/jgd/platformer/rendering/CameraFocusComponent.java b/core/src/main/java/jgd/platformer/rendering/CameraFocusComponent.java new file mode 100644 index 0000000..a14271f --- /dev/null +++ b/core/src/main/java/jgd/platformer/rendering/CameraFocusComponent.java @@ -0,0 +1,9 @@ +package jgd.platformer.rendering; + +import com.gempukku.secsy.entity.Component; + +public interface CameraFocusComponent extends Component { + float getFocusWeight(); + + void setFocusWeight(float focusWeight); +} diff --git a/core/src/main/java/jgd/platformer/rendering/PlatformerRenderingEntityProvider.java b/core/src/main/java/jgd/platformer/rendering/PlatformerRenderingEntityProvider.java index 0987f0c..d355302 100644 --- a/core/src/main/java/jgd/platformer/rendering/PlatformerRenderingEntityProvider.java +++ b/core/src/main/java/jgd/platformer/rendering/PlatformerRenderingEntityProvider.java @@ -7,6 +7,9 @@ import com.gempukku.secsy.context.system.LifeCycleSystem; import com.gempukku.secsy.entity.EntityManager; import com.gempukku.secsy.entity.EntityRef; +import com.gempukku.secsy.entity.index.EntityIndex; +import com.gempukku.secsy.entity.index.EntityIndexManager; +import jgd.platformer.component.LocationComponent; @RegisterSystem( shared = RenderingEntityProvider.class @@ -15,12 +18,18 @@ public class PlatformerRenderingEntityProvider implements RenderingEntityProvide private static final int DISTANCE_FROM_TERRAIN = 8; @Inject private EntityManager entityManager; + @Inject + private EntityIndexManager entityIndexManager; private EntityRef cameraEntity; + private EntityIndex cameraFocusedEntities; + private EntityIndex cameraBoundsEntities; @Override public void initialize() { cameraEntity = entityManager.createEntity(); + cameraFocusedEntities = entityIndexManager.addIndexOnComponents(CameraFocusComponent.class, LocationComponent.class); + cameraBoundsEntities = entityIndexManager.addIndexOnComponents(CameraBoundsComponent.class); } @Override @@ -30,8 +39,32 @@ public EntityRef getRenderingEntity() { @Override public void setupRenderingCamera(Camera camera) { - camera.position.set(0, 0, DISTANCE_FROM_TERRAIN); - camera.lookAt(0, 0, 0); + float weightSum = 0; + float sumX = 0; + float sumY = 0; + + for (EntityRef entityRef : cameraFocusedEntities.getEntities()) { + CameraFocusComponent cameraFocus = entityRef.getComponent(CameraFocusComponent.class); + float weight = cameraFocus.getFocusWeight(); + if (weight > 0) { + LocationComponent location = entityRef.getComponent(LocationComponent.class); + sumX += location.getX() * weight; + sumY += location.getY() * weight; + weightSum += weight; + } + } + + float resultX = sumX / weightSum; + float resultY = sumY / weightSum; + + EntityRef boundsEntity = cameraBoundsEntities.getEntities().iterator().next(); + CameraBoundsComponent cameraBounds = boundsEntity.getComponent(CameraBoundsComponent.class); + + resultX = Math.max(Math.min(resultX, cameraBounds.getMaxX()), cameraBounds.getMinX()); + resultY = Math.max(Math.min(resultY, cameraBounds.getMaxY()), cameraBounds.getMinY()); + + camera.position.set(resultX, resultY, DISTANCE_FROM_TERRAIN); + camera.lookAt(resultX, resultY, 0); camera.up.set(0, 1, 0); } } diff --git a/desktop/src/main/java/jgd/platformer/desktop/DesktopLauncher.java b/desktop/src/main/java/jgd/platformer/desktop/DesktopLauncher.java index f8d4d69..7f46e98 100644 --- a/desktop/src/main/java/jgd/platformer/desktop/DesktopLauncher.java +++ b/desktop/src/main/java/jgd/platformer/desktop/DesktopLauncher.java @@ -4,6 +4,8 @@ import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import jgd.platformer.Platformer; +import java.util.Collections; + public class DesktopLauncher { public static void main(String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); @@ -11,6 +13,6 @@ public static void main(String[] arg) { config.backgroundFPS = 0; config.foregroundFPS = 0; config.vSyncEnabled = false; - new LwjglApplication(new Platformer(), config); + new LwjglApplication(new Platformer(Collections.singleton("keyboard")), config); } }