448 lines
15 KiB
C++
448 lines
15 KiB
C++
#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<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;
|
||
std::vector<std::string> tileArr = std::get<std::vector<std::string>>(_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> tile = new Tile(path);
|
||
tile->SetPos(VecFPos{i * 224, -200 - std::get<int>(_MapInfo["background_pos"])});
|
||
_LayerMap["bottom"]->AddComponent(tile);
|
||
}
|
||
_MapHeight = 560;
|
||
}
|
||
if (_MapInfo.count("extended_tile"))
|
||
{
|
||
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;
|
||
for (int i = 0; i < ExTileCount; i++)
|
||
{
|
||
std::string path = extileArr[i];
|
||
RefPtr<Tile> tile = new Tile(path);
|
||
int xbuf = i % NormalTileCount * 224;
|
||
int ybuf = 560 - 200 - std::get<int>(_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<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(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<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(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<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(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<GameMapLayer>)
|
||
// RefPtr<GameMapLayer> &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<BaseObject> 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;
|
||
} |