From 77cf19b2e0519ae3f01f9fdaea05ab7d9a4cb7fa Mon Sep 17 00:00:00 2001 From: jakubg1 Date: Wed, 28 Dec 2022 02:03:23 +0100 Subject: [PATCH] Config class stub The new `src/Configs` folder includes two classes which serve as an additional layer between raw data coming from JSON files and the game elements themselves. This layer is intended to be a simple yet efficient way to maintain game compatibility across different versions. You can read more about it in the following issue: Extract all JSON structures to their own classes #70 --- src/ConfigManager.lua | 25 +++++++++++++-- src/Configs/Shooter.lua | 54 +++++++++++++++++++++++++++++++++ src/Configs/ShooterMovement.lua | 41 +++++++++++++++++++++++++ src/Game.lua | 2 ++ src/Shooter.lua | 14 ++++----- 5 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 src/Configs/Shooter.lua create mode 100644 src/Configs/ShooterMovement.lua diff --git a/src/ConfigManager.lua b/src/ConfigManager.lua index 6acc6a7c..56a21c16 100644 --- a/src/ConfigManager.lua +++ b/src/ConfigManager.lua @@ -6,6 +6,8 @@ local ConfigManager = class:derive("ConfigManager") local CollectibleGeneratorManager = require("src/CollectibleGenerator/Manager") +local ShooterConfig = require("src/Configs/Shooter") + ---Constructs a new ConfigManager and initializes all lists. @@ -55,7 +57,6 @@ function ConfigManager:new() self.spheres = self:loadFolder("config/spheres", "sphere", true) self.sphereEffects = self:loadFolder("config/sphere_effects", "sphere effect") self.colorGenerators = self:loadFolder("config/color_generators", "color generator") - self.shooters = self:loadFolder("config/shooters", "shooter") self.collectibleGeneratorManager = CollectibleGeneratorManager() @@ -78,12 +79,20 @@ end +---Loads config files which are implemented the new way so that they require to be loaded after the resources. +function ConfigManager:loadStuffAfterResources() + self.shooters = self:loadFolder("config/shooters", "shooter", false, ShooterConfig) +end + + + ---Loads and returns multiple items from a folder. ---@param folderPath string The path to a folder where the files are stored. ---@param name string The name to be used when logging; also a file prefix if `isNumbers` is set to `true`. ---@param isNumbers boolean? If set to `true`, all IDs will be converted to numbers instead of being strings. +---@param constructor any? The config class constructor. If set, the returned table will contain instances of this class instead of raw data structures. ---@return table -function ConfigManager:loadFolder(folderPath, name, isNumbers) +function ConfigManager:loadFolder(folderPath, name, isNumbers, constructor) local t = {} local fileList = _GetDirListing(_ParsePath(folderPath), "file", "json") @@ -94,6 +103,9 @@ function ConfigManager:loadFolder(folderPath, name, isNumbers) end _Log:printt("ConfigManager", string.format("Loading %s %s, %s", name, id, path)) local item = _LoadJson(_ParsePath(folderPath .. "/" .. path)) + if constructor then + item = constructor(item) + end t[id] = item end @@ -102,6 +114,15 @@ end +---Returns a shooter config for a given shooter name. +---@param name string The name of the shooter. +---@return ShooterConfig +function ConfigManager:getShooter(name) + return self.shooters[name] +end + + + ---Returns the game name if specified, else the internal (folder) name. ---@return string function ConfigManager:getGameName() diff --git a/src/Configs/Shooter.lua b/src/Configs/Shooter.lua new file mode 100644 index 00000000..3f907c2b --- /dev/null +++ b/src/Configs/Shooter.lua @@ -0,0 +1,54 @@ +local class = require "com/class" + +---@class ShooterConfig +---@overload fun(data):ShooterConfig +local ShooterConfig = class:derive("ShooterConfig") + +local Vec2 = require("src/Essentials/Vector2") +local ShooterMovementConfig = require("src/Configs/ShooterMovement") + + + +---Constructs a new Shooter Config. +---@param data table Raw data parsed from `config/shooters/*.json`. +---@param path string Path to the file. The file is not loaded here, but is used in error messages. +function ShooterConfig:new(data, path) + self._path = path + + self.movement = ShooterMovementConfig(data.movement, path) + + self.sprite = _Game.resourceManager:getSprite(data.sprite) + self.shadowSprite = _Game.resourceManager:getSprite(data.shadowSprite) + + self.reticle = { + ---@type Sprite? + sprite = data.reticle.sprite and _Game.resourceManager:getSprite(data.reticle.sprite), + ---@type Sprite? + nextBallSprite = data.reticle.nextBallSprite and _Game.resourceManager:getSprite(data.reticle.nextBallSprite), + ---@type Vector2? + nextBallOffset = _ParseVec2(data.reticle.nextBallOffset), + ---@type Sprite? + radiusSprite = data.reticle.radiusSprite and _Game.resourceManager:getSprite(data.reticle.radiusSprite) + } + + self.speedShotBeam = { + sprite = _Game.resourceManager:getSprite(data.speedShotBeam.sprite), + ---@type number + fadeTime = data.speedShotBeam.fadeTime, + ---@type string + renderingType = data.speedShotBeam.renderingType, + ---@type boolean + colored = data.speedShotBeam.colored + } + + ---@type string + self.speedShotParticle = data.speedShotParticle + ---@type number + self.shootSpeed = data.shootSpeed + ---@type Vector2 + self.hitboxSize = _ParseVec2(data.hitboxSize) or Vec2() +end + + + +return ShooterConfig \ No newline at end of file diff --git a/src/Configs/ShooterMovement.lua b/src/Configs/ShooterMovement.lua new file mode 100644 index 00000000..2cf91984 --- /dev/null +++ b/src/Configs/ShooterMovement.lua @@ -0,0 +1,41 @@ +local class = require "com/class" + +---@class ShooterMovementConfig +---@overload fun(data):ShooterMovementConfig +local ShooterMovementConfig = class:derive("ShooterMovementConfig") + +-- Place your imports here + + + +---Constructs a new Shooter Movement Config. +---@param data table Raw shooter movement data, found in `config/levels/*.json` and `config/shooters/*.json`. +---@param path string Path to the file. The file is not loaded here, but is used in error messages. +function ShooterMovementConfig:new(data, path) + self._path = path + + ---@type string + self.type = data.type + + if self.type == "linear" then + ---@type number + self.xMin = data.xMin + ---@type number + self.xMax = data.xMax + ---@type number + self.y = data.y + ---@type number + self.angle = data.angle + elseif self.type == "circular" then + ---@type number + self.x = data.x + ---@type number + self.y = data.y + else + error(string.format("Failed to load file %s, unknown shooter type: %s (expected \"linear\" or \"circular\")", path, data.type)) + end +end + + + +return ShooterMovementConfig \ No newline at end of file diff --git a/src/Game.lua b/src/Game.lua index 6d570e88..a625bb99 100644 --- a/src/Game.lua +++ b/src/Game.lua @@ -92,6 +92,8 @@ end ---Initializes the game session, as well as UI and particle managers. function Game:initSession() + -- Load whatever needs loading the new way from config. + self.configManager:loadStuffAfterResources() -- Setup the UI and particles self.uiManager:init() self.particleManager = ParticleManager() diff --git a/src/Shooter.lua b/src/Shooter.lua index e62c47dc..33a5570b 100644 --- a/src/Shooter.lua +++ b/src/Shooter.lua @@ -16,7 +16,7 @@ local ShotSphere = require("src/ShotSphere") ---Constructs a new Shooter. ---@param data? table Data for the shooter. function Shooter:new(data) - self.config = _Game.configManager.shooters[data and data.name or "default"] + self.config = _Game.configManager:getShooter(data and data.name or "default") self.movement = self.config.movement if data and data.movement then self.movement = data.movement @@ -43,13 +43,13 @@ function Shooter:new(data) self.moveKeySpeed = 500 self.rotateKeySpeed = 4 - self.sprite = _Game.resourceManager:getSprite(self.config.sprite) - self.shadowSprite = _Game.resourceManager:getSprite(self.config.shadowSprite) - self.speedShotSprite = _Game.resourceManager:getSprite(self.config.speedShotBeam.sprite) + self.sprite = self.config.sprite + self.shadowSprite = self.config.shadowSprite + self.speedShotSprite = self.config.speedShotBeam.sprite - self.reticleSprite = self.config.reticle.sprite and _Game.resourceManager:getSprite(self.config.reticle.sprite) - self.reticleNextSprite = self.config.reticle.nextBallSprite and _Game.resourceManager:getSprite(self.config.reticle.nextBallSprite) - self.radiusReticleSprite = self.config.reticle.radiusSprite and _Game.resourceManager:getSprite(self.config.reticle.radiusSprite) + self.reticleSprite = self.config.reticle.sprite + self.reticleNextSprite = self.config.reticle.nextBallSprite + self.radiusReticleSprite = self.config.reticle.radiusSprite self.sphereEntity = nil end