加入 Node节点类 还未测试新框架

This commit is contained in:
2025-10-27 23:12:56 +08:00
parent 80d088316b
commit 0ae47e5d6a
52 changed files with 1642 additions and 458 deletions

View File

@@ -1,10 +1,10 @@
#include "GameMap.h"
#include "Asset/AssetManager.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Scene/Scene.h"
#include "EngineFrame/Component/Animation.h"
#include "Actor/Map/GameMapCamera.h"
#include "Global/Global_Game.h"
#include "Actor/Object/CharacterObject.h"
#include "EngineCore/Game.h"
GameMap::GameMap()
{
@@ -217,34 +217,21 @@ void GameMap::InitTile()
{
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(Vec2{i * 224, -200 - std::get<int>(_MapInfo["background_pos"])});
_LayerMap["bottom"]->AddComponent(tile);
}
_MapHeight = 560;
}
if (_MapInfo.count("extended_tile"))
if (!_MapInfo.count("extended_tile"))
return;
std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
if (extileArr.size() > 0)
{
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 = -200 - std::get<int>(_MapInfo["background_pos"]) + NormalTileHeight + 120 * (i / NormalTileCount);
tile->SetPos(Vec2{xbuf, ybuf});
_LayerMap["bottom"]->AddComponent(tile);
}
}
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()
@@ -340,45 +327,42 @@ void GameMap::LoadMap(std::string mapName)
void GameMap::Enter(Scene *scene)
{
_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"]);
}
void GameMap::HandleEvents(SDL_Event *e)
{
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)
{
if (_Scene->GetCamera() == nullptr)
Actor::Update(deltaTime);
RefPtr<GameCamera> Cam = Global_Game::GetInstance().GetCamera();
if (Cam == nullptr)
return;
GameMapCamera *Cam = (GameMapCamera *)(_Scene->GetCamera().Get());
int targetX = Cam->_currentPosition.x;
int targetY = Cam->_currentPosition.y;
float targetX = Cam->_currentPosition.x;
float targetY = Cam->_currentPosition.y;
// 屏幕中心
int width_Separate = 1067 / 2;
int height_Separate = 600 / 2;
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"]);
int X_Limit_Min = limit[0];
int X_Limit_Max = limit[1];
int Y_Limit_Min = limit[2];
int Y_Limit_Max = limit[3];
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, _MapLength - width_Separate);
targetY = std::clamp(targetY, height_Separate, _MapHeight - height_Separate);
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);
@@ -393,12 +377,12 @@ void GameMap::Update(float deltaTime)
// 更新图层位置
for (auto &Layer : _LayerMap)
{
int posX = -targetX + width_Separate;
int posY = -targetY + height_Separate + MapOffsetY;
float posX = -targetX + width_Separate;
float posY = -targetY + height_Separate + MapOffsetY;
if (Layer.first == "distantback")
{
posX *= BackgroundMoveSpeed;
posX /= 100;
posX /= 100.0f;
}
Layer.second->SetPos(Vec2(posX, posY));
}
@@ -412,14 +396,17 @@ void GameMap::AddObject(RefPtr<BaseObject> object)
if (object->m_objecttype == ObjectType::CHARACTER)
{
CharacterObject *chr = (CharacterObject *)(object.Get());
if( chr->_Shadow != nullptr)_LayerMap["bottom"]->AddComponent(chr->_Shadow);
Global_Game::GetInstance().GetCamera()->SetFromActor(chr);
if (chr->_Shadow)
_LayerMap["bottom"]->AddChild(chr->_Shadow);
}
}
VecPos3 GameMap::CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset)
VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset)
{
// 初始化结果为原坐标(默认不移动)
VecPos3 result = CurPos;
VecFPos3 result = CurPos;
// 如果没有可移动区域限制,直接全量位移
if (_MovableArea.empty())

View File

@@ -8,7 +8,7 @@
class BaseObject;
class GameMapCamera;
class GameMap
class GameMap : public Actor
{
struct BackGroundAni
{
@@ -58,6 +58,8 @@ public:
std::string _MapPath;
// 地图文件夹
std::string _MapDir;
// 地板画布
RefPtr<Tile> _Tile = nullptr;
// 地图宽度
int _MapLength = 0;
// 地图高度
@@ -70,8 +72,6 @@ public:
public:
// 图层Map 图层类型 显示对象
std::unordered_map<std::string, RefPtr<GameMapLayer>> _LayerMap;
// 所属场景
Scene *_Scene = nullptr;
// 背景层移动速率
int BackgroundMoveSpeed = 103;
@@ -88,11 +88,10 @@ public:
void InitMapAnimation();
void InitVirtualMovableArea();
void Enter(Scene *scene);
void HandleEvents(SDL_Event *e);
void Update(float deltaTime);
void Update(float deltaTime) override;
void AddObject(RefPtr<BaseObject> object);
public:
// 检查是否可移动
VecPos3 CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset);
VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset);
};

