#include "GameMap.h" #include "Asset/AssetManager.h" #include "Asset/Asset_SoundPack.h" #include "EngineCore/Game.h" #include "EngineFrame/Scene/Scene.h" #include "EngineFrame/Component/Animation.h" #include "Global/Global_Game.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"]->SetZOrder(10000); _LayerMap["distantback"]->SetZOrder(50000); _LayerMap["middleback"]->SetZOrder(100000); _LayerMap["bottom"]->SetZOrder(150000); _LayerMap["closeback"]->SetZOrder(200000); _LayerMap["normal"]->SetZOrder(250000); _LayerMap["close"]->SetZOrder(300000); _LayerMap["cover"]->SetZOrder(350000); _LayerMap["max"]->SetZOrder(400000); AddChild(_LayerMap["contact"]); AddChild(_LayerMap["distantback"]); AddChild(_LayerMap["middleback"]); AddChild(_LayerMap["bottom"]); AddChild(_LayerMap["closeback"]); AddChild(_LayerMap["normal"]); AddChild(_LayerMap["close"]); AddChild(_LayerMap["cover"]); AddChild(_LayerMap["max"]); } 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]") { int Offset = std::stoi(Data.Get()); MapOffsetY = Offset; _MapInfo["background_pos"] = Offset; } else if (Segment == "[map name]") { _MapInfo["name"] = Data.Get(); } else if (Segment == "[limit map camera move]") { std::vector limit; limit.push_back(std::stoi(Data.Get())); limit.push_back(std::stoi(Data.Get())); limit.push_back(std::stoi(Data.Get())); limit.push_back(std::stoi(Data.Get())); _MapInfo["limit_map_camera_move"] = limit; } 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 = Tool_RegRealPath(_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::map soundArry; while (true) { std::string sounddata = Data.Get(); if (sounddata == "[/sound]") break; soundArry[sounddata] = true; } _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; int x1 = std::stoi(areadata); int y1 = std::stoi(Data.Get()); int x2 = std::stoi(Data.Get()); int y2 = std::stoi(Data.Get()); town_movable_area.push_back(x1); town_movable_area.push_back(y1); town_movable_area.push_back(x2); town_movable_area.push_back(y2); MapMoveArea T; T.town = std::stoi(Data.Get()); T.area = std::stoi(Data.Get()); 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; // 普通地板高度 int NormalTileHeight = 560; std::vector tileArr; std::vector extileArr; tileArr = std::get>(_MapInfo["tile"]); // 拓展地板不一定有 if (_MapInfo.count("extended_tile")) { extileArr = std::get>(_MapInfo["extended_tile"]); } _Tile = new Tile(this, tileArr, extileArr); _Tile->SetPosition(0, -200 - std::get(_MapInfo["background_pos"])); _LayerMap["bottom"]->AddChild(_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]->SetPosition(i * width, -120); AniList[i]->SetZOrder(-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->SetPosition(ani.XPos, ani.YPos - ani.ZPos); AniObj->SetZOrder(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(Vec2(x, y), VecSize(w, h), 0); _MovableArea.push_back(SDL_FRect{x, y, w, h}); } } } void GameMap::InitMoveArea() { std::vector Info = std::get>(_MapInfo["town_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(Vec2(x, y), VecSize(w, h), 1); _MoveArea.push_back(SDL_FRect{x, y, w, h}); } } } void GameMap::LoadMap(std::string mapName) { // 读取脚本配置 InitConfiguration(mapName); // 初始化地板 InitTile(); // 初始化背景动画 InitBackgroundAnimation(); // 初始化场景Ani InitMapAnimation(); // 初始化可行区域 InitVirtualMovableArea(); // 初始化传送区域 InitMoveArea(); } void GameMap::Enter() { auto &Audio = Asset_SoundPack::GetInstance(); // 获取背景音乐 auto bgmIt = _MapInfo.find("sound"); if (bgmIt != _MapInfo.end()) { std::map bgmlist = std::get>(_MapInfo["sound"]); // 获取正在播放的背景音乐 std::map curmap = Audio.GetBackgroudMusicVector(); for (auto &it : curmap) { std::string name = it.first; // 判断正在播放的背景音乐是否与当前地图背景音乐相同 if (!bgmlist.count(name)) { Audio.StopAudio(name); } } // 播放当前地图背景音乐 for (auto &it : bgmlist) { std::string name = it.first; if (!curmap.count(name)) Audio.PlayAudio(name); } } } void GameMap::OnUpdate(float deltaTime) { RefPtr Cam = Global_Game::GetInstance().GetCamera(); if (Cam == nullptr) return; float targetX = Cam->_currentPosition.x; float targetY = Cam->_currentPosition.y; // 屏幕中心 float width_Separate = 1280.0f / 1.2f / 2.0f; float height_Separate = 600.0f / 2.0f; // 获取摄像机可行区域限制 auto limitIt = _MapInfo.find("limit_map_camera_move"); if (limitIt != _MapInfo.end()) { std::vector limit = std::get>(_MapInfo["limit_map_camera_move"]); float X_Limit_Min = limit[0]; float X_Limit_Max = limit[1]; float Y_Limit_Min = limit[2]; float Y_Limit_Max = limit[3]; // 应用地图边界限制 targetX = std::clamp(targetX, width_Separate, (float)_MapLength - width_Separate); targetY = std::clamp(targetY, height_Separate, (float)_MapHeight - height_Separate); // 应用自定义摄像机移动限制 if (X_Limit_Min != -1) targetX = std::max(targetX, X_Limit_Min); if (X_Limit_Max != -1) targetX = std::min(targetX, X_Limit_Max); if (Y_Limit_Min != -1) targetY = std::max(targetY, Y_Limit_Min); if (Y_Limit_Max != -1) targetY = std::min(targetY, Y_Limit_Max); } // 更新图层位置 for (auto &Layer : _LayerMap) { float posX = -targetX + width_Separate; float posY = -targetY + height_Separate + MapOffsetY; if (Layer.first == "distantback") { posX *= BackgroundMoveSpeed; posX /= 100.0f; } Layer.second->SetPosition(posX, posY); } Actor::OnUpdate(deltaTime); } void GameMap::AddObject(RefPtr object) { object->_AffMap = this; _LayerMap["normal"]->AddObject(object); // 如果是角色对象 if (object->m_objecttype == ObjectType::CHARACTER) { CharacterObject *chr = (CharacterObject *)(object.Get()); Global_Game::GetInstance().GetCamera()->SetFromActor(chr); } } 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; } GameMap::MapMoveArea GameMap::CheckIsItMoveArea(VecFPos3 ChrPos) { MapMoveArea invalidArea; invalidArea.town = -2; invalidArea.area = -2; if (_MoveArea.size() && _MapInfo.count("town_movable_area_info")) { SDL_FPoint CurPos = {ChrPos.x, ChrPos.y}; for (int i = 0; i < _MoveArea.size(); i++) { if (SDL_PointInFRect(&CurPos, &_MoveArea[i])) { const std::vector &tma = std::get>(_MapInfo["town_movable_area_info"]); return tma[i]; } } } // 所有矩形都不命中,返回无效值 return invalidArea; } std::vector &GameMap::GetMoveAreaInfo() { return std::get>(_MapInfo["town_movable_area_info"]); } SDL_Rect GameMap::GetMovablePositionArea(int Index) { auto Vertex = std::get>(_MapInfo["town_movable_area"]); int FindIndex = Index * 4; SDL_Rect Buf = {Vertex[FindIndex], Vertex[FindIndex + 1], Vertex[FindIndex + 2], Vertex[FindIndex + 3]}; return Buf; }