#pragma once #include #include #include #include #include #include #include const float REDACTED_EDITOR_LIB_VERSION = 1; /// @class Level /// @brief Represents the complete game level, containing its metadata, tile layers, and entites. /// /// This class serves as the primary data structure for loading, managing, and saving /// all components that constitute the playable game map. It centralizes information /// about the level's dimensions, graphical assets (tilesets), stuctural layers, /// and interactive objects (entities). class Level { public: /// The human-readable name of the level. /// This is typically displayed in level selection menus or editors. std::string name; /// A brief description of the level's content or purpose. /// Useful for level browsers or internal documentation. std::string description; /// The name or identifier of the author who created or last modified the level. std::string author; /// A collection of keywords or categories associated with the level. /// Can be used for filtering, searching, or thematic grouping (e.g., "forest", "puzzle"). std::vector tags; /// The height of the level grid in number of tiles (rows). // TODO: I mixed up rows and columns. I'm just going to leave it as the convention this system follows for now. -josh int rows; /// The width of the level grid in number of tiles (columns). int cols; /// A collection of pointers to the tile layers that compose the level's tile grid. /// Each layer typically represents a distinct plane of tiles (e.g., background, foreground, collisions). /// @warning The `Level` class is responsible for the ownership and lifecycle of these `Layer` objects /// if they are allocated dynamically. Consider using smart pointers like `std::unique_ptr /// for automatic memory management, std::vector layers; /// A collection of pointers to the entities placed within the level. /// Entities represent interactive objects, characters, spawn points, or other dynamic elements. /// @warning Similar to `layers`, the `Level` class is responsible for the ownership and lifecycle /// of these `Entity` objects if they are dynamically allocated. Consider `std::unique_ptr`. std::vector entities; /// The filesystem path to the primary tileset image or definition file used by this level. /// This path is typically relative to the level's main JSON file. std::string tileset_path; /// A generic JSON value for storing arbitrary, unstructured level metdata. /// This can include game-specific settings, editor-specific flags, or any data /// not explicitly covered by other `Level` members. json::value metadata; #pragma region Member Functions /// The default constructor initializes all member variables to their default or empty states. /// The level will have zero dimensions, no layers, no entities, and empty metadata. Level(); /// Destructor for the Level class. /// Responsible for deallocating all dynamically allocated `Layer` and `Entity` objects /// pointed to by the `layers` and `entities` vectors to prevent memory leaks. ~Level() = default; /// Constructs a Level object by loading and parsing a level definition file from the given path. /// This constructor typically reads a JSON file containing the level's metadata, and /// may also initiate the loading of associated binary tile data or other assets. NOTE: Currently, we do not. /// @param path /// @throws std::runtime_error If the file cannot be opened, is malformed, or if associated data (like binary layers) is missing / invalid. explicit Level(const std::filesystem::path& path); /// Constructs a Level object by deserializing its state from a pre-existing JSON value. /// This constructor assumes the JSON value is already loaded in memory and correct. /// It will parse the JSON to populate the level's members, including layers and entities. /// @param json /// @throws json::exception If the JSON structure is malformed. /// @see Deserialize() for the underlying parsing logic. explicit Level(const json::value& json); /// Deserializes the Level object's state from a provided JSON value. /// This method takes a JSON object (typically parsed from a file) and populates /// the current `Level` instance's member variables, including its layers and entities. /// This is the core parsing logic for loading level data into memory. /// @param json /// @throws json::exception If the JSON structure is malformed. void Deserialize(const json::value& json); /// Serializes the current Level object's state into a JSON value. /// This method converts all the level's metadata, layer properties, and entity data /// into a json object, ready for saving to a file or transmitting. /// @return a `json` value representing the complete level data. /// @see Level::Save() for writing the serialized JSON to a file. json::value Serialize() const; bool Load(const std::filesystem::path& path); bool Save(const std::filesystem::path& path); Layer* CreateLayer(const std::string& name); Layer* GetLayer(int index); const Layer* GetLayer(int index) const; Layer* FindLayer(const std::string& name); const Layer* FindLayer(const std::string& name) const; bool RemoveLayer(const std::string& name); bool RemoveLayer(int index); bool RemoveLayer(Layer* layer); bool RemoveAllLayers(); Entity* CreateEntity(const std::string& name); Entity* GetEntity(const std::string& name); const Entity* GetEntity(const std::string& name) const; bool RemoveEntity(Entity* entity); Tile GetTileData(int gid) const; Quad GetTileQuad(int gid) const; #pragma endregion protected: private: };