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

@@ -27,8 +27,6 @@ Animation::~Animation()
void Animation::Init(std::string AniPath)
{
Actor::Init();
AniScriptParser::AniInfo Info = AssetManager::GetInstance().StructAniInfo(AniPath);
this->AniPath = AniPath;
this->AnimationFlag = Info.Flag;
@@ -45,17 +43,19 @@ void Animation::Init(std::string AniPath)
FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path, this->AdditionalOptionsData);
}
SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index);
SpriteObj->SetAnchor(Vec2(0.5f, 0.5f));
SpriteObj->SetPos(Vec2(FrameObj.Img_Pos.x, FrameObj.Img_Pos.y));
SpriteObj->SetPosition(FrameObj.Img_Pos.x, FrameObj.Img_Pos.y);
SpriteObj->SetVisible(false);
}
else
{
SpriteObj = new Sprite();
SpriteObj->SetVisible(false);
SDL_Log("Animation::Init() SpriteObj is nullptr");
}
SpriteArr.push_back(SpriteObj);
//记录最大帧宽高
auto SpriteSize = SpriteObj->GetSize();
if(this->MaxSize.width < SpriteSize.width)this->MaxSize.width = SpriteSize.width;
if(this->MaxSize.height < SpriteSize.height)this->MaxSize.height = SpriteSize.height;
AddChild(SpriteObj);
}
@@ -76,7 +76,7 @@ void Animation::Init(std::string AniPath)
for (auto &Ani : Info.AniList)
{
RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
AlsAniObj->SetZOrder(Ani.second.layer[1]);
AddChild(AlsAniObj);
}
}
@@ -84,20 +84,16 @@ void Animation::Init(std::string AniPath)
FlushFrame(0);
}
void Animation::HandleEvents(SDL_Event *e)
{
}
void Animation::Update(float deltaTime)
void Animation::OnUpdate(float deltaTime)
{
// 可用性检查
if (IsUsability && Visible)
if (IsUsability && IsVisible())
{
float dt_ms = deltaTime * 1000.0f;
// 累加当前帧时间
CurrentIndexT += dt_ms;
// 插值模式判断
InterpolationLogic();
// InterpolationLogic();
// 循环处理:只要当前时间超过帧延迟,就切换帧(支持一次跳过多帧)
while (CurrentIndexT >= NextFrameDelay)
@@ -127,32 +123,26 @@ void Animation::Update(float deltaTime)
}
}
}
Actor::Update(deltaTime);
}
else
{
for (auto &Sp : SpriteArr)
{
Sp->SetVisible(false);
}
}
}
void Animation::Render()
void Animation::OnAdded(Actor *node)
{
Actor::Render();
}
void Animation::OnAdded(BaseNode *node)
{
Actor::OnAdded(node);
FlushFrame(0);
}
void Animation::Clear()
{
}
void Animation::SetVisible(bool visible)
{
// 设置启用的时候要更新一下当前帧的渲染信息 避免因为延迟造成的坐标闪烁
if (visible)
{
CurrentFrame->CalcRenderInfoLogic();
CurrentFrame->CalcRenderInfo();
CurrentFrame->SetVisible(true);
}
Actor::SetVisible(visible);
}
@@ -192,7 +182,8 @@ void Animation::FlushFrame(int Index)
if (FlagBuf.count("IMAGE_RATE"))
{
Vec2 Rate = std::get<Vec2>(FlagBuf["IMAGE_RATE"]);
CurrentFrame->SetScale(Vec2{Rate.x, Rate.y});
CurrentFrame->SetScale(Rate.x, Rate.y);
CurrentFrame->SetPosition(FrameInfo.Img_Pos.x * Rate.x, FrameInfo.Img_Pos.y * Rate.y);
}
// 线性减淡
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
@@ -202,7 +193,7 @@ void Animation::FlushFrame(int Index)
// 旋转
if (FlagBuf.count("IMAGE_ROTATE"))
{
CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f});
// CurrentFrame->SetAnchor(0.5f, 0.5f);
CurrentFrame->SetRotation(std::get<float>(FlagBuf["IMAGE_ROTATE"]));
}
// 染色
@@ -277,10 +268,10 @@ void Animation::InterpolationLogic()
}
// 坐标
{
Vec2 PosData = {
glm::vec2 PosData = {
(OldData.Img_Pos.x + (NewData.Img_Pos.x - OldData.Img_Pos.x) * InterRate),
(OldData.Img_Pos.y + (NewData.Img_Pos.y - OldData.Img_Pos.y) * InterRate)};
CurrentFrame->SetPos(PosData);
CurrentFrame->SetPosition(PosData);
}
// 缩放
{
@@ -294,10 +285,9 @@ void Animation::InterpolationLogic()
{
NewRateData = std::get<Vec2>(NewData.Flag["IMAGE_RATE"]);
}
Vec2 RateData = {
glm::vec2 RateData = {
OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate,
OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate};
CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f});
CurrentFrame->SetScale(RateData);
}
// 旋转
@@ -315,3 +305,8 @@ void Animation::InterpolationLogic()
CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
}
}
VecSize Animation::GetMaxSize()
{
return MaxSize;
}