View File

@@ -1,127 +0,0 @@
#include "GameMapCamera.h"
#include "EngineCore/Game.h"
#include "Actor/Map/GameMap.h"
#include "Actor/Object/BaseObject.h"
#include <algorithm>
GameMapCamera::GameMapCamera()
{
}
GameMapCamera::~GameMapCamera()
{
}
void GameMapCamera::SetFromActor(BaseObject *actor)
{
this->_FromActor = actor;
_FromActor->_AffCamera = this;
}
void GameMapCamera::Update(float deltaTime)
{
SyncPosByFromParent(deltaTime);
}
void GameMapCamera::SyncPos(float deltaTime)
{
}
void GameMapCamera::SetPos(int x, int y, int z)
{
// this->X = x;
// this->Y = y;
// this->Z = z;
}
void GameMapCamera::AddPos(int x, int y, int z)
{
// this->X += x;
// this->Y += y;
// this->Z += z;
}
void GameMapCamera::SyncPosByFromParent(float deltaTime)
{
if (this->_FromActor == nullptr)
{
return;
}
int targetX = _FromActor->Position.x;
int targetY = _FromActor->Position.y;
if (_isSmoothMoving)
{
// 平滑移动计算
VecPos targetPosition(targetX, targetY);
_currentPosition = SmoothDamp(_currentPosition, targetPosition, _velocity, _smoothTime, _maxSpeed, deltaTime);
}
else
{
_currentPosition.x = targetX;
_currentPosition.y = targetY;
}
}
VecPos GameMapCamera::SmoothDamp(const VecPos &current, const VecPos &target, VecPos &currentVelocity, float smoothTime, int maxSpeed, float deltaTime)
{
// 平滑时间为0时直接返回目标位置并重置速度
if (smoothTime <= 0.f)
{
currentVelocity = VecPos(0, 0);
return target;
}
// 临界阻尼系数计算(避免过冲的核心参数)
const float omega = 2.0f / smoothTime;
const float x = omega * deltaTime;
const float expTerm = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x);
// 计算当前位置与目标的差值
VecPos delta = target - current;
// 计算目标速度(基于阻尼公式和当前差值)
// 注意:这里先通过浮点计算保持精度,最后转换为整数
const float tx = delta.x * (omega * omega * deltaTime) - currentVelocity.x * (1.0f + 0.48f * x) * x;
const float ty = delta.y * (omega * omega * deltaTime) - currentVelocity.y * (1.0f + 0.48f * x) * x;
VecPos targetVelocity(static_cast<int>(tx), static_cast<int>(ty));
// 应用速度衰减(指数平滑)
currentVelocity += targetVelocity;
currentVelocity = VecPos(
static_cast<int>(currentVelocity.x * expTerm),
static_cast<int>(currentVelocity.y * expTerm));
// 限制最大速度如果设置了maxSpeed
if (maxSpeed > 0)
{
// 计算当前速度的模长(浮点精度)
const float speedSq = static_cast<float>(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y);
const float maxSpeedSq = static_cast<float>(maxSpeed * maxSpeed);
if (speedSq > maxSpeedSq)
{
// 速度超限,按比例缩放至最大速度
const float scale = maxSpeed / sqrtf(speedSq);
currentVelocity = VecPos(
static_cast<int>(currentVelocity.x * scale),
static_cast<int>(currentVelocity.y * scale));
}
}
// 计算新位置(当前位置 + 速度 * 时间)
VecPos newPos = current + VecPos(
static_cast<int>(currentVelocity.x * deltaTime),
static_cast<int>(currentVelocity.y * deltaTime));
// 检测过冲:如果新位置已越过目标,直接锁定目标并重置速度
// 点积 > 0 表示方向相反(已超过目标)
const int dot = delta.x * (newPos.x - target.x) + delta.y * (newPos.y - target.y);
if (dot > 0)
{
newPos = target;
currentVelocity = VecPos(0, 0);
}
return newPos;
}

