#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 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) { 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(); } RenderManager *Game::GetRenderer() { return m_renderer; }