完成关卡加载器-对象层

This commit is contained in:
Ziyu
2025-06-16 14:44:47 +08:00
parent b607b9e1db
commit 968cd46cda
5 changed files with 103 additions and 4 deletions
+4 -1
View File
@@ -13,4 +13,7 @@
- 通过data数组中的gid查找所需信息(查找函数),填充瓦片vector
- 创建包含 TileLayerComponent 的游戏对象(持有瓦片vector)
- 如果 type : objectgroup ……
- 如果 type : objectgroup 载入对象层
- 对象数据在"objects"字段中,每个对象都创建一个游戏对象
- 关注的要点:gid查找源图片信息,layer数据中确认目标位置(TransformComponent)信息
- 如果没有gid,则代表自己绘制的形状(可能是碰撞盒、触发器等,未来按需处理)
+24 -1
View File
@@ -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",
+11
View File
@@ -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 在初始化前未设置所有者。");
+13
View File
@@ -51,6 +51,19 @@ public:
std::optional<SDL_FRect> 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;
// 禁止拷贝和移动
+51 -2
View File
@@ -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 <nlohmann/json.hpp>
@@ -137,11 +139,58 @@ void LevelLoader::loadTileLayer(const nlohmann::json& layer_json, Scene& scene)
game_object->addComponent<engine::component::TileLayerComponent>(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<engine::object::GameObject>(object_name);
game_object->addComponent<engine::component::TransformComponent>(position, scale, rotation);
game_object->addComponent<engine::component::SpriteComponent>(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)