修改OpenGl渲染底层之前
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "Asset/Asset_Script.h"
|
||||
#include "Tool/Math.h"
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
#include "EngineCore/Game.h"
|
||||
|
||||
Animation::Animation()
|
||||
{
|
||||
@@ -66,20 +67,20 @@ void Animation::Init(std::string AniPath)
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -134,7 +135,18 @@ void Animation::Render()
|
||||
{
|
||||
if (!Visible)
|
||||
return;
|
||||
Actor::Render();
|
||||
// 是否裁切
|
||||
if (CropFlag)
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
SDL_RenderSetClipRect(renderer, &CropRect);
|
||||
Actor::Render();
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor::Render();
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::OnAdded(BaseNode *node)
|
||||
@@ -153,6 +165,7 @@ void Animation::SetVisible(bool visible)
|
||||
if (visible)
|
||||
{
|
||||
CurrentFrame->CalcRenderInfoLogic();
|
||||
CurrentFrame->CalcRenderInfo();
|
||||
}
|
||||
Actor::SetVisible(visible);
|
||||
}
|
||||
@@ -192,7 +205,6 @@ void Animation::FlushFrame(int Index)
|
||||
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});
|
||||
}
|
||||
// 线性减淡
|
||||
@@ -233,7 +245,6 @@ void Animation::FlushFrame(int Index)
|
||||
}
|
||||
// Ani的大小同步为精灵帧对象的大小
|
||||
SetSize(CurrentFrame->GetSize());
|
||||
// 裁切 //TODO
|
||||
}
|
||||
|
||||
void Animation::Reset()
|
||||
@@ -317,3 +328,22 @@ void Animation::InterpolationLogic()
|
||||
CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::SetClipRect(SDL_Rect clipRect)
|
||||
{
|
||||
CropFlag = true;
|
||||
CropRect = clipRect;
|
||||
}
|
||||
|
||||
void Animation::UnsetClipRect()
|
||||
{
|
||||
CropFlag = false;
|
||||
}
|
||||
|
||||
void Animation::SetShadow()
|
||||
{
|
||||
for (auto &Sp : SpriteArr)
|
||||
{
|
||||
Sp->SetShadow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,20 @@ public:
|
||||
void FlushFrame(int Index);
|
||||
void Reset();
|
||||
AniScriptParser::AniFrame GetCurrentFrameInfo();
|
||||
// 设置帧索引
|
||||
void SetFrameIndex(int Index);
|
||||
void InterpolationLogic();
|
||||
// TODO SetOutline
|
||||
// TODO SetDye
|
||||
// TODO SetCrop
|
||||
|
||||
// 设置裁切区域
|
||||
void SetClipRect(SDL_Rect clipRect);
|
||||
// 取消裁切区域
|
||||
void UnsetClipRect();
|
||||
// 设置阴影
|
||||
void SetShadow();
|
||||
|
||||
public:
|
||||
// Ani是否可用
|
||||
bool IsUsability = true;
|
||||
@@ -88,7 +96,9 @@ public:
|
||||
// // 整体染色
|
||||
// DyeAllFlag = false;
|
||||
// // 裁切数据
|
||||
// CropRect = null;
|
||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
||||
// 裁切Flag
|
||||
bool CropFlag = false;
|
||||
|
||||
// 附加选项
|
||||
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
|
||||
|
||||
107
source/EngineFrame/Component/AnimationManager.cpp
Normal file
107
source/EngineFrame/Component/AnimationManager.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "AnimationManager.h"
|
||||
#include "EngineCore/Game.h"
|
||||
|
||||
AnimationManager::AnimationManager()
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
m_Texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_TARGET,
|
||||
Game::GetInstance().Screen_W,
|
||||
Game::GetInstance().Screen_H);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
// 设定渲染目标为纹理
|
||||
SDL_SetRenderTarget(renderer, m_Texture);
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
// 渲染所有子对象
|
||||
Actor::Render();
|
||||
// 恢复渲染目标为默认窗口
|
||||
SDL_SetRenderTarget(renderer, nullptr);
|
||||
|
||||
SDL_Rect srcRect = {
|
||||
static_cast<int>(m_RenderRect.x), // 子对象包围盒左上角X(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.y), // 子对象包围盒左上角Y(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.w), // 包围盒宽度(有效区域宽度)
|
||||
static_cast<int>(m_RenderRect.h) // 包围盒高度(有效区域高度)
|
||||
};
|
||||
|
||||
// SDL_FRect renderToWindow = {
|
||||
// m_RenderRect.x, // 窗口上的X位置(可自定义)
|
||||
// m_RenderRect.y, // 窗口上的Y位置(可自定义)
|
||||
// m_RenderRect.w, // 渲染到窗口的宽度(与源区域等大)
|
||||
// m_RenderRect.h // 渲染到窗口的高度(与源区域等大)
|
||||
// };
|
||||
SDL_FRect renderToWindow = {
|
||||
0, 0, 1080, 720};
|
||||
|
||||
// SDL_Log("m_Texture rect: %f %f %f %f", renderToWindow.x, renderToWindow.y, renderToWindow.w, renderToWindow.h);
|
||||
// SDL_RenderCopyF(renderer, m_Texture, &srcRect, &renderToWindow);
|
||||
SDL_RenderCopyF(renderer, m_Texture, NULL, &renderToWindow);
|
||||
}
|
||||
|
||||
void AnimationManager::AddAnimation(RefPtr<Animation> ani)
|
||||
{
|
||||
this->AddChild(ani);
|
||||
}
|
||||
|
||||
void AnimationManager::Clear()
|
||||
{
|
||||
this->RemoveAllChild();
|
||||
}
|
||||
21
source/EngineFrame/Component/AnimationManager.h
Normal file
21
source/EngineFrame/Component/AnimationManager.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#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();
|
||||
};
|
||||
@@ -9,12 +9,17 @@ class RenderBase : public Component
|
||||
public:
|
||||
struct RenderGuidanceInfo
|
||||
{
|
||||
SDL_Rect rect;
|
||||
SDL_FRect rect;
|
||||
// 旋转角度
|
||||
float rotation;
|
||||
// 翻转Flag
|
||||
SDL_RendererFlip flip = SDL_FLIP_NONE;
|
||||
VecPos AnchorPos;
|
||||
// 锚点坐标
|
||||
VecFPos AnchorPos;
|
||||
// 是否显示
|
||||
bool Visible = true;
|
||||
bool IsInScreen;
|
||||
// 是否在屏幕内
|
||||
bool IsInScreen = false;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "Sprite.h"
|
||||
#include "EngineCore/Game.h"
|
||||
#include "Text.h"
|
||||
Sprite::Sprite()
|
||||
|
||||
void Sprite::Init()
|
||||
{
|
||||
this->Size = m_texture->TextureSize;
|
||||
RenderBase::Init();
|
||||
}
|
||||
|
||||
Sprite::Sprite(std::string imgPath, int Index)
|
||||
@@ -30,27 +33,12 @@ 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;
|
||||
@@ -63,46 +51,55 @@ void Sprite::CalcRenderInfoLogic()
|
||||
_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;
|
||||
float texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x;
|
||||
float 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;
|
||||
float RealPosX = transform.position.x + texturePosX;
|
||||
float RealPosY = transform.position.y + texturePosY;
|
||||
|
||||
// 计算在世界中的位置
|
||||
int baseX = transformIter.position.x + RealPosX;
|
||||
int baseY = transformIter.position.y + RealPosY;
|
||||
float baseX = transformIter.position.x + RealPosX;
|
||||
float baseY = transformIter.position.y + RealPosY;
|
||||
|
||||
// 获取当前帧的原始尺寸
|
||||
int frameWidth = m_texture->TextureSize.width;
|
||||
int frameHeight = m_texture->TextureSize.height;
|
||||
int frameWidth = Size.width;
|
||||
int frameHeight = Size.height;
|
||||
|
||||
// 原始锚点偏移(基于帧尺寸)
|
||||
int origAnchorOffsetX = static_cast<int>(frameWidth * Anchor.x);
|
||||
int origAnchorOffsetY = static_cast<int>(frameHeight * Anchor.y);
|
||||
float origAnchorOffsetX = int(frameWidth * Anchor.x);
|
||||
float origAnchorOffsetY = int(frameHeight * Anchor.y);
|
||||
|
||||
// 缩放的绝对值
|
||||
float absScaleX = SDL_abs(scaleX);
|
||||
float absScaleY = SDL_abs(scaleY);
|
||||
float absScaleX = SDL_fabs(scaleX);
|
||||
float absScaleY = SDL_fabs(scaleY);
|
||||
// 缩放后的尺寸
|
||||
int scaledWidth = static_cast<int>(frameWidth * absScaleX);
|
||||
int scaledHeight = static_cast<int>(frameHeight * absScaleY);
|
||||
float scaledWidth = frameWidth * absScaleX;
|
||||
float scaledHeight = frameHeight * absScaleY;
|
||||
// 缩放后的锚点偏移
|
||||
int scaledAnchorOffsetX = static_cast<int>(origAnchorOffsetX * absScaleX);
|
||||
int scaledAnchorOffsetY = static_cast<int>(origAnchorOffsetY * absScaleY);
|
||||
float scaledAnchorOffsetX = int(origAnchorOffsetX * absScaleX);
|
||||
float scaledAnchorOffsetY = int(origAnchorOffsetY * absScaleY);
|
||||
|
||||
// 计算缩放后的锚点偏移与原锚点偏移的差值
|
||||
int scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
|
||||
int scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY;
|
||||
float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
|
||||
float scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY;
|
||||
|
||||
// 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角)
|
||||
int Xpos = baseX + scaleOffsetX;
|
||||
int Ypos = baseY + scaleOffsetY;
|
||||
float Xpos = baseX - scaleOffsetX;
|
||||
float Ypos = baseY - scaleOffsetY;
|
||||
|
||||
Xpos = (int)Xpos; // 强制转换为整数
|
||||
Ypos = (int)Ypos; // 强制转换为整数
|
||||
|
||||
// 更新渲染信息
|
||||
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
|
||||
|
||||
// 如果有阴影 计算阴影的渲染信息
|
||||
if (ShadowFlag)
|
||||
CalculateShadowData();
|
||||
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
|
||||
// 设置纹理透明度
|
||||
SDL_SetTextureAlphaMod(m_texture->GetTexture(), this->Alpha * 255);
|
||||
|
||||
// 屏幕内检测
|
||||
int screenWidth = Game::GetInstance().Screen_W;
|
||||
@@ -110,12 +107,29 @@ void Sprite::CalcRenderInfoLogic()
|
||||
bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight);
|
||||
_RenderGuidanceInfo.IsInScreen = isInScreen;
|
||||
|
||||
this->Size = {scaledWidth, scaledHeight};
|
||||
// this->Size = {scaledWidth, scaledHeight};
|
||||
_RenderGuidanceInfo.rotation = transformIter.rotation + transform.rotation;
|
||||
|
||||
CalcRenderInfoFlag = false;
|
||||
}
|
||||
|
||||
void Sprite::SetClipRect(SDL_Rect clipRect)
|
||||
{
|
||||
CropFlag = true;
|
||||
CropRect = clipRect;
|
||||
}
|
||||
|
||||
void Sprite::UnsetClipRect()
|
||||
{
|
||||
CropFlag = false;
|
||||
}
|
||||
|
||||
void Sprite::PreRender()
|
||||
{
|
||||
if (CalcRenderInfoFlag && Visible)
|
||||
CalcRenderInfoLogic();
|
||||
}
|
||||
|
||||
void Sprite::Render()
|
||||
{
|
||||
if (!Visible)
|
||||
@@ -126,20 +140,27 @@ void Sprite::Render()
|
||||
|
||||
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
|
||||
{
|
||||
// 如果有阴影绘制阴影
|
||||
if (ShadowFlag)
|
||||
{
|
||||
std::array<int, 6> indices = {0, 1, 2, 1, 3, 2};
|
||||
SDL_RenderGeometry(renderer, m_texture->GetTexture(), vertices.data(), vertices.size(), indices.data(), indices.size());
|
||||
}
|
||||
|
||||
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);
|
||||
SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos;
|
||||
SDL_RenderCopyExF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_RenderCopy(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect);
|
||||
SDL_RenderCopyF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect);
|
||||
// // 设置绘制颜色
|
||||
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
|
||||
// // 绘制填充矩形
|
||||
// SDL_RenderFillRect(renderer, &_RenderGuidanceInfo.rect);
|
||||
// SDL_RenderFillRectF(renderer, &_RenderGuidanceInfo.rect);
|
||||
}
|
||||
Game::GetInstance().RenderCount++;
|
||||
Game::GetInstance().m_RenderCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,3 +178,62 @@ SDL_BlendMode Sprite::GetBlendMode()
|
||||
{
|
||||
return m_texture->GetBlendMode();
|
||||
}
|
||||
|
||||
void Sprite::SetShadow()
|
||||
{
|
||||
ShadowFlag = true;
|
||||
CalcRenderInfo();
|
||||
}
|
||||
|
||||
void Sprite::CalculateShadowData()
|
||||
{
|
||||
const float shearX = 1.3f;
|
||||
SDL_FRect guidance = _RenderGuidanceInfo.rect;
|
||||
float shadowW = guidance.w; // 影子宽度(建议与角色宽度一致)
|
||||
float shadowH = guidance.h * 0.33; // 影子高度(可根据需求调整,比如角色高度的1/4)
|
||||
|
||||
// 计算角色脚部中点坐标(底部中心,即需要重叠的锚点)
|
||||
float roleFootX = guidance.x + guidance.w / 2.0f + 3; // 角色X中心 + 位置偏移
|
||||
float roleFootY = guidance.y + guidance.h - 5; // 角色底部Y坐标(脚的位置)
|
||||
|
||||
// 计算错切后的顶点(局部坐标)
|
||||
vertices = {
|
||||
// 左上角(局部坐标)
|
||||
SDL_Vertex{{0.0f, 0.0f}, {0, 0, 0, 110}, {0.0f, 0.0f}},
|
||||
// 右上角(局部坐标)
|
||||
SDL_Vertex{{shadowW, 0.0f}, {0, 0, 0, 110}, {1.0f, 0.0f}},
|
||||
// 左下角(局部坐标)
|
||||
SDL_Vertex{{0.0f + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {0.0f, 1.0f}},
|
||||
// 右下角(局部坐标)
|
||||
SDL_Vertex{{shadowW + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {1.0f, 1.0f}}};
|
||||
|
||||
bool flipHorizontal = (_RenderGuidanceInfo.flip & SDL_FLIP_HORIZONTAL) != 0; // 检查水平翻转标志
|
||||
bool flipVertical = (_RenderGuidanceInfo.flip & SDL_FLIP_VERTICAL) != 0; // 检查垂直翻转标志
|
||||
// 应用纹理坐标翻转(核心逻辑)
|
||||
for (auto &v : vertices)
|
||||
{
|
||||
// 水平翻转:反转u坐标(0→1,1→0)
|
||||
if (flipHorizontal)
|
||||
{
|
||||
v.tex_coord.x = 1.0f - v.tex_coord.x;
|
||||
}
|
||||
// 垂直翻转:反转v坐标(0→1,1→0)
|
||||
if (flipVertical)
|
||||
{
|
||||
v.tex_coord.y = 1.0f - v.tex_coord.y;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算影子底部中点并对齐角色脚部(与之前逻辑一致)
|
||||
float shadowFootX = (vertices[2].position.x + vertices[3].position.x) / 2.0f;
|
||||
float shadowFootY = shadowH;
|
||||
float offsetX = roleFootX - shadowFootX;
|
||||
float offsetY = roleFootY - shadowFootY;
|
||||
|
||||
// 应用位置偏移
|
||||
for (auto &v : vertices)
|
||||
{
|
||||
v.position.x += offsetX;
|
||||
v.position.y += offsetY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,67 +11,47 @@ class Game;
|
||||
class Sprite : public RenderBase
|
||||
{
|
||||
protected:
|
||||
/* data */
|
||||
RefPtr<Texture> m_texture = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Sprite类的默认构造函数
|
||||
*/
|
||||
Sprite(/* args */);
|
||||
/**
|
||||
* @brief Sprite类的带参数构造函数
|
||||
* @param imgPath 纹理图片路径
|
||||
* @param Index 索引值
|
||||
*/
|
||||
Sprite() = default;
|
||||
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 PreRender() override;
|
||||
void Clear() override;
|
||||
void Init() override;
|
||||
|
||||
/**
|
||||
* @brief 获取纹理
|
||||
* @return SDL_Texture* 纹理指针
|
||||
*/
|
||||
RefPtr<Texture> GetTexture();
|
||||
|
||||
void SetIterationPos(VecFPos pos) override;
|
||||
|
||||
public:
|
||||
// 渲染信息
|
||||
RenderGuidanceInfo _RenderGuidanceInfo;
|
||||
// 裁切数据
|
||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
||||
// 裁切Flag
|
||||
bool CropFlag = false;
|
||||
// 阴影数据
|
||||
std::array<SDL_Vertex, 4> vertices;
|
||||
// 阴影Flag
|
||||
bool ShadowFlag = false;
|
||||
std::string imgPath;
|
||||
int Index;
|
||||
|
||||
public:
|
||||
// 计算渲染信息
|
||||
void CalcRenderInfoLogic();
|
||||
// 设置裁切区域
|
||||
void SetClipRect(SDL_Rect clipRect);
|
||||
// 取消裁切区域
|
||||
void UnsetClipRect();
|
||||
// 设置混合模式
|
||||
void SetBlendMode(SDL_BlendMode blendMode);
|
||||
// 获取混合模式
|
||||
SDL_BlendMode GetBlendMode();
|
||||
// 设置阴影
|
||||
void SetShadow();
|
||||
// 计算阴影数据
|
||||
void CalculateShadowData();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user