This commit is contained in:
2025-10-06 04:18:49 +08:00
commit df2cacdb92
2784 changed files with 1280840 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
#include "Actor.h"
#include "EngineFrame/Scene/Scene.h"
#include "EngineFrame/Component/RenderBase.h"
#include <algorithm>
Actor::Actor()
{
Init();
}
void Actor::Init()
{
addTag(Tag::ACTOR);
addTag(Tag::RENDER);
addTag(Tag::TRANSFORM);
addTag(Tag::UPDATE);
}
void Actor::AddComponent(RefPtr<Component> Component)
{
BaseNode::AddChild(Component);
}
void Actor::RemoveComponent(RefPtr<Component> Component)
{
BaseNode::RemoveChild(Component);
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include "EngineFrame/Base/BaseNode.h"
#include "EngineFrame/Component/Component.h"
#include "Tool/IntrusiveList.hpp"
class Scene;
/**
* @brief Actor类继承自Actor_base类
*
* Actor类是一个基础的游戏对象类可以添加到场景中
*/
class Actor : public BaseNode
{
public:
Actor();
public:
void Init() override;
void AddComponent(RefPtr<Component> Component);
void RemoveComponent(RefPtr<Component> Component);
// void AddChild(RefPtr<Actor> child);
// void RemoveChild(RefPtr<Actor> child);
};

View File

@@ -0,0 +1,155 @@
#include "Debug_Actor.h"
#include "EngineCore/Game.h"
#include <string>
Debug_Actor::Debug_Actor()
{
m_debugFont = TTF_OpenFont("Fonts/GasinamuNew.ttf", 16);
if (m_debugFont == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load debug font: %s", TTF_GetError());
}
FPS_Text = new Text("Current FPS:", m_debugFont, SDL_Color{255, 255, 255, 255});
DT_Text = new Text("DeltaTime :", m_debugFont, SDL_Color{255, 255, 255, 255});
RC_Text = new Text("Render Calls:", m_debugFont, SDL_Color{255, 255, 255, 255});
if (FPS_Text != nullptr)
{
SDL_Point Pos{26, 26};
FPS_Text->SetPos(Pos);
this->AddComponent(FPS_Text);
}
if (DT_Text != nullptr)
{
SDL_Point Pos{26, 46};
DT_Text->SetPos(Pos);
this->AddComponent(DT_Text);
}
if (RC_Text != nullptr)
{
SDL_Point Pos{26, 66};
RC_Text->SetPos(Pos);
this->AddComponent(RC_Text);
}
}
Debug_Actor::~Debug_Actor()
{
if (m_debugFont != nullptr)
{
TTF_CloseFont(m_debugFont);
m_debugFont = nullptr;
}
}
void Debug_Actor::Update(float deltaTime)
{
Actor::Update(deltaTime);
if (FPS_Text != nullptr)
{
std::string fpsText = "Current FPS: " + std::to_string(FPS);
FPS_Text->SetText(fpsText);
std::string dtText = "DeltaTime: " + std::to_string((int)(deltaTime * 1000));
DT_Text->SetText(dtText);
std::string rcText = "Render Calls: " + std::to_string(RenderCount);
RC_Text->SetText(rcText);
}
}
void Debug_Actor::Render()
{
if (FPS_Text != nullptr)
{
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
if (renderer != nullptr)
{
SDL_Point textPos = FPS_Text->Pos;
SDL_Point textSize = FPS_Text->Size;
int bgX = textPos.x - padding;
int bgY = textPos.y - padding;
int bgWidth = textSize.x + padding * 2;
int bgHeight = textSize.y + padding * 2 * 4;
DrawRoundedRect(renderer, bgX, bgY, bgWidth, bgHeight, cornerRadius, bgColor);
}
}
Actor::Render();
}
void Debug_Actor::DrawRoundedRect(SDL_Renderer *renderer, int x, int y, int w, int h, int radius, SDL_Color color)
{
if (renderer == nullptr)
return;
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawLine(renderer, x + radius, y, x + w - radius, y);
SDL_RenderDrawLine(renderer, x + radius, y + h, x + w - radius, y + h);
SDL_RenderDrawLine(renderer, x, y + radius, x, y + h - radius);
SDL_RenderDrawLine(renderer, x + w, y + radius, x + w, y + h - radius);
const int segments = 16;
for (int i = 0; i < segments; i++)
{
float t1 = static_cast<float>(i) / segments;
float t2 = static_cast<float>(i + 1) / segments;
float angle1 = M_PI * (1.0f - t1);
float angle2 = M_PI * (1.0f - t2);
SDL_RenderDrawLineF(
renderer,
x + radius + cos(angle1) * radius, y + radius + sin(angle1) * radius,
x + radius + cos(angle2) * radius, y + radius + sin(angle2) * radius);
angle1 = 2 * M_PI - t1 * M_PI_2;
angle2 = 2 * M_PI - t2 * M_PI_2;
SDL_RenderDrawLineF(
renderer,
x + w - radius + cos(angle1) * radius, y + radius + sin(angle1) * radius,
x + w - radius + cos(angle2) * radius, y + radius + sin(angle2) * radius);
angle1 = t1 * M_PI_2;
angle2 = t2 * M_PI_2;
SDL_RenderDrawLineF(
renderer,
x + w - radius + cos(angle1) * radius, y + h - radius + sin(angle1) * radius,
x + w - radius + cos(angle2) * radius, y + h - radius + sin(angle2) * radius);
angle1 = M_PI_2 + t1 * M_PI_2;
angle2 = M_PI_2 + t2 * M_PI_2;
SDL_RenderDrawLineF(
renderer,
x + radius + cos(angle1) * radius, y + h - radius + sin(angle1) * radius,
x + radius + cos(angle2) * radius, y + h - radius + sin(angle2) * radius);
}
for (int dy = 0; dy < h; dy++)
{
int leftIndent = 0;
int rightIndent = 0;
if (dy < radius)
{
float ratio = 1.0f - static_cast<float>(dy) / radius;
leftIndent = rightIndent = static_cast<int>(radius * (1.0f - sqrt(1.0f - ratio * ratio)));
}
else if (dy > h - radius)
{
float ratio = static_cast<float>(dy - (h - radius)) / radius;
leftIndent = rightIndent = static_cast<int>(radius * (1.0f - sqrt(1.0f - ratio * ratio)));
}
SDL_RenderDrawLine(
renderer,
x + leftIndent, y + dy,
x + w - rightIndent, y + dy);
}
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
#include "EngineFrame/Component/Text.h"
#include <SDL_ttf.h>
#include <cstdint>
class Debug_Actor : public Actor
{
private:
TTF_Font *m_debugFont;
RefPtr<Text> FPS_Text;
RefPtr<Text> DT_Text;
RefPtr<Text> RC_Text;
public:
Debug_Actor();
~Debug_Actor() override;
void Update(float deltaTime) override;
void Render() override;
uint32_t FPS = 0;
uint32_t RenderCount = 0;
SDL_Color bgColor = {0, 0, 0, 90};
int cornerRadius = 4;
int padding = 12;
#ifdef __SWITCH__
double M_PI = 3.14159265358979323846;
double M_PI_2 = 1.57079632679489661923;
#endif
private:
void DrawRoundedRect(SDL_Renderer *renderer, int x, int y, int w, int h, int radius, SDL_Color color);
};

View File

@@ -0,0 +1,303 @@
#include "BaseNode.h"
void BaseNode::Init()
{
}
void BaseNode::HandleEvents(SDL_Event *e)
{
// 如果有子节点并含有事件标签,则处理事件
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
{
if (child->hasTag(Tag::ACTOR) || child->hasTag(Tag::HANDEL_EVENT))
child->HandleEvents(e);
child = child->GetNext();
}
}
void BaseNode::Update(float deltaTime)
{
// 如果有回调函数,则调用回调函数
if (cb_update_)
{
cb_update_(deltaTime);
}
// 如果有子节点并含有刷新标签,则更新子节点
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
{
if (child->hasTag(Tag::UPDATE))
child->Update(deltaTime);
child = child->GetNext();
}
}
void BaseNode::Render()
{
// 如果有子节点并含有渲染标签,则渲染子节点
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
{
if (child->hasTag(Tag::RENDER))
child->Render();
child = child->GetNext();
}
}
void BaseNode::Clear()
{
}
void BaseNode::SetCallbackOnUpdate(const UpdateCallback &cb)
{
cb_update_ = cb;
}
void BaseNode::SetChildIterationTransform()
{
TransformT n_transform;
n_transform.position = transform.position + transformIter.position;
n_transform.scale = transform.scale * transformIter.scale;
n_transform.rotation = transform.rotation + transformIter.rotation;
// 如果有子节点并含有transform标签则设置其位置
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
{
if (child->hasTag(Tag::TRANSFORM))
child->SetIterationTransform(n_transform);
child = child->GetNext();
}
}
void BaseNode::CalcRenderInfo()
{
}
void BaseNode::SetName(std::string name)
{
m_Name = name;
}
std::string BaseNode::GetName()
{
return m_Name;
}
int BaseNode::GetRenderZOrder()
{
return m_RenderZOrder;
}
void BaseNode::SetRenderZOrder(int zOrder)
{
m_RenderZOrder = zOrder;
}
void BaseNode::Reorder()
{
if (m_Parent)
{
RefPtr<BaseNode> me = this;
m_Parent->m_BaseNodes.Remove(me);
RefPtr<BaseNode> sibling = m_Parent->m_BaseNodes.GetLast();
if (sibling && sibling->GetRenderZOrder() > m_RenderZOrder)
{
sibling = sibling->GetPrev();
while (sibling)
{
if (sibling->GetRenderZOrder() <= m_RenderZOrder)
break;
sibling = sibling->GetPrev();
}
}
if (sibling)
{
m_Parent->m_BaseNodes.InsertAfter(me, sibling);
}
else
{
m_Parent->m_BaseNodes.PushFront(me);
}
}
}
void BaseNode::AddChild(RefPtr<BaseNode> child)
{
m_BaseNodes.PushBack(child);
child->OnAdded(this);
// 如果是需要渲染的子对象
if (child->hasTag(Tag::RENDER))
{
// 重新排序
child->Reorder();
// 如果组件有transform标签则设置其位置
if (child->hasTag(Tag::TRANSFORM))
{
TransformT n_transform;
n_transform.position = transform.position + transformIter.position;
n_transform.scale = transform.scale * transformIter.scale;
n_transform.rotation = transform.rotation + transformIter.rotation;
child->SetIterationTransform(n_transform);
}
}
}
void BaseNode::RemoveChild(RefPtr<BaseNode> child)
{
child->m_Parent = nullptr;
m_BaseNodes.Remove(child);
}
void BaseNode::OnAdded(BaseNode *node)
{
m_Parent = node;
}
void BaseNode::SetIterationTransform(TransformT n_transform)
{
if (n_transform == transformIter)
return;
transformIter = n_transform;
CalcRenderInfo();
SetChildIterationTransform();
}
TransformT BaseNode::GetIterationTransform()
{
return transformIter;
}
void BaseNode::SetTransform(TransformT n_transform)
{
if (n_transform == transform)
return;
transform = n_transform;
CalcRenderInfo();
SetChildIterationTransform();
}
TransformT BaseNode::GetTransform()
{
return transform;
}
void BaseNode::SetPos(VecFPos pos)
{
if (pos == this->transform.position)
return;
this->transform.position = pos;
CalcRenderInfo();
SetChildIterationTransform();
}
VecFPos BaseNode::GetPos()
{
return this->transform.position;
}
void BaseNode::SetScale(VecFPos scale)
{
if (scale == this->transform.scale)
return;
this->transform.scale = scale;
CalcRenderInfo();
SetChildIterationTransform();
}
VecFPos BaseNode::GetScale()
{
return this->transform.scale;
}
void BaseNode::SetRotation(float angle)
{
if (angle == this->transform.rotation)
return;
this->transform.rotation = angle;
CalcRenderInfo();
SetChildIterationTransform();
}
float BaseNode::GetRotation()
{
return this->transform.rotation;
}
void BaseNode::SetAnchor(VecFPos anchor)
{
if (anchor == this->Anchor)
return;
Anchor.x = anchor.x;
Anchor.y = anchor.y;
}
VecFPos BaseNode::GetAnchor()
{
VecFPos P;
P.x = Anchor.x;
P.y = Anchor.y;
return P;
}
void BaseNode::SetSize(VecSize size)
{
this->Size = size;
}
VecSize BaseNode::GetSize()
{
return this->Size;
}
void BaseNode::SetVisible(bool visible)
{
this->Visible = visible;
}
bool BaseNode::GetVisible()
{
return this->Visible;
}
void BaseNode::SetIterationPos(VecFPos pos)
{
if (pos == this->transformIter.position)
return;
this->transformIter.position = pos;
CalcRenderInfo();
SetChildIterationTransform();
}
VecFPos BaseNode::GetIterationPos()
{
return this->transformIter.position;
}
void BaseNode::SetIterationScale(VecFPos scale)
{
if (scale == this->transformIter.scale)
return;
this->transformIter.scale = scale;
CalcRenderInfo();
SetChildIterationTransform();
}
VecFPos BaseNode::GetIterationScale()
{
return this->transformIter.scale;
}
void BaseNode::SetIterationRotation(float angle)
{
if (angle == this->transformIter.rotation)
return;
this->transformIter.rotation = angle;
CalcRenderInfo();
SetChildIterationTransform();
}
float BaseNode::GetIterationRotation()
{
return this->transformIter.rotation;
}

View File

@@ -0,0 +1,124 @@
#pragma once
#include <functional>
#include <SDL.h>
#include <string>
#include "Tool/RefObject.h"
#include "Tool/RefPtr.h"
#include "Tool/IntrusiveList.hpp"
#include "Tool/TagGed.h"
#include "Tool/TransformT.h"
class BaseNode : public RefObject, public TagGed, protected IntrusiveListValue<RefPtr<BaseNode>>
{
public:
typedef std::function<void(float deltaTime)> UpdateCallback;
using IntrusiveListValue<RefPtr<BaseNode>>::GetNext;
using IntrusiveListValue<RefPtr<BaseNode>>::GetPrev;
public:
// 更新时的回调函数
UpdateCallback cb_update_;
// 节点名称
std::string m_Name;
// 子节点列表
IntrusiveList<RefPtr<BaseNode>> m_BaseNodes;
// 指向父对象的指针
BaseNode *m_Parent = nullptr;
// 渲染层级
int m_RenderZOrder = 0;
// 二维仿射变换
TransformT transform;
// 迭代的二维仿射变换
TransformT transformIter;
// 锚点
VecFPos Anchor = {0.f, 0.f};
// 大小
VecSize Size = {0, 0};
// 是否显示
bool Visible = true;
// 计算渲染信息Flag (为了保证每帧只计算一次)
bool CalcRenderInfoFlag = true;
public:
BaseNode(/* args */) = default;
~BaseNode() = default;
public:
virtual void Init();
virtual void HandleEvents(SDL_Event *e);
virtual void Update(float deltaTime);
virtual void Render();
virtual void Clear();
/// \~chinese
/// @brief 设置更新时的回调函数
void SetCallbackOnUpdate(const UpdateCallback &cb);
void SetChildIterationTransform();
// 计算渲染信息
virtual void CalcRenderInfo();
// 设置名字
void SetName(std::string name);
// 获取名字
std::string GetName();
// 设置渲染层级
int GetRenderZOrder();
// 获取渲染层级
void SetRenderZOrder(int zOrder);
// 重新排序
void Reorder();
// 添加子对象
virtual void AddChild(RefPtr<BaseNode> child);
// 移除子对象
void RemoveChild(RefPtr<BaseNode> child);
// 被添加时
virtual void OnAdded(BaseNode *node);
// 设置迭代的二维仿射变换
void SetIterationTransform(TransformT transform);
// 获取迭代的二维仿射变换
TransformT GetIterationTransform();
// 设置二维仿射变换
void SetTransform(TransformT transform);
// 获取二维仿射变换
TransformT GetTransform();
// 设置迭代的坐标
virtual void SetIterationPos(VecFPos pos);
// 获取迭代的坐标
VecFPos GetIterationPos();
// 设置迭代的缩放
virtual void SetIterationScale(VecFPos scale);
// 获取迭代的缩放
VecFPos GetIterationScale();
// 设置迭代的旋转角度
virtual void SetIterationRotation(float angle);
// 获取迭代的旋转角度
float GetIterationRotation();
// 设置坐标
virtual void SetPos(VecFPos pos);
// 获取坐标
VecFPos GetPos();
// 设置缩放
virtual void SetScale(VecFPos scale);
// 获取缩放
VecFPos GetScale();
// 设置旋转角度
virtual void SetRotation(float angle);
// 获取旋转角度
float GetRotation();
// 设置中心点
virtual void SetAnchor(VecFPos anchor);
// 获取中心点
VecFPos GetAnchor();
// 设置大小
virtual void SetSize(VecSize size);
// 获取大小
VecSize GetSize();
// 设置是否显示
void SetVisible(bool visible);
// 获取是否显示
bool GetVisible();
};

View File

@@ -0,0 +1,309 @@
#include "Animation.h"
#include "Asset/AssetManager.h"
#include "Asset/Asset_Script.h"
#include "Tool/Math.h"
#include "EngineFrame/Actor/Actor.h"
Animation::Animation()
{
}
Animation::Animation(std::string AniPath)
{
Init(AniPath);
}
Animation::Animation(std::string AniPath, std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions, Animation::ReplaceData data)
{
this->AdditionalOptions = AdditionalOptions;
this->AdditionalOptionsData = data;
Init(AniPath);
}
Animation::~Animation()
{
}
void Animation::Init(std::string AniPath)
{
Actor::Init();
AniScriptParser::AniInfo Info = AssetManager::GetInstance().StructAniInfo(AniPath);
this->AniPath = AniPath;
this->AnimationFlag = Info.Flag;
this->FrameArr = Info.Frame;
for (size_t i = 0; i < this->FrameArr.size(); i++)
{
AniScriptParser::AniFrame FrameObj = this->FrameArr[i];
RefPtr<Sprite> SpriteObj = nullptr;
if (!FrameObj.Img_Path.empty())
{
if (AdditionalOptions)
{
FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path, this->AdditionalOptionsData);
}
SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index);
SpriteObj->SetAnchor(VecFPos(0.5f, 0.5f));
SpriteObj->SetPos(VecFPos(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);
AddChild(SpriteObj);
}
// 初始化完毕 如果是第一次初始化 而非重新构造 设置大小为第0帧大小否则天空 地板等依靠大小的初始化会有问题
if (CurrentIndexT == 0)
SetSize(SpriteArr[0]->GetSize());
// 记录总帧数
TotalFrameIndex = FrameArr.size();
// TODO 染色
// 判断是否有Als
if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
{
AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
if (Info.AniList.size() > 0)
{
std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
for (auto &Ani : Info.AniList)
{
RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
AddChild(AlsAniObj);
}
}
}
FlushFrame(0);
}
void Animation::HandleEvents(SDL_Event *e)
{
}
void Animation::Update(float deltaTime)
{
// 可用性检查
if (IsUsability && Visible)
{
float dt_ms = deltaTime * 1000.0f;
// 累加当前帧时间
CurrentIndexT += dt_ms;
// 插值模式判断
InterpolationLogic();
// 循环处理:只要当前时间超过帧延迟,就切换帧(支持一次跳过多帧)
while (CurrentIndexT >= NextFrameDelay)
{
CurrentIndexT -= NextFrameDelay;
// 如果当前帧小于总帧数就切换
if (CurrentFrameIndex < (TotalFrameIndex - 1))
{
FlushFrame(CurrentFrameIndex + 1);
}
// 说明播放完毕了
else
{
// 如果有循环
if (AnimationFlag.count("LOOP"))
{
FlushFrame(0);
}
// 没有循环触发状态机回调
else
{
// 将不再可用
IsUsability = false;
if (EndCallback)
EndCallback();
break;
}
}
}
Actor::Update(deltaTime);
}
}
void Animation::Render()
{
if (!Visible)
return;
Actor::Render();
}
void Animation::OnAdded(BaseNode *node)
{
Actor::OnAdded(node);
FlushFrame(0);
}
void Animation::Clear()
{
}
void Animation::FlushFrame(int Index)
{
// 关闭旧帧显示
if (CurrentFrame)
CurrentFrame->SetVisible(false);
// 同步当前帧编号
CurrentFrameIndex = Index;
// 当前帧更换为本帧
CurrentFrame = SpriteArr[CurrentFrameIndex];
// 开启新帧显示
CurrentFrame->SetVisible(true);
// 如果是整体染色 则直接使用染色帧
// if (DyeAllFlag) CurrentFrame = DyeFrameList[CurrentFrameIndex];
AniScriptParser::AniFrame FrameInfo = FrameArr[CurrentFrameIndex];
// 设置下帧延迟
NextFrameDelay = FrameInfo.Delay;
std::unordered_map<std::string, AniScriptParser::AniFlag> FlagBuf = FrameInfo.Flag;
// 关键帧
if (FlagBuf.count("SET_FLAG"))
{
if (ChangeFrameCallback)
ChangeFrameCallback(std::get<int>(FlagBuf["SET_FLAG"]));
}
// 播放音效
if (FlagBuf.count("PLAY_SOUND"))
{
// TODO 还没有做音效的播放
}
// 缩放
if (FlagBuf.count("IMAGE_RATE"))
{
VecFPos Rate = std::get<VecFPos>(FlagBuf["IMAGE_RATE"]);
CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f});
CurrentFrame->SetScale(VecFPos{Rate.x, Rate.y});
}
// 线性减淡
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
{
CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD);
}
// 旋转
if (FlagBuf.count("IMAGE_ROTATE"))
{
CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f});
CurrentFrame->SetRotation(std::get<float>(FlagBuf["IMAGE_ROTATE"]));
}
// 染色
// if (!DyeAllFlag)
// 插值模式
if (FlagBuf.count("INTERPOLATION"))
{
// 初始化插值数据
if (InterpolationFlag.size() == 0)
{
// 旧插值数据
InterpolationFlag.push_back(FrameArr[CurrentFrameIndex]);
// 新插值数据
InterpolationFlag.push_back(FrameArr[CurrentFrameIndex + 1]);
}
}
else
{
if (InterpolationFlag.size() > 0)
{
InterpolationFlag.clear();
}
}
// 如果有描边
if (IsOutline)
{
}
// Ani的大小同步为精灵帧对象的大小
SetSize(CurrentFrame->GetSize());
// 裁切 //TODO
}
void Animation::Reset()
{
IsUsability = true;
CurrentIndexT = 0;
FlushFrame(0);
}
AniScriptParser::AniFrame Animation::GetCurrentFrameInfo()
{
return FrameArr[CurrentFrameIndex];
}
void Animation::SetFrameIndex(int Index)
{
FlushFrame(Index);
CurrentIndexT = 0;
}
void Animation::InterpolationLogic()
{
if (InterpolationFlag.size() == 0)
return;
// 插值倍率
float InterRate = Math::getUniformVelocity(0, 100, CurrentIndexT, NextFrameDelay) / 100.0f;
AniScriptParser::AniFrame OldData = InterpolationFlag[0];
AniScriptParser::AniFrame NewData = InterpolationFlag[1];
// RGBA插值
{
std::vector<int> OldRgbaData = {255, 255, 255, 250};
std::vector<int> NewRgbaData = {255, 255, 255, 250};
if (OldData.Flag.count("RGBA"))
OldRgbaData = std::get<std::vector<int>>(OldData.Flag["RGBA"]);
if (NewData.Flag.count("RGBA"))
NewRgbaData = std::get<std::vector<int>>(NewData.Flag["RGBA"]);
std::vector<int> RgbaData = {
(int)(OldRgbaData[0] + (NewRgbaData[0] - OldRgbaData[0]) * InterRate),
(int)(OldRgbaData[1] + (NewRgbaData[1] - OldRgbaData[1]) * InterRate),
(int)(OldRgbaData[2] + (NewRgbaData[2] - OldRgbaData[2]) * InterRate),
(int)(OldRgbaData[3] + (NewRgbaData[3] - OldRgbaData[3]) * InterRate)};
// TODO 染色 和 透明度还没弄
}
// 坐标
{
VecFPos 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);
}
// 缩放
{
VecFPos OldRateData = {1.0f, 1.0f};
VecFPos NewRateData = {1.0f, 1.0f};
if (OldData.Flag.count("IMAGE_RATE"))
{
OldRateData = std::get<VecFPos>(OldData.Flag["IMAGE_RATE"]);
}
if (NewData.Flag.count("IMAGE_RATE"))
{
NewRateData = std::get<VecFPos>(NewData.Flag["IMAGE_RATE"]);
}
VecFPos RateData = {
OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate,
OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate};
CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f});
CurrentFrame->SetScale(RateData);
}
// 旋转
{
float OldAngleData = 0.0;
float NewAngleData = 0.0;
if (OldData.Flag.count("IMAGE_ROTATE"))
{
OldAngleData = std::get<float>(OldData.Flag["IMAGE_ROTATE"]);
}
if (NewData.Flag.count("IMAGE_ROTATE"))
{
NewAngleData = std::get<float>(NewData.Flag["IMAGE_ROTATE"]);
}
CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
}
}

