232 lines
6.0 KiB
C++
232 lines
6.0 KiB
C++
#include "Game.h"
|
||
#include "squirrel/SquirrelEx.h"
|
||
#include "EngineFrame/Component/Sprite.h"
|
||
#include "EngineFrame/Base/Actor.h"
|
||
#include "EngineFrame/Component/Text.h"
|
||
|
||
Game::Game()
|
||
{
|
||
}
|
||
|
||
Game::~Game()
|
||
{
|
||
Clear();
|
||
}
|
||
|
||
void Game::Init(std::function<void()> CallBack)
|
||
{
|
||
|
||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||
SDL_JoystickEventState(SDL_ENABLE);
|
||
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); // 双缓冲
|
||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); // 24位深度缓冲(避免z-fighting)
|
||
|
||
// 启用多重采样(关键步骤)
|
||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // 启用多重采样缓冲
|
||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||
|
||
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not initialize! Error: %s\n", SDL_GetError());
|
||
m_isRunning = false;
|
||
}
|
||
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)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Window! Error: %s\n", SDL_GetError());
|
||
m_isRunning = false;
|
||
}
|
||
// 关闭原生鼠标
|
||
SDL_ShowCursor(0);
|
||
|
||
// 打开所有检测到的控制器
|
||
int numControllers = SDL_NumJoysticks();
|
||
for (int i = 0; i < numControllers; i++)
|
||
{
|
||
if (SDL_IsGameController(i))
|
||
{
|
||
SDL_GameController *controller = SDL_GameControllerOpen(i);
|
||
if (controller)
|
||
{
|
||
SDL_Log("成功打开控制器: %s", SDL_GameControllerName(controller));
|
||
}
|
||
else
|
||
{
|
||
SDL_Log("无法打开控制器 %d! SDL错误: %s", i, SDL_GetError());
|
||
}
|
||
}
|
||
}
|
||
// 创建OpenGL渲染器
|
||
m_renderer = new RenderManager(m_window);
|
||
|
||
IMG_Init(IMG_INIT_PNG);
|
||
|
||
// 初始化SDL_mixer,支持OGG格式
|
||
// 44100: 采样率, MIX_DEFAULT_FORMAT: 音频格式, 2: 声道数(立体声), 4096: 缓冲区大小
|
||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL_mixer初始化失败! Mix_Error: %s\n", Mix_GetError());
|
||
m_isRunning = false;
|
||
}
|
||
|
||
// 初始化 TTF
|
||
if (TTF_Init() == -1)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF 初始化失败!TTF_Error: %s\n", TTF_GetError());
|
||
m_isRunning = false;
|
||
}
|
||
// SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
|
||
CallBack();
|
||
}
|
||
|
||
void Game::Run()
|
||
{
|
||
// 计算帧时间
|
||
m_frameTime = 1000.0 / m_Settingfps;
|
||
|
||
while (m_isRunning)
|
||
{
|
||
// 帧开始时间
|
||
Uint64 frameStart = SDL_GetTicks64();
|
||
SDL_Event m_event;
|
||
HandleEvents(&m_event);
|
||
Update(m_deltaTime);
|
||
Render();
|
||
|
||
// 帧率统计 每一秒钟的时候记录一次帧率
|
||
m_frameCounter++;
|
||
Uint64 currentTime = SDL_GetTicks64();
|
||
if (currentTime - m_lastFpsPrintTime >= 1000)
|
||
{
|
||
m_fps = m_frameCounter;
|
||
m_lastFpsPrintTime = currentTime;
|
||
m_frameCounter = 0;
|
||
}
|
||
|
||
// 计算实际总帧时间(关键修改)
|
||
Uint64 diff = SDL_GetTicks64() - frameStart; // 处理耗时
|
||
if (diff < m_frameTime)
|
||
{
|
||
SDL_Delay(m_frameTime - diff); // 尝试延迟补全
|
||
}
|
||
// 延迟后,重新计算从帧开始到现在的总时间(包含可能的延迟误差)
|
||
Uint64 actualFrameTime = SDL_GetTicks64() - frameStart;
|
||
m_deltaTime = actualFrameTime / 1000.0f; // 用实际总时间更新deltaTime
|
||
m_frameTime_ms = actualFrameTime;
|
||
}
|
||
}
|
||
|
||
void Game::HandleEvents(SDL_Event *e)
|
||
{
|
||
while (SDL_PollEvent(e))
|
||
{
|
||
if (e->type == SDL_QUIT)
|
||
{
|
||
m_isRunning = false;
|
||
SDL_Log("Game Exit1");
|
||
}
|
||
else if (e->type == SDL_JOYBUTTONDOWN)
|
||
{
|
||
if (e->jbutton.button == JOY_PLUS)
|
||
{
|
||
m_isRunning = false;
|
||
SDL_Log("Game Exit2");
|
||
}
|
||
}
|
||
// 处理屏幕按下事件
|
||
else if (e->type == SDL_FINGERDOWN)
|
||
{
|
||
// 触发双击事件
|
||
SDL_Log("退出程序");
|
||
m_isRunning = false;
|
||
SDL_Log("Game Exit3");
|
||
}
|
||
|
||
if (m_scene != nullptr)
|
||
m_scene->HandleEvents(e);
|
||
if (m_uiScene != nullptr)
|
||
m_uiScene->HandleEvents(e);
|
||
}
|
||
}
|
||
|
||
void Game::Update(float deltaTime)
|
||
{
|
||
//调用松鼠的更新
|
||
SquirrelEx::GetInstance().Update(deltaTime);
|
||
if (m_scene != nullptr)
|
||
m_scene->Update(deltaTime);
|
||
if (m_uiScene != nullptr)
|
||
m_uiScene->Update(deltaTime);
|
||
}
|
||
|
||
void Game::Render()
|
||
{
|
||
// 调用预渲染
|
||
if (m_scene != nullptr)
|
||
m_scene->PreRender();
|
||
if (m_uiScene != nullptr)
|
||
m_uiScene->PreRender();
|
||
|
||
// 清空渲染器后渲染
|
||
m_renderer->ClearScreen();
|
||
if (m_scene != nullptr)
|
||
{
|
||
m_renderer->SetOrthoMatrixType(0);
|
||
m_scene->Render();
|
||
}
|
||
if (m_uiScene != nullptr)
|
||
{
|
||
m_renderer->SetOrthoMatrixType(1);
|
||
m_uiScene->Render();
|
||
}
|
||
m_renderer->SwapBuffer();
|
||
}
|
||
|
||
void Game::Clear()
|
||
{
|
||
if (m_scene != nullptr)
|
||
{
|
||
m_scene->Exit();
|
||
}
|
||
m_scene = nullptr;
|
||
if (m_uiScene != nullptr)
|
||
{
|
||
m_uiScene->Exit();
|
||
}
|
||
m_uiScene = nullptr;
|
||
IMG_Quit();
|
||
SDL_DestroyWindow(m_window);
|
||
SDL_Quit();
|
||
}
|
||
|
||
void Game::ChangeScene(RefPtr<Scene> scene)
|
||
{
|
||
if (m_scene != nullptr)
|
||
{
|
||
m_scene->Exit();
|
||
}
|
||
m_scene = scene;
|
||
m_scene->Enter();
|
||
}
|
||
|
||
void Game::ChangeUIScene(RefPtr<Scene> scene)
|
||
{
|
||
if (m_uiScene != nullptr)
|
||
{
|
||
m_uiScene->Exit();
|
||
}
|
||
m_uiScene = scene;
|
||
m_uiScene->Enter();
|
||
}
|
||
|
||
RenderManager *Game::GetRenderer()
|
||
{
|
||
return m_renderer;
|
||
}
|