#include "Sprite.h" #include "EngineCore/Game.h" #include "Text.h" #include "EngineFrame/Render/RenderManager.h" void Sprite::Init() { this->Size = m_texture->getSize(); RenderBase::Init(); } void Sprite::SetTexture(RefPtr texture) { m_texture = texture; Init(); CalcRenderInfoLogic(); // 第一次计算 } Sprite::Sprite(std::string imgPath, int Index) { this->imgPath = imgPath; this->Index = Index; m_texture = new Texture(); m_texture->Init(imgPath, Index); Init(); CalcRenderInfoLogic(); // 第一次计算 } Sprite::Sprite(std::string PngPath) { m_texture = new Texture(); m_texture->Init(PngPath); Init(); CalcRenderInfoLogic(); // 第一次计算 } Sprite::~Sprite() { } RefPtr Sprite::GetTexture() { return m_texture; } GlMatrix Sprite::matrix3x2ToGLMatrix(const Matrix3x2 &mat) { return { // 列0:x轴线性变换 mat._11, // [0][0] mat._12, // [1][0] 0.0f, // [2][0] 0.0f, // [3][0] // 列1:y轴线性变换 mat._21, // [0][1] mat._22, // [1][1] 0.0f, // [2][1] 0.0f, // [3][1] // 列2:z轴(固定) 0.0f, // [0][2] 0.0f, // [1][2] 1.0f, // [2][2] 0.0f, // [3][2] // 列3:平移 mat._31, // [0][3](x平移) mat._32, // [1][3](y平移) 0.0f, // [2][3] 1.0f // [3][3] }; } void Sprite::CalcRenderInfoLogic() { // 获取至在最终的父对象检查是否显示 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_FLIP_HORIZONTAL | _RenderGuidanceInfo.flip); if (flipY) _RenderGuidanceInfo.flip = static_cast(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip); // 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上 auto T_Size = m_texture->getSize(); auto T_Pos = m_texture->getPos(); float texturePosX = flipX ? -(T_Size.width + T_Pos.x) + SDL_abs(transform.position.x * 2) : T_Pos.x; float texturePosY = flipY ? -(T_Size.height + T_Pos.y) + SDL_abs(transform.position.y * 2) : 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; // 获取当前帧的原始尺寸 int frameWidth = Size.width; int frameHeight = Size.height; // 原始锚点偏移(基于帧尺寸) float origAnchorOffsetX = int(frameWidth * Anchor.x); float origAnchorOffsetY = int(frameHeight * Anchor.y); // 缩放的绝对值 float absScaleX = SDL_fabs(scaleX); float absScaleY = SDL_fabs(scaleY); // 缩放后的尺寸 float scaledWidth = frameWidth * absScaleX; float scaledHeight = frameHeight * absScaleY; // 缩放后的锚点偏移 float scaledAnchorOffsetX = int(origAnchorOffsetX * absScaleX); float scaledAnchorOffsetY = int(origAnchorOffsetY * absScaleY); // 计算缩放后的锚点偏移与原锚点偏移的差值 float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX; float scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY; // 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角) float Xpos = baseX - scaleOffsetX; float Ypos = baseY - scaleOffsetY; Xpos = (int)Xpos; // 强制转换为整数 Ypos = (int)Ypos; // 强制转换为整数 // 更新渲染信息 _RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight}; _RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY}; // 设置纹理透明度 m_texture->setAlpha(this->Alpha); // 屏幕内检测 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::PreRender() { if (CalcRenderInfoFlag && Visible) CalcRenderInfoLogic(); } void Sprite::Render() { if (!Visible) return; if (!m_texture) return; RenderManager *renderer = Game::GetInstance().GetRenderer(); if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible) { 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; } }