View File

@@ -0,0 +1,95 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
#include "EngineFrame/Component/Sprite.h"
#include "Asset/AnimationStruct.h"
#include <functional>
#include <tuple>
#include <utility>
class Animation : public Actor
{
public:
struct ReplaceData
{
int Param1;
int Param2;
ReplaceData() : Param1(0), Param2(0) {}
ReplaceData(int _Param1, int _Param2) : Param1(_Param1), Param2(_Param2) {}
};
public:
Animation(/* args */);
Animation(std::string AniPath);
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;
public:
void FlushFrame(int Index);
void Reset();
AniScriptParser::AniFrame GetCurrentFrameInfo();
void SetFrameIndex(int Index);
void InterpolationLogic();
// TODO SetOutline
// TODO SetDye
// TODO SetCrop
public:
// Ani是否可用
bool IsUsability = true;
// 当前帧数
int CurrentFrameIndex = 0;
// 总帧数
int TotalFrameIndex = 0;
// 当前帧时间
float CurrentIndexT = 0;
// 当前帧
RefPtr<Sprite> CurrentFrame = nullptr;
// 下帧延迟
float NextFrameDelay = 9999999;
// 染色Flag
bool DyeingFlag = false;
// 插值模式
std::vector<AniScriptParser::AniFrame> InterpolationFlag;
// 关键帧回调
std::function<void(int)> ChangeFrameCallback;
// 结束回调
std::function<void()> EndCallback;
// Ani的标签
std::unordered_map<std::string, AniScriptParser::AniFlag> AnimationFlag;
// 帧对象数组
std::vector<AniScriptParser::AniFrame> FrameArr;
// 图片精灵帧对象
std::vector<RefPtr<Sprite>> SpriteArr;
// Ani类型
std::string Type = "normal";
// Ani路径
std::string AniPath;
// 是否描边
bool IsOutline = false;
// // 描边颜色
// OutlineColor = null;
// // 描边对象List
// OutlineList = null;
// // 当前描边对象
// CurrentOutline = null;
// // 染色颜色
// DyeColor = null;
// // 染色帧List
// DyeFrameList = null;
// // 整体染色
// DyeAllFlag = false;
// // 裁切数据
// CropRect = null;
// 附加选项
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
Animation::ReplaceData AdditionalOptionsData;
};

