Ethertia
Dev
Dev
Lifetime
整个游戏/程序的生命周期
如你所见,这里没有用OOP的方式(用某个 "class Engine" 来包裹)。因为没有想到 什么情况下会在一个进程内运行多个引擎实例
因为这里默认遵循 “如无必要 勿增实体”,“不要过早优化”,每个功能应该有他存在的原因。否则可能反而会负优化。
void main()
{
Init();
while (g_IsRunning)
{
RunMainLoop();
}
Destroy();
}Init & Destroy
static void Init()
{
BENCHMARK_TIMER_MSG("System initialized in {}.\n");
Settings::Load();
Window::Init(Settings::WindowSize);
Mods::Init(); // ScriptSystem. NativeMods
RenderEngine::Init();
Imgui::Init();
Physics::Init();
AudioEngine::Init();
NetworkSystem::Init();
InitConsoleThread();
g_ThreadPool = std::make_unique<stdx::thread_pool>(std::min(16u, std::thread::hardware_concurrency()));
g_MainThreadId = std::this_thread::get_id();
g_IsRunning = true;
}
static void Destroy()
{
Settings::Save();
if (et::GetWorld()) {
et::UnloadWorld();
}
Physics::Destroy();
RenderEngine::Destroy();
Window::Destroy();
}MainLoop
static void RunMainLoop()
{
ET_PROFILE("MainLoop");
auto& timer = g_Timer;
auto* world = g_World;
timer.Update();
{
ET_PROFILE("Inputs");
HandleInputs();
}
if (world) {
ET_PROFILE("WorldTick");
while (timer.PollTick())
{
world->FixedUpdate();
}
}
{
RenderUI();
ET_PROFILE("RenderWorld");
RenderEngine::RenderWorld(world);
}
glfwSwapBuffers(Window::Handle());
}
void HandleInput()
{
Window::PollEvents();
}
void RenderUI()
{
ET_PROFILE("UI");
{
ET_PROFILE("Imgui::NewFrame");
Imgui::NewFrame();
}
ET_PROFILE("Imgui::ShowWindows");
Imw::ShowDockspaceAndMainMenubar();
Imgui::ShowWindows();
Imgui::Render();
}Core
Preprocessor
#pragma onceNamespace
#define ET_NAMESPACE et
#define ET_NAMESPACE_BEGIN namespace ET_NAMESPACE {
#define ET_NAMESPACE_END }Version
#define ET_VERSION_MAJOR 0
#define ET_VERSION_MINOR 0
#define ET_VERSION_PATCH 3Timer
class Timer {
float m_Delta;
float m_TimeLast = 0;
float m_TicksElapsed = 0;
static int TicksPerSecond = 20;
void Update() {
float time = Time();
if (m_TimeLast == 0)
m_TimeLast = time;
float delta = time - m_TimeLast;
m_TicksElapsed += delta * TicksPerSecond;
m_TimeLast = time;
m_Delta = delta;
}
bool PollTick() {
if (m_TicksElapsed < 1.0)
return false;
m_TicksElapsed -= 1.0;
return true;
}
// Time since Startup
float Time() {
return Window::PerciseTime();
}
static uint64_t TimestampMS() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
static double TimestampNS() { // 1ns = 1,000,000,000, * 0.000000001
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}
}Log
EventBus
World
void et::LoadWorld(const std::string& savedir, const WorldInfo* worldinfo) {
ET_ASSERT(g_World == nullptr);
}
void et::UnloadWorld();
class World
{
entt::registry m_ECS;
PxScene* m_PxScene;
bool Raycast(Vec3 origin, Vec3 dir, f32 maxDistance, Vec3& outPos) const;
bool IsPaused();
void SetPaused(bool paused);
void SetPausedSteps(int steps);
}