From 2b888aae5b62e9901861c5796ee9b227074e411e Mon Sep 17 00:00:00 2001 From: Lenheart <947330670@qq.com> Date: Mon, 20 Oct 2025 20:50:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9OpenGl=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E4=B9=8B=E5=89=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 9 +- Library/SDL_mixer | 1 + Library/SDL_ttf | 1 + Library/squirrel | 1 + folder-alias.json | 18 + source/EngineCore/Game.cpp | 53 ++- source/EngineCore/Game.h | 24 +- source/EngineFrame/Actor/Debug_Actor.cpp | 155 -------- source/EngineFrame/Actor/Debug_Actor.h | 36 -- source/EngineFrame/Base/BaseNode.cpp | 32 ++ source/EngineFrame/Base/BaseNode.h | 11 + source/EngineFrame/Component/Animation.cpp | 64 +++- source/EngineFrame/Component/Animation.h | 12 +- .../Component/AnimationManager.cpp | 107 ++++++ .../EngineFrame/Component/AnimationManager.h | 21 ++ source/EngineFrame/Component/RenderBase.h | 11 +- source/EngineFrame/Component/Sprite.cpp | 166 ++++++--- source/EngineFrame/Component/Sprite.h | 60 ++-- source/EngineFrame/Render/Texture.cpp | 10 +- source/EngineFrame/Render/Texture.h | 8 +- source/EngineFrame/Scene/Scene.cpp | 5 + source/EngineFrame/Scene/Scene.h | 1 + source/Tool/Common.h | 44 +-- source/Tool/Tool_String.cpp | 31 -- source/Tool/Tool_String.h | 2 - source_game/Actor/Map/GameMap.cpp | 109 +++--- source_game/Actor/Map/GameMap.h | 13 +- source_game/Actor/Map/GameMapCamera.cpp | 119 +++++-- source_game/Actor/Map/GameMapCamera.h | 34 +- source_game/Actor/Map/GameMapLayer.cpp | 1 + source_game/Actor/Map/GameMapLayer.h | 2 - source_game/Actor/Map/Tile.cpp | 4 +- source_game/Actor/Object/ActiveObject.cpp | 51 ++- source_game/Actor/Object/ActiveObject.h | 9 +- source_game/Actor/Object/BaseObject.cpp | 62 ++-- source_game/Actor/Object/BaseObject.h | 29 +- source_game/Actor/Object/CharacterObject.cpp | 32 +- source_game/Actor/Object/CharacterObject.h | 10 +- source_game/Actor/Object/MonsterObject.cpp | 10 + source_game/Actor/Object/MonsterObject.h | 18 + source_game/Asset/Character/Chr_Animation.cpp | 16 +- source_game/Asset/Character/Chr_Animation.h | 2 - source_game/Asset/Character/Chr_Shadow.cpp | 44 +++ source_game/Asset/Character/Chr_Shadow.h | 29 ++ source_game/Asset/Monster/Mon_Animation.cpp | 39 ++ source_game/Asset/Monster/Mon_Animation.h | 25 ++ source_game/Asset/Squirrel/Sqr_BaseObject.hpp | 4 +- source_game/Asset/Squirrel/Sqr_UI.hpp | 336 ++++++++++++++++++ .../Asset/Squirrel/SquirrelManager.cpp | 2 + source_game/Asset/Squirrel/SquirrelManager.h | 1 + source_game/Global/Global_Enum.h | 13 +- source_game/Global/Global_Game.cpp | 23 ++ source_game/Global/Global_Game.h | 6 + source_game/Global/Script/MonsterConfig.cpp | 46 +++ source_game/Global/Script/MonsterConfig.h | 26 ++ source_game/Scene/Scene_Loading_UI.cpp | 4 +- source_game/Scene/Scene_MainUi.cpp | 72 ++++ source_game/Scene/Scene_MainUi.h | 15 + .../Scene/Scene_SelectCharacter_UI.hpp | 98 ----- source_game/Scene/Scene_Test.cpp | 89 ++++- source_game/Scene/Scene_Test.h | 13 +- 61 files changed, 1609 insertions(+), 680 deletions(-) create mode 160000 Library/SDL_mixer create mode 160000 Library/SDL_ttf create mode 160000 Library/squirrel delete mode 100644 source/EngineFrame/Actor/Debug_Actor.cpp delete mode 100644 source/EngineFrame/Actor/Debug_Actor.h create mode 100644 source/EngineFrame/Component/AnimationManager.cpp create mode 100644 source/EngineFrame/Component/AnimationManager.h create mode 100644 source_game/Actor/Object/MonsterObject.cpp create mode 100644 source_game/Actor/Object/MonsterObject.h create mode 100644 source_game/Asset/Character/Chr_Shadow.cpp create mode 100644 source_game/Asset/Character/Chr_Shadow.h create mode 100644 source_game/Asset/Monster/Mon_Animation.cpp create mode 100644 source_game/Asset/Monster/Mon_Animation.h create mode 100644 source_game/Asset/Squirrel/Sqr_UI.hpp create mode 100644 source_game/Global/Script/MonsterConfig.cpp create mode 100644 source_game/Global/Script/MonsterConfig.h create mode 100644 source_game/Scene/Scene_MainUi.cpp create mode 100644 source_game/Scene/Scene_MainUi.h delete mode 100644 source_game/Scene/Scene_SelectCharacter_UI.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ec1fb7..77a7cb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,14 @@ add_executable(${PROJECT_NAME} ${SOURCES}) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O1 -g" CACHE STRING "" FORCE) +if (MINGW) + target_link_options(${PROJECT_NAME} PRIVATE + -static-libgcc + -static-libstdc++ + -Wl,-Bstatic,--whole-archive -lpthread -Wl,--no-whole-archive + ) +endif() + # 设置头文件目录(包含所有库的头文件路径) target_include_directories(${PROJECT_NAME} PRIVATE Library/zlib-1.3.1 @@ -90,7 +98,6 @@ target_link_libraries(${PROJECT_NAME} PRIVATE zlibstatic # zlib库 squirrel_static # squirrel库(根据实际目标名调整) sqstdlib_static - iconv mingwex winmm diff --git a/Library/SDL_mixer b/Library/SDL_mixer new file mode 160000 index 0000000..5d0ea94 --- /dev/null +++ b/Library/SDL_mixer @@ -0,0 +1 @@ +Subproject commit 5d0ea9462b002b6cce104f2bbf2cd6bed52e2e1d diff --git a/Library/SDL_ttf b/Library/SDL_ttf new file mode 160000 index 0000000..4a318f8 --- /dev/null +++ b/Library/SDL_ttf @@ -0,0 +1 @@ +Subproject commit 4a318f8dfaa1bb6f10e0c5e54052e25d3c7f3440 diff --git a/Library/squirrel b/Library/squirrel new file mode 160000 index 0000000..f77074b --- /dev/null +++ b/Library/squirrel @@ -0,0 +1 @@ +Subproject commit f77074bdd6152d230609146a3d424c6f49e3770f diff --git a/folder-alias.json b/folder-alias.json index 6eb6628..73ca75b 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -184,5 +184,23 @@ }, "source_game/Asset/Squirrel/Sqr_ActiveObject.hpp": { "description": "注册动态对象脚本" + }, + "source_game/Actor/Object/MonsterObject.h": { + "description": "怪物对象" + }, + "source_game/Global/Script/MonsterConfig.h": { + "description": "怪物配置信息" + }, + "source_game/Asset/Monster": { + "description": "怪物类" + }, + "source_game/Asset/Monster/Mon_Animation.h": { + "description": "怪物动画管理器" + }, + "source_game/Scene/Scene_MainUi.h": { + "description": "MainUI场景" + }, + "source_game/Asset/Squirrel/Sqr_UI.hpp": { + "description": "注册UI脚本" } } \ No newline at end of file diff --git a/source/EngineCore/Game.cpp b/source/EngineCore/Game.cpp index 29bfb39..75aad36 100644 --- a/source/EngineCore/Game.cpp +++ b/source/EngineCore/Game.cpp @@ -3,7 +3,6 @@ #include "EngineFrame/Component/Sprite.h" #include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Component/Text.h" -#include "EngineFrame/Actor/Debug_Actor.h" Game::Game() { @@ -16,8 +15,6 @@ Game::~Game() void Game::Init(std::function CallBack) { - // 计算帧时间 - m_frameTime = 1000 / m_fps; SDL_InitSubSystem(SDL_INIT_JOYSTICK); SDL_JoystickEventState(SDL_ENABLE); @@ -52,7 +49,7 @@ void Game::Init(std::function CallBack) } } // 创建渲染器 - m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED); + m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (m_renderer == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Renderer! Error: %s\n", SDL_GetError()); @@ -78,41 +75,41 @@ void Game::Init(std::function CallBack) m_isRunning = false; } // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - // 构造调试对象 - m_DebugInfoActor = new Debug_Actor(); CallBack(); } void Game::Run() { + // 计算帧时间 + m_frameTime = 1000.0 / m_Settingfps; + while (m_isRunning) { - u32 frameStart = SDL_GetTicks(); // 帧开始时间 + // 帧开始时间 + Uint64 frameStart = SDL_GetTicks64(); SDL_Event m_event; HandleEvents(&m_event); - Update(m_deltaTime); // 注意:这里使用的是上一帧的deltaTime(合理,见说明) + Update(m_deltaTime); Render(); - // 帧率统计(保持不变) - m_frameCount++; - u32 currentTime = SDL_GetTicks(); + // 帧率统计 每一秒钟的时候记录一次帧率 + m_frameCounter++; + Uint64 currentTime = SDL_GetTicks64(); if (currentTime - m_lastFpsPrintTime >= 1000) { - u32 fps = m_frameCount; - if (m_DebugInfoActor) - m_DebugInfoActor->FPS = fps; + m_fps = m_frameCounter; m_lastFpsPrintTime = currentTime; - m_frameCount = 0; + m_frameCounter = 0; } // 计算实际总帧时间(关键修改) - u32 diff = SDL_GetTicks() - frameStart; // 处理耗时 + Uint64 diff = SDL_GetTicks64() - frameStart; // 处理耗时 if (diff < m_frameTime) { SDL_Delay(m_frameTime - diff); // 尝试延迟补全 } // 延迟后,重新计算从帧开始到现在的总时间(包含可能的延迟误差) - u32 actualFrameTime = SDL_GetTicks() - frameStart; + Uint64 actualFrameTime = SDL_GetTicks64() - frameStart; m_deltaTime = actualFrameTime / 1000.0f; // 用实际总时间更新deltaTime } } @@ -156,26 +153,25 @@ void Game::Update(float deltaTime) m_scene->Update(deltaTime); if (m_uiScene != nullptr) m_uiScene->Update(deltaTime); - - // 调试信息 - if (m_DebugInfoActor != nullptr) - { - m_DebugInfoActor->Update(deltaTime); - m_DebugInfoActor->RenderCount = RenderCount; - } - - RenderCount = 0; } void Game::Render() { + // 绘制调用次数清0 + m_RenderCount = 0; + + // 调用预渲染 + if (m_scene != nullptr) + m_scene->PreRender(); + if (m_uiScene != nullptr) + m_uiScene->PreRender(); + + // 清空渲染器后渲染 SDL_RenderClear(m_renderer); if (m_scene != nullptr) m_scene->Render(); if (m_uiScene != nullptr) m_uiScene->Render(); - if (m_DebugInfoActor != nullptr) - m_DebugInfoActor->Render(); SDL_RenderPresent(m_renderer); } @@ -191,7 +187,6 @@ void Game::Clear() m_uiScene->Exit(); } m_uiScene = nullptr; - m_DebugInfoActor = nullptr; IMG_Quit(); SDL_DestroyRenderer(m_renderer); SDL_DestroyWindow(m_window); diff --git a/source/EngineCore/Game.h b/source/EngineCore/Game.h index 90388cc..fdba204 100644 --- a/source/EngineCore/Game.h +++ b/source/EngineCore/Game.h @@ -57,7 +57,10 @@ public: SDL_Renderer *GetRenderer(); - uint32_t RenderCount = 0; + // 每秒帧率 + u32 m_fps; + // 每帧绘制调用次数 + u32 m_RenderCount = 0; private: // 构造函数和析构函数设为私有,防止外部创建和销毁 @@ -78,18 +81,19 @@ private: // 帧数 #ifdef __SWITCH__ - int m_fps = 60; + float m_Settingfps = 60.0; #else - int m_fps = 2000; + float m_Settingfps = 144.0; #endif - u32 m_frameTime; - float m_deltaTime; - // 新增:帧率统计变量 - u32 m_frameCount; // 每秒内的帧数计数器 - u32 m_lastFpsPrintTime; // 上一次输出帧率的时间(毫秒,基于 SDL_GetTicks()) + // 单帧时间 + float m_frameTime = 0.f; + // 每秒内的帧数计数器 + u32 m_frameCounter; + // 上一次输出帧率的时间 + u32 m_lastFpsPrintTime; - // 调试信息Actor - RefPtr m_DebugInfoActor; + // 帧间隔 + float m_deltaTime = 0.f; public: // 屏幕宽高 diff --git a/source/EngineFrame/Actor/Debug_Actor.cpp b/source/EngineFrame/Actor/Debug_Actor.cpp deleted file mode 100644 index 4db67c7..0000000 --- a/source/EngineFrame/Actor/Debug_Actor.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "Debug_Actor.h" -#include "EngineCore/Game.h" -#include - -Debug_Actor::Debug_Actor() -{ - m_debugFont = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 12); - if (m_debugFont == nullptr) - { - - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load debug font: %s", TTF_GetError()); - } - - FPS_Text = new Text("当 前 帧 数 :", m_debugFont, SDL_Color{255, 255, 255, 255}); - DT_Text = new Text("帧 时 间 :", m_debugFont, SDL_Color{255, 255, 255, 255}); - RC_Text = new Text("渲 染 调 用 次 数:", m_debugFont, SDL_Color{255, 255, 255, 255}); - if (FPS_Text != nullptr) - { - SDL_Point Pos{26, 26}; - FPS_Text->SetPos(Pos); - this->AddComponent(FPS_Text); - } - if (DT_Text != nullptr) - { - SDL_Point Pos{26, 46}; - DT_Text->SetPos(Pos); - this->AddComponent(DT_Text); - } - if (RC_Text != nullptr) - { - SDL_Point Pos{26, 66}; - RC_Text->SetPos(Pos); - this->AddComponent(RC_Text); - } -} - -Debug_Actor::~Debug_Actor() -{ - - if (m_debugFont != nullptr) - { - TTF_CloseFont(m_debugFont); - m_debugFont = nullptr; - } -} - -void Debug_Actor::Update(float deltaTime) -{ - Actor::Update(deltaTime); - - if (FPS_Text != nullptr) - { - std::string fpsText = "当前帧数 : " + std::to_string(FPS); - FPS_Text->SetText(fpsText); - std::string dtText = "帧时间 : " + std::to_string((int)(deltaTime * 1000)); - DT_Text->SetText(dtText); - std::string rcText = "渲染调用次数 : " + std::to_string(RenderCount); - RC_Text->SetText(rcText); - } -} - -void Debug_Actor::Render() -{ - if (FPS_Text != nullptr) - { - SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); - if (renderer != nullptr) - { - - SDL_Point textPos = FPS_Text->Pos; - SDL_Point textSize = FPS_Text->Size; - - int bgX = textPos.x - padding; - int bgY = textPos.y - padding; - int bgWidth = textSize.x + padding * 2; - int bgHeight = textSize.y + padding * 2 * 4; - - DrawRoundedRect(renderer, bgX, bgY, bgWidth, bgHeight, cornerRadius, bgColor); - } - } - - Actor::Render(); -} - -void Debug_Actor::DrawRoundedRect(SDL_Renderer *renderer, int x, int y, int w, int h, int radius, SDL_Color color) -{ - if (renderer == nullptr) - return; - - SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); - - SDL_RenderDrawLine(renderer, x + radius, y, x + w - radius, y); - SDL_RenderDrawLine(renderer, x + radius, y + h, x + w - radius, y + h); - SDL_RenderDrawLine(renderer, x, y + radius, x, y + h - radius); - SDL_RenderDrawLine(renderer, x + w, y + radius, x + w, y + h - radius); - - const int segments = 16; - for (int i = 0; i < segments; i++) - { - - float t1 = static_cast(i) / segments; - float t2 = static_cast(i + 1) / segments; - - float angle1 = M_PI * (1.0f - t1); - float angle2 = M_PI * (1.0f - t2); - SDL_RenderDrawLineF( - renderer, - x + radius + cos(angle1) * radius, y + radius + sin(angle1) * radius, - x + radius + cos(angle2) * radius, y + radius + sin(angle2) * radius); - - angle1 = 2 * M_PI - t1 * M_PI_2; - angle2 = 2 * M_PI - t2 * M_PI_2; - SDL_RenderDrawLineF( - renderer, - x + w - radius + cos(angle1) * radius, y + radius + sin(angle1) * radius, - x + w - radius + cos(angle2) * radius, y + radius + sin(angle2) * radius); - - angle1 = t1 * M_PI_2; - angle2 = t2 * M_PI_2; - SDL_RenderDrawLineF( - renderer, - x + w - radius + cos(angle1) * radius, y + h - radius + sin(angle1) * radius, - x + w - radius + cos(angle2) * radius, y + h - radius + sin(angle2) * radius); - - angle1 = M_PI_2 + t1 * M_PI_2; - angle2 = M_PI_2 + t2 * M_PI_2; - SDL_RenderDrawLineF( - renderer, - x + radius + cos(angle1) * radius, y + h - radius + sin(angle1) * radius, - x + radius + cos(angle2) * radius, y + h - radius + sin(angle2) * radius); - } - - for (int dy = 0; dy < h; dy++) - { - int leftIndent = 0; - int rightIndent = 0; - - if (dy < radius) - { - float ratio = 1.0f - static_cast(dy) / radius; - leftIndent = rightIndent = static_cast(radius * (1.0f - sqrt(1.0f - ratio * ratio))); - } - - else if (dy > h - radius) - { - float ratio = static_cast(dy - (h - radius)) / radius; - leftIndent = rightIndent = static_cast(radius * (1.0f - sqrt(1.0f - ratio * ratio))); - } - - SDL_RenderDrawLine( - renderer, - x + leftIndent, y + dy, - x + w - rightIndent, y + dy); - } -} \ No newline at end of file diff --git a/source/EngineFrame/Actor/Debug_Actor.h b/source/EngineFrame/Actor/Debug_Actor.h deleted file mode 100644 index a38ed9d..0000000 --- a/source/EngineFrame/Actor/Debug_Actor.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "EngineFrame/Actor/Actor.h" -#include "EngineFrame/Component/Text.h" -#include -#include - -class Debug_Actor : public Actor -{ -private: - TTF_Font *m_debugFont; - RefPtr FPS_Text; - RefPtr DT_Text; - RefPtr RC_Text; - -public: - Debug_Actor(); - ~Debug_Actor() override; - - void Update(float deltaTime) override; - void Render() override; - - uint32_t FPS = 0; - uint32_t RenderCount = 0; - - SDL_Color bgColor = {0, 0, 0, 90}; - - int cornerRadius = 4; - int padding = 12; -#ifdef __SWITCH__ - double M_PI = 3.14159265358979323846; - double M_PI_2 = 1.57079632679489661923; -#endif - -private: - void DrawRoundedRect(SDL_Renderer *renderer, int x, int y, int w, int h, int radius, SDL_Color color); -}; \ No newline at end of file diff --git a/source/EngineFrame/Base/BaseNode.cpp b/source/EngineFrame/Base/BaseNode.cpp index d05a09d..58e0332 100644 --- a/source/EngineFrame/Base/BaseNode.cpp +++ b/source/EngineFrame/Base/BaseNode.cpp @@ -32,6 +32,18 @@ void BaseNode::Update(float deltaTime) } } +void BaseNode::PreRender() +{ + // 如果有子节点并含有渲染标签,则渲染子节点 + RefPtr child = m_BaseNodes.GetFirst(); + while (child) + { + if (child->hasTag(Tag::RENDER)) + child->PreRender(); + child = child->GetNext(); + } +} + void BaseNode::Render() { // 如果有子节点并含有渲染标签,则渲染子节点 @@ -150,6 +162,11 @@ void BaseNode::RemoveChild(RefPtr child) m_BaseNodes.Remove(child); } +void BaseNode::RemoveAllChild() +{ + m_BaseNodes.Clear(); +} + void BaseNode::OnAdded(BaseNode *node) { m_Parent = node; @@ -197,6 +214,11 @@ VecFPos BaseNode::GetPos() return this->transform.position; } +VecFPos BaseNode::GetWorldPos() +{ + return this->transform.position + this->transformIter.position; +} + void BaseNode::SetScale(VecFPos scale) { if (scale == this->transform.scale) @@ -261,6 +283,16 @@ bool BaseNode::GetVisible() return this->Visible; } +void BaseNode::SetAlpha(float alpha) +{ + this->Alpha = alpha; +} + +float BaseNode::GetAlpha() +{ + return this->Alpha; +} + void BaseNode::SetIterationPos(VecFPos pos) { if (pos == this->transformIter.position) diff --git a/source/EngineFrame/Base/BaseNode.h b/source/EngineFrame/Base/BaseNode.h index dc210fc..8ec00da 100644 --- a/source/EngineFrame/Base/BaseNode.h +++ b/source/EngineFrame/Base/BaseNode.h @@ -35,6 +35,8 @@ public: VecFPos Anchor = {0.f, 0.f}; // 大小 VecSize Size = {0, 0}; + // 透明度 + float Alpha = 1.f; // 是否显示 bool Visible = true; // 计算渲染信息Flag (为了保证每帧只计算一次) @@ -48,6 +50,7 @@ public: virtual void Init(); virtual void HandleEvents(SDL_Event *e); virtual void Update(float deltaTime); + virtual void PreRender(); virtual void Render(); virtual void Clear(); @@ -73,6 +76,8 @@ public: virtual void AddChild(RefPtr child); // 移除子对象 void RemoveChild(RefPtr child); + // 移除所有子对象 + void RemoveAllChild(); // 被添加时 virtual void OnAdded(BaseNode *node); // 设置迭代的二维仿射变换 @@ -101,6 +106,8 @@ public: virtual void SetPos(VecFPos pos); // 获取坐标 VecFPos GetPos(); + // 获取世界坐标 + VecFPos GetWorldPos(); // 设置缩放 virtual void SetScale(VecFPos scale); // 获取缩放 @@ -121,4 +128,8 @@ public: virtual void SetVisible(bool visible); // 获取是否显示 bool GetVisible(); + // 设置透明度 + virtual void SetAlpha(float alpha); + // 获取透明度 + float GetAlpha(); }; diff --git a/source/EngineFrame/Component/Animation.cpp b/source/EngineFrame/Component/Animation.cpp index d9aa63a..4b77b59 100644 --- a/source/EngineFrame/Component/Animation.cpp +++ b/source/EngineFrame/Component/Animation.cpp @@ -3,6 +3,7 @@ #include "Asset/Asset_Script.h" #include "Tool/Math.h" #include "EngineFrame/Actor/Actor.h" +#include "EngineCore/Game.h" Animation::Animation() { @@ -66,20 +67,20 @@ void Animation::Init(std::string AniPath) // TODO 染色 // 判断是否有Als - if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als")) - { - AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als"); - if (Info.AniList.size() > 0) - { - std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1); - for (auto &Ani : Info.AniList) - { - RefPtr AlsAniObj = new Animation(Dir + Ani.second.path); - AlsAniObj->SetRenderZOrder(Ani.second.layer[1]); - AddChild(AlsAniObj); - } - } - } + // if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als")) + // { + // AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als"); + // if (Info.AniList.size() > 0) + // { + // std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1); + // for (auto &Ani : Info.AniList) + // { + // RefPtr AlsAniObj = new Animation(Dir + Ani.second.path); + // AlsAniObj->SetRenderZOrder(Ani.second.layer[1]); + // AddChild(AlsAniObj); + // } + // } + // } FlushFrame(0); } @@ -134,7 +135,18 @@ void Animation::Render() { if (!Visible) return; - Actor::Render(); + // 是否裁切 + if (CropFlag) + { + SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); + SDL_RenderSetClipRect(renderer, &CropRect); + Actor::Render(); + SDL_RenderSetClipRect(renderer, NULL); + } + else + { + Actor::Render(); + } } void Animation::OnAdded(BaseNode *node) @@ -153,6 +165,7 @@ void Animation::SetVisible(bool visible) if (visible) { CurrentFrame->CalcRenderInfoLogic(); + CurrentFrame->CalcRenderInfo(); } Actor::SetVisible(visible); } @@ -192,7 +205,6 @@ void Animation::FlushFrame(int Index) if (FlagBuf.count("IMAGE_RATE")) { VecFPos Rate = std::get(FlagBuf["IMAGE_RATE"]); - CurrentFrame->SetAnchor(VecFPos{0.5f, 0.5f}); CurrentFrame->SetScale(VecFPos{Rate.x, Rate.y}); } // 线性减淡 @@ -233,7 +245,6 @@ void Animation::FlushFrame(int Index) } // Ani的大小同步为精灵帧对象的大小 SetSize(CurrentFrame->GetSize()); - // 裁切 //TODO } void Animation::Reset() @@ -317,3 +328,22 @@ void Animation::InterpolationLogic() CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate); } } + +void Animation::SetClipRect(SDL_Rect clipRect) +{ + CropFlag = true; + CropRect = clipRect; +} + +void Animation::UnsetClipRect() +{ + CropFlag = false; +} + +void Animation::SetShadow() +{ + for (auto &Sp : SpriteArr) + { + Sp->SetShadow(); + } +} diff --git a/source/EngineFrame/Component/Animation.h b/source/EngineFrame/Component/Animation.h index 8ef0bec..6333f56 100644 --- a/source/EngineFrame/Component/Animation.h +++ b/source/EngineFrame/Component/Animation.h @@ -36,12 +36,20 @@ public: void FlushFrame(int Index); void Reset(); AniScriptParser::AniFrame GetCurrentFrameInfo(); + // 设置帧索引 void SetFrameIndex(int Index); void InterpolationLogic(); // TODO SetOutline // TODO SetDye // TODO SetCrop + // 设置裁切区域 + void SetClipRect(SDL_Rect clipRect); + // 取消裁切区域 + void UnsetClipRect(); + // 设置阴影 + void SetShadow(); + public: // Ani是否可用 bool IsUsability = true; @@ -88,7 +96,9 @@ public: // // 整体染色 // DyeAllFlag = false; // // 裁切数据 - // CropRect = null; + SDL_Rect CropRect = {0, 0, 0, 0}; + // 裁切Flag + bool CropFlag = false; // 附加选项 std::function AdditionalOptions; diff --git a/source/EngineFrame/Component/AnimationManager.cpp b/source/EngineFrame/Component/AnimationManager.cpp new file mode 100644 index 0000000..862b2a5 --- /dev/null +++ b/source/EngineFrame/Component/AnimationManager.cpp @@ -0,0 +1,107 @@ +#include "AnimationManager.h" +#include "EngineCore/Game.h" + +AnimationManager::AnimationManager() +{ + SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); + m_Texture = SDL_CreateTexture( + renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, + Game::GetInstance().Screen_W, + Game::GetInstance().Screen_H); +} + +void AnimationManager::PreRender() +{ + Actor::PreRender(); + // 标记是否是第一个子对象(用于初始化min/max值) + bool isFirst = true; + float minX = 0.0f, minY = 0.0f; // 所有子对象的最小X、Y坐标 + float maxX = 0.0f, maxY = 0.0f; // 所有子对象的最大X、Y坐标(右下角) + + RefPtr child = m_BaseNodes.GetFirst(); + while (child) + { + // 转换为Animation对象 + Animation *ani = static_cast(child.Get()); + + float width = ani->CurrentFrame->_RenderGuidanceInfo.rect.w; + float height = ani->CurrentFrame->_RenderGuidanceInfo.rect.h; + float x = ani->CurrentFrame->_RenderGuidanceInfo.rect.x; + float y = ani->CurrentFrame->_RenderGuidanceInfo.rect.y; + + // 计算子对象的右下角坐标(左上角 + 宽高) + float currentMaxX = x + width; + float currentMaxY = y + height; + // 初始化或更新min/max值 + if (isFirst) + { + minX = x; + minY = y; + maxX = currentMaxX; + maxY = currentMaxY; + isFirst = false; + } + else + { + minX = std::min(minX, x); + minY = std::min(minY, y); + maxX = std::max(maxX, currentMaxX); + maxY = std::max(maxY, currentMaxY); + } + + child = child->GetNext(); + } + // 计算最终的包围盒矩形 + if (!isFirst) // 至少有一个子对象时才计算 + { + m_RenderRect.x = minX; // 矩形左上角X + m_RenderRect.y = minY; // 矩形左上角Y + m_RenderRect.w = maxX - minX; // 矩形宽度(右下角X - 左上角X) + m_RenderRect.h = maxY - minY; // 矩形高度(右下角Y - 左上角Y) + } +} + +void AnimationManager::Render() +{ + SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); + // 设定渲染目标为纹理 + SDL_SetRenderTarget(renderer, m_Texture); + + SDL_RenderClear(renderer); + // 渲染所有子对象 + Actor::Render(); + // 恢复渲染目标为默认窗口 + SDL_SetRenderTarget(renderer, nullptr); + + SDL_Rect srcRect = { + static_cast(m_RenderRect.x), // 子对象包围盒左上角X(纹理中的位置) + static_cast(m_RenderRect.y), // 子对象包围盒左上角Y(纹理中的位置) + static_cast(m_RenderRect.w), // 包围盒宽度(有效区域宽度) + static_cast(m_RenderRect.h) // 包围盒高度(有效区域高度) + }; + + // SDL_FRect renderToWindow = { + // m_RenderRect.x, // 窗口上的X位置(可自定义) + // m_RenderRect.y, // 窗口上的Y位置(可自定义) + // m_RenderRect.w, // 渲染到窗口的宽度(与源区域等大) + // m_RenderRect.h // 渲染到窗口的高度(与源区域等大) + // }; + SDL_FRect renderToWindow = { + 0, 0, 1080, 720}; + + // SDL_Log("m_Texture rect: %f %f %f %f", renderToWindow.x, renderToWindow.y, renderToWindow.w, renderToWindow.h); + // SDL_RenderCopyF(renderer, m_Texture, &srcRect, &renderToWindow); + SDL_RenderCopyF(renderer, m_Texture, NULL, &renderToWindow); +} + +void AnimationManager::AddAnimation(RefPtr ani) +{ + this->AddChild(ani); +} + +void AnimationManager::Clear() +{ + this->RemoveAllChild(); +} diff --git a/source/EngineFrame/Component/AnimationManager.h b/source/EngineFrame/Component/AnimationManager.h new file mode 100644 index 0000000..b31784d --- /dev/null +++ b/source/EngineFrame/Component/AnimationManager.h @@ -0,0 +1,21 @@ +#pragma once +#include "EngineFrame/Component/Animation.h" +#include +class AnimationManager : public Actor +{ +private: + SDL_Texture *m_Texture = nullptr; + SDL_FRect m_RenderRect = {0, 0, 0, 0}; + +public: + AnimationManager(); + // void Update(float deltaTime) override; + void PreRender() override; + void Render() override; + +public: + // 添加Ani + void AddAnimation(RefPtr ani); + // 清空Ani + void Clear(); +}; diff --git a/source/EngineFrame/Component/RenderBase.h b/source/EngineFrame/Component/RenderBase.h index 5e3c782..08a015b 100644 --- a/source/EngineFrame/Component/RenderBase.h +++ b/source/EngineFrame/Component/RenderBase.h @@ -9,12 +9,17 @@ class RenderBase : public Component public: struct RenderGuidanceInfo { - SDL_Rect rect; + SDL_FRect rect; + // 旋转角度 float rotation; + // 翻转Flag SDL_RendererFlip flip = SDL_FLIP_NONE; - VecPos AnchorPos; + // 锚点坐标 + VecFPos AnchorPos; + // 是否显示 bool Visible = true; - bool IsInScreen; + // 是否在屏幕内 + bool IsInScreen = false; }; public: diff --git a/source/EngineFrame/Component/Sprite.cpp b/source/EngineFrame/Component/Sprite.cpp index f9b1cc4..72a6165 100644 --- a/source/EngineFrame/Component/Sprite.cpp +++ b/source/EngineFrame/Component/Sprite.cpp @@ -1,8 +1,11 @@ #include "Sprite.h" #include "EngineCore/Game.h" #include "Text.h" -Sprite::Sprite() + +void Sprite::Init() { + this->Size = m_texture->TextureSize; + RenderBase::Init(); } Sprite::Sprite(std::string imgPath, int Index) @@ -30,27 +33,12 @@ RefPtr Sprite::GetTexture() return m_texture; } -void Sprite::SetIterationPos(VecFPos pos) -{ - RenderBase::SetIterationPos(pos); - CalcRenderInfo(); -} - -void Sprite::HandleEvents(SDL_Event *e) -{ -} - -void Sprite::Update(float deltaTime) -{ - if (CalcRenderInfoFlag && Visible) - CalcRenderInfoLogic(); -} - void Sprite::CalcRenderInfoLogic() { // 计算缩放因子和翻转状态 float scaleX = transformIter.scale.x * transform.scale.x; float scaleY = transformIter.scale.y * transform.scale.y; + // X轴和Y轴上是否翻转的标志 bool flipX = scaleX < 0; bool flipY = scaleY < 0; @@ -63,46 +51,55 @@ void Sprite::CalcRenderInfoLogic() _RenderGuidanceInfo.flip = static_cast(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip); // 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上 - int texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x; - int texturePosY = flipY ? -(m_texture->TextureSize.height + m_texture->TexturePos.y) + SDL_abs(transform.position.y * 2) : m_texture->TexturePos.y; + float texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x; + float texturePosY = flipY ? -(m_texture->TextureSize.height + m_texture->TexturePos.y) + SDL_abs(transform.position.y * 2) : m_texture->TexturePos.y; // 先计算Img坐标与精灵坐标合成后的真实坐标 - int RealPosX = transform.position.x + texturePosX; - int RealPosY = transform.position.y + texturePosY; + float RealPosX = transform.position.x + texturePosX; + float RealPosY = transform.position.y + texturePosY; // 计算在世界中的位置 - int baseX = transformIter.position.x + RealPosX; - int baseY = transformIter.position.y + RealPosY; + float baseX = transformIter.position.x + RealPosX; + float baseY = transformIter.position.y + RealPosY; // 获取当前帧的原始尺寸 - int frameWidth = m_texture->TextureSize.width; - int frameHeight = m_texture->TextureSize.height; + int frameWidth = Size.width; + int frameHeight = Size.height; // 原始锚点偏移(基于帧尺寸) - int origAnchorOffsetX = static_cast(frameWidth * Anchor.x); - int origAnchorOffsetY = static_cast(frameHeight * Anchor.y); + float origAnchorOffsetX = int(frameWidth * Anchor.x); + float origAnchorOffsetY = int(frameHeight * Anchor.y); // 缩放的绝对值 - float absScaleX = SDL_abs(scaleX); - float absScaleY = SDL_abs(scaleY); + float absScaleX = SDL_fabs(scaleX); + float absScaleY = SDL_fabs(scaleY); // 缩放后的尺寸 - int scaledWidth = static_cast(frameWidth * absScaleX); - int scaledHeight = static_cast(frameHeight * absScaleY); + float scaledWidth = frameWidth * absScaleX; + float scaledHeight = frameHeight * absScaleY; // 缩放后的锚点偏移 - int scaledAnchorOffsetX = static_cast(origAnchorOffsetX * absScaleX); - int scaledAnchorOffsetY = static_cast(origAnchorOffsetY * absScaleY); + float scaledAnchorOffsetX = int(origAnchorOffsetX * absScaleX); + float scaledAnchorOffsetY = int(origAnchorOffsetY * absScaleY); // 计算缩放后的锚点偏移与原锚点偏移的差值 - int scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX; - int scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY; + float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX; + float scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY; // 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角) - int Xpos = baseX + scaleOffsetX; - int Ypos = baseY + scaleOffsetY; + float Xpos = baseX - scaleOffsetX; + float Ypos = baseY - scaleOffsetY; + + Xpos = (int)Xpos; // 强制转换为整数 + Ypos = (int)Ypos; // 强制转换为整数 // 更新渲染信息 _RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight}; + + // 如果有阴影 计算阴影的渲染信息 + if (ShadowFlag) + CalculateShadowData(); _RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY}; + // 设置纹理透明度 + SDL_SetTextureAlphaMod(m_texture->GetTexture(), this->Alpha * 255); // 屏幕内检测 int screenWidth = Game::GetInstance().Screen_W; @@ -110,12 +107,29 @@ void Sprite::CalcRenderInfoLogic() bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight); _RenderGuidanceInfo.IsInScreen = isInScreen; - this->Size = {scaledWidth, scaledHeight}; + // this->Size = {scaledWidth, scaledHeight}; _RenderGuidanceInfo.rotation = transformIter.rotation + transform.rotation; CalcRenderInfoFlag = false; } +void Sprite::SetClipRect(SDL_Rect clipRect) +{ + CropFlag = true; + CropRect = clipRect; +} + +void Sprite::UnsetClipRect() +{ + CropFlag = false; +} + +void Sprite::PreRender() +{ + if (CalcRenderInfoFlag && Visible) + CalcRenderInfoLogic(); +} + void Sprite::Render() { if (!Visible) @@ -126,20 +140,27 @@ void Sprite::Render() if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible) { + // 如果有阴影绘制阴影 + if (ShadowFlag) + { + std::array indices = {0, 1, 2, 1, 3, 2}; + SDL_RenderGeometry(renderer, m_texture->GetTexture(), vertices.data(), vertices.size(), indices.data(), indices.size()); + } + if (_RenderGuidanceInfo.rotation != 0.f || _RenderGuidanceInfo.flip != SDL_FLIP_NONE) { - SDL_Point AnchorPos = _RenderGuidanceInfo.AnchorPos; - SDL_RenderCopyEx(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip); + SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos; + SDL_RenderCopyExF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip); } else { - SDL_RenderCopy(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect); + SDL_RenderCopyF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect); // // 设置绘制颜色 // SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128); // // 绘制填充矩形 - // SDL_RenderFillRect(renderer, &_RenderGuidanceInfo.rect); + // SDL_RenderFillRectF(renderer, &_RenderGuidanceInfo.rect); } - Game::GetInstance().RenderCount++; + Game::GetInstance().m_RenderCount++; } } @@ -157,3 +178,62 @@ SDL_BlendMode Sprite::GetBlendMode() { return m_texture->GetBlendMode(); } + +void Sprite::SetShadow() +{ + ShadowFlag = true; + CalcRenderInfo(); +} + +void Sprite::CalculateShadowData() +{ + const float shearX = 1.3f; + SDL_FRect guidance = _RenderGuidanceInfo.rect; + float shadowW = guidance.w; // 影子宽度(建议与角色宽度一致) + float shadowH = guidance.h * 0.33; // 影子高度(可根据需求调整,比如角色高度的1/4) + + // 计算角色脚部中点坐标(底部中心,即需要重叠的锚点) + float roleFootX = guidance.x + guidance.w / 2.0f + 3; // 角色X中心 + 位置偏移 + float roleFootY = guidance.y + guidance.h - 5; // 角色底部Y坐标(脚的位置) + + // 计算错切后的顶点(局部坐标) + vertices = { + // 左上角(局部坐标) + SDL_Vertex{{0.0f, 0.0f}, {0, 0, 0, 110}, {0.0f, 0.0f}}, + // 右上角(局部坐标) + SDL_Vertex{{shadowW, 0.0f}, {0, 0, 0, 110}, {1.0f, 0.0f}}, + // 左下角(局部坐标) + SDL_Vertex{{0.0f + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {0.0f, 1.0f}}, + // 右下角(局部坐标) + SDL_Vertex{{shadowW + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {1.0f, 1.0f}}}; + + bool flipHorizontal = (_RenderGuidanceInfo.flip & SDL_FLIP_HORIZONTAL) != 0; // 检查水平翻转标志 + bool flipVertical = (_RenderGuidanceInfo.flip & SDL_FLIP_VERTICAL) != 0; // 检查垂直翻转标志 + // 应用纹理坐标翻转(核心逻辑) + for (auto &v : vertices) + { + // 水平翻转:反转u坐标(0→1,1→0) + if (flipHorizontal) + { + v.tex_coord.x = 1.0f - v.tex_coord.x; + } + // 垂直翻转:反转v坐标(0→1,1→0) + if (flipVertical) + { + v.tex_coord.y = 1.0f - v.tex_coord.y; + } + } + + // 计算影子底部中点并对齐角色脚部(与之前逻辑一致) + float shadowFootX = (vertices[2].position.x + vertices[3].position.x) / 2.0f; + float shadowFootY = shadowH; + float offsetX = roleFootX - shadowFootX; + float offsetY = roleFootY - shadowFootY; + + // 应用位置偏移 + for (auto &v : vertices) + { + v.position.x += offsetX; + v.position.y += offsetY; + } +} diff --git a/source/EngineFrame/Component/Sprite.h b/source/EngineFrame/Component/Sprite.h index b47b152..7c94038 100644 --- a/source/EngineFrame/Component/Sprite.h +++ b/source/EngineFrame/Component/Sprite.h @@ -11,67 +11,47 @@ class Game; class Sprite : public RenderBase { protected: - /* data */ RefPtr m_texture = nullptr; public: - /** - * @brief Sprite类的默认构造函数 - */ - Sprite(/* args */); - /** - * @brief Sprite类的带参数构造函数 - * @param imgPath 纹理图片路径 - * @param Index 索引值 - */ + Sprite() = default; Sprite(std::string imgPath, int Index); - /** - * @brief Sprite类的带参数构造函数 - * @param imgPath 纹理图片文件路径 - */ Sprite(std::string PngPath); - /** - * @brief Sprite类的析构函数 - */ ~Sprite(); - /** - * @brief 处理事件 - * @param e SDL事件指针 - */ - void HandleEvents(SDL_Event *e) override; - /** - * @brief 更新组件状态 - * @param deltaTime 时间增量 - */ - void Update(float deltaTime) override; - /** - * @brief 渲染组件 - * @param deltaTime 时间增量 - */ void Render() override; - /** - * @brief 清理组件资源 - */ + void PreRender() override; void Clear() override; + void Init() override; - /** - * @brief 获取纹理 - * @return SDL_Texture* 纹理指针 - */ RefPtr GetTexture(); - void SetIterationPos(VecFPos pos) override; - public: + // 渲染信息 RenderGuidanceInfo _RenderGuidanceInfo; + // 裁切数据 + SDL_Rect CropRect = {0, 0, 0, 0}; + // 裁切Flag + bool CropFlag = false; + // 阴影数据 + std::array vertices; + // 阴影Flag + bool ShadowFlag = false; std::string imgPath; int Index; public: // 计算渲染信息 void CalcRenderInfoLogic(); + // 设置裁切区域 + void SetClipRect(SDL_Rect clipRect); + // 取消裁切区域 + void UnsetClipRect(); // 设置混合模式 void SetBlendMode(SDL_BlendMode blendMode); // 获取混合模式 SDL_BlendMode GetBlendMode(); + // 设置阴影 + void SetShadow(); + // 计算阴影数据 + void CalculateShadowData(); }; diff --git a/source/EngineFrame/Render/Texture.cpp b/source/EngineFrame/Render/Texture.cpp index 5cf4aad..0ec4032 100644 --- a/source/EngineFrame/Render/Texture.cpp +++ b/source/EngineFrame/Render/Texture.cpp @@ -33,6 +33,8 @@ Texture::Texture(std::string PngPath) Texture::Texture(std::string imgPath, int Index) { + this->ImgPath = imgPath; + this->Index = Index; Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(imgPath); if (Info->lpImgName == "sprite/interface/base.img") return; @@ -50,7 +52,7 @@ Texture::Texture(std::string imgPath, int Index) int pitch = Buf.Width * 4; SDL_UpdateTexture(m_texture, NULL, Buf.PNGdata, pitch); SDL_SetTextureBlendMode(m_texture, SDL_BLENDMODE_BLEND); - SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeBest); + SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest); this->TexturePos.x = Buf.Xpos; this->TexturePos.y = Buf.Ypos; @@ -70,6 +72,12 @@ SDL_Texture *Texture::GetTexture() return m_texture; } +RefPtr Texture::GetTextureCopy() +{ + RefPtr nt = new Texture(this->ImgPath, this->Index); + return nt; +} + void Texture::SetBlendMode(SDL_BlendMode blendMode) { SDL_SetTextureBlendMode(m_texture, blendMode); diff --git a/source/EngineFrame/Render/Texture.h b/source/EngineFrame/Render/Texture.h index 668fd37..a2d6373 100644 --- a/source/EngineFrame/Render/Texture.h +++ b/source/EngineFrame/Render/Texture.h @@ -9,7 +9,8 @@ class Texture : public RefObject { private: SDL_Texture *m_texture = nullptr; - + std::string ImgPath = ""; + int Index = 0; public: VecSize TextureSize = {0, 0}; // 纹理大小 VecPos TexturePos = {0, 0}; // 纹理位置 @@ -25,5 +26,8 @@ public: void SetBlendMode(SDL_BlendMode blendMode); // 获取混合模式 SDL_BlendMode GetBlendMode(); - SDL_Texture *GetTexture(); // 获取纹理 + // 获取纹理 + SDL_Texture *GetTexture(); + // 获取一个拷贝的纹理 + RefPtr GetTextureCopy(); }; diff --git a/source/EngineFrame/Scene/Scene.cpp b/source/EngineFrame/Scene/Scene.cpp index b46a401..f2172b7 100644 --- a/source/EngineFrame/Scene/Scene.cpp +++ b/source/EngineFrame/Scene/Scene.cpp @@ -20,3 +20,8 @@ void Scene::Init() void Scene::Exit() { } + +RefPtr Scene::GetCamera() +{ + return nullptr; +} diff --git a/source/EngineFrame/Scene/Scene.h b/source/EngineFrame/Scene/Scene.h index 7ac8504..7bc1ee6 100644 --- a/source/EngineFrame/Scene/Scene.h +++ b/source/EngineFrame/Scene/Scene.h @@ -6,5 +6,6 @@ public: Scene(); virtual void Enter(); virtual void Exit(); + virtual RefPtr GetCamera(); void Init(); }; \ No newline at end of file diff --git a/source/Tool/Common.h b/source/Tool/Common.h index a544cee..e20543a 100644 --- a/source/Tool/Common.h +++ b/source/Tool/Common.h @@ -84,6 +84,7 @@ typedef struct VecPos y -= other.y; return *this; } + } VecPos; // 浮点数坐标向量 @@ -120,6 +121,12 @@ typedef struct VecFPos 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 @@ -212,38 +219,19 @@ typedef struct VecPos3 return x == other.x && y == other.y && z == other.z; } + bool operator!=(const VecPos3 &other) const + { + return x != other.x || y != other.y || z != other.z; + } + } 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; - } - -} VecFPos3; - typedef struct VecSpeed3 { - float x; - float y; - float z; - VecSpeed3(float x_ = 0, float y_ = 0, float z_ = 0) : x(x_), y(y_), z(z_) {} + int x; + int y; + int z; + VecSpeed3(int x_ = 0, int y_ = 0, int z_ = 0) : x(x_), y(y_), z(z_) {} VecSpeed3 operator+(const VecSpeed3 &other) const { diff --git a/source/Tool/Tool_String.cpp b/source/Tool/Tool_String.cpp index 0444d8e..6520be3 100644 --- a/source/Tool/Tool_String.cpp +++ b/source/Tool/Tool_String.cpp @@ -15,37 +15,6 @@ std::string Tool_toLowerCase(const std::string &str) { return std::tolower(c); }); return result; } -// GBK 转 UTF-8(基于 SDL2 的 SDL_iconv) -std::string Tool_Gbk2Utf8(const std::string &gbk_str) -{ - iconv_t cd = iconv_open("UTF-8", "GBK"); - if (cd == (iconv_t)-1) - { - throw std::runtime_error("Failed to open iconv conversion descriptor"); - } - - size_t in_bytes_left = gbk_str.size(); - char *in_buf = const_cast(gbk_str.data()); - - // 分配输出缓冲区(GBK转UTF-8后长度最多可能增长到原长的3倍) - size_t out_bytes_left = gbk_str.size() * 3 + 1; - std::string utf8_str(out_bytes_left, '\0'); - char *out_buf = &utf8_str[0]; - - // 执行转换 - size_t result = iconv(cd, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left); - iconv_close(cd); - - if (result == (size_t)-1) - { - throw std::runtime_error("Conversion failed!"); - } - - // 调整字符串大小以去除未使用的空间 - utf8_str.resize(utf8_str.size() - out_bytes_left); - return utf8_str; -} - std::string Tool_RegRealPath(const std::string &Path) { // 检查路径中是否包含"../" diff --git a/source/Tool/Tool_String.h b/source/Tool/Tool_String.h index e165d39..ac70571 100644 --- a/source/Tool/Tool_String.h +++ b/source/Tool/Tool_String.h @@ -5,8 +5,6 @@ std::string Tool_toLowerCase(const std::string &str); -std::string Tool_Gbk2Utf8(const std::string &gbk_str); - std::string Tool_RegRealPath(const std::string &Path); std::string Tool_TruncatePath(const std::string &path); \ No newline at end of file diff --git a/source_game/Actor/Map/GameMap.cpp b/source_game/Actor/Map/GameMap.cpp index 6d4fccf..18fb00c 100644 --- a/source_game/Actor/Map/GameMap.cpp +++ b/source_game/Actor/Map/GameMap.cpp @@ -4,6 +4,7 @@ #include "EngineFrame/Component/Animation.h" #include "Actor/Map/GameMapCamera.h" #include "Actor/Object/CharacterObject.h" +#include "EngineCore/Game.h" GameMap::GameMap() { @@ -45,12 +46,23 @@ void GameMap::InitConfiguration(std::string mapName) std::string Segment = Data.Get(); if (Segment == "[background pos]") { - _MapInfo["background_pos"] = std::stoi(Data.Get()); + int Offset = std::stoi(Data.Get()); + MapOffsetY = Offset; + _MapInfo["background_pos"] = Offset; } else if (Segment == "[map name]") { _MapInfo["name"] = Data.Get(); } + else if (Segment == "[limit map camera move]") + { + std::vector limit; + limit.push_back(std::stoi(Data.Get())); + limit.push_back(std::stoi(Data.Get())); + limit.push_back(std::stoi(Data.Get())); + limit.push_back(std::stoi(Data.Get())); + _MapInfo["limit_map_camera_move"] = limit; + } else if (Segment == "[wide mode camera vertical correction]") { _MapInfo["wide_mode_camer_vertical_correction"] = std::stoi(Data.Get()); @@ -196,7 +208,10 @@ void GameMap::InitTile() { if (!_MapInfo.count("tile")) return; + // 普通地板数量 int NormalTileCount = 0; + // 普通地板高度 + int NormalTileHeight = 560; std::vector tileArr = std::get>(_MapInfo["tile"]); if (tileArr.size() > 0) { @@ -224,7 +239,7 @@ void GameMap::InitTile() std::string path = extileArr[i]; RefPtr tile = new Tile(path); int xbuf = i % NormalTileCount * 224; - int ybuf = 560 - 200 - std::get(_MapInfo["background_pos"]) + 40 * (i / NormalTileCount); + int ybuf = -200 - std::get(_MapInfo["background_pos"]) + NormalTileHeight + 120 * (i / NormalTileCount); tile->SetPos(VecFPos{xbuf, ybuf}); _LayerMap["bottom"]->AddComponent(tile); } @@ -325,6 +340,7 @@ void GameMap::LoadMap(std::string mapName) void GameMap::Enter(Scene *scene) { + _Scene = scene; scene->AddChild(_LayerMap["contact"]); scene->AddChild(_LayerMap["distantback"]); scene->AddChild(_LayerMap["middleback"]); @@ -334,18 +350,6 @@ void GameMap::Enter(Scene *scene) scene->AddChild(_LayerMap["close"]); scene->AddChild(_LayerMap["cover"]); scene->AddChild(_LayerMap["max"]); - - // TODO - int HSU = 0; - _LayerMap["contact"]->SetPos(VecFPos{0, HSU}); - _LayerMap["distantback"]->SetPos(VecFPos{0, HSU}); - _LayerMap["middleback"]->SetPos(VecFPos{0, HSU}); - _LayerMap["bottom"]->SetPos(VecFPos{0, HSU}); - _LayerMap["closeback"]->SetPos(VecFPos{0, HSU}); - _LayerMap["normal"]->SetPos(VecFPos{0, HSU}); - _LayerMap["close"]->SetPos(VecFPos{0, HSU}); - _LayerMap["cover"]->SetPos(VecFPos{0, HSU}); - _LayerMap["max"]->SetPos(VecFPos{0, HSU}); } void GameMap::HandleEvents(SDL_Event *e) @@ -354,45 +358,68 @@ void GameMap::HandleEvents(SDL_Event *e) void GameMap::Update(float deltaTime) { - // this->_Camera->Update(deltaTime); + if (_Scene->GetCamera() == nullptr) + return; + GameMapCamera *Cam = (GameMapCamera *)(_Scene->GetCamera().Get()); + 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; - // if (this->_Camera) - // { - // int CamearXpos = this->_Camera->X; - // int CamearYpos = this->_Camera->Y; - // int CamearZpos = this->_Camera->Z; + // 获取摄像机可行区域限制 + auto limitIt = _MapInfo.find("limit_map_camera_move"); + if (limitIt != _MapInfo.end()) + { + std::vector limit = std::get>(_MapInfo["limit_map_camera_move"]); + int X_Limit_Min = limit[0]; + int X_Limit_Max = limit[1]; + int Y_Limit_Min = limit[2]; + int Y_Limit_Max = limit[3]; + // 应用地图边界限制 + targetX = std::clamp(targetX, width_Separate, _MapLength - width_Separate); + targetY = std::clamp(targetY, height_Separate, _MapHeight - height_Separate); + // 应用自定义摄像机移动限制 + if (X_Limit_Min != -1) + targetX = std::max(targetX, X_Limit_Min); + if (X_Limit_Max != -1) + targetX = std::min(targetX, X_Limit_Max); + if (Y_Limit_Min != -1) + targetY = std::max(targetY, Y_Limit_Min); + if (Y_Limit_Max != -1) + targetY = std::min(targetY, Y_Limit_Max); + } - // SDL_Log("Camera Pos: %d, %d", CamearXpos, CamearYpos); - // // 遍历 - // for (auto &pair : _LayerMap) - // { - // // pair.first 是 key(std::string) - // std::string key = pair.first; - // // pair.second 是 value(RefPtr) - // RefPtr &value = pair.second; - - // if (key == "distantback") - // { - // value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)}); - // } - // else - // { - // value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)}); - // } - // } - // } + // 更新图层位置 + for (auto &Layer : _LayerMap) + { + int posX = -targetX + width_Separate; + int posY = -targetY + height_Separate + MapOffsetY; + if (Layer.first == "distantback") + { + posX *= BackgroundMoveSpeed; + posX /= 100; + } + Layer.second->SetPos(VecFPos(posX, posY)); + } } void GameMap::AddObject(RefPtr object) { object->_AffMap = this; _LayerMap["normal"]->AddObject(object); + // 如果是角色对象 + if (object->m_objecttype == ObjectType::CHARACTER) + { + CharacterObject *chr = (CharacterObject *)(object.Get()); + _LayerMap["bottom"]->AddComponent(chr->_Shadow); + } } -VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset) +VecPos3 GameMap::CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset) { // 初始化结果为原坐标(默认不移动) - VecFPos3 result = CurPos; + VecPos3 result = CurPos; // 如果没有可移动区域限制,直接全量位移 if (_MovableArea.empty()) diff --git a/source_game/Actor/Map/GameMap.h b/source_game/Actor/Map/GameMap.h index e936539..8fea3ee 100644 --- a/source_game/Actor/Map/GameMap.h +++ b/source_game/Actor/Map/GameMap.h @@ -65,15 +65,18 @@ public: // 可行区域 std::vector _MovableArea; // 调试模式 - bool _DebugMode = true; + bool _DebugMode = false; public: // 图层Map 图层类型 显示对象 std::unordered_map> _LayerMap; - // 摄像机对象 - GameMapCamera *_Camera; - + // 所属场景 + Scene *_Scene = nullptr; + // 背景层移动速率 + int BackgroundMoveSpeed = 103; + // 地图Y轴偏移量 + int MapOffsetY = 0; public: GameMap(/* args */); ~GameMap(); @@ -91,5 +94,5 @@ public: public: // 检查是否可移动 - VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset); + VecPos3 CheckIsItMovable(VecPos3 CurPos, VecPos3 PosOffset); }; diff --git a/source_game/Actor/Map/GameMapCamera.cpp b/source_game/Actor/Map/GameMapCamera.cpp index e8d6094..598c34c 100644 --- a/source_game/Actor/Map/GameMapCamera.cpp +++ b/source_game/Actor/Map/GameMapCamera.cpp @@ -12,15 +12,10 @@ GameMapCamera::~GameMapCamera() { } -void GameMapCamera::SetParentMap(GameMap *map) -{ - this->_ParentMap = map; - _ParentMap->_Camera = this; -} - void GameMapCamera::SetFromActor(BaseObject *actor) { this->_FromActor = actor; + _FromActor->_AffCamera = this; } void GameMapCamera::Update(float deltaTime) @@ -28,41 +23,105 @@ void GameMapCamera::Update(float deltaTime) SyncPosByFromParent(deltaTime); } +void GameMapCamera::SyncPos(float deltaTime) +{ +} + void GameMapCamera::SetPos(int x, int y, int z) { - this->X = x; - this->Y = y; - this->Z = z; + // this->X = x; + // this->Y = y; + // this->Z = z; } void GameMapCamera::AddPos(int x, int y, int z) { - this->X += x; - this->Y += y; - this->Z += z; + // this->X += x; + // this->Y += y; + // this->Z += z; } void GameMapCamera::SyncPosByFromParent(float deltaTime) { - if (this->_FromActor != nullptr) + if (this->_FromActor == nullptr) { - float width_Separate = Game::GetInstance().Screen_W / 2; - float height_Separate = Game::GetInstance().Screen_H / 2; - int R_X, R_Y, R_Z; - R_X = std::fmin(std::fmax(this->_FromActor->Position.x, width_Separate), _ParentMap->_MapLength - width_Separate); - R_Y = std::fmin(std::fmax(this->_FromActor->Position.y, height_Separate), _ParentMap->_MapHeight - height_Separate); - R_Z = 0; - // SDL_Log("R_X: %d, R_Y: %d, R_Z: %d", R_X, R_Y, R_Z); - // SetPos(R_X, R_Y, R_Z); + return; + } + int targetX = _FromActor->Position.x; + int targetY = _FromActor->Position.y; - for (auto Layer : _ParentMap->_LayerMap) - { - if (Layer.first == "distantback") - { - Layer.second->SetPos(VecFPos((-R_X + width_Separate) * BackgroundMoveSpeed, -R_Y + R_Z + height_Separate + 120 + BackgroundOffset)); - } - else - Layer.second->SetPos(VecFPos((-R_X + width_Separate), -R_Y + R_Z + height_Separate + 120 + BackgroundOffset)); - } + if (_isSmoothMoving) + { + // 平滑移动计算 + VecPos targetPosition(targetX, targetY); + _currentPosition = SmoothDamp(_currentPosition, targetPosition, _velocity, _smoothTime, _maxSpeed, deltaTime); + } + else + { + _currentPosition.x = targetX; + _currentPosition.y = targetY; } } + +VecPos GameMapCamera::SmoothDamp(const VecPos ¤t, const VecPos &target, VecPos ¤tVelocity, float smoothTime, int maxSpeed, float deltaTime) +{ + // 平滑时间为0时直接返回目标位置并重置速度 + if (smoothTime <= 0.f) + { + currentVelocity = VecPos(0, 0); + return target; + } + + // 临界阻尼系数计算(避免过冲的核心参数) + const float omega = 2.0f / smoothTime; + const float x = omega * deltaTime; + const float expTerm = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x); + + // 计算当前位置与目标的差值 + VecPos delta = target - current; + + // 计算目标速度(基于阻尼公式和当前差值) + // 注意:这里先通过浮点计算保持精度,最后转换为整数 + 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; + VecPos targetVelocity(static_cast(tx), static_cast(ty)); + + // 应用速度衰减(指数平滑) + currentVelocity += targetVelocity; + currentVelocity = VecPos( + static_cast(currentVelocity.x * expTerm), + static_cast(currentVelocity.y * expTerm)); + + // 限制最大速度(如果设置了maxSpeed) + if (maxSpeed > 0) + { + // 计算当前速度的模长(浮点精度) + const float speedSq = static_cast(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y); + const float maxSpeedSq = static_cast(maxSpeed * maxSpeed); + + if (speedSq > maxSpeedSq) + { + // 速度超限,按比例缩放至最大速度 + const float scale = maxSpeed / sqrtf(speedSq); + currentVelocity = VecPos( + static_cast(currentVelocity.x * scale), + static_cast(currentVelocity.y * scale)); + } + } + + // 计算新位置(当前位置 + 速度 * 时间) + VecPos newPos = current + VecPos( + static_cast(currentVelocity.x * deltaTime), + static_cast(currentVelocity.y * deltaTime)); + + // 检测过冲:如果新位置已越过目标,直接锁定目标并重置速度 + // 点积 > 0 表示方向相反(已超过目标) + const int dot = delta.x * (newPos.x - target.x) + delta.y * (newPos.y - target.y); + if (dot > 0) + { + newPos = target; + currentVelocity = VecPos(0, 0); + } + + return newPos; +} \ No newline at end of file diff --git a/source_game/Actor/Map/GameMapCamera.h b/source_game/Actor/Map/GameMapCamera.h index 178cde7..172fa2f 100644 --- a/source_game/Actor/Map/GameMapCamera.h +++ b/source_game/Actor/Map/GameMapCamera.h @@ -5,41 +5,37 @@ class BaseObject; class GameMapCamera : public Actor { private: - GameMap *_ParentMap = nullptr; // 跟随对象 BaseObject *_FromActor = nullptr; public: - // 摄像机坐标 - int X = 0; - int Y = 0; - int Z = 0; - // 镜头可行坐标 - int MovableAreaX = 0; - int MovableAreaY = 0; - // 背景偏移量 - int BackgroundOffset = 0; - // 背景层移动速率 - int BackgroundMoveSpeed = 1.03; - // 人物中线长度 - int CharacterLineLength = 0; - // 摄像机朝向 - int Direction = 1; - // 摄像机朝向时间 - float DirectionTime = 0.f; + // 摄像机记录的跟随对象坐标 + 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 SetParentMap(GameMap *map); 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 ¤t, const VecPos &target, VecPos ¤tVelocity, float smoothTime, int maxSpeed, float deltaTime); }; diff --git a/source_game/Actor/Map/GameMapLayer.cpp b/source_game/Actor/Map/GameMapLayer.cpp index fe73de6..b811697 100644 --- a/source_game/Actor/Map/GameMapLayer.cpp +++ b/source_game/Actor/Map/GameMapLayer.cpp @@ -28,6 +28,7 @@ void GameMapLayer::Render() // 绘制填充矩形 SDL_RenderFillRect(renderer, &buf); } + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 250); } void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size) diff --git a/source_game/Actor/Map/GameMapLayer.h b/source_game/Actor/Map/GameMapLayer.h index 8c875a6..b7cdb8f 100644 --- a/source_game/Actor/Map/GameMapLayer.h +++ b/source_game/Actor/Map/GameMapLayer.h @@ -7,8 +7,6 @@ class BaseObject; class GameMapLayer : public Actor { private: - // 地图对象 - std::vector> ObjectManager; // 可行区域信息 std::vector FeasibleAreaInfoList; diff --git a/source_game/Actor/Map/Tile.cpp b/source_game/Actor/Map/Tile.cpp index 3106aad..daf738c 100644 --- a/source_game/Actor/Map/Tile.cpp +++ b/source_game/Actor/Map/Tile.cpp @@ -1,5 +1,6 @@ #include "Tile.h" #include "Tool/Tool_String.h" +#include "EngineCore/Game.h" Tile::Tile() { } @@ -12,6 +13,7 @@ Tile::Tile(std::string Path) : Sprite() m_texture = new Texture(std::get(m_data["path"]), std::get(m_data["idx"])); Sprite::Init(); + this->imgPath = Path; } Tile::~Tile() @@ -42,4 +44,4 @@ void Tile::InitInfo(std::string Path) m_data["pos"] = std::stoi(Data.Get()); } } -} \ No newline at end of file +} diff --git a/source_game/Actor/Object/ActiveObject.cpp b/source_game/Actor/Object/ActiveObject.cpp index 2f98ec7..b375d00 100644 --- a/source_game/Actor/Object/ActiveObject.cpp +++ b/source_game/Actor/Object/ActiveObject.cpp @@ -1,15 +1,12 @@ #include "ActiveObject.h" - -void ActiveObject::SetPosition(VecFPos3 pos) +void ActiveObject::SetPosition(VecPos3 pos) { BaseObject::SetPosition(pos); - BaseObject::SetRenderZOrder(this->Position.y); } -void ActiveObject::SetYpos(float y) +void ActiveObject::SetYpos(int y) { BaseObject::SetYpos(y); - BaseObject::SetRenderZOrder(this->Position.y); } void ActiveObject::SetSpeed(VecSpeed3 speed) @@ -24,27 +21,49 @@ VecSpeed3 ActiveObject::GetSpeed() void ActiveObject::Update(float deltaTime) { - // X Y 轴方向的加速度计算 - if (Speed.x != 0 || Speed.y != 0) + int IntegerDelta = static_cast(deltaTime * 1000); + const int Gravity = 1020; + + // X轴移动(含余数补偿) + if (Speed.x != 0) { - MoveBy(Speed.x * deltaTime, Speed.y * deltaTime, 0); + int totalX = Speed.x * IntegerDelta + Remainder.x; // 加上上次余数 + int moveX = totalX / 1000; // 整数部分为实际移动 + Remainder.x = totalX % 1000; // 保留余数(-999~999) + MoveBy(moveX, 0, 0); } - // Z轴只在Z轴大于0时 或者 Z轴速度向上时才会有重力 + + // Y轴移动(同上) + if (Speed.y != 0) + { + int totalY = Speed.y * IntegerDelta + Remainder.y; + int moveY = totalY / 1000; + Remainder.y = totalY % 1000; + MoveBy(0, moveY, 0); + } + + // Z轴重力与移动(含余数补偿) if (Position.z > 0 || Speed.z > 0) { - // TODO 还没有写角色属性 要读了角色属性以后才是正确的 - float Gravity = 68000.0 / 1000.0 * 15.0; - Speed.z -= Gravity * deltaTime; - MoveBy(0, 0, Speed.z * deltaTime); + // 重力对速度的影响(先更新Speed.z,含余数) + int speedZTotal = -Gravity * IntegerDelta + Remainder.z; // 注意负号(减速) + Speed.z += speedZTotal / 1000; // 速度的整数部分 + Remainder.z = speedZTotal % 1000; // 速度的余数 + + // 基于更新后的Speed.z计算移动量(同样含余数) + int moveZTotal = Speed.z * IntegerDelta + _zRemainderMove; // 新增_zRemainderMove记录移动余数 + int moveZ = moveZTotal / 1000; + _zRemainderMove = moveZTotal % 1000; + MoveBy(0, 0, moveZ); } - // Z轴小于0时要修正 else if (Position.z < 0) { Position.z = 0; Speed.z = 0; + Remainder.z = 0; // 重置余数 + _zRemainderMove = 0; SetPosition(Position); - SDL_LogError(0, "修正Z轴"); } - // 执行父类的更新 + BaseObject::Update(deltaTime); } diff --git a/source_game/Actor/Object/ActiveObject.h b/source_game/Actor/Object/ActiveObject.h index 81b54be..09f721f 100644 --- a/source_game/Actor/Object/ActiveObject.h +++ b/source_game/Actor/Object/ActiveObject.h @@ -5,11 +5,16 @@ class ActiveObject : public BaseObject { public: + // 三轴速度 VecSpeed3 Speed; + // 三轴移动余数 + VecPos3 Remainder; + int _zRemainderMove = 0; public: - void SetPosition(VecFPos3 pos) override; - void SetYpos(float y) override; + void + SetPosition(VecPos3 pos) override; + void SetYpos(int y) override; void SetSpeed(VecSpeed3 speed); VecSpeed3 GetSpeed(); diff --git a/source_game/Actor/Object/BaseObject.cpp b/source_game/Actor/Object/BaseObject.cpp index de9f2d6..1e9b84d 100644 --- a/source_game/Actor/Object/BaseObject.cpp +++ b/source_game/Actor/Object/BaseObject.cpp @@ -1,5 +1,7 @@ #include "BaseObject.h" #include "Actor/Map/GameMap.h" +#include "Actor/Map/GameMapCamera.h" + BaseObject::BaseObject() { Init(); // 调用了RenderBase的Init函数 对象才会被执行回调 @@ -10,41 +12,50 @@ BaseObject::~BaseObject() { } -void BaseObject::SetPosition(VecFPos3 pos) +void BaseObject::Update(float deltaTime) +{ + if (_AffCamera != nullptr) + { + _AffCamera->SyncPos(deltaTime); + } + Actor::Update(deltaTime); +} + +void BaseObject::SetPosition(VecPos3 pos) { if (pos.y != this->Position.y) { - SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序 + SetRenderZOrder(pos.y); // 设置渲染顺序 } this->Position = pos; - Actor::SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z}); + SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z}); } -VecFPos3 BaseObject::GetPosition() +VecPos3 BaseObject::GetPosition() { return this->Position; } -void BaseObject::SetXpos(float x) +void BaseObject::SetXpos(int x) { this->Position.x = x; - Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); + SetPos({this->Position.x, this->Position.y - this->Position.z}); } -void BaseObject::SetYpos(float y) +void BaseObject::SetYpos(int y) { if (y != this->Position.y) { - SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序 + SetRenderZOrder(y); // 设置渲染顺序 } this->Position.y = y; - Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); + SetPos({this->Position.x, this->Position.y - this->Position.z}); } -void BaseObject::SetZpos(float z) +void BaseObject::SetZpos(int z) { this->Position.z = z; - Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); + SetPos({this->Position.x, this->Position.y - this->Position.z}); } int BaseObject::GetXpos() @@ -62,28 +73,33 @@ int BaseObject::GetZpos() return this->Position.z; } -void BaseObject::MoveBy(VecFPos3 pos) +void BaseObject::MoveBy(VecPos3 pos) { // 只有moveby移动时判断所在地图中是否能够这样移动 - VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos); - if (pos.y != 0) + VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos); + if (RealPos.y != this->Position.y) { - SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序 + SetRenderZOrder(RealPos.y); // 设置渲染顺序 + } + if (RealPos != this->Position){ + this->Position = RealPos; + SetPos({this->Position.x, this->Position.y - this->Position.z}); } - this->Position = RealPos; - Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); } -void BaseObject::MoveBy(float x, float y, float z) +void BaseObject::MoveBy(int x, int y, int z) { // 只有moveby移动时判断所在地图中是否能够这样移动 - VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecFPos3({x, y, z})); - if (y != 0) + VecPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecPos3({x, y, z})); + if (RealPos.y != this->Position.y) { - SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序 + SetRenderZOrder(RealPos.y); // 设置渲染顺序 + } + if (RealPos != this->Position) + { + this->Position = RealPos; + SetPos({this->Position.x, this->Position.y - this->Position.z}); } - this->Position = RealPos; - Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); } void BaseObject::SetDirection(int dir) diff --git a/source_game/Actor/Object/BaseObject.h b/source_game/Actor/Object/BaseObject.h index 8a4538a..b7dd02d 100644 --- a/source_game/Actor/Object/BaseObject.h +++ b/source_game/Actor/Object/BaseObject.h @@ -1,38 +1,43 @@ #pragma once #include "EngineFrame/Actor/Actor.h" #include "Asset/Common/ObjectVars.h" +#include "Global/Global_Enum.h" class GameMap; +class GameMapCamera; class BaseObject : public Actor { -private: - /* data */ public: - VecFPos3 Position; // 位置 +public: + ObjectType m_objecttype; // 对象类型 + VecPos3 Position; // 位置 int Direction = 0; // 方向 GameMap *_AffMap = nullptr; // 所在地图 + GameMapCamera *_AffCamera = nullptr; // 跟随相机 public: BaseObject(/* args */); ~BaseObject(); + void Update(float deltaTime) override; + // 数据储存器 ObjectVars _ObjectVars; public: - virtual void SetPosition(VecFPos3 pos); - virtual void SetXpos(float x); - virtual void SetYpos(float y); - virtual void SetZpos(float z); + virtual void SetPosition(VecPos3 pos); + virtual void SetXpos(int x); + virtual void SetYpos(int y); + virtual void SetZpos(int z); - VecFPos3 GetPosition(); + VecPos3 GetPosition(); int GetXpos(); int GetYpos(); int GetZpos(); - void MoveBy(VecFPos3 pos); - void MoveBy(float x, float y, float z); - - void SetDirection(int dir); + virtual void MoveBy(VecPos3 pos); + virtual void MoveBy(int x, int y, int z); + + virtual void SetDirection(int dir); int GetDirection(); ObjectVars &GetObjectVars(); diff --git a/source_game/Actor/Object/CharacterObject.cpp b/source_game/Actor/Object/CharacterObject.cpp index b4472ef..9ac3aaa 100644 --- a/source_game/Actor/Object/CharacterObject.cpp +++ b/source_game/Actor/Object/CharacterObject.cpp @@ -5,21 +5,16 @@ CharacterObject::~CharacterObject() { } -void CharacterObject::Update(float deltaTime) -{ - ActiveObject::Update(deltaTime); -} - -void CharacterObject::Render() -{ - ActiveObject::Render(); -} - void CharacterObject::Construction(int job) { + m_objecttype = ObjectType::CHARACTER; + this->Job = job; // 创建装备管理器 _EquipmentManager = new Chr_Equipment(); _EquipmentManager->Init(this); + // 创建阴影对象 + _Shadow = new Chr_Shadow(); + _Shadow->Init(this); // 创建动画管理器(一定要先创建装备管理器再创建动画管理器 因为需要读取身上的装备) _AnimationManager = new Chr_Animation(); _AnimationManager->Init(this); @@ -55,3 +50,20 @@ void CharacterObject::ControllerMsg(CONTROLLER_MSG_TYPE msgType, void *msgData) this->_StateMachine->ChangeState(BASE_STATE::MOVE); } } + +void CharacterObject::Update(float deltaTime) +{ + ActiveObject::Update(deltaTime); +} + +void CharacterObject::SetPos(VecFPos pos) +{ + BaseObject::SetPos(pos); + if(_Shadow)_Shadow->SetPos(this->GetPos()); +} + +void CharacterObject::SetDirection(int dir) +{ + BaseObject::SetDirection(dir); + if(_Shadow)_Shadow->SetDirection(this->GetDirection()); +} diff --git a/source_game/Actor/Object/CharacterObject.h b/source_game/Actor/Object/CharacterObject.h index f5cbd62..2b202bf 100644 --- a/source_game/Actor/Object/CharacterObject.h +++ b/source_game/Actor/Object/CharacterObject.h @@ -4,6 +4,7 @@ #include "Asset/Character/Chr_Equipment.h" #include "Asset/Character/Chr_Controller.h" #include "Asset/Character/Chr_StateMachine.h" +#include "Asset/Character/Chr_Shadow.h" #include "Global/Global_Enum.h" class CharacterObject : public ActiveObject { @@ -16,6 +17,9 @@ public: RefPtr _Controller = nullptr; // 角色状态机 RefPtr _StateMachine = nullptr; + + // 角色阴影对象 + RefPtr _Shadow = nullptr; // 职业 int Job = 0; // 转职职业 如果是-1则没有转职 @@ -25,8 +29,6 @@ public: ~CharacterObject(); public: - void Update(float deltaTime) override; - void Render() override; // 通过职业创建角色 void Construction(int job); @@ -36,4 +38,8 @@ public: void DisableController(); // 控制器信息 void ControllerMsg(CONTROLLER_MSG_TYPE msgType, void* msgData); + + void Update(float deltaTime) override; + void SetPos(VecFPos pos) override; + void SetDirection(int dir) override; }; diff --git a/source_game/Actor/Object/MonsterObject.cpp b/source_game/Actor/Object/MonsterObject.cpp new file mode 100644 index 0000000..e251f20 --- /dev/null +++ b/source_game/Actor/Object/MonsterObject.cpp @@ -0,0 +1,10 @@ +#include "MonsterObject.h" +#include "Global/Global_Game.h" +void MonsterObject::Construction(int MonsterID) +{ + this->Id = MonsterID; + + // 创建动画管理器(一定要先创建装备管理器再创建动画管理器 因为需要读取身上的装备) + _AnimationManager = new Mon_Animation(); + _AnimationManager->Init(this); +} diff --git a/source_game/Actor/Object/MonsterObject.h b/source_game/Actor/Object/MonsterObject.h new file mode 100644 index 0000000..ad85780 --- /dev/null +++ b/source_game/Actor/Object/MonsterObject.h @@ -0,0 +1,18 @@ +#pragma once +#include "Actor/Object/ActiveObject.h" +#include "Global/Global_Enum.h" +#include "Asset/Monster/Mon_Animation.h" +class MonsterObject : public ActiveObject +{ +public: + // 怪物动画管理器 + RefPtr _AnimationManager = nullptr; + + // 怪物ID + int Id = 0; + +public: + // 通过ID创建怪物 + void Construction(int MonsterID); + +}; diff --git a/source_game/Asset/Character/Chr_Animation.cpp b/source_game/Asset/Character/Chr_Animation.cpp index d2bd1c7..32d646f 100644 --- a/source_game/Asset/Character/Chr_Animation.cpp +++ b/source_game/Asset/Character/Chr_Animation.cpp @@ -36,6 +36,14 @@ void Chr_Animation::CreateSkinmationBySlot(std::string actionName, std::string s Ani->SetRenderZOrder(Variation.Layer); this->AddChild(Ani); ActionAnis[actionName].push_back(Ani); + + // 构造一下阴影对象 + RefPtr ShadowAni = new Animation(path, FormatImgPath, Data); + ShadowAni->SetVisible(false); + // 皮肤统一设置阴影 + ShadowAni->SetShadow(); + chr_parent->_Shadow->AddChild(ShadowAni); + chr_parent->_Shadow->ActionAnis[actionName].push_back(ShadowAni); } } } @@ -106,11 +114,7 @@ void Chr_Animation::SetAction(std::string actionName) Ani->SetVisible(true); } CurrentActionTag = actionName; -} -void Chr_Animation::Update(float deltaTime) -{ - RenderBase::Update(deltaTime); - // SDL_Log("Position %d %d", this->GetTransform().position.x, this->GetTransform().position.y); - // SDL_Log("IterPosition %d %d", this->GetIterationTransform().position.x, this->GetIterationTransform().position.y); + // 设置阴影的动作 + chr_parent->_Shadow->SetAction(actionName); } diff --git a/source_game/Asset/Character/Chr_Animation.h b/source_game/Asset/Character/Chr_Animation.h index 73dd893..5fc170d 100644 --- a/source_game/Asset/Character/Chr_Animation.h +++ b/source_game/Asset/Character/Chr_Animation.h @@ -45,6 +45,4 @@ public: void Init(CharacterObject *parent); // 设置动作 void SetAction(std::string actionName); - - void Update(float deltaTime) override; }; diff --git a/source_game/Asset/Character/Chr_Shadow.cpp b/source_game/Asset/Character/Chr_Shadow.cpp new file mode 100644 index 0000000..3709967 --- /dev/null +++ b/source_game/Asset/Character/Chr_Shadow.cpp @@ -0,0 +1,44 @@ +#include "Chr_Shadow.h" +#include "Global/Global_Game.h" +#include "Actor/Object/CharacterObject.h" +#include "Asset/Character/Chr_Equipment.h" + +void Chr_Shadow::Init(CharacterObject *parent) +{ + // 调用RenderBase类的初始化 才能挂上标签 + RenderBase::Init(); + chr_parent = parent; + SetRenderZOrder(1000000); + SetPos(parent->GetPos()); +} + +void Chr_Shadow::SetAction(std::string actionName) +{ + // 先将原动作的Ani设置为不可见 + for (auto Ani : ActionAnis[CurrentActionTag]) + { + Ani->Reset(); + Ani->SetVisible(false); + } + // 再将新动作的Ani设置为可见 + for (auto Ani : ActionAnis[actionName]) + { + Ani->SetVisible(true); + } + CurrentActionTag = actionName; +} + +void Chr_Shadow::SetDirection(int dir) +{ + VecFPos sc = GetScale(); + // 朝右 + if (dir == 0) + { + SetScale(VecFPos({SDL_fabsf(sc.x), sc.y})); + } + // 朝左 + else if (dir == 1) + { + SetScale(VecFPos({-SDL_fabsf(sc.x), sc.y})); + } +} diff --git a/source_game/Asset/Character/Chr_Shadow.h b/source_game/Asset/Character/Chr_Shadow.h new file mode 100644 index 0000000..65fcfba --- /dev/null +++ b/source_game/Asset/Character/Chr_Shadow.h @@ -0,0 +1,29 @@ +#pragma once +#include "EngineFrame/Component/Animation.h" +#include +#include +#include +class CharacterObject; +class Chr_Shadow : public RenderBase +{ + // 动作动画集合 + using ActionAniList = std::map>>; + +private: + /* data */ +public: + // 父对象 + CharacterObject *chr_parent; + // 时装部位对应的动作动画集合 + ActionAniList ActionAnis; + // 当前动作Tag + std::string CurrentActionTag = "waiting"; + + // 初始化时 + void Init(CharacterObject *parent); + // 设置动作 + void SetAction(std::string actionName); + + // 设置方向 + void SetDirection(int dir); +}; diff --git a/source_game/Asset/Monster/Mon_Animation.cpp b/source_game/Asset/Monster/Mon_Animation.cpp new file mode 100644 index 0000000..83af2d8 --- /dev/null +++ b/source_game/Asset/Monster/Mon_Animation.cpp @@ -0,0 +1,39 @@ +#include "Mon_Animation.h" +#include "Actor/Object/MonsterObject.h" +#include "Global/Global_Game.h" +void Mon_Animation::Init(MonsterObject *parent) +{ + // 调用RenderBase类的初始化 才能挂上标签 + RenderBase::Init(); + parent->AddChild(this); + mon_parent = parent; + + GlobalMonsterScript::MonsterConfig Config = Global_Game::GetInstance().GetMonsterInfo(mon_parent->Id); + + // 遍历所有动作Ani路径 + for (const auto &pair : Config.animationPath) + { + std::string ActionName = pair.first; + std::string Path = std::string(Config.folder + Tool_toLowerCase(pair.second)); + + RefPtr Ani = new Animation(Path); + this->ActionAnis[ActionName] = Ani; + Ani->SetVisible(false); + this->AddChild(Ani); + } + + // 默认动作 + this->SetAction("waiting"); +} + +void Mon_Animation::SetAction(std::string actionName) +{ + // 先将原动作的Ani设置为不可见 + ActionAnis[CurrentActionTag]->Reset(); + ActionAnis[CurrentActionTag]->SetVisible(false); + + // 再将新动作的Ani设置为可见 + ActionAnis[actionName]->SetVisible(true); + + CurrentActionTag = actionName; +} diff --git a/source_game/Asset/Monster/Mon_Animation.h b/source_game/Asset/Monster/Mon_Animation.h new file mode 100644 index 0000000..3d1760a --- /dev/null +++ b/source_game/Asset/Monster/Mon_Animation.h @@ -0,0 +1,25 @@ +#pragma once +#include "EngineFrame/Component/Animation.h" +#include +#include +#include +class MonsterObject; +class Mon_Animation : public RenderBase +{ + // 动作动画集合 + using ActionAniList = std::map>; + +private: + // 父对象 + MonsterObject *mon_parent; + // 动作动画集合 + ActionAniList ActionAnis; + // 当前动作Tag + std::string CurrentActionTag = "waiting"; + +public: + // 初始化时 只完成基础的职业皮肤设置 + void Init(MonsterObject *parent); + // 设置动作 + void SetAction(std::string actionName); +}; diff --git a/source_game/Asset/Squirrel/Sqr_BaseObject.hpp b/source_game/Asset/Squirrel/Sqr_BaseObject.hpp index 7d8a487..75ae349 100644 --- a/source_game/Asset/Squirrel/Sqr_BaseObject.hpp +++ b/source_game/Asset/Squirrel/Sqr_BaseObject.hpp @@ -15,7 +15,7 @@ static SQInteger SQR_GetPosition(HSQUIRRELVM v) SQUserPointer ptr; sq_getuserpointer(v, 2, &ptr); BaseObject *obj = (BaseObject *)ptr; - VecFPos3 Pos = obj->GetPosition(); + VecPos3 Pos = obj->GetPosition(); sq_newtable(v); sq_pushstring(v, _SC("x"), -1); @@ -40,7 +40,7 @@ static SQInteger SQR_SetPosition(HSQUIRRELVM v) sq_getfloat(v, 3, &PosX); sq_getfloat(v, 4, &PosY); sq_getfloat(v, 5, &PosZ); - obj->SetPosition(VecFPos3(PosX, PosY, PosZ)); + obj->SetPosition(VecPos3(PosX, PosY, PosZ)); return 0; } diff --git a/source_game/Asset/Squirrel/Sqr_UI.hpp b/source_game/Asset/Squirrel/Sqr_UI.hpp new file mode 100644 index 0000000..b0db838 --- /dev/null +++ b/source_game/Asset/Squirrel/Sqr_UI.hpp @@ -0,0 +1,336 @@ +#pragma once +#include "squirrel/SquirrelEx.h" +#include "EngineFrame/Actor/Actor.h" +#include "EngineFrame/Component/Sprite.h" + +static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size)) +{ + Actor *Abli = (Actor *)p; + Abli->Release(); + return 0; +} +static SQInteger SQR_RegisterDestruction(HSQUIRRELVM v) +{ + // 析构函数测试 + SQUserPointer P; + sq_getuserpointer(v, 2, &P); + sq_setinstanceup(v, 3, P); + sq_setreleasehook(v, 3, _file_releasehook); + return 0; +} + +static SQInteger SQR_CreateActor(HSQUIRRELVM v) +{ + RefPtr act = new Actor(); + act->Retain(); + sq_pushuserpointer(v, act.Get()); + return 1; +} + +static SQInteger SQR_AddChild(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQUserPointer B_obj; + sq_getuserpointer(v, 3, &B_obj); + Actor *Aobj = (Actor *)A_obj; + Actor *Bobj = (Actor *)B_obj; + Aobj->AddChild(Bobj); + return 0; +} + +static SQInteger SQR_RemoveChild(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQUserPointer B_obj; + sq_getuserpointer(v, 3, &B_obj); + Actor *Aobj = (Actor *)A_obj; + Actor *Bobj = (Actor *)B_obj; + Aobj->RemoveChild(Bobj); + return 0; +} + +static SQInteger SQR_GetZOrder(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + sq_pushinteger(v, Aobj->GetRenderZOrder()); + return 1; +} + +static SQInteger SQR_SetZOrder(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQInteger Value; + sq_getinteger(v, 3, &Value); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetRenderZOrder(Value); + return 0; +} + +static SQInteger SQR_GetPos(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + VecFPos Pos = Aobj->GetPos(); + + sq_newtable(v); + sq_pushstring(v, _SC("x"), -1); + sq_pushfloat(v, Pos.x); + sq_newslot(v, 3, SQFalse); + sq_pushstring(v, _SC("y"), -1); + sq_pushfloat(v, Pos.y); + sq_newslot(v, 3, SQFalse); + return 1; +} + +static SQInteger SQR_SetPos(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + + if (sq_gettop(v) == 3) + { + VecFPos Pos; + sq_pushnull(v); // null iterator + while (SQ_SUCCEEDED(sq_next(v, 3))) + { + SQFloat value; + sq_getfloat(v, -1, &value); + const SQChar *key; + sq_getstring(v, -2, &key); + + if (strcmp(key, _SC("x")) == 0) + { + Pos.x = value; + } + else if (strcmp(key, _SC("y")) == 0) + { + Pos.y = value; + } + sq_pop(v, 2); + } + sq_pop(v, 1); + + Actor *Aobj = (Actor *)A_obj; + Aobj->SetPos(Pos); + } + else if (sq_gettop(v) == 4) + { + SQFloat X, Y; + sq_getfloat(v, 3, &X); + sq_getfloat(v, 4, &Y); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetPos(VecFPos(X, Y)); + } + return 0; +} + +static SQInteger SQR_GetAlpha(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + + sq_pushfloat(v, Aobj->GetAlpha()); + return 1; +} +static SQInteger SQR_SetAlpha(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQFloat Value; + sq_getfloat(v, 3, &Value); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetAlpha(Value); + return 0; +} + +static SQInteger SQR_GetScale(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + VecFPos Pos = Aobj->GetScale(); + sq_newtable(v); + sq_pushstring(v, _SC("x"), -1); + sq_pushfloat(v, Pos.x); + sq_newslot(v, 3, SQFalse); + sq_pushstring(v, _SC("y"), -1); + sq_pushfloat(v, Pos.y); + sq_newslot(v, 3, SQFalse); + return 1; +} + +static SQInteger SQR_SetScale(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + + if (sq_gettop(v) == 3) + { + VecFPos Pos; + sq_pushnull(v); // null iterator + while (SQ_SUCCEEDED(sq_next(v, 3))) + { + SQFloat value; + sq_getfloat(v, -1, &value); + const SQChar *key; + sq_getstring(v, -2, &key); + + if (strcmp(key, _SC("x")) == 0) + { + Pos.x = value; + } + else if (strcmp(key, _SC("y")) == 0) + { + Pos.y = value; + } + sq_pop(v, 2); + } + sq_pop(v, 1); + + Actor *Aobj = (Actor *)A_obj; + Aobj->SetScale(Pos); + } + else if (sq_gettop(v) == 4) + { + SQFloat X, Y; + sq_getfloat(v, 3, &X); + sq_getfloat(v, 4, &Y); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetScale(VecFPos(X, Y)); + } + return 0; +} + +static SQInteger SQR_GetRotation(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + + sq_pushfloat(v, Aobj->GetRotation()); +} + +static SQInteger SQR_SetRotation(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + SQFloat Value; + sq_getfloat(v, 3, &Value); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetRotation(Value); + return 0; +} + +static SQInteger SQR_GetSize(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + Actor *Aobj = (Actor *)A_obj; + VecSize Pos = Aobj->GetSize(); + + sq_newtable(v); + sq_pushstring(v, _SC("w"), -1); + sq_pushfloat(v, Pos.width); + sq_newslot(v, 3, SQFalse); + sq_pushstring(v, _SC("h"), -1); + sq_pushfloat(v, Pos.height); + sq_newslot(v, 3, SQFalse); + return 1; +} + +static SQInteger SQR_SetSize(HSQUIRRELVM v) +{ + SQUserPointer A_obj; + sq_getuserpointer(v, 2, &A_obj); + + if (sq_gettop(v) == 3) + { + VecSize Size; + sq_pushnull(v); // null iterator + while (SQ_SUCCEEDED(sq_next(v, 3))) + { + SQFloat value; + sq_getfloat(v, -1, &value); + const SQChar *key; + sq_getstring(v, -2, &key); + + if (strcmp(key, _SC("w")) == 0) + { + Size.width = value; + } + else if (strcmp(key, _SC("h")) == 0) + { + Size.height = value; + } + sq_pop(v, 2); + } + sq_pop(v, 1); + + Actor *Aobj = (Actor *)A_obj; + Aobj->SetSize(Size); + } + else if (sq_gettop(v) == 4) + { + SQFloat X, Y; + sq_getfloat(v, 3, &X); + sq_getfloat(v, 4, &Y); + Actor *Aobj = (Actor *)A_obj; + Aobj->SetSize(VecSize(X, Y)); + } + return 0; +} + +static SQInteger SQR_CreateSprite(HSQUIRRELVM v) +{ + const SQChar *ImgPath; + SQInteger Idx; + sq_getstring(v, 2, &ImgPath); + sq_getinteger(v, 3, &Idx); + RefPtr act = new Sprite(ImgPath, Idx); + act->Retain(); + sq_pushuserpointer(v, act.Get()); + return 1; +} + +static void RegisterUINutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v) +{ + sq_pushroottable(v); + sq_pushstring(v, funcName, -1); + sq_newclosure(v, funcAddr, 0); + sq_newslot(v, -3, false); + sq_poptop(v); +} + +static void RegisterUI() +{ + SDL_Log("初始化 UI函数-松鼠脚本!"); + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + + // 析构函数 + RegisterUINutApi(_SC("sq_RegisterDestruction"), SQR_RegisterDestruction, v); + + RegisterUINutApi(_SC("sq_CreateActor"), SQR_CreateActor, v); + RegisterUINutApi(_SC("sq_AddChild"), SQR_AddChild, v); + RegisterUINutApi(_SC("sq_RemoveChild"), SQR_RemoveChild, v); + RegisterUINutApi(_SC("sq_GetZOrder"), SQR_GetZOrder, v); + RegisterUINutApi(_SC("sq_SetZOrder"), SQR_SetZOrder, v); + RegisterUINutApi(_SC("sq_GetPos"), SQR_GetPos, v); + RegisterUINutApi(_SC("sq_SetPos"), SQR_SetPos, v); + RegisterUINutApi(_SC("sq_GetAlpha"), SQR_GetAlpha, v); + RegisterUINutApi(_SC("sq_SetAlpha"), SQR_SetAlpha, v); + RegisterUINutApi(_SC("sq_GetScale"), SQR_GetScale, v); + RegisterUINutApi(_SC("sq_SetScale"), SQR_SetScale, v); + RegisterUINutApi(_SC("sq_GetRotation"), SQR_GetRotation, v); + RegisterUINutApi(_SC("sq_SetRotation"), SQR_SetRotation, v); + RegisterUINutApi(_SC("sq_GetSize"), SQR_GetSize, v); + RegisterUINutApi(_SC("sq_SetSize"), SQR_SetSize, v); + + RegisterUINutApi(_SC("sq_CreateSprite"), SQR_CreateSprite, v); +} diff --git a/source_game/Asset/Squirrel/SquirrelManager.cpp b/source_game/Asset/Squirrel/SquirrelManager.cpp index be4db2c..366776d 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管理器!"); + // UI函数 + RegisterUI(); // 基础对象 RegisterBaseObject(); // 动态对象 diff --git a/source_game/Asset/Squirrel/SquirrelManager.h b/source_game/Asset/Squirrel/SquirrelManager.h index 14c7f33..18941ea 100644 --- a/source_game/Asset/Squirrel/SquirrelManager.h +++ b/source_game/Asset/Squirrel/SquirrelManager.h @@ -1,4 +1,5 @@ #pragma once +#include "Asset/Squirrel/Sqr_UI.hpp" #include "Asset/Squirrel/Sqr_BaseObject.hpp" #include "Asset/Squirrel/Sqr_ActiveObject.hpp" #include "Asset/Squirrel/Sqr_CharacterObject.hpp" diff --git a/source_game/Global/Global_Enum.h b/source_game/Global/Global_Enum.h index 55395e6..c985e4e 100644 --- a/source_game/Global/Global_Enum.h +++ b/source_game/Global/Global_Enum.h @@ -29,8 +29,11 @@ enum BASE_STATE JUMP, // 跳跃 }; - - - - - +// 对象类型 +enum ObjectType +{ + BASE = 0, // 基础对象 + ACTIVE = 1 << 0, // 动态对象 + CHARACTER = 1 << 1, // 角色对象 + MONSTER = 1 << 2 // 怪物对象 +}; diff --git a/source_game/Global/Global_Game.cpp b/source_game/Global/Global_Game.cpp index 29dba47..105d5d1 100644 --- a/source_game/Global/Global_Game.cpp +++ b/source_game/Global/Global_Game.cpp @@ -27,6 +27,8 @@ void Global_Game::InitGame() CharacterConfigs = GlobalCharacterScript::InitCharacterLst(); // 读取装备配置文件 EquipmentPathMap = GlobalEquipmentScript::InitEquipmentLst(); + // 读取怪物配置文件 + MonsterPathMap = GlobalMonsterScript::InitMonsterLst(); // 初始化松鼠脚本管理器 SquirrelManager::GetInstance().Init(); @@ -36,3 +38,24 @@ void Global_Game::InitGame() // 游戏初始化完成标志 InitFlag = true; } + +GlobalMonsterScript::MonsterConfig Global_Game::GetMonsterInfo(int id) +{ + if (!InitFlag) + { + SDL_LogError(0, "游戏未初始化"); + return GlobalMonsterScript::MonsterConfig(); + } + if (MonsterInfoMap.count(id)) + return MonsterInfoMap[id]; + if (!MonsterPathMap.count(id)) + { + SDL_LogError(0, "怪物ID不存在"); + return GlobalMonsterScript::MonsterConfig(); + } + std::string path = MonsterPathMap[id]; + GlobalMonsterScript::MonsterConfig MonsterConfig = GlobalMonsterScript::ReadMonsterConfig(path); + MonsterConfig.id = id; + MonsterInfoMap[id] = MonsterConfig; + return MonsterConfig; +} \ No newline at end of file diff --git a/source_game/Global/Global_Game.h b/source_game/Global/Global_Game.h index a26d89d..4981270 100644 --- a/source_game/Global/Global_Game.h +++ b/source_game/Global/Global_Game.h @@ -2,6 +2,7 @@ #include "EngineCore/Game.h" #include "Global/Script/CharacterConfig.h" #include "Global/Script/EquipmentConfig.h" +#include "Global/Script/MonsterConfig.h" #include "Global/Save/SavaManager.h" #include "Asset/Squirrel/SquirrelManager.h" class Global_Game @@ -36,6 +37,11 @@ public: // 装备路径Map std::map EquipmentPathMap; + // 怪物相关 + std::map MonsterPathMap; // 路径 + std::map MonsterInfoMap; // 信息 + GlobalMonsterScript::MonsterConfig GetMonsterInfo(int id); // 获取怪物信息 + // 游戏资源初始化标志 bool InitFlag = false; diff --git a/source_game/Global/Script/MonsterConfig.cpp b/source_game/Global/Script/MonsterConfig.cpp new file mode 100644 index 0000000..336d247 --- /dev/null +++ b/source_game/Global/Script/MonsterConfig.cpp @@ -0,0 +1,46 @@ +#include "MonsterConfig.h" +#include "Asset/AssetManager.h" +#include "Tool/Tool_String.h" + +namespace GlobalMonsterScript +{ + + std::map InitMonsterLst() + { + std::map EquipList; + ScriptData Data = AssetManager::GetInstance().GetScriptInfo("monster/monster.lst"); + while (!Data.IsEnd()) + { + std::string Index = Data.Get(); + std::string MonsterPath = std::string("monster/") + Data.Get(); + EquipList[std::stoi(Index)] = MonsterPath; + } + return EquipList; + } + MonsterConfig ReadMonsterConfig(std::string path) + { + MonsterConfig Config; + Config.folder = path.substr(0, path.find_last_of('/') + 1); + ScriptData Data = AssetManager::GetInstance().GetScriptInfo(path); + while (!Data.IsEnd()) + { + std::string Segment = Data.Get(); + if (Segment == "name") + { + Config.name = Data.Get(); + } + else if (Segment == "[动作动画]") + { + while (true) + { + std::string Ret = Data.Get(); + if (Ret == "[/动作动画]") + break; + std::string path = Data.Get(); + Config.animationPath[Ret] = path; + } + } + } + return Config; + } +} \ No newline at end of file diff --git a/source_game/Global/Script/MonsterConfig.h b/source_game/Global/Script/MonsterConfig.h new file mode 100644 index 0000000..f474ec7 --- /dev/null +++ b/source_game/Global/Script/MonsterConfig.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +namespace GlobalMonsterScript +{ + // 怪物配置 + struct MonsterConfig + { + //编号 + int id = -1; + //名称 + std::string name = "none"; + //动作动画 + std::map animationPath; + + + //所在文件夹 + std::string folder = "none"; + }; + + // 读取怪物列表 + std::map InitMonsterLst(); + // 读取怪物数据 + MonsterConfig ReadMonsterConfig(std::string path); +} \ No newline at end of file diff --git a/source_game/Scene/Scene_Loading_UI.cpp b/source_game/Scene/Scene_Loading_UI.cpp index 0cbe876..94e6f85 100644 --- a/source_game/Scene/Scene_Loading_UI.cpp +++ b/source_game/Scene/Scene_Loading_UI.cpp @@ -1,5 +1,5 @@ #include "Scene/Scene_Loading_UI.h" -#include "Scene/Scene_SelectCharacter_UI.hpp" +#include "Scene/Scene_MainUi.h" #include "Scene/Scene_Test.h" #include "Scene_Loading_UI.h" #include "EngineFrame/Component/Sprite.h" @@ -50,7 +50,7 @@ void Scene_Loading_UI::Update(float deltaTime) RefPtr scene = new Scene_Test; Game::GetInstance().ChangeScene(scene); // 设定UI层场景 - RefPtr sceneUI = new Scene_SelectCharacter_UI; + RefPtr sceneUI = new Scene_MainUi; Game::GetInstance().ChangeUIScene(sceneUI); } } diff --git a/source_game/Scene/Scene_MainUi.cpp b/source_game/Scene/Scene_MainUi.cpp new file mode 100644 index 0000000..edaef9c --- /dev/null +++ b/source_game/Scene/Scene_MainUi.cpp @@ -0,0 +1,72 @@ +#include "Scene_MainUi.h" +#include "Asset/Squirrel/SquirrelManager.h" + +void Scene_MainUi::Enter() +{ + Scene::Enter(); + + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + SQInteger top = sq_gettop(v); + sq_pushroottable(v); + sq_pushstring(v, _SC("_MainUI_Enter_"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_pushroottable(v); + sq_pushuserpointer(v, this); + sq_call(v, 2, SQFalse, SQTrue); + } + sq_settop(v, top); + +} + +void Scene_MainUi::HandleEvents(SDL_Event *e) +{ + Scene::HandleEvents(e); + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + SQInteger top = sq_gettop(v); + sq_pushroottable(v); + sq_pushstring(v, _SC("_MainUI_HandleEvents_"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_pushroottable(v); + sq_pushinteger(v, 1); + sq_call(v, 2, SQFalse, SQTrue); + } + sq_settop(v, top); +} + +void Scene_MainUi::Update(float deltaTime) +{ + Scene::Update(deltaTime); + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + SQInteger top = sq_gettop(v); + sq_pushroottable(v); + sq_pushstring(v, _SC("_MainUI_Update_"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_pushroottable(v); + sq_pushfloat(v, deltaTime); + sq_call(v, 2, SQFalse, SQTrue); + } + sq_settop(v, top); +} + +void Scene_MainUi::Exit() +{ + Scene::Exit(); + HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM(); + SQInteger top = sq_gettop(v); + sq_pushroottable(v); + sq_pushstring(v, _SC("_MainUI_Exit_"), -1); + if (SQ_SUCCEEDED(sq_get(v, -2))) + { + sq_pushroottable(v); + sq_call(v, 1, SQFalse, SQTrue); + } + sq_settop(v, top); +} + +void Scene_MainUi::Render() +{ + Scene::Render(); +} diff --git a/source_game/Scene/Scene_MainUi.h b/source_game/Scene/Scene_MainUi.h new file mode 100644 index 0000000..83058ae --- /dev/null +++ b/source_game/Scene/Scene_MainUi.h @@ -0,0 +1,15 @@ +#pragma once +#include "EngineFrame/Scene/Scene.h" + +class Scene_MainUi : public Scene +{ +private: + /* data */ +public: + void Enter() override; + void HandleEvents(SDL_Event *e) override; + void Update(float deltaTime) override; + void Exit() override; + + void Render() override; +}; diff --git a/source_game/Scene/Scene_SelectCharacter_UI.hpp b/source_game/Scene/Scene_SelectCharacter_UI.hpp deleted file mode 100644 index 37ad994..0000000 --- a/source_game/Scene/Scene_SelectCharacter_UI.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "EngineFrame/Scene/Scene.h" -#include "Asset/AssetManager.h" -#include "EngineFrame/Component/Animation.h" -#include "Actor/Map/GameMap.h" -#include "Actor/Map/GameMapCamera.h" -#include "Actor/Object/CharacterObject.h" -class Scene_SelectCharacter_UI : public Scene -{ -private: - /* data */ - GameMap *map; - RefPtr camera = nullptr; - -public: - Scene_SelectCharacter_UI(/* args */) { - - }; - ~Scene_SelectCharacter_UI() { - - }; - -public: - void Enter() override - { - map = new GameMap; - map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map"); - map->Enter(this); - - RefPtr obj = new CharacterObject(); - obj->SetPosition({620, 200, 0}); - // 构造为鬼剑士 - obj->Construction(0); - - map->AddObject(obj); - - camera = new GameMapCamera; - camera->SetParentMap(map); - camera->SetFromActor(obj.Get()); - AddChild(camera); - - // RefPtr actor = new Actor; - // actor->SetPos(VecFPos{450, 350}); - // // actor->SetAnchor(VecFPos{0.5, 0.5}); - // actor->SetScale(VecFPos{-1.f, 1.f}); - // AddChild(actor); - - // 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}); - // actor2->AddChild(ani4); - - // RefPtr ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani"); - // ani3->SetPos(VecPos{300, 300}); - // actor->AddChild(ani3); - - // RefPtr ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); - // ani4->SetPos(VecPos{300, 500}); - // actor->AddChild(ani4); - - // for (size_t i = 0; i < 400; i++) - // { - // RefPtr actor = new Actor; - // AddChild(actor); - - // // RefPtr ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani"); - // // actor->AddComponent(ani3); - // // ani3->SetRenderZOrder(1000); - - // // RefPtr ani = new Animation("common/anton/main.ani"); - // // actor->AddComponent(ani); - // // ani->SetRenderZOrder(500); - - // RefPtr sprite = new Sprite("sprite/item/avatar/swordman/0sm_acap.img", 0); - // actor->AddComponent(sprite); - // // RefPtr ani2 = new Animation("common/anton/face/0/0.ani"); - // // actor->AddComponent(ani2); - // // ani2->SetRenderZOrder(1000); - // } - - // SDL_Log("进入了选择角色场景!"); - }; - - void HandleEvents(SDL_Event *e) override - { - Scene::HandleEvents(e); - map->HandleEvents(e); - }; - void Update(float deltaTime) override - { - Scene::Update(deltaTime); - map->Update(deltaTime); - }; - // void Render() override; - // void Exit() override; -}; diff --git a/source_game/Scene/Scene_Test.cpp b/source_game/Scene/Scene_Test.cpp index 529f359..1f7fa7e 100644 --- a/source_game/Scene/Scene_Test.cpp +++ b/source_game/Scene/Scene_Test.cpp @@ -1,6 +1,7 @@ #include "Scene_Test.h" #include #include +#include Scene_Test::Scene_Test() { } @@ -12,22 +13,108 @@ Scene_Test::~Scene_Test() void Scene_Test::Enter() { - SDL_Log("进入测试场景!"); + map = new GameMap; + map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map"); + map->Enter(this); + + RefPtr obj = new CharacterObject(); + obj->SetPosition({1000, 300, 0}); + obj->Construction(0); + + 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"); + // actor->AddComponent(sprite); + + // RefPtr chr = new Sprite("sprite/character/swordman/equipment/avatar/skin/sm_body0000.img", 90); + // chr->SetPos(VecFPos{200, 100}); + // chr->SetAlpha(0.5); + // chr->SetShadow(); + // actor->AddComponent(chr); + + RefPtr Am = new AnimationManager; + RefPtr ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); + Am->AddAnimation(ani4); + + // Am->SetPos(VecFPos{200, 100}); + actor->AddChild(Am); + + // // 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}); + // actor->AddChild(ani4); + + // RefPtr ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani"); + // actor->AddChild(ani3); + + // RefPtr ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); + // ani4->SetPos(VecPos{300, 500}); + // actor->AddChild(ani4); + + // for (size_t i = 0; i < 400; i++) + // { + // RefPtr actor = new Actor; + // AddChild(actor); + + // // RefPtr ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani"); + // // actor->AddComponent(ani3); + // // ani3->SetRenderZOrder(1000); + + // // RefPtr ani = new Animation("common/anton/main.ani"); + // // actor->AddComponent(ani); + // // ani->SetRenderZOrder(500); + + // RefPtr sprite = new Sprite("sprite/item/avatar/swordman/0sm_acap.img", 0); + // actor->AddComponent(sprite); + // // RefPtr ani2 = new Animation("common/anton/face/0/0.ani"); + // // actor->AddComponent(ani2); + // // ani2->SetRenderZOrder(1000); + // } } void Scene_Test::HandleEvents(SDL_Event *e) { + Scene::HandleEvents(e); } void Scene_Test::Update(float deltaTime) { + Scene::Update(deltaTime); + // 摄像机中有检测宿主坐标 所以要在场景的update后调用以便读取到本帧最新的坐标 + if (_camera) + _camera->Update(deltaTime); + if (map) + map->Update(deltaTime); } void Scene_Test::Render() { + Scene::Render(); } void Scene_Test::Exit() { SDL_Log("Scene_Test::退出测试场景!当前引用计数%d", this->GetRefCount()); } + +RefPtr Scene_Test::GetCamera() +{ + return this->_camera; +} diff --git a/source_game/Scene/Scene_Test.h b/source_game/Scene/Scene_Test.h index e0239e9..5644985 100644 --- a/source_game/Scene/Scene_Test.h +++ b/source_game/Scene/Scene_Test.h @@ -1,10 +1,18 @@ #pragma once #include "EngineFrame/Scene/Scene.h" +#include "Asset/AssetManager.h" +#include "EngineFrame/Component/Animation.h" +#include "Actor/Map/GameMap.h" +#include "Actor/Map/GameMapCamera.h" +#include "Actor/Object/CharacterObject.h" +#include "Actor/Object/MonsterObject.h" class Scene_Test : public Scene { private: - /* data */ + GameMap *map = nullptr; + RefPtr _camera = nullptr; + public: Scene_Test(/* args */); ~Scene_Test(); @@ -15,7 +23,8 @@ public: void Update(float deltaTime) override; void Render() override; void Exit() override; - + RefPtr GetCamera() override; public: int MyId = 0; + };