This commit is contained in:
lenheart 2025-09-18 15:21:43 +08:00
parent c1c6c7fe7f
commit 1032578ed1
32 changed files with 1409 additions and 446 deletions

4
.gitignore vendored
View File

@ -4,3 +4,7 @@ MyGame.lst
MyGame.elf
build/
romfs/
SwitchGame.elf
SwitchGame.nacp
SwitchGame.nro
.vscode/

View File

@ -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",

View File

@ -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__

View File

@ -76,5 +76,11 @@
},
"source_game/Asset/AnimationStruct.h": {
"description": "Ani结构数据"
},
"source/EngineFrame/Component/Component.h": {
"description": "组件基类"
},
"source/EngineFrame/Component/Animation.h": {
"description": "动画类"
}
}

View File

@ -36,10 +36,6 @@ public:
int Xpos;
// Ypos
int Ypos;
// Xpos
int XposEx = 0;
// Ypos
int YposEx = 0;
// 帧域X
int FrameXpos;
// 帧域Y

View File

@ -61,7 +61,7 @@ void Game::Init(std::function<void()> 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);

View File

@ -1,5 +1,6 @@
#include "Actor.h"
#include "EngineFrame/Scene/Scene.h"
#include <algorithm>
Actor::Actor()
{
@ -23,7 +24,11 @@ void Actor::Update(float deltaTime)
RefPtr<Component> 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<Component> 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> Component)
{
m_Components.PushBack(Component);
Component->Parent = this;
}
Component->OnAdded(this);
Component->ReorderComponents();
}
void Actor::RemoveComponent(RefPtr<Component> Component)
{
Component->Parent = nullptr;
m_Components.Remove(Component);
}
void Actor::SetPos(SDL_Point pos)
{
this->Pos = pos;
}
SDL_Point Actor::GetPos()
{
return this->Pos;
}

View File

@ -10,6 +10,7 @@ class Scene;
*/
class Actor : public Actor_base, protected IntrusiveListValue<RefPtr<Actor>>
{
public:
Actor();
~Actor() override;
@ -26,10 +27,15 @@ public:
public:
void AddComponent(RefPtr<Component> Component);
void RemoveComponent(RefPtr<Component> Component);
void SetPos(SDL_Point pos);
SDL_Point GetPos();
public:
Scene *Parent; // 指向父场景的指针表示该Actor所属的场景
Scene *Parent; // 指向父场景的指针表示该Actor所属的场景
SDL_Point Pos = {0, 0}; // 位置坐标
IntrusiveList<RefPtr<Component>> m_Components; // 组件列表
private:
IntrusiveList<RefPtr<Component>> m_Components;
};

View File

@ -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;
}

View File

@ -28,4 +28,9 @@ public:
private:
/* data */
UpdateCallback cb_update_; // 更新时的回调函数
int RenderZOrder = 0; // 渲染层级
public:
int GetRenderZOrder();
void SetRenderZOrder(int zOrder);
};

View File

@ -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<std::string(std::string)> 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<Sprite> 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<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"))
{
SDL_FPoint Rate = std::get<SDL_FPoint>(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<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 染色 和 透明度还没弄
}
// 坐标
{
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<SDL_FPoint>(OldData.Flag["IMAGE_RATE"]);
}
if (NewData.Flag.count("IMAGE_RATE"))
{
NewRateData = std::get<SDL_FPoint>(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<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);
}
}
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;
}

View File

@ -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 <functional>
class Animation : public Component
{
private:
/* data */
public:
Animation(/* args */);
Animation(std::string AniPath);
Animation(std::string AniPath, std::function<std::string(std::string)> 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<Sprite> CurrentFrame;
// 下帧延迟
int NextFrameDelay = 9999999;
// 染色Flag
bool DyeingFlag = false;
// 插值模式
std::vector<AniScriptParser::AniFrame> InterpolationFlag;
// 关键帧回调
std::function<void(int)> ChangeFrameCallback;
// 结束回调
std::function<void()> EndCallback;
// Ani的标签
std::unordered_map<std::string, AniScriptParser::AniFlag> AnimationFlag;
// 帧对象数组
std::vector<AniScriptParser::AniFrame> FrameArr;
// 图片精灵帧对象
std::vector<RefPtr<Sprite>> 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<std::string(std::string)> 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();
};

View File

@ -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<Component> me = this;
Parent->m_Components.Remove(me);
RefPtr<Component> 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();
}
}

View File

@ -8,9 +8,16 @@
class Actor;
class Component : public RefObject, public TagGed, protected IntrusiveListValue<RefPtr<Component>>
{
friend IntrusiveList<RefPtr<Component>>;
public:
using IntrusiveListValue<RefPtr<Component>>::GetNext;
using IntrusiveListValue<RefPtr<Component>>::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<RefPtr<Component>>::GetNext;
using IntrusiveListValue<RefPtr<Component>>::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; // 渲染层级
};

View File

@ -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<Texture> 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()

View File

