Files
DNF_DEV/source/EngineFrame/Component/Sprite.cpp
2025-10-06 04:18:49 +08:00

160 lines
5.1 KiB
C++

#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();
}