This commit is contained in:
2026-02-08 16:20:50 +08:00
parent 0ae47e5d6a
commit 8b88904ef7
72 changed files with 5963 additions and 2038 deletions

View File

@@ -1,5 +1,6 @@
#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"
@@ -19,15 +20,25 @@ GameMap::GameMap()
_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);
_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()
@@ -107,7 +118,7 @@ void GameMap::InitConfiguration(std::string mapName)
{
BackGroundAni ani;
Data.Get();
ani.filename = _MapDir + Tool_toLowerCase(Data.Get());
ani.filename = Tool_RegRealPath(_MapDir + Tool_toLowerCase(Data.Get()));
Data.Get();
ani.layer = Data.Get();
Data.Get();
@@ -119,13 +130,13 @@ void GameMap::InitConfiguration(std::string mapName)
}
else if (Segment == "[sound]")
{
std::vector<std::string> soundArry;
std::map<std::string, bool> soundArry;
while (true)
{
std::string sounddata = Data.Get();
if (sounddata == "[/sound]")
break;
soundArry.push_back(sounddata);
soundArry[sounddata] = true;
}
_MapInfo["sound"] = soundArry;
}
@@ -174,13 +185,17 @@ void GameMap::InitConfiguration(std::string mapName)
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));
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(areadata);
T.area = std::stoi(areadata);
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;
@@ -212,25 +227,19 @@ void GameMap::InitTile()
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> tileArr;
std::vector<std::string> extileArr;
std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
if (extileArr.size() > 0)
tileArr = std::get<std::vector<std::string>>(_MapInfo["tile"]);
// 拓展地板不一定有
if (_MapInfo.count("extended_tile"))
{
int ExTileCount = extileArr.size();
int Buffer = (ExTileCount / NormalTileCount);
_MapHeight += (Buffer < 1 ? 1 : Buffer) * 40;
extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
}
_Tile = new Tile(this, tileArr, extileArr);
_Tile->SetPosition(0, -200 - std::get<int>(_MapInfo["background_pos"]));
_LayerMap["bottom"]->AddChild(_Tile);
}
@@ -256,8 +265,8 @@ void GameMap::InitBackgroundAnimation()
}
for (int i = 0; i < (int)AniList.size(); i++)
{
AniList[i]->SetPos(Vec2{i * width, -120});
AniList[i]->SetRenderZOrder(-1000000);
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))
@@ -281,8 +290,8 @@ void GameMap::InitMapAnimation()
{
std::string path = ani.filename;
RefPtr<Animation> AniObj = new Animation(path);
AniObj->SetPos(Vec2{ani.XPos, ani.YPos - ani.ZPos});
AniObj->SetRenderZOrder(ani.YPos);
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))
@@ -305,12 +314,30 @@ void GameMap::InitVirtualMovableArea()
float w = Info[i + 2];
float h = Info[i + 3];
if (_DebugMode)
_LayerMap["max"]->AddDebugFeasibleAreaInfo(Vec2(x, y), VecSize(w, h));
_LayerMap["max"]->AddDebugFeasibleAreaInfo(Vec2(x, y), VecSize(w, h), 0);
_MovableArea.push_back(SDL_FRect{x, y, w, h});
}
}
}
void GameMap::InitMoveArea()
{
std::vector<int> Info = std::get<std::vector<int>>(_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)
{
// 读取脚本配置
@@ -323,24 +350,41 @@ void GameMap::LoadMap(std::string mapName)
InitMapAnimation();
// 初始化可行区域
InitVirtualMovableArea();
// 初始化传送区域
InitMoveArea();
}
void GameMap::Enter(Scene *scene)
void GameMap::Enter()
{
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"]);
auto &Audio = Asset_SoundPack::GetInstance();
// 获取背景音乐
auto bgmIt = _MapInfo.find("sound");
if (bgmIt != _MapInfo.end())
{
std::map<std::string, bool> bgmlist = std::get<std::map<std::string, bool>>(_MapInfo["sound"]);
// 获取正在播放的背景音乐
std::map<std::string, int> 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::Update(float deltaTime)
void GameMap::OnUpdate(float deltaTime)
{
Actor::Update(deltaTime);
RefPtr<GameCamera> Cam = Global_Game::GetInstance().GetCamera();
if (Cam == nullptr)
@@ -384,8 +428,11 @@ void GameMap::Update(float deltaTime)
posX *= BackgroundMoveSpeed;
posX /= 100.0f;
}
Layer.second->SetPos(Vec2(posX, posY));
Layer.second->SetPosition(posX, posY);
}
Actor::OnUpdate(deltaTime);
}
void GameMap::AddObject(RefPtr<BaseObject> object)
@@ -397,9 +444,6 @@ void GameMap::AddObject(RefPtr<BaseObject> object)
{
CharacterObject *chr = (CharacterObject *)(object.Get());
Global_Game::GetInstance().GetCamera()->SetFromActor(chr);
if (chr->_Shadow)
_LayerMap["bottom"]->AddChild(chr->_Shadow);
}
}
@@ -459,4 +503,42 @@ VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset)
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<MapMoveArea> &tma = std::get<std::vector<MapMoveArea>>(_MapInfo["town_movable_area_info"]);
return tma[i];
}
}
}
// 所有矩形都不命中,返回无效值
return invalidArea;
}
std::vector<GameMap::MapMoveArea> &GameMap::GetMoveAreaInfo()
{
return std::get<std::vector<GameMap::MapMoveArea>>(_MapInfo["town_movable_area_info"]);
}
SDL_Rect GameMap::GetMovablePositionArea(int Index)
{
auto Vertex = std::get<std::vector<int>>(_MapInfo["town_movable_area"]);
int FindIndex = Index * 4;
SDL_Rect Buf = {Vertex[FindIndex], Vertex[FindIndex + 1], Vertex[FindIndex + 2], Vertex[FindIndex + 3]};
return Buf;
}

