加入 Node节点类 还未测试新框架

This commit is contained in:
2025-10-27 23:12:56 +08:00
parent 80d088316b
commit 0ae47e5d6a
52 changed files with 1642 additions and 458 deletions

View File

@@ -96,5 +96,6 @@
"semaphore": "cpp", "semaphore": "cpp",
"cinttypes": "cpp", "cinttypes": "cpp",
"netfwd": "cpp" "netfwd": "cpp"
} },
"Codegeex.RepoIndex": true
} }

View File

@@ -214,5 +214,8 @@
}, },
"source/EngineFrame/Component/NumberText.h": { "source/EngineFrame/Component/NumberText.h": {
"description": "数字文本" "description": "数字文本"
},
"source/EngineFrame/Attribute": {
"description": "属性"
} }
} }

View File

@@ -1,7 +1,7 @@
#include "Game.h" #include "Game.h"
#include "squirrel/SquirrelEx.h" #include "squirrel/SquirrelEx.h"
#include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Component/Sprite.h"
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Component/Text.h" #include "EngineFrame/Component/Text.h"
Game::Game() Game::Game()
@@ -25,10 +25,11 @@ void Game::Init(std::function<void()> CallBack)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // 双缓冲 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // 双缓冲
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); // 24位深度缓冲避免z-fighting
// 启用多重采样(关键步骤) // 启用多重采样(关键步骤)
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // 启用多重采样缓冲 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // 启用多重采样缓冲
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); // 4x 采样(可改为 8 等) SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{ {

View File

