建档
This commit is contained in:
223
source/EngineCore/Game.cpp
Normal file
223
source/EngineCore/Game.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
94
source/EngineCore/Game.h
Normal file
94
source/EngineCore/Game.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Scene/Scene.h"
|
||||
#include "Tool/RefPtr.h"
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <SDL_mixer.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
// some switch buttons
|
||||
#define JOY_A 0
|
||||
#define JOY_B 1
|
||||
#define JOY_X 2
|
||||
#define JOY_Y 3
|
||||
#define JOY_PLUS 10
|
||||
#define JOY_MINUS 11
|
||||
#define JOY_LEFT 12
|
||||
#define JOY_UP 13
|
||||
#define JOY_RIGHT 14
|
||||
#define JOY_DOWN 15
|
||||
|
||||
class Debug_Actor;
|
||||
|
||||
class Game
|
||||
{
|
||||
#ifndef __SWITCH__
|
||||
typedef Uint32 u32;
|
||||
#endif
|
||||
public:
|
||||
// 删除拷贝构造和赋值运算符,确保无法复制
|
||||
Game(const Game &) = delete;
|
||||
Game &operator=(const Game &) = delete;
|
||||
|
||||
// 移动构造和赋值也删除,避免意外转移
|
||||
Game(Game &&) = delete;
|
||||
Game &operator=(Game &&) = delete;
|
||||
|
||||
// 全局访问点
|
||||
static Game &GetInstance()
|
||||
{
|
||||
static Game instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Init(std::function<void()> CallBack);
|
||||
void Run();
|
||||
void HandleEvents(SDL_Event *e);
|
||||
void Update(float deltaTime);
|
||||
void Render();
|
||||
void Clear();
|
||||
|
||||
// 切换场景
|
||||
void ChangeScene(RefPtr<Scene> scene);
|
||||
// 设定UI层场景对象
|
||||
void ChangeUIScene(RefPtr<Scene> scene);
|
||||
|
||||
SDL_Renderer *GetRenderer();
|
||||
|
||||
uint32_t RenderCount = 0;
|
||||
|
||||
private:
|
||||
// 构造函数和析构函数设为私有,防止外部创建和销毁
|
||||
Game();
|
||||
~Game();
|
||||
|
||||
// 游戏是否运行
|
||||
bool m_isRunning = true;
|
||||
// 窗口
|
||||
SDL_Window *m_window;
|
||||
// 渲染器
|
||||
SDL_Renderer *m_renderer;
|
||||
|
||||
// 游戏层场景
|
||||
RefPtr<Scene> m_scene;
|
||||
// UI层场景
|
||||
RefPtr<Scene> m_uiScene;
|
||||
|
||||
// 帧数
|
||||
int m_fps = 10000;
|
||||
u32 m_frameTime;
|
||||
float m_deltaTime;
|
||||
// 新增:帧率统计变量
|
||||
u32 m_frameCount; // 每秒内的帧数计数器
|
||||
u32 m_lastFpsPrintTime; // 上一次输出帧率的时间(毫秒,基于 SDL_GetTicks())
|
||||
|
||||
// 调试信息Actor
|
||||
RefPtr<Debug_Actor> m_DebugInfoActor;
|
||||
|
||||
public:
|
||||
// 屏幕宽高
|
||||
int Screen_W = 1280;
|
||||
int Screen_H = 720;
|
||||
};
|
||||
Reference in New Issue
Block a user