View File

@@ -1,41 +0,0 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
class GameMap;
class BaseObject;
class GameMapCamera : public Actor
{
private:
// 跟随对象
BaseObject *_FromActor = nullptr;
public:
// 摄像机记录的跟随对象坐标
VecPos3 FromActorPos = {0, 0, 0};
// 缩放比率
float CameraRate = 1.0;
// 添加平滑移动相关的成员变量
bool _isSmoothMoving = false;
VecPos _currentPosition; // 当前摄像机位置
VecPos _velocity; // 当前移动速度(用于平滑移动)
float _smoothTime = 0.1f; // 平滑时间(秒),可调整
int _maxSpeed = 2000; // 最大移动速度,防止过快
public:
GameMapCamera();
~GameMapCamera();
void SetFromActor(BaseObject *actor);
void Update(float deltaTime);
void SetPos(int x, int y, int z);
void AddPos(int x, int y, int z);
//同步坐标相关
void SyncPos(float deltaTime);
void SyncPosByFromParent(float deltaTime);
// 平滑阻尼函数类似Unity的Mathf.SmoothDamp
VecPos SmoothDamp(const VecPos &current, const VecPos &target, VecPos &currentVelocity, float smoothTime, int maxSpeed, float deltaTime);
};

View File

@@ -1,31 +1,25 @@
#include "GameMapLayer.h"
#include "EngineCore/Game.h"
GameMapLayer::GameMapLayer()
{
}
GameMapLayer::~GameMapLayer()
{
}
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: 渲染可行区域
}
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: 渲染可行区域
// }
}
void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size)

View File

@@ -1,6 +1,6 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
#include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Component/Sprite.h"
class BaseObject;
@@ -11,9 +11,6 @@ private:
std::vector<SDL_Rect> FeasibleAreaInfoList;
public:
GameMapLayer(/* args */);
~GameMapLayer();
// 重载Render以实现绘制可行区域
void Render() override;
// 添加调试可行区域信息

View File

@@ -1,33 +1,137 @@
#include "Tile.h"
#include "Tool/Tool_String.h"
#include "EngineCore/Game.h"
Tile::Tile()
{
}
#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";
// 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();
m_texture->Init(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
Sprite::Init();
this->imgPath = Path;
// 通过父对象获取地图大小
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"])));
}
Tile::~Tile()
{
}
void Tile::SetPos(Vec2 pos)
void Tile::InitTile(std::string Path, int Index)
{
pos.y += std::get<int>(m_data["pos"]);
Sprite::SetPos(pos);
// 读取文件
TileInfo data;
InitInfo(Path, data);
// 读取信息
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
if (path == "")
path = "sprite/character/common/circlecooltime.img";
// 构造纹理标识符
ImgKey key = {path, index};
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
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;
// 添加到绘制信息列表
m_drawQueue.push_back(info);
}
void Tile::InitInfo(std::string Path)
void Tile::InitExTile(std::string Path, int Index)
{
// 读取文件
TileInfo data;
InitInfo(Path, data);
// 读取信息
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
if (path == "")
path = "sprite/character/common/circlecooltime.img";
// 构造纹理标识符
ImgKey key = {path, index};
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
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;
// 添加到绘制信息列表
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);
m_data["pos"] = 0;
@@ -46,3 +150,47 @@ void Tile::InitInfo(std::string Path)
}
}
}
void Tile::PreRender()
{
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)
{
// 保存原始的正交矩阵 设置纹理对应的正交矩阵 和 视口
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;
}
renderer->SetCurrentShaderProgram("flip_y");
renderer->DrawTexture(m_texture, nullptr, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
renderer->SetCurrentShaderProgram("normal");
}

