diff --git a/.vscode/settings.json b/.vscode/settings.json index 211e853..baf253f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -94,6 +94,7 @@ "string_view": "cpp", "numbers": "cpp", "semaphore": "cpp", - "cinttypes": "cpp" + "cinttypes": "cpp", + "netfwd": "cpp" } } \ No newline at end of file diff --git a/folder-alias.json b/folder-alias.json index 73ca75b..c661ff6 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -202,5 +202,17 @@ }, "source_game/Asset/Squirrel/Sqr_UI.hpp": { "description": "注册UI脚本" + }, + "source_game/Asset/Squirrel/Sqr_CommonFunc.hpp": { + "description": "通用工具函数" + }, + "source_game/Asset/Squirrel/Sqr_System.hpp": { + "description": "注册系统脚本" + }, + "source_game/Asset/Squirrel/Sqr_Asset.hpp": { + "description": "注册资源脚本" + }, + "source/EngineFrame/Component/NumberText.h": { + "description": "数字文本" } } \ No newline at end of file diff --git a/source/Asset/AnimationStruct.cpp b/source/Asset/AnimationStruct.cpp index a38bbd9..05bf4ee 100644 --- a/source/Asset/AnimationStruct.cpp +++ b/source/Asset/AnimationStruct.cpp @@ -277,7 +277,7 @@ namespace AniScriptParser case 7: { Key = "IMAGE_RATE"; - VecFPos pos{ + Vec2 pos{ blob.getFloat(), blob.getFloat()}; FrameObject.Flag.emplace(Key, pos); diff --git a/source/Asset/AnimationStruct.h b/source/Asset/AnimationStruct.h index 7b3ab9c..5e2c311 100644 --- a/source/Asset/AnimationStruct.h +++ b/source/Asset/AnimationStruct.h @@ -15,7 +15,7 @@ namespace AniScriptParser int, float, VecPos, - VecFPos, + Vec2, std::string, std::vector, std::vector>; diff --git a/source/EngineFrame/Base/BaseNode.cpp b/source/EngineFrame/Base/BaseNode.cpp index 0c33104..639cc92 100644 --- a/source/EngineFrame/Base/BaseNode.cpp +++ b/source/EngineFrame/Base/BaseNode.cpp @@ -1,4 +1,14 @@ #include "BaseNode.h" +#include "EngineCore/Game.h" +BaseNode::BaseNode() +{ + Game::GetInstance().m_nodeCount++; +} + +BaseNode::~BaseNode() +{ + Game::GetInstance().m_nodeCount--; +} void BaseNode::Init() { @@ -67,7 +77,7 @@ void BaseNode::SetCallbackOnUpdate(const UpdateCallback &cb) void BaseNode::SetChildIterationTransform() { - TransformT n_transform; + Transform n_transform; n_transform.position = transform.position + transformIter.position; n_transform.scale = transform.scale * transformIter.scale; n_transform.rotation = transform.rotation + transformIter.rotation; @@ -147,7 +157,7 @@ void BaseNode::AddChild(RefPtr child) // 如果组件有transform标签,则设置其位置 if (child->hasTag(Tag::TRANSFORM)) { - TransformT n_transform; + Transform n_transform; n_transform.position = transform.position + transformIter.position; n_transform.scale = transform.scale * transformIter.scale; n_transform.rotation = transform.rotation + transformIter.rotation; @@ -172,7 +182,7 @@ void BaseNode::OnAdded(BaseNode *node) m_Parent = node; } -void BaseNode::SetIterationTransform(TransformT n_transform) +void BaseNode::SetIterationTransform(Transform n_transform) { if (n_transform == transformIter) return; @@ -181,12 +191,12 @@ void BaseNode::SetIterationTransform(TransformT n_transform) SetChildIterationTransform(); } -TransformT BaseNode::GetIterationTransform() +Transform BaseNode::GetIterationTransform() { return transformIter; } -void BaseNode::SetTransform(TransformT n_transform) +void BaseNode::SetTransform(Transform n_transform) { if (n_transform == transform) return; @@ -195,12 +205,12 @@ void BaseNode::SetTransform(TransformT n_transform) SetChildIterationTransform(); } -TransformT BaseNode::GetTransform() +Transform BaseNode::GetTransform() { return transform; } -void BaseNode::SetPos(VecFPos pos) +void BaseNode::SetPos(Vec2 pos) { if (pos == this->transform.position) return; @@ -209,17 +219,17 @@ void BaseNode::SetPos(VecFPos pos) SetChildIterationTransform(); } -VecFPos BaseNode::GetPos() +Vec2 BaseNode::GetPos() { return this->transform.position; } -VecFPos BaseNode::GetWorldPos() +Vec2 BaseNode::GetWorldPos() { return this->transform.position + this->transformIter.position; } -void BaseNode::SetScale(VecFPos scale) +void BaseNode::SetScale(Vec2 scale) { if (scale == this->transform.scale) return; @@ -228,7 +238,7 @@ void BaseNode::SetScale(VecFPos scale) SetChildIterationTransform(); } -VecFPos BaseNode::GetScale() +Vec2 BaseNode::GetScale() { return this->transform.scale; } @@ -247,7 +257,7 @@ float BaseNode::GetRotation() return this->transform.rotation; } -void BaseNode::SetAnchor(VecFPos anchor) +void BaseNode::SetAnchor(Vec2 anchor) { if (anchor == this->Anchor) return; @@ -255,9 +265,9 @@ void BaseNode::SetAnchor(VecFPos anchor) Anchor.y = anchor.y; } -VecFPos BaseNode::GetAnchor() +Vec2 BaseNode::GetAnchor() { - VecFPos P; + Vec2 P; P.x = Anchor.x; P.y = Anchor.y; return P; @@ -298,7 +308,7 @@ float BaseNode::GetAlpha() return this->Alpha; } -void BaseNode::SetIterationPos(VecFPos pos) +void BaseNode::SetIterationPos(Vec2 pos) { if (pos == this->transformIter.position) return; @@ -307,12 +317,12 @@ void BaseNode::SetIterationPos(VecFPos pos) SetChildIterationTransform(); } -VecFPos BaseNode::GetIterationPos() +Vec2 BaseNode::GetIterationPos() { return this->transformIter.position; } -void BaseNode::SetIterationScale(VecFPos scale) +void BaseNode::SetIterationScale(Vec2 scale) { if (scale == this->transformIter.scale) return; @@ -321,7 +331,7 @@ void BaseNode::SetIterationScale(VecFPos scale) SetChildIterationTransform(); } -VecFPos BaseNode::GetIterationScale() +Vec2 BaseNode::GetIterationScale() { return this->transformIter.scale; } @@ -339,3 +349,13 @@ float BaseNode::GetIterationRotation() { return this->transformIter.rotation; } + +void BaseNode::SetBlendMode(LE_BlEND_MODE mode) +{ + this->_BlendMode = mode; +} + +LE_BlEND_MODE BaseNode::GetBlendMode() +{ + return this->_BlendMode; +} diff --git a/source/EngineFrame/Base/BaseNode.h b/source/EngineFrame/Base/BaseNode.h index 365e2f4..ad29148 100644 --- a/source/EngineFrame/Base/BaseNode.h +++ b/source/EngineFrame/Base/BaseNode.h @@ -6,7 +6,9 @@ #include "Tool/RefPtr.h" #include "Tool/IntrusiveList.hpp" #include "Tool/TagGed.h" -#include "Tool/TransformT.h" +#include "math/Transform.hpp" +#include "math/Math.h" +using namespace ember; class BaseNode : public RefObject, public TagGed, protected IntrusiveListValue> { @@ -28,23 +30,25 @@ public: // 渲染层级 int m_RenderZOrder = 0; // 二维仿射变换 - TransformT transform; + Transform transform; // 迭代的二维仿射变换 - TransformT transformIter; + Transform transformIter; // 锚点 - VecFPos Anchor = {0.f, 0.f}; + Vec2 Anchor = {0.f, 0.f}; // 大小 VecSize Size = {0, 0}; // 透明度 float Alpha = 1.f; + // 混合模式 + LE_BlEND_MODE _BlendMode = NONE; // 是否显示 bool Visible = true; // 计算渲染信息Flag (为了保证每帧只计算一次) bool CalcRenderInfoFlag = true; public: - BaseNode(/* args */) = default; - ~BaseNode() = default; + BaseNode(/* args */); + ~BaseNode(); public: virtual void Init(); @@ -81,45 +85,45 @@ public: // 被添加时 virtual void OnAdded(BaseNode *node); // 设置迭代的二维仿射变换 - void SetIterationTransform(TransformT transform); + void SetIterationTransform(Transform transform); // 获取迭代的二维仿射变换 - TransformT GetIterationTransform(); + Transform GetIterationTransform(); // 设置二维仿射变换 - void SetTransform(TransformT transform); + void SetTransform(Transform transform); // 获取二维仿射变换 - TransformT GetTransform(); + Transform GetTransform(); // 设置迭代的坐标 - virtual void SetIterationPos(VecFPos pos); + virtual void SetIterationPos(Vec2 pos); // 获取迭代的坐标 - VecFPos GetIterationPos(); + Vec2 GetIterationPos(); // 设置迭代的缩放 - virtual void SetIterationScale(VecFPos scale); + virtual void SetIterationScale(Vec2 scale); // 获取迭代的缩放 - VecFPos GetIterationScale(); + Vec2 GetIterationScale(); // 设置迭代的旋转角度 virtual void SetIterationRotation(float angle); // 获取迭代的旋转角度 float GetIterationRotation(); // 设置坐标 - virtual void SetPos(VecFPos pos); + virtual void SetPos(Vec2 pos); // 获取坐标 - VecFPos GetPos(); + Vec2 GetPos(); // 获取世界坐标 - VecFPos GetWorldPos(); + Vec2 GetWorldPos(); // 设置缩放 - virtual void SetScale(VecFPos scale); + virtual void SetScale(Vec2 scale); // 获取缩放 - VecFPos GetScale(); + Vec2 GetScale(); // 设置旋转角度 virtual void SetRotation(float angle); // 获取旋转角度 float GetRotation(); // 设置中心点 - virtual void SetAnchor(VecFPos anchor); + virtual void SetAnchor(Vec2 anchor); // 获取中心点 - VecFPos GetAnchor(); + Vec2 GetAnchor(); // 设置大小 virtual void SetSize(VecSize size); // 获取大小 @@ -132,6 +136,10 @@ public: virtual void SetAlpha(float alpha); // 获取透明度 float GetAlpha(); + // 设置混合模式 + void SetBlendMode(LE_BlEND_MODE mode); + // 获取混合模式 + LE_BlEND_MODE GetBlendMode(); //获取父对象 BaseNode *GetParent(); diff --git a/source/EngineFrame/Component/Animation.cpp b/source/EngineFrame/Component/Animation.cpp index 87369b6..227282d 100644 --- a/source/EngineFrame/Component/Animation.cpp +++ b/source/EngineFrame/Component/Animation.cpp @@ -45,8 +45,8 @@ void Animation::Init(std::string AniPath) FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path, this->AdditionalOptionsData); } SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index); - SpriteObj->SetAnchor(VecFPos(0.5f, 0.5f)); - SpriteObj->SetPos(VecFPos(FrameObj.Img_Pos.x, FrameObj.Img_Pos.y)); + SpriteObj->SetAnchor(Vec2(0.5f, 0.5f)); + SpriteObj->SetPos(Vec2(FrameObj.Img_Pos.x, FrameObj.Img_Pos.y)); SpriteObj->SetVisible(false); } else @@ -191,8 +191,8 @@ void Animation::FlushFrame(int Index) // 缩放 if (FlagBuf.count("IMAGE_RATE")) { - VecFPos Rate = std::get(FlagBuf["IMAGE_RATE"]); - CurrentFrame->SetScale(VecFPos{Rate.x, Rate.y}); + Vec2 Rate = std::get(FlagBuf["IMAGE_RATE"]); + CurrentFrame->SetScale(Vec2{Rate.x, Rate.y}); } // 线性减淡 if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE")) @@ -202,7 +202,7 @@ void Animation::FlushFrame(int Index) // 旋转 if (FlagBuf.count("IMAGE_ROTATE")) { - CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f}); + CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f}); CurrentFrame->SetRotation(std::get(FlagBuf["IMAGE_ROTATE"])); } // 染色 @@ -277,27 +277,27 @@ void Animation::InterpolationLogic() } // 坐标 { - VecFPos PosData = { + Vec2 PosData = { (OldData.Img_Pos.x + (NewData.Img_Pos.x - OldData.Img_Pos.x) * InterRate), (OldData.Img_Pos.y + (NewData.Img_Pos.y - OldData.Img_Pos.y) * InterRate)}; CurrentFrame->SetPos(PosData); } // 缩放 { - VecFPos OldRateData = {1.0f, 1.0f}; - VecFPos NewRateData = {1.0f, 1.0f}; + Vec2 OldRateData = {1.0f, 1.0f}; + Vec2 NewRateData = {1.0f, 1.0f}; if (OldData.Flag.count("IMAGE_RATE")) { - OldRateData = std::get(OldData.Flag["IMAGE_RATE"]); + OldRateData = std::get(OldData.Flag["IMAGE_RATE"]); } if (NewData.Flag.count("IMAGE_RATE")) { - NewRateData = std::get(NewData.Flag["IMAGE_RATE"]); + NewRateData = std::get(NewData.Flag["IMAGE_RATE"]); } - VecFPos RateData = { + Vec2 RateData = { OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate, OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate}; - CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f}); + CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f}); CurrentFrame->SetScale(RateData); } // 旋转 diff --git a/source/EngineFrame/Component/NumberText.cpp b/source/EngineFrame/Component/NumberText.cpp new file mode 100644 index 0000000..b370d17 --- /dev/null +++ b/source/EngineFrame/Component/NumberText.cpp @@ -0,0 +1,104 @@ +#include "NumberText.h" + +void NumberText::PreloadDigits() +{ + // 需要支持的字符:0-9和负号 + const std::string digits = "0123456789-"; + for (char c : digits) + { + std::string charStr(1, c); + // 渲染单个字符为纹理 + SDL_Surface *surface = TTF_RenderUTF8_Blended(m_font, charStr.c_str(), m_color); + if (!surface) + { + SDL_LogError(0, "数字字符渲染数字字符失败:%s", TTF_GetError()); + continue; + } + // 转换为RGBA格式 + SDL_Surface *rgbaSurface = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0); + SDL_FreeSurface(surface); + // 创建纹理并缓存 + Texture *tex = new Texture(); + tex->Init(rgbaSurface); + SDL_FreeSurface(rgbaSurface); + m_digitTextures[c] = tex; + } +} + +void NumberText::UpdateDigitSprites(const std::string &numStr) +{ + // // 先释放旧的精灵 + // for (auto *sprite : m_digitSprites) + // { + // if (sprite) + // { + // delete sprite; + // } + // } + // m_digitSprites.clear(); + + // // 计算总宽度(用于居中或左对齐) + // int totalWidth = 0; + // std::vector charWidths; // 记录每个字符的宽度 + // for (char c : numStr) + // { + // auto it = m_digitTextures.find(c); + // if (it == m_digitTextures.end()) + // continue; // 跳过不支持的字符 + // int w = it->second->getSize().width; + // totalWidth += w; + // charWidths.push_back(w); + // } + + // // 绘制每个字符(从左到右排列) + // float currentX = GetWorldPos().x; // 基于当前位置排列 + // float currentY = GetWorldPos().y; + // int index = 0; + // for (char c : numStr) + // { + // auto it = m_digitTextures.find(c); + // if (it == m_digitTextures.end()) + // continue; + + // // 创建字符精灵 + // Sprite *sprite = new Sprite(); + // sprite->SetTexture(it->second); + // sprite->SetPosition(Vec2(currentX, currentY)); + // sprite->SetSize(it->second->getSize()); + + // m_digitSprites.push_back(sprite); + + // // 移动到下一个字符的位置(预留1px间距) + // currentX += charWidths[index] + 1; + // index++; + // } +} + +NumberText::NumberText(TTF_Font *font, SDL_Color color) : m_font(font), m_color(color) +{ + PreloadDigits(); +} + +NumberText::~NumberText() +{ +} + +void NumberText::SetNumber(int number) +{ + if (number == m_currentNumber) + return; // 数字未变化则跳过 + m_currentNumber = number; + + // 转换数字为字符串(处理负数) + std::string numStr = std::to_string(number); + UpdateDigitSprites(numStr); // 更新数字精灵布局 +} + +void NumberText::Render() +{ + // for (auto *sprite : m_digitSprites) + // { + // if (sprite) + // sprite->Render(); + // } +} \ No newline at end of file diff --git a/source/EngineFrame/Component/NumberText.h b/source/EngineFrame/Component/NumberText.h new file mode 100644 index 0000000..9d358dd --- /dev/null +++ b/source/EngineFrame/Component/NumberText.h @@ -0,0 +1,44 @@ +#pragma once +#include "EngineFrame/Component/Text.h" +#include "EngineCore/Game.h" +#include "EngineFrame/Render/RenderManager.h" +#include +#include +#include + +// 数字文本类,高效处理数字更新 +class NumberText : public Text +{ +private: + // 字体 + TTF_Font *m_font; + // 文本颜色 + SDL_Color m_color; + + // 当前数字 + int m_currentNumber = 0; + // 数字字符纹理缓存('0'-'9'和'-') + std::unordered_map> m_digitTextures; + // 当前数字的字符精灵列表 + std::vector m_digitSprites; + + // 预加载0-9和负号的纹理 + void PreloadDigits(); + + // 更新数字精灵(根据新数字字符串重新排列字符) + void UpdateDigitSprites(const std::string &numStr); + +public: + // 构造函数:指定字体、颜色和字符尺寸 + NumberText(TTF_Font *font, SDL_Color color); + + ~NumberText(); + + // 设置数字(核心方法:仅更新变化的数字部分) + void SetNumber(int number); + + int GetNumber() const { return m_currentNumber; } + + // 重写Render,绘制所有数字字符 + void Render() override; +}; \ No newline at end of file diff --git a/source/EngineFrame/Component/RenderBase.cpp b/source/EngineFrame/Component/RenderBase.cpp index 46046c1..1074f04 100644 --- a/source/EngineFrame/Component/RenderBase.cpp +++ b/source/EngineFrame/Component/RenderBase.cpp @@ -40,13 +40,13 @@ void RenderBase::Render() Component::Render(); } -void RenderBase::SetIterationPos(VecFPos pos) +void RenderBase::SetIterationPos(Vec2 pos) { Component::SetIterationPos(pos); CalcRenderInfo(); // 更新渲染信息 } -void RenderBase::SetIterationScale(VecFPos scale) +void RenderBase::SetIterationScale(Vec2 scale) { Component::SetIterationScale(scale); CalcRenderInfo(); // 更新渲染信息 @@ -60,14 +60,14 @@ void RenderBase::SetIterationRotation(float angle) CalcRenderInfo(); // 更新渲染信息 } -void RenderBase::SetPos(VecFPos pos) +void RenderBase::SetPos(Vec2 pos) { Component::SetPos(pos); CalcRenderInfo(); // 更新渲染信息 } -void RenderBase::SetScale(VecFPos scale) +void RenderBase::SetScale(Vec2 scale) { Component::SetScale(scale); CalcRenderInfo(); // 更新渲染信息 @@ -79,7 +79,7 @@ void RenderBase::SetRotation(float angle) CalcRenderInfo(); // 更新渲染信息 } -void RenderBase::SetAnchor(VecFPos anchor) +void RenderBase::SetAnchor(Vec2 anchor) { Component::SetAnchor(anchor); CalcRenderInfo(); // 更新渲染信息 diff --git a/source/EngineFrame/Component/RenderBase.h b/source/EngineFrame/Component/RenderBase.h index 08a015b..98b542c 100644 --- a/source/EngineFrame/Component/RenderBase.h +++ b/source/EngineFrame/Component/RenderBase.h @@ -1,7 +1,6 @@ #pragma once #include "EngineFrame/Component/Component.h" -#include "Tool/TransformT.h" class RenderBase : public Component { @@ -15,11 +14,13 @@ public: // 翻转Flag SDL_RendererFlip flip = SDL_FLIP_NONE; // 锚点坐标 - VecFPos AnchorPos; + Vec2 AnchorPos; // 是否显示 bool Visible = true; // 是否在屏幕内 bool IsInScreen = false; + //渲染矩阵 + GlMatrix RenderMatrix; }; public: @@ -35,20 +36,20 @@ public: public: public: // 设置迭代的坐标 - void SetIterationPos(VecFPos pos) override; + void SetIterationPos(Vec2 pos) override; // 设置迭代的缩放 - void SetIterationScale(VecFPos scale) override; + void SetIterationScale(Vec2 scale) override; // 设置迭代的旋转角度 void SetIterationRotation(float angle) override; // 设置坐标 - void SetPos(VecFPos pos) override; + void SetPos(Vec2 pos) override; // 设置缩放 - void SetScale(VecFPos scale) override; + void SetScale(Vec2 scale) override; // 设置旋转角度 void SetRotation(float angle) override; // 设置中心点 - void SetAnchor(VecFPos anchor) override; + void SetAnchor(Vec2 anchor) override; // 计算渲染信息 void CalcRenderInfo() override; diff --git a/source/EngineFrame/Component/Sprite.cpp b/source/EngineFrame/Component/Sprite.cpp index 00ce9e0..c800e5a 100644 --- a/source/EngineFrame/Component/Sprite.cpp +++ b/source/EngineFrame/Component/Sprite.cpp @@ -43,6 +43,35 @@ RefPtr Sprite::GetTexture() return m_texture; } +GlMatrix Sprite::matrix3x2ToGLMatrix(const Matrix3x2 &mat) +{ + return { + // 列0:x轴线性变换 + mat._11, // [0][0] + mat._12, // [1][0] + 0.0f, // [2][0] + 0.0f, // [3][0] + + // 列1:y轴线性变换 + mat._21, // [0][1] + mat._22, // [1][1] + 0.0f, // [2][1] + 0.0f, // [3][1] + + // 列2:z轴(固定) + 0.0f, // [0][2] + 0.0f, // [1][2] + 1.0f, // [2][2] + 0.0f, // [3][2] + + // 列3:平移 + mat._31, // [0][3](x平移) + mat._32, // [1][3](y平移) + 0.0f, // [2][3] + 1.0f // [3][3] + }; +} + void Sprite::CalcRenderInfoLogic() { // 获取至在最终的父对象检查是否显示 @@ -151,7 +180,9 @@ void Sprite::Render() if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible) { - SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos; + SDL_FPoint AnchorPos; + AnchorPos.x = _RenderGuidanceInfo.AnchorPos.x; + AnchorPos.y = _RenderGuidanceInfo.AnchorPos.y; // 混合 if (this->_BlendMode != NONE) @@ -163,8 +194,6 @@ void Sprite::Render() // 还原混合 if (this->_BlendMode != NONE) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - Game::GetInstance().m_RenderCount++; } } @@ -172,10 +201,7 @@ void Sprite::Clear() { } -void Sprite::SetBlendMode(LE_BlEND_MODE mode) -{ - this->_BlendMode = mode; -} + void Sprite::Blend() { @@ -186,8 +212,3 @@ void Sprite::Blend() break; } } - -LE_BlEND_MODE Sprite::GetBlendMode() -{ - return this->_BlendMode; -} diff --git a/source/EngineFrame/Component/Sprite.h b/source/EngineFrame/Component/Sprite.h index 4f64630..f2b4b40 100644 --- a/source/EngineFrame/Component/Sprite.h +++ b/source/EngineFrame/Component/Sprite.h @@ -29,19 +29,17 @@ public: public: // 渲染信息 RenderGuidanceInfo _RenderGuidanceInfo; - // 混合模式 - LE_BlEND_MODE _BlendMode = NONE; std::string imgPath; int Index; + Matrix3x2 transform_matrix_; + + GlMatrix matrix3x2ToGLMatrix(const Matrix3x2 &mat); + public: // 计算渲染信息 void CalcRenderInfoLogic(); - // 设置混合模式 - void SetBlendMode(LE_BlEND_MODE mode); // 混合 void Blend(); - // 获取混合模式 - LE_BlEND_MODE GetBlendMode(); }; diff --git a/source/Tool/Allocator.cpp b/source/Tool/Allocator.cpp index 4848b48..390db95 100644 --- a/source/Tool/Allocator.cpp +++ b/source/Tool/Allocator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango +// Copyright (c) 2016-2018 Ember - Nomango // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/source/Tool/Common.h b/source/Tool/Common.h index 04f4d3a..be0aad9 100644 --- a/source/Tool/Common.h +++ b/source/Tool/Common.h @@ -17,6 +17,8 @@ #include #endif +#include "math/Math.h" + /// \~chinese /// @brief 不可拷贝对象 class Noncopyable @@ -30,134 +32,6 @@ private: Noncopyable &operator=(const Noncopyable &) = delete; }; -// 整数坐标向量 -typedef struct VecPos -{ - int x; - int y; - - // 构造函数,方便初始化 - VecPos(int x_ = 0, int y_ = 0) : x(x_), y(y_) {} - - // 定义到 SDL_Point 的转换运算符 - operator SDL_Point() const - { - return {x, y}; // 直接返回包含 x、y 的 SDL_Point - } - // 转换为SDL_Point指针的运算符(用于指针场景) - operator const SDL_Point *() const - { - // 注意:这里返回的是指向当前对象的指针,需确保对象生命周期有效 - return reinterpret_cast(this); - } - - // 加法运算符重载:两个 VecPos 相加 - VecPos operator+(const VecPos &other) const - { - return VecPos(x + other.x, y + other.y); - } - - // 减法运算符重载:两个 VecPos 相减 - VecPos operator-(const VecPos &other) const - { - return VecPos(x - other.x, y - other.y); - } - - // 等于运算符重载:判断两个 VecPos 是否相等 - bool operator==(const VecPos &other) const - { - return x == other.x && y == other.y; - } - - // 复合赋值加法:当前对象加上另一个 VecPos - VecPos &operator+=(const VecPos &other) - { - x += other.x; - y += other.y; - return *this; - } - - // 复合赋值减法:当前对象减去另一个 VecPos - VecPos &operator-=(const VecPos &other) - { - x -= other.x; - y -= other.y; - return *this; - } - - // 乘法 - VecPos operator*(float value) const - { - return VecPos(x * value, y * value); - } -} VecPos; - -// 浮点数坐标向量 -typedef struct VecFPos -{ - float x; - float y; - - // 构造函数,方便初始化 - VecFPos(float x_ = 0.0f, float y_ = 0.0f) : x(x_), y(y_) {} - VecFPos(int x_, int y_ = 0) : x(static_cast(x_)), y(static_cast(y_)) {} - - // 定义到 SDL_FPoint 的转换运算符 - operator SDL_FPoint() const - { - return {x, y}; // 直接返回包含 x、y 的 SDL_Point - } - - // 加法运算符重载:两个 VecFPos 相加 - VecFPos operator+(const VecFPos &other) const - { - return VecFPos(x + other.x, y + other.y); - } - - // 减法运算符重载:两个 VecFPos 相减 - VecFPos operator-(const VecFPos &other) const - { - return VecFPos(x - other.x, y - other.y); - } - - // 乘法运算符重载:两个 VecFPos 相乘 - VecFPos operator*(const VecFPos &other) const - { - return VecFPos(x * other.x, y * other.y); - } - - // 除法运算符重载:除以一个 float 值 - VecFPos operator/(float value) const - { - return VecFPos(x / value, y / value); - } - - // 等于运算符重载:判断两个 VecFPos 是否相等 - // 注意:浮点数比较需要考虑精度问题 - bool operator==(const VecFPos &other) const - { - // 使用一个小的epsilon值来比较浮点数 - const float epsilon = 0.0001f; - return (fabs(x - other.x) < epsilon) && (fabs(y - other.y) < epsilon); - } - - // 复合赋值加法:当前对象加上另一个 VecFPos - VecFPos &operator+=(const VecFPos &other) - { - x += other.x; - y += other.y; - return *this; - } - - // 复合赋值减法:当前对象减去另一个 VecFPos - VecFPos &operator-=(const VecFPos &other) - { - x -= other.x; - y -= other.y; - return *this; - } -} VecFPos; - // 尺寸向量 typedef struct VecSize { diff --git a/source/Tool/RefBasePtr.hpp b/source/Tool/RefBasePtr.hpp index 272e907..0701aab 100644 --- a/source/Tool/RefBasePtr.hpp +++ b/source/Tool/RefBasePtr.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango +// Copyright (c) 2016-2018 Ember - Nomango // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -249,7 +249,7 @@ inline bool operator<(const RefBasePtr<_Ty, _RefPolicy> &lhs, const RefBasePtr<_ } // template class cannot specialize std::swap, -// so implement a swap function in kiwano namespace +// so implement a swap function in ember namespace template inline void swap(RefBasePtr<_Ty, _RefPolicy> &lhs, RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept { diff --git a/source/Tool/RefPtr.h b/source/Tool/RefPtr.h index fa807f6..5b5bfeb 100644 --- a/source/Tool/RefPtr.h +++ b/source/Tool/RefPtr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango +// Copyright (c) 2016-2018 Ember - Nomango // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/source/Tool/TransformT.cpp b/source/Tool/TransformT.cpp deleted file mode 100644 index 3293c34..0000000 --- a/source/Tool/TransformT.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "TransformT.h" - -TransformT::TransformT() - : rotation(0.f), position(), scale(1.f, 1.f) -{ -} - -bool TransformT::IsFast() const -{ - return scale.x == 1.f && scale.y == 1.f && rotation == 0.f; -} - -bool TransformT::operator==(const TransformT &rhs) const -{ - return position == rhs.position && rotation == rhs.rotation && scale == rhs.scale; -} - -// -------------------------- 加法运算符实现 -------------------------- -TransformT TransformT::operator+(const TransformT &rhs) const -{ - TransformT result; - result.rotation = this->rotation + rhs.rotation; - result.position = this->position + rhs.position; - result.scale = this->scale + rhs.scale; - return result; -} - -TransformT TransformT::operator-(const TransformT &rhs) const -{ - TransformT result; - result.rotation = this->rotation - rhs.rotation; - result.position = this->position - rhs.position; - result.scale = this->scale - rhs.scale; - return result; -} - -// -------------------------- 复合赋值运算符实现 -------------------------- -TransformT &TransformT::operator+=(const TransformT &rhs) -{ - this->rotation += rhs.rotation; - this->position += rhs.position; - this->scale += rhs.scale; - return *this; -} - -TransformT &TransformT::operator-=(const TransformT &rhs) -{ - this->rotation -= rhs.rotation; - this->position -= rhs.position; - this->scale -= rhs.scale; - return *this; -} \ No newline at end of file diff --git a/source/Tool/TransformT.h b/source/Tool/TransformT.h deleted file mode 100644 index 33b8caf..0000000 --- a/source/Tool/TransformT.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "Tool/Common.h" -/** - * \~chinese - * @brief 二维放射变换 - */ -class TransformT -{ -public: - float rotation; ///< 旋转 - VecFPos position; ///< 坐标 - VecFPos scale; ///< 缩放 - -public: - TransformT(); - - bool IsFast() const; - - bool operator==(const TransformT &rhs) const; - - TransformT operator+(const TransformT &rhs) const; - TransformT operator-(const TransformT &rhs) const; - TransformT &operator+=(const TransformT &rhs); - TransformT &operator-=(const TransformT &rhs); -}; diff --git a/source/math/Constants.h b/source/math/Constants.h new file mode 100644 index 0000000..5723e03 --- /dev/null +++ b/source/math/Constants.h @@ -0,0 +1,40 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +namespace ember +{ + namespace math + { + + constexpr auto PI_F = 3.141592653589793f; + constexpr auto PI_F_2 = 1.570796326794896f; + constexpr auto PI_F_X_2 = 6.283185307179586f; + + constexpr auto PI_D = 3.14159265358979323846; + constexpr auto PI_D_2 = 1.57079632679489661923; + constexpr auto PI_D_X_2 = 6.28318530717958647692; + + constexpr auto FLOAT_MAX = 3.402823466e+38F; + constexpr auto FLOAT_MIN = 1.175494351e-38F; + + } // namespace math +} // namespace ember diff --git a/source/math/EaseFunctions.h b/source/math/EaseFunctions.h new file mode 100644 index 0000000..3bdfe35 --- /dev/null +++ b/source/math/EaseFunctions.h @@ -0,0 +1,278 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace ember +{ + namespace math + { + + inline float Linear(float step) + { + return step; + } + + // Ease + + inline float EaseIn(float step, float rate) + { + return math::Pow(step, rate); + } + + inline float EaseOut(float step, float rate) + { + return math::Pow(step, 1.f / rate); + } + + inline float EaseInOut(float step, float rate) + { + if (step < .5f) + return .5f * math::Pow(2 * step, rate); + return 1.f - .5f * math::Pow(2.f - 2 * step, rate); + } + + // Exponential Ease + + inline float EaseExponentialIn(float step) + { + return math::Pow(2.f, 10 * (step - 1)); + } + + inline float EaseExponentialOut(float step) + { + return 1.f - math::Pow(2.f, -10 * step); + } + + inline float EaseExponentialInOut(float step) + { + if (step < .5f) + return .5f * math::Pow(2.f, 10 * (2 * step - 1)); + return 0.5f * (2 - math::Pow(2, -10 * (step * 2 - 1))); + } + + // Bounce Ease + + inline float EaseBounceOut(float step) + { + if (step < 1 / 2.75f) + { + return 7.5625f * step * step; + } + else if (step < 2 / 2.75f) + { + step -= 1.5f / 2.75f; + return 7.5625f * step * step + 0.75f; + } + else if (step < 2.5f / 2.75f) + { + step -= 2.25f / 2.75f; + return 7.5625f * step * step + 0.9375f; + } + + step -= 2.625f / 2.75f; + return 7.5625f * step * step + 0.984375f; + } + + inline float EaseBounceIn(float step) + { + return 1 - EaseBounceOut(1 - step); + } + + inline float EaseBounceInOut(float step) + { + if (step < 0.5f) + { + return EaseBounceIn(step * 2) * 0.5f; + } + else + { + return EaseBounceOut(step * 2 - 1) * 0.5f + 0.5f; + } + } + + // Elastic Ease + + inline float EaseElasticIn(float step, float period) + { + if (step == 0 || step == 1) + return step; + + step = step - 1; + return -math::Pow(2, 10 * step) * math::Sin((step - period / 4) * 360.f / period); + } + + inline float EaseElasticOut(float step, float period) + { + if (step == 0 || step == 1) + return step; + + return math::Pow(2, -10 * step) * math::Sin((step - period / 4) * 360.f / period) + 1; + } + + inline float EaseElasticInOut(float step, float period) + { + if (step == 0 || step == 1) + return step; + + step = step * 2 - 1; + if (step < 0) + { + return -0.5f * math::Pow(2, 10 * step) * math::Sin((step - period / 4) * 360.f / period); + } + return math::Pow(2, -10 * step) * math::Sin((step - period / 4) * 360.f / period) * 0.5f + 1; + } + + // Back Ease + + inline float EaseBackIn(float step) + { + const float overshoot = 1.70158f; + return step * step * ((overshoot + 1) * step - overshoot); + } + + inline float EaseBackOut(float step) + { + const float overshoot = 1.70158f; + step = step - 1; + return step * step * ((overshoot + 1) * step + overshoot) + 1; + } + + inline float EaseBackInOut(float step) + { + const float overshoot = 1.70158f * 1.525f; + + step = step * 2; + if (step < 1) + { + return (step * step * ((overshoot + 1) * step - overshoot)) / 2; + } + + step = step - 2; + return (step * step * ((overshoot + 1) * step + overshoot)) / 2 + 1; + } + + // Sine Ease + + inline float EaseSineIn(float step) + { + return 1.f - math::Cos(step * 90); + } + + inline float EaseSineOut(float step) + { + return math::Sin(step * 90); + } + + inline float EaseSineInOut(float step) + { + return -0.5f * (math::Cos(step * 180) - 1); + } + + // Quad Ease + + inline float EaseQuadIn(float step) + { + return step * step; + } + + inline float EaseQuadOut(float step) + { + return -1 * step * (step - 2); + } + + inline float EaseQuadInOut(float step) + { + step = step * 2; + if (step < 1) + return 0.5f * step * step; + --step; + return -0.5f * (step * (step - 2) - 1); + } + + // Cubic Ease + + inline float EaseCubicIn(float step) + { + return step * step * step; + } + + inline float EaseCubicOut(float step) + { + step -= 1; + return (step * step * step + 1); + } + + inline float EaseCubicInOut(float step) + { + step = step * 2; + if (step < 1) + return 0.5f * step * step * step; + step -= 2; + return 0.5f * (step * step * step + 2); + } + + // Quart Ease + + inline float EaseQuartIn(float step) + { + return step * step * step * step; + } + + inline float EaseQuartOut(float step) + { + step -= 1; + return -(step * step * step * step - 1); + } + + inline float EaseQuartInOut(float step) + { + step = step * 2; + if (step < 1) + return 0.5f * step * step * step * step; + step -= 2; + return -0.5f * (step * step * step * step - 2); + } + + // Quint Ease + + inline float EaseQuintIn(float step) + { + return step * step * step * step * step; + } + + inline float EaseQuintOut(float step) + { + step -= 1; + return (step * step * step * step * step + 1); + } + + inline float EaseQuintInOut(float step) + { + step = step * 2; + if (step < 1) + return 0.5f * step * step * step * step * step; + step -= 2; + return 0.5f * (step * step * step * step * step + 2); + } + + } // namespace math +} // namespace ember diff --git a/source/math/Interpolator.h b/source/math/Interpolator.h new file mode 100644 index 0000000..19672c5 --- /dev/null +++ b/source/math/Interpolator.h @@ -0,0 +1,153 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include +#include + +namespace ember +{ + namespace math + { + + template + struct InterpolateMethod; + + template <> + struct InterpolateMethod + { + inline float operator()(float frac) const noexcept + { + return frac; + } + }; + + template <> + struct InterpolateMethod + { + float (*method)(float); + + InterpolateMethod(float (*method)(float)) noexcept + : method(method) + { + } + + inline float operator()(float frac) const noexcept + { + if (method) + return method(frac); + return frac; + } + }; + + template <> + struct InterpolateMethod> + { + Function method; + + InterpolateMethod(const Function &method) noexcept + : method(method) + { + } + + inline float operator()(float frac) const noexcept + { + if (method) + return method(frac); + return frac; + } + }; + + template + class Interpolator; + + template + class Interpolator + { + public: + template + inline _Ty Interpolate(_Ty start, _Ty end, float frac, const InterpolateMethod<_Method> &method = {}) + { + if (frac >= 1) + return end; + return start + static_cast<_Ty>(static_cast(end - start) * method(frac)); + } + }; + + template + class Interpolator> + { + public: + template + inline Vec2T<_Ty> Interpolate(const Vec2T<_Ty> &start, const Vec2T<_Ty> &end, float frac, + const InterpolateMethod<_Method> &method = {}) + { + if (frac >= 1) + return end; + + Interpolator<_Ty> fi; + return Vec2T<_Ty>{fi.Interpolate(start.x, end.x, frac, method), fi.Interpolate(start.y, end.y, frac, method)}; + } + }; + + template + class Interpolator> + { + public: + template + inline RectT<_Ty> Interpolate(const RectT<_Ty> &start, const RectT<_Ty> &end, float frac, + const InterpolateMethod<_Method> &method = {}) + { + if (frac >= 1) + return end; + + Interpolator> vi; + return RectT<_Ty>{vi.Interpolate(start.left_top, end.left_top, frac, method), + vi.Interpolate(start.right_bottom, end.right_bottom, frac, method)}; + } + }; + + template + class Interpolator> + { + public: + template + inline TransformT<_Ty> Interpolate(const TransformT<_Ty> &start, const TransformT<_Ty> &end, float frac, + const InterpolateMethod<_Method> &method = {}) + { + if (frac >= 1) + return end; + + Interpolator<_Ty> fi; + Interpolator> vi; + + TransformT<_Ty> transform; + transform.rotation = fi.Interpolate(start.rotation, end.rotation, frac, method); + transform.position = vi.Interpolate(start.position, end.position, frac, method); + transform.scale = vi.Interpolate(start.scale, end.scale, frac, method); + transform.skew = vi.Interpolate(start.skew, end.skew, frac, method); + return transform; + } + }; + + } // namespace math +} // namespace ember diff --git a/source/math/Math.h b/source/math/Math.h new file mode 100644 index 0000000..57a594e --- /dev/null +++ b/source/math/Math.h @@ -0,0 +1,39 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include +#include +#include +#include +#include + +using Vec2 = ember::math::Vec2T; +using VecPos = ember::math::Vec2T; +using Rect = ember::math::RectT; +using Matrix3x2 = ember::math::Matrix3x2T; +using Transform = ember::math::TransformT; + +using GlMatrix = std::array; + +using Point = Vec2; +using Size = Vec2; diff --git a/source/math/Matrix.hpp b/source/math/Matrix.hpp new file mode 100644 index 0000000..b8eba37 --- /dev/null +++ b/source/math/Matrix.hpp @@ -0,0 +1,268 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include + +namespace ember +{ + namespace math + { + template + struct MatrixMultiply; + + template + struct Matrix3x2T + { + using ValueType = _Ty; + using Vec2Type = Vec2T; + using RectType = RectT; + + union + { + struct + { + _Ty m[6]; // m[3][2] + }; + + struct + { + _Ty _11, _12, _21, _22, _31, _32; + }; + }; + + Matrix3x2T() + : _11(1.f), _12(0.f), _21(0.f), _22(1.f), _31(0.f), _32(0.f) + { + } + + Matrix3x2T(ValueType _11, ValueType _12, ValueType _21, ValueType _22, ValueType _31, ValueType _32) + : _11(_11), _12(_12), _21(_21), _22(_22), _31(_31), _32(_32) + { + } + + explicit Matrix3x2T(const ValueType *p) + { + for (int i = 0; i < 6; i++) + m[i] = p[i]; + } + + Matrix3x2T(const Matrix3x2T &other) + : _11(other._11), _12(other._12), _21(other._21), _22(other._22), _31(other._31), _32(other._32) + { + } + + template + Matrix3x2T(const _MTy &other) + { + for (int i = 0; i < 6; i++) + m[i] = other[i]; + } + + inline ValueType operator[](uint32_t index) const + { + return m[index]; + } + + inline ValueType &operator[](uint32_t index) + { + return m[index]; + } + + inline Matrix3x2T &operator=(const Matrix3x2T &other) + { + for (int i = 0; i < 6; i++) + m[i] = other[i]; + return (*this); + } + + template + inline Matrix3x2T &operator=(const MatrixMultiply &other) + { + Matrix3x2T result(other); + (*this) = result; + return (*this); + } + + inline Matrix3x2T &operator*=(const Matrix3x2T &other) + { + return operator=((*this) * other); + } + + inline void Identity() + { + _11 = 1.f; + _12 = 0.f; + _21 = 0.f; + _22 = 1.f; + _31 = 0.f; + _32 = 0.f; + } + + inline bool IsIdentity() const + { + return _11 == 1.f && _12 == 0.f && _21 == 0.f && _22 == 1.f && _31 == 0.f && _32 == 0.f; + } + + inline Matrix3x2T Invert() const + { + ValueType det = 1.f / Determinant(); + return Matrix3x2T(det * _22, -det * _12, -det * _21, det * _11, det * (_21 * _32 - _22 * _31), + det * (_12 * _31 - _11 * _32)); + } + + inline bool IsInvertible() const + { + return 0 != Determinant(); + } + + inline ValueType Determinant() const + { + return (_11 * _22) - (_12 * _21); + } + + inline Vec2Type Transform(const Vec2Type &v) const + { + return Vec2Type(v.x * _11 + v.y * _21 + _31, v.x * _12 + v.y * _22 + _32); + } + + RectType Transform(const RectType &rect) const + { + Vec2Type top_left = Transform(rect.GetLeftTop()); + Vec2Type top_right = Transform(rect.GetRightTop()); + Vec2Type bottom_left = Transform(rect.GetLeftBottom()); + Vec2Type bottom_right = Transform(rect.GetRightBottom()); + + ValueType left = (std::min)((std::min)(top_left.x, top_right.x), (std::min)(bottom_left.x, bottom_right.x)); + ValueType right = (std::max)((std::max)(top_left.x, top_right.x), (std::max)(bottom_left.x, bottom_right.x)); + ValueType top = (std::min)((std::min)(top_left.y, top_right.y), (std::min)(bottom_left.y, bottom_right.y)); + ValueType bottom = (std::max)((std::max)(top_left.y, top_right.y), (std::max)(bottom_left.y, bottom_right.y)); + + return RectType{left, top, right, bottom}; + } + + inline void Translate(const Vec2Type &v) + { + _31 += _11 * v.x + _21 * v.y; + _32 += _12 * v.x + _22 * v.y; + } + + static inline Matrix3x2T Translation(const Vec2Type &v) + { + return Matrix3x2T(1.f, 0.f, 0.f, 1.f, v.x, v.y); + } + + static inline Matrix3x2T Scaling(const Vec2Type &v) + { + return Matrix3x2T(v.x, 0.f, 0.f, v.y, 0.f, 0.f); + } + + static inline Matrix3x2T Scaling(const Vec2Type &v, const Vec2Type ¢er) + { + return Matrix3x2T(v.x, 0.f, 0.f, v.y, center.x - v.x * center.x, center.y - v.y * center.y); + } + + static inline Matrix3x2T Rotation(ValueType angle) + { + ValueType s = math::Sin(angle); + ValueType c = math::Cos(angle); + return Matrix3x2T(c, s, -s, c, 0.f, 0.f); + } + + static inline Matrix3x2T Rotation(ValueType angle, const Vec2Type ¢er) + { + ValueType s = math::Sin(angle); + ValueType c = math::Cos(angle); + return Matrix3x2T(c, s, -s, c, center.x * (1 - c) + center.y * s, center.y * (1 - c) - center.x * s); + } + + static inline Matrix3x2T SRT(const Vec2Type &trans, const Vec2Type &scale, ValueType angle) + { + ValueType s = math::Sin(angle); + ValueType c = math::Cos(angle); + return Matrix3x2T(c * scale.x, s * scale.x, -s * scale.y, c * scale.y, trans.x, trans.y); + } + + static inline Matrix3x2T Skewing(const Vec2Type &angle) + { + ValueType tx = math::Tan(angle.x); + ValueType ty = math::Tan(angle.y); + return Matrix3x2T(1.f, -ty, -tx, 1.f, 0.f, 0.f); + } + + static inline Matrix3x2T Skewing(const Vec2Type &angle, const Vec2Type ¢er) + { + ValueType tx = math::Tan(angle.x); + ValueType ty = math::Tan(angle.y); + return Matrix3x2T(1.f, -ty, -tx, 1.f, center.y * tx, center.x * ty); + } + }; + + // Use template expression to optimize matrix multiply + template + struct MatrixMultiply + { + const _Lty &lhs; + const _Rty &rhs; + + MatrixMultiply(const _Lty &lhs, const _Rty &rhs) + : lhs(lhs), rhs(rhs) + { + } + + inline _Ty operator[](uint32_t index) const + { + switch (index) + { + case 0: + return lhs[0] * rhs[0] + lhs[1] * rhs[2]; + case 1: + return lhs[0] * rhs[1] + lhs[1] * rhs[3]; + case 2: + return lhs[2] * rhs[0] + lhs[3] * rhs[2]; + case 3: + return lhs[2] * rhs[1] + lhs[3] * rhs[3]; + case 4: + return lhs[4] * rhs[0] + lhs[5] * rhs[2] + rhs[4]; + case 5: + return lhs[4] * rhs[1] + lhs[5] * rhs[3] + rhs[5]; + default: + return 0.f; + } + } + }; + + template + inline MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>> operator*(const Matrix3x2T<_Ty> &lhs, + const Matrix3x2T<_Ty> &rhs) + { + return MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>>(lhs, rhs); + } + + template + inline MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>> + operator*(const MatrixMultiply<_Ty, _Lty, _Rty> &lhs, const Matrix3x2T<_Ty> &rhs) + { + return MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>(lhs, rhs); + } + } // namespace math +} // namespace ember diff --git a/source/math/Random.h b/source/math/Random.h new file mode 100644 index 0000000..6c54441 --- /dev/null +++ b/source/math/Random.h @@ -0,0 +1,114 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace ember +{ + namespace math + { + // + // + // + // ȡָΧڵһ, : + // int n = math::Random(1, 5); // ȡ 1~5 ڵ, 1 5 + // ȡڲ, ȡ: + // float d = math::Random(1.2f, 1.5f); + // + + int Random(int min, int max); + + unsigned int Random(unsigned int min, unsigned int max); + + long Random(long min, long max); + + unsigned long Random(unsigned long min, unsigned long max); + + char Random(char min, char max); + + float Random(float min, float max); + + double Random(double min, double max); + + // + // Details of math::Rand + // + + namespace __rand_detail + { + inline std::default_random_engine &GetRandomEngine() + { + static std::random_device device; + static std::default_random_engine engine(device()); + return engine; + } + + template + inline T RandomInt(T min, T max) + { + std::uniform_int_distribution dist(min, max); + return dist(GetRandomEngine()); + } + + template + inline T RandomReal(T min, T max) + { + std::uniform_real_distribution dist(min, max); + return dist(GetRandomEngine()); + } + } // namespace __rand_detail + + inline int Random(int min, int max) + { + return __rand_detail::RandomInt(min, max); + } + + inline unsigned int Random(unsigned int min, unsigned int max) + { + return __rand_detail::RandomInt(min, max); + } + + inline long Random(long min, long max) + { + return __rand_detail::RandomInt(min, max); + } + + inline unsigned long Random(unsigned long min, unsigned long max) + { + return __rand_detail::RandomInt(min, max); + } + + inline char Random(char min, char max) + { + return static_cast(__rand_detail::RandomInt(static_cast(min), static_cast(max))); + } + + inline float Random(float min, float max) + { + return __rand_detail::RandomReal(min, max); + } + + inline double Random(double min, double max) + { + return __rand_detail::RandomReal(min, max); + } + } // namespace math +} // namespace ember diff --git a/source/math/Rect.hpp b/source/math/Rect.hpp new file mode 100644 index 0000000..01dc13b --- /dev/null +++ b/source/math/Rect.hpp @@ -0,0 +1,154 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace ember +{ + namespace math + { + template + struct RectT + { + public: + using ValueType = _Ty; + + Vec2T left_top; + Vec2T right_bottom; + + public: + RectT() {} + + RectT(ValueType left, ValueType top, ValueType right, ValueType bottom) + : left_top(left, top), right_bottom(right, bottom) + { + } + + RectT(const Vec2T &left_top, const Vec2T &right_bottom) + : left_top(left_top), right_bottom(right_bottom) + { + } + + RectT(const RectT &other) + : left_top(other.left_top), right_bottom(other.right_bottom) + { + } + + RectT &operator=(const RectT &other) + { + left_top = other.left_top; + right_bottom = other.right_bottom; + return *this; + } + + inline bool operator==(const RectT &rect) const + { + return (left_top == rect.left_top) && (right_bottom == rect.right_bottom); + } + + inline void Set(ValueType left, ValueType top, ValueType right, ValueType bottom) + { + left_top = Vec2T{left, top}; + right_bottom = Vec2T{right, bottom}; + } + + inline Vec2T GetCenter() const + { + return Vec2T{(left_top.x + right_bottom.x) / 2, (left_top.y + right_bottom.y) / 2}; + } + + inline Vec2T GetLeftTop() const + { + return left_top; + } + + inline Vec2T GetRightBottom() const + { + return right_bottom; + } + + inline Vec2T GetRightTop() const + { + return Vec2T{right_bottom.x, left_top.y}; + } + + inline Vec2T GetLeftBottom() const + { + return Vec2T{left_top.x, right_bottom.y}; + } + + inline ValueType GetLeft() const + { + return left_top.x; + } + + inline ValueType GetTop() const + { + return left_top.y; + } + + inline ValueType GetRight() const + { + return right_bottom.x; + } + + inline ValueType GetBottom() const + { + return right_bottom.y; + } + + inline ValueType GetWidth() const + { + return right_bottom.x - left_top.x; + } + + inline ValueType GetHeight() const + { + return right_bottom.y - left_top.y; + } + + inline Vec2T GetSize() const + { + return Vec2T{GetWidth(), GetHeight()}; + } + + inline bool IsEmpty() const + { + return left_top.IsOrigin() && right_bottom.IsOrigin(); + } + + inline bool ContainsPoint(const Vec2T &point) const + { + return point.x >= left_top.x && point.x <= right_bottom.x && point.y >= left_top.y && point.y <= right_bottom.y; + } + + inline bool Intersects(const RectT &rect) const + { + return !(right_bottom.x < rect.left_top.x || rect.right_bottom.x < left_top.x || right_bottom.y < rect.left_top.y || rect.right_bottom.y < left_top.y); + } + + static inline RectT Infinite() + { + return RectT{-math::FLOAT_MAX, -math::FLOAT_MAX, math::FLOAT_MAX, math::FLOAT_MAX}; + } + }; + } // namespace math +} // namespace ember diff --git a/source/math/Scalar.h b/source/math/Scalar.h new file mode 100644 index 0000000..ccaaa51 --- /dev/null +++ b/source/math/Scalar.h @@ -0,0 +1,165 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include + +namespace ember +{ + namespace math + { + + inline int Abs(int val) + { + return ::abs(val); + } + inline float Abs(float val) + { + return ::fabsf(val); + } + inline double Abs(double val) + { + return ::fabs(val); + } + + inline float Sqrt(float val) + { + return ::sqrtf(val); + } + inline double Sqrt(double val) + { + return ::sqrt(val); + } + + inline float Pow(float core, float exponent) + { + return ::powf(core, exponent); + } + inline double Pow(double core, double exponent) + { + return ::pow(core, exponent); + } + + inline int Sign(int val) + { + return val < 0 ? -1 : 1; + } + inline float Sign(float val) + { + return val < 0 ? -1.f : 1.f; + } + inline double Sign(double val) + { + return val < 0 ? -1.0 : 1.0; + } + + inline float Degree2Radian(float angle) + { + return angle * math::PI_F / 180.f; + } + inline double Degree2Radian(double angle) + { + return angle * math::PI_D / 180.0; + } + + inline float Radian2Degree(float radian) + { + return radian * 180.f / math::PI_F; + } + inline double Radian2Degree(double radian) + { + return radian * 180.0 / math::PI_D; + } + + inline float Sin(float val) + { + return ::sinf(Degree2Radian(val)); + } + inline double Sin(double val) + { + return ::sin(Degree2Radian(val)); + } + + inline float Cos(float val) + { + return ::cosf(Degree2Radian(val)); + } + inline double Cos(double val) + { + return ::cos(Degree2Radian(val)); + } + + inline float Tan(float val) + { + return ::tanf(Degree2Radian(val)); + } + inline double Tan(double val) + { + return ::tan(Degree2Radian(val)); + } + + inline float Asin(float val) + { + return Radian2Degree(::asinf(val)); + } + inline double Asin(double val) + { + return Radian2Degree(::asin(val)); + } + + inline float Acos(float val) + { + return Radian2Degree(::acosf(val)); + } + inline double Acos(double val) + { + return Radian2Degree(::acos(val)); + } + + inline float Atan(float val) + { + return Radian2Degree(::atanf(val)); + } + inline double Atan(double val) + { + return Radian2Degree(::atan(val)); + } + + inline float Ceil(float val) + { + return ::ceil(val); + } + inline double Ceil(double val) + { + return ::ceil(val); + } + + inline float Floor(float val) + { + return ::floor(val); + } + inline double Floor(double val) + { + return ::floor(val); + } + + } // namespace math +} // namespace ember diff --git a/source/math/Transform.hpp b/source/math/Transform.hpp new file mode 100644 index 0000000..dea096e --- /dev/null +++ b/source/math/Transform.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include + +namespace ember +{ + namespace math + { + + /** + * \~chinese + * @brief ά任 + */ + template + class TransformT + { + public: + using ValueType = _Ty; + + float rotation; ///< ת + Vec2T position; ///< + Vec2T scale; ///< + Vec2T skew; ///< нǶ + + public: + TransformT(); + + /// \~chinese + /// @brief ά任תΪ + Matrix3x2T ToMatrix() const; + + bool IsFast() const; + + bool operator==(const TransformT &rhs) const; + }; + + template + inline TransformT<_Ty>::TransformT() + : position(), rotation(0.f), scale(1.f, 1.f), skew(0.f, 0.f) + { + } + + template + Matrix3x2T<_Ty> TransformT<_Ty>::ToMatrix() const + { + if (!skew.IsOrigin()) + { + return Matrix3x2T<_Ty>::Skewing(skew) * Matrix3x2T<_Ty>::SRT(position, scale, rotation); + } + return Matrix3x2T<_Ty>::SRT(position, scale, rotation); + } + + template + inline bool TransformT<_Ty>::IsFast() const + { + return skew.x == 0.f && skew.y == 0.f && scale.x == 1.f && scale.y == 1.f && rotation == 0.f; + } + + template + bool TransformT<_Ty>::operator==(const TransformT &rhs) const + { + return position == rhs.position && rotation == rhs.rotation && scale == rhs.scale && skew == rhs.skew; + } + + } // namespace math +} // namespace ember diff --git a/source/math/Vec2.hpp b/source/math/Vec2.hpp new file mode 100644 index 0000000..2322421 --- /dev/null +++ b/source/math/Vec2.hpp @@ -0,0 +1,136 @@ +// Copyright (c) 2016-2018 Ember - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace ember +{ + namespace math + { + template + struct Vec2T + { + using ValueType = _Ty; + + ValueType x; + ValueType y; + + Vec2T() + : x(ValueType(0)), y(ValueType(0)) + { + } + + Vec2T(ValueType x, ValueType y) + : x(x), y(y) + { + } + + Vec2T(const Vec2T &other) + : x(other.x), y(other.y) + { + } + + inline ValueType Length() const + { + return static_cast(math::Sqrt(static_cast(x * x + y * y))); + } + + inline bool IsOrigin() const + { + return (x == 0) && (y == 0); + } + + inline void Set(ValueType x, ValueType y) + { + this->x = x; + this->y = y; + } + + inline const Vec2T operator+(const Vec2T &other) const + { + return Vec2T(x + other.x, y + other.y); + } + + inline const Vec2T operator-(const Vec2T &other) const + { + return Vec2T(x - other.x, y - other.y); + } + + inline const Vec2T operator*(ValueType val) const + { + return Vec2T(x * val, y * val); + } + + inline const Vec2T operator*(const Vec2T &other) const + { + return Vec2T(x * other.x, y * other.y); + } + + inline const Vec2T operator/(ValueType val) const + { + return Vec2T(x / val, y / val); + } + + inline const Vec2T operator-() const + { + return Vec2T(-x, -y); + } + + inline Vec2T &operator+=(const Vec2T &other) + { + x += other.x; + y += other.y; + return (*this); + } + + inline Vec2T &operator-=(const Vec2T &other) + { + x -= other.x; + y -= other.y; + return (*this); + } + + inline Vec2T &operator*=(ValueType val) + { + x *= val; + y *= val; + return (*this); + } + + inline Vec2T &operator/=(ValueType val) + { + x /= val; + y /= val; + return (*this); + } + + inline bool operator==(const Vec2T &other) const + { + return (x == other.x) && (y == other.y); + } + + inline bool operator!=(const Vec2T &other) const + { + return (x != other.x) || (y != other.y); + } + }; + } // namespace math +} // namespace ember diff --git a/source/squirrel/SquirrelEx.cpp b/source/squirrel/SquirrelEx.cpp index e455b4b..33a04f6 100644 --- a/source/squirrel/SquirrelEx.cpp +++ b/source/squirrel/SquirrelEx.cpp @@ -102,6 +102,7 @@ void SquirrelEx::Init() dbg = sqdbg_attach_debugger(v); sqdbg_listen_socket(dbg, 2222); + fclose(file1); } #endif diff --git a/source/squirrel/SquirrelEx.h b/source/squirrel/SquirrelEx.h index 68eb9a2..c07cf65 100644 --- a/source/squirrel/SquirrelEx.h +++ b/source/squirrel/SquirrelEx.h @@ -76,6 +76,7 @@ private: //工作目录 std::string WorkPath; //热重载 - bool HotReload = true; + bool HotReload = false; std::map _scriptmap; + }; diff --git a/source/squirrel/sqdbg/server.cpp b/source/squirrel/sqdbg/server.cpp index 5b2d621..e0fc386 100644 --- a/source/squirrel/sqdbg/server.cpp +++ b/source/squirrel/sqdbg/server.cpp @@ -4318,6 +4318,11 @@ void SQDebugServer::OnRequest_SetBreakpoints(const json_table_t &arguments, int return; } +//必须切割否则无法取消断点 +#ifdef SQDBG_SOURCENAME_HAS_PATH + StripFileName(&srcname.ptr, &srcname.len); +#endif + RemoveBreakpoints(srcname); DAP_START_RESPONSE(seq, "setBreakpoints"); @@ -18191,7 +18196,6 @@ void SQDebugServer::RemoveBreakpoints(const string_t &source) for (unsigned int i = 0; i < m_nFunctionBreakpointsIdx;) { breakpoint_t &bp = m_Breakpoints[i]; - if (bp.src.IsEqualTo(src)) { FreeBreakpoint(bp); @@ -19968,6 +19972,7 @@ void SQDebugServer::DebugHook(HSQUIRRELVM vm, int type, sqstring_t src; src.Assign(sourcename, srclen); + breakpoint_t *bp = GetBreakpoint(line, src); if (bp) diff --git a/source_game/Actor/Map/GameMap.cpp b/source_game/Actor/Map/GameMap.cpp index 26e79b7..7060917 100644 --- a/source_game/Actor/Map/GameMap.cpp +++ b/source_game/Actor/Map/GameMap.cpp @@ -221,7 +221,7 @@ void GameMap::InitTile() { std::string path = tileArr[i]; RefPtr tile = new Tile(path); - tile->SetPos(VecFPos{i * 224, -200 - std::get(_MapInfo["background_pos"])}); + tile->SetPos(Vec2{i * 224, -200 - std::get(_MapInfo["background_pos"])}); _LayerMap["bottom"]->AddComponent(tile); } _MapHeight = 560; @@ -240,7 +240,7 @@ void GameMap::InitTile() RefPtr tile = new Tile(path); int xbuf = i % NormalTileCount * 224; int ybuf = -200 - std::get(_MapInfo["background_pos"]) + NormalTileHeight + 120 * (i / NormalTileCount); - tile->SetPos(VecFPos{xbuf, ybuf}); + tile->SetPos(Vec2{xbuf, ybuf}); _LayerMap["bottom"]->AddComponent(tile); } } @@ -269,7 +269,7 @@ void GameMap::InitBackgroundAnimation() } for (int i = 0; i < (int)AniList.size(); i++) { - AniList[i]->SetPos(VecFPos{i * width, -120}); + AniList[i]->SetPos(Vec2{i * width, -120}); AniList[i]->SetRenderZOrder(-1000000); std::string layer = ani.layer; layer = layer.substr(1, layer.length() - 2); @@ -294,7 +294,7 @@ void GameMap::InitMapAnimation() { std::string path = ani.filename; RefPtr AniObj = new Animation(path); - AniObj->SetPos(VecFPos{ani.XPos, ani.YPos - ani.ZPos}); + AniObj->SetPos(Vec2{ani.XPos, ani.YPos - ani.ZPos}); AniObj->SetRenderZOrder(ani.YPos); std::string layer = ani.layer; layer = layer.substr(1, layer.length() - 2); @@ -318,7 +318,7 @@ void GameMap::InitVirtualMovableArea() float w = Info[i + 2]; float h = Info[i + 3]; if (_DebugMode) - _LayerMap["max"]->AddDebugFeasibleAreaInfo(VecFPos(x, y), VecSize(w, h)); + _LayerMap["max"]->AddDebugFeasibleAreaInfo(Vec2(x, y), VecSize(w, h)); _MovableArea.push_back(SDL_FRect{x, y, w, h}); } } @@ -364,8 +364,8 @@ void GameMap::Update(float deltaTime) int targetX = Cam->_currentPosition.x; int targetY = Cam->_currentPosition.y; // 屏幕中心 - int width_Separate = Game::GetInstance().Screen_W / 2; - int height_Separate = Game::GetInstance().Screen_H / 2; + int width_Separate = 1067 / 2; + int height_Separate = 600 / 2; // 获取摄像机可行区域限制 auto limitIt = _MapInfo.find("limit_map_camera_move"); @@ -400,7 +400,7 @@ void GameMap::Update(float deltaTime) posX *= BackgroundMoveSpeed; posX /= 100; } - Layer.second->SetPos(VecFPos(posX, posY)); + Layer.second->SetPos(Vec2(posX, posY)); } } diff --git a/source_game/Actor/Map/GameMapLayer.cpp b/source_game/Actor/Map/GameMapLayer.cpp index d1541c8..7b6e2d4 100644 --- a/source_game/Actor/Map/GameMapLayer.cpp +++ b/source_game/Actor/Map/GameMapLayer.cpp @@ -28,7 +28,7 @@ void GameMapLayer::Render() } } -void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size) +void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size) { SDL_Rect info; info.x = pos.x; diff --git a/source_game/Actor/Map/GameMapLayer.h b/source_game/Actor/Map/GameMapLayer.h index b7cdb8f..eebcdad 100644 --- a/source_game/Actor/Map/GameMapLayer.h +++ b/source_game/Actor/Map/GameMapLayer.h @@ -17,7 +17,7 @@ public: // 重载Render以实现绘制可行区域 void Render() override; // 添加调试可行区域信息 - void AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size); + void AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size); public: void AddObject(RefPtr obj); // 添加对象 diff --git a/source_game/Actor/Map/Tile.cpp b/source_game/Actor/Map/Tile.cpp index 87039c6..f1f6c52 100644 --- a/source_game/Actor/Map/Tile.cpp +++ b/source_game/Actor/Map/Tile.cpp @@ -21,7 +21,7 @@ Tile::~Tile() { } -void Tile::SetPos(VecFPos pos) +void Tile::SetPos(Vec2 pos) { pos.y += std::get(m_data["pos"]); Sprite::SetPos(pos); diff --git a/source_game/Actor/Map/Tile.h b/source_game/Actor/Map/Tile.h index 6b35e67..5578d94 100644 --- a/source_game/Actor/Map/Tile.h +++ b/source_game/Actor/Map/Tile.h @@ -16,7 +16,7 @@ public: Tile(std::string Path); ~Tile(); - void SetPos(VecFPos pos) override; + void SetPos(Vec2 pos) override; void InitInfo(std::string Path); }; diff --git a/source_game/Actor/Object/BaseObject.cpp b/source_game/Actor/Object/BaseObject.cpp index 1e9b84d..c7cba11 100644 --- a/source_game/Actor/Object/BaseObject.cpp +++ b/source_game/Actor/Object/BaseObject.cpp @@ -28,7 +28,7 @@ void BaseObject::SetPosition(VecPos3 pos) SetRenderZOrder(pos.y); // 设置渲染顺序 } this->Position = pos; - SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z}); + SetPos(Vec2{this->Position.x, this->Position.y - this->Position.z}); } VecPos3 BaseObject::GetPosition() @@ -105,16 +105,16 @@ void BaseObject::MoveBy(int x, int y, int z) void BaseObject::SetDirection(int dir) { this->Direction = dir; - VecFPos sc = GetScale(); + Vec2 sc = GetScale(); // 朝右 if (dir == 0) { - SetScale(VecFPos({SDL_fabsf(sc.x), sc.y})); + SetScale(Vec2({SDL_fabsf(sc.x), sc.y})); } // 朝左 else if (dir == 1) { - SetScale(VecFPos({-SDL_fabsf(sc.x), sc.y})); + SetScale(Vec2({-SDL_fabsf(sc.x), sc.y})); } } diff --git a/source_game/Actor/Object/CharacterObject.cpp b/source_game/Actor/Object/CharacterObject.cpp index 2287ce7..54384f6 100644 --- a/source_game/Actor/Object/CharacterObject.cpp +++ b/source_game/Actor/Object/CharacterObject.cpp @@ -44,7 +44,7 @@ void CharacterObject::ControllerMsg(CONTROLLER_MSG_TYPE msgType, void *msgData) // 摇杆移动(左) if (msgType == CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE) { - VecFPos *pos = (VecFPos *)msgData; + Vec2 *pos = (Vec2 *)msgData; std::vector movedata = {pos->x, pos->y}; this->GetObjectVars().SetArray("_move_data_", movedata); this->_StateMachine->ChangeState(BASE_STATE::MOVE); @@ -56,7 +56,7 @@ void CharacterObject::Update(float deltaTime) ActiveObject::Update(deltaTime); } -void CharacterObject::SetPos(VecFPos pos) +void CharacterObject::SetPos(Vec2 pos) { BaseObject::SetPos(pos); if(_Shadow)_Shadow->SetPos(this->GetPos()); diff --git a/source_game/Actor/Object/CharacterObject.h b/source_game/Actor/Object/CharacterObject.h index 2b202bf..e1f818c 100644 --- a/source_game/Actor/Object/CharacterObject.h +++ b/source_game/Actor/Object/CharacterObject.h @@ -40,6 +40,6 @@ public: void ControllerMsg(CONTROLLER_MSG_TYPE msgType, void* msgData); void Update(float deltaTime) override; - void SetPos(VecFPos pos) override; + void SetPos(Vec2 pos) override; void SetDirection(int dir) override; }; diff --git a/source_game/Asset/Character/Chr_Controller.h b/source_game/Asset/Character/Chr_Controller.h index 146e6c7..2542798 100644 --- a/source_game/Asset/Character/Chr_Controller.h +++ b/source_game/Asset/Character/Chr_Controller.h @@ -8,8 +8,8 @@ private: CharacterObject *m_pCharacter = nullptr; public: - VecFPos LeftStick = {0.f, 0.f}; - VecFPos RightStick = {0.f, 0.f}; + Vec2 LeftStick = {0.f, 0.f}; + Vec2 RightStick = {0.f, 0.f}; // 用于将SDL的轴值(-32768到32767)转换为-1到1之间的浮点数 float ConvertAxisValue(Sint16 rawValue); @@ -19,6 +19,6 @@ public: void HandleEvents(SDL_Event *e) override; // 获取摇杆位置的方法 - const VecFPos &GetLeftStick() const { return LeftStick; } - const VecFPos &GetRightStick() const { return RightStick; } + const Vec2 &GetLeftStick() const { return LeftStick; } + const Vec2 &GetRightStick() const { return RightStick; } }; diff --git a/source_game/Asset/Character/Chr_Shadow.cpp b/source_game/Asset/Character/Chr_Shadow.cpp index 3709967..d6cfd05 100644 --- a/source_game/Asset/Character/Chr_Shadow.cpp +++ b/source_game/Asset/Character/Chr_Shadow.cpp @@ -30,15 +30,15 @@ void Chr_Shadow::SetAction(std::string actionName) void Chr_Shadow::SetDirection(int dir) { - VecFPos sc = GetScale(); + Vec2 sc = GetScale(); // 朝右 if (dir == 0) { - SetScale(VecFPos({SDL_fabsf(sc.x), sc.y})); + SetScale(Vec2({SDL_fabsf(sc.x), sc.y})); } // 朝左 else if (dir == 1) { - SetScale(VecFPos({-SDL_fabsf(sc.x), sc.y})); + SetScale(Vec2({-SDL_fabsf(sc.x), sc.y})); } } diff --git a/source_game/Asset/Squirrel/Sqr_UI.hpp b/source_game/Asset/Squirrel/Sqr_UI.hpp index a098d61..2355423 100644 --- a/source_game/Asset/Squirrel/Sqr_UI.hpp +++ b/source_game/Asset/Squirrel/Sqr_UI.hpp @@ -1,7 +1,8 @@ #pragma once -#include "squirrel/SquirrelEx.h" -#include "EngineFrame/Actor/Actor.h" +#include "Sqr_CommonFunc.hpp" #include "EngineFrame/Component/Sprite.h" +#include "EngineFrame/Component/Canvas.h" +#include "EngineFrame/Component/Text.h" static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size)) { @@ -27,6 +28,27 @@ static SQInteger SQR_CreateActor(HSQUIRRELVM v) return 1; } +static SQInteger SQR_SetName(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + const SQChar *name; + sq_getstring(v, 3, &name); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetName(name); + + return 0; +} + +static SQInteger SQR_GetName(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + sq_pushstring(v, Aobj->GetName().c_str(), -1); + return 1; +} + static SQInteger SQR_AddChild(HSQUIRRELVM v) { SQUserPointer A_obj; @@ -76,7 +98,7 @@ static SQInteger SQR_GetPos(HSQUIRRELVM v) SQUserPointer A_obj; sq_getuserpointer(v, 2, &A_obj); Actor *Aobj = (Actor *)A_obj; - VecFPos Pos = Aobj->GetPos(); + Vec2 Pos = Aobj->GetPos(); sq_newtable(v); sq_pushstring(v, _SC("x"), -1); @@ -95,7 +117,7 @@ static SQInteger SQR_SetPos(HSQUIRRELVM v) if (sq_gettop(v) == 3) { - VecFPos Pos; + Vec2 Pos; sq_pushnull(v); // null iterator while (SQ_SUCCEEDED(sq_next(v, 3))) { @@ -125,7 +147,7 @@ static SQInteger SQR_SetPos(HSQUIRRELVM v) sq_getfloat(v, 3, &X); sq_getfloat(v, 4, &Y); Actor *Aobj = (Actor *)A_obj; - Aobj->SetPos(VecFPos(X, Y)); + Aobj->SetPos(Vec2(X, Y)); } return 0; } @@ -135,7 +157,7 @@ static SQInteger SQR_GetWorldPos(HSQUIRRELVM v) SQUserPointer A_obj; sq_getuserpointer(v, 2, &A_obj); Actor *Aobj = (Actor *)A_obj; - VecFPos Pos = Aobj->GetWorldPos(); + Vec2 Pos = Aobj->GetWorldPos(); sq_newtable(v); sq_pushstring(v, _SC("x"), -1); @@ -172,7 +194,7 @@ static SQInteger SQR_GetScale(HSQUIRRELVM v) SQUserPointer A_obj; sq_getuserpointer(v, 2, &A_obj); Actor *Aobj = (Actor *)A_obj; - VecFPos Pos = Aobj->GetScale(); + Vec2 Pos = Aobj->GetScale(); sq_newtable(v); sq_pushstring(v, _SC("x"), -1); sq_pushfloat(v, Pos.x); @@ -190,7 +212,7 @@ static SQInteger SQR_SetScale(HSQUIRRELVM v) if (sq_gettop(v) == 3) { - VecFPos Pos; + Vec2 Pos; sq_pushnull(v); // null iterator while (SQ_SUCCEEDED(sq_next(v, 3))) { @@ -220,7 +242,7 @@ static SQInteger SQR_SetScale(HSQUIRRELVM v) sq_getfloat(v, 3, &X); sq_getfloat(v, 4, &Y); Actor *Aobj = (Actor *)A_obj; - Aobj->SetScale(VecFPos(X, Y)); + Aobj->SetScale(Vec2(X, Y)); } return 0; } @@ -232,6 +254,7 @@ static SQInteger SQR_GetRotation(HSQUIRRELVM v) Actor *Aobj = (Actor *)A_obj; sq_pushfloat(v, Aobj->GetRotation()); + return 1; } static SQInteger SQR_SetRotation(HSQUIRRELVM v) @@ -314,6 +337,26 @@ static SQInteger SQR_SetVisible(HSQUIRRELVM v){ return 0; } +static SQInteger SQR_GetVisible(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + sq_pushbool(v, Aobj->GetVisible()); + return 1; +} + +static SQInteger SQR_SetBlendMode(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQInteger Value; + sq_getinteger(v, 3, &Value); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetBlendMode((LE_BlEND_MODE)Value); + return 0; +} + static SQInteger SQR_CreateSprite(HSQUIRRELVM v) { const SQChar *ImgPath; @@ -326,6 +369,77 @@ static SQInteger SQR_CreateSprite(HSQUIRRELVM v) return 1; } +static SQInteger SQR_CreateCanvas(HSQUIRRELVM v) +{ + SQInteger Width, Height; + sq_getinteger(v, 2, &Width); + sq_getinteger(v, 3, &Height); + RefPtr act = new Canvas(VecSize(Width, Height)); + act->Retain(); + sq_pushuserpointer(v, act.Get()); + return 1; +} + +static SQInteger SQR_Canvas_DrawImg(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + const SQChar *ImgPath; + SQInteger Idx; + Vec2 Pos; + sq_getuserpointer(v, 2, &A_obj); + sq_getstring(v, 3, &ImgPath); + sq_getinteger(v, 4, &Idx); + sq_GetVec2(v, 5, &Pos); + Canvas *Aobj = (Canvas *)A_obj; + Aobj->DrawImg(ImgPath, Idx, Pos); + return 0; +} + +static SQInteger SQR_Canvas_DrawImgRect(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + const SQChar *ImgPath; + SQInteger Idx; + SDL_FRect Rect; + sq_getuserpointer(v, 2, &A_obj); + sq_getstring(v, 3, &ImgPath); + sq_getinteger(v, 4, &Idx); + sq_GetFRect(v, 5, &Rect); + Canvas *Aobj = (Canvas *)A_obj; + Aobj->DrawImg(ImgPath, Idx, Rect); + return 0; +} + +static SQInteger SQR_CreateText(HSQUIRRELVM v) +{ + const SQChar *Str; + SQInteger FontIndex, FontColor; + SDL_Color color; + sq_getstring(v, 2, &Str); + sq_getinteger(v, 3, &FontIndex); + sq_getinteger(v, 4, &FontColor); + color.a = (FontColor >> 24) & 0xFF; + color.r = (FontColor >> 16) & 0xFF; + color.g = (FontColor >> 8) & 0xFF; + color.b = FontColor & 0xFF; + RefPtr act = new Text(); + act->Init(Str, Global_Game::GetInstance().Fonts[FontIndex], color); + act->Retain(); + sq_pushuserpointer(v, act.Get()); + return 1; +} + +static SQInteger SQR_Text_SetText(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + const SQChar *Str; + sq_getuserpointer(v, 2, &A_obj); + sq_getstring(v, 3, &Str); + Text *Aobj = (Text *)A_obj; + Aobj->SetText(Str); + return 0; +} + static void RegisterUINutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v) { sq_pushroottable(v); @@ -344,6 +458,8 @@ static void RegisterUI() RegisterUINutApi(_SC("sq_RegisterDestruction"), SQR_RegisterDestruction, v); RegisterUINutApi(_SC("sq_CreateActor"), SQR_CreateActor, v); + RegisterUINutApi(_SC("sq_SetName"), SQR_SetName, v); + RegisterUINutApi(_SC("sq_GetName"), SQR_GetName, v); RegisterUINutApi(_SC("sq_AddChild"), SQR_AddChild, v); RegisterUINutApi(_SC("sq_RemoveChild"), SQR_RemoveChild, v); RegisterUINutApi(_SC("sq_GetZOrder"), SQR_GetZOrder, v); @@ -360,6 +476,15 @@ static void RegisterUI() RegisterUINutApi(_SC("sq_GetSize"), SQR_GetSize, v); RegisterUINutApi(_SC("sq_SetSize"), SQR_SetSize, v); RegisterUINutApi(_SC("sq_SetVisible"), SQR_SetVisible, v); + RegisterUINutApi(_SC("sq_GetVisible"), SQR_GetVisible, v); + RegisterUINutApi(_SC("sq_SetBlendMode"), SQR_SetBlendMode, v); RegisterUINutApi(_SC("sq_CreateSprite"), SQR_CreateSprite, v); + + RegisterUINutApi(_SC("sq_CreateCanvas"), SQR_CreateCanvas, v); + RegisterUINutApi(_SC("sq_Canvas_DrawImg"), SQR_Canvas_DrawImg, v); + RegisterUINutApi(_SC("sq_Canvas_DrawImgRect"), SQR_Canvas_DrawImgRect, v); + + RegisterUINutApi(_SC("sq_CreateText"), SQR_CreateText, v); + RegisterUINutApi(_SC("sq_Text_SetText"), SQR_Text_SetText, v); } diff --git a/source_game/Asset/Squirrel/SquirrelManager.cpp b/source_game/Asset/Squirrel/SquirrelManager.cpp index 366776d..6e8720b 100644 --- a/source_game/Asset/Squirrel/SquirrelManager.cpp +++ b/source_game/Asset/Squirrel/SquirrelManager.cpp @@ -3,6 +3,8 @@ void SquirrelManager::Init() { SDL_Log("开始初始化sqr管理器!"); + // 系统函数 + RegisterSystem(); // UI函数 RegisterUI(); // 基础对象 @@ -11,4 +13,6 @@ void SquirrelManager::Init() RegisterActiveObject(); // 角色对象 RegisterCharacterObject(); + //资产 + RegisterAsset(); } diff --git a/source_game/Asset/Squirrel/SquirrelManager.h b/source_game/Asset/Squirrel/SquirrelManager.h index 18941ea..091fb44 100644 --- a/source_game/Asset/Squirrel/SquirrelManager.h +++ b/source_game/Asset/Squirrel/SquirrelManager.h @@ -1,8 +1,11 @@ #pragma once +#include "Global/Global_Game.h" +#include "Asset/Squirrel/Sqr_System.hpp" #include "Asset/Squirrel/Sqr_UI.hpp" #include "Asset/Squirrel/Sqr_BaseObject.hpp" #include "Asset/Squirrel/Sqr_ActiveObject.hpp" #include "Asset/Squirrel/Sqr_CharacterObject.hpp" +#include "Asset/Squirrel/Sqr_Asset.hpp" class SquirrelManager { public: diff --git a/source_game/Global/Global_Game.cpp b/source_game/Global/Global_Game.cpp index b7aa121..a4e30ba 100644 --- a/source_game/Global/Global_Game.cpp +++ b/source_game/Global/Global_Game.cpp @@ -1,4 +1,5 @@ #include "Global_Game.h" +#include "Asset/Squirrel/SquirrelManager.h" Global_Game::Global_Game() { @@ -7,18 +8,68 @@ Global_Game::~Global_Game() { } +void Global_Game::InitFont() +{ + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + SQInteger top = sq_gettop(v); + + sq_pushroottable(v); + sq_pushstring(v, _SC("_InitFont_"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_pushroottable(v); + if (SQ_SUCCEEDED(sq_call(v, 1, SQTrue, SQTrue))) + { + sq_pushnull(v); + while (SQ_SUCCEEDED(sq_next(v, -2))) + { + const SQChar *path = nullptr; + SQInteger size = 0; + + if (sq_gettype(v, -1) == OT_TABLE) + { + // 获取path + sq_pushstring(v, _SC("path"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_getstring(v, -1, &path); + sq_pop(v, 1); + } + + // 获取size + sq_pushstring(v, _SC("size"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_getinteger(v, -1, &size); + sq_pop(v, 1); + } + + // 初始化ttf字体资源 + TTF_Font *FontBuf = TTF_OpenFont(path, size); + if (!FontBuf) + { + SDL_LogError(0, "字体加载失败: %s", TTF_GetError()); + continue; + } + Fonts.push_back(FontBuf); + } + + sq_pop(v, 2); + } + sq_pop(v, 1); + } + } + sq_settop(v, top); +} + void Global_Game::Init() { - // 初始化ttf字体资源 - TTF_Font *FontBuf = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 24); + InitFont(); + // TTF_Font *FontBuf = TTF_OpenFont("Fonts/NotoSansSC-Regular.otf", 24); // TTF_Font *FontBuf = TTF_OpenFont("Fonts/calibri.ttf", 24); - if (!FontBuf) - { - SDL_LogError(0, "字体加载失败: %s", TTF_GetError()); - } - Fonts.push_back(FontBuf); + } void Global_Game::InitGame() diff --git a/source_game/Global/Global_Game.h b/source_game/Global/Global_Game.h index 4981270..74b2152 100644 --- a/source_game/Global/Global_Game.h +++ b/source_game/Global/Global_Game.h @@ -4,7 +4,6 @@ #include "Global/Script/EquipmentConfig.h" #include "Global/Script/MonsterConfig.h" #include "Global/Save/SavaManager.h" -#include "Asset/Squirrel/SquirrelManager.h" class Global_Game { @@ -48,4 +47,6 @@ public: private: Global_Game(/* args */); ~Global_Game(); + + void InitFont(); }; diff --git a/source_game/Scene/Scene_Loading_UI.cpp b/source_game/Scene/Scene_Loading_UI.cpp index bc8205e..509f20d 100644 --- a/source_game/Scene/Scene_Loading_UI.cpp +++ b/source_game/Scene/Scene_Loading_UI.cpp @@ -22,23 +22,19 @@ void Scene_Loading_UI::Enter() RefPtr BackGroundSp = new Sprite("ImagePacks2/Loading1.png"); actor->AddComponent(BackGroundSp); RefPtr BackGround2Sp = new Sprite("ImagePacks2/Loading0.png"); - BackGround2Sp->SetPos(VecFPos{0, 686}); + BackGround2Sp->SetPos(Vec2{0, 686}); actor->AddComponent(BackGround2Sp); RefPtr LoadCircleSp = new Sprite("ImagePacks2/Loading2.png"); LoadCircleSp->SetName("LoadCircle"); - LoadCircleSp->SetPos(VecFPos{1280 - 60, 686 - 60}); + LoadCircleSp->SetPos(Vec2{1280 - 60, 686 - 60}); LoadCircleSp->SetBlendMode(LINEARDODGE); - LoadCircleSp->SetAnchor(VecFPos{0.5f, 0.5f}); + LoadCircleSp->SetAnchor(Vec2{0.5f, 0.5f}); actor->AddComponent(LoadCircleSp); actor->SetCallbackOnUpdate([LoadCircleSp](float deltaTime) mutable { float angle = LoadCircleSp->GetRotation(); LoadCircleSp->SetRotation(angle + 180.0f * deltaTime); }); - - // 文字测试 - // RefPtr text = new Text("测试文字加载中...", Global_Game::GetInstance().Fonts[0], SDL_Color{255, 255, 255, 255}, SDL_Color{0, 0, 0, 255}, 4); - // actor->AddComponent(text); } void Scene_Loading_UI::Update(float deltaTime) diff --git a/source_game/Scene/Scene_MainUi.cpp b/source_game/Scene/Scene_MainUi.cpp index 835c927..5c3c82e 100644 --- a/source_game/Scene/Scene_MainUi.cpp +++ b/source_game/Scene/Scene_MainUi.cpp @@ -4,7 +4,6 @@ void Scene_MainUi::Enter() { Scene::Enter(); - HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); SQInteger top = sq_gettop(v); sq_pushroottable(v); diff --git a/source_game/Scene/Scene_Test.cpp b/source_game/Scene/Scene_Test.cpp index 76765bc..61b8ee6 100644 --- a/source_game/Scene/Scene_Test.cpp +++ b/source_game/Scene/Scene_Test.cpp @@ -16,41 +16,42 @@ Scene_Test::~Scene_Test() void Scene_Test::Enter() { - SetScale(VecFPos(1.2f, 1.2f)); map = new GameMap; - map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map"); + map->LoadMap("map/cataclysm/town/elvengard/new_d_elvengard_l.map"); map->Enter(this); RefPtr obj = new CharacterObject(); obj->SetPosition({1000, 300, 0}); obj->Construction(0); + map->AddObject(obj); + RefPtr monster = new MonsterObject(); monster->SetPosition({1200, 301, 0}); monster->Construction(1); monster->SetDirection(1); - - map->AddObject(obj); map->AddObject(monster); _camera = new GameMapCamera; _camera->SetFromActor(obj.Get()); + return; // // SDL_Log("Scene_Test::进入测试场景!"); RefPtr actor = new Actor; AddChild(actor); - RefPtr sprite = new Sprite("ImagePacks2/test_white_background.png"); + // RefPtr sprite = new Sprite("ImagePacks2/test_white_background.png"); RefPtr chr = new Sprite("sprite/interface2/hud/hud.img", 0); - // chr->SetPos(VecFPos{200, 100}); + chr->SetPos(Vec2{200, 100}); // chr->SetAlpha(0.5); // chr->SetShadow(); - actor->AddComponent(chr); + // actor->AddComponent(chr); - // RefPtr canvas = new Canvas(VecSize{1280, 720}); - // actor->AddChild(canvas); + RefPtr canvas = new Canvas(VecSize{250, 720}); + actor->AddChild(canvas); + canvas->DrawImg("sprite/interface2/hud/hud.img", 0, Vec2{0, 0}); // canvas->AddChild(chr); @@ -58,21 +59,16 @@ void Scene_Test::Enter() // RefPtr ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); // Am->AddAnimation(ani4); - // // Am->SetPos(VecFPos{200, 100}); + // // Am->SetPos(Vec2{200, 100}); // actor->AddChild(Am); - // RefPtr text = new Text(); - // text->Init("测试文本", Global_Game::GetInstance().Fonts[0], SDL_Color{255, 255, 255, 255}); - // text->SetPos(VecFPos{200, 100}); - // actor->AddChild(text); - // // sprite2->UnsetClipRect(); // RefPtr actor2 = new Actor; // actor->AddChild(actor2); // RefPtr ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); - // // ani4->SetScale(VecFPos{-1.0, 1.0}); + // // ani4->SetScale(Vec2{-1.0, 1.0}); // actor->AddChild(ani4); // RefPtr ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani");