Files
DNF_DEV/source_game/Actor/Map/GameMap.cpp

462 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "GameMap.h"
#include "Asset/AssetManager.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"]->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]")
{
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<int> 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<std::string> 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<std::string> 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<BackGroundAni> 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<std::string> 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<MapAni> 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<MapNpc> 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<int> town_movable_area;
std::vector<MapMoveArea> 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<int> 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<std::string> tileArr = std::get<std::vector<std::string>>(_MapInfo["tile"]);
if (tileArr.size() > 0)
{
NormalTileCount = tileArr.size();
_MapLength = NormalTileCount * 224;
_MapHeight = 560;
}
if (!_MapInfo.count("extended_tile"))
return;
std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
if (extileArr.size() > 0)
{
int ExTileCount = extileArr.size();
int Buffer = (ExTileCount / NormalTileCount);
_MapHeight += (Buffer < 1 ? 1 : Buffer) * 40;
}
_Tile = new Tile(this, tileArr, extileArr);
_LayerMap["bottom"]->AddChild(_Tile);
}
void GameMap::InitBackgroundAnimation()
{
float Rate = _MapInfo.count("far_sight_scroll") ? std::get<int>(_MapInfo["far_sight_scroll"]) / 100.0f : 1.0f;
(void)Rate;
// TODO 摄像机
if (_MapInfo.count("background_animation"))
{
std::vector<BackGroundAni> aniArr = std::get<std::vector<BackGroundAni>>(_MapInfo["background_animation"]);
for (auto &ani : aniArr)
{
std::string path = ani.filename;
std::vector<RefPtr<Animation>> AniList;
RefPtr<Animation> AniObj = new Animation(path);
int width = AniObj->GetSize().width;
AniList.push_back(AniObj);
for (int i = 0; i < (_MapLength * Rate) / width; i++)
{
RefPtr<Animation> AniObj = new Animation(path);
AniList.push_back(AniObj);
}
for (int i = 0; i < (int)AniList.size(); i++)
{
AniList[i]->SetPos(Vec2{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<MapAni> aniArr = std::get<std::vector<MapAni>>(_MapInfo["animation"]);
for (auto &ani : aniArr)
{
std::string path = ani.filename;
RefPtr<Animation> AniObj = new Animation(path);
AniObj->SetPos(Vec2{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<int> Info = std::get<std::vector<int>>(_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));
_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)
{
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"]);
}
void GameMap::Update(float deltaTime)
{
Actor::Update(deltaTime);
RefPtr<GameCamera> 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<int> limit = std::get<std::vector<int>>(_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->SetPos(Vec2(posX, posY));
}
}
void GameMap::AddObject(RefPtr<BaseObject> 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);
if (chr->_Shadow)
_LayerMap["bottom"]->AddChild(chr->_Shadow);
}
}
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;
}