View File

@@ -1,22 +1,65 @@
#pragma once
#include "Asset/AssetManager.h"
#include "EngineFrame/Component/Sprite.h"
class Tile : public Sprite
#include "EngineFrame/Component/Canvas.h"
class GameMap;
class Tile : public Actor
{
struct ImgKey
{
std::string img;
int index;
using TileInfoBody = std::variant<
int,
std::string>;
private:
std::unordered_map<std::string, TileInfoBody> m_data;
bool operator<(const ImgKey &other) const
{
if (img != other.img)
{
return img < other.img; // 字符串按字典序比较
}
return index < other.index; // 字符串相同则比较index
}
};
struct DrawInfo
{
ImgKey texture;
SDL_FRect rect = {0, 0, 0, 0};
};
public:
Tile(/* args */);
Tile(std::string Path);
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;
/**绘制队列 */
std::vector<DrawInfo> m_drawQueue;
/**渲染大小 */
SDL_Rect m_srcRect;
SDL_FRect m_rect;
/**大纹理构造完成Flag */
bool m_isBuild = false;
/**Tile横轴个数 */
int m_tileX = 0;
public:
Tile(GameMap *parentMap, std::vector<std::string> normal,std::vector<std::string> ex);
~Tile();
void SetPos(Vec2 pos) override;
void InitTile(std::string Path,int Index);
void InitExTile(std::string Path, int Index);
void InitInfo(std::string Path, TileInfo &m_data);
void InitInfo(std::string Path);
void PreRender() override;
void Render() override;
// void SetPos(Vec2 pos) override;
};

View File

@@ -1,5 +1,5 @@
#include "ActiveObject.h"
void ActiveObject::SetPosition(VecPos3 pos)
void ActiveObject::SetPosition(VecFPos3 pos)
{
BaseObject::SetPosition(pos);
}
@@ -21,49 +21,36 @@ VecSpeed3 ActiveObject::GetSpeed()
void ActiveObject::Update(float deltaTime)
{
int IntegerDelta = static_cast<int>(deltaTime * 1000);
const int Gravity = 1020;
VecFPos3 MovePos;
// X轴移动含余数补偿
if (Speed.x != 0)
{
int totalX = Speed.x * IntegerDelta + Remainder.x; // 加上上次余数
int moveX = totalX / 1000; // 整数部分为实际移动
Remainder.x = totalX % 1000; // 保留余数(-999~999
MoveBy(moveX, 0, 0);
MovePos.x = Speed.x * deltaTime;
}
// Y轴移动同上
if (Speed.y != 0)
{
int totalY = Speed.y * IntegerDelta + Remainder.y;
int moveY = totalY / 1000;
Remainder.y = totalY % 1000;
MoveBy(0, moveY, 0);
MovePos.y = Speed.y * deltaTime;
}
// Z轴重力与移动含余数补偿
if (Position.z > 0 || Speed.z > 0)
{
// 重力对速度的影响先更新Speed.z含余数
int speedZTotal = -Gravity * IntegerDelta + Remainder.z; // 注意负号(减速)
Speed.z += speedZTotal / 1000; // 速度的整数部分
Remainder.z = speedZTotal % 1000; // 速度的余数
int speedZTotal = -1020 * deltaTime;
// 基于更新后的Speed.z计算移动量同样含余数
int moveZTotal = Speed.z * IntegerDelta + _zRemainderMove; // 新增_zRemainderMove记录移动余数
int moveZ = moveZTotal / 1000;
_zRemainderMove = moveZTotal % 1000;
MoveBy(0, 0, moveZ);
MovePos.z = Speed.z * deltaTime;
}
else if (Position.z < 0)
{
Position.z = 0;
Speed.z = 0;
Remainder.z = 0; // 重置余数
_zRemainderMove = 0;
SetPosition(Position);
}
MoveBy(MovePos);
BaseObject::Update(deltaTime);
}

View File

