diff --git a/Tiled地图解析思路.md b/Tiled地图解析思路.md index a660aca..19ce9e2 100644 --- a/Tiled地图解析思路.md +++ b/Tiled地图解析思路.md @@ -13,4 +13,7 @@ - 通过data数组中的gid查找所需信息(查找函数),填充瓦片vector - 创建包含 TileLayerComponent 的游戏对象(持有瓦片vector) - - 如果 type : objectgroup …… \ No newline at end of file + - 如果 type : objectgroup 载入对象层 + - 对象数据在"objects"字段中,每个对象都创建一个游戏对象 + - 关注的要点:gid查找源图片信息,layer数据中确认目标位置(TransformComponent)信息 + - 如果没有gid,则代表自己绘制的形状(可能是碰撞盒、触发器等,未来按需处理) \ No newline at end of file diff --git a/assets/maps/level1.tmj b/assets/maps/level1.tmj index b97900b..e56a5b9 100644 --- a/assets/maps/level1.tmj +++ b/assets/maps/level1.tmj @@ -296,6 +296,29 @@ "width":15, "x":304, "y":297 + }, + { + "height":29, + "id":17, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":29, + "x":19, + "y":25 + }, + { + "height":0, + "id":18, + "name":"", + "point":true, + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":87, + "y":43 }], "opacity":1, "type":"objectgroup", @@ -316,7 +339,7 @@ "y":0 }], "nextlayerid":7, - "nextobjectid":17, + "nextobjectid":19, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.11.2", diff --git a/src/engine/component/sprite_component.cpp b/src/engine/component/sprite_component.cpp index 05a6be5..54bc688 100644 --- a/src/engine/component/sprite_component.cpp +++ b/src/engine/component/sprite_component.cpp @@ -27,6 +27,17 @@ SpriteComponent::SpriteComponent( spdlog::trace("创建 SpriteComponent,纹理ID: {}", texture_id); } +SpriteComponent::SpriteComponent(engine::render::Sprite&& sprite, engine::resource::ResourceManager& resource_manager, engine::utils::Alignment alignment) + : resource_manager_(&resource_manager), sprite_(std::move(sprite)), alignment_(alignment) +{ + if (!resource_manager_) { + spdlog::critical("创建 SpriteComponent 时 ResourceManager 为空!,此组件将无效。"); + // 不要在游戏主循环中使用 try...catch / throw,会极大影响性能 + } + // offset_ 和 sprite_size_ 将在 init 中计算 + spdlog::trace("创建 SpriteComponent,纹理ID: {}", sprite_.getTextureId()); +} + void SpriteComponent::init() { if (!owner_) { spdlog::error("SpriteComponent 在初始化前未设置所有者。"); diff --git a/src/engine/component/sprite_component.h b/src/engine/component/sprite_component.h index 1b31b01..7ce011e 100644 --- a/src/engine/component/sprite_component.h +++ b/src/engine/component/sprite_component.h @@ -51,6 +51,19 @@ public: std::optional source_rect_opt = std::nullopt, bool is_flipped = false ); + + /** + * @brief 构造函数 + * @param sprite 精灵对象。 + * @param resource_manager 资源管理器指针。 + * @param alignment 初始对齐方式。 + */ + SpriteComponent( + engine::render::Sprite&& sprite, + engine::resource::ResourceManager& resource_manager, + engine::utils::Alignment alignment = engine::utils::Alignment::NONE + ); + ~SpriteComponent() override = default; // 禁止拷贝和移动 diff --git a/src/engine/scene/level_loader.cpp b/src/engine/scene/level_loader.cpp index c2fb9e4..7e01ca5 100644 --- a/src/engine/scene/level_loader.cpp +++ b/src/engine/scene/level_loader.cpp @@ -2,9 +2,11 @@ #include "../component/parallax_component.h" #include "../component/transform_component.h" #include "../component/tilelayer_component.h" +#include "../component/sprite_component.h" #include "../object/game_object.h" #include "../scene/scene.h" #include "../core/context.h" +#include "../resource/resource_manager.h" #include "../render/sprite.h" #include "../utils/math.h" #include @@ -137,11 +139,58 @@ void LevelLoader::loadTileLayer(const nlohmann::json& layer_json, Scene& scene) game_object->addComponent(tile_size_, map_size_, std::move(tiles)); // 添加到场景中 scene.addGameObject(std::move(game_object)); + spdlog::info("加载瓦片图层: '{}' 完成", layer_name); } -void LevelLoader::loadObjectLayer(const nlohmann::json&, Scene&) +void LevelLoader::loadObjectLayer(const nlohmann::json& layer_json, Scene& scene) { - // TODO + if (!layer_json.contains("objects") || !layer_json["objects"].is_array()) { + spdlog::error("对象图层 '{}' 缺少 'objects' 属性。", layer_json.value("name", "Unnamed")); + return; + } + // 获取对象数据 + const auto& objects = layer_json["objects"]; + // 遍历对象数据 + for (const auto& object : objects) { + // 获取对象gid + auto gid = object.value("gid", 0); + if (gid == 0) { // 如果gid为0 (即不存在),则代表自己绘制的形状(可能是碰撞盒、触发器等,未来按需处理) + // TODO + + } else { // 如果gid存在,则按照图片解析流程 + // --- 根据gid获取必要信息,每个gid对应一个游戏对象 --- + auto tile_info = getTileInfoByGid(gid); + if (tile_info.sprite.getTextureId().empty()) { + spdlog::error("gid为 {} 的瓦片没有图像纹理。", gid); + continue; + } + // 获取Transform相关信息 + auto position = glm::vec2(object.value("x", 0.0f), object.value("y", 0.0f)); + auto dst_size = glm::vec2(object.value("width", 0.0f), object.value("height", 0.0f)); + position = glm::vec2(position.x, position.y - dst_size.y); // 实际position需要进行调整(左下角到左上角) + + auto rotation = object.value("rotation", 0.0f); + auto src_size_opt = tile_info.sprite.getSourceRect(); + if (!src_size_opt) { // 正常情况下,所有瓦片的Sprite都设置了源矩形,没有代表某处出错 + spdlog::error("gid为 {} 的瓦片没有源矩形。", gid); + continue; + } + auto src_size = glm::vec2(src_size_opt->w, src_size_opt->h); // 成员变量除了 value().w 外,也可以这样获取 + auto scale = dst_size / src_size; + + // 获取对象名称 + const std::string& object_name = object.value("name", "Unnamed"); + + // 创建游戏对象并添加组件 + auto game_object = std::make_unique(object_name); + game_object->addComponent(position, scale, rotation); + game_object->addComponent(std::move(tile_info.sprite), scene.getContext().getResourceManager()); + + // 添加到场景中 + scene.addGameObject(std::move(game_object)); + spdlog::info("加载对象: '{}' 完成", object_name); + } + } } engine::component::TileInfo LevelLoader::getTileInfoByGid(int gid)