From 8e8574522294830b8186c6d65b71f36eada971c3 Mon Sep 17 00:00:00 2001 From: eldek Date: Wed, 1 Apr 2026 15:09:34 -0300 Subject: [PATCH] toy_freddy basic movement and camera adjust to the animatronics on it --- assets/data/config/animatronics.json | 2 +- .../{freddy.json => toy_freddy.json} | 12 +- assets/data/config/cameras.json | 125 +++++++++++++----- assets/data/sprites/minigames.json | 2 +- assets/data/sprites/office.json | 2 +- .../github/eldek0/asset/GameAssetManager.java | 42 +++++- .../eldek0/asset/group/AssetBundle.java | 6 + .../eldek0/asset/group/BatteryAssets.java | 14 ++ .../eldek0/asset/group/CameraAssets.java | 50 +++++++ .../eldek0/asset/group/CustomNightAssets.java | 21 +++ .../eldek0/asset/group/CutsceneAssets.java | 19 +++ .../eldek0/asset/group/JumpscareAssets.java | 20 +++ .../github/eldek0/asset/group/MaskAssets.java | 11 ++ .../github/eldek0/asset/group/MenuAssets.java | 58 ++++++++ .../eldek0/asset/group/MinigameAssets.java | 81 +++++++++++- .../eldek0/asset/group/MonitorAssets.java | 11 ++ .../eldek0/asset/group/NumbersAssets.java | 21 +++ .../eldek0/asset/group/OfficeAssets.java | 54 +++++++- .../io/github/eldek0/config/CameraConfig.java | 1 + .../eldek0/config/CameraConfigFile.java | 1 + .../github/eldek0/config/CameraVariant.java | 8 ++ .../java/io/github/eldek0/config/Rect.java | 5 + .../io/github/eldek0/config/SpriteConfig.java | 5 + .../eldek0/config/SpritePositionData.java | 4 + .../animatronic/AnimatronicMovement.java | 6 + .../eldek0/config/animatronic/AttackType.java | 4 +- .../io/github/eldek0/game/Animatronic.java | 44 ++++++ .../java/io/github/eldek0/game/Camera.java | 104 +++++++++++---- .../io/github/eldek0/screen/GameScene.java | 1 + .../io/github/eldek0/ui/SpriteLayout.java | 3 + movement.txt | 17 +++ 31 files changed, 674 insertions(+), 80 deletions(-) rename assets/data/config/animatronics/{freddy.json => toy_freddy.json} (61%) create mode 100644 core/src/main/java/io/github/eldek0/config/CameraVariant.java create mode 100644 core/src/main/java/io/github/eldek0/config/Rect.java create mode 100644 movement.txt diff --git a/assets/data/config/animatronics.json b/assets/data/config/animatronics.json index a42d909..9384c37 100644 --- a/assets/data/config/animatronics.json +++ b/assets/data/config/animatronics.json @@ -1,5 +1,5 @@ { "animatronics": [ - "freddy" + "toy_freddy" ] } diff --git a/assets/data/config/animatronics/freddy.json b/assets/data/config/animatronics/toy_freddy.json similarity index 61% rename from assets/data/config/animatronics/freddy.json rename to assets/data/config/animatronics/toy_freddy.json index f511217..540f19e 100644 --- a/assets/data/config/animatronics/freddy.json +++ b/assets/data/config/animatronics/toy_freddy.json @@ -1,6 +1,6 @@ { - "id": "freddy", - "displayName": "Freddy Fazbear", + "id": "toy_freddy", + "displayName": "Freddy Fazbear (Toy)", "inRoom": 9, "restRoom": 9, @@ -9,14 +9,14 @@ "movement": { "type": "SEQUENTIAL", - "path": [9], - "moveIntervalSeconds": 30, + "path": [9, 10, -2, -3], + "moveIntervalSeconds": 12, "aiSpeedMultiplier": true }, "attackType": { - "kind": "LIGHT", - "lightLevel": 3 + "kind": "IN_OFFICE", + "officeSprite": 3 }, "jumpscare": { diff --git a/assets/data/config/cameras.json b/assets/data/config/cameras.json index dc8e754..55a342f 100644 --- a/assets/data/config/cameras.json +++ b/assets/data/config/cameras.json @@ -4,18 +4,18 @@ "min": 5000, "max": 7000 }, + "lightHitbox": { + "x": 100, + "y": 200, + "width": 400, + "height": 350 + }, "sprites": [ - { "type": "BORDER", "x": 0, "y": 0, "zIndex": 0 }, - - { "type": "MAP", "x": 550, "y": 310, "fromTop": true, "zIndex": 1 }, - + { "type": "BORDER", "group": "cameras", "key": "borderline", "frame": 0, "x": 0, "y": 0, "zIndex": 0 }, + { "type": "MAP", "group": "cameras", "key": "map", "frame": 0, "x": 550, "y": 310, "fromTop": true, "zIndex": 1 }, { "type": "LABEL", "x": 550, "y": 280, "fromTop": true, "zIndex": 2 }, - - { "type": "REC", "x": 40, "y": 40, "fromTop": true, "zIndex": 3 }, - - { "type": "REC", "x": 90, "y": 130, "fromTop": true, "zIndex": 3 }, - - { "type": "SIGNAL_INTERRUPTED", "x": 0, "y": 80, "fromTop": true, "centerX": true, "zIndex": 10 } + { "type": "REC", "group": "cameras", "key": "recordSprite", "frame": 0, "x": 40, "y": 40, "fromTop": true, "zIndex": 3 }, + { "type": "SIGNAL_INTERRUPTED", "group": "cameras", "key": "signalInterrupted", "frame": 0, "x": 0, "y": 80, "fromTop": true, "centerX": true, "zIndex": 10 } ], "cameras": [ { @@ -24,7 +24,12 @@ "labelPathId": 0, "buttonX": 595, "buttonY": 496, - "wide": false + "wide": false, + "variants": [ + { "animatronics": ["toy_chica"], "indexOff": 0, "indexOn": 3 }, + { "animatronics": ["withered_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 2, @@ -32,7 +37,12 @@ "labelPathId": 1, "buttonX": 710, "buttonY": 496, - "wide": false + "wide": false, + "variants": [ + { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": ["withered_chica"], "indexOff": 3, "indexOn": 4 }, + { "animatronics": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 3, @@ -40,7 +50,12 @@ "labelPathId": 2, "buttonX": 595, "buttonY": 431, - "wide": false + "wide": false, + "variants": [ + { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": ["withered_freddy"], "indexOff": 3, "indexOn": 4 }, + { "animatronics": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 4, @@ -48,7 +63,13 @@ "labelPathId": 3, "buttonX": 710, "buttonY": 431, - "wide": false + "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": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 5, @@ -56,7 +77,14 @@ "labelPathId": 4, "buttonX": 585, "buttonY": 595, - "wide": false + "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": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 6, @@ -64,7 +92,13 @@ "labelPathId": 5, "buttonX": 695, "buttonY": 595, - "wide": false + "wide": false, + "variants": [ + { "animatronics": ["toy_bonnie"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": ["withered_chica"], "indexOff": 0, "indexOn": 3 }, + { "animatronics": ["mangle"], "indexOff": 0, "indexOn": 4 }, + { "animatronics": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 7, @@ -72,7 +106,13 @@ "labelPathId": 6, "buttonX": 734, "buttonY": 367, - "wide": true + "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": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 8, @@ -80,7 +120,16 @@ "labelPathId": 7, "buttonX": 575, "buttonY": 356, - "wide": true + "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": [], "indexOff": 0, "indexOn": 5 } + ] }, { "id": 9, @@ -88,7 +137,13 @@ "labelPathId": 8, "buttonX": 895, "buttonY": 331, - "wide": true + "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": [], "indexOff": 6, "indexOn": -1 } + ] }, { "id": 10, @@ -96,7 +151,13 @@ "labelPathId": 9, "buttonX": 820, "buttonY": 455, - "wide": true + "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": [], "indexOff": 2, "indexOn": 3 } + ] }, { "id": 11, @@ -104,7 +165,15 @@ "labelPathId": 10, "buttonX": 929, "buttonY": 405, - "wide": true + "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": [], "indexOff": 0, "indexOn": 1 } + ] }, { "id": 12, @@ -112,15 +181,11 @@ "labelPathId": 11, "buttonX": 920, "buttonY": 503, - "wide": true - }, - { - "id": 13, - "name": "ShowStage", - "labelPathId": 1, - "buttonX": 120, - "buttonY": 503, - "wide": true + "wide": true, + "variants": [ + { "animatronics": ["mangle"], "indexOff": 0, "indexOn": 2 }, + { "animatronics": [], "indexOff": 0, "indexOn": 1 } + ] } ] } diff --git a/assets/data/sprites/minigames.json b/assets/data/sprites/minigames.json index 9bfd0af..a537d38 100644 --- a/assets/data/sprites/minigames.json +++ b/assets/data/sprites/minigames.json @@ -30,7 +30,7 @@ "endoAnim": { "base": "sprites/minigames/SAVE THEM/", "start": 25, "end": 26 } }, "foxyGoGo": { - "courtain": "sprites/minigames/Go! Go! Go!/4.png", + "curtain": "sprites/minigames/Go! Go! Go!/4.png", "sadChild": "sprites/minigames/Go! Go! Go!/20.png", "happyChild": "sprites/minigames/Go! Go! Go!/21.png", "arrow": "sprites/minigames/Go! Go! Go!/22.png", diff --git a/assets/data/sprites/office.json b/assets/data/sprites/office.json index 0c325d0..cdf29e6 100644 --- a/assets/data/sprites/office.json +++ b/assets/data/sprites/office.json @@ -15,7 +15,7 @@ "balloonGirl": "sprites/office/inside/8.png", "dwarf": "sprites/office/inside/DWARF.png", "plastic": "sprites/office/inside/10.png", - "bunny": "sprites/office/inside/3.png", + "bonnie": "sprites/office/inside/3.png", "goldenFreddy": "sprites/office/inside/6.png", "mangle": "sprites/office/inside/7.png", "balloonBoy": "sprites/office/inside/5.png" diff --git a/core/src/main/java/io/github/eldek0/asset/GameAssetManager.java b/core/src/main/java/io/github/eldek0/asset/GameAssetManager.java index df389cf..0a6ae4f 100644 --- a/core/src/main/java/io/github/eldek0/asset/GameAssetManager.java +++ b/core/src/main/java/io/github/eldek0/asset/GameAssetManager.java @@ -3,10 +3,14 @@ package io.github.eldek0.asset; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.Json; import io.github.eldek0.asset.group.*; +import java.util.LinkedHashMap; +import java.util.Map; + public class GameAssetManager { private static final String DATA = "data/sprites/"; @@ -40,6 +44,8 @@ public class GameAssetManager { private MinigameAssets.Data minigameData; private MenuAssets.Data menuData; + private Map> groups; + // ========================================================= // LOAD ENTRY POINTS // ========================================================= @@ -90,6 +96,40 @@ public class GameAssetManager { minigames = new MinigameAssets(); minigames.queue(manager, minigameData); } + private void initGroups() { + groups = new LinkedHashMap<>(); + groups.put("office", office); + groups.put("monitor", monitor); + groups.put("mask", mask); + groups.put("cameras", cameras); + groups.put("battery", battery); + groups.put("numbers", numbers); + groups.put("customNight", customNight); + groups.put("jumpscares", jumpscares); + groups.put("cutscenes", cutscenes); + groups.put("minigames", minigames); + groups.put("menu", menu); + } + + /** + * Returns a texture by passing a group a key and a frame + * **/ + public Texture resolve(String group, String key, int frame) { + if (group.equals("null")){return null;} + AssetBundle bundle = groups.get(group); + if (bundle == null) throw new IllegalArgumentException( + "Unknown asset group: '" + group + "'. Valid groups: " + groups.keySet() + ); + return bundle.resolve(key, frame); + } + + /** + * Returns its first texture by passing a group and a key + */ + public Texture resolve(String group, String key) { + return resolve(group, key, 0); + } + // ========================================================= // GAME LOOP — call in render() // ========================================================= @@ -113,7 +153,7 @@ public class GameAssetManager { private void fetchAll() { if (fetched) return; fetched = true; - + this.initGroups(); if (menuData != null) menu.fetch(manager, menuData); if (monitorData != null) monitor.fetch(manager, monitorData); if (officeData != null) office.fetch(manager, officeData); diff --git a/core/src/main/java/io/github/eldek0/asset/group/AssetBundle.java b/core/src/main/java/io/github/eldek0/asset/group/AssetBundle.java index 1a0041b..2db4bb8 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/AssetBundle.java +++ b/core/src/main/java/io/github/eldek0/asset/group/AssetBundle.java @@ -1,6 +1,7 @@ package io.github.eldek0.asset.group; import com.badlogic.gdx.assets.AssetManager; +import com.badlogic.gdx.graphics.Texture; /** * Common contract for all typed asset groups. @@ -41,4 +42,9 @@ public interface AssetBundle { * Useful for fine-grained loading checks. */ boolean isLoaded(AssetManager manager, D data); + + /** + * Use a texture called from a json (string) + * **/ + Texture resolve(String key, int frame); } diff --git a/core/src/main/java/io/github/eldek0/asset/group/BatteryAssets.java b/core/src/main/java/io/github/eldek0/asset/group/BatteryAssets.java index 99cc6a1..7ab7ffa 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/BatteryAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/BatteryAssets.java @@ -4,6 +4,9 @@ import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.Texture; import io.github.eldek0.config.FrameRange; +import java.util.LinkedHashMap; +import java.util.Map; + public class BatteryAssets extends AssetBase implements AssetBundle { public BatteryAssets(){ @@ -45,4 +48,15 @@ public class BatteryAssets extends AssetBase implements AssetBundle flashlightLabel; + case "stages" -> stages[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: [flashlightLabel, stages]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/CameraAssets.java b/core/src/main/java/io/github/eldek0/asset/group/CameraAssets.java index 4cc08a0..2be15ab 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/CameraAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/CameraAssets.java @@ -160,6 +160,56 @@ public class CameraAssets extends AssetBase implements AssetBundle map; + case "borderline" -> borderline; + case "recordSprite" -> recordSprite; + case "signalInterrupted" -> signalInterrupted; + + // Labels + case "roomButtonUnselected" -> roomButtonUnselected; + case "roomButtonSelected" -> roomButtonSelected; + case "clicknhold" -> clicknhold; + case "musicBoxButtonOff" -> musicBoxButtonOff; + case "musicBoxButtonOn" -> musicBoxButtonOn; + case "musicBoxLabel" -> musicBoxLabel; + case "roomLabels" -> roomLabels[frame]; + + // Ranges + case "mangle" -> mangle[frame]; + case "staticA" -> staticA[frame]; + case "staticB" -> staticB[frame]; + case "staticStripes" -> staticStripes[frame]; + case "musicBoxTimer" -> musicBoxTimer[frame]; + + default -> { + // Dinamic locations: key = location name + if (locationFrames.containsKey(key)) + yield locationFrames.get(key)[frame]; + + // Location label: key = "label:PartyRoom1" for example + if (key.startsWith("label:")) { + String locName = key.substring(6); + Texture label = locationLabels.get(locName); + if (label != null) yield label; + } + + throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[map, borderline, recordSprite, signalInterrupted, " + + "roomButtonUnselected, roomButtonSelected, clicknhold, " + + "musicBoxButtonOff, musicBoxButtonOn, musicBoxLabel, roomLabels, " + + "mangle, staticA, staticB, staticStripes, musicBoxTimer] " + + "or a location name from: " + locationFrames.keySet() + + " (prefix with 'label:' for its label texture)" + ); + } + }; + } + public Texture[] getLocationFrames(String name) { return locationFrames.get(name); } public Texture getLocationLabel(String name) { return locationLabels.get(name); } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/CustomNightAssets.java b/core/src/main/java/io/github/eldek0/asset/group/CustomNightAssets.java index bfdc4b8..26abdf9 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/CustomNightAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/CustomNightAssets.java @@ -84,5 +84,26 @@ public class CustomNightAssets extends AssetBase implements AssetBundle title; + case "arrowRight" -> arrowRight; + case "arrowLeft" -> arrowLeft; + case "readyButton" -> readyButton; + case "arrowRight2" -> arrowRight2; + case "arrowLeft2" -> arrowLeft2; + case "levelInfo" -> levelInfo; + case "icons" -> icons[frame]; + case "names" -> names[frame]; + case "modes" -> modes[frame]; + case "rewards" -> rewards[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[title, arrowRight, arrowLeft, readyButton, arrowRight2, arrowLeft2, levelInfo, icons, names, modes, rewards]" + ); + }; + } + } diff --git a/core/src/main/java/io/github/eldek0/asset/group/CutsceneAssets.java b/core/src/main/java/io/github/eldek0/asset/group/CutsceneAssets.java index ed18220..5f7f41d 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/CutsceneAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/CutsceneAssets.java @@ -65,4 +65,23 @@ public class CutsceneAssets extends AssetBase implements AssetBundle freddy; + case "puppet" -> puppet; + case "background" -> background; + case "black" -> black; + case "mask" -> mask; + case "errImg" -> errImg; + case "itsMe" -> itsMe; + case "chica" -> chica[frame]; + case "bonnie" -> bonnie[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[freddy, puppet, background, black, mask, errImg, itsMe, chica, bonnie]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/JumpscareAssets.java b/core/src/main/java/io/github/eldek0/asset/group/JumpscareAssets.java index 6e76739..1a8a533 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/JumpscareAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/JumpscareAssets.java @@ -71,4 +71,24 @@ public class JumpscareAssets extends AssetBase implements AssetBundle puppet[frame]; + case "toyBonnie" -> toyBonnie[frame]; + case "toyChica" -> toyChica[frame]; + case "toyFreddy" -> toyFreddy[frame]; + case "witheredFreddy" -> witheredFreddy[frame]; + case "witheredBonnie" -> witheredBonnie[frame]; + case "witheredChica" -> witheredChica[frame]; + case "foxy" -> foxy[frame]; + case "mangle" -> mangle[frame]; + case "goldenFreddy" -> goldenFreddy[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[puppet, toyBonnie, toyChica, toyFreddy, witheredFreddy, witheredBonnie, witheredChica, foxy, mangle, goldenFreddy]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/MaskAssets.java b/core/src/main/java/io/github/eldek0/asset/group/MaskAssets.java index 58b6fcc..11db41e 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/MaskAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/MaskAssets.java @@ -41,4 +41,15 @@ public class MaskAssets extends AssetBase implements AssetBundle button; + case "sprites" -> sprites[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: [button, sprites]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/MenuAssets.java b/core/src/main/java/io/github/eldek0/asset/group/MenuAssets.java index 551a133..6a84eba 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/MenuAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/MenuAssets.java @@ -187,4 +187,62 @@ public class MenuAssets extends AssetBase implements AssetBundle title; + case "scottCredits" -> scottCredits; + case "selScottCredits" -> selScottCredits; + case "optionSelected" -> optionSelected; + case "newGame" -> newGame; + case "continueGame" -> continueGame; + case "deleteData" -> deleteData; + case "version" -> version; + case "nightLabel2" -> nightLabel2; + case "escToReturn" -> escToReturn; + case "extras" -> extras; + case "animatronics" -> animatronics; + case "jumpscares" -> jumpscares; + case "minigames" -> minigames; + case "selSquare" -> selSquare; + case "realTimeButton" -> realTimeButton; + case "loadingIcon" -> loadingIcon; + + // Nights + case "nightSixOption" -> nightSixOption; + case "customNightOption" -> customNightOption; + case "lostScreen" -> lostScreen; + case "gameOver" -> gameOver; + case "realTimeNight" -> realTimeNight; + case "night12am" -> night12am[frame]; + + // Paychecks + case "newspaper" -> newspaper; + case "nightFivePaycheck" -> nightFivePaycheck; + case "nightSixPaycheck" -> nightSixPaycheck; + case "nightSevenPaycheck" -> nightSevenPaycheck; + + // Misc + case "star" -> star; + case "blueStar" -> blueStar; + case "background" -> background[frame]; + + // Confetti + case "confettiBlue" -> confettiBlue[frame]; + case "confettiGreen" -> confettiGreen[frame]; + case "confettiYellow" -> confettiYellow[frame]; + case "confettiPink" -> confettiPink[frame]; + + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[title, scottCredits, selScottCredits, optionSelected, newGame, continueGame, deleteData, " + + "version, nightLabel2, escToReturn, extras, animatronics, jumpscares, minigames, selSquare, " + + "realTimeButton, loadingIcon, nightSixOption, customNightOption, lostScreen, gameOver, " + + "realTimeNight, night12am, newspaper, nightFivePaycheck, nightSixPaycheck, nightSevenPaycheck, " + + "star, blueStar, background, confettiBlue, confettiGreen, confettiYellow, confettiPink]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/MinigameAssets.java b/core/src/main/java/io/github/eldek0/asset/group/MinigameAssets.java index 92b0cec..b32d0f8 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/MinigameAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/MinigameAssets.java @@ -23,7 +23,7 @@ public class MinigameAssets extends AssetBase implements AssetBundle puppet; + case "soul" -> soul; + case "gift" -> gift; + case "giveGifts" -> giveGifts; + case "giveLife" -> giveLife; + case "chicaMask" -> chicaMask; + case "fredMask" -> fredMask; + case "bonnieMask" -> bonnieMask; + case "foxyMask" -> foxyMask; + + // Save Them + case "table" -> table; + case "desk" -> desk; + case "scenery" -> scenery; + case "dust" -> dust; + case "floor1" -> floor1; + case "floor2" -> floor2; + case "wasd" -> wasd; + case "suit1" -> suit1; + case "suit2" -> suit2; + case "suit3" -> suit3; + case "suitGr1" -> suitGr1; + case "suitGr2" -> suitGr2; + case "sadSoul" -> sadSoul; + case "blood" -> blood; + case "bigGift" -> bigGift; + case "freddyWalking" -> freddyWalking[frame]; + case "endoAnim" -> endoAnim[frame]; + + // Foxy Go Go Go + case "curtain" -> curtain; + case "sadChild" -> sadChild; + case "happyChild" -> happyChild; + case "arrow" -> arrow; + case "purpleGuy" -> purpleGuy; + case "getReady" -> getReady; + case "go" -> go; + case "hurray" -> hurray; + case "foxyAnim" -> foxyAnim[frame]; + case "confetti" -> confetti[frame]; + + // Take Cake to the Children + case "deadChild" -> deadChild; + case "car" -> car; + case "label" -> label; + case "cakeFreddy" -> cakeFreddy[frame]; + case "childCrying" -> childCrying[frame]; + case "child" -> child[frame]; + + // Misc + case "screenshots" -> screenshots[frame]; + case "rare" -> rare[frame]; + case "animatronics" -> animatronics[frame]; + + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[puppet, soul, gift, giveGifts, giveLife, chicaMask, fredMask, bonnieMask, foxyMask, " + + "table, desk, scenery, dust, floor1, floor2, wasd, suit1, suit2, suit3, suitGr1, suitGr2, sadSoul, blood, bigGift, freddyWalking, endoAnim, " + + "curtain, sadChild, happyChild, arrow, purpleGuy, getReady, go, hurray, foxyAnim, confetti, " + + "deadChild, car, label, cakeFreddy, childCrying, child, " + + "screenshots, rare, animatronics]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/MonitorAssets.java b/core/src/main/java/io/github/eldek0/asset/group/MonitorAssets.java index d69fa33..533970f 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/MonitorAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/MonitorAssets.java @@ -41,4 +41,15 @@ public class MonitorAssets extends AssetBase implements AssetBundle button; + case "sprites" -> sprites[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: [button, sprites]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/NumbersAssets.java b/core/src/main/java/io/github/eldek0/asset/group/NumbersAssets.java index 428ba7a..636e5a5 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/NumbersAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/NumbersAssets.java @@ -75,4 +75,25 @@ public class NumbersAssets extends AssetBase implements AssetBundle dots; + case "nightLabel" -> nightLabel; + case "amLabel" -> amLabel; + case "bigAm" -> bigAm; + case "medium" -> medium[frame]; + case "small" -> small[frame]; + case "big" -> big[frame]; + case "medium2" -> medium2[frame]; + case "small2" -> small2[frame]; + case "fiveAnimation" -> fiveAnimation[frame]; + case "sixAnimation" -> sixAnimation[frame]; + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[dots, nightLabel, amLabel, bigAm, medium, small, big, medium2, small2, fiveAnimation, sixAnimation]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/asset/group/OfficeAssets.java b/core/src/main/java/io/github/eldek0/asset/group/OfficeAssets.java index 9a30cde..a5bd840 100644 --- a/core/src/main/java/io/github/eldek0/asset/group/OfficeAssets.java +++ b/core/src/main/java/io/github/eldek0/asset/group/OfficeAssets.java @@ -18,7 +18,7 @@ public class OfficeAssets extends AssetBase implements AssetBundle bg; + case "telephoneMute"-> telephoneMute; + case "ctrlAdv" -> ctrlAdv; + + // Vent buttons + case "rightVentButtonOff" -> rightVentButtonOff; + case "rightVentButtonOn" -> rightVentButtonOn; + case "leftVentButtonOff" -> leftVentButtonOff; + case "leftVentButtonOn" -> leftVentButtonOn; + + // Easter eggs + case "balloonGirl" -> balloonGirl; + case "dwarf" -> dwarf; + case "plastic" -> plastic; + case "bonnie" -> bonnie; + case "goldenFreddy" -> goldenFreddy; + case "mangle" -> mangle; + case "balloonBoy" -> balloonBoy; + + // Ranges + case "inside" -> inside[frame]; + case "hallway" -> hallway[frame]; + case "rightVents" -> rightVents[frame]; + case "leftVents" -> leftVents[frame]; + case "desk" -> desk[frame]; + case "warnBig" -> warnBig[frame]; + case "warnSmall" -> warnSmall[frame]; + + default -> throw new IllegalArgumentException( + "Unknown key: '" + key + "'. Valid keys: " + + "[bg, telephoneMute, ctrlAdv, " + + "rightVentButtonOff, rightVentButtonOn, leftVentButtonOff, leftVentButtonOn, " + + "balloonGirl, dwarf, plastic, bonnie, goldenFreddy, mangle, balloonBoy, " + + "inside, hallway, rightVents, leftVents, desk, warnBig, warnSmall]" + ); + }; + } } diff --git a/core/src/main/java/io/github/eldek0/config/CameraConfig.java b/core/src/main/java/io/github/eldek0/config/CameraConfig.java index 0c0a9b5..ded1951 100644 --- a/core/src/main/java/io/github/eldek0/config/CameraConfig.java +++ b/core/src/main/java/io/github/eldek0/config/CameraConfig.java @@ -7,4 +7,5 @@ public class CameraConfig { public float buttonX; public float buttonY; public boolean wide; + public CameraVariant[] variants; } diff --git a/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java b/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java index 9c43f51..ff3d605 100644 --- a/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java +++ b/core/src/main/java/io/github/eldek0/config/CameraConfigFile.java @@ -3,6 +3,7 @@ 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 new file mode 100644 index 0000000..2deaa70 --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/CameraVariant.java @@ -0,0 +1,8 @@ +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/Rect.java b/core/src/main/java/io/github/eldek0/config/Rect.java new file mode 100644 index 0000000..0323d2c --- /dev/null +++ b/core/src/main/java/io/github/eldek0/config/Rect.java @@ -0,0 +1,5 @@ +package io.github.eldek0.config; + +public class Rect { + public float x, y, width, height; +} diff --git a/core/src/main/java/io/github/eldek0/config/SpriteConfig.java b/core/src/main/java/io/github/eldek0/config/SpriteConfig.java index 3c6231b..8f98f62 100644 --- a/core/src/main/java/io/github/eldek0/config/SpriteConfig.java +++ b/core/src/main/java/io/github/eldek0/config/SpriteConfig.java @@ -4,6 +4,11 @@ public record SpriteConfig>( T type, float x, float y, + + String group, + String key, + int frame, + boolean active, boolean fromTop, boolean centerX, diff --git a/core/src/main/java/io/github/eldek0/config/SpritePositionData.java b/core/src/main/java/io/github/eldek0/config/SpritePositionData.java index ecd23a3..4e2a29b 100644 --- a/core/src/main/java/io/github/eldek0/config/SpritePositionData.java +++ b/core/src/main/java/io/github/eldek0/config/SpritePositionData.java @@ -4,6 +4,10 @@ public class SpritePositionData { public String type; public int x, y; + public String group = "null"; + public String key = "null"; + public int frame = 0; + public boolean active = true; public boolean fromTop = false; public boolean centerX = false; 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 3f36dfd..fc81255 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 @@ -5,4 +5,10 @@ public class AnimatronicMovement { public int[] path; public int moveIntervalSeconds; public boolean aiSpeedMultiplier; + + private int pathIndex = 0; + + public int getPathIndex(){return pathIndex;} + + public void setPathIndex(int val){pathIndex = val;} } diff --git a/core/src/main/java/io/github/eldek0/config/animatronic/AttackType.java b/core/src/main/java/io/github/eldek0/config/animatronic/AttackType.java index b944956..d23de9f 100644 --- a/core/src/main/java/io/github/eldek0/config/animatronic/AttackType.java +++ b/core/src/main/java/io/github/eldek0/config/animatronic/AttackType.java @@ -4,8 +4,8 @@ public class AttackType { public AttackKind kind; // If attack kind is IN_OFFICE - public String officeSprite = null; - public String inOfficeAnimatronicSprite = null; + public String officeSprite = null; // Full office sprite + public String inOfficeAnimatronicSprite = null; // Animatronic sprite over office sprite // If attack kind is LIGHT public int lightLevel = 2; 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 fc947e3..4a8f435 100644 --- a/core/src/main/java/io/github/eldek0/game/Animatronic.java +++ b/core/src/main/java/io/github/eldek0/game/Animatronic.java @@ -5,13 +5,16 @@ import com.badlogic.gdx.utils.Json; import io.github.eldek0.config.animatronic.AnimatronicConfig; import io.github.eldek0.config.animatronic.AnimatronicManifest; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; public class Animatronic { private static final String MANIFEST = "data/config/animatronics.json"; private static final String CONFIG = "data/config/animatronics/"; + private float[] movementsTimer; private String[] availableAnimatronics; private HashMap data = new HashMap<>(); @@ -25,16 +28,57 @@ public class Animatronic { } private void loadConfig(){ + // Global config Json json = new Json(); String raw = Gdx.files.internal(MANIFEST).readString(); AnimatronicManifest manifest = json.fromJson(AnimatronicManifest.class, raw); availableAnimatronics = manifest.animatronics; + // Individual config String rawAnim; for (String animatronic : availableAnimatronics){ rawAnim = Gdx.files.internal(CONFIG + animatronic + ".json").readString(); data.put(animatronic, json.fromJson(AnimatronicConfig.class, rawAnim)); } + movementsTimer = new float[availableAnimatronics.length]; + } + + public void update(float delta){ + this.updateTimers(delta); + this.updateAnimatronics(); + } + + private void updateTimers(float delta){ + for (int i = 0; i < movementsTimer.length; i++) { + movementsTimer[i] += delta; + } + } + + private void updateAnimatronics(){ + List values = new ArrayList<>(data.values()); + int index; + for (int i = 0; i animatronic.movement.moveIntervalSeconds){ + index = animatronic.movement.getPathIndex() + 1; + if (index >= animatronic.movement.path.length){ + index = 0; + } + animatronic.movement.setPathIndex(index); + animatronic.inRoom = animatronic.movement.path[index]; + movementsTimer[i] = 0; + } + } + } + + public List getAnimatronicsInLocation(int location){ + List list = new ArrayList<>(); + for (AnimatronicConfig animatronic : data.values()){ + if (animatronic.inRoom == location){ + list.add(animatronic.id); + } + } + 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 b42af85..fcd66a9 100644 --- a/core/src/main/java/io/github/eldek0/game/Camera.java +++ b/core/src/main/java/io/github/eldek0/game/Camera.java @@ -29,6 +29,7 @@ public class Camera { private int inCameraRoom; private Rectangle[] buttonScreenRects; + private Rectangle lightHitbox; // Wide-camera panning private float[] camerasXPosition; @@ -46,6 +47,8 @@ public class Camera { private GameScene gameScene; + private boolean lightOn; + public Camera(GameScene gameScene) { this.gameScene = gameScene; @@ -57,6 +60,7 @@ public class Camera { timerWaitTimeMs[i] = wideRandomMov.min + (long) rng.nextInt((int) (wideRandomMov.max - wideRandomMov.min)); } + this.lightOn = false; this.initButtonScreenRects(); } @@ -87,6 +91,8 @@ public class Camera { } public void update(float delta) { + debugUpdateCamConfig(); + for (int i = 0; i < cameraConfigs.length; i++) { if (cameraConfigs[i].wide) { updateCameraTimer(i, delta); @@ -108,23 +114,50 @@ public class Camera { } public void onTouchDown() { - Vector2 position = App.convertPosToWorldPos(new Vector2(Gdx.input.getX(), Gdx.input.getY())); - for (int i = 0; i < this.cameraConfigs.length; i++) { + Vector2 position = App.convertPosToWorldPos( + new Vector2(Gdx.input.getX(), Gdx.input.getY()) + ); + + if (!Gdx.input.isButtonPressed(Input.Buttons.LEFT)) { + return; + } + + for (int i = 0; i < cameraConfigs.length; i++) { if (buttonScreenRects[i].contains(position)) { - if (Gdx.input.isButtonJustPressed(Input.Buttons.LEFT)) { - inCameraRoom = i + 1; - return; - } + inCameraRoom = cameraConfigs[i].id; + lightOn = false; + return; } } + + lightOn = lightHitbox.contains(position); } private void renderCurrentRoom(SpriteBatch batch) { int idx = inCameraRoom - 1; float xOff = camerasXPosition[idx]; + Texture frame; if (!occupiedCamera[idx]) { - Texture frame = getFrame(inCameraRoom, 0); + 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); + } + if (frame != null) { batch.draw(frame, xOff, 0); } @@ -138,6 +171,12 @@ public class Camera { this.inCameraRoom = configFile.inCameraId; this.cameraConfigs = configFile.cameras; this.wideRandomMov = configFile.wideRandomMov; + this.lightHitbox = new Rectangle( + configFile.lightHitbox.x, + configFile.lightHitbox.y, + configFile.lightHitbox.width, + configFile.lightHitbox.height + ); this.layout = new SpriteLayout<>( configFile.sprites, @@ -146,6 +185,21 @@ public class Camera { } + 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 config : layout.getSortedSprites()) { if (!config.active()) continue; - Texture texture = getTextureForSprite(config.type()); + Texture texture = assets.resolve(config.group(), config.key(), config.frame()); if (config.type() == CameraSpriteType.LABEL) { texture = getRoomLabel(inCameraRoom); } @@ -188,16 +242,6 @@ public class Camera { drawCameraButtons(batch); } - private Texture getTextureForSprite(CameraSpriteType type) { - return switch (type) { - case BORDER -> assets.cameras.borderline; - case MAP -> assets.cameras.map; - case REC -> assets.cameras.recordSprite; - case SIGNAL_INTERRUPTED -> assets.cameras.signalInterrupted; - case LABEL -> null; - }; - } - public void renderHitboxes(ShapeRenderer shapeRenderer) { shapeRenderer.setColor(1, 0, 0, 1); CameraConfig config; @@ -208,21 +252,29 @@ public class Camera { shapeRenderer.rect(rect.x, rect.y, rect.width, rect.height); + shapeRenderer.end(); + shapeRenderer.begin(ShapeRenderer.ShapeType.Filled); for (AnimatronicConfig animatronicConfig : gameScene.animatronic.getAnimatronicsData()) { - + shapeRenderer.setColor(Color.valueOf(animatronicConfig.color)); if (animatronicConfig.inRoom == config.id) { - shapeRenderer.end(); - shapeRenderer.begin(ShapeRenderer.ShapeType.Filled); - - shapeRenderer.setColor(Color.valueOf(animatronicConfig.color)); shapeRenderer.rect(rect.x, rect.y, 10, 30); + } - shapeRenderer.end(); - shapeRenderer.begin(ShapeRenderer.ShapeType.Line); - shapeRenderer.setColor(1, 0, 0, 1); + else if (animatronicConfig.inRoom == -2){ + shapeRenderer.rect(670, 300, 10, 30); + } + + else if (animatronicConfig.inRoom == -3){ + shapeRenderer.rect(670, 260, 10, 30); } } + shapeRenderer.end(); + shapeRenderer.begin(ShapeRenderer.ShapeType.Line); + shapeRenderer.setColor(1, 0, 0, 1); } + + // Light hitbox + shapeRenderer.rect(lightHitbox.x, lightHitbox.y, lightHitbox.width, lightHitbox.height); } private void drawCameraButtons(SpriteBatch batch) { 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 e27ed6a..f3ff886 100644 --- a/core/src/main/java/io/github/eldek0/screen/GameScene.java +++ b/core/src/main/java/io/github/eldek0/screen/GameScene.java @@ -62,6 +62,7 @@ public class GameScene implements Screen { hud.update(v); mask.update(v); camera.update(v); + animatronic.update(v); frameBuffer.begin(); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); diff --git a/core/src/main/java/io/github/eldek0/ui/SpriteLayout.java b/core/src/main/java/io/github/eldek0/ui/SpriteLayout.java index 2f08a0c..66b6f12 100644 --- a/core/src/main/java/io/github/eldek0/ui/SpriteLayout.java +++ b/core/src/main/java/io/github/eldek0/ui/SpriteLayout.java @@ -32,6 +32,9 @@ public class SpriteLayout> { enumType, raw.x, raw.y, + raw.group, + raw.key, + raw.frame, raw.active, raw.fromTop, raw.centerX, diff --git a/movement.txt b/movement.txt new file mode 100644 index 0000000..c5ef094 --- /dev/null +++ b/movement.txt @@ -0,0 +1,17 @@ +animatronics: + animatronics.json (manifests all the animatronics available) + night_control.json (gets all the nights info with the animatronics ai level per hour) + animatronic: + freddy (example): + - StartRoom + - RestRoom + - Movement + - AtackType (elect from these options) + - InOffice: (enters the office, like withered) + - Office sprite with animatronic or inOfficeAnimatronicSprite + - Light: (have to light em to make him quit) + - Level (will be affected by AI) + - MoveInOffice: (a sprite of the animatronic moves in the office, like toy bonnie) + - Speed + - Normal + - Jumpscare