@@ -0,0 +1,26 @@
#pragma once
#include <type_traits>
namespace bits
{
template <typename _Ty>
inline void Set(_Ty &old, _Ty flag)
{
static_assert(std::is_arithmetic<_Ty>::value, "_Ty must be an arithmetic type");
old |= flag;
}
template <typename _Ty>
inline void Unset(_Ty &old, _Ty flag)
{
static_assert(std::is_arithmetic<_Ty>::value, "_Ty must be an arithmetic type");
old &= ~flag;
}
template <typename _Ty>
inline bool Has(_Ty old, _Ty flag)
{
static_assert(std::is_arithmetic<_Ty>::value, "_Ty must be an arithmetic type");
return !!(old & flag);
}
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <cstdint> // uint8_t
#include "Bits.h"
template <typename _Ty>
class Flag
{
public:
static_assert(std::is_arithmetic<_Ty>::value, "_Ty must be an arithmetic type");
typedef _Ty value_type;
_Ty value;
inline Flag()
: value()
{
}
inline Flag(_Ty value)
: value(value)
{
}
inline void Set(_Ty value)
{
bits::Set(this->value, value);
}
inline void Unset(_Ty value)
{
bits::Unset(this->value, value);
}
inline bool Has(_Ty value) const
{
return bits::Has(this->value, value);
}
};
template <typename _Ty>
struct IsFlag : public std::false_type
{
};
template <typename _Ty>
struct IsFlag<Flag<_Ty>> : public std::true_type
{
};
typedef Flag<uint8_t> FlagUint8;
typedef Flag<uint16_t> FlagUint16;
typedef Flag<uint32_t> FlagUint32;
typedef Flag<uint64_t> FlagUint64;
typedef Flag<int8_t> FlagInt8;
typedef Flag<int16_t> FlagInt16;
typedef Flag<int32_t> FlagInt32;
typedef Flag<int64_t> FlagInt64;

View File

@@ -0,0 +1,61 @@
#include "Y_Transform.h"
#include <cmath>
Y_Transform::Y_Transform() : position(0.f, 0.f), scale(1.0f, 1.0f), skew(0.f, 0.f), rotation(0.f)
{
}
Matrix3x2 Y_Transform::ToMatrix() const
{
// 将角度转换为弧度
float rotRad = glm::radians(rotation);
float skewXRad = glm::radians(skew.x);
float skewYRad = glm::radians(skew.y);
// 计算旋转的正弦和余弦
float cosRot = std::cos(rotRad);
float sinRot = std::sin(rotRad);
// 计算错切的正切值
float tanSkewX = std::tan(skewXRad);
float tanSkewY = std::tan(skewYRad);
// 构造基础变换矩阵(缩放 × 错切 × 旋转的组合)
// 注意:矩阵乘法顺序为 旋转 × 错切 × 缩放(从右向左应用)
float m00 = scale.x * (cosRot - sinRot * tanSkewY);
float m01 = scale.y * (-sinRot + cosRot * tanSkewX);
float m10 = scale.x * (sinRot + cosRot * tanSkewY);
float m11 = scale.y * (cosRot + sinRot * tanSkewX);
// 平移分量
float tx = position.x;
float ty = position.y;
// 构造并返回 3x2 矩阵(假设 Matrix3x2 可通过此方式初始化)
return Matrix3x2(m00, m01, m10, m11, tx, ty);
}
glm::mat4 Y_Transform::GetTransformMatrix() const
{
// 缩放矩阵Scale
glm::mat4 scaleMat = glm::mat4(1.0f); // 单位矩阵
scaleMat[0][0] = scale.x; // x轴缩放
scaleMat[1][1] = scale.y; // y轴缩放
// 错切矩阵Skew先将角度转为弧度
float skewX = glm::radians(skew.x); // 沿y轴错切角度x方向倾斜
float skewY = glm::radians(skew.y); // 沿x轴错切角度y方向倾斜
glm::mat4 skewMat = glm::mat4(1.0f);
skewMat[0][1] = tan(skewX); // x方向错切因子影响y轴
skewMat[1][0] = tan(skewY); // y方向错切因子影响x轴
// 旋转矩阵Rotation绕z轴旋转角度转弧度
float rotRad = glm::radians(rotation);
glm::mat4 rotMat = glm::rotate(glm::mat4(1.0f), rotRad, glm::vec3(0, 0, 1));
// 平移矩阵Translation
glm::mat4 transMat = glm::translate(glm::mat4(1.0f), glm::vec3(position, 0.0f));
// 组合变换矩阵:平移 × 旋转 × 错切 × 缩放(注意乘法顺序,从右向左应用)
return transMat * rotMat * skewMat * scaleMat;
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "math/Math.h"
#include <glm/glm.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/gtc/type_ptr.hpp>
class Y_Transform
{
public:
float rotation; ///< 旋转
glm::vec2 position; ///< 坐标
glm::vec2 scale; ///< 缩放
glm::vec2 skew; ///< 错切角度
public:
Y_Transform(/* args */);
bool IsFast() const
{
return skew.x == 0.f && skew.y == 0.f &&
scale.x == 1.f && scale.y == 1.f &&
rotation == 0.f;
}
Matrix3x2 ToMatrix() const;
glm::mat4 GetTransformMatrix() const;
};

View File

@@ -18,8 +18,17 @@ void Actor::Init()
addTag(Tag::UPDATE); addTag(Tag::UPDATE);
} }
void Actor::Update(float deltaTime)
{
if (!Visible)
return;
BaseNode::Update(deltaTime);
}
void Actor::Render() void Actor::Render()
{ {
if (!Visible)
return;
// 如果有裁切视口 // 如果有裁切视口
if (this->_CropViewportFlag) if (this->_CropViewportFlag)
{ {
@@ -34,16 +43,6 @@ void Actor::Render()
} }
} }
void Actor::AddComponent(RefPtr<Component> Component)
{
BaseNode::AddChild(Component);
}
void Actor::RemoveComponent(RefPtr<Component> Component)
{
BaseNode::RemoveChild(Component);
}
void Actor::SetCropViewport(SDL_Rect CropViewport) void Actor::SetCropViewport(SDL_Rect CropViewport)
{ {
if (CropViewport.x == 0 && CropViewport.y == 0 && CropViewport.w == 0 && CropViewport.h == 0) if (CropViewport.x == 0 && CropViewport.y == 0 && CropViewport.w == 0 && CropViewport.h == 0)

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include "EngineFrame/Base/BaseNode.h" #include "EngineFrame/Base/BaseNode.h"
#include "EngineFrame/Component/Component.h"
#include "Tool/IntrusiveList.hpp" #include "Tool/IntrusiveList.hpp"
class Scene; class Scene;
/** /**
@@ -21,9 +20,8 @@ public:
public: public:
void Init() override; void Init() override;
void Update(float deltaTime) override;
void Render() override; void Render() override;
void AddComponent(RefPtr<Component> Component);
void RemoveComponent(RefPtr<Component> Component);
// 设置裁切视口(放在Actor里 他与他的子对象都会被裁切) // 设置裁切视口(放在Actor里 他与他的子对象都会被裁切)
void SetCropViewport(SDL_Rect CropViewport); void SetCropViewport(SDL_Rect CropViewport);

View File

@@ -27,11 +27,6 @@ void BaseNode::HandleEvents(SDL_Event *e)
void BaseNode::Update(float deltaTime) void BaseNode::Update(float deltaTime)
{ {
// 如果有回调函数,则调用回调函数
if (cb_update_)
{
cb_update_(deltaTime);
}
// 如果有子节点并含有刷新标签,则更新子节点 // 如果有子节点并含有刷新标签,则更新子节点
RefPtr<BaseNode> child = m_BaseNodes.GetFirst(); RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child) while (child)
@@ -40,6 +35,14 @@ void BaseNode::Update(float deltaTime)
child->Update(deltaTime); child->Update(deltaTime);
child = child->GetNext(); child = child->GetNext();
} }
// 如果有回调函数,则调用回调函数
if (cb_update_.size() > 0)
{
for (auto &cb : cb_update_)
{
cb.second(deltaTime);
}
}
} }
void BaseNode::PreRender() void BaseNode::PreRender()
@@ -53,7 +56,6 @@ void BaseNode::PreRender()
child = child->GetNext(); child = child->GetNext();
} }
} }
void BaseNode::Render() void BaseNode::Render()
{ {
// 如果有子节点并含有渲染标签,则渲染子节点 // 如果有子节点并含有渲染标签,则渲染子节点
@@ -70,9 +72,14 @@ void BaseNode::Clear()
{ {
} }
void BaseNode::SetCallbackOnUpdate(const UpdateCallback &cb) void BaseNode::SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb)
{ {
cb_update_ = cb; cb_update_[Key] = cb;
}
void BaseNode::RemoveCallbackOnUpdate(std::string Key)
{
cb_update_.erase(Key);
} }
void BaseNode::SetChildIterationTransform() void BaseNode::SetChildIterationTransform()

View File

@@ -20,7 +20,7 @@ public:
public: public:
// 更新时的回调函数 // 更新时的回调函数
UpdateCallback cb_update_; std::map<std::string ,UpdateCallback> cb_update_;
// 节点名称 // 节点名称
std::string m_Name; std::string m_Name;
// 子节点列表 // 子节点列表
@@ -60,7 +60,8 @@ public:
/// \~chinese /// \~chinese
/// @brief 设置更新时的回调函数 /// @brief 设置更新时的回调函数
void SetCallbackOnUpdate(const UpdateCallback &cb); void SetCallbackOnUpdate(std::string Key,const UpdateCallback &cb);
void RemoveCallbackOnUpdate(std::string Key);
void SetChildIterationTransform(); void SetChildIterationTransform();

View File

@@ -0,0 +1,549 @@
#include "Node.h"
#include "EngineCore/Game.h"
void Node::Init()
{
}
void Node::HandleEvents(SDL_Event *e)
{
}
inline void Node::Update(float deltaTime)
{
if (children_.IsEmpty())
{
return;
}
RefPtr<Node> child = children_.GetFirst();
while (child)
{
if (child->GetZOrder() >= 0)
break;
child->Update(deltaTime);
child = child->GetNext();
}
UpdateSelf(deltaTime);
while (child)
{
child->Update(deltaTime);
child = child->GetNext();
}
}
inline void Node::PreRender()
{
}
inline void Node::Render()
{
}
void Node::Clear()
{
}
void Node::UpdateSelf(float deltaTime)
{
// 如果有回调函数,则调用回调函数
if (cb_update_.size() > 0)
{
for (auto &cb : cb_update_)
{
cb.second(deltaTime);
}
}
}
void Node::RemoveFromParent()
{
if (parent_)
{
parent_->RemoveChild(this);
}
}
inline void Node::PauseUpdating()
{
update_pausing_ = true;
}
inline void Node::ResumeUpdating()
{
update_pausing_ = false;
}
inline bool Node::IsUpdatePausing() const
{
return update_pausing_;
}
void Node::SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb)
{
cb_update_[Key] = cb;
}
void Node::RemoveCallbackOnUpdate(std::string Key)
{
cb_update_.erase(Key);
}
bool Node::ContainsPoint(const glm::vec2 &point) const
{
// if (size_.x == 0.f || size_.y == 0.f)
return false;
// glm::vec2 local = ConvertToLocal(point);
// return local.x >= 0 && local.y >= 0 && local.x <= size_.x && local.y <= size_.y;
}
glm::vec2 Node::ConvertToLocal(const glm::vec2 &point) const
{
glm::vec2 local = GetTransformInverseMatrix().Transform(point);
return local;
}
glm::vec2 Node::ConvertToWorld(const glm::vec2 &point) const
{
glm::vec2 world = GetTransformMatrix().Transform(point);
return world;
}
void Node::ShowBorder(bool show)
{
show_border_ = show;
}
Node::Node() : visible_(true), update_pausing_(false), show_border_(false), parent_(nullptr), anchor_(0.0f, 0.0f), z_order_(0), opacity_(1.f), name_("Node")
{
Game::GetInstance().m_nodeCount++;
}
Node::~Node()
{
Game::GetInstance().m_nodeCount--;
RemoveAllChildren();
}
void Node::UpdateTransform() const
{
if (!dirty_flag_.Has(DirtyFlag::DirtyTransform))
return;
dirty_flag_.Unset(DirtyFlag::DirtyTransform);
dirty_flag_.Set(DirtyFlag::DirtyTransformInverse);
dirty_flag_.Set(DirtyFlag::DirtyVisibility);
if (transform_.IsFast())
{
transform_matrix_to_parent_ = Matrix3x2::Translation(transform_.position);
}
else
{
transform_matrix_to_parent_ = transform_.ToMatrix();
}
glm::vec2 anchor_offset(-size_.width * anchor_.x, -size_.height * anchor_.y);
transform_matrix_to_parent_.Translate(anchor_offset);
transform_matrix_ = transform_matrix_to_parent_;
if (parent_)
{
transform_matrix_ *= parent_->transform_matrix_;
}
for (const auto &child : children_)
child->dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
void Node::UpdateTransformUpwards() const
{
if (parent_)
{
parent_->UpdateTransformUpwards();
if (parent_->dirty_flag_.Has(DirtyFlag::DirtyTransform))
{
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
}
UpdateTransform();
}
const Matrix3x2 &Node::GetTransformMatrix() const
{
UpdateTransformUpwards();
return transform_matrix_;
}
const Matrix3x2 &Node::GetTransformInverseMatrix() const
{
UpdateTransformUpwards();
if (dirty_flag_.Has(DirtyFlag::DirtyTransformInverse))
{
dirty_flag_.Unset(DirtyFlag::DirtyTransformInverse);
transform_matrix_inverse_ = transform_matrix_.Invert();
}
return transform_matrix_inverse_;
}
const Matrix3x2 &Node::GetTransformMatrixToParent() const
{
UpdateTransformUpwards();
return transform_matrix_to_parent_;
}
void Node::Reorder()
{
if (parent_)
{
RefPtr<Node> me = this;
parent_->children_.Remove(me);
RefPtr<Node> sibling = parent_->children_.GetLast();
if (sibling && sibling->GetZOrder() > z_order_)
{
sibling = sibling->GetPrev();
while (sibling)
{
if (sibling->GetZOrder() <= z_order_)
break;
sibling = sibling->GetPrev();
}
}
if (sibling)
{
parent_->children_.InsertAfter(me, sibling);
}
else
{
parent_->children_.PushFront(me);
}
}
}
inline void Node::RemoveAllChildren()
{
RefPtr<Node> next;
for (RefPtr<Node> child = children_.GetFirst(); child; child = next)
{
next = child->GetNext();
RemoveChild(child);
}
}
inline bool Node::IsVisible() const
{
return visible_;
}
inline int Node::GetZOrder() const
{
return z_order_;
}
inline glm::vec2 Node::GetPosition() const
{
return transform_.position;
}
inline float Node::GetPositionX() const
{
return GetPosition().x;
}
inline float Node::GetPositionY() const
{
return GetPosition().y;
}
inline VecSize Node::GetSize() const
{
return size_;
}
inline float Node::GetWidth() const
{
return GetSize().width;
}
inline float Node::GetHeight() const
{
return GetSize().height;
}
inline float Node::GetScaledWidth() const
{
return GetWidth() * GetScaleX();
}
inline float Node::GetScaledHeight() const
{
return GetHeight() * GetScaleY();
}
inline VecSize Node::GetScaledSize() const
{
return VecSize{GetScaledWidth(), GetScaledHeight()};
}
inline glm::vec2 Node::GetAnchor() const
{
return anchor_;
}
inline float Node::GetAnchorX() const
{
return GetAnchor().x;
}
inline float Node::GetAnchorY() const
{
return GetAnchor().y;
}
inline float Node::GetOpacity() const
{
return opacity_;
}
inline float Node::GetRotation() const
{
return transform_.rotation;
}
inline glm::vec2 Node::GetScale() const
{
return transform_.scale;
}
inline float Node::GetScaleX() const
{
return GetScale().x;
}
inline float Node::GetScaleY() const
{
return GetScale().y;
}
inline glm::vec2 Node::GetSkew() const
{
return transform_.skew;
}
inline float Node::GetSkewX() const
{
return GetSkew().x;
}
inline float Node::GetSkewY() const
{
return GetSkew().y;
}
inline Y_Transform Node::GetTransform() const
{
return transform_;
}
inline Node *Node::GetParent() const
{
return parent_;
}
inline void Node::SetVisible(bool val)
{
visible_ = val;
}
inline void Node::SetName(std::string name)
{
name_ = name;
}
inline void Node::SetPosition(const glm::vec2 &pos)
{
if (transform_.position == pos)
return;
transform_.position = pos;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetPosition(float x, float y)
{
this->SetPosition(glm::vec2(x, y));
}
inline void Node::SetPositionX(float x)
{
this->SetPosition(glm::vec2(x, GetPosition().y));
}
inline void Node::SetPositionY(float y)
{
this->SetPosition(glm::vec2(GetPosition().x, y));
}
inline void Node::MoveTo(const glm::vec2 &p)
{
this->SetPosition(p);
}
inline void Node::MoveTo(float x, float y)
{
this->SetPosition(glm::vec2(x, y));
}
inline void Node::MoveBy(const glm::vec2 &trans)
{
this->SetPosition(transform_.position.x + trans.x, transform_.position.y + trans.y);
}
inline void Node::MoveBy(float trans_x, float trans_y)
{
this->MoveBy(glm::vec2(trans_x, trans_y));
}
inline void Node::SetScale(const glm::vec2 &scale)
{
if (transform_.scale == scale)
return;
transform_.scale = scale;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetScale(float scalex, float scaley)
{
this->SetScale(glm::vec2(scalex, scaley));
}
inline void Node::SetSkew(const glm::vec2 &skew)
{
if (transform_.skew == skew)
return;
transform_.skew = skew;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetSkew(float skewx, float skewy)
{
this->SetSkew(glm::vec2(skewx, skewy));
}
inline void Node::SetRotation(float rotation)
{
if (transform_.rotation == rotation)
return;
transform_.rotation = rotation;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetAnchor(const glm::vec2 &anchor)
{
if (anchor_ == anchor)
return;
anchor_ = anchor;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetAnchor(float anchorx, float anchory)
{
this->SetAnchor(glm::vec2(anchorx, anchory));
}
inline void Node::SetSize(const VecSize &size)
{
if (size_ == size)
return;
size_ = size;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetSize(float width, float height)
{
this->SetSize(VecSize{width, height});
}
inline void Node::SetWidth(float width)
{
this->SetSize(width, GetHeight());
}
inline void Node::SetHeight(float height)
{
this->SetSize(GetWidth(), height);
}
inline void Node::SetOpacity(float opacity)
{
if (opacity_ == opacity)
return;
opacity_ = std::min(std::max(opacity, 0.f), 1.f);
dirty_flag_.Set(DirtyFlag::DirtyOpacity);
}
inline void Node::SetTransform(const Y_Transform &transform)
{
transform_ = transform;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetZOrder(int zorder)
{
if (z_order_ != zorder)
{
z_order_ = zorder;
Reorder();
}
}
void Node::AddChild(RefPtr<Node> child)
{
if (child)
{
assert(!child->parent_ && "Actor::AddChild failed, the actor to be added already has a parent");
children_.PushBack(child);
child->parent_ = this;
child->dirty_flag_.Set(DirtyFlag::DirtyTransform);
child->dirty_flag_.Set(DirtyFlag::DirtyOpacity);
child->Reorder();
}
else
{
SDL_LogError(0, "Actor::AddChild failed, NULL pointer exception");
}
}
Node::NodeList &Node::GetAllChildren()
{
return children_;
}
const Node::NodeList &Node::GetAllChildren() const
{
return children_;
}
inline void Node::RemoveChild(RefPtr<Node> child)
{
if (children_.IsEmpty())
return;
if (child)
{
child->parent_ = nullptr;
children_.Remove(child);
}
else
{
SDL_LogError(0, "Actor::RemoveChild failed, NULL pointer exception");
}
}

View File

@@ -0,0 +1,355 @@
#pragma once
#include <SDL.h>
#include "EngineFrame/Attribute/Y_Transform.h"
#include "EngineFrame/Attribute/Flag.h"
#include "math/Math.h"
#include "Tool/RefObject.h"
#include "Tool/RefPtr.h"
#include "Tool/IntrusiveList.hpp"
class Node : public RefObject, protected IntrusiveListValue<RefPtr<Node>>
{
public:
typedef std::function<void(float deltaTime)> UpdateCallback;
typedef IntrusiveList<RefPtr<Node>> NodeList;
using IntrusiveListValue<RefPtr<Node>>::GetNext;
using IntrusiveListValue<RefPtr<Node>>::GetPrev;
private:
/**变换属性 */
Y_Transform transform_;
/**变换矩阵 */
mutable Matrix3x2 transform_matrix_;
mutable Matrix3x2 transform_matrix_inverse_;
mutable Matrix3x2 transform_matrix_to_parent_;
/**更新时的回调函数 */
std::map<std::string, UpdateCallback> cb_update_;
/**锚点 */
glm::vec2 anchor_;
/**Z轴显示层级 */
int z_order_;
/**大小 */
VecSize size_;
/**透明度 */
float opacity_;
/**是否可见 */
bool visible_;
/**是否暂停更新 */
bool update_pausing_;
/**是否显示边界 */
bool show_border_;
/**名称 */
std::string name_;
/**父对象 */
Node *parent_;
/**子对象链表 */
NodeList children_;
/**标志 */
mutable Flag<uint8_t> dirty_flag_;
public:
virtual void Init();
virtual void HandleEvents(SDL_Event *e);
virtual void Update(float deltaTime);
virtual void PreRender();
virtual void Render();
virtual void Clear();
void UpdateSelf(float dt);
public:
/// \~chinese
/// @brief 获取显示状态
bool IsVisible() const;
/// \~chinese
/// @brief 获取 Z 轴顺序
int GetZOrder() const;
/// \~chinese
/// @brief 获取坐标
glm::vec2 GetPosition() const;
/// \~chinese
/// @brief 获取 x 坐标
float GetPositionX() const;
/// \~chinese
/// @brief 获取 y 坐标
float GetPositionY() const;
/// \~chinese
/// @brief 获取大小
virtual VecSize GetSize() const;
/// \~chinese
/// @brief 获取宽度
float GetWidth() const;
/// \~chinese
/// @brief 获取高度
float GetHeight() const;
/// \~chinese
/// @brief 获取缩放后的宽度
float GetScaledWidth() const;
/// \~chinese
/// @brief 获取缩放后的高度
float GetScaledHeight() const;
/// \~chinese
/// @brief 获取缩放后的大小
VecSize GetScaledSize() const;
/// \~chinese
/// @brief 获取锚点
glm::vec2 GetAnchor() const;
/// \~chinese
/// @brief 获取 x 方向锚点
float GetAnchorX() const;
/// \~chinese
/// @brief 获取 y 方向锚点
float GetAnchorY() const;
/// \~chinese
/// @brief 获取透明度
float GetOpacity() const;
/// \~chinese
/// @brief 获取旋转角度
float GetRotation() const;
/// \~chinese
/// @brief 获取缩放比例
glm::vec2 GetScale() const;
/// \~chinese
/// @brief 获取横向缩放比例
float GetScaleX() const;
/// \~chinese
/// @brief 获取纵向缩放比例
float GetScaleY() const;
/// \~chinese
/// @brief 获取错切角度
glm::vec2 GetSkew() const;
/// \~chinese
/// @brief 获取横向错切角度
float GetSkewX() const;
/// \~chinese
/// @brief 获取纵向错切角度
float GetSkewY() const;
/// \~chinese
/// @brief 获取变换
Y_Transform GetTransform() const;
/// \~chinese
/// @brief 获取父角色
Node *GetParent() const;
/// \~chinese
/// @brief 设置角色是否可见
void SetVisible(bool val);
/// \~chinese
/// @brief 设置名称
void SetName(std::string name);
/// \~chinese
/// @brief 设置坐标
void SetPosition(const glm::vec2 &pos);
/// \~chinese
/// @brief 设置坐标
void SetPosition(float x, float y);
/// \~chinese
/// @brief 设置横坐标
void SetPositionX(float x);
/// \~chinese
/// @brief 设置纵坐标
void SetPositionY(float y);
/// \~chinese
/// @brief 移动至坐标
void MoveTo(const glm::vec2 &p);
/// \~chinese
/// @brief 移动至坐标
void MoveTo(float x, float y);
/// \~chinese
/// @brief 移动相对坐标
void MoveBy(const glm::vec2 &trans);
/// \~chinese
/// @brief 移动相对坐标
void MoveBy(float trans_x, float trans_y);
/// \~chinese
/// @brief 设置缩放比例,默认为 (1.0, 1.0)
void SetScale(const glm::vec2 &scale);
/// \~chinese
/// @brief 设置缩放比例,默认为 (1.0, 1.0)
void SetScale(float scalex, float scaley);
/// \~chinese
/// @brief 设置错切角度,默认为 (0, 0)
void SetSkew(const glm::vec2 &skew);
/// \~chinese
/// @brief 设置错切角度,默认为 (0, 0)
void SetSkew(float skewx, float skewy);
/// \~chinese
/// @brief 设置旋转角度,默认为 0
void SetRotation(float rotation);
/// \~chinese
/// @brief 设置锚点位置,默认为 (0, 0), 范围 [0, 1]
void SetAnchor(const glm::vec2 &anchor);
/// \~chinese
/// @brief 设置锚点位置,默认为 (0, 0), 范围 [0, 1]
void SetAnchor(float anchorx, float anchory);
/// \~chinese
/// @brief 修改大小
void SetSize(const VecSize &size);
/// \~chinese
/// @brief 修改大小
void SetSize(float width, float height);
/// \~chinese
/// @brief 修改宽度
void SetWidth(float width);
/// \~chinese
/// @brief 修改高度
void SetHeight(float height);
/// \~chinese
/// @brief 设置透明度,默认为 1.0, 范围 [0, 1]
void SetOpacity(float opacity);
/// \~chinese
/// @brief 设置二维仿射变换
void SetTransform(const Y_Transform &transform);
/// \~chinese
/// @brief 设置 Z 轴顺序,默认为 0
void SetZOrder(int zorder);
/// \~chinese
/// @brief 添加子角色
void AddChild(RefPtr<Node> child);
/// \~chinese
/// @brief 获取全部子角色
NodeList &GetAllChildren();
/// \~chinese
/// @brief 获取全部子角色
const NodeList &GetAllChildren() const;
/// \~chinese
/// @brief 移除子角色
void RemoveChild(RefPtr<Node> child);
/// \~chinese
/// @brief 移除所有节点
void RemoveAllChildren();
/// \~chinese
/// @brief 从父角色移除
void RemoveFromParent();
/// \~chinese
/// @brief 暂停角色更新
void PauseUpdating();
/// \~chinese
/// @brief 继续角色更新
void ResumeUpdating();
/// \~chinese
/// @brief 角色更新是否暂停
bool IsUpdatePausing() const;
/// \~chinese
/// @brief 设置更新时的回调函数
void SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb);
/// \~chinese
/// @brief 移除更新时的回调函数
void RemoveCallbackOnUpdate(std::string Key);
/// \~chinese
/// @brief 判断点是否在角色内
virtual bool ContainsPoint(const glm::vec2 &point) const;
/// \~chinese
/// @brief 将世界坐标系点转换为局部坐标系点
glm::vec2 ConvertToLocal(const glm::vec2 &point) const;
/// \~chinese
/// @brief 将局部坐标系点转换为世界坐标系点
glm::vec2 ConvertToWorld(const glm::vec2 &point) const;
/// \~chinese
/// @brief 渲染角色边界
void ShowBorder(bool show);
public:
Node(/* args */);
~Node();
/// \~chinese
/// @brief 更新自己的二维变换,并通知所有子角色
void UpdateTransform() const;
/// \~chinese
/// @brief 向上追溯更新
/// @details 对于节点树 A->B(dirty)->C->D当对 D 执行 UpdateTransformUpwards 时会对 B、C、D 从上到下依次更新
void UpdateTransformUpwards() const;
/// \~chinese
/// @brief 获取二维变换矩阵
const Matrix3x2 &GetTransformMatrix() const;
/// \~chinese
/// @brief 获取二维变换的逆矩阵
const Matrix3x2 &GetTransformInverseMatrix() const;
/// \~chinese
/// @brief 获取变换到父角色的二维变换矩阵
const Matrix3x2 &GetTransformMatrixToParent() const;
/// \~chinese
/// @brief 将所有子角色按Z轴顺序排序
void Reorder();
enum DirtyFlag : uint8_t
{
Clean = 0,
DirtyTransform = 1,
DirtyTransformInverse = 1 << 1,
DirtyOpacity = 1 << 2,
DirtyVisibility = 1 << 3
};
};