View File

@@ -10,6 +10,7 @@ class BaseObject;
class GameMapCamera;
class GameMap : public Actor
{
public:
struct BackGroundAni
{
std::string filename;
@@ -37,13 +38,14 @@ class GameMap : public Actor
struct MapMoveArea
{
int town;
int area;
int town = 0;
int area = 0;
};
using MapInfoBody = std::variant<
int,
std::string,
std::map<std::string, bool>,
std::vector<BackGroundAni>,
std::vector<MapAni>,
std::vector<MapNpc>,
@@ -66,6 +68,8 @@ public:
int _MapHeight = 0;
// 可行区域
std::vector<SDL_FRect> _MovableArea;
// 传送区域
std::vector<SDL_FRect> _MoveArea;
// 调试模式
bool _DebugMode = false;
@@ -81,17 +85,36 @@ public:
GameMap(/* args */);
~GameMap();
/**加载地图 (地图路径) */
void LoadMap(std::string mapName);
/**进入地图执行的操作 */
void Enter();
/**重载OnUpdate函数 */
void OnUpdate(float deltaTime) override;
public:
/**读取脚本配置 */
void InitConfiguration(std::string mapName);
/**初始化地板 */
void InitTile();
/**初始化背景动画 */
void InitBackgroundAnimation();
/**初始化地图动画 */
void InitMapAnimation();
/**初始化移动区域 */
void InitVirtualMovableArea();
void Enter(Scene *scene);
void Update(float deltaTime) override;
/**初始化传送区域 */
void InitMoveArea();
/**添加对象 */
void AddObject(RefPtr<BaseObject> object);
public:
// 检查是否可移动
VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset);
// 检查是否进入传送区域
MapMoveArea CheckIsItMoveArea(VecFPos3 CurPos);
/**获取移动区域信息 */
std::vector<GameMap::MapMoveArea> &GetMoveAreaInfo();
/**获取移动区域坐标信息 */
SDL_Rect GetMovablePositionArea(int Index);
};

View File

@@ -1,35 +1,47 @@
#include "GameMapLayer.h"
#include "EngineCore/Game.h"
void GameMapLayer::Render()
{
Actor::Render();
// RenderManager *renderer = Game::GetInstance().GetRenderer();
// // 自身坐标
// float Xpos = GetIterationPos().x + GetPos().x;
// float Ypos = GetIterationPos().y + GetPos().y;
// for (auto &info : this->FeasibleAreaInfoList)
// {
// SDL_Rect buf;
// buf.x = info.x + Xpos;
// buf.y = info.y + Ypos;
// buf.w = info.w;
// buf.h = info.h;
// //TODO: 渲染可行区域
// }
// 自身坐标
glm::vec2 Pos = this->ConvertToWorld({0, 0});
// 可行区域
for (auto &info : this->FeasibleAreaInfoList)
{
SDL_Rect buf;
buf.x = info.x + Pos.x;
buf.y = info.y + Pos.y;
buf.w = info.w;
buf.h = info.h;
glm::vec4 red = {1.0f, 0.0f, 0.0f, 0.4f}; // RGBA红色不透明基础色
Game::GetInstance().GetRenderer()->DrawRect(&buf, red);
}
// 移动区域
for (auto &info : this->MoveAreaInfoList)
{
SDL_Rect buf;
buf.x = info.x + Pos.x;
buf.y = info.y + Pos.y;
buf.w = info.w;
buf.h = info.h;
glm::vec4 red = {0.0f, 0.0f, 1.0f, 0.4f}; // RGBA红色不透明基础色
Game::GetInstance().GetRenderer()->DrawRect(&buf, red);
}
}
void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size)
void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size, int Type)
{
SDL_Rect info;
info.x = pos.x;
info.y = pos.y;
info.w = size.width;
info.h = size.height;
this->FeasibleAreaInfoList.push_back(info);
if (Type == 0)
this->FeasibleAreaInfoList.push_back(info);
else if (Type == 1)
this->MoveAreaInfoList.push_back(info);
}
void GameMapLayer::AddObject(RefPtr<Actor> obj)

View File

@@ -9,12 +9,14 @@ class GameMapLayer : public Actor
private:
// 可行区域信息
std::vector<SDL_Rect> FeasibleAreaInfoList;
// 移动区域信息
std::vector<SDL_Rect> MoveAreaInfoList;
public:
// 重载Render以实现绘制可行区域
// 重载OnRender以实现绘制可行区域
void Render() override;
// 添加调试可行区域信息
void AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size);
void AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size, int Type);
public:
void AddObject(RefPtr<Actor> obj); // 添加对象

View File

@@ -0,0 +1,67 @@
#include "GameTown.h"
#include "Global/Global_Game.h"
GameTown::GameTown()
{
}
GameTown::~GameTown()
{
}
void GameTown::Init(int Index)
{
GlobalTownScript::TownConfig *Config = Global_Game::GetInstance().GetTownInfo(Index);
if (Config)
{
this->Name_ = Config->TownName;
this->Entering_Title = Config->Entering_Title;
this->Entering_Cutscene = Config->Entering_Cutscene;
this->NeedLevel = Config->NeedLevel;
this->NeedQuestID = Config->NeedQuestID;
// 构造全部地图
for (auto &it : Config->AreaLst)
{
MapInfo info;
info.Map = new GameMap();
info.Map->LoadMap(it.second.MapPath);
info.Type = it.second.MapType;
MapList_.push_back(info);
if (info.Type == "gate")
{
SariaRoomID = it.first;
SariaRoomPos = {it.second.GenerateXPos, it.second.GenerateYPos, 0};
}
}
}
}
void GameTown::AddCharacter(RefPtr<CharacterObject> Chr, int Index)
{
int TargetMapIndex = Index;
if (Index == -2)
{
TargetMapIndex = SariaRoomID;
}
// 如果有当前调用中的地图
if (CurMapIndex != -1)
{
RemoveChild(MapList_[CurMapIndex].Map);
}
// 如果角色已有父对象
if (Chr->GetParent())
{
Chr->RemoveFromParent();
}
// 调用赛利亚房间地图
AddChild(MapList_[TargetMapIndex].Map);
if(Index == -2)Chr->SetPosition(SariaRoomPos);
MapList_[TargetMapIndex].Map->Enter();
MapList_[TargetMapIndex].Map->AddObject(Chr);
CurMapIndex = TargetMapIndex;
}
void GameTown::OnUpdate(float DeltaTime)
{
Actor::OnUpdate(DeltaTime);
}

View File

@@ -0,0 +1,54 @@
#pragma once
#include "EngineFrame/Base/Actor.h"
#include "Actor/Map/GameMap.h"
#include "Actor/Object/CharacterObject.h"
class GameTown : public Actor
{
public:
struct MapInfo
{
/**地图对象 */
RefPtr<GameMap> Map;
/**地图类型 */
std::string Type;
};
private:
/**城镇名称 */
std::string Name_;
/**进入城镇时的标题Img */
std::string Entering_Title;
/**进入城镇时的过场Img */
std::string Entering_Cutscene;
/**需要的任务进入条件 */
int NeedQuestID;
/**需要的等级进入条件 */
int NeedLevel;
/**赛利亚房间编号 */
int SariaRoomID = -1;
/**赛丽亚房间生成坐标 */
VecFPos3 SariaRoomPos;
/**地图集合 */
std::vector<MapInfo> MapList_;
/**当前所在地图 */
int CurMapIndex = -1;
public:
GameTown(/* args */);
~GameTown();
/**通过城镇ID初始化 */
void Init(int Index);
public:
/**获取当前所在区域 */
int GetCurAreaIndex() { return CurMapIndex; };
/**获取区域对象 */
RefPtr<GameMap> GetArea(int Index) { return MapList_[Index].Map; };
/**添加角色 (无区域编号 上线进入城镇 或 使用传送时进入城镇 有区域编号 移动进入的)*/
void AddCharacter(RefPtr<CharacterObject> Chr, int AreaIndex = -2);
void OnUpdate(float DeltaTime) override;
};

View File