View File

@@ -0,0 +1,7 @@
#include "Component.h"
#include "EngineFrame/Actor/Actor.h"
void Component::Init()
{
addTag(Tag::COMPONENT);
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "EngineFrame/Base/BaseNode.h"
#include <SDL.h>
class Actor;
class Component : public BaseNode
{
public:
void Init() override;
};

View File

@@ -0,0 +1,86 @@
#include "RenderBase.h"
#include "EngineFrame/Actor/Actor.h"
RenderBase::RenderBase()
{
}
RenderBase::~RenderBase()
{
}
void RenderBase::CalcRenderInfo()
{
this->CalcRenderInfoFlag = true;
}
void RenderBase::Init()
{
Component::Init();
// 标记该组件需要渲染和更新
addTag(Tag::RENDER);
addTag(Tag::UPDATE);
addTag(Tag::TRANSFORM);
// 计算渲染信息
CalcRenderInfo();
}
void RenderBase::Update(float deltaTime)
{
if (!Visible)
return;
Component::Update(deltaTime);
}
void RenderBase::Render()
{
if (!Visible)
return;
Component::Render();
}
void RenderBase::SetIterationPos(VecFPos pos)
{
Component::SetIterationPos(pos);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetIterationScale(VecFPos scale)
{
Component::SetIterationScale(scale);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetIterationRotation(float angle)
{
if (!Visible)
return;
Component::SetIterationRotation(angle);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetPos(VecFPos pos)
{
Component::SetPos(pos);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetScale(VecFPos scale)
{
Component::SetScale(scale);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetRotation(float angle)
{
Component::SetRotation(angle);
CalcRenderInfo(); // 更新渲染信息
}
void RenderBase::SetAnchor(VecFPos anchor)
{
Component::SetAnchor(anchor);
CalcRenderInfo(); // 更新渲染信息
}

View File

@@ -0,0 +1,50 @@
#pragma once
#include "EngineFrame/Component/Component.h"
#include "Tool/TransformT.h"
class RenderBase : public Component
{
public:
struct RenderGuidanceInfo
{
SDL_Rect rect;
float rotation;
SDL_RendererFlip flip = SDL_FLIP_NONE;
VecPos AnchorPos;
bool Visible = true;
bool IsInScreen;
};
public:
RenderBase(/* args */);
~RenderBase();
public:
void Init() override;
void Update(float deltaTime) override;
void Render() override;
public:
public:
// 设置迭代的坐标
void SetIterationPos(VecFPos pos) override;
// 设置迭代的缩放
void SetIterationScale(VecFPos scale) override;
// 设置迭代的旋转角度
void SetIterationRotation(float angle) override;
// 设置坐标
void SetPos(VecFPos pos) override;
// 设置缩放
void SetScale(VecFPos scale) override;
// 设置旋转角度
void SetRotation(float angle) override;
// 设置中心点
void SetAnchor(VecFPos anchor) override;
// 计算渲染信息
void CalcRenderInfo() override;
};

View File

@@ -0,0 +1,159 @@
#include "Sprite.h"
#include "EngineCore/Game.h"
#include "Text.h"
Sprite::Sprite()
{
}
Sprite::Sprite(std::string imgPath, int Index)
{
this->imgPath = imgPath;
this->Index = Index;
m_texture = new Texture(imgPath, Index);
Init();
CalcRenderInfoLogic(); // 第一次计算
}
Sprite::Sprite(std::string PngPath)
{
m_texture = new Texture(PngPath);
Init();
CalcRenderInfoLogic(); // 第一次计算
}
Sprite::~Sprite()
{
}
RefPtr<Texture> Sprite::GetTexture()
{
return m_texture;
}
void Sprite::SetIterationPos(VecFPos pos)
{
RenderBase::SetIterationPos(pos);
CalcRenderInfo();
}
void Sprite::HandleEvents(SDL_Event *e)
{
}
void Sprite::Update(float deltaTime)
{
if (CalcRenderInfoFlag && Visible)
CalcRenderInfoLogic();
}
void Sprite::CalcRenderInfoLogic()
{
// 计算缩放因子和翻转状态
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);
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
int texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x;
int texturePosY = flipY ? -(m_texture->TextureSize.height + m_texture->TexturePos.y) + SDL_abs(transform.position.y * 2) : m_texture->TexturePos.y;
// 先计算Img坐标与精灵坐标合成后的真实坐标
int RealPosX = transform.position.x + texturePosX;
int RealPosY = transform.position.y + texturePosY;
// 计算在世界中的位置
int baseX = transformIter.position.x + RealPosX;
int baseY = transformIter.position.y + RealPosY;
// 获取当前帧的原始尺寸
int frameWidth = m_texture->TextureSize.width;
int frameHeight = m_texture->TextureSize.height;
// 原始锚点偏移(基于帧尺寸)
int origAnchorOffsetX = static_cast<int>(frameWidth * Anchor.x);
int origAnchorOffsetY = static_cast<int>(frameHeight * Anchor.y);
// 缩放的绝对值
float absScaleX = SDL_abs(scaleX);
float absScaleY = SDL_abs(scaleY);
// 缩放后的尺寸
int scaledWidth = static_cast<int>(frameWidth * absScaleX);
int scaledHeight = static_cast<int>(frameHeight * absScaleY);
// 缩放后的锚点偏移
int scaledAnchorOffsetX = static_cast<int>(origAnchorOffsetX * absScaleX);
int scaledAnchorOffsetY = static_cast<int>(origAnchorOffsetY * absScaleY);
// 计算缩放后的锚点偏移与原锚点偏移的差值
int scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
int scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY;
// 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角)
int Xpos = baseX + scaleOffsetX;
int Ypos = baseY + scaleOffsetY;
// 更新渲染信息
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
// 屏幕内检测
int screenWidth = Game::GetInstance().Screen_W;
int screenHeight = 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::Render()
{
if (!Visible)
return;
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
if (!m_texture)
return;
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
{
if (_RenderGuidanceInfo.rotation != 0.f || _RenderGuidanceInfo.flip != SDL_FLIP_NONE)
{
SDL_Point AnchorPos = _RenderGuidanceInfo.AnchorPos;
SDL_RenderCopyEx(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
}
else
{
SDL_RenderCopy(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect);
// // 设置绘制颜色
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
// // 绘制填充矩形
// SDL_RenderFillRect(renderer, &_RenderGuidanceInfo.rect);
}
Game::GetInstance().RenderCount++;
}
}
void Sprite::Clear()
{
}
void Sprite::SetBlendMode(SDL_BlendMode blendMode)
{
if (GetBlendMode() != blendMode)
m_texture->SetBlendMode(blendMode);
}
SDL_BlendMode Sprite::GetBlendMode()
{
return m_texture->GetBlendMode();
}

View File

@@ -0,0 +1,77 @@
#pragma once
#include <string>
#include "Asset/Asset_ImagePack.h"
#include "EngineFrame/Component/RenderBase.h"
#include "EngineFrame/Render/Texture.h"
class Game;
/**
* @brief Sprite类继承自Component类用于表示游戏中的精灵组件
*/
class Sprite : public RenderBase
{
protected:
/* data */
RefPtr<Texture> m_texture = nullptr;
public:
/**
* @brief Sprite类的默认构造函数
*/
Sprite(/* args */);
/**
* @brief Sprite类的带参数构造函数
* @param imgPath 纹理图片路径
* @param Index 索引值
*/
Sprite(std::string imgPath, int Index);
/**
* @brief Sprite类的带参数构造函数
* @param imgPath 纹理图片文件路径
*/
Sprite(std::string PngPath);
/**
* @brief Sprite类的析构函数
*/
~Sprite();
/**
* @brief 处理事件
* @param e SDL事件指针
*/
void HandleEvents(SDL_Event *e) override;
/**
* @brief 更新组件状态
* @param deltaTime 时间增量
*/
void Update(float deltaTime) override;
/**
* @brief 渲染组件
* @param deltaTime 时间增量
*/
void Render() override;
/**
* @brief 清理组件资源
*/
void Clear() override;
/**
* @brief 获取纹理
* @return SDL_Texture* 纹理指针
*/
RefPtr<Texture> GetTexture();
void SetIterationPos(VecFPos pos) override;
public:
RenderGuidanceInfo _RenderGuidanceInfo;
std::string imgPath;
int Index;
public:
// 计算渲染信息
void CalcRenderInfoLogic();
// 设置混合模式
void SetBlendMode(SDL_BlendMode blendMode);
// 获取混合模式
SDL_BlendMode GetBlendMode();
};

View File

@@ -0,0 +1,207 @@
#include "EngineFrame/Component/Text.h"
#include "Text.h"
#include "EngineCore/Game.h"
Text::Text()
{
}
Text::Text(std::string Str, TTF_Font *font, SDL_Color color)
{
m_text = Str;
m_font = font;
m_text_color = color;
Init(Str, font, color);
}
Text::Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
{
m_text = Str;
m_font = font;
m_text_color = textColor;
m_stroke_color = strokeColor;
m_stroke_size = strokeSize;
Init(Str, font, textColor, strokeColor, strokeSize);
}
Text::~Text()
{
}
void Text::Init(std::string Str, TTF_Font *font, SDL_Color color)
{
// 标记该组件需要渲染和更新
addTag(Tag::RENDER);
addTag(Tag::UPDATE);
// TTF_SetFontOutline(font, 1);
// 先渲染为表面
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), color);
if (!textSurface)
{
SDL_LogError(0, "文字渲染为表面失败TTF_Error:%s", TTF_GetError());
}
// 再将表面转换为纹理
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
m_texture = SDL_CreateTextureFromSurface(renderer, textSurface);
if (!m_texture)
{
SDL_LogError(0, "表面转换为纹理失败SDL_Error:%s", SDL_GetError());
}
// 设置纹理过滤模式为最近邻,避免缩放模糊
SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest);
Size.x = textSurface->w;
Size.y = textSurface->h;
TextureSize.x = textSurface->w;
TextureSize.y = textSurface->h;
// 释放表面
SDL_FreeSurface(textSurface);
}
void Text::Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
{
// 先保存原始字体的轮廓设置
int originalOutline = TTF_GetFontOutline(font);
// 设置字体轮廓大小(描边宽度)
TTF_SetFontOutline(font, strokeSize);
// 渲染描边(使用描边颜色)
SDL_Surface *strokeSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), strokeColor);
if (!strokeSurface)
{
SDL_LogError(0, "描边渲染为表面失败TTF_Error:%s", TTF_GetError());
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
return;
}
// 恢复字体轮廓设置,用于渲染文字本身
TTF_SetFontOutline(font, 0);
// 渲染文字本身(使用文字颜色)
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), textColor);
if (!textSurface)
{
SDL_LogError(0, "文字渲染为表面失败TTF_Error:%s", TTF_GetError());
SDL_FreeSurface(strokeSurface);
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
return;
}
// 创建一个合并描边和文字的表面
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
// 计算最终纹理大小(描边会增加额外尺寸)
int finalWidth = strokeSurface->w;
int finalHeight = strokeSurface->h;
// 创建一个临时表面用于合并描边和文字
SDL_Surface *finalSurface = SDL_CreateRGBSurfaceWithFormat(
0, finalWidth, finalHeight, 32, SDL_PIXELFORMAT_RGBA32);
if (!finalSurface)
{
SDL_LogError(0, "创建最终表面失败SDL_Error:%s", SDL_GetError());
SDL_FreeSurface(textSurface);
SDL_FreeSurface(strokeSurface);
TTF_SetFontOutline(font, originalOutline);
return;
}
// 将描边绘制到最终表面
SDL_Rect strokeRect = {0, 0, strokeSurface->w, strokeSurface->h};
SDL_BlitSurface(strokeSurface, nullptr, finalSurface, &strokeRect);
// 计算文字在描边中间的位置
SDL_Rect textRect = {
strokeSize, // X偏移描边宽度
strokeSize, // Y偏移描边宽度
textSurface->w,
textSurface->h};
SDL_BlitSurface(textSurface, nullptr, finalSurface, &textRect);
// 将合并后的表面转换为纹理
m_texture = SDL_CreateTextureFromSurface(renderer, finalSurface);
if (!m_texture)
{
SDL_LogError(0, "表面转换为纹理失败SDL_Error:%s", SDL_GetError());
}
// 设置尺寸信息
Size.x = finalSurface->w;
Size.y = finalSurface->h;
TextureSize.x = finalSurface->w;
TextureSize.y = finalSurface->h;
// 释放所有临时表面
SDL_FreeSurface(textSurface);
SDL_FreeSurface(strokeSurface);
SDL_FreeSurface(finalSurface);
// 恢复字体原始轮廓设置
TTF_SetFontOutline(font, originalOutline);
}
void Text::HandleEvents(SDL_Event *e)
{
}
void Text::Update(float deltaTime)
{
}
void Text::Render()
{
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
if (!renderer || !m_texture)
return;
SDL_Rect dstrect = {Pos.x, Pos.y, Size.x, Size.y};
SDL_RenderCopy(renderer, m_texture, NULL, &dstrect);
}
void Text::Clear()
{
}
void Text::SetPos(SDL_Point pos)
{
Pos = pos;
}
SDL_Point Text::GetPos()
{
return Pos;
}
void Text::SetText(std::string Str)
{
if (Str == m_text)
return;
if (!m_font)
{
SDL_LogError(0, "SetText失败字体指针为空");
return;
}
// 如果有原纹理先删除原纹理
if (m_texture)
{
SDL_DestroyTexture(m_texture);
m_texture = nullptr; // 置空指针
}
m_text = Str;
// 根据是否有描边选择对应的Init方法
if (m_stroke_size > 0)
{
Init(Str, m_font, m_text_color, m_stroke_color, m_stroke_size);
}
else
{
Init(Str, m_font, m_text_color);
}
}
std::string Text::GetText()
{
return m_text;
}

