#include "GameMap.h" #include "Asset/AssetManager.h" #include "EngineFrame/Scene/Scene.h" #include "EngineFrame/Component/Animation.h" #include "Actor/Map/GameMapCamera.h" #include "Actor/Object/CharacterObject.h" GameMap::GameMap() { _LayerMap["contact"] = new GameMapLayer(); _LayerMap["distantback"] = new GameMapLayer(); _LayerMap["middleback"] = new GameMapLayer(); _LayerMap["bottom"] = new GameMapLayer(); _LayerMap["closeback"] = new GameMapLayer(); _LayerMap["normal"] = new GameMapLayer(); _LayerMap["close"] = new GameMapLayer(); _LayerMap["cover"] = new GameMapLayer(); _LayerMap["max"] = new GameMapLayer(); // 设置图层渲染顺序 _LayerMap["contact"]->SetRenderZOrder(10000); _LayerMap["distantback"]->SetRenderZOrder(50000); _LayerMap["middleback"]->SetRenderZOrder(100000); _LayerMap["bottom"]->SetRenderZOrder(150000); _LayerMap["closeback"]->SetRenderZOrder(200000); _LayerMap["normal"]->SetRenderZOrder(250000); _LayerMap["close"]->SetRenderZOrder(300000); _LayerMap["cover"]->SetRenderZOrder(350000); _LayerMap["max"]->SetRenderZOrder(400000); } GameMap::~GameMap() { } void GameMap::InitConfiguration(std::string mapName) { ScriptData Data = AssetManager::GetInstance().GetScriptInfo(mapName); _MapInfo["wide_mode_camer_vertical_correction"] = 0; _MapInfo["background_pos"] = 0; _MapPath = mapName; _MapDir = mapName.substr(0, mapName.find_last_of("/") + 1); while (!Data.IsEnd()) { std::string Segment = Data.Get(); if (Segment == "[background pos]") { _MapInfo["background_pos"] = std::stoi(Data.Get()); } else if (Segment == "[map name]") { _MapInfo["name"] = Data.Get(); } else if (Segment == "[wide mode camera vertical correction]") { _MapInfo["wide_mode_camer_vertical_correction"] = std::stoi(Data.Get()); } else if (Segment == "[tile]") { std::vector tileArry; while (true) { auto tiledata = Data.Get(); if (tiledata == "[/tile]") break; tileArry.push_back(_MapDir + Tool_toLowerCase(tiledata)); } _MapInfo["tile"] = tileArry; } else if (Segment == "[extended tile]") { std::vector tileArry; while (true) { auto tiledata = Data.Get(); if (tiledata == "[/extended tile]") break; tileArry.push_back(_MapDir + Tool_toLowerCase(tiledata)); } _MapInfo["extended_tile"] = tileArry; } else if (Segment == "[far sight scroll]" || Segment == "[middle sight scroll]" || Segment == "[near sight scroll]") { _MapInfo[Segment.substr(1, Segment.length() - 2)] = std::stoi(Data.Get()); } else if (Segment == "[background animation]") { std::vector Arr; while (true) { std::string aniData = Data.Get(); if (aniData == "[/background animation]") break; if (aniData == "[ani info]") { BackGroundAni ani; Data.Get(); ani.filename = _MapDir + Tool_toLowerCase(Data.Get()); Data.Get(); ani.layer = Data.Get(); Data.Get(); ani.order = Data.Get(); Arr.push_back(ani); } } _MapInfo["background_animation"] = Arr; } else if (Segment == "[sound]") { std::vector soundArry; while (true) { std::string sounddata = Data.Get(); if (sounddata == "[/sound]") break; soundArry.push_back(sounddata); } _MapInfo["sound"] = soundArry; } else if (Segment == "[animation]") { std::vector aniArry; while (true) { std::string aniData = Data.Get(); if (aniData == "[/animation]") break; MapAni info; info.filename = Tool_RegRealPath(_MapDir + Tool_toLowerCase(aniData)); info.layer = Data.Get(); info.XPos = std::stoi(Data.Get()); info.YPos = std::stoi(Data.Get()); info.ZPos = std::stoi(Data.Get()); aniArry.push_back(info); } _MapInfo["animation"] = aniArry; } else if (Segment == "[NPC]") { std::vector npcArry; while (true) { std::string npcData = Data.Get(); if (npcData == "[/NPC]") break; MapNpc info; info.id = std::stoi(npcData); info.direction = Data.Get(); info.XPos = std::stoi(Data.Get()); info.YPos = std::stoi(Data.Get()); info.ZPos = std::stoi(Data.Get()); npcArry.push_back(info); } _MapInfo["NPC"] = npcArry; } else if (Segment == "[town movable area]") { std::vector town_movable_area; std::vector town_movable_area_info; while (true) { std::string areadata = Data.Get(); if (areadata == "[/town movable area]") break; town_movable_area.push_back(std::stoi(areadata)); town_movable_area.push_back(std::stoi(areadata)); town_movable_area.push_back(std::stoi(areadata)); town_movable_area.push_back(std::stoi(areadata)); MapMoveArea T; T.town = std::stoi(areadata); T.area = std::stoi(areadata); town_movable_area_info.push_back(T); } _MapInfo["town_movable_area"] = town_movable_area; _MapInfo["town_movable_area_info"] = town_movable_area_info; } else if (Segment == "[virtual movable area]") { std::vector virtual_movable_area; while (true) { std::string areadata = Data.Get(); if (areadata == "[/virtual movable area]") break; virtual_movable_area.push_back(std::stoi(areadata)); virtual_movable_area.push_back(std::stoi(Data.Get())); virtual_movable_area.push_back(std::stoi(Data.Get())); virtual_movable_area.push_back(std::stoi(Data.Get())); } _MapInfo["virtual_movable_area"] = virtual_movable_area; } } } void GameMap::InitTile() { if (!_MapInfo.count("tile")) return; int NormalTileCount = 0; std::vector tileArr = std::get>(_MapInfo["tile"]); if (tileArr.size() > 0) { NormalTileCount = tileArr.size(); _MapLength = NormalTileCount * 224; for (int i = 0; i < NormalTileCount; i++) { std::string path = tileArr[i]; RefPtr tile = new Tile(path); tile->SetPos(VecFPos{i * 224, -200 - std::get(_MapInfo["background_pos"])}); _LayerMap["bottom"]->AddComponent(tile); } _MapHeight = 560; } if (_MapInfo.count("extended_tile")) { std::vector extileArr = std::get>(_MapInfo["extended_tile"]); if (extileArr.size() > 0) { int ExTileCount = extileArr.size(); int Buffer = (ExTileCount / NormalTileCount); _MapHeight += (Buffer < 1 ? 1 : Buffer) * 40; for (int i = 0; i < ExTileCount; i++) { std::string path = extileArr[i]; RefPtr tile = new Tile(path); int xbuf = i % NormalTileCount * 224; int ybuf = 560 - 200 - std::get(_MapInfo["background_pos"]) + 40 * (i / NormalTileCount); tile->SetPos(VecFPos{xbuf, ybuf}); _LayerMap["bottom"]->AddComponent(tile); } } } } void GameMap::InitBackgroundAnimation() { float Rate = _MapInfo.count("far_sight_scroll") ? std::get(_MapInfo["far_sight_scroll"]) / 100.0f : 1.0f; (void)Rate; // TODO 摄像机 if (_MapInfo.count("background_animation")) { std::vector aniArr = std::get>(_MapInfo["background_animation"]); for (auto &ani : aniArr) { std::string path = ani.filename; std::vector> AniList; RefPtr AniObj = new Animation(path); int width = AniObj->GetSize().width; AniList.push_back(AniObj); for (int i = 0; i < (_MapLength * Rate) / width; i++) { RefPtr AniObj = new Animation(path); AniList.push_back(AniObj); } for (int i = 0; i < (int)AniList.size(); i++) { AniList[i]->SetPos(VecFPos{i * width, -120}); AniList[i]->SetRenderZOrder(-1000000); std::string layer = ani.layer; layer = layer.substr(1, layer.length() - 2); if (_LayerMap.count(layer)) { _LayerMap[layer]->AddChild(AniList[i]); } else { } } } } } void GameMap::InitMapAnimation() { if (_MapInfo.count("animation")) { std::vector aniArr = std::get>(_MapInfo["animation"]); for (auto &ani : aniArr) { std::string path = ani.filename; RefPtr AniObj = new Animation(path); AniObj->SetPos(VecFPos{ani.XPos, ani.YPos - ani.ZPos}); AniObj->SetRenderZOrder(ani.YPos); std::string layer = ani.layer; layer = layer.substr(1, layer.length() - 2); if (_LayerMap.count(layer)) { _LayerMap[layer]->AddChild(AniObj); } } } } void GameMap::InitVirtualMovableArea() { std::vector Info = std::get>(_MapInfo["virtual_movable_area"]); if (Info.size() > 0) { for (int i = 0; i < Info.size(); i += 4) { float x = Info[i]; float y = Info[i + 1]; float w = Info[i + 2]; float h = Info[i + 3]; if (_DebugMode) _LayerMap["max"]->AddDebugFeasibleAreaInfo(VecFPos(x, y), VecSize(w, h)); _MovableArea.push_back(SDL_FRect{x, y, w, h}); } } } void GameMap::LoadMap(std::string mapName) { // 读取脚本配置 InitConfiguration(mapName); // 初始化地板 InitTile(); // 初始化背景动画 InitBackgroundAnimation(); // 初始化场景Ani InitMapAnimation(); // 初始化可行区域 InitVirtualMovableArea(); } void GameMap::Enter(Scene *scene) { scene->AddChild(_LayerMap["contact"]); scene->AddChild(_LayerMap["distantback"]); scene->AddChild(_LayerMap["middleback"]); scene->AddChild(_LayerMap["bottom"]); scene->AddChild(_LayerMap["closeback"]); scene->AddChild(_LayerMap["normal"]); scene->AddChild(_LayerMap["close"]); scene->AddChild(_LayerMap["cover"]); scene->AddChild(_LayerMap["max"]); // TODO int HSU = 0; _LayerMap["contact"]->SetPos(VecFPos{0, HSU}); _LayerMap["distantback"]->SetPos(VecFPos{0, HSU}); _LayerMap["middleback"]->SetPos(VecFPos{0, HSU}); _LayerMap["bottom"]->SetPos(VecFPos{0, HSU}); _LayerMap["closeback"]->SetPos(VecFPos{0, HSU}); _LayerMap["normal"]->SetPos(VecFPos{0, HSU}); _LayerMap["close"]->SetPos(VecFPos{0, HSU}); _LayerMap["cover"]->SetPos(VecFPos{0, HSU}); _LayerMap["max"]->SetPos(VecFPos{0, HSU}); } void GameMap::HandleEvents(SDL_Event *e) { } void GameMap::Update(float deltaTime) { // this->_Camera->Update(deltaTime); // if (this->_Camera) // { // int CamearXpos = this->_Camera->X; // int CamearYpos = this->_Camera->Y; // int CamearZpos = this->_Camera->Z; // SDL_Log("Camera Pos: %d, %d", CamearXpos, CamearYpos); // // 遍历 // for (auto &pair : _LayerMap) // { // // pair.first 是 key(std::string) // std::string key = pair.first; // // pair.second 是 value(RefPtr) // RefPtr &value = pair.second; // if (key == "distantback") // { // value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)}); // } // else // { // value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)}); // } // } // } } void GameMap::AddObject(RefPtr object) { object->_AffMap = this; _LayerMap["normal"]->AddObject(object); } VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset) { // 初始化结果为原坐标(默认不移动) VecFPos3 result = CurPos; // 如果没有可移动区域限制,直接全量位移 if (_MovableArea.empty()) { result.x += PosOffset.x; result.y += PosOffset.y; result.z += PosOffset.z; // Z轴不受限 return result; } // 计算X轴单独位移后的目标位置 float targetX = CurPos.x + PosOffset.x; // 计算Y轴单独位移后的目标位置 float targetY = CurPos.y + PosOffset.y; // 检查X轴位移是否合法(固定Y为当前值,仅移动X) SDL_FPoint xTestPoint{targetX, CurPos.y}; bool isXValid = false; for (auto &area : _MovableArea) { if (SDL_PointInFRect(&xTestPoint, &area)) { isXValid = true; break; } } // 检查Y轴位移是否合法(固定X为当前值,仅移动Y) SDL_FPoint yTestPoint{CurPos.x, targetY}; bool isYValid = false; for (auto &area : _MovableArea) { if (SDL_PointInFRect(&yTestPoint, &area)) { isYValid = true; break; } } // 应用合法的位移 if (isXValid) { result.x = targetX; // X轴允许移动 } if (isYValid) { result.y = targetY; // Y轴允许移动 } // Z轴不受限制,直接应用位移 result.z += PosOffset.z; return result; }