#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 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; } // 创建渲染器 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); 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); Render(m_deltaTime); // -------------------------- 新增:帧率统计与输出 -------------------------- m_frameCount++; // 每帧递增计数器 u32 currentTime = SDL_GetTicks(); // 判断是否已过去 1 秒(1000 毫秒) if (currentTime - m_lastFpsPrintTime >= 1000) { // 计算帧率:总帧数 / 1秒 = 帧率(如 60 帧 → 60FPS) u32 fps = m_frameCount; // 输出帧率(用 SDL_Log 或 printf 均可,SDL_Log 更适配 SDL 日志系统) // SDL_Log("当前帧率:%d FPS | DeltaTime:%.4f 秒", fps, m_deltaTime); 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); m_deltaTime = m_frameTime / 1000.0f; } else { m_deltaTime = diff / 1000.0f; } } } 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"); } } 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); } void Game::Render(float deltaTime) { SDL_RenderClear(m_renderer); if (m_scene != nullptr) m_scene->Render(deltaTime); if (m_uiScene != nullptr) m_uiScene->Render(deltaTime); if (m_DebugInfoActor != nullptr) m_DebugInfoActor->Render(deltaTime); 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) { if (m_scene != nullptr) { m_scene->Exit(); } m_scene = scene; m_scene->Enter(); } void Game::ChangeUIScene(RefPtr scene) { if (m_uiScene != nullptr) { m_uiScene->Exit(); } m_uiScene = scene; m_uiScene->Enter(); } SDL_Renderer *Game::GetRenderer() { return m_renderer; }