@@ -7,13 +7,12 @@ class ActiveObject : public BaseObject
public:
// 三轴速度
VecSpeed3 Speed;
// 三轴移动余数
VecPos3 Remainder;
int _zRemainderMove = 0;
public:
void
SetPosition(VecPos3 pos) override;
SetPosition(VecFPos3 pos) override;
void SetYpos(int y) override;
void SetSpeed(VecSpeed3 speed);

View File

@@ -1,6 +1,5 @@
#include "BaseObject.h"
#include "Actor/Map/GameMap.h"
#include "Actor/Map/GameMapCamera.h"
BaseObject::BaseObject()
{
@@ -14,15 +13,13 @@ BaseObject::~BaseObject()
void BaseObject::Update(float deltaTime)
{
if (_AffCamera != nullptr)
{
_AffCamera->SyncPos(deltaTime);
}
Actor::Update(deltaTime);
}
void BaseObject::SetPosition(VecPos3 pos)
void BaseObject::SetPosition(VecFPos3 pos)
{
if(pos == this->Position)
return;
if (pos.y != this->Position.y)
{
SetRenderZOrder(pos.y); // 设置渲染顺序
@@ -31,19 +28,23 @@ void BaseObject::SetPosition(VecPos3 pos)
SetPos(Vec2{this->Position.x, this->Position.y - this->Position.z});
}
VecPos3 BaseObject::GetPosition()
VecFPos3 BaseObject::GetPosition()
{
return this->Position;
}
void BaseObject::SetXpos(int x)
{
if (x == this->Position.x)
return;
this->Position.x = x;
SetPos({this->Position.x, this->Position.y - this->Position.z});
}
void BaseObject::SetYpos(int y)
{
if (y == this->Position.y)
return;
if (y != this->Position.y)
{
SetRenderZOrder(y); // 设置渲染顺序
@@ -54,6 +55,8 @@ void BaseObject::SetYpos(int y)
void BaseObject::SetZpos(int z)
{
if (z == this->Position.z)
return;
this->Position.z = z;
SetPos({this->Position.x, this->Position.y - this->Position.z});
}
@@ -73,10 +76,12 @@ int BaseObject::GetZpos()
return this->Position.z;
}
void BaseObject::MoveBy(VecPos3 pos)
void BaseObject::MoveBy(VecFPos3 pos)
{
// 只有moveby移动时判断所在地图中是否能够这样移动
VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos);
VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos);
if (RealPos == this->Position)
return;
if (RealPos.y != this->Position.y)
{
SetRenderZOrder(RealPos.y); // 设置渲染顺序
@@ -90,7 +95,9 @@ void BaseObject::MoveBy(VecPos3 pos)
void BaseObject::MoveBy(int x, int y, int z)
{
// 只有moveby移动时判断所在地图中是否能够这样移动
VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecPos3({x, y, z}));
VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecFPos3({x, y, z}));
if (RealPos == this->Position)
return;
if (RealPos.y != this->Position.y)
{
SetRenderZOrder(RealPos.y); // 设置渲染顺序

View File

@@ -1,18 +1,16 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
#include "EngineFrame/Base/Actor.h"
#include "Asset/Common/ObjectVars.h"
#include "Global/Global_Enum.h"
class GameMap;
class GameMapCamera;
class BaseObject : public Actor
{
public:
public:
ObjectType m_objecttype; // 对象类型
VecPos3 Position; // 位置
VecFPos3 Position; // 位置
int Direction = 0; // 方向
GameMap *_AffMap = nullptr; // 所在地图
GameMapCamera *_AffCamera = nullptr; // 跟随相机
public:
BaseObject(/* args */);
@@ -24,17 +22,17 @@ public:
ObjectVars _ObjectVars;
public:
virtual void SetPosition(VecPos3 pos);
virtual void SetPosition(VecFPos3 pos);
virtual void SetXpos(int x);
virtual void SetYpos(int y);
virtual void SetZpos(int z);
VecPos3 GetPosition();
VecFPos3 GetPosition();
int GetXpos();
int GetYpos();
int GetZpos();
virtual void MoveBy(VecPos3 pos);
virtual void MoveBy(VecFPos3 pos);
virtual void MoveBy(int x, int y, int z);
virtual void SetDirection(int dir);