View File

@@ -2,7 +2,7 @@
#include "Asset/AssetManager.h" #include "Asset/AssetManager.h"
#include "Asset/Asset_Script.h" #include "Asset/Asset_Script.h"
#include "Tool/Math.h" #include "Tool/Math.h"
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "EngineCore/Game.h" #include "EngineCore/Game.h"
Animation::Animation() Animation::Animation()

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Component/Sprite.h"
#include "Asset/AnimationStruct.h" #include "Asset/AnimationStruct.h"
#include <functional> #include <functional>

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Render/Texture.h" #include "EngineFrame/Render/Texture.h"
#include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Component/Sprite.h"
class Canvas : public Actor class Canvas : public Actor

View File

@@ -1,7 +0,0 @@
#include "Component.h"
#include "EngineFrame/Actor/Actor.h"
void Component::Init()
{
addTag(Tag::COMPONENT);
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "EngineFrame/Base/BaseNode.h"
#include <SDL.h>
class Actor;
class Component : public BaseNode
{
public:
void Init() override;
};

View File

@@ -1,13 +1,6 @@
#include "RenderBase.h" #include "RenderBase.h"
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
RenderBase::RenderBase()
{
}
RenderBase::~RenderBase()
{
}
void RenderBase::CalcRenderInfo() void RenderBase::CalcRenderInfo()
{ {
@@ -16,39 +9,23 @@ void RenderBase::CalcRenderInfo()
void RenderBase::Init() void RenderBase::Init()
{ {
Component::Init();
// 标记该组件需要渲染和更新
addTag(Tag::RENDER);
addTag(Tag::UPDATE);
addTag(Tag::TRANSFORM);
// 计算渲染信息 // 计算渲染信息
CalcRenderInfo(); CalcRenderInfo();
} }
void RenderBase::Update(float deltaTime)
{
if (!Visible)
return;
Component::Update(deltaTime);
}
void RenderBase::Render()
{
if (!Visible)
return;
Component::Render();
}
void RenderBase::SetIterationPos(Vec2 pos) void RenderBase::SetIterationPos(Vec2 pos)
{ {
Component::SetIterationPos(pos); Actor::SetIterationPos(pos);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
void RenderBase::SetIterationScale(Vec2 scale) void RenderBase::SetIterationScale(Vec2 scale)
{ {
Component::SetIterationScale(scale); Actor::SetIterationScale(scale);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
@@ -56,31 +33,31 @@ void RenderBase::SetIterationRotation(float angle)
{ {
if (!Visible) if (!Visible)
return; return;
Component::SetIterationRotation(angle); Actor::SetIterationRotation(angle);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
void RenderBase::SetPos(Vec2 pos) void RenderBase::SetPos(Vec2 pos)
{ {
Component::SetPos(pos); Actor::SetPos(pos);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
void RenderBase::SetScale(Vec2 scale) void RenderBase::SetScale(Vec2 scale)
{ {
Component::SetScale(scale); Actor::SetScale(scale);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
void RenderBase::SetRotation(float angle) void RenderBase::SetRotation(float angle)
{ {
Component::SetRotation(angle); Actor::SetRotation(angle);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }
void RenderBase::SetAnchor(Vec2 anchor) void RenderBase::SetAnchor(Vec2 anchor)
{ {
Component::SetAnchor(anchor); Actor::SetAnchor(anchor);
CalcRenderInfo(); // 更新渲染信息 CalcRenderInfo(); // 更新渲染信息
} }

View File

@@ -1,8 +1,7 @@
#pragma once #pragma once
#include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Component/Component.h" class RenderBase : public Actor
class RenderBase : public Component
{ {
public: public:
@@ -19,21 +18,11 @@ public:
bool Visible = true; bool Visible = true;
// 是否在屏幕内 // 是否在屏幕内
bool IsInScreen = false; bool IsInScreen = false;
//渲染矩阵
GlMatrix RenderMatrix;
}; };
public:
RenderBase(/* args */);
~RenderBase();
public: public:
void Init() override; void Init() override;
void Update(float deltaTime) override;
void Render() override;
public:
public: public:
// 设置迭代的坐标 // 设置迭代的坐标
void SetIterationPos(Vec2 pos) override; void SetIterationPos(Vec2 pos) override;

View File

@@ -43,35 +43,6 @@ RefPtr<Texture> Sprite::GetTexture()
return m_texture; return m_texture;
} }
GlMatrix Sprite::matrix3x2ToGLMatrix(const Matrix3x2 &mat)
{
return {
// 列0x轴线性变换
mat._11, // [0][0]
mat._12, // [1][0]
0.0f, // [2][0]
0.0f, // [3][0]
// 列1y轴线性变换
mat._21, // [0][1]
mat._22, // [1][1]
0.0f, // [2][1]
0.0f, // [3][1]
// 列2z轴固定
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() void Sprite::CalcRenderInfoLogic()
{ {
// 获取至在最终的父对象检查是否显示 // 获取至在最终的父对象检查是否显示
@@ -105,8 +76,8 @@ void Sprite::CalcRenderInfoLogic()
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上 // 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
auto T_Size = m_texture->getSize(); auto T_Size = m_texture->getSize();
auto T_Pos = m_texture->getPos(); auto T_Pos = m_texture->getPos();
float texturePosX = flipX ? -(T_Size.width + T_Pos.x) + SDL_abs(transform.position.x * 2) : T_Pos.x; float texturePosX = flipX ? -((float)T_Size.width + (float)T_Pos.x) + SDL_fabsf(transform.position.x * 2.0f) : (float)T_Pos.x;
float texturePosY = flipY ? -(T_Size.height + T_Pos.y) + SDL_abs(transform.position.y * 2) : T_Pos.y; float texturePosY = flipY ? -((float)T_Size.height + (float)T_Pos.y) + SDL_fabsf(transform.position.y * 2.0f) : (float)T_Pos.y;
// 先计算Img坐标与精灵坐标合成后的真实坐标 // 先计算Img坐标与精灵坐标合成后的真实坐标
float RealPosX = transform.position.x + texturePosX; float RealPosX = transform.position.x + texturePosX;
@@ -117,22 +88,22 @@ void Sprite::CalcRenderInfoLogic()
float baseY = transformIter.position.y + RealPosY; float baseY = transformIter.position.y + RealPosY;
// 获取当前帧的原始尺寸 // 获取当前帧的原始尺寸
int frameWidth = Size.width; float frameWidth = (float)Size.width;
int frameHeight = Size.height; float frameHeight = (float)Size.height;
// 原始锚点偏移(基于帧尺寸) // 原始锚点偏移(基于帧尺寸)
float origAnchorOffsetX = int(frameWidth * Anchor.x); float origAnchorOffsetX = frameWidth * Anchor.x;
float origAnchorOffsetY = int(frameHeight * Anchor.y); float origAnchorOffsetY = frameHeight * Anchor.y;
// 缩放的绝对值 // 缩放的绝对值
float absScaleX = SDL_fabs(scaleX); float absScaleX = SDL_fabsf(scaleX);
float absScaleY = SDL_fabs(scaleY); float absScaleY = SDL_fabsf(scaleY);
// 缩放后的尺寸 // 缩放后的尺寸
float scaledWidth = frameWidth * absScaleX; float scaledWidth = frameWidth * absScaleX;
float scaledHeight = frameHeight * absScaleY; float scaledHeight = frameHeight * absScaleY;
// 缩放后的锚点偏移 // 缩放后的锚点偏移
float scaledAnchorOffsetX = int(origAnchorOffsetX * absScaleX); float scaledAnchorOffsetX = origAnchorOffsetX * absScaleX;
float scaledAnchorOffsetY = int(origAnchorOffsetY * absScaleY); float scaledAnchorOffsetY = origAnchorOffsetY * absScaleY;
// 计算缩放后的锚点偏移与原锚点偏移的差值 // 计算缩放后的锚点偏移与原锚点偏移的差值
float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX; float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
@@ -142,9 +113,6 @@ void Sprite::CalcRenderInfoLogic()
float Xpos = baseX - scaleOffsetX; float Xpos = baseX - scaleOffsetX;
float Ypos = baseY - scaleOffsetY; float Ypos = baseY - scaleOffsetY;
Xpos = (int)Xpos; // 强制转换为整数
Ypos = (int)Ypos; // 强制转换为整数
// 更新渲染信息 // 更新渲染信息
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight}; _RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY}; _RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
@@ -152,8 +120,8 @@ void Sprite::CalcRenderInfoLogic()
m_texture->setAlpha(this->Alpha); m_texture->setAlpha(this->Alpha);
// 屏幕内检测 // 屏幕内检测
int screenWidth = Game::GetInstance().Screen_W; float screenWidth = (float)Game::GetInstance().Screen_W;
int screenHeight = Game::GetInstance().Screen_H; float screenHeight = (float)Game::GetInstance().Screen_H;
bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight); bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight);
_RenderGuidanceInfo.IsInScreen = isInScreen; _RenderGuidanceInfo.IsInScreen = isInScreen;

View File

@@ -33,10 +33,6 @@ public:
std::string imgPath; std::string imgPath;
int Index; int Index;
Matrix3x2 transform_matrix_;
GlMatrix matrix3x2ToGLMatrix(const Matrix3x2 &mat);
public: public:
// 计算渲染信息 // 计算渲染信息
void CalcRenderInfoLogic(); void CalcRenderInfoLogic();

View File

@@ -10,7 +10,7 @@ public:
~Text(); ~Text();
// 显式引入基类的Init方法避免隐藏 // 显式引入基类的Init方法避免隐藏
using Component::Init; using Actor::Init;
void Init(std::string Str, TTF_Font *font, SDL_Color color); void Init(std::string Str, TTF_Font *font, SDL_Color color);
void Render() override; void Render() override;

View File

@@ -28,7 +28,7 @@ RenderManager::RenderManager(SDL_Window *window)
_windowHeight = height; _windowHeight = height;
// 游戏的初始正交投影矩阵 // 游戏的初始正交投影矩阵
_GameOrthoMatrix = glm::ortho(0.0f, (float)width / 1.2f, (float)height / 1.2f, 0.0f, -1.0f, 1.0f); _GameOrthoMatrix = glm::ortho(0.0f, (float)width, (float)height, 0.0f, -1.0f, 1.0f);
// UI的初始正交投影矩阵 // UI的初始正交投影矩阵
_UIOrthoMatrix = glm::ortho(0.0f, (float)width, (float)height, 0.0f, -1.0f, 1.0f); _UIOrthoMatrix = glm::ortho(0.0f, (float)width, (float)height, 0.0f, -1.0f, 1.0f);
@@ -36,6 +36,7 @@ RenderManager::RenderManager(SDL_Window *window)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 启用混合模式 // 启用混合模式
glEnable(GL_BLEND); glEnable(GL_BLEND);
// 默认设置标准alpha混合 // 默认设置标准alpha混合
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -228,8 +229,8 @@ void RenderManager::Init2DTextureProgram()
glUniform1i(_currentRenderParams.UnimLocs[2], 0); glUniform1i(_currentRenderParams.UnimLocs[2], 0);
// 处理纹理裁剪 // 处理纹理裁剪
int texWidth = textureObj->getSize().width; float texWidth = (float)textureObj->getSize().width;
int texHeight = textureObj->getSize().height; float texHeight = (float)textureObj->getSize().height;
// 计算纹理坐标 // 计算纹理坐标
float minu, minv, maxu, maxv; float minu, minv, maxu, maxv;
@@ -336,6 +337,16 @@ void RenderManager::SetOrthoMatrixType(int type)
_OrthoMatrix = _UIOrthoMatrix; _OrthoMatrix = _UIOrthoMatrix;
} }
glm::mat4 RenderManager::GetOrthoMatrix()
{
return _OrthoMatrix;
}
void RenderManager::SetOrthoMatrix(glm::mat4 matrix)
{
_OrthoMatrix = matrix;
}
GLuint RenderManager::CompileShader(GLenum type, std::string Path) GLuint RenderManager::CompileShader(GLenum type, std::string Path)
{ {
std::ifstream Source("shader/" + Path); std::ifstream Source("shader/" + Path);

View File

@@ -78,6 +78,11 @@ public:
void DrawTexture(RefPtr<Texture> texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, void *userdata = nullptr); void DrawTexture(RefPtr<Texture> texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, void *userdata = nullptr);
// 设置正交投影矩阵类型 // 设置正交投影矩阵类型
void SetOrthoMatrixType(int type); void SetOrthoMatrixType(int type);
// 获取渲染的正交投影矩阵
glm::mat4 GetOrthoMatrix();
// 设置渲染的正交投影矩阵
void SetOrthoMatrix(glm::mat4 matrix);
private: private:

View File

@@ -32,8 +32,9 @@ bool Texture::Init(std::string PngPath)
glBindTexture(GL_TEXTURE_2D, m_TextureID); glBindTexture(GL_TEXTURE_2D, m_TextureID);
// 环绕方式 // 环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样 // 缩小过滤:使用最近邻采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 放大过滤:使用最近邻采样 // 放大过滤:使用最近邻采样
@@ -100,8 +101,9 @@ bool Texture::Init(std::string ImgPath, int Index)
// 设置纹理参数保持与原有SDL纹理相同的采样模式 // 设置纹理参数保持与原有SDL纹理相同的采样模式
// 环绕方式:重复 // 环绕方式:重复
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 过滤方式最近邻与SDL_ScaleModeNearest对应 // 过滤方式最近邻与SDL_ScaleModeNearest对应
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -139,8 +141,9 @@ bool Texture::Init(SDL_Surface *rgbaSurface)
glBindTexture(GL_TEXTURE_2D, m_TextureID); glBindTexture(GL_TEXTURE_2D, m_TextureID);
// 环绕方式 // 环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样 // 缩小过滤:使用最近邻采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 放大过滤:使用最近邻采样 // 放大过滤:使用最近邻采样
@@ -192,8 +195,9 @@ bool Texture::Init(VecSize size)
m_FrameSize = size; m_FrameSize = size;
// 环绕方式 // 环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样 // 缩小过滤:使用最近邻采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 放大过滤:使用最近邻采样 // 放大过滤:使用最近邻采样

View File

@@ -111,12 +111,41 @@ typedef struct VecPos3
} VecPos3; } VecPos3;
typedef struct VecFPos3
{
float x;
float y;
float z;
VecFPos3(float x_ = 0, float y_ = 0, float z_ = 0) : x(x_), y(y_), z(z_) {}
VecFPos3 operator+(const VecFPos3 &other) const
{
return VecFPos3(x + other.x, y + other.y, z + other.z);
}
VecFPos3 operator-(const VecFPos3 &other) const
{
return VecFPos3(x - other.x, y - other.y, z - other.z);
}
bool operator==(const VecFPos3 &other) const
{
return x == other.x && y == other.y && z == other.z;
}
bool operator!=(const VecFPos3 &other) const
{
return x != other.x || y != other.y || z != other.z;
}
} VecFPos3;
typedef struct VecSpeed3 typedef struct VecSpeed3
{ {
int x; float x;
int y; float y;
int z; float z;
VecSpeed3(int x_ = 0, int y_ = 0, int z_ = 0) : x(x_), y(y_), z(z_) {} VecSpeed3(float x_ = 0, float y_ = 0, float z_ = 0) : x(x_), y(y_), z(z_) {}
VecSpeed3 operator+(const VecSpeed3 &other) const VecSpeed3 operator+(const VecSpeed3 &other) const
{ {

View File

@@ -27,13 +27,13 @@
#include <math/EaseFunctions.h> #include <math/EaseFunctions.h>
#include <math/Scalar.h> #include <math/Scalar.h>
using Vec2 = ember::math::Vec2T<float>; using Vec2 = ember::math::Vec2T<float>;
using VecPos = ember::math::Vec2T<int>; using VecPos = ember::math::Vec2T<int>;
using Rect = ember::math::RectT<float>; using Rect = ember::math::RectT<float>;
using Matrix3x2 = ember::math::Matrix3x2T<float>; using Matrix3x2 = ember::math::Matrix3x2T<float>;
using Transform = ember::math::TransformT<float>; using Transform = ember::math::TransformT<float>;
using GlMatrix = std::array<float, 16>;
using Point = Vec2; using Point = Vec2;
using Size = Vec2; using Size = Vec2;

View File

@@ -20,8 +20,12 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <math/Rect.hpp> #include <math/Rect.hpp>
#include <math/Vec2.hpp> #include <math/Vec2.hpp>
#include <glm/glm.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace ember namespace ember
{ {
@@ -34,7 +38,7 @@ namespace ember
struct Matrix3x2T struct Matrix3x2T
{ {
using ValueType = _Ty; using ValueType = _Ty;
using Vec2Type = Vec2T<ValueType>; using Vec2Type = glm::vec2;
using RectType = RectT<ValueType>; using RectType = RectT<ValueType>;
union union
@@ -160,13 +164,13 @@ namespace ember
return RectType{left, top, right, bottom}; return RectType{left, top, right, bottom};
} }
inline void Translate(const Vec2Type &v) inline void Translate(const glm::vec2 &v)
{ {
_31 += _11 * v.x + _21 * v.y; _31 += _11 * v.x + _21 * v.y;
_32 += _12 * v.x + _22 * v.y; _32 += _12 * v.x + _22 * v.y;
} }
static inline Matrix3x2T Translation(const Vec2Type &v) static inline Matrix3x2T Translation(const glm::vec2 &v)
{ {
return Matrix3x2T(1.f, 0.f, 0.f, 1.f, v.x, v.y); return Matrix3x2T(1.f, 0.f, 0.f, 1.f, v.x, v.y);
} }

View File

@@ -1,10 +1,10 @@
#include "GameMap.h" #include "GameMap.h"
#include "Asset/AssetManager.h" #include "Asset/AssetManager.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Scene/Scene.h" #include "EngineFrame/Scene/Scene.h"
#include "EngineFrame/Component/Animation.h" #include "EngineFrame/Component/Animation.h"
#include "Actor/Map/GameMapCamera.h" #include "Global/Global_Game.h"
#include "Actor/Object/CharacterObject.h" #include "Actor/Object/CharacterObject.h"
#include "EngineCore/Game.h"
GameMap::GameMap() GameMap::GameMap()
{ {
@@ -217,34 +217,21 @@ void GameMap::InitTile()
{ {
NormalTileCount = tileArr.size(); NormalTileCount = tileArr.size();
_MapLength = NormalTileCount * 224; _MapLength = NormalTileCount * 224;
for (int i = 0; i < NormalTileCount; i++)
{
std::string path = tileArr[i];
RefPtr<Tile> tile = new Tile(path);
tile->SetPos(Vec2{i * 224, -200 - std::get<int>(_MapInfo["background_pos"])});
_LayerMap["bottom"]->AddComponent(tile);
}
_MapHeight = 560; _MapHeight = 560;
} }
if (_MapInfo.count("extended_tile")) if (!_MapInfo.count("extended_tile"))
{ return;
std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]); std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
if (extileArr.size() > 0) if (extileArr.size() > 0)
{ {
int ExTileCount = extileArr.size(); int ExTileCount = extileArr.size();
int Buffer = (ExTileCount / NormalTileCount); int Buffer = (ExTileCount / NormalTileCount);
_MapHeight += (Buffer < 1 ? 1 : Buffer) * 40; _MapHeight += (Buffer < 1 ? 1 : Buffer) * 40;
for (int i = 0; i < ExTileCount; i++)
{
std::string path = extileArr[i];
RefPtr<Tile> tile = new Tile(path);
int xbuf = i % NormalTileCount * 224;
int ybuf = -200 - std::get<int>(_MapInfo["background_pos"]) + NormalTileHeight + 120 * (i / NormalTileCount);
tile->SetPos(Vec2{xbuf, ybuf});
_LayerMap["bottom"]->AddComponent(tile);
}
}
} }
_Tile = new Tile(this, tileArr, extileArr);
_LayerMap["bottom"]->AddChild(_Tile);
} }
void GameMap::InitBackgroundAnimation() void GameMap::InitBackgroundAnimation()
@@ -340,45 +327,42 @@ void GameMap::LoadMap(std::string mapName)
void GameMap::Enter(Scene *scene) void GameMap::Enter(Scene *scene)
{ {
_Scene = scene; AddChild(_LayerMap["contact"]);
scene->AddChild(_LayerMap["contact"]); AddChild(_LayerMap["distantback"]);
scene->AddChild(_LayerMap["distantback"]); AddChild(_LayerMap["middleback"]);
scene->AddChild(_LayerMap["middleback"]); AddChild(_LayerMap["bottom"]);
scene->AddChild(_LayerMap["bottom"]); AddChild(_LayerMap["closeback"]);
scene->AddChild(_LayerMap["closeback"]); AddChild(_LayerMap["normal"]);
scene->AddChild(_LayerMap["normal"]); AddChild(_LayerMap["close"]);
scene->AddChild(_LayerMap["close"]); AddChild(_LayerMap["cover"]);
scene->AddChild(_LayerMap["cover"]); AddChild(_LayerMap["max"]);
scene->AddChild(_LayerMap["max"]);
}
void GameMap::HandleEvents(SDL_Event *e)
{
} }
void GameMap::Update(float deltaTime) void GameMap::Update(float deltaTime)
{ {
if (_Scene->GetCamera() == nullptr) Actor::Update(deltaTime);
RefPtr<GameCamera> Cam = Global_Game::GetInstance().GetCamera();
if (Cam == nullptr)
return; return;
GameMapCamera *Cam = (GameMapCamera *)(_Scene->GetCamera().Get()); float targetX = Cam->_currentPosition.x;
int targetX = Cam->_currentPosition.x; float targetY = Cam->_currentPosition.y;
int targetY = Cam->_currentPosition.y;
// 屏幕中心 // 屏幕中心
int width_Separate = 1067 / 2; float width_Separate = 1280.0f / 1.2f / 2.0f;
int height_Separate = 600 / 2; float height_Separate = 600.0f / 2.0f;
// 获取摄像机可行区域限制 // 获取摄像机可行区域限制
auto limitIt = _MapInfo.find("limit_map_camera_move"); auto limitIt = _MapInfo.find("limit_map_camera_move");
if (limitIt != _MapInfo.end()) if (limitIt != _MapInfo.end())
{ {
std::vector<int> limit = std::get<std::vector<int>>(_MapInfo["limit_map_camera_move"]); std::vector<int> limit = std::get<std::vector<int>>(_MapInfo["limit_map_camera_move"]);
int X_Limit_Min = limit[0]; float X_Limit_Min = limit[0];
int X_Limit_Max = limit[1]; float X_Limit_Max = limit[1];
int Y_Limit_Min = limit[2]; float Y_Limit_Min = limit[2];
int Y_Limit_Max = limit[3]; float Y_Limit_Max = limit[3];
// 应用地图边界限制 // 应用地图边界限制
targetX = std::clamp(targetX, width_Separate, _MapLength - width_Separate); targetX = std::clamp(targetX, width_Separate, (float)_MapLength - width_Separate);
targetY = std::clamp(targetY, height_Separate, _MapHeight - height_Separate); targetY = std::clamp(targetY, height_Separate, (float)_MapHeight - height_Separate);
// 应用自定义摄像机移动限制 // 应用自定义摄像机移动限制
if (X_Limit_Min != -1) if (X_Limit_Min != -1)
targetX = std::max(targetX, X_Limit_Min); targetX = std::max(targetX, X_Limit_Min);
@@ -393,12 +377,12 @@ void GameMap::Update(float deltaTime)
// 更新图层位置 // 更新图层位置
for (auto &Layer : _LayerMap) for (auto &Layer : _LayerMap)
{ {
int posX = -targetX + width_Separate; float posX = -targetX + width_Separate;
int posY = -targetY + height_Separate + MapOffsetY; float posY = -targetY + height_Separate + MapOffsetY;
if (Layer.first == "distantback") if (Layer.first == "distantback")
{ {
posX *= BackgroundMoveSpeed; posX *= BackgroundMoveSpeed;
posX /= 100; posX /= 100.0f;
} }
Layer.second->SetPos(Vec2(posX, posY)); Layer.second->SetPos(Vec2(posX, posY));
} }
@@ -412,14 +396,17 @@ void GameMap::AddObject(RefPtr<BaseObject> object)
if (object->m_objecttype == ObjectType::CHARACTER) if (object->m_objecttype == ObjectType::CHARACTER)
{ {
CharacterObject *chr = (CharacterObject *)(object.Get()); CharacterObject *chr = (CharacterObject *)(object.Get());
if( chr->_Shadow != nullptr)_LayerMap["bottom"]->AddComponent(chr->_Shadow); Global_Game::GetInstance().GetCamera()->SetFromActor(chr);
if (chr->_Shadow)
_LayerMap["bottom"]->AddChild(chr->_Shadow);
} }
} }
VecPos3 GameMap::CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset) VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset)
{ {
// 初始化结果为原坐标(默认不移动) // 初始化结果为原坐标(默认不移动)
VecPos3 result = CurPos; VecFPos3 result = CurPos;
// 如果没有可移动区域限制,直接全量位移 // 如果没有可移动区域限制,直接全量位移
if (_MovableArea.empty()) if (_MovableArea.empty())

View File

@@ -8,7 +8,7 @@
class BaseObject; class BaseObject;
class GameMapCamera; class GameMapCamera;
class GameMap class GameMap : public Actor
{ {
struct BackGroundAni struct BackGroundAni
{ {
@@ -58,6 +58,8 @@ public:
std::string _MapPath; std::string _MapPath;
// 地图文件夹 // 地图文件夹
std::string _MapDir; std::string _MapDir;
// 地板画布
RefPtr<Tile> _Tile = nullptr;
// 地图宽度 // 地图宽度
int _MapLength = 0; int _MapLength = 0;
// 地图高度 // 地图高度
@@ -70,8 +72,6 @@ public:
public: public:
// 图层Map 图层类型 显示对象 // 图层Map 图层类型 显示对象
std::unordered_map<std::string, RefPtr<GameMapLayer>> _LayerMap; std::unordered_map<std::string, RefPtr<GameMapLayer>> _LayerMap;
// 所属场景
Scene *_Scene = nullptr;
// 背景层移动速率 // 背景层移动速率
int BackgroundMoveSpeed = 103; int BackgroundMoveSpeed = 103;
@@ -88,11 +88,10 @@ public:
void InitMapAnimation(); void InitMapAnimation();
void InitVirtualMovableArea(); void InitVirtualMovableArea();
void Enter(Scene *scene); void Enter(Scene *scene);
void HandleEvents(SDL_Event *e); void Update(float deltaTime) override;
void Update(float deltaTime);
void AddObject(RefPtr<BaseObject> object); void AddObject(RefPtr<BaseObject> object);
public: public:
// 检查是否可移动 // 检查是否可移动
VecPos3 CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset); VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset);
}; };

View File

@@ -1,41 +0,0 @@
#pragma once
#include "EngineFrame/Actor/Actor.h"
class GameMap;
class BaseObject;
class GameMapCamera : public Actor
{
private:
// 跟随对象
BaseObject *_FromActor = nullptr;
public:
// 摄像机记录的跟随对象坐标
VecPos3 FromActorPos = {0, 0, 0};
// 缩放比率
float CameraRate = 1.0;
// 添加平滑移动相关的成员变量
bool _isSmoothMoving = false;
VecPos _currentPosition; // 当前摄像机位置
VecPos _velocity; // 当前移动速度(用于平滑移动)
float _smoothTime = 0.1f; // 平滑时间(秒),可调整
int _maxSpeed = 2000; // 最大移动速度,防止过快
public:
GameMapCamera();
~GameMapCamera();
void SetFromActor(BaseObject *actor);
void Update(float deltaTime);
void SetPos(int x, int y, int z);
void AddPos(int x, int y, int z);
//同步坐标相关
void SyncPos(float deltaTime);
void SyncPosByFromParent(float deltaTime);
// 平滑阻尼函数类似Unity的Mathf.SmoothDamp
VecPos SmoothDamp(const VecPos &current, const VecPos &target, VecPos &currentVelocity, float smoothTime, int maxSpeed, float deltaTime);
};

View File

@@ -1,31 +1,25 @@
#include "GameMapLayer.h" #include "GameMapLayer.h"
#include "EngineCore/Game.h" #include "EngineCore/Game.h"
GameMapLayer::GameMapLayer()
{
}
GameMapLayer::~GameMapLayer()
{
}
void GameMapLayer::Render() void GameMapLayer::Render()
{ {
Actor::Render();
RenderManager *renderer = Game::GetInstance().GetRenderer();
// 自身坐标 Actor::Render();
float Xpos = GetIterationPos().x + GetPos().x; // RenderManager *renderer = Game::GetInstance().GetRenderer();
float Ypos = GetIterationPos().y + GetPos().y;
for (auto &info : this->FeasibleAreaInfoList) // // 自身坐标
{ // float Xpos = GetIterationPos().x + GetPos().x;
SDL_Rect buf; // float Ypos = GetIterationPos().y + GetPos().y;
buf.x = info.x + Xpos; // for (auto &info : this->FeasibleAreaInfoList)
buf.y = info.y + Ypos; // {
buf.w = info.w; // SDL_Rect buf;
buf.h = info.h; // buf.x = info.x + Xpos;
//TODO: 渲染可行区域 // buf.y = info.y + Ypos;
} // buf.w = info.w;
// buf.h = info.h;
// //TODO: 渲染可行区域
// }
} }
void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size) void GameMapLayer::AddDebugFeasibleAreaInfo(Vec2 pos, VecSize size)

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Component/Sprite.h"
class BaseObject; class BaseObject;
@@ -11,9 +11,6 @@ private:
std::vector<SDL_Rect> FeasibleAreaInfoList; std::vector<SDL_Rect> FeasibleAreaInfoList;
public: public:
GameMapLayer(/* args */);
~GameMapLayer();
// 重载Render以实现绘制可行区域 // 重载Render以实现绘制可行区域
void Render() override; void Render() override;
// 添加调试可行区域信息 // 添加调试可行区域信息

View File

@@ -1,33 +1,137 @@
#include "Tile.h" #include "Tile.h"
#include "Tool/Tool_String.h" #include "Tool/Tool_String.h"
#include "EngineCore/Game.h" #include "EngineCore/Game.h"
Tile::Tile() #include "Actor/Map/GameMap.h"
{ #include "Global/Global_Game.h"
}
Tile::Tile(std::string Path) : Sprite() // Tile::Tile(std::string Path) : Sprite()
{ // {
InitInfo(Path); // InitInfo(Path);
if (std::get<std::string>(m_data["path"]) == "") // if (std::get<std::string>(m_data["path"]) == "")
m_data["path"] = "sprite/character/common/circlecooltime.img"; // m_data["path"] = "sprite/character/common/circlecooltime.img";
// m_texture = new Texture();
// m_texture->Init(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
// Sprite::Init();
// this->imgPath = Path;
// }
Tile::Tile(GameMap *parentMap, std::vector<std::string> normal, std::vector<std::string> ex)
{
m_parentMap = parentMap;
m_texture = new Texture(); m_texture = new Texture();
m_texture->Init(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
Sprite::Init(); // 通过父对象获取地图大小
this->imgPath = Path; int Width = m_parentMap->_MapLength;
int Height = m_parentMap->_MapHeight;
// 通过大小纹理大小
m_texture->Init(VecSize(Width, Height));
m_rect = {0, 0, (float)Width, (float)Height};
Actor::Init();
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 将目标纹理附加到FBO的颜色附着点
glFramebufferTexture2D(
GL_FRAMEBUFFER, // 帧缓冲类型
GL_COLOR_ATTACHMENT0, // 颜色附着点(可多个,这里用第一个)
GL_TEXTURE_2D, // 纹理类型
m_texture->getID(), // 目标纹理ID
0 // 多级渐远纹理级别
);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
for (size_t i = 0; i < normal.size(); i++)
{
InitTile(normal[i], i);
}
m_tileX = normal.size();
for (size_t i = 0; i < ex.size(); i++)
{
InitExTile(ex[i], i);
}
SetPos(Vec2(0, 80 - 200 - std::get<int>(m_parentMap->_MapInfo["background_pos"])));
} }
Tile::~Tile() Tile::~Tile()
{ {
} }
void Tile::SetPos(Vec2 pos) void Tile::InitTile(std::string Path, int Index)
{ {
pos.y += std::get<int>(m_data["pos"]); // 读取文件
Sprite::SetPos(pos); TileInfo data;
InitInfo(Path, data);
// 读取信息
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
if (path == "")
path = "sprite/character/common/circlecooltime.img";
// 构造纹理标识符
ImgKey key = {path, index};
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
DrawInfo info;
info.rect.x = Index * m_imgMap[key]->getSize().width + m_imgMap[key]->getPos().x;
info.rect.y = m_imgMap[key]->getPos().y;
info.rect.w = m_imgMap[key]->getSize().width;
info.rect.h = m_imgMap[key]->getSize().height;
info.texture = key;
// 添加到绘制信息列表
m_drawQueue.push_back(info);
} }
void Tile::InitInfo(std::string Path) void Tile::InitExTile(std::string Path, int Index)
{
// 读取文件
TileInfo data;
InitInfo(Path, data);
// 读取信息
std::string path = std::get<std::string>(data["path"]);
int index = std::get<int>(data["idx"]);
// 如果是个空地板 给他默认赋值
if (path == "")
path = "sprite/character/common/circlecooltime.img";
// 构造纹理标识符
ImgKey key = {path, index};
// 判断是否存在标识符对应的纹理,如果不存在则创建
if (m_imgMap.find(key) == m_imgMap.end())
{
RefPtr<Texture> tex = new Texture();
tex->Init(path, index);
m_imgMap[key] = tex;
}
// 构造绘制信息
DrawInfo info;
info.rect.x = Index * m_imgMap[key]->getSize().width + m_imgMap[key]->getPos().x;
info.rect.y = m_imgMap[key]->getPos().y + 560 + ((Index / m_tileX) * 120);
info.rect.w = m_imgMap[key]->getSize().width;
info.rect.h = m_imgMap[key]->getSize().height;
info.texture = key;
// 添加到绘制信息列表
m_drawQueue.push_back(info);
}
// void Tile::SetPos(Vec2 pos)
// {
// // pos.y += std::get<int>(m_data["pos"]);
// // Sprite::SetPos(pos);
// }
void Tile::InitInfo(std::string Path, TileInfo &m_data)
{ {
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(Path); ScriptData Data = AssetManager::GetInstance().GetScriptInfo(Path);
m_data["pos"] = 0; m_data["pos"] = 0;
@@ -46,3 +150,47 @@ void Tile::InitInfo(std::string Path)
} }
} }
} }
void Tile::PreRender()
{
m_rect.x = GetWorldPos().x;
m_rect.y = GetWorldPos().y;
//计算摄像机位置 知道自己需要渲染多大的区域
// m_srcRect = {0, 0, m_parentMap->_MapLength, m_parentMap->_MapHeight};
// Vec2 Pos = Global_Game::GetInstance().GetCamera() -> _currentPosition;
// m_srcRect = {Pos.x < 1067 ? 0 : Pos.x - 1067, Pos.y, 1067, 600};
}
void Tile::Render()
{
RenderManager *renderer = Game::GetInstance().GetRenderer();
SDL_FPoint AnchorPos = {0, 0};
if (!m_isBuild)
{
// 保存原始的正交矩阵 设置纹理对应的正交矩阵 和 视口
auto oldOm = Game::GetInstance().GetRenderer()->GetOrthoMatrix();
Game::GetInstance().GetRenderer()->SetOrthoMatrix(glm::ortho(0.0f, (float)m_texture->getSize().width, (float)m_texture->getSize().height, 0.0f, -1.0f, 1.0f));
glViewport(0, 0, m_texture->getSize().width, m_texture->getSize().height);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for (auto &info : m_drawQueue)
{
renderer->DrawTexture(m_imgMap[info.texture], nullptr, &info.rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
// 还原原始的正交矩阵 和 视口
Game::GetInstance().GetRenderer()->SetOrthoMatrix(oldOm);
glViewport(0, 0, Game::GetInstance().Screen_W, Game::GetInstance().Screen_H);
m_isBuild = true;
}
renderer->SetCurrentShaderProgram("flip_y");
renderer->DrawTexture(m_texture, nullptr, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
renderer->SetCurrentShaderProgram("normal");
}

View File

@@ -1,22 +1,65 @@
#pragma once #pragma once
#include "Asset/AssetManager.h" #include "Asset/AssetManager.h"
#include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Component/Canvas.h"
class Tile : public Sprite class GameMap;
class Tile : public Actor
{ {
struct ImgKey
{
std::string img;
int index;
using TileInfoBody = std::variant< bool operator<(const ImgKey &other) const
int, {
std::string>; if (img != other.img)
{
private: return img < other.img; // 字符串按字典序比较
std::unordered_map<std::string, TileInfoBody> m_data; }
return index < other.index; // 字符串相同则比较index
}
};
struct DrawInfo
{
ImgKey texture;
SDL_FRect rect = {0, 0, 0, 0};
};
public: public:
Tile(/* args */); using TileInfoBody = std::variant<int,std::string>;
Tile(std::string Path); using TileInfo = std::unordered_map<std::string, TileInfoBody>;
private:
/**纹理 */
RefPtr<Texture> m_texture = nullptr;
/**FBO */
GLuint m_fbo = 0;
/**地图父对象 */
GameMap* m_parentMap;
/**绘制纹理集 */
std::map<ImgKey, RefPtr<Texture>> m_imgMap;
/**绘制队列 */
std::vector<DrawInfo> m_drawQueue;
/**渲染大小 */
SDL_Rect m_srcRect;
SDL_FRect m_rect;
/**大纹理构造完成Flag */
bool m_isBuild = false;
/**Tile横轴个数 */
int m_tileX = 0;
public:
Tile(GameMap *parentMap, std::vector<std::string> normal,std::vector<std::string> ex);
~Tile(); ~Tile();
void SetPos(Vec2 pos) override; void InitTile(std::string Path,int Index);
void InitExTile(std::string Path, int Index);
void InitInfo(std::string Path, TileInfo &m_data);
void InitInfo(std::string Path); void PreRender() override;
void Render() override;
// void SetPos(Vec2 pos) override;
}; };

View File

@@ -1,5 +1,5 @@
#include "ActiveObject.h" #include "ActiveObject.h"
void ActiveObject::SetPosition(VecPos3 pos) void ActiveObject::SetPosition(VecFPos3 pos)
{ {
BaseObject::SetPosition(pos); BaseObject::SetPosition(pos);
} }
@@ -21,49 +21,36 @@ VecSpeed3 ActiveObject::GetSpeed()
void ActiveObject::Update(float deltaTime) void ActiveObject::Update(float deltaTime)
{ {
int IntegerDelta = static_cast<int>(deltaTime * 1000);
const int Gravity = 1020;
VecFPos3 MovePos;
// X轴移动含余数补偿 // X轴移动含余数补偿
if (Speed.x != 0) if (Speed.x != 0)
{ {
int totalX = Speed.x * IntegerDelta + Remainder.x; // 加上上次余数 MovePos.x = Speed.x * deltaTime;
int moveX = totalX / 1000; // 整数部分为实际移动
Remainder.x = totalX % 1000; // 保留余数(-999~999
MoveBy(moveX, 0, 0);
} }
// Y轴移动同上 // Y轴移动同上
if (Speed.y != 0) if (Speed.y != 0)
{ {
int totalY = Speed.y * IntegerDelta + Remainder.y; MovePos.y = Speed.y * deltaTime;
int moveY = totalY / 1000;
Remainder.y = totalY % 1000;
MoveBy(0, moveY, 0);
} }
// Z轴重力与移动含余数补偿 // Z轴重力与移动含余数补偿
if (Position.z > 0 || Speed.z > 0) if (Position.z > 0 || Speed.z > 0)
{ {
// 重力对速度的影响先更新Speed.z含余数 int speedZTotal = -1020 * deltaTime;
int speedZTotal = -Gravity * IntegerDelta + Remainder.z; // 注意负号(减速)
Speed.z += speedZTotal / 1000; // 速度的整数部分
Remainder.z = speedZTotal % 1000; // 速度的余数
// 基于更新后的Speed.z计算移动量同样含余数 // 基于更新后的Speed.z计算移动量同样含余数
int moveZTotal = Speed.z * IntegerDelta + _zRemainderMove; // 新增_zRemainderMove记录移动余数 MovePos.z = Speed.z * deltaTime;
int moveZ = moveZTotal / 1000;
_zRemainderMove = moveZTotal % 1000;
MoveBy(0, 0, moveZ);
} }
else if (Position.z < 0) else if (Position.z < 0)
{ {
Position.z = 0; Position.z = 0;
Speed.z = 0; Speed.z = 0;
Remainder.z = 0; // 重置余数
_zRemainderMove = 0;
SetPosition(Position); SetPosition(Position);
} }
MoveBy(MovePos);
BaseObject::Update(deltaTime); BaseObject::Update(deltaTime);
} }

View File

@@ -7,13 +7,12 @@ class ActiveObject : public BaseObject
public: public:
// 三轴速度 // 三轴速度
VecSpeed3 Speed; VecSpeed3 Speed;
// 三轴移动余数
VecPos3 Remainder;
int _zRemainderMove = 0; int _zRemainderMove = 0;
public: public:
void void
SetPosition(VecPos3 pos) override; SetPosition(VecFPos3 pos) override;
void SetYpos(int y) override; void SetYpos(int y) override;
void SetSpeed(VecSpeed3 speed); void SetSpeed(VecSpeed3 speed);

View File

@@ -1,6 +1,5 @@
#include "BaseObject.h" #include "BaseObject.h"
#include "Actor/Map/GameMap.h" #include "Actor/Map/GameMap.h"
#include "Actor/Map/GameMapCamera.h"
BaseObject::BaseObject() BaseObject::BaseObject()
{ {
@@ -14,15 +13,13 @@ BaseObject::~BaseObject()
void BaseObject::Update(float deltaTime) void BaseObject::Update(float deltaTime)
{ {
if (_AffCamera != nullptr)
{
_AffCamera->SyncPos(deltaTime);
}
Actor::Update(deltaTime); Actor::Update(deltaTime);
} }
void BaseObject::SetPosition(VecPos3 pos) void BaseObject::SetPosition(VecFPos3 pos)
{ {
if(pos == this->Position)
return;
if (pos.y != this->Position.y) if (pos.y != this->Position.y)
{ {
SetRenderZOrder(pos.y); // 设置渲染顺序 SetRenderZOrder(pos.y); // 设置渲染顺序
@@ -31,19 +28,23 @@ void BaseObject::SetPosition(VecPos3 pos)
SetPos(Vec2{this->Position.x, this->Position.y - this->Position.z}); SetPos(Vec2{this->Position.x, this->Position.y - this->Position.z});
} }
VecPos3 BaseObject::GetPosition() VecFPos3 BaseObject::GetPosition()
{ {
return this->Position; return this->Position;
} }
void BaseObject::SetXpos(int x) void BaseObject::SetXpos(int x)
{ {
if (x == this->Position.x)
return;
this->Position.x = x; this->Position.x = x;
SetPos({this->Position.x, this->Position.y - this->Position.z}); SetPos({this->Position.x, this->Position.y - this->Position.z});
} }
void BaseObject::SetYpos(int y) void BaseObject::SetYpos(int y)
{ {
if (y == this->Position.y)
return;
if (y != this->Position.y) if (y != this->Position.y)
{ {
SetRenderZOrder(y); // 设置渲染顺序 SetRenderZOrder(y); // 设置渲染顺序
@@ -54,6 +55,8 @@ void BaseObject::SetYpos(int y)
void BaseObject::SetZpos(int z) void BaseObject::SetZpos(int z)
{ {
if (z == this->Position.z)
return;
this->Position.z = z; this->Position.z = z;
SetPos({this->Position.x, this->Position.y - this->Position.z}); SetPos({this->Position.x, this->Position.y - this->Position.z});
} }
@@ -73,10 +76,12 @@ int BaseObject::GetZpos()
return this->Position.z; return this->Position.z;
} }
void BaseObject::MoveBy(VecPos3 pos) void BaseObject::MoveBy(VecFPos3 pos)
{ {
// 只有moveby移动时判断所在地图中是否能够这样移动 // 只有moveby移动时判断所在地图中是否能够这样移动
VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos); VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos);
if (RealPos == this->Position)
return;
if (RealPos.y != this->Position.y) if (RealPos.y != this->Position.y)
{ {
SetRenderZOrder(RealPos.y); // 设置渲染顺序 SetRenderZOrder(RealPos.y); // 设置渲染顺序
@@ -90,7 +95,9 @@ void BaseObject::MoveBy(VecPos3 pos)
void BaseObject::MoveBy(int x, int y, int z) void BaseObject::MoveBy(int x, int y, int z)
{ {
// 只有moveby移动时判断所在地图中是否能够这样移动 // 只有moveby移动时判断所在地图中是否能够这样移动
VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecPos3({x, y, z})); VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecFPos3({x, y, z}));
if (RealPos == this->Position)
return;
if (RealPos.y != this->Position.y) if (RealPos.y != this->Position.y)
{ {
SetRenderZOrder(RealPos.y); // 设置渲染顺序 SetRenderZOrder(RealPos.y); // 设置渲染顺序

View File

@@ -1,18 +1,16 @@
#pragma once #pragma once
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
#include "Asset/Common/ObjectVars.h" #include "Asset/Common/ObjectVars.h"
#include "Global/Global_Enum.h" #include "Global/Global_Enum.h"
class GameMap; class GameMap;
class GameMapCamera;
class BaseObject : public Actor class BaseObject : public Actor
{ {
public: public:
public: public:
ObjectType m_objecttype; // 对象类型 ObjectType m_objecttype; // 对象类型
VecPos3 Position; // 位置 VecFPos3 Position; // 位置
int Direction = 0; // 方向 int Direction = 0; // 方向
GameMap *_AffMap = nullptr; // 所在地图 GameMap *_AffMap = nullptr; // 所在地图
GameMapCamera *_AffCamera = nullptr; // 跟随相机
public: public:
BaseObject(/* args */); BaseObject(/* args */);
@@ -24,17 +22,17 @@ public:
ObjectVars _ObjectVars; ObjectVars _ObjectVars;
public: public:
virtual void SetPosition(VecPos3 pos); virtual void SetPosition(VecFPos3 pos);
virtual void SetXpos(int x); virtual void SetXpos(int x);
virtual void SetYpos(int y); virtual void SetYpos(int y);
virtual void SetZpos(int z); virtual void SetZpos(int z);
VecPos3 GetPosition(); VecFPos3 GetPosition();
int GetXpos(); int GetXpos();
int GetYpos(); int GetYpos();
int GetZpos(); int GetZpos();
virtual void MoveBy(VecPos3 pos); virtual void MoveBy(VecFPos3 pos);
virtual void MoveBy(int x, int y, int z); virtual void MoveBy(int x, int y, int z);
virtual void SetDirection(int dir); virtual void SetDirection(int dir);

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include "EngineFrame/Component/Component.h"
#include "Asset/Common/Equipment.h" #include "Asset/Common/Equipment.h"
#include "EngineFrame/Base/Actor.h"
class CharacterObject; class CharacterObject;
class Chr_Equipment : public Component class Chr_Equipment : public Actor
{ {
public: public:
// 默认装备 // 默认装备

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include "EngineFrame/Component/Component.h"
#include "Global/Global_Enum.h" #include "Global/Global_Enum.h"
#include "EngineFrame/Base/Actor.h"
class CharacterObject; class CharacterObject;
class Chr_StateMachine : public Component class Chr_StateMachine : public Actor
{ {
private: private:
// 父对象 // 父对象

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "EngineFrame/Component/Component.h"
#include "Global/Global_Enum.h" #include "Global/Global_Enum.h"
class Equipment : public Component #include "EngineFrame/Base/Actor.h"
class Equipment : public Actor
{ {
public: public:
// 职业动画结构体 // 职业动画结构体

View File

@@ -15,7 +15,7 @@ static SQInteger SQR_GetPosition(HSQUIRRELVM v)
SQUserPointer ptr; SQUserPointer ptr;
sq_getuserpointer(v, 2, &ptr); sq_getuserpointer(v, 2, &ptr);
BaseObject *obj = (BaseObject *)ptr; BaseObject *obj = (BaseObject *)ptr;
VecPos3 Pos = obj->GetPosition(); VecFPos3 Pos = obj->GetPosition();
sq_newtable(v); sq_newtable(v);
sq_pushstring(v, _SC("x"), -1); sq_pushstring(v, _SC("x"), -1);
@@ -40,7 +40,7 @@ static SQInteger SQR_SetPosition(HSQUIRRELVM v)
sq_getfloat(v, 3, &PosX); sq_getfloat(v, 3, &PosX);
sq_getfloat(v, 4, &PosY); sq_getfloat(v, 4, &PosY);
sq_getfloat(v, 5, &PosZ); sq_getfloat(v, 5, &PosZ);
obj->SetPosition(VecPos3(PosX, PosY, PosZ)); obj->SetPosition(VecFPos3(PosX, PosY, PosZ));
return 0; return 0;
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "squirrel/SquirrelEx.h" #include "squirrel/SquirrelEx.h"
#include "Global/Global_Game.h" #include "Global/Global_Game.h"
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Base/Actor.h"
static SQRESULT sq_GetVecSize(HSQUIRRELVM v, int Index, VecSize *Size) static SQRESULT sq_GetVecSize(HSQUIRRELVM v, int Index, VecSize *Size)
{ {

View File

@@ -1,59 +1,58 @@
#include "GameMapCamera.h" #include "GameCamera.h"
#include "EngineCore/Game.h" #include "EngineCore/Game.h"
#include "Actor/Map/GameMap.h" #include "Actor/Map/GameMap.h"
#include "Actor/Object/BaseObject.h" #include "Actor/Object/BaseObject.h"
#include "Global/Global_Game.h"
#include <algorithm> #include <algorithm>
GameMapCamera::GameMapCamera() void GameCamera::SetFromActor(BaseObject *actor)
{
}
GameMapCamera::~GameMapCamera()
{
}
void GameMapCamera::SetFromActor(BaseObject *actor)
{ {
// 如果原来有跟随对象
if (this->_FromActor)
{
this->_FromActor->RemoveCallbackOnUpdate("Camear Update");
}
this->_FromActor = actor; this->_FromActor = actor;
_FromActor->_AffCamera = this; actor->SetCallbackOnUpdate("Camear Update", [](float deltaTime) mutable
{ Global_Game::GetInstance().GetCamera()->Update(deltaTime); });
} }
void GameMapCamera::Update(float deltaTime) void GameCamera::Update(float deltaTime)
{ {
SyncPosByFromParent(deltaTime); SyncPosByFromParent(deltaTime);
} }
void GameMapCamera::SyncPos(float deltaTime) void GameCamera::SyncPos(float deltaTime)
{ {
} }
void GameMapCamera::SetPos(int x, int y, int z) void GameCamera::SetPos(float x, float y, float z)
{ {
// this->X = x; // this->X = x;
// this->Y = y; // this->Y = y;
// this->Z = z; // this->Z = z;
} }
void GameMapCamera::AddPos(int x, int y, int z) void GameCamera::AddPos(float x, float y, float z)
{ {
// this->X += x; // this->X += x;
// this->Y += y; // this->Y += y;
// this->Z += z; // this->Z += z;
} }
void GameMapCamera::SyncPosByFromParent(float deltaTime) void GameCamera::SyncPosByFromParent(float deltaTime)
{ {
if (this->_FromActor == nullptr) if (this->_FromActor == nullptr)
{ {
return; return;
} }
int targetX = _FromActor->Position.x; float targetX = _FromActor->Position.x;
int targetY = _FromActor->Position.y; float targetY = _FromActor->Position.y;
if (_isSmoothMoving) if (_isSmoothMoving)
{ {
// 平滑移动计算 // 平滑移动计算
VecPos targetPosition(targetX, targetY); Vec2 targetPosition(targetX, targetY);
_currentPosition = SmoothDamp(_currentPosition, targetPosition, _velocity, _smoothTime, _maxSpeed, deltaTime); _currentPosition = SmoothDamp(_currentPosition, targetPosition, _velocity, _smoothTime, _maxSpeed, deltaTime);
} }
else else
@@ -63,12 +62,12 @@ void GameMapCamera::SyncPosByFromParent(float deltaTime)
} }
} }
VecPos GameMapCamera::SmoothDamp(const VecPos &current, const VecPos &target, VecPos &currentVelocity, float smoothTime, int maxSpeed, float deltaTime) Vec2 GameCamera::SmoothDamp(const Vec2 &current, const Vec2 &target, Vec2 &currentVelocity, float smoothTime, float maxSpeed, float deltaTime)
{ {
// 平滑时间为0时直接返回目标位置并重置速度 // 平滑时间为0时直接返回目标位置并重置速度
if (smoothTime <= 0.f) if (smoothTime <= 0.f)
{ {
currentVelocity = VecPos(0, 0); currentVelocity = Vec2(0, 0);
return target; return target;
} }
@@ -78,49 +77,43 @@ VecPos GameMapCamera::SmoothDamp(const VecPos &current, const VecPos &target, Ve
const float expTerm = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x); const float expTerm = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x);
// 计算当前位置与目标的差值 // 计算当前位置与目标的差值
VecPos delta = target - current; Vec2 delta = target - current;
// 计算目标速度(基于阻尼公式和当前差值) // 计算目标速度(基于阻尼公式和当前差值)
// 注意:这里先通过浮点计算保持精度,最后转换为整数 // 注意:这里先通过浮点计算保持精度,最后转换为整数
const float tx = delta.x * (omega * omega * deltaTime) - currentVelocity.x * (1.0f + 0.48f * x) * x; const float tx = delta.x * (omega * omega * deltaTime) - currentVelocity.x * (1.0f + 0.48f * x) * x;
const float ty = delta.y * (omega * omega * deltaTime) - currentVelocity.y * (1.0f + 0.48f * x) * x; const float ty = delta.y * (omega * omega * deltaTime) - currentVelocity.y * (1.0f + 0.48f * x) * x;
VecPos targetVelocity(static_cast<int>(tx), static_cast<int>(ty)); Vec2 targetVelocity(tx, ty);
// 应用速度衰减(指数平滑) // 应用速度衰减(指数平滑)
currentVelocity += targetVelocity; currentVelocity += targetVelocity;
currentVelocity = VecPos( currentVelocity = Vec2(currentVelocity.x * expTerm, currentVelocity.y * expTerm);
static_cast<int>(currentVelocity.x * expTerm),
static_cast<int>(currentVelocity.y * expTerm));
// 限制最大速度如果设置了maxSpeed // 限制最大速度如果设置了maxSpeed
if (maxSpeed > 0) if (maxSpeed > 0)
{ {
// 计算当前速度的模长(浮点精度) // 计算当前速度的模长(浮点精度)
const float speedSq = static_cast<float>(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y); const float speedSq = currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y;
const float maxSpeedSq = static_cast<float>(maxSpeed * maxSpeed); const float maxSpeedSq = maxSpeed * maxSpeed;
if (speedSq > maxSpeedSq) if (speedSq > maxSpeedSq)
{ {
// 速度超限,按比例缩放至最大速度 // 速度超限,按比例缩放至最大速度
const float scale = maxSpeed / sqrtf(speedSq); const float scale = maxSpeed / sqrtf(speedSq);
currentVelocity = VecPos( currentVelocity = Vec2(currentVelocity.x * scale, currentVelocity.y * scale);
static_cast<int>(currentVelocity.x * scale),
static_cast<int>(currentVelocity.y * scale));
} }
} }
// 计算新位置(当前位置 + 速度 * 时间) // 计算新位置(当前位置 + 速度 * 时间)
VecPos newPos = current + VecPos( Vec2 newPos = current + Vec2(currentVelocity.x * deltaTime, currentVelocity.y * deltaTime);
static_cast<int>(currentVelocity.x * deltaTime),
static_cast<int>(currentVelocity.y * deltaTime));
// 检测过冲:如果新位置已越过目标,直接锁定目标并重置速度 // 检测过冲:如果新位置已越过目标,直接锁定目标并重置速度
// 点积 > 0 表示方向相反(已超过目标) // 点积 > 0 表示方向相反(已超过目标)
const int dot = delta.x * (newPos.x - target.x) + delta.y * (newPos.y - target.y); const float dot = delta.x * (newPos.x - target.x) + delta.y * (newPos.y - target.y);
if (dot > 0) if (dot > 0)
{ {
newPos = target; newPos = target;
currentVelocity = VecPos(0, 0); currentVelocity = Vec2(0, 0);
} }
return newPos; return newPos;

View File

@@ -0,0 +1,35 @@
#pragma once
#include "EngineFrame/Base/Actor.h"
class GameMap;
class BaseObject;
class GameCamera : public Actor
{
private:
// 跟随对象
BaseObject *_FromActor = nullptr;
public:
// 缩放比率
float CameraRate = 1.0;
// 添加平滑移动相关的成员变量
bool _isSmoothMoving = false;
Vec2 _currentPosition; // 当前摄像机位置
Vec2 _velocity; // 当前移动速度(用于平滑移动)
float _smoothTime = 0.1f; // 平滑时间(秒),可调整
float _maxSpeed = 2000; // 最大移动速度,防止过快
public:
void SetFromActor(BaseObject *actor);
void Update(float deltaTime);
void SetPos(float x, float y, float z);
void AddPos(float x, float y, float z);
// 同步坐标相关
void SyncPos(float deltaTime);
void SyncPosByFromParent(float deltaTime);
// 平滑阻尼函数类似Unity的Mathf.SmoothDamp
Vec2 SmoothDamp(const Vec2 &current, const Vec2 &target, Vec2 &currentVelocity, float smoothTime, float maxSpeed, float deltaTime);
};

View File

@@ -4,9 +4,6 @@
Global_Game::Global_Game() Global_Game::Global_Game()
{ {
} }
Global_Game::~Global_Game()
{
}
void Global_Game::InitFont() void Global_Game::InitFont()
{ {
@@ -65,11 +62,6 @@ void Global_Game::InitFont()
void Global_Game::Init() void Global_Game::Init()
{ {
InitFont(); InitFont();
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/NotoSansSC-Regular.otf", 24);
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/calibri.ttf", 24);
} }
void Global_Game::InitGame() void Global_Game::InitGame()
@@ -83,9 +75,11 @@ void Global_Game::InitGame()
// 初始化松鼠脚本管理器 // 初始化松鼠脚本管理器
SquirrelManager::GetInstance().Init(); SquirrelManager::GetInstance().Init();
// 读取存档 // 读取存档
SavaManager::GetInstance().Init(); SavaManager::GetInstance().Init();
//创建摄像机
_GameCamera = new GameCamera();
// 游戏初始化完成标志 // 游戏初始化完成标志
InitFlag = true; InitFlag = true;
} }
@@ -110,3 +104,8 @@ GlobalMonsterScript::MonsterConfig Global_Game::GetMonsterInfo(int id)
MonsterInfoMap[id] = MonsterConfig; MonsterInfoMap[id] = MonsterConfig;
return MonsterConfig; return MonsterConfig;
} }
RefPtr<GameCamera> Global_Game::GetCamera()
{
return _GameCamera;
}

View File

@@ -4,6 +4,7 @@
#include "Global/Script/EquipmentConfig.h" #include "Global/Script/EquipmentConfig.h"
#include "Global/Script/MonsterConfig.h" #include "Global/Script/MonsterConfig.h"
#include "Global/Save/SavaManager.h" #include "Global/Save/SavaManager.h"
#include "Global/GameCamera.h"
class Global_Game class Global_Game
{ {
@@ -19,14 +20,15 @@ public:
return instance; return instance;
} }
Global_Game();
// 游戏资源加载之前的初始化 // 游戏资源加载之前的初始化
void Init(); void Init();
// 游戏资源加载之后的初始化 // 游戏资源加载之后的初始化
void InitGame(); void InitGame();
public: private:
// 当前游戏状态 0未初始化 void InitFont();
int game_state = 0;
public: public:
// 字体资源 // 字体资源
@@ -41,12 +43,12 @@ public:
std::map<int, GlobalMonsterScript::MonsterConfig> MonsterInfoMap; // 信息 std::map<int, GlobalMonsterScript::MonsterConfig> MonsterInfoMap; // 信息
GlobalMonsterScript::MonsterConfig GetMonsterInfo(int id); // 获取怪物信息 GlobalMonsterScript::MonsterConfig GetMonsterInfo(int id); // 获取怪物信息
// 游戏摄像机
RefPtr<GameCamera> _GameCamera = nullptr;
// 游戏资源初始化标志 // 游戏资源初始化标志
bool InitFlag = false; bool InitFlag = false;
private: public:
Global_Game(/* args */); RefPtr<GameCamera> GetCamera();
~Global_Game();
void InitFont();
}; };

View File

@@ -20,18 +20,18 @@ void Scene_Loading_UI::Enter()
AddChild(actor); AddChild(actor);
RefPtr<Sprite> BackGroundSp = new Sprite("ImagePacks2/Loading1.png"); RefPtr<Sprite> BackGroundSp = new Sprite("ImagePacks2/Loading1.png");
actor->AddComponent(BackGroundSp); actor->AddChild(BackGroundSp);
RefPtr<Sprite> BackGround2Sp = new Sprite("ImagePacks2/Loading0.png"); RefPtr<Sprite> BackGround2Sp = new Sprite("ImagePacks2/Loading0.png");
BackGround2Sp->SetPos(Vec2{0, 686}); BackGround2Sp->SetPos(Vec2{0, 686});
actor->AddComponent(BackGround2Sp); actor->AddChild(BackGround2Sp);
RefPtr<Sprite> LoadCircleSp = new Sprite("ImagePacks2/Loading2.png"); RefPtr<Sprite> LoadCircleSp = new Sprite("ImagePacks2/Loading2.png");
LoadCircleSp->SetName("LoadCircle"); LoadCircleSp->SetName("LoadCircle");
LoadCircleSp->SetPos(Vec2{1280 - 60, 686 - 60}); LoadCircleSp->SetPos(Vec2{1280 - 60, 686 - 60});
LoadCircleSp->SetBlendMode(LINEARDODGE); LoadCircleSp->SetBlendMode(LINEARDODGE);
LoadCircleSp->SetAnchor(Vec2{0.5f, 0.5f}); LoadCircleSp->SetAnchor(Vec2{0.5f, 0.5f});
actor->AddComponent(LoadCircleSp); actor->AddChild(LoadCircleSp);
actor->SetCallbackOnUpdate([LoadCircleSp](float deltaTime) mutable actor->SetCallbackOnUpdate("Rotate", [LoadCircleSp](float deltaTime) mutable
{ {
float angle = LoadCircleSp->GetRotation(); float angle = LoadCircleSp->GetRotation();
LoadCircleSp->SetRotation(angle + 180.0f * deltaTime); }); LoadCircleSp->SetRotation(angle + 180.0f * deltaTime); });

View File

@@ -17,23 +17,25 @@ Scene_Test::~Scene_Test()
void Scene_Test::Enter() void Scene_Test::Enter()
{ {
map = new GameMap; map = new GameMap;
map->LoadMap("map/cataclysm/town/elvengard/new_d_elvengard_l.map"); map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map");
map->Enter(this); map->Enter(this);
AddChild(map);
map->SetCallbackOnUpdate("csas", [this](float dt)
{
Vec2 pos = map->GetPos();
pos.x -= 10 * dt;
map->SetPos(pos); });
RefPtr<CharacterObject> obj = new CharacterObject(); // RefPtr<CharacterObject> obj = new CharacterObject();
obj->SetPosition({1000, 300, 0}); // obj->SetPosition({1000, 300, 0});
obj->Construction(0); // obj->Construction(0);
// map->AddObject(obj);
map->AddObject(obj); // RefPtr<MonsterObject> monster = new MonsterObject();
// monster->SetPosition({1200, 301, 0});
RefPtr<MonsterObject> monster = new MonsterObject(); // monster->Construction(1);
monster->SetPosition({1200, 301, 0}); // monster->SetDirection(1);
monster->Construction(1); // map->AddObject(monster);
monster->SetDirection(1);
map->AddObject(monster);
_camera = new GameMapCamera;
_camera->SetFromActor(obj.Get());
return; return;
@@ -107,11 +109,6 @@ void Scene_Test::HandleEvents(SDL_Event *e)
void Scene_Test::Update(float deltaTime) void Scene_Test::Update(float deltaTime)
{ {
Scene::Update(deltaTime); Scene::Update(deltaTime);
// 摄像机中有检测宿主坐标 所以要在场景的update后调用以便读取到本帧最新的坐标
if (_camera)
_camera->Update(deltaTime);
if (map)
map->Update(deltaTime);
} }
void Scene_Test::Render() void Scene_Test::Render()
@@ -123,8 +120,3 @@ void Scene_Test::Exit()
{ {
SDL_Log("Scene_Test::退出测试场景!当前引用计数%d", this->GetRefCount()); SDL_Log("Scene_Test::退出测试场景!当前引用计数%d", this->GetRefCount());
} }
RefPtr<BaseNode> Scene_Test::GetCamera()
{
return this->_camera;
}

View File

@@ -3,7 +3,6 @@
#include "Asset/AssetManager.h" #include "Asset/AssetManager.h"
#include "EngineFrame/Component/Animation.h" #include "EngineFrame/Component/Animation.h"
#include "Actor/Map/GameMap.h" #include "Actor/Map/GameMap.h"
#include "Actor/Map/GameMapCamera.h"
#include "Actor/Object/CharacterObject.h" #include "Actor/Object/CharacterObject.h"
#include "Actor/Object/MonsterObject.h" #include "Actor/Object/MonsterObject.h"
@@ -11,7 +10,6 @@ class Scene_Test : public Scene
{ {
private: private:
GameMap *map = nullptr; GameMap *map = nullptr;
RefPtr<GameMapCamera> _camera = nullptr;
public: public:
Scene_Test(/* args */); Scene_Test(/* args */);
@@ -23,7 +21,7 @@ public:
void Update(float deltaTime) override; void Update(float deltaTime) override;
void Render() override; void Render() override;
void Exit() override; void Exit() override;
RefPtr<BaseNode> GetCamera() override;
public: public:
int MyId = 0; int MyId = 0;