修改渲染底层,新增场景摄像机逻辑,地图可行区域逻辑

This commit is contained in:
2025-10-08 23:58:15 +08:00
parent df2cacdb92
commit 1b011b9b68
23 changed files with 5350 additions and 40 deletions

View File

@@ -291,6 +291,24 @@ void GameMap::InitMapAnimation()
}
}
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)
{
// 读取脚本配置
@@ -301,11 +319,8 @@ void GameMap::LoadMap(std::string mapName)
InitBackgroundAnimation();
// 初始化场景Ani
InitMapAnimation();
RefPtr<CharacterObject> obj = new CharacterObject();
obj->SetPosition({620, 200, 0});
obj->Construction(0);
_LayerMap["normal"]->AddObject(obj);
// 初始化可行区域
InitVirtualMovableArea();
}
void GameMap::Enter(Scene *scene)
@@ -321,7 +336,7 @@ void GameMap::Enter(Scene *scene)
scene->AddChild(_LayerMap["max"]);
// TODO
int HSU = 230;
int HSU = 0;
_LayerMap["contact"]->SetPos(VecFPos{0, HSU});
_LayerMap["distantback"]->SetPos(VecFPos{0, HSU});
_LayerMap["middleback"]->SetPos(VecFPos{0, HSU});
@@ -367,3 +382,67 @@ void GameMap::Update(float deltaTime)
// }
// }
}
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;
}

View File

@@ -62,6 +62,10 @@ public:
int _MapLength = 0;
// 地图高度
int _MapHeight = 0;
// 可行区域
std::vector<SDL_FRect> _MovableArea;
// 调试模式
bool _DebugMode = true;
public:
// 图层Map 图层类型 显示对象
@@ -79,9 +83,13 @@ public:
void InitTile();
void InitBackgroundAnimation();
void InitMapAnimation();
void InitVirtualMovableArea();
void Enter(Scene *scene);
void HandleEvents(SDL_Event *e);
void Update(float deltaTime);
void AddObject(RefPtr<BaseObject> object);
public:
// 检查是否可移动
VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset);
};

View File

@@ -1,4 +1,5 @@
#include "GameMapCamera.h"
#include "EngineCore/Game.h"
#include "Actor/Map/GameMap.h"
#include "Actor/Object/BaseObject.h"
#include <algorithm>
@@ -45,10 +46,23 @@ void GameMapCamera::SyncPosByFromParent(float deltaTime)
{
if (this->_FromActor != nullptr)
{
// int R_X, R_Y, R_Z;
// R_X = std::min(std::max(this->_FromActor->X, 533), MovableAreaX - 533);
// R_Y = std::min(std::max(this->_FromActor->Y, 300), MovableAreaY - 300);
// R_Z = 0;
float width_Separate = Game::GetInstance().Screen_W / 2;
float height_Separate = Game::GetInstance().Screen_H / 2;
int R_X, R_Y, R_Z;
R_X = std::fmin(std::fmax(this->_FromActor->Position.x, width_Separate), _ParentMap->_MapLength - width_Separate);
R_Y = std::fmin(std::fmax(this->_FromActor->Position.y, height_Separate), _ParentMap->_MapHeight - height_Separate);
R_Z = 0;
// SDL_Log("R_X: %d, R_Y: %d, R_Z: %d", R_X, R_Y, R_Z);
// SetPos(R_X, R_Y, R_Z);
for (auto Layer : _ParentMap->_LayerMap)
{
if (Layer.first == "distantback")
{
Layer.second->SetPos(VecFPos((-R_X + width_Separate) * BackgroundMoveSpeed, -R_Y + R_Z + height_Separate + 120 + BackgroundOffset));
}
else
Layer.second->SetPos(VecFPos((-R_X + width_Separate), -R_Y + R_Z + height_Separate + 120 + BackgroundOffset));
}
}
}

View File

@@ -20,7 +20,7 @@ public:
// 背景偏移量
int BackgroundOffset = 0;
// 背景层移动速率
int BackgroundMoveSpeed = 1.0;
int BackgroundMoveSpeed = 1.03;
// 人物中线长度
int CharacterLineLength = 0;
// 摄像机朝向

View File

@@ -1,4 +1,5 @@
#include "GameMapLayer.h"
#include "EngineCore/Game.h"
GameMapLayer::GameMapLayer()
{
@@ -8,6 +9,37 @@ GameMapLayer::~GameMapLayer()
{
}
void GameMapLayer::Render()
{
Actor::Render();
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
// 设置绘制颜色
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
// 自身坐标
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;
// 绘制填充矩形
SDL_RenderFillRect(renderer, &buf);
}
}
void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size)
{
SDL_Rect info;
info.x = pos.x;
info.y = pos.y;
info.w = size.width;
info.h = size.height;
this->FeasibleAreaInfoList.push_back(info);
}
void GameMapLayer::AddObject(RefPtr<Actor> obj)
{
this->AddChild(obj);

View File

@@ -9,11 +9,18 @@ class GameMapLayer : public Actor
private:
// 地图对象
std::vector<RefPtr<Component>> ObjectManager;
// 可行区域信息
std::vector<SDL_Rect> FeasibleAreaInfoList;
public:
GameMapLayer(/* args */);
~GameMapLayer();
// 重载Render以实现绘制可行区域
void Render() override;
// 添加调试可行区域信息
void AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size);
public:
void AddObject(RefPtr<Actor> obj); // 添加对象
};

View File

@@ -45,6 +45,6 @@ void ActiveObject::Update(float deltaTime)
SetPosition(Position);
SDL_LogError(0, "修正Z轴");
}
// 执行父对象的更新
// 执行父的更新
BaseObject::Update(deltaTime);
}

View File

@@ -1,5 +1,5 @@
#include "BaseObject.h"
#include "Actor/Map/GameMap.h"
BaseObject::BaseObject()
{
Init(); // 调用了RenderBase的Init函数 对象才会被执行回调
@@ -12,6 +12,10 @@ BaseObject::~BaseObject()
void BaseObject::SetPosition(VecFPos3 pos)
{
if (pos.y != this->Position.y)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = pos;
Actor::SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z});
}
@@ -29,6 +33,10 @@ void BaseObject::SetXpos(float x)
void BaseObject::SetYpos(float y)
{
if (y != this->Position.y)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position.y = y;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
}
@@ -56,17 +64,25 @@ int BaseObject::GetZpos()
void BaseObject::MoveBy(VecFPos3 pos)
{
this->Position.x += pos.x;
this->Position.y += pos.y;
this->Position.z += pos.z;
// 只有moveby移动时判断所在地图中是否能够这样移动
VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos);
if (pos.y != 0)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = RealPos;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
}
void BaseObject::MoveBy(float x, float y, float z)
{
this->Position.x += x;
this->Position.y += y;
this->Position.z += z;
// 只有moveby移动时判断所在地图中是否能够这样移动
VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecFPos3({x, y, z}));
if (y != 0)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = RealPos;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
#include "Asset/Common/ObjectVars.h"
class GameMap;
class BaseObject : public Actor
{
private:
@@ -8,6 +9,7 @@ private:
public:
VecFPos3 Position; // 位置
int Direction = 0; // 方向
GameMap *_AffMap = nullptr; // 所在地图
public:
BaseObject(/* args */);