#pragma once #include #include #include #include #include #include #include #define SDL_MAIN_HANDLED #include "SDL.h" #include "SDL_mixer.h" #include "SDL_ttf.h" #define GL_GLEXT_PROTOTYPES #define GLEW_STATIC #if defined(__EMSCRIPTEN__) #include #include #include #else #include "glew/glew.h" #endif #include "Node.hpp" #include "Input.hpp" #include "Display.hpp" #include "Configuration.hpp" #include "Delegate.hpp" #include "Recorder.hpp" #include "Sprite.hpp" #include "Audio.hpp" #include "Log.hpp" #include "filesystem.hpp" #include "extension.hpp" class FramerateIndicator : public Sprite { public: FramerateIndicator(Node*); void respond(SDL_Event&); SDL_Surface* get_surface(); void refresh(); }; class Game : public Node { private: int ticks; float frame_length = 1000.0 / 60.0; Configuration _configuration {this}; SDL_Window* _window; static void sdl_log_override(void*, int, SDL_LogPriority, const char*); public: /* two-state enum equivalent to a boolean that can improve readability depending on the context */ enum class Flip { OFF, ON }; /* Prevent an instance of this class from being copied or moved */ Game(const Game&) = delete; Game& operator=(const Game&) = delete; Game(Game&&) = delete; Game& operator=(Game&&) = delete; SDL_Renderer* renderer = nullptr; SDL_GLContext glcontext = nullptr; int frame_count_this_second = 0, last_frame_length; float frame_time_overflow = 0, last_frame_timestamp, last_frame_count_timestamp; bool done = false, show_framerate = true, is_gl_context = true; Delegate delegate {this}; sb::Display display {this}; Recorder recorder {this}; Input input {this}; Audio audio {this}; std::vector frame_length_history; TTF_Font* bp_mono_font = nullptr; FramerateIndicator framerate_indicator {this}; Game(); virtual void reset() { activate(); } void print_frame_length_history(); void load_sdl_context(); void load_gl_context(); GLuint load_shader(const fs::path&, GLenum) const; bool link_shader(GLuint program) const; void log_renderer_info(SDL_RendererInfo&); void log_display_mode(); void log_surface_format(SDL_Surface*, std::string = "surface"); std::string get_pixel_format_string(Uint32); const nlohmann::json& configuration() const; nlohmann::json& configuration(); const SDL_Window* window() const; SDL_Window* window(); const SDL_Renderer* get_renderer() const; SDL_Renderer* get_renderer(); const Input& get_input() const; Input& get_input(); Audio& get_audio(); glm::vec2 weight(glm::vec2); void run(); void frame(float); void flag_to_end(); virtual void update() {}; void set_framerate(int); float get_frame_length() const; void handle_quit_event(SDL_Event&); void quit(); virtual std::string class_name() const { return "Game"; } ~Game(); /* Applies delta timing to a value: returns the value as weighted by the amount of time passed since the * last frame update, allowing for values to change the same amount over time independent of the frame rate */ template float weight(T amount) { return (last_frame_length / (1000.0 / 60)) * amount; } }; #if defined(__EMSCRIPTEN__) void loop(void*); #endif