View File

@@ -24,24 +24,26 @@ public:
Animation(std::string AniPath, std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions, Animation::ReplaceData);
~Animation();
/**初始化 */
void Init(std::string AniPath);
void HandleEvents(SDL_Event *e) override;
void Update(float deltaTime) override;
void Render() override;
void OnAdded(BaseNode *node) override;
void Clear() override;
void OnUpdate(float deltaTime) override;
void OnAdded(Actor *node) override;
void SetVisible(bool visible) override;
public:
/**刷新帧 */
void FlushFrame(int Index);
/**重置Ani */
void Reset();
/**获取当前帧信息 */
AniScriptParser::AniFrame GetCurrentFrameInfo();
// 设置帧索引
void SetFrameIndex(int Index);
void InterpolationLogic();
// TODO SetOutline
// TODO SetDye
// TODO SetCrop
/**获取最大尺寸 */
VecSize GetMaxSize();
public:
// Ani是否可用
@@ -76,20 +78,11 @@ public:
std::string AniPath;
// 是否描边
bool IsOutline = false;
// // 描边颜色
// OutlineColor = null;
// // 描边对象List
// OutlineList = null;
// // 当前描边对象
// CurrentOutline = null;
// // 染色颜色
// DyeColor = null;
// // 染色帧List
// DyeFrameList = null;
// // 整体染色
// DyeAllFlag = false;
// 附加选项
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
Animation::ReplaceData AdditionalOptionsData;
/**最大尺寸
* 所有子精灵最大的尺寸
*/
VecSize MaxSize = {0, 0};
};

View File

