From 1e40bacfb7260207ad17d65c6017a532256ad6e6 Mon Sep 17 00:00:00 2001 From: Joeyrp Date: Fri, 3 Sep 2021 20:54:22 -0400 Subject: [PATCH] Real main file added Game loop shell implemented --- .gitignore | 1 + CMakeLists.txt | 5 +- docs/Tasks.todo | 11 ++++ src/core/core.cpp | 117 ++++++++++++++++++++++++++++++----- src/core/core.h | 15 ++++- src/graphics/IGraphics.h | 2 +- src/graphics/OGLGraphics.cpp | 2 +- src/graphics/OGLGraphics.h | 2 +- src/main.cpp | 44 +++++++++++++ src/utils/FrameCounter.cpp | 62 +++++++++++++++++++ src/utils/FrameCounter.h | 47 ++++++++++++++ src/utils/OpRes.cpp | 10 +++ src/utils/OpRes.h | 2 + src/utils/helpers.cpp | 36 ++++++++++- src/utils/helpers.h | 4 ++ 15 files changed, 336 insertions(+), 24 deletions(-) create mode 100644 docs/Tasks.todo create mode 100644 src/main.cpp create mode 100644 src/utils/FrameCounter.cpp create mode 100644 src/utils/FrameCounter.h diff --git a/.gitignore b/.gitignore index a2c6edb..543ffac 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ *.app # other +*.log *.zip *.ini test_data/test_save.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 94ca967..61f73b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16.3) project(Lunarium VERSION 0.1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) # specify the opengl version @@ -15,7 +15,7 @@ configure_file(LunariumConfig.h.in LunariumConfig.h) # Source Files set(LUNARIUM_SRC -"src/test_main.cpp" +"src/main.cpp" "src/core/core.cpp" "src/core/state.cpp" "src/core/Version.cpp" @@ -26,6 +26,7 @@ set(LUNARIUM_SRC "src/utils/OpRes.cpp" "src/utils/Args.cpp" "src/utils/BinaryFileBuffer.cpp" +"src/utils/FrameCounter.cpp" "src/graphics/window.cpp" "src/graphics/oglgraphics.cpp" "src/graphics/glShader.cpp" diff --git a/docs/Tasks.todo b/docs/Tasks.todo new file mode 100644 index 0000000..cea585a --- /dev/null +++ b/docs/Tasks.todo @@ -0,0 +1,11 @@ + +Core: + ☐ Add log settings to the state file + + +Graphics: + ☐ Dear ImGui class with basic initialization + ☐ Decide on a font/text rendering system + +Input: + ☐ Port over the Element2D input system and adust it to use glfw \ No newline at end of file diff --git a/src/core/core.cpp b/src/core/core.cpp index bf8e5cc..67308d4 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -9,11 +9,15 @@ #include "core.h" #include "Version.h" +// Sub Systems +#include +#include + namespace lunarium { Core* Core::mpInstance = nullptr; Core::Core() - : mbIsInit(false), mpArgs(nullptr) + : mbIsInit(false), mpArgs(nullptr), mpWindow(nullptr), mpGraphics(nullptr) { } @@ -33,52 +37,103 @@ namespace lunarium if (!mpInstance) return; + + Logger::Log(LogCategory::CORE, LogLevel::INFO, "Lunarium is shutting down!"); + // Shutdown subsystems + delete mpInstance->mpGraphics; + mpInstance->mpGraphics = nullptr; + + delete mpInstance->mpWindow; + mpInstance->mpWindow = nullptr; delete mpInstance->mpArgs; mpInstance->mpArgs = nullptr; delete mpInstance; mpInstance = nullptr; + + mpInstance->mbIsInit = false; } - void Core::Initialize(int argc, char** argv, std::vector& listeners) + void Core::Initialize(int argc, char** argv) { - // Setup the log system and add any listeners - mpLog = Logger::GetInstance(); - - mMasterLogFile.open("Element2D_Master.log", std::ios_base::app); + // Setup the log system + mMasterLogFile.open("Lunarium_Master.log", std::ios_base::app); mMasterLogFile << "\n\n"; - mErrorLogFile.open("Element2D_Errors.log", std::ios_base::app); + mErrorLogFile.open("Lunarium_Errors.log", std::ios_base::app); mErrorLogFile << "\n\n"; if (mMasterLogFile.is_open()) - mpLog->AddListener(new FileListener(mMasterLogFile)); + Logger::GetInstance()->AddListener(new FileListener(mMasterLogFile)); if (mErrorLogFile.is_open()) - mpLog->AddListener(new FileListener(mErrorLogFile, LogLevel::ERROR | LogLevel::FATAL_ERROR)); + Logger::GetInstance()->AddListener(new FileListener(mErrorLogFile, LogLevel::ERROR | LogLevel::FATAL_ERROR)); - for (unsigned i = 0; i < listeners.size(); i++) - { - mpLog->AddListener(listeners[i]); - } - Logger::Log(LogCategory::CORE, LogLevel::INFO, "Running Lunarium version %s", Version::GetVersion().ToString().c_str()); // Attempt to load the engine state file. This file should be placed in the same directory as the lunarium program. - mpLog->Log(LogCategory::CORE, LogLevel::INFO, "Attempting to load state file: lunarium_state.xml"); if (Failed(State::CreateFromFile("lunarium_state.xml", mState))) { Logger::Log(LogCategory::CORE, LogLevel::WARNING, "Unable to load state file: lunarium_state.xml. Loading default state."); mState = State::CreateDefault(); } + else + { + Logger::Log(LogCategory::CORE, LogLevel::INFO, "Loaded state file: lunarium_state.xml"); + } // Parse command line args -- None right now std::vector sd; mpArgs = new Args(argc, argv, '-', sd); + + OpRes result; + + // Init Graphics/Window system + mpWindow = new Window; + result = mpWindow->Initialize(mState); + if (Failed(result)) + { + Logger::Log(LogCategory::CORE, LogLevel::FATAL_ERROR, + "Could not initialize the Window system: %s", result.Description); + return; + } + + if (Renderer::OPENGL == mState.Display.RenderFramework) + { + mpGraphics = new OglGraphics; + } + else if (Renderer::VULKAN == mState.Display.RenderFramework) + { + Logger::Log(LogCategory::CORE, LogLevel::FATAL_ERROR, + "Can not create Vulkan graphics system because it is not yet implemented. Must use OpenGL instead."); + return; + } + else + { + Logger::Log(LogCategory::CORE, LogLevel::FATAL_ERROR, + "Could not create graphics system: Unknown render framework specified."); + return; + } + + // TODO: This should probably be based on a state setting instead +#ifdef _DEBUG + result = mpGraphics->Initialize(mpWindow); +#else + result = mpGraphics->Initialize(mpWindow, false); +#endif + + if (Failed(result)) + { + Logger::Log(LogCategory::CORE, LogLevel::FATAL_ERROR, + "Could not initialized the graphics system: %s", result.Description); + return; + } + + mbIsInit = true; } bool Core::IsInit() const @@ -90,4 +145,36 @@ namespace lunarium { return mState; } + + void Core::RunGameLoop() + { + mFrameCounter.Reset(); + + // TODO: Init frame counter + while (!mpWindow->ShouldWindowClose()) + { + mFrameCounter.NewFrame(); + + // Display FPS in window title for now + std::string title = "Lunarium - FPS: "; + title += std::to_string(mFrameCounter.GetFrameData().CurrentFPS); + glfwSetWindowTitle(mpWindow->GetWindow(), title.c_str()); + + // Poll input + Window::PollEvents(); + + // HACK: Temporary solution to close the program + if (glfwGetKey(mpWindow->GetWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS) + { + mpWindow->SetShouldCloseFlag(true); + } + + // Update game state + + // Render + mpGraphics->BeginDraw(); + + mpGraphics->EndDraw(); + } + } } \ No newline at end of file diff --git a/src/core/core.h b/src/core/core.h index 57a3bcd..a2b3a32 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -12,33 +12,44 @@ #include "state.h" #include #include +#include namespace lunarium { + class IGraphics; + class Window; + class Core { public: static Core& GetInstance(); static void Shutdown(); - void Initialize(int argc, char** argv, std::vector& listeners); + void Initialize(int argc, char** argv); bool IsInit() const; const State& GetState() const; void ApplyState(State newState); + void RunGameLoop(); + private: // DATA static Core* mpInstance; bool mbIsInit; State mState; Args* mpArgs; - Logger* mpLog; + FrameCounter mFrameCounter; // Log Files std::ofstream mMasterLogFile; std::ofstream mErrorLogFile; + private: // SUBSYSTEMS + + Window* mpWindow; + IGraphics* mpGraphics; + private: // HIDDEN METHODS Core(); diff --git a/src/graphics/IGraphics.h b/src/graphics/IGraphics.h index 4c1f9d2..60a774f 100644 --- a/src/graphics/IGraphics.h +++ b/src/graphics/IGraphics.h @@ -34,7 +34,7 @@ namespace lunarium IGraphics() : mbIsInit(false) {} - virtual OpRes Initialized(Window* pWindow, bool enableDebugMessages = true) = 0; + virtual OpRes Initialize(Window* pWindow, bool enableDebugMessages = true) = 0; virtual void Shutdown() = 0; virtual void ResizeCanvas() = 0; diff --git a/src/graphics/OGLGraphics.cpp b/src/graphics/OGLGraphics.cpp index a3feafd..c1c4c40 100644 --- a/src/graphics/OGLGraphics.cpp +++ b/src/graphics/OGLGraphics.cpp @@ -44,7 +44,7 @@ namespace lunarium } - OpRes OglGraphics::Initialized(Window* pWindow, bool enableDebugMessages) + OpRes OglGraphics::Initialize(Window* pWindow, bool enableDebugMessages) { if (!pWindow->IsInit()) { diff --git a/src/graphics/OGLGraphics.h b/src/graphics/OGLGraphics.h index e1b12bc..a5832ff 100644 --- a/src/graphics/OGLGraphics.h +++ b/src/graphics/OGLGraphics.h @@ -25,7 +25,7 @@ namespace lunarium OglGraphics(); - virtual OpRes Initialized(Window* pWindow, bool enableDebugMessages = true); + virtual OpRes Initialize(Window* pWindow, bool enableDebugMessages = true); virtual void Shutdown(); virtual void ResizeCanvas(); diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..393fe49 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** +* File - main.cpp +* Author - Joey Pollack +* Date - 2021/09/03 (y/m/d) +* Mod Date - 2021/09/03 (y/m/d) +* Description - Main entry-point for Lunarium +******************************************************************************/ + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + // Switch the currrent working directory to the directory + // containing the lunarium.exe file because the data and state + // file should be in that location + std::string path = argv[0]; + path = lunarium::String::TrimFileNameFromPath(path); + std::filesystem::current_path(path); + + // All log messages will go to stdout + lunarium::Logger::GetInstance()->AddListener(new lunarium::StandardListener); + + lunarium::Core& core = lunarium::Core::GetInstance(); + core.Initialize(argc, argv); + + if (!core.IsInit()) + { + std::cout << "\nFailed to initialize the engine core."; + return 1; + } + + std::cout << "\nEngine core successfully initialized!"; + + core.RunGameLoop(); + + core.Shutdown(); + lunarium::Logger::GetInstance()->FreeAllListeners(); + lunarium::Logger::FreeInstance(); + return 0; +} \ No newline at end of file diff --git a/src/utils/FrameCounter.cpp b/src/utils/FrameCounter.cpp new file mode 100644 index 0000000..67bc19a --- /dev/null +++ b/src/utils/FrameCounter.cpp @@ -0,0 +1,62 @@ +/****************************************************************************** +* File - FrameCounter.cpp +* Author - Joey Pollack +* Date - 2021/09/03 (y/m/d) +* Mod Date - 2021/09/03 (y/m/d) +* Description - Tracks frame statistics +******************************************************************************/ + +#include "FrameCounter.h" + +namespace lunarium +{ + void FrameCounter::Reset(bool minimalTracking) + { + // Zero out the struct + memset(&mFrameData, 0, sizeof(FrameData)); + mFrameData.LowestFPS = 10000; + mbMinimalTracking = minimalTracking; + mSecondTimer = 0.0; + mTimer.Reset(); + } + + void FrameCounter::NewFrame() + { + double now = mTimer.GetElapsedSeconds(); + mSecondTimer += now; + mFPSCount++; + mFrameData.NumFrames++; + mFrameData.TotalRunTime += now; + mFrameData.LastFrameTime = now; + + if (mSecondTimer >= 1.0) + { + mFrameData.CurrentFPS = mFPSCount; + mFPSCount = 0; + mSecondTimer = 0.0; + } + + if (!mbMinimalTracking) + { + if (mFrameData.CurrentFPS > mFrameData.HighestFPS) + { + mFrameData.HighestFPS = mFrameData.CurrentFPS; + } + + if (mFrameData.CurrentFPS < mFrameData.LowestFPS) + { + mFrameData.LowestFPS = mFrameData.CurrentFPS; + } + + mFrameData.AverageFrameTime = mFrameData.TotalRunTime / mFrameData.NumFrames; + mFrameData.AverageFPS = mFrameData.NumFrames / mFrameData.TotalRunTime; // NOTE: Not 100% sure this is correct + } + + mTimer.Reset(); + } + + const FrameData& FrameCounter::GetFrameData() const + { + return mFrameData; + } +} \ No newline at end of file diff --git a/src/utils/FrameCounter.h b/src/utils/FrameCounter.h new file mode 100644 index 0000000..c44049a --- /dev/null +++ b/src/utils/FrameCounter.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* File - FrameCounter.h +* Author - Joey Pollack +* Date - 2021/09/03 (y/m/d) +* Mod Date - 2021/09/03 (y/m/d) +* Description - Tracks frame statistics +******************************************************************************/ + +#ifndef FRAME_COUNTER_H_ +#define FRAME_COUNTER_H_ + +#include +#include "highResTimer.h" + +namespace lunarium +{ + struct FrameData + { + uint64_t NumFrames; + double TotalRunTime; + double AverageFrameTime; + double LastFrameTime; + uint32_t CurrentFPS; + uint32_t AverageFPS; + uint32_t LowestFPS; + uint32_t HighestFPS; + }; + + class FrameCounter + { + public: + void Reset(bool minimalTracking = false); + void NewFrame(); + + const FrameData& GetFrameData() const; + + private: + bool mbMinimalTracking; // If true will only track basic data + FrameData mFrameData; + HighResTimer mTimer; + double mSecondTimer; + int mFPSCount; + }; +} + + +#endif // FRAME_COUNTER_H_ \ No newline at end of file diff --git a/src/utils/OpRes.cpp b/src/utils/OpRes.cpp index 1f7cab7..ffba023 100644 --- a/src/utils/OpRes.cpp +++ b/src/utils/OpRes.cpp @@ -36,8 +36,18 @@ namespace lunarium return res.Type == ResultType::OK; } + bool IsOK(OpRes& res) + { + return res.Type == ResultType::OK; + } + bool Failed(OpRes&& res) { return res.Type == ResultType::FAIL; } + + bool Failed(OpRes& res) + { + return res.Type == ResultType::FAIL; + } } \ No newline at end of file diff --git a/src/utils/OpRes.h b/src/utils/OpRes.h index 1258d21..4be48c0 100644 --- a/src/utils/OpRes.h +++ b/src/utils/OpRes.h @@ -36,8 +36,10 @@ namespace lunarium }; bool IsOK(OpRes&& res); + bool IsOK(OpRes& res); bool Failed(OpRes&& res); + bool Failed(OpRes& res); } #endif // _OPERATION_RESULT_H_ \ No newline at end of file diff --git a/src/utils/helpers.cpp b/src/utils/helpers.cpp index 446a319..0fd6af1 100644 --- a/src/utils/helpers.cpp +++ b/src/utils/helpers.cpp @@ -31,12 +31,15 @@ namespace lunarium std::string System::GetGLSLVersionString() { std::string glsl_version = "#version "; - glsl_version += OPENGL_MAJOR_VERSION; - glsl_version += OPENGL_MINOR_VERSION; + glsl_version += (OPENGL_MAJOR_VERSION + 48); // Need to convert to ascii + glsl_version += (OPENGL_MINOR_VERSION) + 48; glsl_version += "0"; return glsl_version; } + //////////////////////////////////////////////////////////// + // STRING MANIPULATION + //////////////////////////////////////////////////////////// std::vector String::Split(std::string str, char delim, int maxSplits) { std::vector splits; @@ -166,4 +169,33 @@ namespace lunarium return str; } + + //////////////////////////////////////////////////////////// + // PATH MANIPULATION + //////////////////////////////////////////////////////////// + std::string String::GetFileNameFromPath(std::string path, bool includeExt) + { + path.erase(path.begin(), std::find_if(path.rbegin(), path.rend(), [](int ch) { return ch == '\\' || ch == '/'; }).base()); + + if (!includeExt) + { + path.erase(std::find_if(path.rbegin(), path.rend(), [](int ch) { return ch == '.'; }).base(), path.end()); + path.erase(path.begin() + path.size() - 1); + } + + return path; + } + + std::string String::TrimFileNameFromPath(std::string path) + { + path.erase(std::find_if(path.rbegin(), path.rend(), [](int ch) { return ch == '\\' || ch == '/'; }).base(), path.end()); + return path; + } + + std::string String::GetFileExtension(std::string filename) + { + filename.erase(filename.begin(), std::find_if(filename.begin(), filename.end(), [](int ch) { return ch == '.'; })); + filename.erase(filename.begin()); + return filename; + } } \ No newline at end of file diff --git a/src/utils/helpers.h b/src/utils/helpers.h index b95fe40..e8ac3e7 100644 --- a/src/utils/helpers.h +++ b/src/utils/helpers.h @@ -45,6 +45,10 @@ namespace lunarium static std::string StringToUpper(std::string str); static std::string StringToLower(std::string str); + + static std::string GetFileNameFromPath(std::string path, bool includeExt); + static std::string TrimFileNameFromPath(std::string path); + static std::string GetFileExtension(std::string filename); }; }