SwitchGame/source/EngineFrame/Component/Animation.cpp

315 lines
8.8 KiB
C++
Raw Normal View History

2025-09-18 15:21:43 +08:00
#include "Animation.h"
#include "Asset/AssetManager.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)> AdditionalOptions)
{
this->AdditionalOptions = AdditionalOptions;
Init(AniPath);
}
Animation::~Animation()
{
}
void Animation::Init(std::string AniPath)
{
// 标记该组件需要渲染和更新
addTag(Tag::RENDER);
addTag(Tag::UPDATE);
2025-09-19 12:18:57 +08:00
addTag(Tag::TRANSFORM);
2025-09-18 15:21:43 +08:00
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];
2025-09-19 12:18:57 +08:00
RefPtr<Sprite> SpriteObj = nullptr;
2025-09-18 15:21:43 +08:00
if (!FrameObj.Img_Path.empty())
{
if (AdditionalOptions)
{
FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path);
}
2025-09-19 12:18:57 +08:00
SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index);
SpriteObj->SetPos(FrameObj.Img_Pos);
2025-09-18 15:21:43 +08:00
}
2025-09-19 12:18:57 +08:00
else
SpriteObj = new Sprite();
2025-09-18 15:21:43 +08:00
SpriteArr.push_back(SpriteObj);
}
// 初始化完毕 如果是第一次初始化 而非重新构造 设置大小为第0帧大小否则天空 地板等依靠大小的初始化会有问题
if (CurrentIndexT == 0)
SetSize(SpriteArr[0]->GetSize());
// 记录总帧数
TotalFrameIndex = FrameArr.size();
// TODO 染色
}
void Animation::HandleEvents(SDL_Event *e)
{
}
void Animation::Update(float deltaTime)
{
Component::Update(deltaTime);
// 可用性检查
if (IsUsability)
{
int dt = (int)(deltaTime * 1000);
// 累加当前帧时间
CurrentIndexT += dt;
// 插值模式判断
InterpolationLogic();
// 当前帧时间 超过 当前帧延迟就需要切换帧了
if (CurrentIndexT >= NextFrameDelay)
{
CurrentIndexT = 0;
// 如果当前帧小于总帧数就切换
if (CurrentFrameIndex < (TotalFrameIndex - 1))
{
FlushFrame(CurrentFrameIndex + 1);
}
// 说明播放完毕了
else
{
// 如果有循环
if (AnimationFlag.count("LOOP"))
{
FlushFrame(0);
}
// 没有循环触发状态机回调
else
{
// 将不再可用
IsUsability = false;
if (EndCallback)
EndCallback();
}
}
}
}
}
void Animation::Render(float deltaTime)
{
if (IsUsability)
{
if (CurrentFrame)
{
2025-09-19 12:18:57 +08:00
CurrentFrame->Render(deltaTime);
2025-09-18 15:21:43 +08:00
}
}
}
void Animation::OnAdded(Actor *actor)
{
Component::OnAdded(actor);
FlushFrame(0);
}
void Animation::Clear()
{
}
2025-09-19 12:18:57 +08:00
void Animation::SetIterationPos(VecPos pos)
{
Component::SetIterationPos(pos);
if (CurrentFrame)
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
}
2025-09-18 15:21:43 +08:00
void Animation::FlushFrame(int Index)
{
// 同步当前帧
CurrentFrameIndex = Index;
// 当前帧更换为本帧
CurrentFrame = SpriteArr[CurrentFrameIndex];
2025-09-19 12:18:57 +08:00
// 设置精灵帧的迭代坐标为自己的坐标和自己的迭代坐标
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
2025-09-18 15:21:43 +08:00
// 如果是整体染色 则直接使用染色帧
// 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"))
{
2025-09-19 12:18:57 +08:00
VecFPos Rate = std::get<VecFPos>(FlagBuf["IMAGE_RATE"]);
VecSize Size = CurrentFrame->GetSize();
CurrentFrame->SetSize(VecSize{int(Size.width * Rate.x), (int)(Size.width * Rate.y)});
2025-09-18 15:21:43 +08:00
}
// 线性减淡
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
{
CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD);
}
// 旋转
if (FlagBuf.count("IMAGE_ROTATE"))
{
2025-09-19 12:18:57 +08:00
CurrentFrame->SetAnchor(VecFPos{0.5, 0.5});
2025-09-18 15:21:43 +08:00
CurrentFrame->SetAngle(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 染色 和 透明度还没弄
}
// 坐标
{
2025-09-19 12:18:57 +08:00
VecPos PosData = {
2025-09-18 15:21:43 +08:00
(int)(OldData.Img_Pos.x + (NewData.Img_Pos.x - OldData.Img_Pos.x) * InterRate),
(int)(OldData.Img_Pos.y + (NewData.Img_Pos.y - OldData.Img_Pos.y) * InterRate)};
SetPos(PosData);
2025-09-19 12:18:57 +08:00
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
2025-09-18 15:21:43 +08:00
}
// 缩放
{
2025-09-19 12:18:57 +08:00
VecFPos OldRateData = {1.0, 1.0};
VecFPos NewRateData = {1.0, 1.0};
2025-09-18 15:21:43 +08:00
if (OldData.Flag.count("IMAGE_RATE"))
{
2025-09-19 12:18:57 +08:00
OldRateData = std::get<VecFPos>(OldData.Flag["IMAGE_RATE"]);
2025-09-18 15:21:43 +08:00
}
if (NewData.Flag.count("IMAGE_RATE"))
{
2025-09-19 12:18:57 +08:00
NewRateData = std::get<VecFPos>(NewData.Flag["IMAGE_RATE"]);
2025-09-18 15:21:43 +08:00
}
2025-09-19 12:18:57 +08:00
VecSize ScaleData = {
(int)(CurrentFrame->GetSize().width * (OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate)),
(int)(CurrentFrame->GetSize().height * (OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate))};
VecSize Size = CurrentFrame->GetSize();
CurrentFrame->SetSize(VecSize{int(Size.width * ScaleData.width), (int)(Size.height * ScaleData.height)});
2025-09-18 15:21:43 +08:00
}
// 旋转
{
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->SetAngle(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
}
}
2025-09-19 12:18:57 +08:00
void Animation::SetSize(VecSize size)
2025-09-18 15:21:43 +08:00
{
this->Size = size;
}
2025-09-19 12:18:57 +08:00
void Animation::SetPos(VecPos pos)
2025-09-18 15:21:43 +08:00
{
this->Pos = pos;
2025-09-19 12:18:57 +08:00
if (CurrentFrame)
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
2025-09-18 15:21:43 +08:00
}
2025-09-19 12:18:57 +08:00
VecPos Animation::GetPos()
2025-09-18 15:21:43 +08:00
{
return this->Pos;
}
2025-09-19 12:18:57 +08:00
VecSize Animation::GetSize()
2025-09-18 15:21:43 +08:00
{
return this->Size;
}