Files
DNF_DEV/source/EngineCore/Game.cpp

225 lines
5.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Game.h"
#include "squirrel/SquirrelEx.h"
#include "EngineFrame/Component/Sprite.h"
#include "EngineFrame/Actor/Actor.h"
#include "EngineFrame/Component/Text.h"
#include "EngineFrame/Actor/Debug_Actor.h"
Game::Game()
{
}
Game::~Game()
{
Clear();
}
void Game::Init(std::function<void()> CallBack)
{
// 计算帧时间
m_frameTime = 1000 / m_fps;
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_JoystickEventState(SDL_ENABLE);
SDL_JoystickOpen(0);
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);
if (m_window == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL could not Create Window! Error: %s\n", SDL_GetError());
m_isRunning = false;
}
// 打开所有检测到的控制器
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());
}
}
}
// 创建渲染器
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
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);
// 初始化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");
// 构造调试对象
m_DebugInfoActor = new Debug_Actor();
CallBack();
}
void Game::Run()
{
while (m_isRunning)
{
u32 frameStart = SDL_GetTicks(); // 帧开始时间
SDL_Event m_event;
HandleEvents(&m_event);
Update(m_deltaTime); // 注意这里使用的是上一帧的deltaTime合理见说明
Render();
// 帧率统计(保持不变)
m_frameCount++;
u32 currentTime = SDL_GetTicks();
if (currentTime - m_lastFpsPrintTime >= 1000)
{
u32 fps = m_frameCount;
if (m_DebugInfoActor)
m_DebugInfoActor->FPS = fps;
m_lastFpsPrintTime = currentTime;
m_frameCount = 0;
}
// 计算实际总帧时间(关键修改)
u32 diff = SDL_GetTicks() - frameStart; // 处理耗时
if (diff < m_frameTime)
{
SDL_Delay(m_frameTime - diff); // 尝试延迟补全
}
// 延迟后,重新计算从帧开始到现在的总时间(包含可能的延迟误差)
u32 actualFrameTime = SDL_GetTicks() - frameStart;
m_deltaTime = actualFrameTime / 1000.0f; // 用实际总时间更新deltaTime
}
}
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)
{
if (m_scene != nullptr)
m_scene->Update(deltaTime);
if (m_uiScene != nullptr)
m_uiScene->Update(deltaTime);
// 调试信息
if (m_DebugInfoActor != nullptr)
{
m_DebugInfoActor->Update(deltaTime);
m_DebugInfoActor->RenderCount = RenderCount;
}
RenderCount = 0;
}
void Game::Render()
{
SDL_RenderClear(m_renderer);
if (m_scene != nullptr)
m_scene->Render();
if (m_uiScene != nullptr)
m_uiScene->Render();
if (m_DebugInfoActor != nullptr)
m_DebugInfoActor->Render();
SDL_RenderPresent(m_renderer);
}
void Game::Clear()
{
if (m_scene != nullptr)
{
m_scene->Exit();
}
m_scene = nullptr;
if (m_uiScene != nullptr)
{
m_uiScene->Exit();
}
m_uiScene = nullptr;
m_DebugInfoActor = nullptr;
IMG_Quit();
SDL_DestroyRenderer(m_renderer);
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();
}
SDL_Renderer *Game::GetRenderer()
{
return m_renderer;
}