修改OpenGl渲染底层之前
This commit is contained in:
@@ -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
|
||||
|
||||
1
Library/SDL_mixer
Submodule
1
Library/SDL_mixer
Submodule
Submodule Library/SDL_mixer added at 5d0ea9462b
1
Library/SDL_ttf
Submodule
1
Library/SDL_ttf
Submodule
Submodule Library/SDL_ttf added at 4a318f8dfa
1
Library/squirrel
Submodule
1
Library/squirrel
Submodule
Submodule Library/squirrel added at f77074bdd6
@@ -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脚本"
|
||||
}
|
||||
}
|
||||
@@ -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<void()> CallBack)
|
||||
{
|
||||
// 计算帧时间
|
||||
m_frameTime = 1000 / m_fps;
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
@@ -52,7 +49,7 @@ void Game::Init(std::function<void()> 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<void()> 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);
|
||||
|
||||
@@ -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<Debug_Actor> m_DebugInfoActor;
|
||||
// 帧间隔
|
||||
float m_deltaTime = 0.f;
|
||||
|
||||
public:
|
||||
// 屏幕宽高
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
#include "Debug_Actor.h"
|
||||
#include "EngineCore/Game.h"
|
||||
#include <string>
|
||||
|
||||
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<float>(i) / segments;
|
||||
float t2 = static_cast<float>(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<float>(dy) / radius;
|
||||
leftIndent = rightIndent = static_cast<int>(radius * (1.0f - sqrt(1.0f - ratio * ratio)));
|
||||
}
|
||||
|
||||
else if (dy > h - radius)
|
||||
{
|
||||
float ratio = static_cast<float>(dy - (h - radius)) / radius;
|
||||
leftIndent = rightIndent = static_cast<int>(radius * (1.0f - sqrt(1.0f - ratio * ratio)));
|
||||
}
|
||||
|
||||
SDL_RenderDrawLine(
|
||||
renderer,
|
||||
x + leftIndent, y + dy,
|
||||
x + w - rightIndent, y + dy);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
#include "EngineFrame/Component/Text.h"
|
||||
#include <SDL_ttf.h>
|
||||
#include <cstdint>
|
||||
|
||||
class Debug_Actor : public Actor
|
||||
{
|
||||
private:
|
||||
TTF_Font *m_debugFont;
|
||||
RefPtr<Text> FPS_Text;
|
||||
RefPtr<Text> DT_Text;
|
||||
RefPtr<Text> 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);
|
||||
};
|
||||
@@ -32,6 +32,18 @@ void BaseNode::Update(float deltaTime)
|
||||
}
|
||||
}
|
||||
|
||||
void BaseNode::PreRender()
|
||||
{
|
||||
// 如果有子节点并含有渲染标签,则渲染子节点
|
||||
RefPtr<BaseNode> 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<BaseNode> 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)
|
||||
|
||||
@@ -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<BaseNode> child);
|
||||
// 移除子对象
|
||||
void RemoveChild(RefPtr<BaseNode> 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();
|
||||
};
|
||||
|
||||
@@ -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<Animation> 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<Animation> 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<VecFPos>(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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
|
||||
|
||||
107
source/EngineFrame/Component/AnimationManager.cpp
Normal file
107
source/EngineFrame/Component/AnimationManager.cpp
Normal file
@@ -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<BaseNode> child = m_BaseNodes.GetFirst();
|
||||
while (child)
|
||||
{
|
||||
// 转换为Animation对象
|
||||
Animation *ani = static_cast<Animation *>(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<int>(m_RenderRect.x), // 子对象包围盒左上角X(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.y), // 子对象包围盒左上角Y(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.w), // 包围盒宽度(有效区域宽度)
|
||||
static_cast<int>(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<Animation> ani)
|
||||
{
|
||||
this->AddChild(ani);
|
||||
}
|
||||
|
||||
void AnimationManager::Clear()
|
||||
{
|
||||
this->RemoveAllChild();
|
||||
}
|
||||
21
source/EngineFrame/Component/AnimationManager.h
Normal file
21
source/EngineFrame/Component/AnimationManager.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include <vector>
|
||||
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<Animation> ani);
|
||||
// 清空Ani
|
||||
void Clear();
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -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<Texture> 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_RendererFlip>(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<int>(frameWidth * Anchor.x);
|
||||
int origAnchorOffsetY = static_cast<int>(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<int>(frameWidth * absScaleX);
|
||||
int scaledHeight = static_cast<int>(frameHeight * absScaleY);
|
||||
float scaledWidth = frameWidth * absScaleX;
|
||||
float scaledHeight = frameHeight * absScaleY;
|
||||
// 缩放后的锚点偏移
|
||||
int scaledAnchorOffsetX = static_cast<int>(origAnchorOffsetX * absScaleX);
|
||||
int scaledAnchorOffsetY = static_cast<int>(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<int, 6> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,67 +11,47 @@ class Game;
|
||||
class Sprite : public RenderBase
|
||||
{
|
||||
protected:
|
||||
/* data */
|
||||
RefPtr<Texture> 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<Texture> GetTexture();
|
||||
|
||||
void SetIterationPos(VecFPos pos) override;
|
||||
|
||||
public:
|
||||
// 渲染信息
|
||||
RenderGuidanceInfo _RenderGuidanceInfo;
|
||||
// 裁切数据
|
||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
||||
// 裁切Flag
|
||||
bool CropFlag = false;
|
||||
// 阴影数据
|
||||
std::array<SDL_Vertex, 4> 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();
|
||||
};
|
||||
|
||||
@@ -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> Texture::GetTextureCopy()
|
||||
{
|
||||
RefPtr<Texture> nt = new Texture(this->ImgPath, this->Index);
|
||||
return nt;
|
||||
}
|
||||
|
||||
void Texture::SetBlendMode(SDL_BlendMode blendMode)
|
||||
{
|
||||
SDL_SetTextureBlendMode(m_texture, blendMode);
|
||||
|
||||
@@ -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<Texture> GetTextureCopy();
|
||||
};
|
||||
|
||||
@@ -20,3 +20,8 @@ void Scene::Init()
|
||||
void Scene::Exit()
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<BaseNode> Scene::GetCamera()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@ public:
|
||||
Scene();
|
||||
virtual void Enter();
|
||||
virtual void Exit();
|
||||
virtual RefPtr<BaseNode> GetCamera();
|
||||
void Init();
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<char *>(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)
|
||||
{
|
||||
// 检查路径中是否包含"../"
|
||||
|
||||
@@ -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);
|
||||
@@ -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<int> 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<std::string> tileArr = std::get<std::vector<std::string>>(_MapInfo["tile"]);
|
||||
if (tileArr.size() > 0)
|
||||
{
|
||||
@@ -224,7 +239,7 @@ void GameMap::InitTile()
|
||||
std::string path = extileArr[i];
|
||||
RefPtr<Tile> tile = new Tile(path);
|
||||
int xbuf = i % NormalTileCount * 224;
|
||||
int ybuf = 560 - 200 - std::get<int>(_MapInfo["background_pos"]) + 40 * (i / NormalTileCount);
|
||||
int ybuf = -200 - std::get<int>(_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<int> limit = std::get<std::vector<int>>(_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<GameMapLayer>)
|
||||
// RefPtr<GameMapLayer> &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<BaseObject> 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())
|
||||
|
||||
@@ -65,15 +65,18 @@ public:
|
||||
// 可行区域
|
||||
std::vector<SDL_FRect> _MovableArea;
|
||||
// 调试模式
|
||||
bool _DebugMode = true;
|
||||
bool _DebugMode = false;
|
||||
|
||||
public:
|
||||
// 图层Map 图层类型 显示对象
|
||||
std::unordered_map<std::string, RefPtr<GameMapLayer>> _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);
|
||||
};
|
||||
|
||||
@@ -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<int>(tx), static_cast<int>(ty));
|
||||
|
||||
// 应用速度衰减(指数平滑)
|
||||
currentVelocity += targetVelocity;
|
||||
currentVelocity = VecPos(
|
||||
static_cast<int>(currentVelocity.x * expTerm),
|
||||
static_cast<int>(currentVelocity.y * expTerm));
|
||||
|
||||
// 限制最大速度(如果设置了maxSpeed)
|
||||
if (maxSpeed > 0)
|
||||
{
|
||||
// 计算当前速度的模长(浮点精度)
|
||||
const float speedSq = static_cast<float>(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y);
|
||||
const float maxSpeedSq = static_cast<float>(maxSpeed * maxSpeed);
|
||||
|
||||
if (speedSq > maxSpeedSq)
|
||||
{
|
||||
// 速度超限,按比例缩放至最大速度
|
||||
const float scale = maxSpeed / sqrtf(speedSq);
|
||||
currentVelocity = VecPos(
|
||||
static_cast<int>(currentVelocity.x * scale),
|
||||
static_cast<int>(currentVelocity.y * scale));
|
||||
}
|
||||
}
|
||||
|
||||
// 计算新位置(当前位置 + 速度 * 时间)
|
||||
VecPos newPos = current + VecPos(
|
||||
static_cast<int>(currentVelocity.x * deltaTime),
|
||||
static_cast<int>(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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -7,8 +7,6 @@ class BaseObject;
|
||||
class GameMapLayer : public Actor
|
||||
{
|
||||
private:
|
||||
// 地图对象
|
||||
std::vector<RefPtr<Component>> ObjectManager;
|
||||
// 可行区域信息
|
||||
std::vector<SDL_Rect> FeasibleAreaInfoList;
|
||||
|
||||
|
||||
@@ -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<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
|
||||
Sprite::Init();
|
||||
this->imgPath = Path;
|
||||
}
|
||||
|
||||
Tile::~Tile()
|
||||
|
||||
@@ -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<int>(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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
virtual void MoveBy(VecPos3 pos);
|
||||
virtual void MoveBy(int x, int y, int z);
|
||||
|
||||
void SetDirection(int dir);
|
||||
virtual void SetDirection(int dir);
|
||||
int GetDirection();
|
||||
|
||||
ObjectVars &GetObjectVars();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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<Chr_Controller> _Controller = nullptr;
|
||||
// 角色状态机
|
||||
RefPtr<Chr_StateMachine> _StateMachine = nullptr;
|
||||
|
||||
// 角色阴影对象
|
||||
RefPtr<Chr_Shadow> _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;
|
||||
};
|
||||
|
||||
10
source_game/Actor/Object/MonsterObject.cpp
Normal file
10
source_game/Actor/Object/MonsterObject.cpp
Normal file
@@ -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);
|
||||
}
|
||||
18
source_game/Actor/Object/MonsterObject.h
Normal file
18
source_game/Actor/Object/MonsterObject.h
Normal file
@@ -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<Mon_Animation> _AnimationManager = nullptr;
|
||||
|
||||
// 怪物ID
|
||||
int Id = 0;
|
||||
|
||||
public:
|
||||
// 通过ID创建怪物
|
||||
void Construction(int MonsterID);
|
||||
|
||||
};
|
||||
@@ -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<Animation> 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);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,4 @@ public:
|
||||
void Init(CharacterObject *parent);
|
||||
// 设置动作
|
||||
void SetAction(std::string actionName);
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
};
|
||||
|
||||
44
source_game/Asset/Character/Chr_Shadow.cpp
Normal file
44
source_game/Asset/Character/Chr_Shadow.cpp
Normal file
@@ -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}));
|
||||
}
|
||||
}
|
||||
29
source_game/Asset/Character/Chr_Shadow.h
Normal file
29
source_game/Asset/Character/Chr_Shadow.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
class CharacterObject;
|
||||
class Chr_Shadow : public RenderBase
|
||||
{
|
||||
// 动作动画集合
|
||||
using ActionAniList = std::map<std::string, std::vector<RefPtr<Animation>>>;
|
||||
|
||||
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);
|
||||
};
|
||||
39
source_game/Asset/Monster/Mon_Animation.cpp
Normal file
39
source_game/Asset/Monster/Mon_Animation.cpp
Normal file
@@ -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<Animation> 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;
|
||||
}
|
||||
25
source_game/Asset/Monster/Mon_Animation.h
Normal file
25
source_game/Asset/Monster/Mon_Animation.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
class MonsterObject;
|
||||
class Mon_Animation : public RenderBase
|
||||
{
|
||||
// 动作动画集合
|
||||
using ActionAniList = std::map<std::string, RefPtr<Animation>>;
|
||||
|
||||
private:
|
||||
// 父对象
|
||||
MonsterObject *mon_parent;
|
||||
// 动作动画集合
|
||||
ActionAniList ActionAnis;
|
||||
// 当前动作Tag
|
||||
std::string CurrentActionTag = "waiting";
|
||||
|
||||
public:
|
||||
// 初始化时 只完成基础的职业皮肤设置
|
||||
void Init(MonsterObject *parent);
|
||||
// 设置动作
|
||||
void SetAction(std::string actionName);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
336
source_game/Asset/Squirrel/Sqr_UI.hpp
Normal file
336
source_game/Asset/Squirrel/Sqr_UI.hpp
Normal file
@@ -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<Actor> 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<Sprite> 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);
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
void SquirrelManager::Init()
|
||||
{
|
||||
SDL_Log("开始初始化sqr管理器!");
|
||||
// UI函数
|
||||
RegisterUI();
|
||||
// 基础对象
|
||||
RegisterBaseObject();
|
||||
// 动态对象
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -29,8 +29,11 @@ enum BASE_STATE
|
||||
JUMP, // 跳跃
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 对象类型
|
||||
enum ObjectType
|
||||
{
|
||||
BASE = 0, // 基础对象
|
||||
ACTIVE = 1 << 0, // 动态对象
|
||||
CHARACTER = 1 << 1, // 角色对象
|
||||
MONSTER = 1 << 2 // 怪物对象
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<int, std::string> EquipmentPathMap;
|
||||
|
||||
// 怪物相关
|
||||
std::map<int, std::string> MonsterPathMap; // 路径
|
||||
std::map<int, GlobalMonsterScript::MonsterConfig> MonsterInfoMap; // 信息
|
||||
GlobalMonsterScript::MonsterConfig GetMonsterInfo(int id); // 获取怪物信息
|
||||
|
||||
// 游戏资源初始化标志
|
||||
bool InitFlag = false;
|
||||
|
||||
|
||||
46
source_game/Global/Script/MonsterConfig.cpp
Normal file
46
source_game/Global/Script/MonsterConfig.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "MonsterConfig.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "Tool/Tool_String.h"
|
||||
|
||||
namespace GlobalMonsterScript
|
||||
{
|
||||
|
||||
std::map<int, std::string> InitMonsterLst()
|
||||
{
|
||||
std::map<int, std::string> 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;
|
||||
}
|
||||
}
|
||||
26
source_game/Global/Script/MonsterConfig.h
Normal file
26
source_game/Global/Script/MonsterConfig.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace GlobalMonsterScript
|
||||
{
|
||||
// 怪物配置
|
||||
struct MonsterConfig
|
||||
{
|
||||
//编号
|
||||
int id = -1;
|
||||
//名称
|
||||
std::string name = "none";
|
||||
//动作动画
|
||||
std::map<std::string, std::string> animationPath;
|
||||
|
||||
|
||||
//所在文件夹
|
||||
std::string folder = "none";
|
||||
};
|
||||
|
||||
// 读取怪物列表
|
||||
std::map<int, std::string> InitMonsterLst();
|
||||
// 读取怪物数据
|
||||
MonsterConfig ReadMonsterConfig(std::string path);
|
||||
}
|
||||
@@ -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_Test> scene = new Scene_Test;
|
||||
Game::GetInstance().ChangeScene(scene);
|
||||
// 设定UI层场景
|
||||
RefPtr<Scene_SelectCharacter_UI> sceneUI = new Scene_SelectCharacter_UI;
|
||||
RefPtr<Scene_MainUi> sceneUI = new Scene_MainUi;
|
||||
Game::GetInstance().ChangeUIScene(sceneUI);
|
||||
}
|
||||
}
|
||||
|
||||
72
source_game/Scene/Scene_MainUi.cpp
Normal file
72
source_game/Scene/Scene_MainUi.cpp
Normal file
@@ -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();
|
||||
}
|
||||
15
source_game/Scene/Scene_MainUi.h
Normal file
15
source_game/Scene/Scene_MainUi.h
Normal file
@@ -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;
|
||||
};
|
||||
@@ -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<GameMapCamera> 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<CharacterObject> 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> 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<Actor> actor2 = new Actor;
|
||||
// actor->AddChild(actor2);
|
||||
|
||||
// RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani");
|
||||
// // ani4->SetScale(VecFPos{-1.0, 1.0});
|
||||
// actor2->AddChild(ani4);
|
||||
|
||||
// RefPtr<Animation> ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani");
|
||||
// ani3->SetPos(VecPos{300, 300});
|
||||
// actor->AddChild(ani3);
|
||||
|
||||
// RefPtr<Animation> 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> actor = new Actor;
|
||||
// AddChild(actor);
|
||||
|
||||
// // RefPtr<Animation> ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani");
|
||||
// // actor->AddComponent(ani3);
|
||||
// // ani3->SetRenderZOrder(1000);
|
||||
|
||||
// // RefPtr<Animation> ani = new Animation("common/anton/main.ani");
|
||||
// // actor->AddComponent(ani);
|
||||
// // ani->SetRenderZOrder(500);
|
||||
|
||||
// RefPtr<Sprite> sprite = new Sprite("sprite/item/avatar/swordman/0sm_acap.img", 0);
|
||||
// actor->AddComponent(sprite);
|
||||
// // RefPtr<Animation> 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;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Scene_Test.h"
|
||||
#include <memory>
|
||||
#include <EngineCore/Game.h>
|
||||
#include <EngineFrame/Component/AnimationManager.h>
|
||||
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<CharacterObject> obj = new CharacterObject();
|
||||
obj->SetPosition({1000, 300, 0});
|
||||
obj->Construction(0);
|
||||
|
||||
RefPtr<MonsterObject> 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> actor = new Actor;
|
||||
AddChild(actor);
|
||||
// RefPtr<Sprite> sprite = new Sprite("ImagePacks2/test_white_background.png");
|
||||
// actor->AddComponent(sprite);
|
||||
|
||||
// RefPtr<Sprite> 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<AnimationManager> Am = new AnimationManager;
|
||||
RefPtr<Animation> 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<Actor> actor2 = new Actor;
|
||||
// actor->AddChild(actor2);
|
||||
|
||||
// RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani");
|
||||
// // ani4->SetScale(VecFPos{-1.0, 1.0});
|
||||
// actor->AddChild(ani4);
|
||||
|
||||
// RefPtr<Animation> ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani");
|
||||
// actor->AddChild(ani3);
|
||||
|
||||
// RefPtr<Animation> 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> actor = new Actor;
|
||||
// AddChild(actor);
|
||||
|
||||
// // RefPtr<Animation> ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani");
|
||||
// // actor->AddComponent(ani3);
|
||||
// // ani3->SetRenderZOrder(1000);
|
||||
|
||||
// // RefPtr<Animation> ani = new Animation("common/anton/main.ani");
|
||||
// // actor->AddComponent(ani);
|
||||
// // ani->SetRenderZOrder(500);
|
||||
|
||||
// RefPtr<Sprite> sprite = new Sprite("sprite/item/avatar/swordman/0sm_acap.img", 0);
|
||||
// actor->AddComponent(sprite);
|
||||
// // RefPtr<Animation> 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<BaseNode> Scene_Test::GetCamera()
|
||||
{
|
||||
return this->_camera;
|
||||
}
|
||||
|
||||
@@ -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<GameMapCamera> _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<BaseNode> GetCamera() override;
|
||||
public:
|
||||
int MyId = 0;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user