View File

@@ -0,0 +1,59 @@
#pragma once
#include <string>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include "EngineFrame/Component/Component.h"
class Game;
class Text : public Component
{
private:
/* data */
SDL_Texture *m_texture = nullptr;
public:
Text(/* args */);
Text(std::string Str, TTF_Font *font, SDL_Color color);
Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
~Text();
// 显式引入基类的Init方法避免隐藏
using Component::Init;
void Init(std::string Str, TTF_Font *font, SDL_Color color);
void Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
void HandleEvents(SDL_Event *e) override;
void Update(float deltaTime) override;
void Render() override;
void Clear() override;
SDL_Texture *GetTexture();
public:
// 组件标签
Tag m_tag = Tag::RENDER | Tag::UPDATE; // 标记该组件需要渲染和更新
std::string m_text;
TTF_Font *m_font;
SDL_Color m_text_color;
SDL_Color m_stroke_color;
int m_stroke_size = 0;
SDL_Point Pos = {0, 0}; // 位置坐标
SDL_Point TextureSize = {0, 0}; // 纹理大小
SDL_Point Size = {0, 0}; // 大小
SDL_Point Anchor = {0, 0}; // 中心点
float Angle = 0.0f; // 旋转角度
SDL_RendererFlip flip = SDL_FLIP_NONE; // 翻转
public:
// 设置坐标
void SetPos(SDL_Point pos);
// 设置文本
void SetText(std::string Str);
// 获取坐标
SDL_Point GetPos();
// 获取文本
std::string GetText();
};