@@ -0,0 +1,100 @@
#include "GameWorld.h"
#include "Global/Global_Game.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Component/AnimationMap.h"
#include "EngineFrame/Component/Animation.h"
GameWorld::GameWorld()
{
}
GameWorld::~GameWorld()
{
}
void GameWorld::Enter()
{
SetScale(1.2f, 1.2f);
Init();
}
void GameWorld::Exit()
{
}
void GameWorld::Init()
{
// RefPtr<Animation> ani = new Animation("common/tuguan/maineff.ani");
RefPtr<Sprite> sp = new Sprite("sprite/live/else/chn/2022/0510_danjin_jar/22_danjineft/0510_danjin_body.img",0);
RefPtr<AnimationMap> am = new AnimationMap();
// am->AddAnimation(ani);
am->AddChild(sp);
am->CompleteConstruction();
AddChild(am);
// // 构造所有城镇
// auto &GlobalGame = Global_Game::GetInstance();
// for (auto obj : GlobalGame.GetTownMap())
// {
// RefPtr<GameTown> town = new GameTown;
// town->Init(obj.first);
// m_TownMap[obj.first] = town;
// }
// // 构造角色
// RefPtr<CharacterObject> obj = new CharacterObject();
// obj->Construction(0);
// AddCharacter(obj, 1);
}
void GameWorld::AddCharacter(RefPtr<CharacterObject> Chr, int TownId)
{
// 游戏世界类赋值我的角色
m_MyCharacter = Chr;
// 记录当前城镇
m_CurTown = TownId;
// 进入城镇
m_TownMap[TownId]->AddCharacter(Chr);
// 渲染并更新城镇
AddChild(m_TownMap[TownId]);
}
void GameWorld::MoveCharacter(RefPtr<CharacterObject> Chr, int TownId, int Area)
{
// 当前所在城镇
int curTown = m_CurTown;
// 当前所在区域
int curArea = m_TownMap[curTown]->GetCurAreaIndex();
// 获取目标城镇移动信息表
auto MapObj = m_TownMap[TownId]->GetArea(Area);
auto MoveInfo = MapObj->GetMoveAreaInfo();
// 传送后的目标区域
SDL_Rect destArea = {0, 0, 0, 0};
// 遍历移动信息表
for (size_t i = 0; i < MoveInfo.size(); ++i)
{
auto info = MoveInfo[i];
if (info.town == curTown && info.area == curArea)
{
destArea = MapObj->GetMovablePositionArea(i);
}
}
// 读取出应该存在的坐标以后设置角色的坐标
float Xpos = destArea.x + destArea.w / 2;
float Ypos = destArea.y + destArea.h / 2;
Chr->SetPosition({Xpos, Ypos, 0});
// 将角色添加到目标城镇
m_TownMap[TownId]->AddCharacter(Chr, Area);
// 停止渲染更新旧城镇
RemoveChild(m_TownMap[curTown]);
// 记录当前城镇
m_CurTown = TownId;
// 渲染并更新城镇
AddChild(m_TownMap[TownId]);
}
GameWorld *GameWorld::GetWorld()
{
return (GameWorld *)Game::GetInstance().GetScene().Get();
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include "EngineFrame/Scene/Scene.h"
#include "Actor/Map/GameTown.h"
class GameWorld : public Scene
{
private:
/**城镇Map */
std::map<int, RefPtr<GameTown>> m_TownMap;
/**我的角色 */
RefPtr<CharacterObject> m_MyCharacter;
/**当前城镇 */
int m_CurTown;
public:
GameWorld();
~GameWorld();
void Enter() override;
void Exit() override;
/**初始化 */
void Init() override;
/**加入角色 */
void AddCharacter(RefPtr<CharacterObject> Chr, int TownId);
/**移动角色 */
void MoveCharacter(RefPtr<CharacterObject> Chr, int TownId,int Area);
public:
static GameWorld *GetWorld();
};

View File

@@ -4,56 +4,29 @@
#include "Actor/Map/GameMap.h"
#include "Global/Global_Game.h"
// Tile::Tile(std::string Path) : Sprite()
// {
// InitInfo(Path);
// if (std::get<std::string>(m_data["path"]) == "")
// m_data["path"] = "sprite/character/common/circlecooltime.img";
// m_texture = new Texture();
// m_texture->Init(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
// Sprite::Init();
// this->imgPath = Path;
// }
Tile::Tile(GameMap *parentMap, std::vector<std::string> normal, std::vector<std::string> ex)
{
m_parentMap = parentMap;
m_texture = new Texture();
// 通过父对象获取地图大小
int Width = m_parentMap->_MapLength;
int Height = m_parentMap->_MapHeight;
// 通过大小纹理大小
m_texture->Init(VecSize(Width, Height));
m_rect = {0, 0, (float)Width, (float)Height};
Actor::Init();
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 将目标纹理附加到FBO的颜色附着点
glFramebufferTexture2D(
GL_FRAMEBUFFER, // 帧缓冲类型
GL_COLOR_ATTACHMENT0, // 颜色附着点(可多个,这里用第一个)
GL_TEXTURE_2D, // 纹理类型
m_texture->getID(), // 目标纹理ID
0 // 多级渐远纹理级别
);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
for (size_t i = 0; i < normal.size(); i++)
{
InitTile(normal[i], i);
}
m_tileX = normal.size();
for (size_t i = 0; i < ex.size(); i++)
{
InitExTile(ex[i], i);
}
SetPos(Vec2(0, 80 - 200 - std::get<int>(m_parentMap->_MapInfo["background_pos"])));
// 有可能没写地板
if (m_BasicTileWidth == 0)
m_BasicTileWidth = 224 * normal.size();
// 通过父对象获取地图大小
m_parentMap->_MapLength = m_BasicTileWidth;
m_parentMap->_MapHeight = m_BasicTileHeight + m_ExTileHeight;
Canvas::Init({(int)m_BasicTileWidth, (int)m_BasicTileHeight + (int)m_ExTileHeight + (int)m_tileY});
DrawTile();
}
Tile::~Tile()
@@ -66,6 +39,9 @@ void Tile::InitTile(std::string Path, int Index)
TileInfo data;
InitInfo(Path, data);
// 读取信息
float ImgOffset = std::get<int>(data["pos"]);
if (ImgOffset > m_tileY)
m_tileY = ImgOffset;
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
@@ -77,18 +53,20 @@ void Tile::InitTile(std::string Path, int Index)
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
RefPtr<Sprite> tex = new Sprite(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
// 横向地板数量增加
m_Tile_X_Count++;
// 基础地板宽度增加
m_BasicTileWidth += m_imgMap[key]->GetTexture()->getFrameSize().width;
// 取基础地板最高的高度
if (m_imgMap[key]->GetTexture()->getFrameSize().height > m_BasicTileHeight)
m_BasicTileHeight = m_imgMap[key]->GetTexture()->getFrameSize().height;
DrawInfo info;
info.rect.x = Index * m_imgMap[key]->getSize().width + m_imgMap[key]->getPos().x;
info.rect.y = m_imgMap[key]->getPos().y;
info.rect.w = m_imgMap[key]->getSize().width;
info.rect.h = m_imgMap[key]->getSize().height;
info.texture = key;
// 添加到绘制信息列表
info.sprite_ = key;
info.pos = {Index * 224, ImgOffset};
m_drawQueue.push_back(info);
}
@@ -98,6 +76,9 @@ void Tile::InitExTile(std::string Path, int Index)
TileInfo data;
InitInfo(Path, data);
// 读取信息
float ImgOffset = std::get<int>(data["pos"]);
if (ImgOffset > m_tileY)
m_tileY = ImgOffset;
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
@@ -109,28 +90,23 @@ void Tile::InitExTile(std::string Path, int Index)
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
RefPtr<Sprite> tex = new Sprite(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
// 如果进了这个函数默认有1格
if (m_ExTileHeight == 0)
m_ExTileHeight = 120;
// Ex地板高度120一格
if (((Index / m_Tile_X_Count) * 120) > m_ExTileHeight)
m_ExTileHeight = ((Index / m_Tile_X_Count) * 120);
DrawInfo info;
info.rect.x = Index * m_imgMap[key]->getSize().width + m_imgMap[key]->getPos().x;
info.rect.y = m_imgMap[key]->getPos().y + 560 + ((Index / m_tileX) * 120);
info.rect.w = m_imgMap[key]->getSize().width;
info.rect.h = m_imgMap[key]->getSize().height;
info.texture = key;
// 添加到绘制信息列表
info.sprite_ = key;
info.pos = {Index * 224, m_tileY + m_BasicTileHeight + ((Index / m_Tile_X_Count) * 120)};
m_drawQueue.push_back(info);
}
// void Tile::SetPos(Vec2 pos)
// {
// // pos.y += std::get<int>(m_data["pos"]);
// // Sprite::SetPos(pos);
// }
void Tile::InitInfo(std::string Path, TileInfo &m_data)
{
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(Path);
@@ -151,46 +127,13 @@ void Tile::InitInfo(std::string Path, TileInfo &m_data)
}
}
void Tile::PreRender()
void Tile::DrawTile()
{
m_rect.x = GetWorldPos().x;
m_rect.y = GetWorldPos().y;
//计算摄像机位置 知道自己需要渲染多大的区域
// m_srcRect = {0, 0, m_parentMap->_MapLength, m_parentMap->_MapHeight};
// Vec2 Pos = Global_Game::GetInstance().GetCamera() -> _currentPosition;
// m_srcRect = {Pos.x < 1067 ? 0 : Pos.x - 1067, Pos.y, 1067, 600};
}
void Tile::Render()
{
RenderManager *renderer = Game::GetInstance().GetRenderer();
SDL_FPoint AnchorPos = {0, 0};
if (!m_isBuild)
BeginDraw();
for (auto &info : m_drawQueue)
{
// 保存原始的正交矩阵 设置纹理对应的正交矩阵 和 视口
auto oldOm = Game::GetInstance().GetRenderer()->GetOrthoMatrix();
Game::GetInstance().GetRenderer()->SetOrthoMatrix(glm::ortho(0.0f, (float)m_texture->getSize().width, (float)m_texture->getSize().height, 0.0f, -1.0f, 1.0f));
glViewport(0, 0, m_texture->getSize().width, m_texture->getSize().height);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for (auto &info : m_drawQueue)
{
renderer->DrawTexture(m_imgMap[info.texture], nullptr, &info.rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
// 还原原始的正交矩阵 和 视口
Game::GetInstance().GetRenderer()->SetOrthoMatrix(oldOm);
glViewport(0, 0, Game::GetInstance().Screen_W, Game::GetInstance().Screen_H);
m_isBuild = true;
m_imgMap[info.sprite_]->SetPosition(info.pos);
DrawActor(m_imgMap[info.sprite_]);
}
renderer->SetCurrentShaderProgram("flip_y");
renderer->DrawTexture(m_texture, nullptr, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
renderer->SetCurrentShaderProgram("normal");
EndDraw();
}

View File

@@ -1,9 +1,12 @@
#pragma once
#include "Asset/AssetManager.h"
#include "EngineFrame/Component/Canvas.h"
#include "EngineFrame/Component/Sprite.h"
class GameMap;
class Tile : public Actor
class Tile : public Canvas
{
public:
struct ImgKey
{
std::string img;
@@ -20,46 +23,40 @@ class Tile : public Actor
};
struct DrawInfo
{
ImgKey texture;
SDL_FRect rect = {0, 0, 0, 0};
ImgKey sprite_;
glm::vec2 pos;
};
public:
using TileInfoBody = std::variant<int,std::string>;
using TileInfoBody = std::variant<int, std::string>;
using TileInfo = std::unordered_map<std::string, TileInfoBody>;
private:
/**纹理 */
RefPtr<Texture> m_texture = nullptr;
/**FBO */
GLuint m_fbo = 0;
/**地图父对象 */
GameMap* m_parentMap;
/**绘制纹理集 */
std::map<ImgKey, RefPtr<Texture>> m_imgMap;
/**父对象地图 */
GameMap *m_parentMap;
/**绘制精灵集 */
std::map<ImgKey, RefPtr<Sprite>> m_imgMap;
/**绘制队列 */
std::vector<DrawInfo> m_drawQueue;
/**渲染大小 */
SDL_Rect m_srcRect;
SDL_FRect m_rect;
/**大纹理构造完成Flag */
bool m_isBuild = false;
/**基础地板宽度 */
float m_BasicTileWidth = 0;
/**基础地板高度 */
float m_BasicTileHeight = 0;
/**Ex地板高度 */
float m_ExTileHeight = 0;
/**Tile横轴个数 */
int m_tileX = 0;
/**横向地板数量 */
int m_Tile_X_Count = 0;
/**纵向最大偏移 */
float m_tileY = 0;
public:
Tile(GameMap *parentMap, std::vector<std::string> normal,std::vector<std::string> ex);
Tile(GameMap *parentMap, std::vector<std::string> normal, std::vector<std::string> ex);
~Tile();
void InitTile(std::string Path,int Index);
void InitTile(std::string Path, int Index);
void InitExTile(std::string Path, int Index);
void InitInfo(std::string Path, TileInfo &m_data);
void PreRender() override;
void Render() override;
// void SetPos(Vec2 pos) override;
void DrawTile();
};