@@ -1,72 +0,0 @@
#include "AnimationManager.h"
#include "EngineCore/Game.h"
AnimationManager::AnimationManager()
{
}
void AnimationManager::PreRender()
{
Actor::PreRender();
// 标记是否是第一个子对象用于初始化min/max值
bool isFirst = true;
float minX = 0.0f, minY = 0.0f; // 所有子对象的最小X、Y坐标
float maxX = 0.0f, maxY = 0.0f; // 所有子对象的最大X、Y坐标右下角
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
{
// 转换为Animation对象
Animation *ani = static_cast<Animation *>(child.Get());
float width = ani->CurrentFrame->_RenderGuidanceInfo.rect.w;
float height = ani->CurrentFrame->_RenderGuidanceInfo.rect.h;
float x = ani->CurrentFrame->_RenderGuidanceInfo.rect.x;
float y = ani->CurrentFrame->_RenderGuidanceInfo.rect.y;
// 计算子对象的右下角坐标(左上角 + 宽高)
float currentMaxX = x + width;
float currentMaxY = y + height;
// 初始化或更新min/max值
if (isFirst)
{
minX = x;
minY = y;
maxX = currentMaxX;
maxY = currentMaxY;
isFirst = false;
}
else
{
minX = std::min(minX, x);
minY = std::min(minY, y);
maxX = std::max(maxX, currentMaxX);
maxY = std::max(maxY, currentMaxY);
}
child = child->GetNext();
}
// 计算最终的包围盒矩形
if (!isFirst) // 至少有一个子对象时才计算
{
m_RenderRect.x = minX; // 矩形左上角X
m_RenderRect.y = minY; // 矩形左上角Y
m_RenderRect.w = maxX - minX; // 矩形宽度右下角X - 左上角X
m_RenderRect.h = maxY - minY; // 矩形高度右下角Y - 左上角Y
}
}
void AnimationManager::Render()
{
Actor::Render();
}
void AnimationManager::AddAnimation(RefPtr<Animation> ani)
{
this->AddChild(ani);
}
void AnimationManager::Clear()
{
this->RemoveAllChild();
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include "EngineFrame/Component/Animation.h"
#include <vector>
class AnimationManager : public Actor
{
private:
SDL_Texture *m_Texture = nullptr;
SDL_FRect m_RenderRect = {0, 0, 0, 0};
public:
AnimationManager();
// void Update(float deltaTime) override;
void PreRender() override;
void Render() override;
public:
// 添加Ani
void AddAnimation(RefPtr<Animation> ani);
// 清空Ani
void Clear();
};

View File

@@ -0,0 +1,132 @@
#include "AnimationMap.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Render/RenderManager.h"
AnimationMap::~AnimationMap()
{
}
void AnimationMap::CompleteConstruction()
{
m_size = {800, 600};
// 遍历自己的所持有的所有Ani 取最大的尺寸
auto &ac = this->GetAllChildren();
RefPtr<Node> child = ac.GetFirst();
while (child)
{
Animation *anim = static_cast<Animation *>(child.Get());
auto size = anim->GetMaxSize();
if (size.width > m_size.width)
m_size.width = size.width;
if (size.height > m_size.height)
m_size.height = size.height;
child = child->GetNext();
}
SetSize(m_size);
// 创建指定大小的纹理
m_texture = new Texture();
m_texture->Init(m_size);
// 构造FBO
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
}
void AnimationMap::AddAnimation(RefPtr<Animation> animation)
{
this->AddChild(animation);
}
void AnimationMap::Reset()
{
auto &ac = this->GetAllChildren();
RefPtr<Node> child = ac.GetFirst();
while (child)
{
Animation *anim = static_cast<Animation *>(child.Get());
anim->Reset();
child = child->GetNext();
}
}
void AnimationMap::Render()
{
Actor::PreRender();
Actor::PrepareToRender();
Actor::OnRender();
}
void AnimationMap::OnRender()
{
RenderManager *renderer = Game::GetInstance().GetRenderer();
renderer->DrawTexture(m_texture);
}
void AnimationMap::OnUpdate(float deltaTime)
{
Actor::OnUpdate(deltaTime);
RenderManager *renderer = Game::GetInstance().GetRenderer();
// 绑定FBO
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 清屏
glClear(GL_COLOR_BUFFER_BIT);
// 保存原始的正交矩阵 设置纹理对应的正交矩阵 和 视口
Oom = renderer->GetOrthoMatrix();
renderer->SetOrthoMatrix(glm::ortho(0.0f, (float)m_size.width, 0.0f, (float)m_size.height, -1.0f, 1.0f));
Oviewport = renderer->GetViewport();
renderer->SetViewport({0, 0, m_size.width, m_size.height});
// 以上步骤将渲染目标调整至AniMap的纹理上
SDL_Rect buf;
buf.x = 0;
buf.y = 0;
buf.w = m_size.width;
buf.h = m_size.height;
glm::vec4 red = {0.0f, 0.0f, 1.0f, 0.4f}; // RGBA红色不透明基础色
Game::GetInstance().GetRenderer()->DrawRect(&buf, red);
auto &ac = this->GetAllChildren();
RefPtr<Node> child = ac.GetFirst();
while (child)
{
child->Render();
child = child->GetNext();
}
// 渲染完毕后,将渲染目标恢复为默认
// 解绑FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 恢复原始的正交矩阵 和 视口
renderer->SetOrthoMatrix(Oom);
renderer->SetViewport(Oviewport);
Actor::OnUpdate(deltaTime);
}
// void AnimationMap::SetVisible(bool visible)
// {
// if (this->IsVisible() == visible)
// return;
// Actor::SetVisible(visible);
// auto ac = this->GetAllChildren();
// RefPtr<Node> next;
// for (RefPtr<Node> child = ac.GetFirst(); child; child = next)
// {
// next = child->GetNext();
// child->SetVisible(visible);
// }
// }
AnimationMap::AnimationMap()
{
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "EngineFrame/Base/Actor.h"
#include "Animation.h"
class AnimationMap : public Actor
{
private:
/**纹理 */
RefPtr<Texture> m_texture = nullptr;
/**FBO */
GLuint m_fbo = 0;
/**大小 */
VecSize m_size;
/**原始的正交矩阵 */
glm::mat4 Oom;
/**原始的视口 */
SDL_Rect Oviewport;
public:
AnimationMap(/* args */);
~AnimationMap();
/**完成构造
* 必须调用完成构造以创建足够大小的画布和各项初始化
*/
void CompleteConstruction();
/**添加动画 */
void AddAnimation(RefPtr<Animation> animation);
/**重置动画组 */
void Reset();
void Render() override;
void OnRender() override;
void OnUpdate(float deltaTime) override;
// void SetVisible(bool visible) override;
};

View File

@@ -1,16 +1,29 @@
#include "Canvas.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Render/RenderManager.h"
Canvas::Canvas()
{
}
Canvas::Canvas(VecSize size)
{
Init(size);
}
Canvas::Canvas(int width, int height)
{
Init({width, height});
}
void Canvas::Init(VecSize size)
{
m_size = size;
m_renderRect = {0, 0, size.width, size.height};
m_rect = {0, 0, (float)size.width, (float)size.height};
SetSize(size);
// 创建指定大小的纹理
m_texture = new Texture();
m_texture->Init(VecSize(Game::GetInstance().Screen_W, Game::GetInstance().Screen_H));
Actor::Init();
m_texture->Init(m_size);
// 构造FBO
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 将目标纹理附加到FBO的颜色附着点
@@ -24,92 +37,86 @@ Canvas::Canvas(VecSize size)
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
}
void Canvas::PreRender()
{
m_rect.x = GetWorldPos().x;
m_rect.y = GetWorldPos().y;
}
void Canvas::Render()
void Canvas::BeginDraw()
{
RenderManager *renderer = Game::GetInstance().GetRenderer();
SDL_FPoint AnchorPos = {0, 0};
if (m_dirty)
{
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
m_dirty = false;
}
// 绑定FBO
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 清屏
glClear(GL_COLOR_BUFFER_BIT);
// 保存原始的正交矩阵 设置纹理对应的正交矩阵 和 视口
Oom = renderer->GetOrthoMatrix();
renderer->SetOrthoMatrix(glm::ortho(0.0f, (float)m_size.width, 0.0f, (float)m_size.height, -1.0f, 1.0f));
Oviewport = renderer->GetViewport();
renderer->SetViewport({0, 0, m_size.width, m_size.height});
renderer->SetCurrentShaderProgram("flip_y");
// 混合
if (this->_BlendMode != NONE)
Blend();
renderer->DrawTexture(m_texture, &m_renderRect, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
// 还原混合
if (this->_BlendMode != NONE)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderer->SetCurrentShaderProgram("normal");
}
void Canvas::DrawImg(std::string img, int index, Vec2 pos)
void Canvas::EndDraw()
{
m_dirty = true;
ImgKey key = {img, index};
DrawInfo info;
info.rect.x = pos.x;
info.rect.y = pos.y;
info.texture = key;
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(img, index);
m_imgMap[key] = tex;
}
info.rect.w = m_imgMap[key]->getSize().width;
info.rect.h = m_imgMap[key]->getSize().height;
m_drawQueue.push_back(info);
RenderManager *renderer = Game::GetInstance().GetRenderer();
// 解绑FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 恢复原始的正交矩阵 和 视口
renderer->SetOrthoMatrix(Oom);
renderer->SetViewport(Oviewport);
}
void Canvas::DrawImg(std::string img, int index, SDL_FRect rect)
void Canvas::DrawActor(RefPtr<Actor> actor)
{
m_dirty = true;
ImgKey key = {img, index};
DrawInfo info;
info.rect = rect;
info.texture = key;
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(img, index);
m_imgMap[key] = tex;
}
m_drawQueue.push_back(info);
// 计算矩阵
actor->PreRender();
// 设定矩阵并渲染(Render中会调用OnRender)
actor->Render();
}
void Canvas::Clear()
{
m_drawQueue.clear();
m_dirty = true;
m_texture = new Texture();
m_texture->Init(m_size);
}
void Canvas::Blend()
void Canvas::OnRender()
{
switch (this->_BlendMode)
if (!m_texture || !IsVisible())
return;
RenderManager *renderer = Game::GetInstance().GetRenderer();
if (this->_BlendMode != NONE)
{
case LINEARDODGE:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
break;
renderer->SetBlendMode(this->_BlendMode);
}
renderer->DrawTexture(m_texture);
if (this->_BlendMode != NONE)
{
renderer->SetBlendMode(NONE);
}
}
// void Canvas::Render()
// {
// RenderManager *renderer = Game::GetInstance().GetRenderer();
// SDL_FPoint AnchorPos = {0, 0};
// if (m_dirty)
// {
// 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
// m_dirty = false;
// }
// renderer->SetCurrentShaderProgram("flip_y");
// // 混合
// if (this->_BlendMode != NONE)
// Blend();
// renderer->DrawTexture(m_texture, &m_renderRect, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
// // 还原混合
// if (this->_BlendMode != NONE)
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// renderer->SetCurrentShaderProgram("normal");
// }

View File

@@ -18,37 +18,37 @@ class Canvas : public Actor
return index < other.index; // 字符串相同则比较index
}
};
struct DrawInfo
{
ImgKey texture;
SDL_FRect rect = {0, 0, 0, 0};
};
private:
/**纹理 */
RefPtr<Texture> m_texture = nullptr;
/**大小 */
VecSize m_size;
/**渲染大小 */
SDL_Rect m_renderRect;
SDL_FRect m_rect;
/**脏标记 */
bool m_dirty = true;
/**FBO */
GLuint m_fbo = 0;
/**绘制纹理集 */
std::map<ImgKey, RefPtr<Texture>> m_imgMap;
/**绘制队列 */
std::vector<DrawInfo> m_drawQueue;
/**原始的正交矩阵 */
glm::mat4 Oom;
/**原始的视口 */
SDL_Rect Oviewport;
public:
Canvas();
Canvas(VecSize size);
Canvas(int width, int height);
void PreRender() override;
void Render() override;
void Blend();
/**初始化 */
void Init(VecSize size);
void DrawImg(std::string img, int index, Vec2 pos);
void DrawImg(std::string img, int index, SDL_FRect rect);
/**开始绘制 */
void BeginDraw();
/**结束绘制 */
void EndDraw();
/**绘制角色 */
void DrawActor(RefPtr<Actor> actor);
/**清空画布 */
void Clear();
/**重载OnRender函数 */
void OnRender() override;
};

