diff --git a/.gitignore b/.gitignore index e048dfe..e105966 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # binaries *.o game +.sconsign.dblite diff --git a/.sconsign.dblite b/.sconsign.dblite deleted file mode 100644 index 82a4aa5..0000000 Binary files a/.sconsign.dblite and /dev/null differ diff --git a/SConstruct b/SConstruct index d3972cf..f3650f0 100644 --- a/SConstruct +++ b/SConstruct @@ -1,6 +1,17 @@ +from pathlib import Path +import os project='game' +def glob_recurse(dir): + sources = Glob(os.path.join(dir, '*.cpp')) + for path in dir.iterdir(): + if path.is_dir(): + sources.extend(glob_recurse(path)) + return sources + +sources = glob_recurse(Path('src/')) + env = Environment(CCFLAGS=['-std=c++20', '-Wall', '-O0', '-g3']) env.ParseConfig('sdl2-config --static-libs') -env.Program(project, Glob('src/*.cpp')) +env.Program(project, sources) diff --git a/src/core/application.cpp b/src/core/application.cpp new file mode 100644 index 0000000..aa8a68e --- /dev/null +++ b/src/core/application.cpp @@ -0,0 +1,76 @@ +#include "application.hpp" +#include +#include +#include + +#ifndef PROJECTNAME +#define PROJECTNAME "application" +#endif + +Application::Application() { + if(SDL_Init(SDL_INIT_EVERYTHING) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to initialize SDL, SDL error: %s", SDL_GetError()); + return; + } + this->window = SDL_CreateWindow(PROJECTNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_FULLSCREEN); + if(this->window == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window, SDL error: %s", SDL_GetError()); + SDL_Quit(); + return; + } + this->render = SDL_CreateRenderer(this->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if(this->render == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to initialize renderer, SDL error: %s", SDL_GetError()); + SDL_DestroyWindow(this->window); + SDL_Quit(); + return; + } + this->stay_open = true; +} + +Application::~Application() { + SDL_DestroyRenderer(this->render); + SDL_DestroyWindow(this->window); + SDL_Quit(); +} + +void Application::run() { + // start tracking time + std::timespec_get(&this->startup_ts, TIME_UTC); + this->frame_start_ts = this->last_frame_start_ts = this->startup_ts; + // main application loop + while(stay_open) { + // track frame time + std::timespec_get(&this->frame_start_ts, TIME_UTC); + this->delta_time = double(this->last_frame_start_ts.tv_nsec - this->frame_start_ts.tv_nsec) / 1000000000.f; + // process events + this->process_events(); + // update application implementation + if(this->delta_time > this->target_delta_time) { + this->tick(this->delta_time); + this->draw(render); + this->last_frame_start_ts = this->frame_start_ts; + } + } +} + +void Application::request_close() { + this->stay_open = false; +} + +void Application::set_target_delta_time(double target) { + this->target_delta_time = target; +} + +void Application::process_events() { + SDL_Event evt{}; + while(SDL_PollEvent(&evt)) { + switch(evt.type) { + case SDL_QUIT: + this->request_close(); + break; + default:break; + } + this->process_event(evt); + } +} diff --git a/src/core/application.hpp b/src/core/application.hpp new file mode 100644 index 0000000..09497f8 --- /dev/null +++ b/src/core/application.hpp @@ -0,0 +1,33 @@ +#ifndef CORE_APPLICATION_HPP +#define CORE_APPLICATION_HPP + +#include +#include +#include +#include + +class Application { +public: Application(); + virtual ~Application(); + void run(); + virtual void process_event(SDL_Event const &event) = 0; + virtual void tick(double delta_time) = 0; + virtual void draw(SDL_Renderer *render) = 0; + + void request_close(); + void set_target_delta_time(double target); +private: + void process_events(); +protected: + SDL_Window *window{nullptr}; //!< primary application window + SDL_Renderer *render{nullptr}; //!< primary application window's renderer +private: + std::timespec startup_ts{}; //!< time in UTC at start of application (when run() was called) + std::timespec last_frame_start_ts{}; //!< time at start of last frame + std::timespec frame_start_ts{}; //!< time at start of this frame + double delta_time{0.f}; + double target_delta_time{}; + bool stay_open{false}; //!< application loop will continue so long as this is true +}; + +#endif // !CORE_APPLICATION_HPP diff --git a/src/main.cpp b/src/main.cpp index bd91c67..dc5b5a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,13 +18,12 @@ int main(int argc, char* argv[]) { while(keep_open) { SDL_PollEvent(&event); switch(event.type) { - case SDL_QUIT: - keep_open = false; - break; - default: - break; + case SDL_QUIT: + keep_open = false; + break; + default: + break; } - SDL_RenderClear(render); SDL_RenderPresent(render); }