diff --git a/.gitignore b/.gitignore index e81beb4..f46b146 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ MyGame.lst MyGame.elf build/ romfs/ +SwitchGame.elf +SwitchGame.nacp +SwitchGame.nro +.vscode/ diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 831f1ad..34c9334 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -5,15 +5,15 @@ "includePath": [ "${workspaceFolder}/source/**", "${workspaceFolder}/source_game/**", - "L:/Switch/devkitPro/devkitA64/aarch64-none-elf/include", - "L:/Switch/devkitPro/libnx/include", - "L:/Switch/devkitPro/portlibs/switch/include", - "L:/Switch/devkitPro/portlibs/switch/include/SDL2" + "D:/devkitPro/devkitA64/aarch64-none-elf/include", + "D:/devkitPro/libnx/include", + "D:/devkitPro/portlibs/switch/include", + "D:/devkitPro/portlibs/switch/include/SDL2" ], "defines": [ "__SWITCH__" ], - "compilerPath": "L:/Switch/devkitPro/devkitA64/bin/aarch64-none-elf-gcc", + "compilerPath": "D:/devkitPro/devkitA64/bin/aarch64-none-elf-gcc", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "gcc-arm", diff --git a/Makefile b/Makefile index 7f82a95..74c22e4 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,8 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := `$(PREFIX)pkg-config --cflags sdl2 SDL2_mixer SDL2_image` -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) +# CFLAGS := `$(PREFIX)pkg-config --cflags sdl2 SDL2_mixer SDL2_image` -Wall -g -O0 -ffunction-sections \ +# $(ARCH) $(DEFINES) -DDEBUG # 添加 -g -O0 -DDEBUG CFLAGS += $(INCLUDE) -D__SWITCH__ diff --git a/folder-alias.json b/folder-alias.json index 16d83ce..21792b2 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -76,5 +76,11 @@ }, "source_game/Asset/AnimationStruct.h": { "description": "Ani结构数据" + }, + "source/EngineFrame/Component/Component.h": { + "description": "组件基类" + }, + "source/EngineFrame/Component/Animation.h": { + "description": "动画类" } } \ No newline at end of file diff --git a/source/EngineCore/Asset_ImagePack.h b/source/EngineCore/Asset_ImagePack.h index e048968..ddbeea4 100644 --- a/source/EngineCore/Asset_ImagePack.h +++ b/source/EngineCore/Asset_ImagePack.h @@ -36,10 +36,6 @@ public: int Xpos; // Ypos int Ypos; - // Xpos - int XposEx = 0; - // Ypos - int YposEx = 0; // 帧域X int FrameXpos; // 帧域Y diff --git a/source/EngineCore/Game.cpp b/source/EngineCore/Game.cpp index 4f54d5d..db47314 100644 --- a/source/EngineCore/Game.cpp +++ b/source/EngineCore/Game.cpp @@ -61,7 +61,7 @@ void Game::Init(std::function CallBack) m_isRunning = false; } // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - + // 构造调试对象 m_DebugInfoActor = new Debug_Actor(); CallBack(); } @@ -127,6 +127,14 @@ void Game::HandleEvents(SDL_Event *e) SDL_Log("Game Exit2"); } } + // 处理屏幕按下事件 + else if (e->type == SDL_FINGERDOWN) + { + // 触发双击事件 + SDL_Log("退出程序"); + m_isRunning = false; + SDL_Log("Game Exit3"); + } if (m_scene != nullptr) m_scene->HandleEvents(e); diff --git a/source/EngineFrame/Actor/Actor.cpp b/source/EngineFrame/Actor/Actor.cpp index f4e833d..6ef5924 100644 --- a/source/EngineFrame/Actor/Actor.cpp +++ b/source/EngineFrame/Actor/Actor.cpp @@ -1,5 +1,6 @@ #include "Actor.h" #include "EngineFrame/Scene/Scene.h" +#include Actor::Actor() { @@ -23,7 +24,11 @@ void Actor::Update(float deltaTime) RefPtr child = m_Components.GetFirst(); while (child) { - child->Update(deltaTime); + if (child->hasTag(Tag::UPDATE)) + child->Update(deltaTime); + if (child->hasTag(Tag::RENDER)) + { + } child = child->GetNext(); } } @@ -34,7 +39,8 @@ void Actor::Render(float deltaTime) RefPtr child = m_Components.GetFirst(); while (child) { - child->Render(deltaTime); + if (child->hasTag(Tag::RENDER)) + child->Render(deltaTime); child = child->GetNext(); } } @@ -46,5 +52,22 @@ void Actor::Clear() void Actor::AddComponent(RefPtr Component) { m_Components.PushBack(Component); - Component->Parent = this; -} \ No newline at end of file + Component->OnAdded(this); + Component->ReorderComponents(); +} + +void Actor::RemoveComponent(RefPtr Component) +{ + Component->Parent = nullptr; + m_Components.Remove(Component); +} + +void Actor::SetPos(SDL_Point pos) +{ + this->Pos = pos; +} + +SDL_Point Actor::GetPos() +{ + return this->Pos; +} diff --git a/source/EngineFrame/Actor/Actor.h b/source/EngineFrame/Actor/Actor.h index 0468b28..9af4f96 100644 --- a/source/EngineFrame/Actor/Actor.h +++ b/source/EngineFrame/Actor/Actor.h @@ -10,6 +10,7 @@ class Scene; */ class Actor : public Actor_base, protected IntrusiveListValue> { + public: Actor(); ~Actor() override; @@ -26,10 +27,15 @@ public: public: void AddComponent(RefPtr Component); + void RemoveComponent(RefPtr Component); + void SetPos(SDL_Point pos); + SDL_Point GetPos(); public: - Scene *Parent; // 指向父场景的指针,表示该Actor所属的场景 + Scene *Parent; // 指向父场景的指针,表示该Actor所属的场景 + SDL_Point Pos = {0, 0}; // 位置坐标 + + IntrusiveList> m_Components; // 组件列表 private: - IntrusiveList> m_Components; }; diff --git a/source/EngineFrame/Actor/Actor_base.cpp b/source/EngineFrame/Actor/Actor_base.cpp index 0bf4131..207edfe 100644 --- a/source/EngineFrame/Actor/Actor_base.cpp +++ b/source/EngineFrame/Actor/Actor_base.cpp @@ -27,3 +27,13 @@ void Actor_base::SetCallbackOnUpdate(const UpdateCallback &cb) { cb_update_ = cb; } + +int Actor_base::GetRenderZOrder() +{ + return this->RenderZOrder; +} + +void Actor_base::SetRenderZOrder(int zOrder) +{ + this->RenderZOrder = zOrder; +} \ No newline at end of file diff --git a/source/EngineFrame/Actor/Actor_base.h b/source/EngineFrame/Actor/Actor_base.h index 469e8d3..8918878 100644 --- a/source/EngineFrame/Actor/Actor_base.h +++ b/source/EngineFrame/Actor/Actor_base.h @@ -28,4 +28,9 @@ public: private: /* data */ UpdateCallback cb_update_; // 更新时的回调函数 + int RenderZOrder = 0; // 渲染层级 + +public: + int GetRenderZOrder(); + void SetRenderZOrder(int zOrder); }; diff --git a/source/EngineFrame/Component/Animation.cpp b/source/EngineFrame/Component/Animation.cpp new file mode 100644 index 0000000..737ea13 --- /dev/null +++ b/source/EngineFrame/Component/Animation.cpp @@ -0,0 +1,307 @@ +#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 AdditionalOptions) +{ + this->AdditionalOptions = AdditionalOptions; + Init(AniPath); +} + +Animation::~Animation() +{ +} + +void Animation::Init(std::string AniPath) +{ + // 标记该组件需要渲染和更新 + addTag(Tag::RENDER); + addTag(Tag::UPDATE); + + 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 SpriteObj = new Sprite(); + if (!FrameObj.Img_Path.empty()) + { + if (AdditionalOptions) + { + FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path); + } + SpriteObj->Init(FrameObj.Img_Path, FrameObj.Img_Index); + } + 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) + { + SDL_Point PosData = Pos; + SDL_Point ParentPos = Parent->GetPos(); + if (Parent) + { + PosData.x += ParentPos.x; + PosData.y += ParentPos.y; + } + CurrentFrame->RenderByAni(deltaTime, PosData); + } + } +} + +void Animation::OnAdded(Actor *actor) +{ + Component::OnAdded(actor); + FlushFrame(0); +} + +void Animation::Clear() +{ +} + +void Animation::FlushFrame(int Index) +{ + // 同步当前帧 + CurrentFrameIndex = Index; + // 当前帧更换为本帧 + CurrentFrame = SpriteArr[CurrentFrameIndex]; + // 如果是整体染色 则直接使用染色帧 + // if (DyeAllFlag) CurrentFrame = DyeFrameList[CurrentFrameIndex]; + + AniScriptParser::AniFrame FrameInfo = FrameArr[CurrentFrameIndex]; + // 设置坐标 + SetPos(FrameInfo.Img_Pos); + // 设置下帧延迟 + NextFrameDelay = FrameInfo.Delay; + + std::unordered_map FlagBuf = FrameInfo.Flag; + // 关键帧 + if (FlagBuf.count("SET_FLAG")) + { + if (ChangeFrameCallback) + ChangeFrameCallback(std::get(FlagBuf["SET_FLAG"])); + } + // 播放音效 + if (FlagBuf.count("PLAY_SOUND")) + { + // TODO 还没有做音效的播放 + } + // 缩放 + if (FlagBuf.count("IMAGE_RATE")) + { + SDL_FPoint Rate = std::get(FlagBuf["IMAGE_RATE"]); + SDL_Point Size = CurrentFrame->GetSize(); + CurrentFrame->SetSize(SDL_Point{int(Size.x * Rate.x), (int)(Size.y * Rate.y)}); + } + // 线性减淡 + if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE")) + { + CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD); + } + // 旋转 + if (FlagBuf.count("IMAGE_ROTATE")) + { + CurrentFrame->SetAnchor(SDL_FPoint{0.5, 0.5}); + CurrentFrame->SetAngle(std::get(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 OldRgbaData = {255, 255, 255, 250}; + std::vector NewRgbaData = {255, 255, 255, 250}; + if (OldData.Flag.count("RGBA")) + OldRgbaData = std::get>(OldData.Flag["RGBA"]); + if (NewData.Flag.count("RGBA")) + NewRgbaData = std::get>(NewData.Flag["RGBA"]); + std::vector 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 染色 和 透明度还没弄 + } + // 坐标 + { + SDL_Point PosData = { + (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); + } + // 缩放 + { + SDL_FPoint OldRateData = {1.0, 1.0}; + SDL_FPoint NewRateData = {1.0, 1.0}; + if (OldData.Flag.count("IMAGE_RATE")) + { + OldRateData = std::get(OldData.Flag["IMAGE_RATE"]); + } + if (NewData.Flag.count("IMAGE_RATE")) + { + NewRateData = std::get(NewData.Flag["IMAGE_RATE"]); + } + SDL_Point ScaleData = { + (int)(CurrentFrame->GetSize().x * (OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate)), + (int)(CurrentFrame->GetSize().y * (OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate))}; + SDL_Point Size = CurrentFrame->GetSize(); + CurrentFrame->SetSize(SDL_Point{int(Size.x * ScaleData.x), (int)(Size.y * ScaleData.y)}); + } + // 旋转 + { + float OldAngleData = 0.0; + float NewAngleData = 0.0; + if (OldData.Flag.count("IMAGE_ROTATE")) + { + OldAngleData = std::get(OldData.Flag["IMAGE_ROTATE"]); + } + if (NewData.Flag.count("IMAGE_ROTATE")) + { + NewAngleData = std::get(NewData.Flag["IMAGE_ROTATE"]); + } + CurrentFrame->SetAngle(OldAngleData + (NewAngleData - OldAngleData) * InterRate); + } +} + +void Animation::SetSize(SDL_Point size) +{ + this->Size = size; +} + +void Animation::SetPos(SDL_Point pos) +{ + this->Pos = pos; +} + +SDL_Point Animation::GetPos() +{ + return this->Pos; +} + +SDL_Point Animation::GetSize() +{ + return this->Size; +} diff --git a/source/EngineFrame/Component/Animation.h b/source/EngineFrame/Component/Animation.h new file mode 100644 index 0000000..59a7612 --- /dev/null +++ b/source/EngineFrame/Component/Animation.h @@ -0,0 +1,98 @@ +#pragma once +#include "Tool/IntrusiveList.hpp" +#include "EngineFrame/Component/Component.h" +#include "EngineFrame/Component/Sprite.h" +#include "Asset/AnimationStruct.h" +#include + +class Animation : public Component +{ +private: + /* data */ +public: + Animation(/* args */); + Animation(std::string AniPath); + Animation(std::string AniPath, std::function AdditionalOptions); + ~Animation(); + + // 显式引入基类的Init方法,避免隐藏 + using Component::Init; + + void Init(std::string AniPath); + void HandleEvents(SDL_Event *e) override; + void Update(float deltaTime) override; + void Render(float deltaTime) override; + void OnAdded(Actor *actor) 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; + // 当前帧时间 + int CurrentIndexT = 0; + // 当前帧 + RefPtr CurrentFrame; + // 下帧延迟 + int NextFrameDelay = 9999999; + // 染色Flag + bool DyeingFlag = false; + // 插值模式 + std::vector InterpolationFlag; + // 关键帧回调 + std::function ChangeFrameCallback; + // 结束回调 + std::function EndCallback; + // Ani的标签 + std::unordered_map AnimationFlag; + // 帧对象数组 + std::vector FrameArr; + // 图片精灵帧对象 + std::vector> 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 AdditionalOptions; + + SDL_Point Pos = {0, 0}; // 位置坐标 + SDL_Point Size = {0, 0}; // 大小 + int RenderZOrder = 0; // 渲染层级 + +public: + void SetSize(SDL_Point size); + void SetPos(SDL_Point pos); + SDL_Point GetSize(); + SDL_Point GetPos(); +}; diff --git a/source/EngineFrame/Component/Component.cpp b/source/EngineFrame/Component/Component.cpp index 7b05154..d118d7e 100644 --- a/source/EngineFrame/Component/Component.cpp +++ b/source/EngineFrame/Component/Component.cpp @@ -1,4 +1,5 @@ #include "Component.h" +#include "EngineFrame/Actor/Actor.h" Component::Component() { @@ -31,3 +32,50 @@ void Component::SetName(std::string name) { m_Name = name; } + +void Component::OnAdded(Actor *actor) +{ + this->Parent = actor; +} + +int Component::GetRenderZOrder() +{ + return this->RenderZOrder; +} + +void Component::ReorderComponents() +{ + if (Parent) + { + RefPtr me = this; + Parent->m_Components.Remove(me); + RefPtr sibling = Parent->m_Components.GetLast(); + if (sibling && sibling->GetRenderZOrder() > RenderZOrder) + { + sibling = sibling->GetPrev(); + while (sibling) + { + if (sibling->GetRenderZOrder() <= RenderZOrder) + break; + sibling = sibling->GetPrev(); + } + } + if (sibling) + { + Parent->m_Components.InsertAfter(me, sibling); + } + else + { + Parent->m_Components.PushFront(me); + } + } +} + +void Component::SetRenderZOrder(int zOrder) +{ + if (zOrder != this->RenderZOrder) + { + this->RenderZOrder = zOrder; + ReorderComponents(); + } +} \ No newline at end of file diff --git a/source/EngineFrame/Component/Component.h b/source/EngineFrame/Component/Component.h index 73a8beb..70289a1 100644 --- a/source/EngineFrame/Component/Component.h +++ b/source/EngineFrame/Component/Component.h @@ -8,9 +8,16 @@ class Actor; class Component : public RefObject, public TagGed, protected IntrusiveListValue> { + friend IntrusiveList>; + +public: + using IntrusiveListValue>::GetNext; + using IntrusiveListValue>::GetPrev; + private: /* data */ std::string m_Name; + public: Component(/* args */); ~Component(); @@ -21,11 +28,16 @@ public: virtual void Render(float deltaTime); virtual void Clear(); - using IntrusiveListValue>::GetNext; - using IntrusiveListValue>::GetPrev; - void SetName(std::string name); + virtual void OnAdded(Actor *actor); + // 设置渲染层级 + void SetRenderZOrder(int zOrder); + // 获取渲染层级 + int GetRenderZOrder(); + // 重新排列组件 + void ReorderComponents(); public: - Actor *Parent; // 指向父对象的指针,用于访问父对象 + Actor *Parent = nullptr; // 指向父对象的指针,用于访问父对象 + int RenderZOrder; // 渲染层级 }; diff --git a/source/EngineFrame/Component/Sprite.cpp b/source/EngineFrame/Component/Sprite.cpp index 64232d9..772b056 100644 --- a/source/EngineFrame/Component/Sprite.cpp +++ b/source/EngineFrame/Component/Sprite.cpp @@ -1,6 +1,7 @@ #include "Sprite.h" #include "EngineCore/Game.h" #include "Text.h" +#include "Render/Texture.h" Sprite::Sprite() { } @@ -12,37 +13,18 @@ Sprite::Sprite(std::string imgPath, int Index) Sprite::~Sprite() { - SDL_DestroyTexture(m_texture); } void Sprite::Init(std::string imgPath, int Index) { - Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(imgPath); - Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index]; + // 标记该组件需要渲染和更新 + addTag(Tag::RENDER); + addTag(Tag::UPDATE); - 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); - - if (Info != NULL) - { - // SDL_Log("第%d张图片的宽度为%d,高度为%d\n", Index, Buf.Width, Buf.Height); - } - TextureSize.x = Buf.Width; - TextureSize.y = Buf.Height; - Size.x = Buf.Width; - Size.y = Buf.Height; + m_texture = new Texture(imgPath, Index); } -SDL_Texture *Sprite::GetTexture() +RefPtr Sprite::GetTexture() { return m_texture; } @@ -53,6 +35,14 @@ void Sprite::HandleEvents(SDL_Event *e) void Sprite::Update(float deltaTime) { + // // 检测是否超出屏幕 + // bool isFullyOutOfScreen = + // (Pos.x + Size.x <= 0) // 完全在屏幕左侧外 + // || (Pos.x >= 1280) // 完全在屏幕右侧外 + // || (Pos.y + Size.y <= 0) // 完全在屏幕上侧外 + // || (Pos.y >= 720); // 完全在下侧外 + + // isRenderScreen = !isFullyOutOfScreen; } void Sprite::Render(float deltaTime) @@ -62,12 +52,30 @@ void Sprite::Render(float deltaTime) return; SDL_Rect dstrect = {Pos.x, Pos.y, Size.x, Size.y}; + if (isRenderScreen) + { + if (Angle != 0 || flip != SDL_FLIP_NONE) + { + SDL_RenderCopyEx(renderer, m_texture->GetTexture(), NULL, &dstrect, Angle, &Anchor, flip); + } + else + SDL_RenderCopy(renderer, m_texture->GetTexture(), NULL, &dstrect); + } +} + +void Sprite::RenderByAni(float deltaTime, SDL_Point pos) +{ + SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); + if (!m_texture) + return; + SDL_Rect dstrect = {Pos.x + pos.x, Pos.y + pos.y, Size.x, Size.y}; + if (Angle != 0 || flip != SDL_FLIP_NONE) { - SDL_RenderCopyEx(renderer, m_texture, NULL, &dstrect, Angle, &Anchor, flip); + SDL_RenderCopyEx(renderer, m_texture->GetTexture(), NULL, &dstrect, Angle, &Anchor, flip); } else - SDL_RenderCopy(renderer, m_texture, NULL, &dstrect); + SDL_RenderCopy(renderer, m_texture->GetTexture(), NULL, &dstrect); } void Sprite::Clear() @@ -81,7 +89,7 @@ void Sprite::SetPos(SDL_Point pos) void Sprite::SetBlendMode(SDL_BlendMode blendMode) { - SDL_SetTextureBlendMode(m_texture, blendMode); + m_texture->SetBlendMode(blendMode); } void Sprite::SetAngle(float angle) @@ -95,17 +103,24 @@ void Sprite::SetAnchor(SDL_FPoint anchor) Anchor.y = Size.y * anchor.y; } +void Sprite::SetSize(SDL_Point size) +{ + Size = size; +} + +SDL_Point Sprite::GetSize() +{ + return Size; +} + SDL_Point Sprite::GetPos() { return Pos; } - SDL_BlendMode Sprite::GetBlendMode() { - SDL_BlendMode blendMode; - SDL_GetTextureBlendMode(m_texture, &blendMode); - return blendMode; + return m_texture->GetBlendMode(); } float Sprite::GetAngle() diff --git a/source/EngineFrame/Component/Sprite.h b/source/EngineFrame/Component/Sprite.h index 709025f..24f8509 100644 --- a/source/EngineFrame/Component/Sprite.h +++ b/source/EngineFrame/Component/Sprite.h @@ -11,7 +11,7 @@ class Sprite : public Component { private: /* data */ - SDL_Texture *m_texture = nullptr; // 纹理指针,用于存储精灵的纹理资源 + RefPtr m_texture = nullptr; public: /** @@ -52,6 +52,11 @@ public: * @param deltaTime 时间增量 */ void Render(float deltaTime) override; + /** + * @brief 渲染组件 + * @param deltaTime 时间增量 + */ + void RenderByAni(float deltaTime, SDL_Point pos); /** * @brief 清理组件资源 */ @@ -61,12 +66,9 @@ public: * @brief 获取纹理 * @return SDL_Texture* 纹理指针 */ - SDL_Texture *GetTexture(); + RefPtr GetTexture(); public: - // 组件标签 - Tag m_tag = Tag::RENDER | Tag::UPDATE; // 标记该组件需要渲染和更新 - SDL_Point Pos = {0, 0}; // 位置坐标 SDL_Point TextureSize = {0, 0}; // 纹理大小 SDL_Point Size = {0, 0}; // 大小 @@ -74,6 +76,9 @@ public: float Angle = 0.0f; // 旋转角度 SDL_RendererFlip flip = SDL_FLIP_NONE; // 翻转 + // 是否在需要渲染的屏幕上 + bool isRenderScreen = true; + public: // 设置坐标 void SetPos(SDL_Point pos); @@ -81,8 +86,10 @@ public: void SetBlendMode(SDL_BlendMode blendMode); // 设置旋转角度 void SetAngle(float angle); - //设置中心点 + // 设置中心点 void SetAnchor(SDL_FPoint anchor); + // 设置大小 + void SetSize(SDL_Point size); // 获取坐标 SDL_Point GetPos(); @@ -92,4 +99,6 @@ public: float GetAngle(); // 获取中心点 SDL_FPoint GetAnchor(); + // 获取大小 + SDL_Point GetSize(); }; diff --git a/source/EngineFrame/Component/Text.cpp b/source/EngineFrame/Component/Text.cpp index 62c67c4..fe027a9 100644 --- a/source/EngineFrame/Component/Text.cpp +++ b/source/EngineFrame/Component/Text.cpp @@ -29,6 +29,10 @@ 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); diff --git a/source/EngineFrame/Render/Texture.cpp b/source/EngineFrame/Render/Texture.cpp new file mode 100644 index 0000000..21d1450 --- /dev/null +++ b/source/EngineFrame/Render/Texture.cpp @@ -0,0 +1,62 @@ +#include "Texture.h" +#include "EngineCore/Asset_ImagePack.h" +#include "EngineCore/Game.h" + +Texture::Texture() +{ +} + +Texture::Texture(std::string imgPath, int Index) +{ + Init(imgPath, Index); +} + +Texture::~Texture() +{ + SDL_DestroyTexture(m_texture); +} + +void Texture::Init(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); + + this->TexturePos.x = Buf.Xpos; + this->TexturePos.y = Buf.Ypos; + this->TextureSize.x = Buf.Width; + this->TextureSize.y = Buf.Height; + this->TextureFramepos.x = Buf.FrameXpos; + this->TextureFramepos.y = Buf.FrameYpos; +} + +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; +} \ No newline at end of file diff --git a/source/EngineFrame/Render/Texture.h b/source/EngineFrame/Render/Texture.h new file mode 100644 index 0000000..7a30c29 --- /dev/null +++ b/source/EngineFrame/Render/Texture.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +class Texture : public RefObject +{ +private: + SDL_Texture *m_texture = nullptr; + +public: + SDL_Point TextureSize = {0, 0}; // 纹理大小 + SDL_Point TexturePos = {0, 0}; // 纹理位置 + SDL_Point TextureFramepos = {0, 0}; // 帧域宽高 + +public: + Texture(/* args */); + Texture(std::string imgPath, int Index); + ~Texture(); + +public: + void Init(std::string imgPath, int Index); + + void SetBlendMode(SDL_BlendMode blendMode); + // 获取混合模式 + SDL_BlendMode GetBlendMode(); + SDL_Texture *GetTexture(); // 获取纹理 +}; diff --git a/source/EngineFrame/Scene/Scene.cpp b/source/EngineFrame/Scene/Scene.cpp index eb0f71a..ef4fe3d 100644 --- a/source/EngineFrame/Scene/Scene.cpp +++ b/source/EngineFrame/Scene/Scene.cpp @@ -1,5 +1,6 @@ -#include "EngineFrame/Scene/Scene.h" #include "Scene.h" +#include "EngineFrame/Scene/Scene.h" +#include void Scene::Enter() { @@ -7,7 +8,6 @@ void Scene::Enter() void Scene::Exit() { - } void Scene::AddChild(RefPtr actor) @@ -39,4 +39,3 @@ void Scene::Render(float deltaTime) void Scene::HandleEvents(SDL_Event *e) { } - diff --git a/source/EngineFrame/Scene/Scene.h b/source/EngineFrame/Scene/Scene.h index c0831ab..072e794 100644 --- a/source/EngineFrame/Scene/Scene.h +++ b/source/EngineFrame/Scene/Scene.h @@ -17,6 +17,7 @@ public: public: void AddChild(RefPtr actor); + private: IntrusiveList> m_Actors; }; \ No newline at end of file diff --git a/source/Tool/IntrusiveList.hpp b/source/Tool/IntrusiveList.hpp index f4508e5..4257b5a 100644 --- a/source/Tool/IntrusiveList.hpp +++ b/source/Tool/IntrusiveList.hpp @@ -237,7 +237,6 @@ public: inline reference operator*() const { - KGE_ASSERT(base_ && !is_end_); return const_cast(base_); } @@ -248,7 +247,6 @@ public: inline Iterator &operator++() { - KGE_ASSERT(base_ && !is_end_); value_type next = base_->GetNext(); if (next) base_ = next; @@ -266,7 +264,6 @@ public: inline Iterator &operator--() { - KGE_ASSERT(base_); if (is_end_) is_end_ = false; else diff --git a/source/Tool/Math.h b/source/Tool/Math.h new file mode 100644 index 0000000..9f22336 --- /dev/null +++ b/source/Tool/Math.h @@ -0,0 +1,282 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +class Math +{ +private: + /* data */ +public: + Math(/* args */) = default; + ~Math() = default; + +public: + static void InitRandomSeed() + { + static bool seeded = false; + if (!seeded) + { + srand(static_cast(time(nullptr))); + seeded = true; + } + } + + // 1. 获取X轴方向(0:目标在左侧,1:目标在右侧) + static int getDirectionToTargetX(float objX, float x) + { + return (objX > x) ? 0 : 1; + } + + // 2. 生成[Min, Max]范围内的随机整数(左闭右闭) + static int Rand(int Min, int Max) + { + InitRandomSeed(); // 确保随机数种子已初始化 + if (Min > Max) + { + throw std::invalid_argument("Rand: Min must be less than or equal to Max"); + } + // 计算随机数范围:(Max - Min + 1)个可能值 + int range = Max - Min + 1; + // rand()返回[0, RAND_MAX],通过取模和偏移实现范围映射 + return Min + (rand() % range); + } + + // 3. 从数组中随机获取一个元素(支持任意可索引容器) + template + static T GetRandomElementFromArray(const std::vector &arr) + { + if (arr.empty()) + { + throw std::invalid_argument("GetRandomElementFromArray: Array is empty"); + } + int randomIndex = Rand(0, static_cast(arr.size()) - 1); + return arr[randomIndex]; + } + + // 5. 根据方向计算偏移后的X坐标 + static float GetDistancePos(float startX, int direction, float offsetX) + { + return (direction == 0) ? (startX - offsetX) : (startX + offsetX); + } + + // 6. 通过两点坐标计算旋转角度(预留实现,需根据具体需求补充) + static float getRorateAngleByCurrentPos(float x1, float y1, float z1, float x2, float y2, float z2) + { + // 示例实现:计算X-Z平面内的角度(可根据需求调整为3D角度) + float dx = x2 - x1; + float dz = z2 - z1; + // atan2(dz, dx):返回与X轴正方向的夹角(弧度),范围[-π, π] + return std::atan2(dz, dx); + } + + // 8. 标准抛物线计算(y = a(x - c/2)² + b,开口向下) + static float sq_Parabola(float x, float b, float c) + { + if (c == 0) + { + throw std::invalid_argument("sq_Parabola: c cannot be zero"); + } + // 计算抛物线系数a(确保顶点在x=c/2,y=b) + float a = (-4.0f * b) / (c * c); + return a * (x - c / 2.0f) * (x - c / 2.0f) + b; + } + + // 9. 计算2D平面两点距离(Y轴权重0.29,用于透视校正) + static float Get2D_Distance(float x1, float y1, float x2, float y2) + { + float offsetX = x1 - x2; + float offsetY = (y1 - y2) * 0.29f; + // 勾股定理计算距离 + return std::sqrt(offsetX * offsetX + offsetY * offsetY); + } + + // 10. 判断角度是否在[startA, endA]形成的锐角范围内(角度单位:度) + static bool CheckAngleIsInArea(float judge, float startA, float endA) + { + // 步骤1:将角度标准化到[0, 360)范围 + auto normalizeAngle = [](float angle) + { + angle = std::fmod(angle, 360.0f); + return (angle < 0) ? (angle + 360.0f) : angle; + }; + + startA = normalizeAngle(startA); + endA = normalizeAngle(endA); + judge = normalizeAngle(judge); + + // 特殊情况:范围跨0度(如startA=350°,endA=10°) + if (startA > 270.0f && startA < 360.0f && endA > 0.0f && endA < 90.0f) + { + return (judge >= startA && judge <= 360.0f) || (judge >= 0.0f && judge <= endA); + } + // 普通情况:范围不跨0度 + else + { + // 处理startA > endA的正常范围(如startA=30°,endA=60°) + if (startA > endA) + { + std::swap(startA, endA); + } + return (judge >= startA && judge <= endA); + } + } + + // 11. 弧度转角度 + static float toDegree(float radian) + { + return radian * 57.2957795f; // 180/π ≈ 57.2957795 + } + + // 12. 角度转弧度 + static float toRadian(float degree) + { + return degree * 0.0174532925f; // π/180 ≈ 0.0174532925 + } + + // 13. 判断点是否在立方体内(立方体由对角点定义) + static bool pointIsInCubeArea(float px, float py, float pz, + float startX, float startY, float startZ, + float endX, float endY, float endZ) + { + // 计算立方体中心点和半边长 + float cubeCenterX = (startX + endX) / 2.0f; + float cubeXLen = std::fabs(startX - endX) / 2.0f; + + float cubeCenterY = (startY + endY) / 2.0f; + float cubeYLen = std::fabs(startY - endY) / 2.0f; + + float cubeCenterZ = (startZ + endZ) / 2.0f; + float cubeZLen = std::fabs(startZ - endZ) / 2.0f; + + // 点到各轴中心点的距离 ≤ 半边长 → 在立方体内 + return (std::fabs(px - cubeCenterX) <= cubeXLen + 1e-6f) && + (std::fabs(py - cubeCenterY) <= cubeYLen + 1e-6f) && + (std::fabs(pz - cubeCenterZ) <= cubeZLen + 1e-6f); + } + + // 14. 立方体与立方体碰撞检测(基于顶点和中心点判断) + static bool CubeAndCubeCollection(float c1StartX, float c1StartY, float c1StartZ, + float c1EndX, float c1EndY, float c1EndZ, + float c2StartX, float c2StartY, float c2StartZ, + float c2EndX, float c2EndY, float c2EndZ) + { + // 优化说明:原Squirrel代码判断过多冗余点,此处保留核心顶点+中心点判断 + const std::vector> c1Points = { + // 立方体1的8个顶点 + {c1StartX, c1StartY, c1StartZ}, + {c1EndX, c1StartY, c1StartZ}, + {c1StartX, c1EndY, c1StartZ}, + {c1EndX, c1EndY, c1StartZ}, + {c1StartX, c1StartY, c1EndZ}, + {c1EndX, c1StartY, c1EndZ}, + {c1StartX, c1EndY, c1EndZ}, + {c1EndX, c1EndY, c1EndZ}, + // 立方体1的中心点 + {(c1StartX + c1EndX) / 2, (c1StartY + c1EndY) / 2, (c1StartZ + c1EndZ) / 2}}; + + const std::vector> c2Points = { + // 立方体2的8个顶点 + {c2StartX, c2StartY, c2StartZ}, + {c2EndX, c2StartY, c2StartZ}, + {c2StartX, c2EndY, c2StartZ}, + {c2EndX, c2EndY, c2StartZ}, + {c2StartX, c2StartY, c2EndZ}, + {c2EndX, c2StartY, c2EndZ}, + {c2StartX, c2EndY, c2EndZ}, + {c2EndX, c2EndY, c2EndZ}, + // 立方体2的中心点 + {(c2StartX + c2EndX) / 2, (c2StartY + c2EndY) / 2, (c2StartZ + c2EndZ) / 2}}; + + // 检查立方体1的点是否在立方体2内 + for (const auto &[x, y, z] : c1Points) + { + if (pointIsInCubeArea(x, y, z, c2StartX, c2StartY, c2StartZ, c2EndX, c2EndY, c2EndZ)) + { + return true; + } + } + + // 检查立方体2的点是否在立方体1内 + for (const auto &[x, y, z] : c2Points) + { + if (pointIsInCubeArea(x, y, z, c1StartX, c1StartY, c1StartZ, c1EndX, c1EndY, c1EndZ)) + { + return true; + } + } + + return false; + } + + // 15. 计算三角形面积(叉乘法,避免开方,效率更高) + static float get3PointArea(float x1, float y1, float x2, float y2, float x3, float y3) + { + // 面积公式:0.5 * |x1(y2-y3) + x2(y3-y1) + x3(y1-y2)| + return 0.5f * std::fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); + } + + // 16. 计算四边形面积(拆分为两个三角形面积之和) + static float get4PointArea(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) + { + // 四边形拆分为:(x1,y1)-(x2,y2)-(x3,y3) 和 (x2,y2)-(x3,y3)-(x4,y4) + float area1 = get3PointArea(x1, y1, x2, y2, x3, y3); + float area2 = get3PointArea(x2, y2, x3, y3, x4, y4); + return area1 + area2; + } + + // 17. 判断点是否在四边形内(面积比较法,要求四边形顶点按顺序排列) + static bool pointIsIn4PointArea(float px, float py, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4) + { + const float eps = 10.0f; // 容差(原Squirrel代码定义为10.0) + float totalArea = get4PointArea(x1, y1, x2, y2, x3, y3, x4, y4); + // 点与四边形各边组成的4个三角形面积之和 + float sumArea = get3PointArea(x1, y1, x2, y2, px, py) + + get3PointArea(x2, y2, x3, y3, px, py) + + get3PointArea(x3, y3, x4, y4, px, py) + + get3PointArea(x4, y4, x1, y1, px, py); + + // 面积差在容差范围内 → 点在四边形内 + return std::fabs(totalArea - sumArea) < eps; + } + + // 18. 判断点是否在矩形内(矩形由坐标数组定义,格式:[x, y, width, height]) + static bool PointIsInSquare(float x1, float y1, const std::vector &SquareArr) + { + if (SquareArr.size() != 4) + { + throw std::invalid_argument("PointIsInSquare: SquareArr must have 4 elements (x, y, width, height)"); + } + float sqX = SquareArr[0]; + float sqY = SquareArr[1]; + float sqWidth = SquareArr[2]; + float sqHeight = SquareArr[3]; + + // 点的X在[sqX, sqX+width],Y在[sqY, sqY+height] → 在矩形内 + return (x1 >= sqX - 1e-6f) && (x1 <= sqX + sqWidth + 1e-6f) && + (y1 >= sqY - 1e-6f) && (y1 <= sqY + sqHeight + 1e-6f); + } + + static float getUniformVelocity(float sv, float ev, float currentRate, float maxRate) + { + // 避免除零错误 + if (maxRate <= 0.0f) + { + throw std::invalid_argument("maxRate must be greater than 0"); + } + + // 计算当前进度比例(0.0到1.0之间) + float rate = currentRate / maxRate; + // 限制比例在[0, 1]范围内,避免超出边界 + rate = std::clamp(rate, 0.0f, 1.0f); + + // 计算变化量并返回当前值 + float varyValue = ev - sv; + return sv + varyValue * rate; + } +}; \ No newline at end of file diff --git a/source/Tool/TagGed.h b/source/Tool/TagGed.h index 4121f37..30c87d4 100644 --- a/source/Tool/TagGed.h +++ b/source/Tool/TagGed.h @@ -3,7 +3,7 @@ #include enum class Tag { - NONE = 0, // 无标签 + NONE = 0, // 无标签 UPDATE = 1 << 0, // 更新标签 RENDER = 1 << 1, // 渲染标签 }; @@ -31,13 +31,15 @@ public: // 添加标签 void addTag(Tag tag) { - m_tags |= static_cast(tag); + if (!hasTag(tag)) + m_tags |= static_cast(tag); } // 移除标签 void removeTag(Tag tag) { - m_tags &= ~static_cast(tag); + if (hasTag(tag)) + m_tags &= ~static_cast(tag); } // 判断是否包含指定标签 @@ -58,4 +60,3 @@ public: m_tags = 0; } }; - diff --git a/source/Tool/Tool_String.hpp b/source/Tool/Tool_String.cpp similarity index 81% rename from source/Tool/Tool_String.hpp rename to source/Tool/Tool_String.cpp index b7945f5..29703df 100644 --- a/source/Tool/Tool_String.hpp +++ b/source/Tool/Tool_String.cpp @@ -1,8 +1,4 @@ -#pragma once -#include -#include -#include - +#include "Tool/Tool_String.h" std::string Tool_toLowerCase(const std::string &str) { std::string result = str; diff --git a/source/Tool/Tool_String.h b/source/Tool/Tool_String.h new file mode 100644 index 0000000..fb65cb0 --- /dev/null +++ b/source/Tool/Tool_String.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include +#include + +std::string Tool_toLowerCase(const std::string &str); \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 4ad4e23..81c3b07 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -46,6 +46,7 @@ void RunSetup() int main(int argc, char *argv[]) { + socketInitializeDefault(); nxlinkStdio(); // 启用nxlink调试输出 curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化libcurl @@ -67,7 +68,7 @@ int main(int argc, char *argv[]) // 初始化Squirrel脚本系统 SquirrelEx::GetInstance().Init(); // 请求脚本 - SquirrelEx::GetInstance().RequestNetScript(PC_IP, PC_SCRIPT_PORT); + // SquirrelEx::GetInstance().RequestNetScript(PC_IP, PC_SCRIPT_PORT); // 初始化游戏引擎 Game &game = Game::GetInstance(); diff --git a/source_game/Asset/AnimationStruct.cpp b/source_game/Asset/AnimationStruct.cpp new file mode 100644 index 0000000..a755ad8 --- /dev/null +++ b/source_game/Asset/AnimationStruct.cpp @@ -0,0 +1,355 @@ +#include "Asset/AnimationStruct.h" + +namespace AniScriptParser +{ + + std::string Get_Ani_Flag(int data) + { + switch (data) + { + case 0: + return "LOOP"; + case 1: + return "SHADOW"; + case 3: + return "COORD"; + case 7: + return "IMAGE_RATE"; + case 8: + return "IMAGE_ROTATE"; + case 9: + return "RGBA"; + case 10: + return "INTERPOLATION"; + case 11: + return "GRAPHIC_EFFECT"; + case 12: + return "DELAY"; + case 13: + return "DAMAGE_TYPE"; + case 14: + return "DAMAGE_BOX"; + case 15: + return "ATTACK_BOX"; + case 16: + return "PLAY_SOUND"; + case 17: + return "PRELOAD"; + case 18: + return "SPECTRUM"; + case 23: + return "SET_FLAG"; + case 24: + return "FLIP_TYPE"; + case 25: + return "LOOP_START"; + case 26: + return "LOOP_END"; + case 27: + return "CLIP"; + case 28: + return "OPERATION"; + default: + return ""; + } + } + + std::string Get_Ani_Effect_Type(int data) + { + switch (data) + { + case 0: + return "NONE"; + case 1: + return "DODGE"; + case 2: + return "LINEARDODGE"; + case 3: + return "DARK"; + case 4: + return "XOR"; + case 5: + return "MONOCHROME"; + case 6: + return "SPACEDISTORT"; + default: + return ""; + } + }; + + std::string Get_Ani_Flip_Type(int data) + { + switch (data) + { + case 1: + return "HORIZON"; + case 2: + return "VERTICAL"; + case 3: + return "ALL"; + default: + return ""; + } + }; + + std::string Get_Ani_Damage_Type(int data) + { + switch (data) + { + case 0: + return "NORMAL"; + case 1: + return "SUPERARMOR"; + case 2: + return "UNBREAKABLE"; + default: + return ""; + } + }; + + /////////以下是读取逻辑 + AniInfo StructAniInfo(Blob blob) + { + AniInfo Info; + int Frame_Max = blob.getUShort(); + int Img_Count = blob.getUShort(); + + // Img的路径读取 存入数组 + for (int i = 0; i < Img_Count; i++) + { + int Buf = blob.getInt(); + std::string ImgPath = "sprite/" + blob.getString(Buf); + Info.Img_List.push_back(ImgPath); + } + + // Ani头部标签数量 + int Ani_H_Item_Count = blob.getUShort(); + // 处理标签 + for (int i = 0; i < Ani_H_Item_Count; i++) + { + int Type = blob.getUShort(); + switch (Type) + { + case 0: + case 1: + { + std::string Key = AniScriptParser::Get_Ani_Flag(Type); + int Value = blob.getByte(); + Info.Flag.emplace(Key, Value); + break; + } + case 3: + case 28: + { + std::string Key = AniScriptParser::Get_Ani_Flag(Type); + int Value = blob.getUShort(); + Info.Flag.emplace(Key, Value); + break; + } + case 18: + { + blob.getByte(); + blob.getInt(); + blob.getInt(); + blob.getInt(); + blob.get256(); + blob.get256(); + blob.get256(); + blob.get256(); + blob.getUShort(); + } + default: + break; + } + } + + // 读取每一个Img + for (int i = 0; i < Frame_Max; i++) + { + AniFrame FrameObject; + + // 碰撞框项目数量 + int Ani_Box_Item_Count = blob.getUShort(); + for (int j = 0; j < Ani_Box_Item_Count; j++) + { + int Box_Type = blob.getUShort(); + std::vector D_Box_b; + for (int k = 0; k < 6; k++) + { + D_Box_b.push_back(blob.getInt()); + } + if (Box_Type == 15) + FrameObject.AttackBox.push_back(D_Box_b); + else + FrameObject.DamageBox.push_back(D_Box_b); + } + + // 调用的第几个Img + int Index_Buf = blob.getShort(); + if (Index_Buf != -1) + { + FrameObject.Img_Path = Tool_toLowerCase(Info.Img_List[Index_Buf]); + FrameObject.Img_Index = blob.getUShort(); + } + else + { + FrameObject.Img_Path = ""; + FrameObject.Img_Index = 0; + } + + // 坐标 + FrameObject.Img_Pos = SDL_Point{blob.getInt(), blob.getInt()}; + + // Img中的项目数量 + int Img_Flag_Count = blob.getUShort(); + for (int j = 0; j < Img_Flag_Count; j++) + { + int Img_Flag_Type = blob.getUShort(); + std::string Key; + int Value; + switch (Img_Flag_Type) + { + case 0: + case 1: + case 10: + { + Key = AniScriptParser::Get_Ani_Flag(Img_Flag_Type); + Value = blob.getByte(); + FrameObject.Flag.emplace(Key, Value); + break; + } + case 3: + { + Key = "COORD"; + Value = blob.getUShort(); + FrameObject.Flag.emplace(Key, Value); + break; + } + case 17: + { + Key = "PRELOAD"; + Value = 1; + FrameObject.Flag.emplace(Key, Value); + break; + } + case 7: + { + Key = "IMAGE_RATE"; + SDL_FPoint pos{ + blob.getFloat(), + blob.getFloat()}; + FrameObject.Flag.emplace(Key, pos); + break; + } + case 8: + { + Key = "IMAGE_ROTATE"; + Value = blob.getFloat(); + FrameObject.Flag.emplace(Key, Value); + break; + } + case 9: + { + Key = "RGBA"; + std::vector RGBA = { + (int)blob.get256(), + (int)blob.get256(), + (int)blob.get256(), + (int)blob.get256()}; + FrameObject.Flag.emplace(Key, RGBA); + break; + } + case 11: + { + int Effect_Type = blob.getUShort(); + Key = "GRAPHIC_EFFECT_" + AniScriptParser::Get_Ani_Effect_Type(Effect_Type); + std::vector effect; + switch (Effect_Type) + { + case 5: + { + effect.push_back(blob.get256()); + effect.push_back(blob.get256()); + effect.push_back(blob.get256()); + break; + } + case 6: + { + effect.push_back(blob.get256()); + effect.push_back(blob.get256()); + break; + } + } + FrameObject.Flag.emplace(Key, effect); + break; + } + case 12: + { + Value = blob.getInt(); + FrameObject.Delay = Value; + break; + } + case 13: + { + Key = "DAMAGE_TYPE"; + std::string DTYPE = AniScriptParser::Get_Ani_Damage_Type(blob.getUShort()); + FrameObject.Flag.emplace(Key, DTYPE); + break; + } + case 16: + { + int SoundTempSize = blob.getInt(); + Key = "PLAY_SOUND"; + std::string sound = blob.getString(SoundTempSize); + FrameObject.Flag.emplace(Key, sound); + break; + } + case 23: + { + Key = "SET_FLAG"; + Value = blob.getInt(); + FrameObject.Flag.emplace(Key, Value); + break; + } + case 24: + { + Key = "FLIP_TYPE"; + std::string FTYPEValue = AniScriptParser::Get_Ani_Flip_Type(blob.getUShort()); + FrameObject.Flag.emplace(Key, FTYPEValue); + break; + } + case 25: + { + Key = "LOOP_START"; + FrameObject.Flag.emplace(Key, 1); + break; + } + case 26: + { + Key = "LOOP_END"; + Value = blob.getInt(); + FrameObject.Flag.emplace(Key, Value); + break; + } + case 27: + { + Key = "CLIP"; + std::vector ClipArr{ + blob.getShort(), + blob.getShort(), + blob.getShort(), + blob.getShort(), + }; + FrameObject.Flag.emplace(Key, ClipArr); + break; + } + default: + break; + } + } + + Info.Frame.push_back(FrameObject); + } + return Info; + } +}; \ No newline at end of file diff --git a/source_game/Asset/AnimationStruct.h b/source_game/Asset/AnimationStruct.h index 89fe63e..2e041d9 100644 --- a/source_game/Asset/AnimationStruct.h +++ b/source_game/Asset/AnimationStruct.h @@ -4,134 +4,42 @@ #include #include #include +#include "Tool/Blob.hpp" +#include "Tool/Tool_String.h" -using AniFlag = std::variant< - int, - float, - SDL_Point, - SDL_FPoint, - std::string, - std::vector, - std::vector>; -struct AniFrame -{ - std::string Img_Path; // img路径 - int Img_Index; // img索引 - SDL_Point Img_Pos; // img位置 - std::vector> AttackBox; // 攻击框 - std::vector> DamageBox; // 受击框 - std::unordered_map Flag; // Frame特效数据 - int Delay; // 延迟 -}; -struct AniInfo -{ - std::vector Img_List; // img列表 - std::vector Frame; // ani列表 - std::unordered_map Flag; // ani特效数据 -}; namespace AniScriptParser { - static std::string Get_Ani_Flag(int data) + using AniFlag = std::variant< + int, + float, + SDL_Point, + SDL_FPoint, + std::string, + std::vector, + std::vector>; + struct AniFrame { - switch (data) - { - case 0: - return "LOOP"; - case 1: - return "SHADOW"; - case 3: - return "COORD"; - case 7: - return "IMAGE_RATE"; - case 8: - return "IMAGE_ROTATE"; - case 9: - return "RGBA"; - case 10: - return "INTERPOLATION"; - case 11: - return "GRAPHIC_EFFECT"; - case 12: - return "DELAY"; - case 13: - return "DAMAGE_TYPE"; - case 14: - return "DAMAGE_BOX"; - case 15: - return "ATTACK_BOX"; - case 16: - return "PLAY_SOUND"; - case 17: - return "PRELOAD"; - case 18: - return "SPECTRUM"; - case 23: - return "SET_FLAG"; - case 24: - return "FLIP_TYPE"; - case 25: - return "LOOP_START"; - case 26: - return "LOOP_END"; - case 27: - return "CLIP"; - case 28: - return "OPERATION"; - default: - return ""; - } - } - - static std::string Get_Ani_Effect_Type(int data) + std::string Img_Path; // img路径 + int Img_Index; // img索引 + SDL_Point Img_Pos; // img位置 + std::vector> AttackBox; // 攻击框 + std::vector> DamageBox; // 受击框 + std::unordered_map Flag; // Frame特效数据 + int Delay; // 延迟 + }; + struct AniInfo { - switch (data) - { - case 0: - return "NONE"; - case 1: - return "DODGE"; - case 2: - return "LINEARDODGE"; - case 3: - return "DARK"; - case 4: - return "XOR"; - case 5: - return "MONOCHROME"; - case 6: - return "SPACEDISTORT"; - default: - return ""; - } + std::vector Img_List; // img列表 + std::vector Frame; // ani列表 + std::unordered_map Flag; // ani特效数据 }; - static std::string Get_Ani_Flip_Type(int data) - { - switch (data) - { - case 1: - return "HORIZON"; - case 2: - return "VERTICAL"; - case 3: - return "ALL"; - default: - return ""; - } - }; + // 工具函数 + std::string Get_Ani_Flag(int data); + std::string Get_Ani_Effect_Type(int data); + std::string Get_Ani_Flip_Type(int data); + std::string Get_Ani_Damage_Type(int data); - static std::string Get_Ani_Damage_Type(int data) - { - switch (data) - { - case 0: - return "NORMAL"; - case 1: - return "SUPERARMOR"; - case 2: - return "UNBREAKABLE"; - default: - return ""; - } - }; + // Ani脚本的读取逻辑 + AniInfo StructAniInfo(Blob blob); }; \ No newline at end of file diff --git a/source_game/Asset/AssetManager.cpp b/source_game/Asset/AssetManager.cpp index 9fc748b..a2563bd 100644 --- a/source_game/Asset/AssetManager.cpp +++ b/source_game/Asset/AssetManager.cpp @@ -1,7 +1,5 @@ #include "AssetManager.h" #include "EngineCore/Asset_Script.h" -#include "Tool/Blob.hpp" -#include "Tool/Tool_String.hpp" AssetManager::AssetManager() { @@ -10,255 +8,14 @@ AssetManager::~AssetManager() { } -AniInfo AssetManager::StructAniInfo(std::string path) +AniScriptParser::AniInfo AssetManager::StructAniInfo(std::string path) { - AniInfo Info; std::vector Data = Asset_Script::GetInstance().GetFileContentByte(path); - Blob blob(Data); - - int Frame_Max = blob.getUShort(); - int Img_Count = blob.getUShort(); - - printf("Frame_Max : %d\n", Frame_Max); - printf("Img_Count : %d\n", Img_Count); - - // Img的路径读取 存入数组 - for (int i = 0; i < Img_Count; i++) + if (Data.size() > 0) { - int Buf = blob.getInt(); - std::string ImgPath = blob.getString(Buf); - printf("ImgPath : %s\n", ImgPath.c_str()); - Info.Img_List.push_back(ImgPath); + Blob blob(Data); + return AniScriptParser::StructAniInfo(blob); } - - // Ani头部标签数量 - int Ani_H_Item_Count = blob.getUShort(); - // 处理标签 - for (int i = 0; i < Ani_H_Item_Count; i++) - { - int Type = blob.getUShort(); - switch (Type) - { - case 0: - case 1: - { - std::string Key = AniScriptParser::Get_Ani_Flag(Type); - int Value = blob.getByte(); - Info.Flag.emplace(Key, Value); - break; - } - case 3: - case 28: - { - std::string Key = AniScriptParser::Get_Ani_Flag(Type); - int Value = blob.getUShort(); - Info.Flag.emplace(Key, Value); - break; - } - case 18: - { - blob.getByte(); - blob.getInt(); - blob.getInt(); - blob.getInt(); - blob.get256(); - blob.get256(); - blob.get256(); - blob.get256(); - blob.getUShort(); - } - default: - break; - } - } - - // 读取每一个Img - for (int i = 0; i < Frame_Max; i++) - { - AniFrame FrameObject; - - // 碰撞框项目数量 - int Ani_Box_Item_Count = blob.getUShort(); - for (int j = 0; j < Ani_Box_Item_Count; j++) - { - int Box_Type = blob.getUShort(); - std::vector D_Box_b; - for (int k = 0; k < 6; k++) - { - D_Box_b.push_back(blob.getInt()); - } - if (Box_Type == 15) - FrameObject.AttackBox.push_back(D_Box_b); - else - FrameObject.DamageBox.push_back(D_Box_b); - } - - // 调用的第几个Img - int Index_Buf = blob.getShort(); - if (Index_Buf != -1) - { - FrameObject.Img_Path = Tool_toLowerCase(Info.Img_List[Index_Buf]); - FrameObject.Img_Index = blob.getUShort(); - } - else - { - FrameObject.Img_Path = ""; - FrameObject.Img_Index = 0; - } - - // 坐标 - FrameObject.Img_Pos = SDL_Point{blob.getInt(), blob.getInt()}; - - // Img中的项目数量 - int Img_Flag_Count = blob.getUShort(); - for (int j = 0; j < Img_Flag_Count; j++) - { - int Img_Flag_Type = blob.getUShort(); - std::string Key; - int Value; - switch (Img_Flag_Type) - { - case 0: - case 1: - case 10: - { - Key = AniScriptParser::Get_Ani_Flag(Img_Flag_Type); - Value = blob.getInt(); - FrameObject.Flag.emplace(Key, Value); - break; - } - case 3: - { - Key = "COORD"; - Value = blob.getUShort(); - FrameObject.Flag.emplace(Key, Value); - break; - } - case 17: - { - Key = "PRELOAD"; - Value = 1; - FrameObject.Flag.emplace(Key, Value); - break; - } - case 7: - { - Key = "IMAGE_RATE"; - SDL_FPoint pos{ - blob.getFloat(), - blob.getFloat()}; - FrameObject.Flag.emplace(Key, pos); - break; - } - case 8: - { - Key = "IMAGE_ROTATE"; - Value = blob.getFloat(); - FrameObject.Flag.emplace(Key, Value); - break; - } - case 9: - { - Key = "RGBA"; - std::vector RGBA = { - blob.get256(), - blob.get256(), - blob.get256(), - blob.get256()}; - FrameObject.Flag.emplace(Key, RGBA); - break; - } - case 11: - { - int Effect_Type = blob.getUShort(); - Key = "GRAPHIC_EFFECT_" + AniScriptParser::Get_Ani_Effect_Type(Effect_Type); - std::vector effect; - switch (Effect_Type) - { - case 5: - { - effect.push_back(blob.get256()); - effect.push_back(blob.get256()); - effect.push_back(blob.get256()); - break; - } - case 6: - { - effect.push_back(blob.get256()); - effect.push_back(blob.get256()); - break; - } - } - FrameObject.Flag.emplace(Key, effect); - break; - } - case 12: - { - Value = blob.getInt(); - FrameObject.Delay = Value; - break; - } - case 13: - { - Key = "DAMAGE_TYPE"; - std::string DTYPE = AniScriptParser::Get_Ani_Damage_Type(blob.getUShort()); - FrameObject.Flag.emplace(Key, DTYPE); - break; - } - case 16: - { - int SoundTempSize = blob.getInt(); - Key = "PLAY_SOUND"; - std::string sound = blob.getString(SoundTempSize); - FrameObject.Flag.emplace(Key, sound); - break; - } - case 23: - { - Key = "SET_FLAG"; - Value = blob.getInt(); - FrameObject.Flag.emplace(Key, Value); - break; - } - case 24: - { - Key = "FLIP_TYPE"; - std::string FTYPEValue = AniScriptParser::Get_Ani_Flip_Type(blob.getUShort()); - FrameObject.Flag.emplace(Key, FTYPEValue); - break; - } - case 25: - { - Key = "LOOP_START"; - FrameObject.Flag.emplace(Key, 1); - break; - } - case 26: - { - Key = "LOOP_END"; - Value = blob.getInt(); - FrameObject.Flag.emplace(Key, Value); - break; - } - case 27: - { - Key = "CLIP"; - std::vector ClipArr{ - blob.getShort(), - blob.getShort(), - blob.getShort(), - blob.getShort(), - }; - FrameObject.Flag.emplace(Key, ClipArr); - break; - } - default: - break; - } - } - - Info.Frame.push_back(FrameObject); - } - - return Info; + SDL_LogError(0, "Ani加载失败 Error : %s", path.c_str()); + return AniScriptParser::AniInfo(); } diff --git a/source_game/Asset/AssetManager.h b/source_game/Asset/AssetManager.h index fa1b685..e34d0f5 100644 --- a/source_game/Asset/AssetManager.h +++ b/source_game/Asset/AssetManager.h @@ -22,5 +22,5 @@ private: public: // 构造Ani结构体 - AniInfo StructAniInfo(std::string path); + AniScriptParser::AniInfo StructAniInfo(std::string path); }; diff --git a/source_game/Scene/Scene_SelectCharacter_UI.hpp b/source_game/Scene/Scene_SelectCharacter_UI.hpp index 9820ff5..d1cceac 100644 --- a/source_game/Scene/Scene_SelectCharacter_UI.hpp +++ b/source_game/Scene/Scene_SelectCharacter_UI.hpp @@ -1,6 +1,7 @@ #pragma once #include "EngineFrame/Scene/Scene.h" #include "Asset/AssetManager.h" +#include "EngineFrame/Component/Animation.h" class Scene_SelectCharacter_UI : public Scene { @@ -17,7 +18,23 @@ public: public: void Enter() override { - AssetManager::GetInstance().StructAniInfo("common/training/main/main.ani"); + RefPtr actor = new Actor; + AddChild(actor); + + RefPtr ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani"); + actor->AddComponent(ani3); + ani3->SetRenderZOrder(1000); + + RefPtr ani = new Animation("common/anton/main.ani"); + actor->AddComponent(ani); + ani->SetRenderZOrder(500); + + RefPtr ani2 = new Animation("common/anton/face/0/0.ani"); + actor->AddComponent(ani2); + ani2->SetRenderZOrder(1000); + + actor->SetPos(SDL_Point{500, 500}); + SDL_Log("进入了选择角色场景!"); }; // void HandleEvents(SDL_Event *e) override;