@ -11,7 +11,7 @@ class Sprite : public Component
{
private:
/* data */
SDL_Texture *m_texture = nullptr; // 纹理指针,用于存储精灵的纹理资源
RefPtr<Texture> 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<Texture> 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();
};

View File

@ -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);

View File

@ -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;
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <SDL.h>
#include <string>
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(); // 获取纹理
};

View File

@ -1,5 +1,6 @@
#include "EngineFrame/Scene/Scene.h"
#include "Scene.h"
#include "EngineFrame/Scene/Scene.h"
#include <algorithm>
void Scene::Enter()
{
@ -7,7 +8,6 @@ void Scene::Enter()
void Scene::Exit()
{
}
void Scene::AddChild(RefPtr<Actor> actor)
@ -39,4 +39,3 @@ void Scene::Render(float deltaTime)
void Scene::HandleEvents(SDL_Event *e)
{
}

View File

@ -17,6 +17,7 @@ public:
public:
void AddChild(RefPtr<Actor> actor);
private:
IntrusiveList<RefPtr<Actor>> m_Actors;
};

View File

@ -237,7 +237,6 @@ public:
inline reference operator*() const
{
KGE_ASSERT(base_ && !is_end_);
return const_cast<reference>(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

282
source/Tool/Math.h Normal file
View File

@ -0,0 +1,282 @@
#pragma once
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <stdexcept>
class Math
{
private:
/* data */
public:
Math(/* args */) = default;
~Math() = default;
public:
static void InitRandomSeed()
{
static bool seeded = false;
if (!seeded)
{
srand(static_cast<unsigned int>(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 <typename T>
static T GetRandomElementFromArray(const std::vector<T> &arr)
{
if (arr.empty())
{
throw std::invalid_argument("GetRandomElementFromArray: Array is empty");
}
int randomIndex = Rand(0, static_cast<int>(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/2y=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<std::tuple<float, float, float>> 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<std::tuple<float, float, float>> 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<float> &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;
}
};

View File

@ -3,7 +3,7 @@
#include <cstdint>
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<uint64_t>(tag);
if (!hasTag(tag))
m_tags |= static_cast<uint64_t>(tag);
}
// 移除标签
void removeTag(Tag tag)
{
m_tags &= ~static_cast<uint64_t>(tag);
if (hasTag(tag))
m_tags &= ~static_cast<uint64_t>(tag);
}
// 判断是否包含指定标签
@ -58,4 +60,3 @@ public:
m_tags = 0;
}
};

View File

@ -1,8 +1,4 @@
#pragma once
#include <string>
#include <cctype>
#include <algorithm>
#include "Tool/Tool_String.h"
std::string Tool_toLowerCase(const std::string &str)
{
std::string result = str;

View File

@ -0,0 +1,6 @@
#pragma once
#include <string>
#include <cctype>
#include <algorithm>
std::string Tool_toLowerCase(const std::string &str);

View File

@ -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();

View File

@ -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<int> 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<int> 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<float> 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<int> ClipArr{
blob.getShort(),
blob.getShort(),
blob.getShort(),
blob.getShort(),
};
FrameObject.Flag.emplace(Key, ClipArr);
break;
}
default:
break;
}
}
Info.Frame.push_back(FrameObject);
}
return Info;
}
};

View File

@ -4,134 +4,42 @@
#include <variant>
#include <unordered_map>
#include <SDL.h>
#include "Tool/Blob.hpp"
#include "Tool/Tool_String.h"
using AniFlag = std::variant<
int,
float,
SDL_Point,
SDL_FPoint,
std::string,
std::vector<int>,
std::vector<float>>;
struct AniFrame
{
std::string Img_Path; // img路径
int Img_Index; // img索引
SDL_Point Img_Pos; // img位置
std::vector<std::vector<int>> AttackBox; // 攻击框
std::vector<std::vector<int>> DamageBox; // 受击框
std::unordered_map<std::string, AniFlag> Flag; // Frame特效数据
int Delay; // 延迟
};
struct AniInfo
{
std::vector<std::string> Img_List; // img列表
std::vector<AniFrame> Frame; // ani列表
std::unordered_map<std::string, AniFlag> 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<int>,
std::vector<float>>;
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<std::vector<int>> AttackBox; // 攻击框
std::vector<std::vector<int>> DamageBox; // 受击框
std::unordered_map<std::string, AniFlag> 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<std::string> Img_List; // img列表
std::vector<AniFrame> Frame; // ani列表
std::unordered_map<std::string, AniFlag> 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);
};

View File

@ -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<BYTE> 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<int> 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<float> 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<float> 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<int> 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();
}

View File

@ -22,5 +22,5 @@ private:
public:
// 构造Ani结构体
AniInfo StructAniInfo(std::string path);
AniScriptParser::AniInfo StructAniInfo(std::string path);
};

View File

@ -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> actor = new Actor;
AddChild(actor);
RefPtr<Animation> ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani");
actor->AddComponent(ani3);
ani3->SetRenderZOrder(1000);
RefPtr<Animation> ani = new Animation("common/anton/main.ani");
actor->AddComponent(ani);
ani->SetRenderZOrder(500);
RefPtr<Animation> 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;