From 458d30f107e0985f2a0f57290dd39c8918f52dfd Mon Sep 17 00:00:00 2001 From: eldek Date: Thu, 2 Apr 2026 15:42:08 -0300 Subject: [PATCH] Partially implemented office.json and states in animatronics movements --- .../data/config/animatronics/toy_freddy.json | 9 +- assets/data/config/cameras.json | 100 +++--- assets/data/config/office.json | 60 ++++ .../eldek0/config/CameraConfigFile.java | 9 - .../github/eldek0/config/CameraVariant.java | 8 - .../eldek0/config/animatronic/AnimState.java | 6 + .../config/animatronic/AnimatronicConfig.java | 5 +- .../animatronic/AnimatronicMovement.java | 2 +- .../eldek0/config/animatronic/Path.java | 6 + .../config/{ => camera}/CameraConfig.java | 4 +- .../config/camera/CameraConfigFile.java | 13 + .../config/{ => camera}/CameraSpriteType.java | 2 +- .../eldek0/config/camera/CameraVariant.java | 10 + .../eldek0/config/office/OfficeConfig.java | 20 ++ .../config/office/OfficeConfigFile.java | 5 + .../eldek0/config/office/OfficeVariant.java | 8 + .../io/github/eldek0/game/Animatronic.java | 18 +- .../java/io/github/eldek0/game/Camera.java | 305 +++++++++++------- .../java/io/github/eldek0/game/Office.java | 157 +++++---- .../io/github/eldek0/screen/GameScene.java | 2 +- 20 files changed, 487 insertions(+), 262 deletions(-) create mode 100644 assets/data/config/office.json delete mode 100644 core/src/main/java/io/github/eldek0/config/CameraConfigFile.java delete mode 100644 core/src/main/java/io/github/eldek0/config/CameraVariant.java create mode 100644 core/src/main/java/io/github/eldek0/config/animatronic/AnimState.java create mode 100644 core/src/main/java/io/github/eldek0/config/animatronic/Path.java rename core/src/main/java/io/github/eldek0/config/{ => camera}/CameraConfig.java (76%) create mode 100644 core/src/main/java/io/github/eldek0/config/camera/CameraConfigFile.java rename core/src/main/java/io/github/eldek0/config/{ => camera}/CameraSpriteType.java (71%) create mode 100644 core/src/main/java/io/github/eldek0/config/camera/CameraVariant.java create mode 100644 core/src/main/java/io/github/eldek0/config/office/OfficeConfig.java create mode 100644 core/src/main/java/io/github/eldek0/config/office/OfficeConfigFile.java create mode 100644 core/src/main/java/io/github/eldek0/config/office/OfficeVariant.java diff --git a/assets/data/config/animatronics/toy_freddy.json b/assets/data/config/animatronics/toy_freddy.json index 540f19e..2474d9e 100644 --- a/assets/data/config/animatronics/toy_freddy.json +++ b/assets/data/config/animatronics/toy_freddy.json @@ -2,14 +2,17 @@ "id": "toy_freddy", "displayName": "Freddy Fazbear (Toy)", - "inRoom": 9, - "restRoom": 9, + "inRoom": "cam9", + "restRoom": "cam9", "color": "#FF5733", "movement": { "type": "SEQUENTIAL", - "path": [9, 10, -2, -3], + "path": [ + { "room": "hallway", "state": 0 }, + { "room": "hallway", "state": 1 } + ], "moveIntervalSeconds": 12, "aiSpeedMultiplier": true }, diff --git a/assets/data/config/cameras.json b/assets/data/config/cameras.json index 55a342f..761d108 100644 --- a/assets/data/config/cameras.json +++ b/assets/data/config/cameras.json @@ -1,5 +1,5 @@ { - "inCameraId": 1, + "inCameraId": "cam1", "wideRandomMov": { "min": 5000, "max": 7000 @@ -19,171 +19,171 @@ ], "cameras": [ { - "id": 1, + "id": "cam1", "name": "PartyRoom1", "labelPathId": 0, "buttonX": 595, "buttonY": 496, "wide": false, "variants": [ - { "animatronics": ["toy_chica"], "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["withered_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "toy_chica" }], "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "withered_bonnie" }], "indexOff": 0, "indexOn": 2 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 2, + "id": "cam2", "name": "PartyRoom2", "labelPathId": 1, "buttonX": 710, "buttonY": 496, "wide": false, "variants": [ - { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["withered_chica"], "indexOff": 3, "indexOn": 4 }, + { "animatronics": [{ "id": "toy_bonnie" }], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "withered_chica" }], "indexOff": 3, "indexOn": 4 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 3, + "id": "cam3", "name": "PartyRoom3", "labelPathId": 2, "buttonX": 595, "buttonY": 431, "wide": false, "variants": [ - { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["withered_freddy"], "indexOff": 3, "indexOn": 4 }, + { "animatronics": [{ "id": "toy_bonnie" }], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "withered_freddy" }], "indexOff": 3, "indexOn": 4 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 4, + "id": "cam4", "name": "PartyRoom4", "labelPathId": 3, "buttonX": 710, "buttonY": 431, "wide": false, "variants": [ - { "animatronics": ["toy_bonnie"], "indexOff": 2, "indexOn": 3 }, - { "animatronics": ["toy_chica"], "indexOff": 0, "indexOn": 4 }, - { "animatronics": ["withered_chica"], "indexOff": 0, "indexOn": 5 }, + { "animatronics": [{ "id": "toy_bonnie" }], "indexOff": 2, "indexOn": 3 }, + { "animatronics": [{ "id": "toy_chica" }], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "withered_chica" }], "indexOff": 0, "indexOn": 5 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 5, + "id": "cam5", "name": "LeftAirVent", "labelPathId": 4, "buttonX": 585, "buttonY": 595, "wide": false, "variants": [ - { "animatronics": ["toy_chica"], "indexOff": 0, "indexOn": 4 }, - { "animatronics": ["baloon_boy"], "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["withered_bonnie"], "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["endo"], "indexOff": 0, "indexOn": 5 }, + { "animatronics": [{ "id": "toy_chica" }], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "baloon_boy" }], "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "withered_bonnie" }], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "endo" }], "indexOff": 0, "indexOn": 5 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 6, + "id": "cam6", "name": "RightAirVent", "labelPathId": 5, "buttonX": 695, "buttonY": 595, "wide": false, "variants": [ - { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["withered_chica"], "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["mangle"], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "toy_bonnie" }], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "withered_chica" }], "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "mangle" }], "indexOff": 0, "indexOn": 4 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 7, + "id": "cam7", "name": "MainHall", "labelPathId": 6, "buttonX": 734, "buttonY": 367, "wide": true, "variants": [ - { "animatronics": ["toy_chica"], "indexOff": 4, "indexOn": 5 }, - { "animatronics": ["withered_freddy"], "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["withered_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "toy_chica" }], "indexOff": 4, "indexOn": 5 }, + { "animatronics": [{ "id": "withered_freddy" }], "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "withered_bonnie" }], "indexOff": 0, "indexOn": 2 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 8, + "id": "cam8", "name": "PartsnService", "labelPathId": 7, "buttonX": 575, "buttonY": 356, "wide": true, "variants": [ - { "animatronics": ["withered_freddy", "withered_bonnie", "withered_chica"], "indexOff": 0, "indexOn": 1 }, - { "animatronics": ["withered_freddy", "withered_chica"], "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["withered_freddy"], "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["foxy"], "indexOff": 0, "indexOn": 4 }, - { "animatronics": ["TODO"], "condition": "ENDO_1987", "indexOff": 0, "indexOn": 6 }, - { "animatronics": ["TODO"], "condition": "SHADOW_FREDDY", "indexOff": 0, "indexOn": 5 }, + { "animatronics": [{ "id": "withered_freddy" }, { "id": "withered_bonnie" }, { "id": "withered_chica" }], "indexOff": 0, "indexOn": 1 }, + { "animatronics": [{ "id": "withered_freddy" }, { "id": "withered_chica" }], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "withered_freddy" }], "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "foxy" }], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "TODO" }], "condition": "ENDO_1987", "indexOff": 0, "indexOn": 6 }, + { "animatronics": [{ "id": "TODO" }], "condition": "SHADOW_FREDDY", "indexOff": 0, "indexOn": 5 }, { "animatronics": [], "indexOff": 0, "indexOn": 5 } ] }, { - "id": 9, + "id": "cam9", "name": "ShowStage", "labelPathId": 8, "buttonX": 895, "buttonY": 331, "wide": true, "variants": [ - { "animatronics": ["toy_bonnie", "toy_freddy", "toy_chica"], "indexOff": 0, "indexOn": 1 }, - { "animatronics": ["toy_freddy", "toy_chica"], "indexOff": 2, "indexOn": 3 }, - { "animatronics": ["toy_freddy"], "indexOff": 4, "indexOn": 5 }, + { "animatronics": [{ "id": "toy_bonnie" }, { "id": "toy_freddy" }, { "id": "toy_chica" }], "indexOff": 0, "indexOn": 1 }, + { "animatronics": [{ "id": "toy_freddy" }, { "id": "toy_chica" }], "indexOff": 2, "indexOn": 3 }, + { "animatronics": [{ "id": "toy_freddy" }], "indexOff": 4, "indexOn": 5 }, { "animatronics": [], "indexOff": 6, "indexOn": -1 } ] }, { - "id": 10, + "id": "cam10", "name": "GameArea", "labelPathId": 9, "buttonX": 820, "buttonY": 455, "wide": true, "variants": [ - { "animatronics": ["toy_freddy", "baloon_boy"], "indexOff": 0, "indexOn": 4 }, - { "animatronics": ["toy_freddy"], "indexOff": 2, "indexOn": 5 }, - { "animatronics": ["baloon_boy"], "indexOff": 0, "indexOn": 1 }, + { "animatronics": [{ "id": "toy_freddy" }, { "id": "baloon_boy" }], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "toy_freddy" }], "indexOff": 2, "indexOn": 5 }, + { "animatronics": [{ "id": "baloon_boy" }], "indexOff": 0, "indexOn": 1 }, { "animatronics": [], "indexOff": 2, "indexOn": 3 } ] }, { - "id": 11, + "id": "cam11", "name": "PrizeCorner", "labelPathId": 10, "buttonX": 929, "buttonY": 405, "wide": true, "variants": [ - { "animatronics": ["puppet"], "indexOff": 0, "indexOn": 1 }, - { "animatronics": ["puppet", "TODO"], "condition": "PUPPET_POS_1_TIMEOUT", "indexOff": 0, "indexOn": 2 }, - { "animatronics": ["puppet", "TODO"], "condition": "PUPPET_POS_2_TIMEOUT", "indexOff": 0, "indexOn": 3 }, - { "animatronics": ["puppet", "TODO"], "condition": "PUPPET_POS_3_TIMEOUT", "indexOff": 0, "indexOn": 4 }, - { "animatronics": ["endo"], "indexOff": 0, "indexOn": 5 }, + { "animatronics": [{ "id": "puppet" }], "indexOff": 0, "indexOn": 1 }, + { "animatronics": [{ "id": "puppet" }, { "id": "TODO" }], "condition": "PUPPET_POS_1_TIMEOUT", "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "puppet" }, { "id": "TODO" }], "condition": "PUPPET_POS_2_TIMEOUT", "indexOff": 0, "indexOn": 3 }, + { "animatronics": [{ "id": "puppet" }, { "id": "TODO" }], "condition": "PUPPET_POS_3_TIMEOUT", "indexOff": 0, "indexOn": 4 }, + { "animatronics": [{ "id": "endo" }], "indexOff": 0, "indexOn": 5 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] }, { - "id": 12, + "id": "cam12", "name": "KidsCove", "labelPathId": 11, "buttonX": 920, "buttonY": 503, "wide": true, "variants": [ - { "animatronics": ["mangle"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [{ "id": "mangle" }], "indexOff": 0, "indexOn": 2 }, { "animatronics": [], "indexOff": 0, "indexOn": 1 } ] } diff --git a/assets/data/config/office.json b/assets/data/config/office.json new file mode 100644 index 0000000..459f72b --- /dev/null +++ b/assets/data/config/office.json @@ -0,0 +1,60 @@ +{ + "config": [ + { + "id": "hallway", + "officeSpriteKey": "hallway", + "hitbox": { + "x": 600, + "y": 200, + "width": 400, + "height": 300 + }, + "variants": [ + { + "animatronics": [], + "indexOn": 0 + }, + { + "animatronics": [{"id": "toy_freddy", "state": 0}], + "indexOn": 2 + }, + { + "animatronics": [{"id": "toy_freddy", "state": 1}], + "indexOn": 4 + } + ] + }, + { + "id": "rightVent", + "officeSpriteKey": "rightVents", + "hitbox": { + "x": 1440, + "y": 200, + "width": 80, + "height": 90 + }, + "variants": [ + { + "animatronics": [], + "indexOn": 0 + } + ] + }, + { + "id": "leftVent", + "officeSpriteKey": "leftVents", + "hitbox": { + "x": 100, + "y": 200, + "width": 80, + "height": 90 + }, + "variants": [ + { + "animatronics": [], + "indexOn": 0 + } + ] + } + ] +} diff --git a/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java b/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java deleted file mode 100644 index ff3d605..0000000 --- a/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.eldek0.config; - -public class CameraConfigFile { - public int inCameraId; - public RangeLong wideRandomMov; - public Rect lightHitbox; - public SpritePositionData[] sprites; - public CameraConfig[] cameras; -} diff --git a/core/src/main/java/io/github/eldek0/config/CameraVariant.java b/core/src/main/java/io/github/eldek0/config/CameraVariant.java deleted file mode 100644 index 2deaa70..0000000 --- a/core/src/main/java/io/github/eldek0/config/CameraVariant.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.eldek0.config; - -public class CameraVariant { - public String[] animatronics; - public int indexOff; - public int indexOn = -1; - public String condition = null; -} diff --git a/core/src/main/java/io/github/eldek0/config/animatronic/AnimState.java b/core/src/main/java/io/github/eldek0/config/animatronic/AnimState.java new file mode 100644 index 0000000..6a90a96 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/animatronic/AnimState.java @@ -0,0 +1,6 @@ +package io.github.eldek0.config.animatronic; + +public class AnimState { + public String id; + public int state = 0; +} diff --git a/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicConfig.java b/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicConfig.java index afe97c0..226ca5e 100644 --- a/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicConfig.java +++ b/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicConfig.java @@ -3,8 +3,9 @@ package io.github.eldek0.config.animatronic; public class AnimatronicConfig { public String id; public String displayName; - public int inRoom; - public int restRoom; + public String inRoom; + public int state = 0; + public String restRoom; public String color; public AnimatronicMovement movement; public AttackType attackType; diff --git a/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicMovement.java b/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicMovement.java index fc81255..c1093f8 100644 --- a/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicMovement.java +++ b/core/src/main/java/io/github/eldek0/config/animatronic/AnimatronicMovement.java @@ -2,7 +2,7 @@ package io.github.eldek0.config.animatronic; public class AnimatronicMovement { public MovementType type; - public int[] path; + public Path[] path; public int moveIntervalSeconds; public boolean aiSpeedMultiplier; diff --git a/core/src/main/java/io/github/eldek0/config/animatronic/Path.java b/core/src/main/java/io/github/eldek0/config/animatronic/Path.java new file mode 100644 index 0000000..0115457 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/animatronic/Path.java @@ -0,0 +1,6 @@ +package io.github.eldek0.config.animatronic; + +public class Path { + public String room; + public int state = 0; +} diff --git a/core/src/main/java/io/github/eldek0/config/CameraConfig.java b/core/src/main/java/io/github/eldek0/config/camera/CameraConfig.java similarity index 76% rename from core/src/main/java/io/github/eldek0/config/CameraConfig.java rename to core/src/main/java/io/github/eldek0/config/camera/CameraConfig.java index ded1951..6d5c1ea 100644 --- a/core/src/main/java/io/github/eldek0/config/CameraConfig.java +++ b/core/src/main/java/io/github/eldek0/config/camera/CameraConfig.java @@ -1,7 +1,7 @@ -package io.github.eldek0.config; +package io.github.eldek0.config.camera; public class CameraConfig { - public int id; + public String id; public String name; public int labelPathId; public float buttonX; diff --git a/core/src/main/java/io/github/eldek0/config/camera/CameraConfigFile.java b/core/src/main/java/io/github/eldek0/config/camera/CameraConfigFile.java new file mode 100644 index 0000000..abf4fa4 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/camera/CameraConfigFile.java @@ -0,0 +1,13 @@ +package io.github.eldek0.config.camera; + +import io.github.eldek0.config.RangeLong; +import io.github.eldek0.config.Rect; +import io.github.eldek0.config.SpritePositionData; + +public class CameraConfigFile { + public String inCameraId; + public RangeLong wideRandomMov; + public Rect lightHitbox; + public SpritePositionData[] sprites; + public CameraConfig[] cameras; +} diff --git a/core/src/main/java/io/github/eldek0/config/CameraSpriteType.java b/core/src/main/java/io/github/eldek0/config/camera/CameraSpriteType.java similarity index 71% rename from core/src/main/java/io/github/eldek0/config/CameraSpriteType.java rename to core/src/main/java/io/github/eldek0/config/camera/CameraSpriteType.java index 84a3d3a..6c176dd 100644 --- a/core/src/main/java/io/github/eldek0/config/CameraSpriteType.java +++ b/core/src/main/java/io/github/eldek0/config/camera/CameraSpriteType.java @@ -1,4 +1,4 @@ -package io.github.eldek0.config; +package io.github.eldek0.config.camera; public enum CameraSpriteType { BORDER, diff --git a/core/src/main/java/io/github/eldek0/config/camera/CameraVariant.java b/core/src/main/java/io/github/eldek0/config/camera/CameraVariant.java new file mode 100644 index 0000000..fe8f7fc --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/camera/CameraVariant.java @@ -0,0 +1,10 @@ +package io.github.eldek0.config.camera; + +import io.github.eldek0.config.animatronic.AnimState; + +public class CameraVariant { + public AnimState[] animatronics; + public int indexOff; + public int indexOn = -1; + public String condition = null; +} diff --git a/core/src/main/java/io/github/eldek0/config/office/OfficeConfig.java b/core/src/main/java/io/github/eldek0/config/office/OfficeConfig.java new file mode 100644 index 0000000..12673b9 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/office/OfficeConfig.java @@ -0,0 +1,20 @@ +package io.github.eldek0.config.office; + +import io.github.eldek0.config.Rect; + +public class OfficeConfig { + public String id; + public Rect hitbox; + public String officeSpriteKey; + public OfficeVariant[] variants; + + private boolean lightOn = true; + + public boolean isLightOn() { + return lightOn; + } + + public void setLightOn(boolean lightOn) { + this.lightOn = lightOn; + } +} diff --git a/core/src/main/java/io/github/eldek0/config/office/OfficeConfigFile.java b/core/src/main/java/io/github/eldek0/config/office/OfficeConfigFile.java new file mode 100644 index 0000000..c24c074 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/office/OfficeConfigFile.java @@ -0,0 +1,5 @@ +package io.github.eldek0.config.office; + +public class OfficeConfigFile { + public OfficeConfig[] config; +} diff --git a/core/src/main/java/io/github/eldek0/config/office/OfficeVariant.java b/core/src/main/java/io/github/eldek0/config/office/OfficeVariant.java new file mode 100644 index 0000000..8365598 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/office/OfficeVariant.java @@ -0,0 +1,8 @@ +package io.github.eldek0.config.office; + +import io.github.eldek0.config.animatronic.AnimState; + +public class OfficeVariant { + public AnimState[] animatronics; + public int indexOn; +} diff --git a/core/src/main/java/io/github/eldek0/game/Animatronic.java b/core/src/main/java/io/github/eldek0/game/Animatronic.java index 4a8f435..f48142f 100644 --- a/core/src/main/java/io/github/eldek0/game/Animatronic.java +++ b/core/src/main/java/io/github/eldek0/game/Animatronic.java @@ -4,11 +4,9 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Json; import io.github.eldek0.config.animatronic.AnimatronicConfig; import io.github.eldek0.config.animatronic.AnimatronicManifest; +import io.github.eldek0.config.animatronic.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; +import java.util.*; public class Animatronic { private static final String MANIFEST = "data/config/animatronics.json"; @@ -66,17 +64,19 @@ public class Animatronic { index = 0; } animatronic.movement.setPathIndex(index); - animatronic.inRoom = animatronic.movement.path[index]; + Path path = animatronic.movement.path[index]; + animatronic.inRoom = path.room; + animatronic.state = path.state; movementsTimer[i] = 0; } } } - public List getAnimatronicsInLocation(int location){ - List list = new ArrayList<>(); + public List getAnimatronicsInLocation(String location){ + List list = new ArrayList<>(); for (AnimatronicConfig animatronic : data.values()){ - if (animatronic.inRoom == location){ - list.add(animatronic.id); + if (Objects.equals(animatronic.inRoom, location)){ + list.add(animatronic); } } return list; diff --git a/core/src/main/java/io/github/eldek0/game/Camera.java b/core/src/main/java/io/github/eldek0/game/Camera.java index fcd66a9..f79cc50 100644 --- a/core/src/main/java/io/github/eldek0/game/Camera.java +++ b/core/src/main/java/io/github/eldek0/game/Camera.java @@ -10,92 +10,106 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Json; import io.github.eldek0.App; -import io.github.eldek0.config.*; +import io.github.eldek0.config.RangeLong; +import io.github.eldek0.config.SpriteConfig; +import io.github.eldek0.config.animatronic.AnimState; import io.github.eldek0.config.animatronic.AnimatronicConfig; +import io.github.eldek0.config.camera.CameraConfig; +import io.github.eldek0.config.camera.CameraConfigFile; +import io.github.eldek0.config.camera.CameraSpriteType; +import io.github.eldek0.config.camera.CameraVariant; import io.github.eldek0.screen.GameScene; import io.github.eldek0.ui.SpriteLayout; import java.util.*; +import java.util.stream.Collectors; import static io.github.eldek0.App.assets; public class Camera { - private static final float CAMERA_SPEED = 5f * 60f; // px/s + private static final float CAMERA_SPEED = 5f * 60f; private static final String CONFIG = "data/config/cameras.json"; private CameraConfig[] cameraConfigs; + private final Map camerasById = new LinkedHashMap<>(); - /** 1-based room index currently shown on the monitor. */ - private int inCameraRoom; + private String inCameraRoom; - private Rectangle[] buttonScreenRects; + private final Map buttonScreenRects = new HashMap<>(); private Rectangle lightHitbox; - // Wide-camera panning - private float[] camerasXPosition; - private int[] wideCameraMovDirection; - private long[] timerCheckpoints; - private long[] timerWaitTimeMs; + private final Map camerasXPosition = new HashMap<>(); + private final Map wideCameraMovDirection = new HashMap<>(); + private final Map timerCheckpoints = new HashMap<>(); + private final Map timerWaitTimeMs = new HashMap<>(); private RangeLong wideRandomMov; - private boolean[] occupiedCamera; + private final Map occupiedCamera = new HashMap<>(); - private float recBlinkTimer = 0f; - private boolean recVisible = true; - - SpriteLayout layout; - - private GameScene gameScene; + private float recBlinkTimer = 0f; + private boolean recVisible = true; + private SpriteLayout layout; + private final GameScene gameScene; private boolean lightOn; public Camera(GameScene gameScene) { this.gameScene = gameScene; loadCameraConfig(); - initializeArrays(); - - java.util.Random rng = new java.util.Random(); - for (int i = 0; i < cameraConfigs.length; i++) { - timerWaitTimeMs[i] = wideRandomMov.min + (long) rng.nextInt((int) (wideRandomMov.max - wideRandomMov.min)); - } + initializeMaps(); + initButtonScreenRects(); + randomizeWideTimers(); this.lightOn = false; - this.initButtonScreenRects(); } - private void initializeArrays() { - int camCount = cameraConfigs.length; + private void initializeMaps() { + camerasById.clear(); - buttonScreenRects = new Rectangle[camCount]; - camerasXPosition = new float[camCount]; - wideCameraMovDirection = new int[camCount]; - timerCheckpoints = new long[camCount]; - timerWaitTimeMs = new long[camCount]; - occupiedCamera = new boolean[camCount]; + for (CameraConfig config : cameraConfigs) { + camerasById.put(config.id, config); + camerasXPosition.put(config.id, 0f); + wideCameraMovDirection.put(config.id, 0); + timerCheckpoints.put(config.id, 0L); + timerWaitTimeMs.put(config.id, 0L); + occupiedCamera.put(config.id, false); + } } - private void initButtonScreenRects(){ + private void randomizeWideTimers() { + Random rng = new Random(); + + for (CameraConfig config : cameraConfigs) { + long wait = wideRandomMov.min + + (long) rng.nextInt((int) (wideRandomMov.max - wideRandomMov.min)); + timerWaitTimeMs.put(config.id, wait); + } + } + + private void initButtonScreenRects() { Texture btnUnsel = assets.cameras.roomButtonUnselected; - for (int i = 0; i < cameraConfigs.length; i++) { - CameraConfig cameraConfig = cameraConfigs[i]; - - float worldY = App.SCREEN_HEIGHT - cameraConfig.buttonY - btnUnsel.getHeight(); - buttonScreenRects[i] = new Rectangle( - cameraConfig.buttonX, - worldY, - btnUnsel.getWidth(), - btnUnsel.getHeight()); + for (CameraConfig config : cameraConfigs) { + float worldY = App.SCREEN_HEIGHT - config.buttonY - btnUnsel.getHeight(); + buttonScreenRects.put( + config.id, + new Rectangle( + config.buttonX, + worldY, + btnUnsel.getWidth(), + btnUnsel.getHeight() + ) + ); } } public void update(float delta) { debugUpdateCamConfig(); - for (int i = 0; i < cameraConfigs.length; i++) { - if (cameraConfigs[i].wide) { - updateCameraTimer(i, delta); + for (CameraConfig config : cameraConfigs) { + if (config.wide) { + updateCameraTimer(config.id, delta); } } @@ -105,11 +119,11 @@ public class Camera { recVisible = !recVisible; } - this.onTouchDown(); + onTouchDown(); } public void renderBackground(SpriteBatch batch) { - if (!gameScene.hud.isInsideCamera()){return;} + if (!gameScene.hud.isInsideCamera()) return; renderCurrentRoom(batch); } @@ -122,9 +136,10 @@ public class Camera { return; } - for (int i = 0; i < cameraConfigs.length; i++) { - if (buttonScreenRects[i].contains(position)) { - inCameraRoom = cameraConfigs[i].id; + for (CameraConfig config : cameraConfigs) { + Rectangle rect = buttonScreenRects.get(config.id); + if (rect != null && rect.contains(position)) { + inCameraRoom = config.id; lightOn = false; return; } @@ -134,40 +149,65 @@ public class Camera { } private void renderCurrentRoom(SpriteBatch batch) { - int idx = inCameraRoom - 1; - float xOff = camerasXPosition[idx]; - Texture frame; + CameraConfig currentCamera = camerasById.get(inCameraRoom); + if (currentCamera == null) return; - if (!occupiedCamera[idx]) { - List animatronicsInCam = gameScene.animatronic.getAnimatronicsInLocation(idx + 1); - CameraVariant variant = null; - for (CameraVariant v : cameraConfigs[idx].variants){ - System.out.println(animatronicsInCam + ", " + Arrays.toString(v.animatronics)); - if (Arrays.equals(v.animatronics, animatronicsInCam.toArray())){ - variant = v; - break; - } - } - if (variant == null){ - return; - } - if (lightOn && variant.indexOn != -1){ - frame = getFrame(inCameraRoom, variant.indexOn); - } - else { - frame = getFrame(inCameraRoom, variant.indexOff); - } + float xOff = camerasXPosition.getOrDefault(inCameraRoom, 0f); - if (frame != null) { - batch.draw(frame, xOff, 0); - } + if (occupiedCamera.getOrDefault(inCameraRoom, false)) { + return; + } + + List animatronicsInCam = + gameScene.animatronic.getAnimatronicsInLocation(currentCamera.id); + + CameraVariant variant = findVariant(currentCamera, animatronicsInCam); + if (variant == null) return; + + int frameIndex = (!lightOn || variant.indexOn == -1) + ? variant.indexOff + : variant.indexOn; + + Texture frame = getFrame(currentCamera.id, frameIndex); + if (frame != null) { + batch.draw(frame, xOff, 0); } } - private void loadCameraConfig(){ + private CameraVariant findVariant(CameraConfig camera, List animatronicsInCam) { + if (camera.variants == null) return null; + + Set inCamIds = animatronicsInCam.stream() + .filter(a -> a.inRoom.equals(camera.id)) + .map(a -> a.id) + .collect(Collectors.toSet()); + + for (CameraVariant variant : camera.variants) { + AnimState[] expected = variant.animatronics; + + if (expected.length == 0 && inCamIds.isEmpty()) { + return variant; + } + + if (expected.length != inCamIds.size()) continue; + + Set expectedIds = Arrays.stream(expected) + .map(a -> a.id) + .collect(Collectors.toSet()); + + if (expectedIds.equals(inCamIds)) { + return variant; + } + } + + return null; + } + + private void loadCameraConfig() { Json json = new Json(); String raw = Gdx.files.internal(CONFIG).readString(); CameraConfigFile configFile = json.fromJson(CameraConfigFile.class, raw); + this.inCameraRoom = configFile.inCameraId; this.cameraConfigs = configFile.cameras; this.wideRandomMov = configFile.wideRandomMov; @@ -182,16 +222,17 @@ public class Camera { configFile.sprites, CameraSpriteType::valueOf ); - } - private void debugUpdateCamConfig(){ + private void debugUpdateCamConfig() { Json json = new Json(); String raw = Gdx.files.internal(CONFIG).readString(); CameraConfigFile configFile = json.fromJson(CameraConfigFile.class, raw); - for (int i = 0; i= textures.length) { return null; } @@ -211,8 +253,10 @@ public class Camera { return textures[index]; } - private Texture getRoomLabel(int room) { - CameraConfig config = cameraConfigs[room - 1]; + private Texture getRoomLabel(String roomId) { + CameraConfig config = camerasById.get(roomId); + if (config == null) return null; + return assets.cameras.locationLabels.get(config.name); } @@ -228,9 +272,9 @@ public class Camera { } if (texture == null) continue; - if (config.type() == CameraSpriteType.REC && !recVisible) continue; - if (config.type() == CameraSpriteType.SIGNAL_INTERRUPTED && !occupiedCamera[inCameraRoom - 1]) continue; + if (config.type() == CameraSpriteType.SIGNAL_INTERRUPTED + && !occupiedCamera.getOrDefault(inCameraRoom, false)) continue; batch.draw( texture, @@ -243,37 +287,35 @@ public class Camera { } public void renderHitboxes(ShapeRenderer shapeRenderer) { + if (!gameScene.hud.isInsideCamera()) return; shapeRenderer.setColor(1, 0, 0, 1); - CameraConfig config; - Rectangle rect; - for (int i = 0; i timerWaitTimeMs[index]) { - timerCheckpoints[index] = 0; + long checkpoint = timerCheckpoints.getOrDefault(cameraId, 0L); + long waitTime = timerWaitTimeMs.getOrDefault(cameraId, 0L); + int direction = wideCameraMovDirection.getOrDefault(cameraId, 0); + float x = camerasXPosition.getOrDefault(cameraId, 0f); + + if (checkpoint != 0L) { + if (now - checkpoint > waitTime) { + timerCheckpoints.put(cameraId, 0L); } return; } - if (wideCameraMovDirection[index] == 0) { - camerasXPosition[index] -= CAMERA_SPEED * delta; - if (camerasXPosition[index] <= maxOffset) { - camerasXPosition[index] = maxOffset; - timerCheckpoints[index] = now; - wideCameraMovDirection[index] = 1; + if (direction == 0) { + x -= CAMERA_SPEED * delta; + if (x <= maxOffset) { + x = maxOffset; + timerCheckpoints.put(cameraId, now); + wideCameraMovDirection.put(cameraId, 1); } } else { - camerasXPosition[index] += CAMERA_SPEED * delta; - if (camerasXPosition[index] >= 0) { - camerasXPosition[index] = 0; - timerCheckpoints[index] = now; - wideCameraMovDirection[index] = 0; + x += CAMERA_SPEED * delta; + if (x >= 0) { + x = 0; + timerCheckpoints.put(cameraId, now); + wideCameraMovDirection.put(cameraId, 0); } } + + camerasXPosition.put(cameraId, x); } - public int getInCameraRoom() { return inCameraRoom; } - public void setInCameraRoom(int room) { this.inCameraRoom = room; } - public boolean isOccupied(int roomIndex) { return occupiedCamera[roomIndex]; } - public void setOccupied(int roomIndex, boolean v) { occupiedCamera[roomIndex] = v; } + public String getInCameraRoom() { + return inCameraRoom; + } + + public void setInCameraRoom(String roomId) { + this.inCameraRoom = roomId; + } + + public boolean isOccupied(String roomId) { + return occupiedCamera.getOrDefault(roomId, false); + } + + public void setOccupied(String roomId, boolean value) { + occupiedCamera.put(roomId, value); + } } diff --git a/core/src/main/java/io/github/eldek0/game/Office.java b/core/src/main/java/io/github/eldek0/game/Office.java index e21249a..87d290a 100644 --- a/core/src/main/java/io/github/eldek0/game/Office.java +++ b/core/src/main/java/io/github/eldek0/game/Office.java @@ -7,32 +7,42 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Json; import io.github.eldek0.App; -import io.github.eldek0.ui.HUD; +import io.github.eldek0.config.Rect; +import io.github.eldek0.config.animatronic.AnimState; +import io.github.eldek0.config.animatronic.AnimatronicConfig; +import io.github.eldek0.config.office.OfficeConfig; +import io.github.eldek0.config.office.OfficeConfigFile; +import io.github.eldek0.config.office.OfficeVariant; +import io.github.eldek0.screen.GameScene; + +import java.util.List; import static io.github.eldek0.App.assets; public class Office { + private static final String CONFIG = "data/config/office.json"; private static final float SPEED = 600; public static final float MAX_POS_X = assets.office.bg.getWidth() - App.SCREEN_WIDTH; - private final HUD hud; + private final GameScene gameScene; private final ShapeRenderer shapeRenderer; private int movement = 0; private float positionX = 0; - private boolean rightLight = false; - private boolean leftLight = false; - private boolean hallwayLight = false; + private OfficeConfig[] officeConfig; + private Rectangle[] hitboxes; - public Office(HUD hud) { - this.hud = hud; + public Office(GameScene gameScene) { + this.gameScene = gameScene; this.shapeRenderer = new ShapeRenderer(); + this.loadOfficeConfig(); this.inputInitialization(); } private void handleMovement(int screenX, int screenY) { - if (hud.isInsideMask() || hud.isInsideCamera()) return; + if (gameScene.hud.isInsideMask() || gameScene.hud.isInsideCamera()) return; Vector2 worldPos = App.convertPosToWorldPos(new Vector2(screenX, screenY)); float threshold = (float) App.SCREEN_WIDTH / 2 * 0.5f; @@ -42,6 +52,19 @@ public class Office { else movement = 0; } + private void loadOfficeConfig(){ + Json json = new Json(); + String raw = Gdx.files.internal(CONFIG).readString(); + OfficeConfigFile configFile = json.fromJson(OfficeConfigFile.class, raw); + officeConfig = configFile.config; + + hitboxes = new Rectangle[officeConfig.length]; + for (int i = 0; i< officeConfig.length; i++){ + Rect hitbox = officeConfig[i].hitbox; + hitboxes[i] = new Rectangle(hitbox.x + positionX, hitbox.y, hitbox.width, hitbox.height); + } + } + private void inputInitialization() { Gdx.input.setInputProcessor(new InputAdapter() { @Override @@ -51,59 +74,48 @@ public class Office { } @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - if (hud.isInsideMask() || hud.isInsideCamera()) return false; - - handleMovement(screenX, screenY); + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + if (gameScene.hud.isInsideMask() || gameScene.hud.isInsideCamera()) return false; Vector2 pos = App.convertPosToWorldPos(new Vector2(screenX, screenY)); - if (!getRightBounds().contains(pos)) rightLight = false; - if (!getLeftBounds().contains(pos)) leftLight = false; - if (!getHallwayBounds().contains(pos)) hallwayLight = false; - + for (int i = 0; i < officeConfig.length; i++) { + Rectangle rect = hitboxes[i]; + OfficeConfig config = officeConfig[i]; + if (rect.contains(pos)) config.setLightOn(true); + } return true; } @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - if (hud.isInsideMask() || hud.isInsideCamera()) return false; + public boolean touchDragged(int screenX, int screenY, int pointer) { + if (gameScene.hud.isInsideMask() || gameScene.hud.isInsideCamera()) return false; + + handleMovement(screenX, screenY); Vector2 pos = App.convertPosToWorldPos(new Vector2(screenX, screenY)); - if (getRightBounds().contains(pos)) rightLight = true; - if (getLeftBounds().contains(pos)) leftLight = true; - if (getHallwayBounds().contains(pos)) hallwayLight = true; - return false; + for (int i = 0; i < officeConfig.length; i++) { + Rectangle rect = hitboxes[i]; + OfficeConfig config = officeConfig[i]; + if (!rect.contains(pos)) config.setLightOn(false); + } + return true; } @Override public boolean touchUp(int screenX, int screenY, int pointer, int button) { - rightLight = false; - leftLight = false; - hallwayLight = false; + for (OfficeConfig config : officeConfig) { + config.setLightOn(false); + } return false; } }); } - private Rectangle getRightBounds() { - float lightHeight = App.SCREEN_HEIGHT - 340 - assets.office.rightVentButtonOff.getHeight(); - return new Rectangle(1440 + positionX, lightHeight, 80, 90); - } - - private Rectangle getLeftBounds() { - float lightHeight = App.SCREEN_HEIGHT - 340 - assets.office.leftVentButtonOff.getHeight(); - return new Rectangle(100 + positionX, lightHeight, 80, 90); - } - - private Rectangle getHallwayBounds() { - return new Rectangle(600 + positionX, 200, 400, 380); - } - public void render(SpriteBatch batch) { renderBackground(batch); - Texture btnRight = rightLight ? assets.office.rightVentButtonOn : assets.office.rightVentButtonOff; - Texture btnLeft = leftLight ? assets.office.leftVentButtonOn : assets.office.leftVentButtonOff; + Texture btnRight = assets.office.rightVentButtonOn; + Texture btnLeft = assets.office.leftVentButtonOn; float lightHeight = App.SCREEN_HEIGHT - 360 - btnRight.getHeight(); batch.draw(btnRight, 1440 + positionX, lightHeight); @@ -111,29 +123,66 @@ public class Office { } private void renderBackground(SpriteBatch batch) { - if (rightLight) batch.draw(assets.office.rightVents[0], positionX, 0); - else if (leftLight) batch.draw(assets.office.leftVents[0], positionX, 0); - else if (hallwayLight) batch.draw(assets.office.hallway[0], positionX, 0); - else batch.draw(assets.office.bg, positionX, 0); + Texture bg = assets.office.bg; + + for (OfficeConfig config : officeConfig) { + if (!config.isLightOn()) continue; + + List animInLocation = gameScene.animatronic + .getAnimatronicsInLocation(config.id); + if (animInLocation == null) animInLocation = List.of(); + + for (OfficeVariant variant : config.variants) { + AnimState[] variantList = variant.animatronics; + + if (variantList.length == 0 && animInLocation.isEmpty()) { + bg = assets.resolve("office", config.officeSpriteKey, variant.indexOn); + break; + } + + if (variantList.length != animInLocation.size()) continue; + + boolean allMatch = true; + for (AnimState animVariant : variantList) { + boolean found = animInLocation.stream().anyMatch(a -> + a.id.equals(animVariant.id) && a.state == animVariant.state + ); + if (!found) { + allMatch = false; + break; + } + } + + if (allMatch) { + bg = assets.resolve("office", config.officeSpriteKey, variant.indexOn); + break; + } + } + } + + batch.draw(bg, positionX, 0); } public void renderHitboxes(ShapeRenderer shapeRenderer) { - if (hud.isInsideMask() || hud.isInsideCamera()) return; + if (gameScene.hud.isInsideMask() || gameScene.hud.isInsideCamera()) return; shapeRenderer.setColor(1, 0, 0, 1); - Rectangle right = getRightBounds(); - Rectangle left = getLeftBounds(); - Rectangle hallway = getHallwayBounds(); - - shapeRenderer.rect(right.x, right.y, right.width, right.height); - shapeRenderer.rect(left.x, left.y, left.width, left.height); - shapeRenderer.rect(hallway.x, hallway.y, hallway.width, hallway.height); + for (OfficeConfig config : officeConfig){ + Rect hitbox = config.hitbox; + Rectangle rect = new Rectangle(hitbox.x + positionX, hitbox.y, hitbox.width, hitbox.height); + shapeRenderer.rect(rect.x, rect.y, rect.width, rect.height); + } } public void update(float dt) { positionX += SPEED * movement * dt; - if (-positionX < 0) positionX = 0; + if (-positionX < 0) positionX = 0; else if (-positionX > MAX_POS_X) positionX = -MAX_POS_X; + + for (int i = 0; i < officeConfig.length; i++) { + Rect hitbox = officeConfig[i].hitbox; + hitboxes[i].setPosition(hitbox.x + positionX, hitbox.y); + } } public void dispose() { diff --git a/core/src/main/java/io/github/eldek0/screen/GameScene.java b/core/src/main/java/io/github/eldek0/screen/GameScene.java index f3ff886..414cee2 100644 --- a/core/src/main/java/io/github/eldek0/screen/GameScene.java +++ b/core/src/main/java/io/github/eldek0/screen/GameScene.java @@ -37,7 +37,7 @@ public class GameScene implements Screen { this.batch = new SpriteBatch(); this.shapeRenderer = new ShapeRenderer(); - this.office = new Office(this.hud); + this.office = new Office(this); this.mask = new Mask(this.hud); this.camera = new Camera(this);