diff --git a/.clang-tidy b/.clang-tidy index 8855835..08e52d4 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '*,-llvmlibc-implementation-in-namespace' +Checks: '*,-altera-unroll-loops, -cppcoreguidelines-pro-type-reinterpret-cast,-llvmlibc-implementation-in-namespace,-llvmlibc-callee-namespace, -llvmlibc-restrict-system-libc-headers, -modernize-use-trailing-return-type' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/breakout/breakout b/breakout/breakout old mode 100755 new mode 100644 index 6d1146a..4c9a06c Binary files a/breakout/breakout and b/breakout/breakout differ diff --git a/breakout/breakout.cpp b/breakout/breakout.cpp index 4ea5f9d..2ace101 100644 --- a/breakout/breakout.cpp +++ b/breakout/breakout.cpp @@ -1,9 +1,11 @@ // Copyright [2023] Krzysztof Rudnicki #ifndef HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_BREAKOUT_CPP #define HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_BREAKOUT_CPP - #include +#include +#include + #include "../dependencies/include/glad/glad.h" #include "./game.hpp" #include "./resourceManager.hpp" @@ -23,7 +25,7 @@ Game &getBreakoutInstance() { return Breakout; } -int main(int /*argc*/, char * /*argv*/[]) { +void initGLFW() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -32,79 +34,130 @@ int main(int /*argc*/, char * /*argv*/[]) { glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif glfwWindowHint(GLFW_RESIZABLE, 0); +} - GLFWwindow *window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Breakout", - nullptr, nullptr); - glfwMakeContextCurrent(window); - - // glad: load all OpenGL function pointers - // --------------------------------------- +int failedGLAD() { + // we are forced to use reinterpret_cast since there is no standard-compliant + // way to convert a void* (which is what glfwGetProcAddress returns) to a + // function pointer in C++ if (gladLoadGLLoader(reinterpret_cast(glfwGetProcAddress)) == 0) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } + return 0; +} - glfwSetKeyCallback(window, bugprone-easily-swappable-parameters +std::pair calculate_delta_time(double deltaTime, + double lastFrame) { + // calculate delta time // -------------------- - glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + double const currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + glfwPollEvents(); + return std::make_pair(deltaTime, lastFrame); +} - // initialize game - // --------------- - Breakout.Init(); +void main_loop_render(Game Breakout) { + // render + glClearColor(0.0F, 0.0F, 0.0F, 1.0F); + glClear(GL_COLOR_BUFFER_BIT); + Breakout.Render(); +} +void main_loop_inside(GLFWwindow *window, double deltaTime, double lastFrame, + Game Breakout) { + const std::pair times = + calculate_delta_time(deltaTime, lastFrame); + deltaTime = times.first; + lastFrame = times.second; + + // manage user input + Breakout.ProcessInput(deltaTime); + + // update game state + Breakout.Update(deltaTime); + + main_loop_render(Breakout); + glfwSwapBuffers(window); +} + +void main_loop(GLFWwindow *window, const Game &Breakout) { // deltaTime variables - // ------------------- - float deltaTime = 0.0F; - float lastFrame = 0.0F; - + const double deltaTime = 0.0F; + const double lastFrame = 0.0F; + // We do not comply with altera-unroll-loops + // since each loop iteration is dependent on the previous one. while (glfwWindowShouldClose(window) == 0) { - // calculate delta time - // -------------------- - float const currentFrame = glfwGetTime(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; - glfwPollEvents(); - - // manage user input - // ----------------- - Breakout.ProcessInput(deltaTime); - - // update game state - // ----------------- - Breakout.Update(deltaTime); - - // render - // ------ - glClearColor(0.0F, 0.0F, 0.0F, 1.0F); - glClear(GL_COLOR_BUFFER_BIT); - Breakout.Render(); - - glfwSwapBuffers(window); + main_loop_inside(window, deltaTime, lastFrame, Breakout); } +} +int delete_resources() { // delete all resources as loaded using the resource manager - // --------------------------------------------------------- ResourceManager::Clear(); - glfwTerminate(); return 0; } -void key_callback(GLFWwindow *window, int key, int /*scancode*/, int action, - int /*mode*/) { +void gl_magic(GLFWwindow *window) { + glfwSetKeyCallback(window, key_callback); + glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +int main(int /*argc*/, char * /*argv*/[]) { + initGLFW(); + GLFWwindow *window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Breakout", + nullptr, nullptr); + glfwMakeContextCurrent(window); + if (failedGLAD() != 0) { + return -1; + } + gl_magic(window); + Game Breakout = getBreakoutInstance(); + // initialize game + Breakout.Init(); + main_loop(window, Breakout); + return delete_resources(); +} + +void exit_window(GLFWwindow *window, const int key, const int action) { // when a user presses the escape key, we set the // WindowShouldClose property to true, closing the application if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, 1); } - if (key >= 0 && key < 1024) { - if (action == GLFW_PRESS) { - Breakout.Keys[key] = true; - } else if (action == GLFW_RELEASE) { - Breakout.Keys[key] = false; +} + +void key_callback_happy(const std::pair action_key) { + Game Breakout = getBreakoutInstance(); + if (action_key.first == GLFW_PRESS) { + Breakout.Keys.at(action_key.second) = true; + } else if (action_key.first == GLFW_RELEASE) { + Breakout.Keys.at(action_key.second) = false; + } +} + +void key_callback_sad(int key) { + std::cerr << "key_callback_sad Error! key is out of range!" << key + << std::endl; +} + +// Assume Breakout.Keys is of type KeyArray +void key_callback(GLFWwindow *window, int key, int /*scancode*/, int action, + int /*mode*/) { + // Define the array type for keys + const int MAX_KEYS_TRACKED = 1024; + using KeyArray = std::array; + exit_window(window, key, action); + if (key >= 0 && key < MAX_KEYS_TRACKED) { + try { + key_callback_happy(std::pair(action, key)); + } catch (const std::out_of_range &e) { + key_callback_sad(key); } } } diff --git a/breakout/game.cpp b/breakout/game.cpp index fb96a02..25154e6 100644 --- a/breakout/game.cpp +++ b/breakout/game.cpp @@ -6,13 +6,11 @@ Game::Game(unsigned int width, unsigned int height) : State(GAME_ACTIVE), Keys(), Width(width), Height(height) {} -Game::~Game() = default; - void Game::Init() {} -void Game::Update(float dt) {} +void Game::Update(double dt) {} -void Game::ProcessInput(float dt) {} +void Game::ProcessInput(double dt) {} void Game::Render() {} diff --git a/breakout/game.hpp b/breakout/game.hpp index 9ad48f4..8be52b0 100644 --- a/breakout/game.hpp +++ b/breakout/game.hpp @@ -1,6 +1,7 @@ // Copyright [2023] Krzysztof Rudnicki #ifndef HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_GAME_HPP #define HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_GAME_HPP +#include #include @@ -13,16 +14,16 @@ class Game { public: // game state GameState State; - bool Keys[1024]; + std::array Keys; unsigned int Width, Height; // constructor/destructor Game(unsigned int width, unsigned int height); - ~Game(); + ~Game() = default; // initialize game state (load all shaders/textures/levels) void Init(); // game loop - void ProcessInput(float dt); - void Update(float dt); + void ProcessInput(double dt); + void Update(double dt); void Render(); }; diff --git a/breakout/resourceManager.hpp b/breakout/resourceManager.hpp index b8adcb0..f65ea69 100644 --- a/breakout/resourceManager.hpp +++ b/breakout/resourceManager.hpp @@ -25,8 +25,8 @@ class ResourceManager { public: // resource storage - static std::max Shaders; - static std::max Textures; + template<> static std::max; Shaders; + template<> static std::max; Textures; // loads (and generates) a shader program from file loading vertex, // fragment (and geometry) shader's source code. // If gShaderFile is not nullptr, it also loads a geometry shader diff --git a/clang_script.sh b/clang_script.sh index e8abb5f..eb146fd 100755 --- a/clang_script.sh +++ b/clang_script.sh @@ -1,4 +1,4 @@ #!/bin/sh -clang-tidy --config-file=./.clang-tidy --fix-errors --fix-notes -p ./build/compile_commands.json ./breakout/breakout.cpp +clang-tidy --config-file=./.clang-tidy -p ./build/compile_commands.json ./breakout/breakout.cpp cpplint ./breakout/breakout.cpp \ No newline at end of file