完成关卡切换-新地图

This commit is contained in:
Ziyu
2025-06-16 14:44:47 +08:00
parent cb10827fd6
commit e08b436e9a
7 changed files with 188 additions and 12 deletions
+12 -6
View File
@@ -126,7 +126,7 @@
"type":"", "type":"",
"visible":true, "visible":true,
"width":32, "width":32,
"x":113.174242424242, "x":1330.17424242424,
"y":156.628787878788 "y":156.628787878788
}, },
{ {
@@ -298,15 +298,21 @@
"y":297 "y":297
}, },
{ {
"height":29, "height":100.333333333333,
"id":17, "id":17,
"name":"", "name":"level2",
"properties":[
{
"name":"tag",
"type":"string",
"value":"next_level"
}],
"rotation":0, "rotation":0,
"type":"", "type":"",
"visible":true, "visible":true,
"width":29, "width":21,
"x":19, "x":1434,
"y":25 "y":59
}, },
{ {
"height":0, "height":0,
+115
View File
@@ -0,0 +1,115 @@
{ "compressionlevel":-1,
"height":25,
"infinite":false,
"layers":[
{
"id":2,
"image":"..\/textures\/Layers\/back.png",
"imageheight":240,
"imagewidth":384,
"name":"far",
"opacity":1,
"parallaxx":0.2,
"repeatx":true,
"type":"imagelayer",
"visible":true,
"x":0,
"y":0
},
{
"id":3,
"image":"..\/textures\/Layers\/middle.png",
"imageheight":368,
"imagewidth":176,
"name":"mid",
"offsetx":0,
"offsety":96,
"opacity":1,
"parallaxx":0.6,
"repeatx":true,
"type":"imagelayer",
"visible":true,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 253, 79, 79, 183, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 277, 278, 79, 79, 79, 79, 181, 79, 79, 79, 181, 181, 79, 79, 79, 79, 183, 79, 79, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 255, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 79, 79, 181, 79, 79, 79, 183, 79, 79, 79, 79, 181, 79, 79, 79, 280, 281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 253, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 255, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502,
502, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 277, 278, 339, 339, 339, 339, 335, 339, 337, 339, 339, 129, 129, 129, 280, 281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 502,
504, 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 377, 378, 472, 360, 472, 362, 472, 405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504, 505,
529, 530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 402, 403, 472, 385, 472, 472, 468, 430, 431, 406, 0, 0, 177, 177, 177, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 529, 530,
504, 505, 504, 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 427, 428, 472, 472, 472, 472, 472, 472, 430, 431, 0, 366, 368, 368, 368, 368, 370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504, 505,
529, 530, 529, 530, 502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, 453, 468, 472, 472, 472, 472, 472, 502, 456, 0, 0, 403, 472, 472, 405, 177, 177, 0, 179, 177, 177, 502, 502, 177, 179, 261, 0, 0, 0, 0, 261, 179, 0, 177, 0, 0, 0, 177, 177, 0, 502, 529, 530,
79, 79, 181, 79, 81, 0, 0, 0, 0, 0, 29, 29, 29, 29, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 29, 29, 502, 29, 29, 29, 29, 29, 29, 29, 31, 262, 262, 262, 262, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 504, 505, 502,
79, 181, 79, 79, 133, 134, 135, 0, 0, 86, 87, 79, 79, 79, 79, 183, 79, 79, 79, 79, 79, 79, 79, 183, 79, 79, 79, 181, 79, 79, 79, 79, 79, 79, 502, 79, 502, 79, 79, 79, 81, 0, 0, 0, 0, 77, 502, 79, 79, 79, 79, 79, 181, 79, 79, 529, 530, 502,
79, 79, 79, 81, 280, 0, 0, 0, 179, 0, 502, 502, 79, 79, 79, 79, 79, 79, 181, 79, 79, 79, 79, 79, 79, 79, 79, 183, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 133, 134, 135, 0, 0, 77, 79, 79, 79, 183, 79, 79, 183, 79, 79, 79, 79, 79,
79, 79, 79, 81, 177, 177, 0, 35, 36, 36, 37, 79, 79, 181, 181, 79, 79, 79, 79, 79, 502, 293, 333, 293, 502, 79, 79, 79, 79, 79, 79, 79, 181, 79, 79, 79, 79, 79, 79, 79, 81, 185, 0, 0, 179, 77, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
79, 79, 133, 134, 134, 134, 135, 0, 0, 187, 502, 79, 79, 79, 79, 79, 79, 183, 79, 79, 245, 472, 358, 472, 291, 339, 339, 339, 339, 339, 337, 335, 293, 293, 337, 293, 293, 293, 502, 79, 81, 0, 0, 35, 36, 37, 79, 79, 79, 79, 79, 181, 79, 79, 181, 79, 183, 79,
79, 79, 81, 0, 0, 0, 0, 0, 35, 36, 37, 79, 79, 79, 79, 79, 79, 79, 79, 79, 245, 472, 472, 472, 472, 472, 412, 472, 472, 472, 362, 360, 472, 472, 362, 472, 472, 472, 241, 79, 133, 134, 135, 0, 187, 77, 79, 181, 183, 79, 79, 181, 79, 79, 79, 79, 79, 183,
79, 79, 81, 185, 0, 0, 35, 36, 36, 36, 291, 333, 293, 293, 293, 293, 337, 293, 293, 293, 295, 472, 470, 472, 472, 472, 412, 472, 472, 472, 472, 385, 472, 472, 418, 419, 420, 472, 241, 79, 81, 0, 0, 0, 0, 77, 79, 79, 79, 79, 79, 79, 79, 79, 79, 181, 79, 79,
79, 79, 81, 109, 177, 0, 0, 0, 0, 0, 403, 358, 472, 412, 472, 472, 362, 472, 472, 412, 472, 472, 472, 472, 472, 472, 412, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 241, 79, 81, 179, 0, 35, 36, 37, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
183, 79, 502, 502, 134, 135, 0, 0, 0, 0, 403, 472, 472, 412, 472, 472, 472, 518, 472, 412, 472, 472, 472, 518, 472, 472, 412, 472, 472, 518, 472, 472, 472, 415, 416, 472, 518, 472, 291, 293, 133, 134, 135, 0, 0, 77, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 181, 79,
79, 79, 79, 502, 0, 0, 0, 0, 0, 0, 403, 472, 472, 412, 472, 472, 418, 419, 420, 412, 514, 515, 516, 472, 472, 472, 437, 472, 472, 472, 472, 472, 472, 440, 441, 472, 472, 472, 472, 405, 0, 0, 0, 0, 0, 77, 181, 79, 79, 183, 183, 79, 79, 79, 79, 79, 79, 79,
79, 79, 79, 79, 502, 0, 0, 0, 0, 0, 191, 193, 193, 193, 502, 193, 193, 193, 195, 412, 539, 540, 541, 472, 472, 461, 462, 463, 418, 419, 420, 504, 505, 465, 466, 472, 472, 472, 472, 430, 431, 179, 0, 35, 36, 37, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 181, 79,
183, 79, 79, 504, 505, 502, 179, 179, 179, 179, 241, 79, 502, 79, 79, 79, 79, 502, 502, 193, 193, 193, 193, 193, 193, 193, 193, 502, 193, 502, 193, 529, 530, 193, 193, 193, 502, 193, 193, 193, 193, 502, 502, 0, 179, 77, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
79, 79, 79, 529, 530, 502, 29, 29, 29, 29, 502, 79, 79, 79, 79, 79, 79, 79, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 183, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 181, 504, 505, 502, 502, 502, 502, 79, 79, 79, 79, 181, 79, 79, 79, 79, 79, 79,
79, 79, 183, 79, 79, 79, 79, 502, 79, 79, 79, 79, 79, 79, 181, 79, 79, 79, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 181, 2684354639, 529, 530, 504, 505, 502, 181, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2684354639, 181, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 181, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 2684354639, 183, 2684354639, 2684354639, 2684354639, 2684354639, 504, 505, 529, 530, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
"height":25,
"id":1,
"name":"main",
"offsetx":-0.5,
"offsety":0,
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":58,
"x":0,
"y":0
},
{
"draworder":"topdown",
"id":4,
"name":"object",
"objects":[
{
"gid":577,
"height":32,
"id":1,
"name":"player",
"rotation":0,
"type":"",
"visible":true,
"width":32,
"x":32,
"y":128
}],
"opacity":1,
"type":"objectgroup",
"visible":true,
"x":0,
"y":0
}],
"nextlayerid":5,
"nextobjectid":2,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.11.2",
"tileheight":16,
"tilesets":[
{
"firstgid":1,
"source":"tileset.tsj"
},
{
"firstgid":576,
"source":"actor.tsj"
}],
"tilewidth":16,
"type":"map",
"version":"1.10",
"width":58
}
+1 -1
View File
@@ -471,7 +471,7 @@
"id":261, "id":261,
"properties":[ "properties":[
{ {
"name":"solid", "name":"unisolid",
"type":"bool", "type":"bool",
"value":true "value":true
}] }]
+1 -1
View File
@@ -61,7 +61,7 @@ bool GameApp::init() {
if (!initSceneManager()) return false; if (!initSceneManager()) return false;
// 创建第一个场景并压入栈 // 创建第一个场景并压入栈
auto scene = std::make_unique<game::scene::GameScene>("GameScene", *context_, *scene_manager_); auto scene = std::make_unique<game::scene::GameScene>("level1", *context_, *scene_manager_);
scene_manager_->requestPushScene(std::move(scene)); scene_manager_->requestPushScene(std::move(scene));
is_running_ = true; is_running_ = true;
+37 -2
View File
@@ -160,9 +160,44 @@ void LevelLoader::loadObjectLayer(const nlohmann::json& layer_json, Scene& scene
for (const auto& object : objects) { for (const auto& object : objects) {
// 获取对象gid // 获取对象gid
auto gid = object.value("gid", 0); auto gid = object.value("gid", 0);
if (gid == 0) { // 如果gid为0 (即不存在),则代表自己绘制的形状(可能是碰撞盒、触发器等,未来按需处理) if (gid == 0) { // 如果gid为0 (即不存在),则代表自己绘制的形状
// TODO // 非矩形对象会有额外标识(目前不考虑)
if (object.value("point", false)) { // 如果是点对象
continue; // TODO: 点对象的处理方式
} else if (object.value("ellipse", false)) { // 如果是椭圆对象
continue; // TODO: 椭圆对象的处理方式
} else if (object.value("polygon", false)) { // 如果是多边形对象
continue; // TODO: 多边形对象的处理方式
}
// 没有这些标识则默认是矩形对象
else {
// --- 创建游戏对象并添加TransfromComponent ---
const std::string& object_name = object.value("name", "Unnamed");
auto game_object = std::make_unique<engine::object::GameObject>(object_name);
// 获取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));
auto rotation = object.value("rotation", 0.0f);
// 添加TransformComponent,缩放为设定为1.0f
game_object->addComponent<engine::component::TransformComponent>(position, glm::vec2(1.0f), rotation);
// --- 添加碰撞组件和物理组件 ---
// 碰撞盒大小与dst_size相同
auto collider = std::make_unique<engine::physics::AABBCollider>(dst_size);
auto* cc = game_object->addComponent<engine::component::ColliderComponent>(std::move(collider));
// 自定义形状通常是trigger类型,除非显示指定 (因此默认为真)
cc->setTrigger(object.value("trigger", true));
// 添加物理组件,不受重力影响
game_object->addComponent<engine::component::PhysicsComponent>(&scene.getContext().getPhysicsEngine(), false);
// 获取标签信息并设置
if (auto tag = getTileProperty<std::string>(object, "tag"); tag) { // 如果有标签
game_object->setTag(tag.value());
}
// 添加到场景
scene.addGameObject(std::move(game_object));
spdlog::info("加载对象: '{}' 完成 (类型: 自定义形状)", object_name);
}
} else { // 如果gid存在,则按照图片解析流程 } else { // 如果gid存在,则按照图片解析流程
// --- 根据gid获取必要信息,每个gid对应一个游戏对象 --- // --- 根据gid获取必要信息,每个gid对应一个游戏对象 ---
auto tile_info = getTileInfoByGid(gid); auto tile_info = getTileInfoByGid(gid);
+17 -2
View File
@@ -11,6 +11,7 @@
#include "../../engine/component/health_component.h" #include "../../engine/component/health_component.h"
#include "../../engine/physics/physics_engine.h" #include "../../engine/physics/physics_engine.h"
#include "../../engine/scene/level_loader.h" #include "../../engine/scene/level_loader.h"
#include "../../engine/scene/scene_manager.h"
#include "../../engine/input/input_manager.h" #include "../../engine/input/input_manager.h"
#include "../../engine/render/camera.h" #include "../../engine/render/camera.h"
#include "../../engine/render/animation.h" #include "../../engine/render/animation.h"
@@ -57,7 +58,7 @@ void GameScene::init() {
context_.getAudioPlayer().setMusicVolume(0.2f); // 设置背景音乐音量为20% context_.getAudioPlayer().setMusicVolume(0.2f); // 设置背景音乐音量为20%
context_.getAudioPlayer().setSoundVolume(0.5f); // 设置音效音量为50% context_.getAudioPlayer().setSoundVolume(0.5f); // 设置音效音量为50%
// 播放背景音乐 (循环,淡入1秒) // 播放背景音乐 (循环,淡入1秒)
context_.getAudioPlayer().playMusic("assets/audio/hurry_up_and_run.ogg", true, 1000); // context_.getAudioPlayer().playMusic("assets/audio/hurry_up_and_run.ogg", true, 1000);
Scene::init(); Scene::init();
spdlog::trace("GameScene 初始化完成。"); spdlog::trace("GameScene 初始化完成。");
@@ -85,7 +86,8 @@ bool GameScene::initLevel()
{ {
// 加载关卡(level_loader通常加载完成后即可销毁,因此不存为成员变量) // 加载关卡(level_loader通常加载完成后即可销毁,因此不存为成员变量)
engine::scene::LevelLoader level_loader; engine::scene::LevelLoader level_loader;
if (!level_loader.loadLevel("assets/maps/level1.tmj", *this)){ auto level_path = levelNameToPath(scene_name_);
if (!level_loader.loadLevel(level_path, *this)){
spdlog::error("关卡加载失败"); spdlog::error("关卡加载失败");
return false; return false;
} }
@@ -207,6 +209,12 @@ void GameScene::handleObjectCollisions()
obj2->getComponent<game::component::PlayerComponent>()->takeDamage(1); obj2->getComponent<game::component::PlayerComponent>()->takeDamage(1);
spdlog::debug("玩家 {} 受到了 HAZARD 对象伤害", obj2->getName()); spdlog::debug("玩家 {} 受到了 HAZARD 对象伤害", obj2->getName());
} }
// 处理玩家与关底触发器碰撞
else if (obj1->getName() == "player" && obj2->getTag() == "next_level") {
toNextLevel(obj2);
} else if (obj2->getName() == "player" && obj1->getTag() == "next_level") {
toNextLevel(obj1);
}
} }
} }
@@ -276,6 +284,13 @@ void GameScene::playerVSItemCollision(engine::object::GameObject * player, engin
context_.getAudioPlayer().playSound("assets/audio/poka01.mp3"); // 播放音效 context_.getAudioPlayer().playSound("assets/audio/poka01.mp3"); // 播放音效
} }
void GameScene::toNextLevel(engine::object::GameObject *trigger)
{
auto scene_name = trigger->getName();
auto next_scene = std::make_unique<game::scene::GameScene>(scene_name, context_, scene_manager_);
scene_manager_.requestReplaceScene(std::move(next_scene));
}
void GameScene::createEffect(const glm::vec2& center_pos, const std::string &tag) void GameScene::createEffect(const glm::vec2& center_pos, const std::string &tag)
{ {
// --- 创建游戏对象和变换组件 --- // --- 创建游戏对象和变换组件 ---
+5
View File
@@ -36,6 +36,11 @@ private:
void playerVSEnemyCollision(engine::object::GameObject* player, engine::object::GameObject* enemy); ///< @brief 玩家与敌人碰撞处理 void playerVSEnemyCollision(engine::object::GameObject* player, engine::object::GameObject* enemy); ///< @brief 玩家与敌人碰撞处理
void playerVSItemCollision(engine::object::GameObject* player, engine::object::GameObject* item); ///< @brief 玩家与道具碰撞处理 void playerVSItemCollision(engine::object::GameObject* player, engine::object::GameObject* item); ///< @brief 玩家与道具碰撞处理
void toNextLevel(engine::object::GameObject* trigger); ///< @brief 进入下一个关卡
/// @brief 根据关卡名称获取对应的地图文件路径
std::string levelNameToPath(const std::string& level_name) const { return "assets/maps/" + level_name + ".tmj"; }
/** /**
* @brief 创建一个特效对象(一次性)。 * @brief 创建一个特效对象(一次性)。
* @param center_pos 特效中心位置 * @param center_pos 特效中心位置