View File

@@ -20,7 +20,7 @@ private:
// 数字字符纹理缓存('0'-'9'和'-'
std::unordered_map<char, RefPtr<Texture>> m_digitTextures;
// 当前数字的字符精灵列表
std::vector<Sprite *> m_digitSprites;
std::vector<Sprite *> m_digitSprites;
// 预加载0-9和负号的纹理
void PreloadDigits();

View File

@@ -1,63 +0,0 @@
#include "RenderBase.h"
#include "EngineFrame/Base/Actor.h"
void RenderBase::CalcRenderInfo()
{
this->CalcRenderInfoFlag = true;
}
void RenderBase::Init()
{
// 计算渲染信息
CalcRenderInfo();
}
void RenderBase::SetIterationPos(Vec2 pos)
{
Actor::SetIterationPos(pos);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetIterationScale(Vec2 scale)
{
Actor::SetIterationScale(scale);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetIterationRotation(float angle)
{
if (!Visible)
return;
Actor::SetIterationRotation(angle);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetPos(Vec2 pos)
{
Actor::SetPos(pos);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetScale(Vec2 scale)
{
Actor::SetScale(scale);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetRotation(float angle)
{
Actor::SetRotation(angle);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetAnchor(Vec2 anchor)
{
Actor::SetAnchor(anchor);
CalcRenderInfo(); // 更新渲染信息
}

View File

@@ -1,45 +0,0 @@
#pragma once
#include "EngineFrame/Base/Actor.h"
class RenderBase : public Actor
{
public:
struct RenderGuidanceInfo
{
SDL_FRect rect;
// 旋转角度
float rotation;
// 翻转Flag
SDL_RendererFlip flip = SDL_FLIP_NONE;
// 锚点坐标
Vec2 AnchorPos;
// 是否显示
bool Visible = true;
// 是否在屏幕内
bool IsInScreen = false;
};
public:
void Init() override;
public:
// 设置迭代的坐标
void SetIterationPos(Vec2 pos) override;
// 设置迭代的缩放
void SetIterationScale(Vec2 scale) override;
// 设置迭代的旋转角度
void SetIterationRotation(float angle) override;
// 设置坐标
void SetPos(Vec2 pos) override;
// 设置缩放
void SetScale(Vec2 scale) override;
// 设置旋转角度
void SetRotation(float angle) override;
// 设置中心点
void SetAnchor(Vec2 anchor) override;
// 计算渲染信息
void CalcRenderInfo() override;
};

View File

@@ -3,17 +3,31 @@
#include "Text.h"
#include "EngineFrame/Render/RenderManager.h"
void Sprite::GenerateRenderMatrix() const
{
Matrix3x2 RenderBuffer = Matrix3x2::Translation(glm::vec2(m_texture->getPos().x, m_texture->getPos().y)) * GetTransformMatrix();
// 构造OpenGl渲染矩阵
render_matrix_ = glm::mat4(1.0f);
// 填充旋转+缩放分量2D 变换核心,对应 4x4 矩阵左上 2x2 区域)
render_matrix_[0][0] = RenderBuffer[0]; // _11 → x轴缩放+旋转
render_matrix_[0][1] = RenderBuffer[1]; // _12 → 影响y轴方向的旋转分量
render_matrix_[1][0] = RenderBuffer[2]; // _21 → 影响x轴方向的旋转分量
render_matrix_[1][1] = RenderBuffer[3]; // _22 → y轴缩放+旋转
// 填充平移分量(对应 4x4 矩阵最后一行前两列z轴平移为0
render_matrix_[3][0] = RenderBuffer[4]; // _31 → x方向平移世界坐标
render_matrix_[3][1] = RenderBuffer[5]; // _32 → y方向平移世界坐标
}
void Sprite::Init()
{
this->Size = m_texture->getSize();
RenderBase::Init();
SetSize(m_texture->getSize());
}
void Sprite::SetTexture(RefPtr<Texture> texture)
{
m_texture = texture;
Init();
CalcRenderInfoLogic(); // 第一次计算
}
Sprite::Sprite(std::string imgPath, int Index)
@@ -23,7 +37,6 @@ Sprite::Sprite(std::string imgPath, int Index)
m_texture = new Texture();
m_texture->Init(imgPath, Index);
Init();
CalcRenderInfoLogic(); // 第一次计算
}
Sprite::Sprite(std::string PngPath)
@@ -31,7 +44,6 @@ Sprite::Sprite(std::string PngPath)
m_texture = new Texture();
m_texture->Init(PngPath);
Init();
CalcRenderInfoLogic(); // 第一次计算
}
Sprite::~Sprite()
@@ -43,140 +55,19 @@ RefPtr<Texture> Sprite::GetTexture()
return m_texture;
}
void Sprite::CalcRenderInfoLogic()
void Sprite::OnRender()
{
// 获取至在最终的父对象检查是否显示
BaseNode *parentNode = this->GetParent();
while (parentNode != nullptr)
{
if (parentNode->Visible == false)
{
_RenderGuidanceInfo.Visible = false;
return;
}
parentNode = parentNode->GetParent();
}
_RenderGuidanceInfo.Visible = true;
// 计算缩放因子和翻转状态
float scaleX = transformIter.scale.x * transform.scale.x;
float scaleY = transformIter.scale.y * transform.scale.y;
// X轴和Y轴上是否翻转的标志
bool flipX = scaleX < 0;
bool flipY = scaleY < 0;
_RenderGuidanceInfo.flip = SDL_FLIP_NONE;
// 更新翻转状态
if (flipX)
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_HORIZONTAL | _RenderGuidanceInfo.flip);
if (flipY)
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip);
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
auto T_Size = m_texture->getSize();
auto T_Pos = m_texture->getPos();
float texturePosX = flipX ? -((float)T_Size.width + (float)T_Pos.x) + SDL_fabsf(transform.position.x * 2.0f) : (float)T_Pos.x;
float texturePosY = flipY ? -((float)T_Size.height + (float)T_Pos.y) + SDL_fabsf(transform.position.y * 2.0f) : (float)T_Pos.y;
// 先计算Img坐标与精灵坐标合成后的真实坐标
float RealPosX = transform.position.x + texturePosX;
float RealPosY = transform.position.y + texturePosY;
// 计算在世界中的位置
float baseX = transformIter.position.x + RealPosX;
float baseY = transformIter.position.y + RealPosY;
// 获取当前帧的原始尺寸
float frameWidth = (float)Size.width;
float frameHeight = (float)Size.height;
// 原始锚点偏移(基于帧尺寸)
float origAnchorOffsetX = frameWidth * Anchor.x;
float origAnchorOffsetY = frameHeight * Anchor.y;
// 缩放的绝对值
float absScaleX = SDL_fabsf(scaleX);
float absScaleY = SDL_fabsf(scaleY);
// 缩放后的尺寸
float scaledWidth = frameWidth * absScaleX;
float scaledHeight = frameHeight * absScaleY;
// 缩放后的锚点偏移
float scaledAnchorOffsetX = origAnchorOffsetX * absScaleX;
float scaledAnchorOffsetY = origAnchorOffsetY * absScaleY;
// 计算缩放后的锚点偏移与原锚点偏移的差值
float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
float scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY;
// 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角)
float Xpos = baseX - scaleOffsetX;
float Ypos = baseY - scaleOffsetY;
// 更新渲染信息
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
// 设置纹理透明度
m_texture->setAlpha(this->Alpha);
// 屏幕内检测
float screenWidth = (float)Game::GetInstance().Screen_W;
float screenHeight = (float)Game::GetInstance().Screen_H;
bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight);
_RenderGuidanceInfo.IsInScreen = isInScreen;
// this->Size = {scaledWidth, scaledHeight};
_RenderGuidanceInfo.rotation = transformIter.rotation + transform.rotation;
CalcRenderInfoFlag = false;
}
void Sprite::PreRender()
{
if (CalcRenderInfoFlag && Visible)
CalcRenderInfoLogic();
}
void Sprite::Render()
{
if (!Visible)
return;
if (!m_texture)
if (!m_texture || !IsVisible())
return;
RenderManager *renderer = Game::GetInstance().GetRenderer();
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
if (this->_BlendMode != NONE)
{
SDL_FPoint AnchorPos;
AnchorPos.x = _RenderGuidanceInfo.AnchorPos.x;
AnchorPos.y = _RenderGuidanceInfo.AnchorPos.y;
// 混合
if (this->_BlendMode != NONE)
Blend();
SDL_Rect srcrect = {0, 0, this->Size.width, this->Size.height};
renderer->DrawTexture(m_texture, &srcrect, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
// 还原混合
if (this->_BlendMode != NONE)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
void Sprite::Clear()
{
}
void Sprite::Blend()
{
switch (this->_BlendMode)
{
case LINEARDODGE:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
break;
renderer->SetBlendMode(this->_BlendMode);
}
renderer->DrawTexture(m_texture);
if (this->_BlendMode != NONE)
{
renderer->SetBlendMode(NONE);
}
}

View File

@@ -1,14 +1,14 @@
#pragma once
#include <string>
#include "Asset/Asset_ImagePack.h"
#include "EngineFrame/Component/RenderBase.h"
#include "EngineFrame/Render/Texture.h"
#include "EngineFrame/Base/Actor.h"
class Game;
/**
* @brief Sprite类继承自Component类用于表示游戏中的精灵组件
*/
class Sprite : public RenderBase
class Sprite : public Actor
{
protected:
RefPtr<Texture> m_texture = nullptr;
@@ -18,24 +18,18 @@ public:
Sprite(std::string imgPath, int Index);
Sprite(std::string PngPath);
~Sprite();
void Render() override;
void PreRender() override;
void Clear() override;
void Init() override;
void SetTexture(RefPtr<Texture> texture);
void SetTexture(RefPtr<Texture> texture);
RefPtr<Texture> GetTexture();
public:
// 渲染信息
RenderGuidanceInfo _RenderGuidanceInfo;
/**重载生成渲染矩阵函数 */
void GenerateRenderMatrix() const override;
/**重载初始化函数 */
void Init() override;
/**重载渲染函数 */
void OnRender() override;
public:
std::string imgPath;
int Index;
public:
// 计算渲染信息
void CalcRenderInfoLogic();
// 混合
void Blend();
};