修改底层渲染为OpenGL
This commit is contained in:
File diff suppressed because it is too large
Load Diff
1178
Library/src/glad.c
1178
Library/src/glad.c
File diff suppressed because it is too large
Load Diff
@@ -20,17 +20,25 @@ void Game::Init(std::function<void()> CallBack)
|
|||||||
SDL_JoystickEventState(SDL_ENABLE);
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
SDL_JoystickOpen(0);
|
SDL_JoystickOpen(0);
|
||||||
|
|
||||||
|
// 设置OpenGL ES 3.2上下文属性
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // 双缓冲
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
|
||||||
{
|
{
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not initialize! Error: %s\n", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not initialize! Error: %s\n", SDL_GetError());
|
||||||
m_isRunning = false;
|
m_isRunning = false;
|
||||||
}
|
}
|
||||||
m_window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Screen_W, Screen_H, SDL_WINDOW_SHOWN);
|
m_window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Screen_W, Screen_H, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
|
||||||
if (m_window == nullptr)
|
if (m_window == nullptr)
|
||||||
{
|
{
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Window! Error: %s\n", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Window! Error: %s\n", SDL_GetError());
|
||||||
m_isRunning = false;
|
m_isRunning = false;
|
||||||
}
|
}
|
||||||
|
// 关闭原生鼠标
|
||||||
|
SDL_ShowCursor(0);
|
||||||
// 打开所有检测到的控制器
|
// 打开所有检测到的控制器
|
||||||
int numControllers = SDL_NumJoysticks();
|
int numControllers = SDL_NumJoysticks();
|
||||||
for (int i = 0; i < numControllers; i++)
|
for (int i = 0; i < numControllers; i++)
|
||||||
@@ -48,16 +56,9 @@ void Game::Init(std::function<void()> CallBack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建渲染器
|
// 创建OpenGL渲染器
|
||||||
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
m_renderer = new RenderManager(m_window);
|
||||||
if (m_renderer == nullptr)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Renderer! Error: %s\n", SDL_GetError());
|
|
||||||
m_isRunning = false;
|
|
||||||
}
|
|
||||||
// 启用渲染器的混合功能(必须,否则纹理混合模式无效)
|
|
||||||
SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_BLEND);
|
|
||||||
// SDL_RenderSetScale(m_renderer, 1.2, 1.2);
|
|
||||||
IMG_Init(IMG_INIT_PNG);
|
IMG_Init(IMG_INIT_PNG);
|
||||||
|
|
||||||
// 初始化SDL_mixer,支持OGG格式
|
// 初始化SDL_mixer,支持OGG格式
|
||||||
@@ -149,7 +150,9 @@ void Game::HandleEvents(SDL_Event *e)
|
|||||||
|
|
||||||
void Game::Update(float deltaTime)
|
void Game::Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (m_scene != nullptr)
|
//调用松鼠的更新
|
||||||
|
SquirrelEx::GetInstance().Update(deltaTime);
|
||||||
|
if (m_scene != nullptr)
|
||||||
m_scene->Update(deltaTime);
|
m_scene->Update(deltaTime);
|
||||||
if (m_uiScene != nullptr)
|
if (m_uiScene != nullptr)
|
||||||
m_uiScene->Update(deltaTime);
|
m_uiScene->Update(deltaTime);
|
||||||
@@ -167,12 +170,12 @@ void Game::Render()
|
|||||||
m_uiScene->PreRender();
|
m_uiScene->PreRender();
|
||||||
|
|
||||||
// 清空渲染器后渲染
|
// 清空渲染器后渲染
|
||||||
SDL_RenderClear(m_renderer);
|
m_renderer->ClearScreen();
|
||||||
if (m_scene != nullptr)
|
if (m_scene != nullptr)
|
||||||
m_scene->Render();
|
m_scene->Render();
|
||||||
if (m_uiScene != nullptr)
|
if (m_uiScene != nullptr)
|
||||||
m_uiScene->Render();
|
m_uiScene->Render();
|
||||||
SDL_RenderPresent(m_renderer);
|
m_renderer->SwapBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::Clear()
|
void Game::Clear()
|
||||||
@@ -188,7 +191,6 @@ void Game::Clear()
|
|||||||
}
|
}
|
||||||
m_uiScene = nullptr;
|
m_uiScene = nullptr;
|
||||||
IMG_Quit();
|
IMG_Quit();
|
||||||
SDL_DestroyRenderer(m_renderer);
|
|
||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
@@ -213,7 +215,7 @@ void Game::ChangeUIScene(RefPtr<Scene> scene)
|
|||||||
m_uiScene->Enter();
|
m_uiScene->Enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Renderer *Game::GetRenderer()
|
RenderManager *Game::GetRenderer()
|
||||||
{
|
{
|
||||||
return m_renderer;
|
return m_renderer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "EngineFrame/Scene/Scene.h"
|
#include "EngineFrame/Scene/Scene.h"
|
||||||
|
#include "EngineFrame/Render/RenderManager.h"
|
||||||
#include "Tool/RefPtr.h"
|
#include "Tool/RefPtr.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
@@ -55,7 +56,7 @@ public:
|
|||||||
// 设定UI层场景对象
|
// 设定UI层场景对象
|
||||||
void ChangeUIScene(RefPtr<Scene> scene);
|
void ChangeUIScene(RefPtr<Scene> scene);
|
||||||
|
|
||||||
SDL_Renderer *GetRenderer();
|
RenderManager* GetRenderer();
|
||||||
|
|
||||||
// 每秒帧率
|
// 每秒帧率
|
||||||
u32 m_fps;
|
u32 m_fps;
|
||||||
@@ -72,7 +73,7 @@ private:
|
|||||||
// 窗口
|
// 窗口
|
||||||
SDL_Window *m_window;
|
SDL_Window *m_window;
|
||||||
// 渲染器
|
// 渲染器
|
||||||
SDL_Renderer *m_renderer;
|
RenderManager* m_renderer;
|
||||||
|
|
||||||
// 游戏层场景
|
// 游戏层场景
|
||||||
RefPtr<Scene> m_scene;
|
RefPtr<Scene> m_scene;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "EngineFrame/Scene/Scene.h"
|
#include "EngineFrame/Scene/Scene.h"
|
||||||
|
#include "EngineCore/Game.h"
|
||||||
#include "EngineFrame/Component/RenderBase.h"
|
#include "EngineFrame/Component/RenderBase.h"
|
||||||
|
#include "EngineFrame/Render/RenderManager.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
Actor::Actor()
|
Actor::Actor()
|
||||||
@@ -16,6 +18,22 @@ void Actor::Init()
|
|||||||
addTag(Tag::UPDATE);
|
addTag(Tag::UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actor::Render()
|
||||||
|
{
|
||||||
|
// 如果有裁切视口
|
||||||
|
if (this->_CropViewportFlag)
|
||||||
|
{
|
||||||
|
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||||
|
renderer->SetClipRect(&this->_CropViewport);
|
||||||
|
BaseNode::Render();
|
||||||
|
renderer->CloseClipRect();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseNode::Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::AddComponent(RefPtr<Component> Component)
|
void Actor::AddComponent(RefPtr<Component> Component)
|
||||||
{
|
{
|
||||||
BaseNode::AddChild(Component);
|
BaseNode::AddChild(Component);
|
||||||
@@ -25,3 +43,21 @@ void Actor::RemoveComponent(RefPtr<Component> Component)
|
|||||||
{
|
{
|
||||||
BaseNode::RemoveChild(Component);
|
BaseNode::RemoveChild(Component);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actor::SetCropViewport(SDL_Rect CropViewport)
|
||||||
|
{
|
||||||
|
if (CropViewport.x == 0 && CropViewport.y == 0 && CropViewport.w == 0 && CropViewport.h == 0)
|
||||||
|
{
|
||||||
|
this->_CropViewportFlag = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->_CropViewportFlag = true;
|
||||||
|
this->_CropViewport = CropViewport;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect Actor::GetCropViewport()
|
||||||
|
{
|
||||||
|
return this->_CropViewport;
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,14 +10,23 @@ class Scene;
|
|||||||
*/
|
*/
|
||||||
class Actor : public BaseNode
|
class Actor : public BaseNode
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
//裁切视口Flag
|
||||||
|
bool _CropViewportFlag = false;
|
||||||
|
//裁切视口
|
||||||
|
SDL_Rect _CropViewport = {0, 0, 0, 0};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Actor();
|
Actor();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init() override;
|
void Init() override;
|
||||||
|
void Render() override;
|
||||||
void AddComponent(RefPtr<Component> Component);
|
void AddComponent(RefPtr<Component> Component);
|
||||||
void RemoveComponent(RefPtr<Component> Component);
|
void RemoveComponent(RefPtr<Component> Component);
|
||||||
// void AddChild(RefPtr<Actor> child);
|
|
||||||
// void RemoveChild(RefPtr<Actor> child);
|
// 设置裁切视口(放在Actor里 他与他的子对象都会被裁切)
|
||||||
|
void SetCropViewport(SDL_Rect CropViewport);
|
||||||
|
// 获取裁切视口
|
||||||
|
SDL_Rect GetCropViewport();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -288,6 +288,11 @@ void BaseNode::SetAlpha(float alpha)
|
|||||||
this->Alpha = alpha;
|
this->Alpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BaseNode *BaseNode::GetParent()
|
||||||
|
{
|
||||||
|
return this->m_Parent;
|
||||||
|
}
|
||||||
|
|
||||||
float BaseNode::GetAlpha()
|
float BaseNode::GetAlpha()
|
||||||
{
|
{
|
||||||
return this->Alpha;
|
return this->Alpha;
|
||||||
|
|||||||
@@ -132,4 +132,7 @@ public:
|
|||||||
virtual void SetAlpha(float alpha);
|
virtual void SetAlpha(float alpha);
|
||||||
// 获取透明度
|
// 获取透明度
|
||||||
float GetAlpha();
|
float GetAlpha();
|
||||||
|
|
||||||
|
//获取父对象
|
||||||
|
BaseNode *GetParent();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -67,20 +67,20 @@ void Animation::Init(std::string AniPath)
|
|||||||
// TODO 染色
|
// TODO 染色
|
||||||
|
|
||||||
// 判断是否有Als
|
// 判断是否有Als
|
||||||
// if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
|
if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
|
||||||
// {
|
{
|
||||||
// AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
|
AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
|
||||||
// if (Info.AniList.size() > 0)
|
if (Info.AniList.size() > 0)
|
||||||
// {
|
{
|
||||||
// std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
|
std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
|
||||||
// for (auto &Ani : Info.AniList)
|
for (auto &Ani : Info.AniList)
|
||||||
// {
|
{
|
||||||
// RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
|
RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
|
||||||
// AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
|
AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
|
||||||
// AddChild(AlsAniObj);
|
AddChild(AlsAniObj);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
FlushFrame(0);
|
FlushFrame(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,20 +133,7 @@ void Animation::Update(float deltaTime)
|
|||||||
|
|
||||||
void Animation::Render()
|
void Animation::Render()
|
||||||
{
|
{
|
||||||
if (!Visible)
|
Actor::Render();
|
||||||
return;
|
|
||||||
// 是否裁切
|
|
||||||
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)
|
void Animation::OnAdded(BaseNode *node)
|
||||||
@@ -210,7 +197,7 @@ void Animation::FlushFrame(int Index)
|
|||||||
// 线性减淡
|
// 线性减淡
|
||||||
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
|
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
|
||||||
{
|
{
|
||||||
CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD);
|
CurrentFrame->SetBlendMode(LINEARDODGE);
|
||||||
}
|
}
|
||||||
// 旋转
|
// 旋转
|
||||||
if (FlagBuf.count("IMAGE_ROTATE"))
|
if (FlagBuf.count("IMAGE_ROTATE"))
|
||||||
@@ -328,22 +315,3 @@ void Animation::InterpolationLogic()
|
|||||||
CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -43,13 +43,6 @@ public:
|
|||||||
// TODO SetDye
|
// TODO SetDye
|
||||||
// TODO SetCrop
|
// TODO SetCrop
|
||||||
|
|
||||||
// 设置裁切区域
|
|
||||||
void SetClipRect(SDL_Rect clipRect);
|
|
||||||
// 取消裁切区域
|
|
||||||
void UnsetClipRect();
|
|
||||||
// 设置阴影
|
|
||||||
void SetShadow();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Ani是否可用
|
// Ani是否可用
|
||||||
bool IsUsability = true;
|
bool IsUsability = true;
|
||||||
@@ -95,10 +88,6 @@ public:
|
|||||||
// DyeFrameList = null;
|
// DyeFrameList = null;
|
||||||
// // 整体染色
|
// // 整体染色
|
||||||
// DyeAllFlag = false;
|
// DyeAllFlag = false;
|
||||||
// // 裁切数据
|
|
||||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
|
||||||
// 裁切Flag
|
|
||||||
bool CropFlag = false;
|
|
||||||
|
|
||||||
// 附加选项
|
// 附加选项
|
||||||
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
|
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
|
||||||
|
|||||||
@@ -3,13 +3,6 @@
|
|||||||
|
|
||||||
AnimationManager::AnimationManager()
|
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()
|
void AnimationManager::PreRender()
|
||||||
@@ -65,35 +58,7 @@ void AnimationManager::PreRender()
|
|||||||
|
|
||||||
void AnimationManager::Render()
|
void AnimationManager::Render()
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
|
||||||
// 设定渲染目标为纹理
|
|
||||||
SDL_SetRenderTarget(renderer, m_Texture);
|
|
||||||
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
// 渲染所有子对象
|
|
||||||
Actor::Render();
|
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)
|
void AnimationManager::AddAnimation(RefPtr<Animation> ani)
|
||||||
|
|||||||
62
source/EngineFrame/Component/Canvas.cpp
Normal file
62
source/EngineFrame/Component/Canvas.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "Canvas.h"
|
||||||
|
#include "EngineCore/Game.h"
|
||||||
|
#include "EngineFrame/Render/RenderManager.h"
|
||||||
|
Canvas::Canvas(VecSize size)
|
||||||
|
{
|
||||||
|
m_texture = new Texture();
|
||||||
|
m_texture->Init(size);
|
||||||
|
m_sprite = new Sprite();
|
||||||
|
m_sprite->SetTexture(m_texture);
|
||||||
|
|
||||||
|
Actor::Init();
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &m_fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
// 将目标纹理附加到FBO的颜色附着点
|
||||||
|
glFramebufferTexture2D(
|
||||||
|
GL_FRAMEBUFFER, // 帧缓冲类型
|
||||||
|
GL_COLOR_ATTACHMENT0, // 颜色附着点(可多个,这里用第一个)
|
||||||
|
GL_TEXTURE_2D, // 纹理类型
|
||||||
|
m_texture->getID(), // 目标纹理ID
|
||||||
|
0 // 多级渐远纹理级别
|
||||||
|
);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::PreRender()
|
||||||
|
{
|
||||||
|
if (m_dirty)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO
|
||||||
|
// glViewport(0, 0, m_texture->getSize().width, m_texture->getSize().height);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 全透明黑色
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
Actor::PreRender();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sprite->PreRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::Render()
|
||||||
|
{
|
||||||
|
if (m_dirty)
|
||||||
|
{
|
||||||
|
|
||||||
|
Actor::Render();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
|
||||||
|
// glViewport(0, 0, Game::GetInstance().Screen_W, Game::GetInstance().Screen_H);
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||||
|
renderer->SetCurrentShaderProgram("flip_y");
|
||||||
|
m_sprite->Render();
|
||||||
|
renderer->SetCurrentShaderProgram("normal");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::AddChild(RefPtr<BaseNode> child)
|
||||||
|
{
|
||||||
|
m_dirty = true;
|
||||||
|
Actor::AddChild(child);
|
||||||
|
}
|
||||||
23
source/EngineFrame/Component/Canvas.h
Normal file
23
source/EngineFrame/Component/Canvas.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "EngineFrame/Actor/Actor.h"
|
||||||
|
#include "EngineFrame/Render/Texture.h"
|
||||||
|
#include "EngineFrame/Component/Sprite.h"
|
||||||
|
class Canvas : public Actor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/**纹理 */
|
||||||
|
RefPtr<Texture> m_texture = nullptr;
|
||||||
|
/**精灵 */
|
||||||
|
RefPtr<Sprite> m_sprite = nullptr;
|
||||||
|
/**脏标记 */
|
||||||
|
bool m_dirty = true;
|
||||||
|
/**FBO */
|
||||||
|
GLuint m_fbo = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Canvas(VecSize size);
|
||||||
|
|
||||||
|
void PreRender() override;
|
||||||
|
void Render() override;
|
||||||
|
void AddChild(RefPtr<BaseNode> child) override;
|
||||||
|
};
|
||||||
@@ -1,25 +1,35 @@
|
|||||||
#include "Sprite.h"
|
#include "Sprite.h"
|
||||||
#include "EngineCore/Game.h"
|
#include "EngineCore/Game.h"
|
||||||
#include "Text.h"
|
#include "Text.h"
|
||||||
|
#include "EngineFrame/Render/RenderManager.h"
|
||||||
|
|
||||||
void Sprite::Init()
|
void Sprite::Init()
|
||||||
{
|
{
|
||||||
this->Size = m_texture->TextureSize;
|
this->Size = m_texture->getSize();
|
||||||
RenderBase::Init();
|
RenderBase::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sprite::SetTexture(RefPtr<Texture> texture)
|
||||||
|
{
|
||||||
|
m_texture = texture;
|
||||||
|
Init();
|
||||||
|
CalcRenderInfoLogic(); // 第一次计算
|
||||||
|
}
|
||||||
|
|
||||||
Sprite::Sprite(std::string imgPath, int Index)
|
Sprite::Sprite(std::string imgPath, int Index)
|
||||||
{
|
{
|
||||||
this->imgPath = imgPath;
|
this->imgPath = imgPath;
|
||||||
this->Index = Index;
|
this->Index = Index;
|
||||||
m_texture = new Texture(imgPath, Index);
|
m_texture = new Texture();
|
||||||
|
m_texture->Init(imgPath, Index);
|
||||||
Init();
|
Init();
|
||||||
CalcRenderInfoLogic(); // 第一次计算
|
CalcRenderInfoLogic(); // 第一次计算
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite::Sprite(std::string PngPath)
|
Sprite::Sprite(std::string PngPath)
|
||||||
{
|
{
|
||||||
m_texture = new Texture(PngPath);
|
m_texture = new Texture();
|
||||||
|
m_texture->Init(PngPath);
|
||||||
Init();
|
Init();
|
||||||
CalcRenderInfoLogic(); // 第一次计算
|
CalcRenderInfoLogic(); // 第一次计算
|
||||||
}
|
}
|
||||||
@@ -35,6 +45,19 @@ RefPtr<Texture> Sprite::GetTexture()
|
|||||||
|
|
||||||
void Sprite::CalcRenderInfoLogic()
|
void Sprite::CalcRenderInfoLogic()
|
||||||
{
|
{
|
||||||
|
// 获取至在最终的父对象检查是否显示
|
||||||
|
BaseNode *parentNode = this->GetParent();
|
||||||
|
while (parentNode != nullptr)
|
||||||
|
{
|
||||||
|
if (parentNode->Visible == false)
|
||||||
|
{
|
||||||
|
_RenderGuidanceInfo.Visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parentNode = parentNode->GetParent();
|
||||||
|
}
|
||||||
|
_RenderGuidanceInfo.Visible = true;
|
||||||
|
|
||||||
// 计算缩放因子和翻转状态
|
// 计算缩放因子和翻转状态
|
||||||
float scaleX = transformIter.scale.x * transform.scale.x;
|
float scaleX = transformIter.scale.x * transform.scale.x;
|
||||||
float scaleY = transformIter.scale.y * transform.scale.y;
|
float scaleY = transformIter.scale.y * transform.scale.y;
|
||||||
@@ -51,8 +74,10 @@ void Sprite::CalcRenderInfoLogic()
|
|||||||
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip);
|
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip);
|
||||||
|
|
||||||
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
|
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
|
||||||
float texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x;
|
auto T_Size = m_texture->getSize();
|
||||||
float texturePosY = flipY ? -(m_texture->TextureSize.height + m_texture->TexturePos.y) + SDL_abs(transform.position.y * 2) : m_texture->TexturePos.y;
|
auto T_Pos = m_texture->getPos();
|
||||||
|
float texturePosX = flipX ? -(T_Size.width + T_Pos.x) + SDL_abs(transform.position.x * 2) : T_Pos.x;
|
||||||
|
float texturePosY = flipY ? -(T_Size.height + T_Pos.y) + SDL_abs(transform.position.y * 2) : T_Pos.y;
|
||||||
|
|
||||||
// 先计算Img坐标与精灵坐标合成后的真实坐标
|
// 先计算Img坐标与精灵坐标合成后的真实坐标
|
||||||
float RealPosX = transform.position.x + texturePosX;
|
float RealPosX = transform.position.x + texturePosX;
|
||||||
@@ -93,13 +118,9 @@ void Sprite::CalcRenderInfoLogic()
|
|||||||
|
|
||||||
// 更新渲染信息
|
// 更新渲染信息
|
||||||
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
|
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
|
||||||
|
|
||||||
// 如果有阴影 计算阴影的渲染信息
|
|
||||||
if (ShadowFlag)
|
|
||||||
CalculateShadowData();
|
|
||||||
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
|
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
|
||||||
// 设置纹理透明度
|
// 设置纹理透明度
|
||||||
SDL_SetTextureAlphaMod(m_texture->GetTexture(), this->Alpha * 255);
|
m_texture->setAlpha(this->Alpha);
|
||||||
|
|
||||||
// 屏幕内检测
|
// 屏幕内检测
|
||||||
int screenWidth = Game::GetInstance().Screen_W;
|
int screenWidth = Game::GetInstance().Screen_W;
|
||||||
@@ -113,17 +134,6 @@ void Sprite::CalcRenderInfoLogic()
|
|||||||
CalcRenderInfoFlag = false;
|
CalcRenderInfoFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::SetClipRect(SDL_Rect clipRect)
|
|
||||||
{
|
|
||||||
CropFlag = true;
|
|
||||||
CropRect = clipRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sprite::UnsetClipRect()
|
|
||||||
{
|
|
||||||
CropFlag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sprite::PreRender()
|
void Sprite::PreRender()
|
||||||
{
|
{
|
||||||
if (CalcRenderInfoFlag && Visible)
|
if (CalcRenderInfoFlag && Visible)
|
||||||
@@ -134,32 +144,26 @@ void Sprite::Render()
|
|||||||
{
|
{
|
||||||
if (!Visible)
|
if (!Visible)
|
||||||
return;
|
return;
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
|
||||||
if (!m_texture)
|
if (!m_texture)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||||
|
|
||||||
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
|
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
|
||||||
{
|
{
|
||||||
// 如果有阴影绘制阴影
|
SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos;
|
||||||
if (ShadowFlag)
|
|
||||||
{
|
// 混合
|
||||||
std::array<int, 6> indices = {0, 1, 2, 1, 3, 2};
|
if (this->_BlendMode != NONE)
|
||||||
SDL_RenderGeometry(renderer, m_texture->GetTexture(), vertices.data(), vertices.size(), indices.data(), indices.size());
|
Blend();
|
||||||
}
|
|
||||||
|
SDL_Rect srcrect = {0, 0, this->Size.width, this->Size.height};
|
||||||
|
renderer->DrawTexture(m_texture, &srcrect, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
|
||||||
|
|
||||||
|
// 还原混合
|
||||||
|
if (this->_BlendMode != NONE)
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
if (_RenderGuidanceInfo.rotation != 0.f || _RenderGuidanceInfo.flip != SDL_FLIP_NONE)
|
|
||||||
{
|
|
||||||
SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos;
|
|
||||||
SDL_RenderCopyExF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_RenderCopyF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect);
|
|
||||||
// // 设置绘制颜色
|
|
||||||
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
|
|
||||||
// // 绘制填充矩形
|
|
||||||
// SDL_RenderFillRectF(renderer, &_RenderGuidanceInfo.rect);
|
|
||||||
}
|
|
||||||
Game::GetInstance().m_RenderCount++;
|
Game::GetInstance().m_RenderCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,72 +172,22 @@ void Sprite::Clear()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::SetBlendMode(SDL_BlendMode blendMode)
|
void Sprite::SetBlendMode(LE_BlEND_MODE mode)
|
||||||
{
|
{
|
||||||
if (GetBlendMode() != blendMode)
|
this->_BlendMode = mode;
|
||||||
m_texture->SetBlendMode(blendMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_BlendMode Sprite::GetBlendMode()
|
void Sprite::Blend()
|
||||||
{
|
{
|
||||||
return m_texture->GetBlendMode();
|
switch (this->_BlendMode)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
case LINEARDODGE:
|
||||||
if (flipHorizontal)
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||||
{
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LE_BlEND_MODE Sprite::GetBlendMode()
|
||||||
|
{
|
||||||
|
return this->_BlendMode;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Game;
|
|||||||
/**
|
/**
|
||||||
* @brief Sprite类,继承自Component类,用于表示游戏中的精灵组件
|
* @brief Sprite类,继承自Component类,用于表示游戏中的精灵组件
|
||||||
*/
|
*/
|
||||||
class Sprite : public RenderBase
|
class Sprite : public RenderBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
RefPtr<Texture> m_texture = nullptr;
|
RefPtr<Texture> m_texture = nullptr;
|
||||||
@@ -22,36 +22,26 @@ public:
|
|||||||
void PreRender() override;
|
void PreRender() override;
|
||||||
void Clear() override;
|
void Clear() override;
|
||||||
void Init() override;
|
void Init() override;
|
||||||
|
void SetTexture(RefPtr<Texture> texture);
|
||||||
|
|
||||||
RefPtr<Texture> GetTexture();
|
RefPtr<Texture> GetTexture();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 渲染信息
|
// 渲染信息
|
||||||
RenderGuidanceInfo _RenderGuidanceInfo;
|
RenderGuidanceInfo _RenderGuidanceInfo;
|
||||||
// 裁切数据
|
// 混合模式
|
||||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
LE_BlEND_MODE _BlendMode = NONE;
|
||||||
// 裁切Flag
|
|
||||||
bool CropFlag = false;
|
|
||||||
// 阴影数据
|
|
||||||
std::array<SDL_Vertex, 4> vertices;
|
|
||||||
// 阴影Flag
|
|
||||||
bool ShadowFlag = false;
|
|
||||||
std::string imgPath;
|
std::string imgPath;
|
||||||
int Index;
|
int Index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 计算渲染信息
|
// 计算渲染信息
|
||||||
void CalcRenderInfoLogic();
|
void CalcRenderInfoLogic();
|
||||||
// 设置裁切区域
|
|
||||||
void SetClipRect(SDL_Rect clipRect);
|
|
||||||
// 取消裁切区域
|
|
||||||
void UnsetClipRect();
|
|
||||||
// 设置混合模式
|
// 设置混合模式
|
||||||
void SetBlendMode(SDL_BlendMode blendMode);
|
void SetBlendMode(LE_BlEND_MODE mode);
|
||||||
|
// 混合
|
||||||
|
void Blend();
|
||||||
// 获取混合模式
|
// 获取混合模式
|
||||||
SDL_BlendMode GetBlendMode();
|
LE_BlEND_MODE GetBlendMode();
|
||||||
// 设置阴影
|
|
||||||
void SetShadow();
|
|
||||||
// 计算阴影数据
|
|
||||||
void CalculateShadowData();
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,200 +5,56 @@ Text::Text()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Text::Text(std::string Str, TTF_Font *font, SDL_Color color)
|
|
||||||
{
|
|
||||||
m_text = Str;
|
|
||||||
m_font = font;
|
|
||||||
m_text_color = color;
|
|
||||||
Init(Str, font, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
Text::Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
|
|
||||||
{
|
|
||||||
m_text = Str;
|
|
||||||
m_font = font;
|
|
||||||
m_text_color = textColor;
|
|
||||||
m_stroke_color = strokeColor;
|
|
||||||
m_stroke_size = strokeSize;
|
|
||||||
Init(Str, font, textColor, strokeColor, strokeSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Text::~Text()
|
Text::~Text()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::Init(std::string Str, TTF_Font *font, SDL_Color color)
|
void Text::Init(std::string Str, TTF_Font *font, SDL_Color color)
|
||||||
{
|
{
|
||||||
// 标记该组件需要渲染和更新
|
if (!m_texture)
|
||||||
addTag(Tag::RENDER);
|
{
|
||||||
addTag(Tag::UPDATE);
|
this->m_font = font;
|
||||||
|
this->m_color = color;
|
||||||
// TTF_SetFontOutline(font, 1);
|
}
|
||||||
// 先渲染为表面
|
// 先渲染为表面
|
||||||
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), color);
|
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), color);
|
||||||
if (!textSurface)
|
if (!textSurface)
|
||||||
{
|
{
|
||||||
SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
||||||
}
|
}
|
||||||
|
// 转换为RGBA8888格式(与OpenGL的GL_RGBA匹配)
|
||||||
|
SDL_Surface *rgbaSurface = SDL_ConvertSurfaceFormat(
|
||||||
|
textSurface,
|
||||||
|
SDL_PIXELFORMAT_ABGR8888,
|
||||||
|
0);
|
||||||
|
|
||||||
|
SDL_FreeSurface(textSurface);
|
||||||
// 再将表面转换为纹理
|
// 再将表面转换为纹理
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||||
m_texture = SDL_CreateTextureFromSurface(renderer, textSurface);
|
m_texture = new Texture;
|
||||||
if (!m_texture)
|
m_texture->Init(rgbaSurface);
|
||||||
{
|
|
||||||
SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError());
|
|
||||||
}
|
|
||||||
// 设置纹理过滤模式为最近邻,避免缩放模糊
|
|
||||||
SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest);
|
|
||||||
Size.x = textSurface->w;
|
|
||||||
Size.y = textSurface->h;
|
|
||||||
TextureSize.x = textSurface->w;
|
|
||||||
TextureSize.y = textSurface->h;
|
|
||||||
|
|
||||||
// 释放表面
|
// 释放表面
|
||||||
SDL_FreeSurface(textSurface);
|
SDL_FreeSurface(rgbaSurface);
|
||||||
}
|
Sprite::Init();
|
||||||
|
|
||||||
void Text::Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
|
|
||||||
{
|
|
||||||
// 先保存原始字体的轮廓设置
|
|
||||||
int originalOutline = TTF_GetFontOutline(font);
|
|
||||||
|
|
||||||
// 设置字体轮廓大小(描边宽度)
|
|
||||||
TTF_SetFontOutline(font, strokeSize);
|
|
||||||
|
|
||||||
// 渲染描边(使用描边颜色)
|
|
||||||
SDL_Surface *strokeSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), strokeColor);
|
|
||||||
if (!strokeSurface)
|
|
||||||
{
|
|
||||||
SDL_LogError(0, "描边渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
|
||||||
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 恢复字体轮廓设置,用于渲染文字本身
|
|
||||||
TTF_SetFontOutline(font, 0);
|
|
||||||
|
|
||||||
// 渲染文字本身(使用文字颜色)
|
|
||||||
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), textColor);
|
|
||||||
if (!textSurface)
|
|
||||||
{
|
|
||||||
SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
|
||||||
SDL_FreeSurface(strokeSurface);
|
|
||||||
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建一个合并描边和文字的表面
|
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
|
||||||
|
|
||||||
// 计算最终纹理大小(描边会增加额外尺寸)
|
|
||||||
int finalWidth = strokeSurface->w;
|
|
||||||
int finalHeight = strokeSurface->h;
|
|
||||||
|
|
||||||
// 创建一个临时表面用于合并描边和文字
|
|
||||||
SDL_Surface *finalSurface = SDL_CreateRGBSurfaceWithFormat(
|
|
||||||
0, finalWidth, finalHeight, 32, SDL_PIXELFORMAT_RGBA32);
|
|
||||||
if (!finalSurface)
|
|
||||||
{
|
|
||||||
SDL_LogError(0, "创建最终表面失败!SDL_Error:%s", SDL_GetError());
|
|
||||||
SDL_FreeSurface(textSurface);
|
|
||||||
SDL_FreeSurface(strokeSurface);
|
|
||||||
TTF_SetFontOutline(font, originalOutline);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将描边绘制到最终表面
|
|
||||||
SDL_Rect strokeRect = {0, 0, strokeSurface->w, strokeSurface->h};
|
|
||||||
SDL_BlitSurface(strokeSurface, nullptr, finalSurface, &strokeRect);
|
|
||||||
|
|
||||||
// 计算文字在描边中间的位置
|
|
||||||
SDL_Rect textRect = {
|
|
||||||
strokeSize, // X偏移(描边宽度)
|
|
||||||
strokeSize, // Y偏移(描边宽度)
|
|
||||||
textSurface->w,
|
|
||||||
textSurface->h};
|
|
||||||
SDL_BlitSurface(textSurface, nullptr, finalSurface, &textRect);
|
|
||||||
|
|
||||||
// 将合并后的表面转换为纹理
|
|
||||||
m_texture = SDL_CreateTextureFromSurface(renderer, finalSurface);
|
|
||||||
if (!m_texture)
|
|
||||||
{
|
|
||||||
SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置尺寸信息
|
|
||||||
Size.x = finalSurface->w;
|
|
||||||
Size.y = finalSurface->h;
|
|
||||||
TextureSize.x = finalSurface->w;
|
|
||||||
TextureSize.y = finalSurface->h;
|
|
||||||
|
|
||||||
// 释放所有临时表面
|
|
||||||
SDL_FreeSurface(textSurface);
|
|
||||||
SDL_FreeSurface(strokeSurface);
|
|
||||||
SDL_FreeSurface(finalSurface);
|
|
||||||
|
|
||||||
// 恢复字体原始轮廓设置
|
|
||||||
TTF_SetFontOutline(font, originalOutline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::HandleEvents(SDL_Event *e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::Update(float deltaTime)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::Render()
|
void Text::Render()
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
Sprite::Render();
|
||||||
if (!renderer || !m_texture)
|
|
||||||
return;
|
|
||||||
SDL_Rect dstrect = {Pos.x, Pos.y, Size.x, Size.y};
|
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, m_texture, NULL, &dstrect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::Clear()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::SetPos(SDL_Point pos)
|
|
||||||
{
|
|
||||||
Pos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Point Text::GetPos()
|
|
||||||
{
|
|
||||||
return Pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::SetText(std::string Str)
|
void Text::SetText(std::string Str)
|
||||||
{
|
{
|
||||||
if (Str == m_text)
|
if (Str == m_text)
|
||||||
return;
|
return;
|
||||||
if (!m_font)
|
|
||||||
{
|
|
||||||
SDL_LogError(0, "SetText失败:字体指针为空!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有原纹理先删除原纹理
|
// 如果有原纹理先删除原纹理
|
||||||
if (m_texture)
|
if (m_texture)
|
||||||
{
|
{
|
||||||
SDL_DestroyTexture(m_texture);
|
|
||||||
m_texture = nullptr; // 置空指针
|
m_texture = nullptr; // 置空指针
|
||||||
}
|
}
|
||||||
m_text = Str;
|
m_text = Str;
|
||||||
// 根据是否有描边选择对应的Init方法
|
Init(Str, m_font, m_color);
|
||||||
if (m_stroke_size > 0)
|
|
||||||
{
|
|
||||||
Init(Str, m_font, m_text_color, m_stroke_color, m_stroke_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Init(Str, m_font, m_text_color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Text::GetText()
|
std::string Text::GetText()
|
||||||
|
|||||||
@@ -1,59 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include <SDL2/SDL_ttf.h>
|
#include <SDL2/SDL_ttf.h>
|
||||||
#include "EngineFrame/Component/Component.h"
|
#include "EngineFrame/Component/Sprite.h"
|
||||||
class Game;
|
|
||||||
|
|
||||||
class Text : public Component
|
class Text : public Sprite
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
/* data */
|
|
||||||
SDL_Texture *m_texture = nullptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Text(/* args */);
|
Text(/* args */);
|
||||||
Text(std::string Str, TTF_Font *font, SDL_Color color);
|
|
||||||
Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
|
|
||||||
~Text();
|
~Text();
|
||||||
|
|
||||||
// 显式引入基类的Init方法,避免隐藏
|
// 显式引入基类的Init方法,避免隐藏
|
||||||
using Component::Init;
|
using Component::Init;
|
||||||
void Init(std::string Str, TTF_Font *font, SDL_Color color);
|
void Init(std::string Str, TTF_Font *font, SDL_Color color);
|
||||||
void Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
|
|
||||||
void HandleEvents(SDL_Event *e) override;
|
|
||||||
void Update(float deltaTime) override;
|
|
||||||
void Render() override;
|
void Render() override;
|
||||||
void Clear() override;
|
|
||||||
|
|
||||||
SDL_Texture *GetTexture();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 组件标签
|
/** 文本内容 */
|
||||||
Tag m_tag = Tag::RENDER | Tag::UPDATE; // 标记该组件需要渲染和更新
|
|
||||||
|
|
||||||
std::string m_text;
|
std::string m_text;
|
||||||
|
/** 字体 */
|
||||||
TTF_Font *m_font;
|
TTF_Font *m_font;
|
||||||
SDL_Color m_text_color;
|
/** 字体颜色 */
|
||||||
SDL_Color m_stroke_color;
|
SDL_Color m_color;
|
||||||
int m_stroke_size = 0;
|
|
||||||
|
|
||||||
SDL_Point Pos = {0, 0}; // 位置坐标
|
|
||||||
SDL_Point TextureSize = {0, 0}; // 纹理大小
|
|
||||||
SDL_Point Size = {0, 0}; // 大小
|
|
||||||
SDL_Point Anchor = {0, 0}; // 中心点
|
|
||||||
float Angle = 0.0f; // 旋转角度
|
|
||||||
SDL_RendererFlip flip = SDL_FLIP_NONE; // 翻转
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 设置坐标
|
|
||||||
void SetPos(SDL_Point pos);
|
|
||||||
// 设置文本
|
// 设置文本
|
||||||
void SetText(std::string Str);
|
void SetText(std::string Str);
|
||||||
|
|
||||||
// 获取坐标
|
|
||||||
SDL_Point GetPos();
|
|
||||||
// 获取文本
|
// 获取文本
|
||||||
std::string GetText();
|
std::string GetText();
|
||||||
};
|
};
|
||||||
|
|||||||
359
source/EngineFrame/Render/RenderManager.cpp
Normal file
359
source/EngineFrame/Render/RenderManager.cpp
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
#include "RenderManager.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
RenderManager::RenderManager(SDL_Window *window)
|
||||||
|
{
|
||||||
|
_window = window;
|
||||||
|
// 创建OpenGL上下文
|
||||||
|
_ctx = SDL_GL_CreateContext(window);
|
||||||
|
if (!_ctx)
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "GL context create failed: %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化GLAD
|
||||||
|
if (!gladLoadGLES2Loader((GLADloadproc)SDL_GL_GetProcAddress))
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "GLAD init failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取窗口大小
|
||||||
|
int width, height;
|
||||||
|
SDL_GetWindowSize(window, &width, &height);
|
||||||
|
// 设置视口
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
// 设置窗口尺寸
|
||||||
|
_windowWidth = width;
|
||||||
|
_windowHeight = height;
|
||||||
|
// 设置正交投影矩阵
|
||||||
|
_orthoMatrix = glm::ortho(0.0f, (float)width, (float)height, 0.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
// 设置清屏颜色
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
// 启用混合模式
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
// 默认设置标准alpha混合
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// 初始化着色器程序
|
||||||
|
InitShaderProgram();
|
||||||
|
// 初始化绘制2D纹理缓冲程序
|
||||||
|
Init2DTextureProgram();
|
||||||
|
|
||||||
|
// 设定默认使用的着色器程序和缓冲程序
|
||||||
|
SetCurrentShaderProgram("normal");
|
||||||
|
SetCurrentBufferObject("2DTexture");
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderManager::~RenderManager()
|
||||||
|
{
|
||||||
|
// 释放着色器程序
|
||||||
|
for (auto &[name, program] : _shaderProgramMap)
|
||||||
|
{
|
||||||
|
glDeleteProgram(program);
|
||||||
|
}
|
||||||
|
// 释放缓冲对象
|
||||||
|
for (auto &[name, program] : _RenderParamsMap)
|
||||||
|
{
|
||||||
|
glDeleteVertexArrays(1, &program.VAO);
|
||||||
|
glDeleteBuffers(1, &program.VBO);
|
||||||
|
glDeleteBuffers(1, &program.EBO);
|
||||||
|
}
|
||||||
|
// 释放OpenGL上下文
|
||||||
|
SDL_GL_DeleteContext(_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::InitShaderProgram()
|
||||||
|
{
|
||||||
|
std::ifstream shaderFile("shader/config.json");
|
||||||
|
|
||||||
|
nlohmann::json shaderConfig;
|
||||||
|
shaderFile >> shaderConfig;
|
||||||
|
|
||||||
|
for (auto &[groupName, groupData] : shaderConfig["shader"].items())
|
||||||
|
{
|
||||||
|
if (!groupData.is_object())
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "着色器组 %s 格式错误,跳过\n", groupName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!groupData.contains("vertex") || !groupData["vertex"].is_string())
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "组 %s 缺少 vertex 路径,跳过\n", groupName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!groupData.contains("fragment") || !groupData["fragment"].is_string())
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "组 %s 缺少 fragment 路径,跳过\n", groupName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string vertPath = groupData["vertex"].get<std::string>();
|
||||||
|
std::string fragPath = groupData["fragment"].get<std::string>();
|
||||||
|
|
||||||
|
GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertPath);
|
||||||
|
GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragPath);
|
||||||
|
if (vertexShader == 0 || fragmentShader == 0)
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "组 %s 着色器编译失败,跳过\n", groupName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint program = glCreateProgram();
|
||||||
|
glAttachShader(program, vertexShader);
|
||||||
|
glAttachShader(program, fragmentShader);
|
||||||
|
glLinkProgram(program);
|
||||||
|
GLint programLinksuccess;
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &programLinksuccess);
|
||||||
|
if (!programLinksuccess)
|
||||||
|
{
|
||||||
|
char infoLog[512];
|
||||||
|
glGetProgramInfoLog(program, 512, nullptr, infoLog);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "组 %s 着色器链接失败,失败原因: %s\n", groupName.c_str(), infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
_shaderProgramMap[groupName] = program;
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::Init2DTextureProgram()
|
||||||
|
{
|
||||||
|
// 初始化顶点数据(矩形的四个顶点)
|
||||||
|
float vertices[] = {
|
||||||
|
0.0f, 0.0f, 0.0f, 0.0f, // 左下(单位坐标)
|
||||||
|
1.0f, 0.0f, 1.0f, 0.0f, // 右下
|
||||||
|
1.0f, 1.0f, 1.0f, 1.0f, // 右上
|
||||||
|
0.0f, 1.0f, 0.0f, 1.0f // 左上
|
||||||
|
};
|
||||||
|
// 索引数组
|
||||||
|
unsigned int indices[] = {0, 1, 2, 2, 3, 0};
|
||||||
|
GLuint VAO, VBO, EBO;
|
||||||
|
// 创建VAO/VBO/EBO
|
||||||
|
glGenVertexArrays(1, &VAO);
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
glGenBuffers(1, &EBO);
|
||||||
|
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
// 创建完解绑
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
SetCurrentShaderProgram("normal");
|
||||||
|
glUseProgram(_currentShaderProgram);
|
||||||
|
|
||||||
|
// 获取uniform变量位置
|
||||||
|
GLuint _uModelLoc = glGetUniformLocation(_currentShaderProgram, "uModel");
|
||||||
|
GLuint _uViewProjLoc = glGetUniformLocation(_currentShaderProgram, "uViewProj");
|
||||||
|
GLuint _uTextureLoc = glGetUniformLocation(_currentShaderProgram, "uTexture");
|
||||||
|
if (_uModelLoc == -1 || _uViewProjLoc == -1 || _uTextureLoc == -1)
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "无法获取着色器 uniform 变量位置\n");
|
||||||
|
}
|
||||||
|
std::vector<GLuint> uniformLocs = {_uModelLoc, _uViewProjLoc, _uTextureLoc};
|
||||||
|
|
||||||
|
DrawLogicFunc drawFunc = [this](
|
||||||
|
RefPtr<Texture> textureObj, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, void *userdata)
|
||||||
|
{
|
||||||
|
GLuint texture = textureObj->getID();
|
||||||
|
if (!texture || !dstrect)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glUseProgram(_currentShaderProgram);
|
||||||
|
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
// 平移
|
||||||
|
model = glm::translate(model, glm::vec3(dstrect->x, dstrect->y, 0.0f));
|
||||||
|
|
||||||
|
// 计算旋转中心
|
||||||
|
float centerX = center ? center->x : dstrect->w * 0.5f;
|
||||||
|
float centerY = center ? center->y : dstrect->h * 0.5f;
|
||||||
|
|
||||||
|
// 旋转中心平移
|
||||||
|
model = glm::translate(model, glm::vec3(centerX, centerY, 0.0f));
|
||||||
|
|
||||||
|
// 旋转
|
||||||
|
if (angle != 0.0)
|
||||||
|
{
|
||||||
|
model = glm::rotate(model, glm::radians(static_cast<float>(angle)), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 旋转中心平移
|
||||||
|
model = glm::translate(model, glm::vec3(-centerX, -centerY, 0.0f));
|
||||||
|
|
||||||
|
// 缩放和翻转
|
||||||
|
float scaleX = dstrect->w;
|
||||||
|
float scaleY = dstrect->h;
|
||||||
|
|
||||||
|
// 应用翻转(通过负缩放实现)
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL)
|
||||||
|
scaleX = -scaleX;
|
||||||
|
if (flip & SDL_FLIP_VERTICAL)
|
||||||
|
scaleY = -scaleY;
|
||||||
|
|
||||||
|
model = glm::scale(model, glm::vec3(scaleX, scaleY, 1.0f));
|
||||||
|
|
||||||
|
// 翻转后的位置补偿
|
||||||
|
if (flip & SDL_FLIP_HORIZONTAL)
|
||||||
|
{
|
||||||
|
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 0.0f));
|
||||||
|
}
|
||||||
|
if (flip & SDL_FLIP_VERTICAL)
|
||||||
|
{
|
||||||
|
model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置着色器 uniforms
|
||||||
|
glUniformMatrix4fv(_currentRenderParams.UnimLocs[0], 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
glUniformMatrix4fv(_currentRenderParams.UnimLocs[1], 1, GL_FALSE, glm::value_ptr(_orthoMatrix));
|
||||||
|
|
||||||
|
// 绑定纹理并设置采样器
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glUniform1i(_currentRenderParams.UnimLocs[2], 0);
|
||||||
|
|
||||||
|
// 处理纹理裁剪
|
||||||
|
int texWidth = textureObj->getSize().width;
|
||||||
|
int texHeight = textureObj->getSize().height;
|
||||||
|
|
||||||
|
// 计算纹理坐标
|
||||||
|
float minu, minv, maxu, maxv;
|
||||||
|
if (srcrect)
|
||||||
|
{
|
||||||
|
minu = (float)srcrect->x / texWidth;
|
||||||
|
minv = (float)srcrect->y / texHeight;
|
||||||
|
maxu = (float)(srcrect->x + srcrect->w) / texWidth;
|
||||||
|
maxv = (float)(srcrect->y + srcrect->h) / texHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minu = 0.0f;
|
||||||
|
minv = 0.0f;
|
||||||
|
maxu = 1.0f;
|
||||||
|
maxv = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算顶点位置(单位矩形,通过模型变换进行缩放和平移)
|
||||||
|
float minx = 0.0f;
|
||||||
|
float miny = 0.0f;
|
||||||
|
float maxx = 1.0f;
|
||||||
|
float maxy = 1.0f;
|
||||||
|
|
||||||
|
// 创建顶点数据(位置 + 纹理坐标)
|
||||||
|
float vertices[] = {
|
||||||
|
// 位置 // 纹理坐标
|
||||||
|
minx, miny, minu, minv, // 左上
|
||||||
|
maxx, miny, maxu, minv, // 右上
|
||||||
|
maxx, maxy, maxu, maxv, // 右下
|
||||||
|
minx, maxy, minu, maxv // 左下
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新VBO数据
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _currentRenderParams.VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
// 绘制纹理
|
||||||
|
glBindVertexArray(_currentRenderParams.VAO);
|
||||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
GL_RenderParams bufferObject = {VAO, VBO, EBO, uniformLocs, drawFunc};
|
||||||
|
AddBufferObject("2DTexture", bufferObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::SetCurrentShaderProgram(std::string name)
|
||||||
|
{
|
||||||
|
if (_shaderProgramMap.find(name) != _shaderProgramMap.end())
|
||||||
|
{
|
||||||
|
this->_currentShaderProgram = _shaderProgramMap[name];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "找不到着色器程序: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::SetCurrentBufferObject(std::string name)
|
||||||
|
{
|
||||||
|
if (_RenderParamsMap.find(name) != _RenderParamsMap.end())
|
||||||
|
{
|
||||||
|
this->_currentRenderParams = _RenderParamsMap[name];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "找不到渲染参数: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::ClearScreen()
|
||||||
|
{
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::SwapBuffer()
|
||||||
|
{
|
||||||
|
SDL_GL_SwapWindow(_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::SetClipRect(const SDL_Rect *rect)
|
||||||
|
{
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(rect->x, _windowHeight - rect->y - rect->h, rect->w, rect->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::CloseClipRect()
|
||||||
|
{
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::DrawTexture(RefPtr<Texture> textureObj, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, void *userdata)
|
||||||
|
{
|
||||||
|
if (_currentRenderParams.DrawFunc != nullptr)
|
||||||
|
_currentRenderParams.DrawFunc(textureObj, srcrect, dstrect, angle, center, flip, userdata);
|
||||||
|
else
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "找不到渲染逻辑函数\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint RenderManager::CompileShader(GLenum type, std::string Path)
|
||||||
|
{
|
||||||
|
std::ifstream Source("shader/" + Path);
|
||||||
|
if (!Source.is_open())
|
||||||
|
{
|
||||||
|
SDL_LogError(0, "Failed to open shader file: %s\n", Path.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShaderSource((std::istreambuf_iterator<char>(Source)), std::istreambuf_iterator<char>());
|
||||||
|
const char *SourcePtr = ShaderSource.c_str();
|
||||||
|
|
||||||
|
GLuint ShaderId = glCreateShader(type);
|
||||||
|
glShaderSource(ShaderId, 1, &SourcePtr, NULL);
|
||||||
|
glCompileShader(ShaderId);
|
||||||
|
|
||||||
|
// 检查编译错误
|
||||||
|
GLint success;
|
||||||
|
glGetShaderiv(ShaderId, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
char infoLog[512];
|
||||||
|
glGetShaderInfoLog(ShaderId, 512, nullptr, infoLog);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Shader compile error: %s\n", infoLog);
|
||||||
|
glDeleteShader(ShaderId);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ShaderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::AddBufferObject(std::string name, GL_RenderParams bufferObject)
|
||||||
|
{
|
||||||
|
_RenderParamsMap[name] = bufferObject;
|
||||||
|
}
|
||||||
78
source/EngineFrame/Render/RenderManager.h
Normal file
78
source/EngineFrame/Render/RenderManager.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_image.h>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/ext/matrix_clip_space.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <json.hpp>
|
||||||
|
#include "EngineFrame/Render/Texture.h"
|
||||||
|
class RenderManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 绘制纹理的逻辑函数
|
||||||
|
using DrawLogicFunc = std::function<void(RefPtr<Texture>, const SDL_Rect *, const SDL_FRect *,
|
||||||
|
double, const SDL_FPoint *, SDL_RendererFlip,
|
||||||
|
void *)>;
|
||||||
|
|
||||||
|
struct GL_RenderParams
|
||||||
|
{
|
||||||
|
GLuint VAO;
|
||||||
|
GLuint VBO;
|
||||||
|
GLuint EBO;
|
||||||
|
std::vector<GLuint> UnimLocs;
|
||||||
|
DrawLogicFunc DrawFunc = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Window *_window;
|
||||||
|
// 窗口尺寸
|
||||||
|
int _windowWidth;
|
||||||
|
int _windowHeight;
|
||||||
|
// 正交投影矩阵
|
||||||
|
glm::mat4 _orthoMatrix;
|
||||||
|
|
||||||
|
// 渲染器上下文
|
||||||
|
SDL_GLContext _ctx;
|
||||||
|
// 着色器程序
|
||||||
|
std::map<std::string, GLuint> _shaderProgramMap;
|
||||||
|
// 渲染参数
|
||||||
|
std::map<std::string, GL_RenderParams> _RenderParamsMap;
|
||||||
|
|
||||||
|
// 当前使用着色器程序
|
||||||
|
GLuint _currentShaderProgram;
|
||||||
|
// 当前使用渲染参数
|
||||||
|
GL_RenderParams _currentRenderParams;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderManager(SDL_Window *window);
|
||||||
|
~RenderManager();
|
||||||
|
|
||||||
|
// 初始化着色器程序
|
||||||
|
void InitShaderProgram();
|
||||||
|
// 初始化绘制2D纹理缓冲程序
|
||||||
|
void Init2DTextureProgram();
|
||||||
|
// 设定当前使用的着色器程序
|
||||||
|
void SetCurrentShaderProgram(std::string name);
|
||||||
|
// 设定当前使用的缓冲对象
|
||||||
|
void SetCurrentBufferObject(std::string name);
|
||||||
|
|
||||||
|
// 清空屏幕
|
||||||
|
void ClearScreen();
|
||||||
|
// 交换缓冲区
|
||||||
|
void SwapBuffer();
|
||||||
|
// 设置裁切区域
|
||||||
|
void SetClipRect(const SDL_Rect *rect);
|
||||||
|
// 关闭裁切区域
|
||||||
|
void CloseClipRect();
|
||||||
|
// 绘制纹理
|
||||||
|
void DrawTexture(RefPtr<Texture> texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, void *userdata = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 编译着色器
|
||||||
|
GLuint CompileShader(GLenum type, std::string Path);
|
||||||
|
// 新增缓冲程序
|
||||||
|
void AddBufferObject(std::string name, GL_RenderParams bufferObject);
|
||||||
|
};
|
||||||
@@ -1,91 +1,204 @@
|
|||||||
#include "EngineFrame/Render/Texture.h"
|
#include "Texture.h"
|
||||||
#include "Asset/Asset_ImagePack.h"
|
#include "Asset/Asset_ImagePack.h"
|
||||||
#include "EngineCore/Game.h"
|
#include "EngineCore/Game.h"
|
||||||
#include "Texture.h"
|
|
||||||
|
|
||||||
Texture::Texture()
|
Texture::Texture()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(std::string PngPath)
|
Texture::~Texture()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_TextureID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Texture::Init(std::string PngPath)
|
||||||
{
|
{
|
||||||
SDL_Surface *surface = IMG_Load(PngPath.c_str());
|
SDL_Surface *surface = IMG_Load(PngPath.c_str());
|
||||||
if (!surface)
|
if (!surface)
|
||||||
{
|
{
|
||||||
SDL_Log("无法加载图片: %s", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't load image %s: %s", PngPath.c_str(), IMG_GetError());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
SDL_Surface *rgbaSurface = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
|
||||||
m_texture = SDL_CreateTextureFromSurface(Game::GetInstance().GetRenderer(), surface);
|
|
||||||
if (!m_texture)
|
|
||||||
{
|
|
||||||
SDL_Log("无法创建纹理: %s", SDL_GetError());
|
|
||||||
SDL_FreeSurface(surface); // 记得释放surface
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->TextureSize.width = surface->w;
|
|
||||||
this->TextureSize.height = surface->h;
|
|
||||||
this->TextureFramepos.width = surface->w;
|
|
||||||
this->TextureFramepos.height = surface->h;
|
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
|
if (!rgbaSurface)
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to convert surface: %s\n", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成OpenGL纹理
|
||||||
|
glGenTextures(1, &m_TextureID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||||||
|
|
||||||
|
// 环绕方式
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
// 缩小过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
// 放大过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
// 处理像素对齐(确保SDL的像素行对齐与OpenGL兼容)
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
// 记录纹理信息
|
||||||
|
m_TextureSize.width = rgbaSurface->w;
|
||||||
|
m_TextureSize.height = rgbaSurface->h;
|
||||||
|
m_FrameSize.width = rgbaSurface->w;
|
||||||
|
m_FrameSize.height = rgbaSurface->h;
|
||||||
|
m_Path = PngPath;
|
||||||
|
|
||||||
|
// 将像素数据上传到GPU
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0, // 纹理级别(基础级)
|
||||||
|
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||||||
|
m_TextureSize.width,
|
||||||
|
m_TextureSize.height,
|
||||||
|
0, // 边框(必须为0)
|
||||||
|
GL_RGBA, // 源数据格式(与SDL转换后的格式一致)
|
||||||
|
GL_UNSIGNED_BYTE, // 源数据类型(无符号字节)
|
||||||
|
rgbaSurface->pixels);
|
||||||
|
|
||||||
|
// 释放转换后的表面(数据已上传到GPU)
|
||||||
|
SDL_FreeSurface(rgbaSurface);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(std::string imgPath, int Index)
|
bool Texture::Init(std::string ImgPath, int Index)
|
||||||
{
|
{
|
||||||
this->ImgPath = imgPath;
|
m_Path = ImgPath;
|
||||||
this->Index = Index;
|
m_TextureIndex = Index;
|
||||||
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(imgPath);
|
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(ImgPath);
|
||||||
if (Info->lpImgName == "sprite/interface/base.img")
|
if (Info->lpImgName == "sprite/interface/base.img")
|
||||||
return;
|
return false;
|
||||||
Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index];
|
Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index];
|
||||||
|
|
||||||
m_texture = SDL_CreateTexture(
|
// 检查像素数据是否有效
|
||||||
Game::GetInstance().GetRenderer(),
|
if (!Buf.PNGdata || Buf.Width <= 0 || Buf.Height <= 0)
|
||||||
SDL_PIXELFORMAT_ARGB8888, // 匹配RGBA数据格式
|
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
|
||||||
Buf.Width, Buf.Height);
|
|
||||||
if (!m_texture)
|
|
||||||
{
|
{
|
||||||
SDL_Log("纹理创建失败: %s", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "无效的图像数据: %s (index: %d)", ImgPath.c_str(), Index);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
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_ScaleModeNearest);
|
|
||||||
|
|
||||||
this->TexturePos.x = Buf.Xpos;
|
int pixelCount = Buf.Width * Buf.Height;
|
||||||
this->TexturePos.y = Buf.Ypos;
|
uint32_t *srcPixels = reinterpret_cast<uint32_t *>(Buf.PNGdata);
|
||||||
this->TextureSize.width = Buf.Width;
|
uint32_t *dstPixels = new uint32_t[pixelCount];
|
||||||
this->TextureSize.height = Buf.Height;
|
for (int i = 0; i < pixelCount; ++i)
|
||||||
this->TextureFramepos.width = Buf.FrameXpos;
|
{
|
||||||
this->TextureFramepos.height = Buf.FrameYpos;
|
uint8_t b = (srcPixels[i] >> 0) & 0xFF; // 蓝
|
||||||
|
uint8_t g = (srcPixels[i] >> 8) & 0xFF; // 绿
|
||||||
|
uint8_t r = (srcPixels[i] >> 16) & 0xFF; // 红
|
||||||
|
uint8_t a = (srcPixels[i] >> 24) & 0xFF; // 透明
|
||||||
|
dstPixels[i] = (a << 24) | (b << 16) | (g << 8) | r; // 重组为 RGBA
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成OpenGL纹理
|
||||||
|
glGenTextures(1, &m_TextureID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||||||
|
|
||||||
|
// 设置纹理参数(保持与原有SDL纹理相同的采样模式)
|
||||||
|
// 环绕方式:重复
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
// 过滤方式:最近邻(与SDL_ScaleModeNearest对应)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// 处理像素对齐(SDL表面可能有不同的行对齐方式)
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
// 记录纹理信息
|
||||||
|
m_TextureSize.width = Buf.Width;
|
||||||
|
m_TextureSize.height = Buf.Height;
|
||||||
|
m_FrameSize.width = Buf.FrameXpos;
|
||||||
|
m_FrameSize.height = Buf.FrameYpos;
|
||||||
|
m_TexturePos.x = Buf.Xpos;
|
||||||
|
m_TexturePos.y = Buf.Ypos;
|
||||||
|
|
||||||
|
// 上传纹理数据到GPU
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0, // 基础纹理级别
|
||||||
|
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||||||
|
m_TextureSize.width,
|
||||||
|
m_TextureSize.height,
|
||||||
|
0, // 无边框
|
||||||
|
GL_RGBA, // 源数据格式(根据实际数据格式调整)
|
||||||
|
GL_UNSIGNED_BYTE, // 源数据类型
|
||||||
|
dstPixels);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture()
|
bool Texture::Init(SDL_Surface *rgbaSurface)
|
||||||
{
|
{
|
||||||
SDL_DestroyTexture(m_texture);
|
// 生成OpenGL纹理
|
||||||
|
glGenTextures(1, &m_TextureID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||||||
|
|
||||||
|
// 环绕方式
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
// 缩小过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
// 放大过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// 处理像素对齐(确保SDL的像素行对齐与OpenGL兼容)
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
// 记录纹理信息
|
||||||
|
m_TextureSize.width = rgbaSurface->w;
|
||||||
|
m_TextureSize.height = rgbaSurface->h;
|
||||||
|
m_FrameSize.width = rgbaSurface->w;
|
||||||
|
m_FrameSize.height = rgbaSurface->h;
|
||||||
|
|
||||||
|
// 将像素数据上传到GPU
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0, // 纹理级别(基础级)
|
||||||
|
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||||||
|
m_TextureSize.width,
|
||||||
|
m_TextureSize.height,
|
||||||
|
0, // 边框(必须为0)
|
||||||
|
GL_RGBA, // 源数据格式(与SDL转换后的格式一致)
|
||||||
|
GL_UNSIGNED_BYTE, // 源数据类型(无符号字节)
|
||||||
|
rgbaSurface->pixels);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Texture *Texture::GetTexture()
|
bool Texture::Init(VecSize size)
|
||||||
{
|
{
|
||||||
return m_texture;
|
glGenTextures(1, &m_TextureID);
|
||||||
}
|
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||||||
|
// 设置纹理参数(根据需求调整尺寸、格式)
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0, // 多级渐远纹理级别
|
||||||
|
GL_RGBA, // 内部格式(存储格式)
|
||||||
|
size.width, // 纹理宽度
|
||||||
|
size.height, // 纹理高度
|
||||||
|
0, // 边框(必须为0)
|
||||||
|
GL_RGBA, // 源数据格式
|
||||||
|
GL_UNSIGNED_BYTE, // 源数据类型
|
||||||
|
nullptr // 初始数据(为空,后续绘制填充)
|
||||||
|
);
|
||||||
|
|
||||||
RefPtr<Texture> Texture::GetTextureCopy()
|
// 记录纹理信息
|
||||||
{
|
m_TextureSize = size;
|
||||||
RefPtr<Texture> nt = new Texture(this->ImgPath, this->Index);
|
m_FrameSize = size;
|
||||||
return nt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Texture::SetBlendMode(SDL_BlendMode blendMode)
|
// 环绕方式
|
||||||
{
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
SDL_SetTextureBlendMode(m_texture, blendMode);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
}
|
// 缩小过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
// 放大过滤:使用最近邻采样
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
SDL_BlendMode Texture::GetBlendMode()
|
glBindTexture(GL_TEXTURE_2D, 0); // 解绑
|
||||||
{
|
return true;
|
||||||
SDL_BlendMode blendMode;
|
}
|
||||||
SDL_GetTextureBlendMode(m_texture, &blendMode);
|
|
||||||
return blendMode;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,33 +1,59 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <SDL_image.h>
|
||||||
|
#include <glad/glad.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Tool/RefPtr.h"
|
#include "Tool/Common.h"
|
||||||
#include "Tool/RefObject.h"
|
#include "Tool/RefObject.h"
|
||||||
|
#include "Tool/RefPtr.h"
|
||||||
|
#include "Tool/IntrusiveList.hpp"
|
||||||
|
|
||||||
class Texture : public RefObject
|
class Texture : public RefObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SDL_Texture *m_texture = nullptr;
|
// OpenGL 纹理ID
|
||||||
std::string ImgPath = "";
|
GLuint m_TextureID;
|
||||||
int Index = 0;
|
// 纹理大小
|
||||||
public:
|
VecSize m_TextureSize;
|
||||||
VecSize TextureSize = {0, 0}; // 纹理大小
|
// 帧域大小
|
||||||
VecPos TexturePos = {0, 0}; // 纹理位置
|
VecSize m_FrameSize;
|
||||||
VecSize TextureFramepos = {0, 0}; // 帧域宽高
|
// 纹理坐标
|
||||||
|
VecPos m_TexturePos;
|
||||||
|
// 纹理透明度
|
||||||
|
float m_Alpha = 1.0f;
|
||||||
|
|
||||||
|
// 纹理路径
|
||||||
|
std::string m_Path;
|
||||||
|
// 纹理编号(可选 在使用img构造时才会有编号)
|
||||||
|
int m_TextureIndex = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Texture(/* args */);
|
Texture(/* args */);
|
||||||
Texture(std::string PngPath);
|
|
||||||
Texture(std::string imgPath, int Index);
|
|
||||||
~Texture();
|
~Texture();
|
||||||
|
Texture(const Texture &) = delete;
|
||||||
|
Texture &operator=(const Texture &) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetBlendMode(SDL_BlendMode blendMode);
|
// 获取纹理ID
|
||||||
// 获取混合模式
|
GLuint getID() const { return m_TextureID; }
|
||||||
SDL_BlendMode GetBlendMode();
|
// 设置纹理透明度
|
||||||
// 获取纹理
|
void setAlpha(float alpha) { m_Alpha = alpha; }
|
||||||
SDL_Texture *GetTexture();
|
// 获取纹理透明度
|
||||||
// 获取一个拷贝的纹理
|
float getAlpha() const { return m_Alpha; }
|
||||||
RefPtr<Texture> GetTextureCopy();
|
// 获取纹理大小
|
||||||
|
VecSize getSize() const { return m_TextureSize; }
|
||||||
|
// 获取纹理坐标
|
||||||
|
VecPos getPos() const { return m_TexturePos; }
|
||||||
|
// 获取纹理路径
|
||||||
|
std::string getPath() const { return m_Path; }
|
||||||
|
// 获取纹理编号
|
||||||
|
int getIndex() const { return m_TextureIndex; }
|
||||||
|
// 获取帧域大小
|
||||||
|
VecSize getFrameSize() const { return m_FrameSize; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Init(std::string PngPath);
|
||||||
|
bool Init(std::string ImgPath, int index);
|
||||||
|
bool Init(SDL_Surface *surface);
|
||||||
|
bool Init(VecSize size);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -85,6 +85,11 @@ typedef struct VecPos
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 乘法
|
||||||
|
VecPos operator*(float value) const
|
||||||
|
{
|
||||||
|
return VecPos(x * value, y * value);
|
||||||
|
}
|
||||||
} VecPos;
|
} VecPos;
|
||||||
|
|
||||||
// 浮点数坐标向量
|
// 浮点数坐标向量
|
||||||
@@ -195,6 +200,12 @@ typedef struct VecSize
|
|||||||
height -= other.height;
|
height -= other.height;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 乘法
|
||||||
|
VecSize operator*(float value) const
|
||||||
|
{
|
||||||
|
return VecSize(width * value, height * value);
|
||||||
|
}
|
||||||
} VecSize;
|
} VecSize;
|
||||||
|
|
||||||
typedef struct VecPos3
|
typedef struct VecPos3
|
||||||
@@ -247,4 +258,10 @@ typedef struct VecSpeed3
|
|||||||
{
|
{
|
||||||
return x == other.x && y == other.y && z == other.z;
|
return x == other.x && y == other.y && z == other.z;
|
||||||
}
|
}
|
||||||
} VecSpeed3;
|
} VecSpeed3;
|
||||||
|
|
||||||
|
enum LE_BlEND_MODE
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
LINEARDODGE
|
||||||
|
};
|
||||||
@@ -54,4 +54,19 @@ std::string Tool_TruncatePath(const std::string &path)
|
|||||||
|
|
||||||
// 如果没有找到 '/',返回原字符串(或根据需求返回空)
|
// 如果没有找到 '/',返回原字符串(或根据需求返回空)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Tool_get_file_size(const std::string &path)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(path.c_str(), "rb");
|
||||||
|
if (file == nullptr)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
int size = ftell(file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ std::string Tool_toLowerCase(const std::string &str);
|
|||||||
|
|
||||||
std::string Tool_RegRealPath(const std::string &Path);
|
std::string Tool_RegRealPath(const std::string &Path);
|
||||||
|
|
||||||
std::string Tool_TruncatePath(const std::string &path);
|
std::string Tool_TruncatePath(const std::string &path);
|
||||||
|
|
||||||
|
int Tool_get_file_size(const std::string &path);
|
||||||
@@ -78,7 +78,9 @@ bool SquirrelEx::Compilebuffer(std::string Path, std::string Code)
|
|||||||
|
|
||||||
void SquirrelEx::Init()
|
void SquirrelEx::Init()
|
||||||
{
|
{
|
||||||
v = sq_open(1024); // 栈大小1024
|
// 初始化虚拟机
|
||||||
|
if (v == nullptr)
|
||||||
|
v = sq_open(1024); // 栈大小1024
|
||||||
sqstd_seterrorhandlers(v);
|
sqstd_seterrorhandlers(v);
|
||||||
sq_pushroottable(v);
|
sq_pushroottable(v);
|
||||||
sqstd_register_bloblib(v);
|
sqstd_register_bloblib(v);
|
||||||
@@ -89,6 +91,20 @@ void SquirrelEx::Init()
|
|||||||
|
|
||||||
sq_setprintfunc(v, printfunc, errorfunc);
|
sq_setprintfunc(v, printfunc, errorfunc);
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
#else
|
||||||
|
// 获取工作目录 (switch 不允许)
|
||||||
|
WorkPath = SDL_GetBasePath();
|
||||||
|
FILE *file1 = fopen("DevMode.ini", "rb");
|
||||||
|
if (file1)
|
||||||
|
{
|
||||||
|
sq_enabledebuginfo(v, true);
|
||||||
|
|
||||||
|
dbg = sqdbg_attach_debugger(v);
|
||||||
|
sqdbg_listen_socket(dbg, 2222);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 加载脚本
|
// 加载脚本
|
||||||
LoadLocalScript();
|
LoadLocalScript();
|
||||||
}
|
}
|
||||||
@@ -151,6 +167,14 @@ void SquirrelEx::LoadLocalScript()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string RegistPath = "sqr/" + clean_line;
|
std::string RegistPath = "sqr/" + clean_line;
|
||||||
|
|
||||||
|
#ifndef __SWITCH__
|
||||||
|
std::replace(RegistPath.begin(), RegistPath.end(), '/', '\\');
|
||||||
|
RegistPath = WorkPath + RegistPath;
|
||||||
|
|
||||||
|
_scriptmap[RegistPath] = Tool_get_file_size(RegistPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(RegistPath.c_str()), SQFalse, SQTrue)))
|
if (!SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(RegistPath.c_str()), SQFalse, SQTrue)))
|
||||||
{
|
{
|
||||||
SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
|
SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
|
||||||
@@ -198,6 +222,37 @@ void SquirrelEx::Run()
|
|||||||
sq_settop(v, top); // restores the original stack size
|
sq_settop(v, top); // restores the original stack size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SquirrelEx::Update(float Dt)
|
||||||
|
{
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
#else
|
||||||
|
sqdbg_frame(dbg);
|
||||||
|
|
||||||
|
// 热重载
|
||||||
|
if (HotReload)
|
||||||
|
{
|
||||||
|
for (auto &script : _scriptmap)
|
||||||
|
{
|
||||||
|
std::string path = script.first;
|
||||||
|
int value = script.second;
|
||||||
|
int newvalue = Tool_get_file_size(path);
|
||||||
|
if (value != newvalue)
|
||||||
|
{
|
||||||
|
if (SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(path.c_str()), SQFalse, SQTrue)))
|
||||||
|
{
|
||||||
|
SDL_Log("脚本文件热重载成功 %s", path.c_str());
|
||||||
|
_scriptmap[path] = newvalue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SDL_Log("脚本文件热重载失败 %s", path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void SquirrelEx::Clean()
|
void SquirrelEx::Clean()
|
||||||
{
|
{
|
||||||
sq_close(v);
|
sq_close(v);
|
||||||
|
|||||||
@@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
#include "Tool/Tool_Network.h"
|
#include "Tool/Tool_Network.h"
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
#else
|
||||||
|
#include "sqdbg.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SQUNICODE
|
#ifdef SQUNICODE
|
||||||
|
|
||||||
#define scvprintf vfwprintf
|
#define scvprintf vfwprintf
|
||||||
@@ -50,6 +55,7 @@ public:
|
|||||||
void LoadLocalScript();
|
void LoadLocalScript();
|
||||||
// 运行
|
// 运行
|
||||||
void Run();
|
void Run();
|
||||||
|
void Update(float Dt);
|
||||||
// 清理
|
// 清理
|
||||||
void Clean();
|
void Clean();
|
||||||
|
|
||||||
@@ -60,5 +66,16 @@ private:
|
|||||||
SquirrelEx(/* args */);
|
SquirrelEx(/* args */);
|
||||||
~SquirrelEx();
|
~SquirrelEx();
|
||||||
HSQUIRRELVM v = nullptr;
|
HSQUIRRELVM v = nullptr;
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
#else
|
||||||
|
// 虚拟机调试对象
|
||||||
|
HSQDEBUGSERVER dbg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//工作目录
|
||||||
|
std::string WorkPath;
|
||||||
|
//热重载
|
||||||
|
bool HotReload = true;
|
||||||
|
std::map<std::string, int> _scriptmap;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ void GameMap::AddObject(RefPtr<BaseObject> object)
|
|||||||
if (object->m_objecttype == ObjectType::CHARACTER)
|
if (object->m_objecttype == ObjectType::CHARACTER)
|
||||||
{
|
{
|
||||||
CharacterObject *chr = (CharacterObject *)(object.Get());
|
CharacterObject *chr = (CharacterObject *)(object.Get());
|
||||||
_LayerMap["bottom"]->AddComponent(chr->_Shadow);
|
if( chr->_Shadow != nullptr)_LayerMap["bottom"]->AddComponent(chr->_Shadow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ GameMapLayer::~GameMapLayer()
|
|||||||
void GameMapLayer::Render()
|
void GameMapLayer::Render()
|
||||||
{
|
{
|
||||||
Actor::Render();
|
Actor::Render();
|
||||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||||
// 设置绘制颜色
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
|
|
||||||
// 自身坐标
|
// 自身坐标
|
||||||
float Xpos = GetIterationPos().x + GetPos().x;
|
float Xpos = GetIterationPos().x + GetPos().x;
|
||||||
float Ypos = GetIterationPos().y + GetPos().y;
|
float Ypos = GetIterationPos().y + GetPos().y;
|
||||||
@@ -25,10 +24,8 @@ void GameMapLayer::Render()
|
|||||||
buf.y = info.y + Ypos;
|
buf.y = info.y + Ypos;
|
||||||
buf.w = info.w;
|
buf.w = info.w;
|
||||||
buf.h = info.h;
|
buf.h = info.h;
|
||||||
// 绘制填充矩形
|
//TODO: 渲染可行区域
|
||||||
SDL_RenderFillRect(renderer, &buf);
|
|
||||||
}
|
}
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 250);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size)
|
void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size)
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ Tile::Tile(std::string Path) : Sprite()
|
|||||||
if (std::get<std::string>(m_data["path"]) == "")
|
if (std::get<std::string>(m_data["path"]) == "")
|
||||||
m_data["path"] = "sprite/character/common/circlecooltime.img";
|
m_data["path"] = "sprite/character/common/circlecooltime.img";
|
||||||
|
|
||||||
m_texture = new Texture(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
|
m_texture = new Texture();
|
||||||
|
m_texture->Init(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
|
||||||
Sprite::Init();
|
Sprite::Init();
|
||||||
this->imgPath = Path;
|
this->imgPath = Path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ void CharacterObject::Construction(int job)
|
|||||||
// 创建装备管理器
|
// 创建装备管理器
|
||||||
_EquipmentManager = new Chr_Equipment();
|
_EquipmentManager = new Chr_Equipment();
|
||||||
_EquipmentManager->Init(this);
|
_EquipmentManager->Init(this);
|
||||||
// 创建阴影对象
|
// // 创建阴影对象
|
||||||
_Shadow = new Chr_Shadow();
|
// _Shadow = new Chr_Shadow();
|
||||||
_Shadow->Init(this);
|
// _Shadow->Init(this);
|
||||||
// 创建动画管理器(一定要先创建装备管理器再创建动画管理器 因为需要读取身上的装备)
|
// 创建动画管理器(一定要先创建装备管理器再创建动画管理器 因为需要读取身上的装备)
|
||||||
_AnimationManager = new Chr_Animation();
|
_AnimationManager = new Chr_Animation();
|
||||||
_AnimationManager->Init(this);
|
_AnimationManager->Init(this);
|
||||||
|
|||||||
@@ -33,17 +33,17 @@ void Chr_Animation::CreateSkinmationBySlot(std::string actionName, std::string s
|
|||||||
// 构造好Ani以后 统一设置为不可见 然后放入ActionAnis表
|
// 构造好Ani以后 统一设置为不可见 然后放入ActionAnis表
|
||||||
RefPtr<Animation> Ani = new Animation(path, FormatImgPath, Data);
|
RefPtr<Animation> Ani = new Animation(path, FormatImgPath, Data);
|
||||||
Ani->SetVisible(false);
|
Ani->SetVisible(false);
|
||||||
|
|
||||||
Ani->SetRenderZOrder(Variation.Layer);
|
Ani->SetRenderZOrder(Variation.Layer);
|
||||||
this->AddChild(Ani);
|
this->AddChild(Ani);
|
||||||
ActionAnis[actionName].push_back(Ani);
|
ActionAnis[actionName].push_back(Ani);
|
||||||
|
|
||||||
// 构造一下阴影对象
|
// 构造一下阴影对象 //TODO
|
||||||
RefPtr<Animation> ShadowAni = new Animation(path, FormatImgPath, Data);
|
// RefPtr<Animation> ShadowAni = new Animation(path, FormatImgPath, Data);
|
||||||
ShadowAni->SetVisible(false);
|
// ShadowAni->SetVisible(false);
|
||||||
// 皮肤统一设置阴影
|
|
||||||
ShadowAni->SetShadow();
|
// chr_parent->_Shadow->AddChild(ShadowAni);
|
||||||
chr_parent->_Shadow->AddChild(ShadowAni);
|
// chr_parent->_Shadow->ActionAnis[actionName].push_back(ShadowAni);
|
||||||
chr_parent->_Shadow->ActionAnis[actionName].push_back(ShadowAni);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ void Chr_Animation::Init(CharacterObject *parent)
|
|||||||
parent->AddChild(this);
|
parent->AddChild(this);
|
||||||
chr_parent = parent;
|
chr_parent = parent;
|
||||||
GlobalCharacterScript::CharacterConfig Config = Global_Game::GetInstance().CharacterConfigs[parent->Job];
|
GlobalCharacterScript::CharacterConfig Config = Global_Game::GetInstance().CharacterConfigs[parent->Job];
|
||||||
|
|
||||||
// 遍历所有动作Ani路径
|
// 遍历所有动作Ani路径
|
||||||
for (const auto &pair : Config.animationPath)
|
for (const auto &pair : Config.animationPath)
|
||||||
{
|
{
|
||||||
@@ -116,5 +116,5 @@ void Chr_Animation::SetAction(std::string actionName)
|
|||||||
CurrentActionTag = actionName;
|
CurrentActionTag = actionName;
|
||||||
|
|
||||||
// 设置阴影的动作
|
// 设置阴影的动作
|
||||||
chr_parent->_Shadow->SetAction(actionName);
|
if(chr_parent->_Shadow)chr_parent->_Shadow->SetAction(actionName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,23 @@ static SQInteger SQR_SetPos(HSQUIRRELVM v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SQInteger SQR_GetWorldPos(HSQUIRRELVM v)
|
||||||
|
{
|
||||||
|
SQUserPointer A_obj;
|
||||||
|
sq_getuserpointer(v, 2, &A_obj);
|
||||||
|
Actor *Aobj = (Actor *)A_obj;
|
||||||
|
VecFPos Pos = Aobj->GetWorldPos();
|
||||||
|
|
||||||
|
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_GetAlpha(HSQUIRRELVM v)
|
static SQInteger SQR_GetAlpha(HSQUIRRELVM v)
|
||||||
{
|
{
|
||||||
SQUserPointer A_obj;
|
SQUserPointer A_obj;
|
||||||
@@ -287,6 +304,16 @@ static SQInteger SQR_SetSize(HSQUIRRELVM v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SQInteger SQR_SetVisible(HSQUIRRELVM v){
|
||||||
|
SQUserPointer A_obj;
|
||||||
|
sq_getuserpointer(v, 2, &A_obj);
|
||||||
|
SQBool Value;
|
||||||
|
sq_getbool(v, 3, &Value);
|
||||||
|
Actor *Aobj = (Actor *)A_obj;
|
||||||
|
Aobj->SetVisible(Value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static SQInteger SQR_CreateSprite(HSQUIRRELVM v)
|
static SQInteger SQR_CreateSprite(HSQUIRRELVM v)
|
||||||
{
|
{
|
||||||
const SQChar *ImgPath;
|
const SQChar *ImgPath;
|
||||||
@@ -323,6 +350,7 @@ static void RegisterUI()
|
|||||||
RegisterUINutApi(_SC("sq_SetZOrder"), SQR_SetZOrder, v);
|
RegisterUINutApi(_SC("sq_SetZOrder"), SQR_SetZOrder, v);
|
||||||
RegisterUINutApi(_SC("sq_GetPos"), SQR_GetPos, v);
|
RegisterUINutApi(_SC("sq_GetPos"), SQR_GetPos, v);
|
||||||
RegisterUINutApi(_SC("sq_SetPos"), SQR_SetPos, v);
|
RegisterUINutApi(_SC("sq_SetPos"), SQR_SetPos, v);
|
||||||
|
RegisterUINutApi(_SC("sq_GetWorldPos"), SQR_GetWorldPos, v);
|
||||||
RegisterUINutApi(_SC("sq_GetAlpha"), SQR_GetAlpha, v);
|
RegisterUINutApi(_SC("sq_GetAlpha"), SQR_GetAlpha, v);
|
||||||
RegisterUINutApi(_SC("sq_SetAlpha"), SQR_SetAlpha, v);
|
RegisterUINutApi(_SC("sq_SetAlpha"), SQR_SetAlpha, v);
|
||||||
RegisterUINutApi(_SC("sq_GetScale"), SQR_GetScale, v);
|
RegisterUINutApi(_SC("sq_GetScale"), SQR_GetScale, v);
|
||||||
@@ -331,6 +359,7 @@ static void RegisterUI()
|
|||||||
RegisterUINutApi(_SC("sq_SetRotation"), SQR_SetRotation, v);
|
RegisterUINutApi(_SC("sq_SetRotation"), SQR_SetRotation, v);
|
||||||
RegisterUINutApi(_SC("sq_GetSize"), SQR_GetSize, v);
|
RegisterUINutApi(_SC("sq_GetSize"), SQR_GetSize, v);
|
||||||
RegisterUINutApi(_SC("sq_SetSize"), SQR_SetSize, v);
|
RegisterUINutApi(_SC("sq_SetSize"), SQR_SetSize, v);
|
||||||
|
RegisterUINutApi(_SC("sq_SetVisible"), SQR_SetVisible, v);
|
||||||
|
|
||||||
RegisterUINutApi(_SC("sq_CreateSprite"), SQR_CreateSprite, v);
|
RegisterUINutApi(_SC("sq_CreateSprite"), SQR_CreateSprite, v);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ Global_Game::~Global_Game()
|
|||||||
void Global_Game::Init()
|
void Global_Game::Init()
|
||||||
{
|
{
|
||||||
// 初始化ttf字体资源
|
// 初始化ttf字体资源
|
||||||
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/LXGWWenKai-Regular.ttf", 24);
|
|
||||||
TTF_Font *FontBuf = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 24);
|
TTF_Font *FontBuf = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 24);
|
||||||
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gothica-Book.ttf", 24);
|
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/NotoSansSC-Regular.otf", 24);
|
||||||
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gasinamu.ttf", 24);
|
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/calibri.ttf", 24);
|
||||||
|
|
||||||
if (!FontBuf)
|
if (!FontBuf)
|
||||||
{
|
{
|
||||||
SDL_LogError(0, "字体加载失败: %s", TTF_GetError());
|
SDL_LogError(0, "字体加载失败: %s", TTF_GetError());
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void Scene_Loading_UI::Enter()
|
|||||||
RefPtr<Sprite> LoadCircleSp = new Sprite("ImagePacks2/Loading2.png");
|
RefPtr<Sprite> LoadCircleSp = new Sprite("ImagePacks2/Loading2.png");
|
||||||
LoadCircleSp->SetName("LoadCircle");
|
LoadCircleSp->SetName("LoadCircle");
|
||||||
LoadCircleSp->SetPos(VecFPos{1280 - 60, 686 - 60});
|
LoadCircleSp->SetPos(VecFPos{1280 - 60, 686 - 60});
|
||||||
LoadCircleSp->SetBlendMode(SDL_BLENDMODE_ADD);
|
LoadCircleSp->SetBlendMode(LINEARDODGE);
|
||||||
LoadCircleSp->SetAnchor(VecFPos{0.5f, 0.5f});
|
LoadCircleSp->SetAnchor(VecFPos{0.5f, 0.5f});
|
||||||
actor->AddComponent(LoadCircleSp);
|
actor->AddComponent(LoadCircleSp);
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,59 @@ void Scene_MainUi::Enter()
|
|||||||
sq_call(v, 2, SQFalse, SQTrue);
|
sq_call(v, 2, SQFalse, SQTrue);
|
||||||
}
|
}
|
||||||
sq_settop(v, top);
|
sq_settop(v, top);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene_MainUi::HandleEvents(SDL_Event *e)
|
void Scene_MainUi::HandleEvents(SDL_Event *event)
|
||||||
{
|
{
|
||||||
Scene::HandleEvents(e);
|
SQInteger EventType = -1;
|
||||||
|
std::vector<SQInteger> EventData;
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
// 鼠标移动
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
{
|
||||||
|
EventType = 0;
|
||||||
|
EventData.push_back(event->motion.x);
|
||||||
|
EventData.push_back(event->motion.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 鼠标按键按下
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
EventType = 1;
|
||||||
|
EventData.push_back(event->button.button);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 鼠标按键释放
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
{
|
||||||
|
EventType = 2;
|
||||||
|
EventData.push_back(event->button.button);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 鼠标滚轮
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
EventType = 3;
|
||||||
|
EventData.push_back(event->wheel.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 键盘按键按下
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
EventType = 4;
|
||||||
|
EventData.push_back(event->key.keysym.sym);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 键盘按键释放
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
EventType = 5;
|
||||||
|
EventData.push_back(event->key.keysym.sym);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||||
SQInteger top = sq_gettop(v);
|
SQInteger top = sq_gettop(v);
|
||||||
sq_pushroottable(v);
|
sq_pushroottable(v);
|
||||||
@@ -29,8 +76,14 @@ void Scene_MainUi::HandleEvents(SDL_Event *e)
|
|||||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||||
{
|
{
|
||||||
sq_pushroottable(v);
|
sq_pushroottable(v);
|
||||||
sq_pushinteger(v, 1);
|
sq_pushinteger(v, EventType);
|
||||||
sq_call(v, 2, SQFalse, SQTrue);
|
sq_newarray(v, 0);
|
||||||
|
for (SQInteger i = 0; i < EventData.size(); i++)
|
||||||
|
{
|
||||||
|
sq_pushinteger(v, EventData[i]);
|
||||||
|
sq_arrayappend(v, -2);
|
||||||
|
}
|
||||||
|
sq_call(v, 3, SQFalse, SQTrue);
|
||||||
}
|
}
|
||||||
sq_settop(v, top);
|
sq_settop(v, top);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "Scene_Test.h"
|
#include "Scene_Test.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <EngineCore/Game.h>
|
#include "EngineCore/Game.h"
|
||||||
#include <EngineFrame/Component/AnimationManager.h>
|
#include "EngineFrame/Component/AnimationManager.h"
|
||||||
|
#include "EngineFrame/Component/Text.h"
|
||||||
|
#include "EngineFrame/Component/Canvas.h"
|
||||||
|
#include "Global/Global_Game.h"
|
||||||
Scene_Test::Scene_Test()
|
Scene_Test::Scene_Test()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -13,44 +16,55 @@ Scene_Test::~Scene_Test()
|
|||||||
|
|
||||||
void Scene_Test::Enter()
|
void Scene_Test::Enter()
|
||||||
{
|
{
|
||||||
map = new GameMap;
|
// SetScale(VecFPos(1.2f, 1.2f));
|
||||||
map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map");
|
// map = new GameMap;
|
||||||
map->Enter(this);
|
// map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map");
|
||||||
|
// map->Enter(this);
|
||||||
|
|
||||||
RefPtr<CharacterObject> obj = new CharacterObject();
|
// RefPtr<CharacterObject> obj = new CharacterObject();
|
||||||
obj->SetPosition({1000, 300, 0});
|
// obj->SetPosition({1000, 300, 0});
|
||||||
obj->Construction(0);
|
// obj->Construction(0);
|
||||||
|
|
||||||
RefPtr<MonsterObject> monster = new MonsterObject();
|
// RefPtr<MonsterObject> monster = new MonsterObject();
|
||||||
monster->SetPosition({1200, 301, 0});
|
// monster->SetPosition({1200, 301, 0});
|
||||||
monster->Construction(1);
|
// monster->Construction(1);
|
||||||
monster->SetDirection(1);
|
// monster->SetDirection(1);
|
||||||
|
|
||||||
map->AddObject(obj);
|
// map->AddObject(obj);
|
||||||
map->AddObject(monster);
|
// map->AddObject(monster);
|
||||||
|
|
||||||
_camera = new GameMapCamera;
|
// _camera = new GameMapCamera;
|
||||||
_camera->SetFromActor(obj.Get());
|
// _camera->SetFromActor(obj.Get());
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// SDL_Log("Scene_Test::进入测试场景!");
|
// // SDL_Log("Scene_Test::进入测试场景!");
|
||||||
RefPtr<Actor> actor = new Actor;
|
RefPtr<Actor> actor = new Actor;
|
||||||
AddChild(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);
|
RefPtr<Sprite> sprite = new Sprite("ImagePacks2/test_white_background.png");
|
||||||
|
|
||||||
|
RefPtr<Sprite> chr = new Sprite("sprite/interface2/hud/hud.img", 0);
|
||||||
// chr->SetPos(VecFPos{200, 100});
|
// chr->SetPos(VecFPos{200, 100});
|
||||||
// chr->SetAlpha(0.5);
|
// chr->SetAlpha(0.5);
|
||||||
// chr->SetShadow();
|
// chr->SetShadow();
|
||||||
// actor->AddComponent(chr);
|
actor->AddComponent(chr);
|
||||||
|
|
||||||
RefPtr<AnimationManager> Am = new AnimationManager;
|
// RefPtr<Canvas> canvas = new Canvas(VecSize{1280, 720});
|
||||||
RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani");
|
// actor->AddChild(canvas);
|
||||||
Am->AddAnimation(ani4);
|
|
||||||
|
|
||||||
// Am->SetPos(VecFPos{200, 100});
|
// canvas->AddChild(chr);
|
||||||
actor->AddChild(Am);
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// RefPtr<Text> text = new Text();
|
||||||
|
// text->Init("测试文本", Global_Game::GetInstance().Fonts[0], SDL_Color{255, 255, 255, 255});
|
||||||
|
// text->SetPos(VecFPos{200, 100});
|
||||||
|
// actor->AddChild(text);
|
||||||
|
|
||||||
// // sprite2->UnsetClipRect();
|
// // sprite2->UnsetClipRect();
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ int main(int argc, char *argv[])
|
|||||||
Asset_Script::GetInstance();
|
Asset_Script::GetInstance();
|
||||||
// 初始化线程池
|
// 初始化线程池
|
||||||
ThreadPool::GetInstance();
|
ThreadPool::GetInstance();
|
||||||
|
|
||||||
// 初始化日志系统
|
// 初始化日志系统
|
||||||
// Logger::GetInstance().Init();
|
// Logger::GetInstance().Init();
|
||||||
// 初始化Squirrel脚本系统
|
// 初始化Squirrel脚本系统
|
||||||
|
|||||||
Reference in New Issue
Block a user