View File

@@ -0,0 +1,83 @@
#include "EngineFrame/Render/Texture.h"
#include "Asset/Asset_ImagePack.h"
#include "EngineCore/Game.h"
#include "Texture.h"
Texture::Texture()
{
}
Texture::Texture(std::string PngPath)
{
SDL_Surface *surface = IMG_Load(PngPath.c_str());
if (!surface)
{
SDL_Log("无法加载图片: %s", SDL_GetError());
return;
}
m_texture = SDL_CreateTextureFromSurface(Game::GetInstance().GetRenderer(), surface);
if (!m_texture)
{
SDL_Log("无法创建纹理: %s", SDL_GetError());
SDL_FreeSurface(surface); // 记得释放surface
return;
}
this->TextureSize.width = surface->w;
this->TextureSize.height = surface->h;
this->TextureFramepos.width = surface->w;
this->TextureFramepos.height = surface->h;
SDL_FreeSurface(surface);
}
Texture::Texture(std::string imgPath, int Index)
{
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(imgPath);
if (Info->lpImgName == "sprite/interface/base.img")
return;
Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index];
m_texture = SDL_CreateTexture(
Game::GetInstance().GetRenderer(),
SDL_PIXELFORMAT_ARGB8888, // 匹配RGBA数据格式
SDL_TEXTUREACCESS_STREAMING,
Buf.Width, Buf.Height);
if (!m_texture)
{
SDL_Log("纹理创建失败: %s", SDL_GetError());
}
int pitch = Buf.Width * 4;
SDL_UpdateTexture(m_texture, NULL, Buf.PNGdata, pitch);
SDL_SetTextureBlendMode(m_texture, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeBest);
this->TexturePos.x = Buf.Xpos;
this->TexturePos.y = Buf.Ypos;
this->TextureSize.width = Buf.Width;
this->TextureSize.height = Buf.Height;
this->TextureFramepos.width = Buf.FrameXpos;
this->TextureFramepos.height = Buf.FrameYpos;
}
Texture::~Texture()
{
SDL_DestroyTexture(m_texture);
}
SDL_Texture *Texture::GetTexture()
{
return m_texture;
}
void Texture::SetBlendMode(SDL_BlendMode blendMode)
{
SDL_SetTextureBlendMode(m_texture, blendMode);
}
SDL_BlendMode Texture::GetBlendMode()
{
SDL_BlendMode blendMode;
SDL_GetTextureBlendMode(m_texture, &blendMode);
return blendMode;
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <SDL.h>
#include <string>
#include "Tool/RefPtr.h"
#include "Tool/RefObject.h"
class Texture : public RefObject
{
private:
SDL_Texture *m_texture = nullptr;
public:
VecSize TextureSize = {0, 0}; // 纹理大小
VecPos TexturePos = {0, 0}; // 纹理位置
VecSize TextureFramepos = {0, 0}; // 帧域宽高
public:
Texture(/* args */);
Texture(std::string PngPath);
Texture(std::string imgPath, int Index);
~Texture();
public:
void SetBlendMode(SDL_BlendMode blendMode);
// 获取混合模式
SDL_BlendMode GetBlendMode();
SDL_Texture *GetTexture(); // 获取纹理
};

View File

@@ -0,0 +1,22 @@
#include "Scene.h"
#include "EngineFrame/Scene/Scene.h"
#include <algorithm>
Scene::Scene()
{
Init();
}
void Scene::Enter()
{
}
void Scene::Init()
{
BaseNode::Init();
addTag(Tag::SCENE);
}
void Scene::Exit()
{
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "EngineFrame/Base/BaseNode.h"
class Scene : public BaseNode
{
public:
Scene();
virtual void Enter();
virtual void Exit();
void Init();
};