├── .github └── workflows │ └── doxygen-gh-pages.yml ├── .gitignore ├── .vscode └── settings.json ├── CMakeLists.txt ├── Doxyfile ├── LICENSE.md ├── README.md └── include └── silvergun ├── _debug ├── exceptions.hpp └── logger.hpp ├── _globals ├── _defines.hpp ├── commands.hpp ├── engine_time.hpp ├── handlers.hpp ├── message.hpp ├── scene.hpp └── slv_asset.hpp ├── cmp ├── _components.hpp ├── ai.hpp ├── background.hpp ├── bounding_box.hpp ├── component.hpp ├── dispatcher.hpp ├── gfx.hpp ├── hitbox.hpp ├── location.hpp ├── motion.hpp ├── overlay.hpp └── sprite.hpp ├── config.hpp ├── display.hpp ├── engine.hpp ├── input.hpp ├── mgr ├── _managers.hpp ├── assets.hpp ├── audio.hpp ├── manager.hpp ├── messages.hpp ├── renderer.hpp ├── spawner.hpp ├── systems.hpp ├── variables.hpp └── world.hpp ├── silvergun.hpp └── sys ├── _systems.hpp ├── animate.hpp ├── collision.hpp ├── logic.hpp ├── movement.hpp └── system.hpp /.github/workflows/doxygen-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/marketplace/actions/doxygen-github-pages-deploy-action 2 | name: Doxygen GitHub Pages Deploy Action 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | steps: 15 | - uses: DenverCoder1/doxygen-github-pages-action@v2.0.0 16 | with: 17 | github_token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | docs -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/build": true, 5 | "**/docs": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Silvergun CMake 2 | # See LICENSE.md for copyright information. 3 | 4 | cmake_minimum_required(VERSION 3.11) 5 | project(silvergun VERSION 0.8.0 DESCRIPTION "Silvergun Game Engine") 6 | enable_language(CXX) 7 | 8 | set(CMAKE_BUILD_TYPE Release) 9 | include(GNUInstallDirs) 10 | 11 | install(DIRECTORY include/ 12 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 13 | FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019-present Matthew Evans 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Silvergun Game Engine 2 | 3 | __Silvergun__ is a lightweight cross-platform 2D game engine written in C++17 using an [ECS](https://en.wikipedia.org/wiki/Entity_component_system) design. 4 | 5 | ### Requirements 6 | - __Build tools__: 7 | - A working C++ build environment with [CMake](https://cmake.org) 8 | - __Libraries__: 9 | - [Allegro Game Library](https://liballeg.org) 10 | 11 | ----- 12 | 13 | ### Documentation 14 | 15 | See the API documentation at . Documentation can be built locally using [Doxygen](https://doxygen.nl/index.html). 16 | 17 | ----- 18 | 19 | ### Tools 20 | 21 | - [slv-mkscript](https://github.com/AtomicSponge/slv-mkscript) - Generate game scripts. Requires [NodeJS](https://nodejs.org/) 22 | 23 | ----- 24 | 25 | ### Demo Game 26 | 27 | For a live demo and simple example of the the API usage, see the following: 28 | 29 | - [Playable Demo](https://atomicsponge.github.io/slv-demo-01/) 30 | 31 | - [Source Code](https://github.com/AtomicSponge/slv-demo-01) 32 | -------------------------------------------------------------------------------- /include/silvergun/_debug/exceptions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_EXCEPTION_HPP) 9 | #define SLV_EXCEPTION_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "silvergun/_debug/logger.hpp" 16 | #include "silvergun/_globals/_defines.hpp" 17 | #include "silvergun/_globals/engine_time.hpp" 18 | 19 | namespace slv { 20 | 21 | /* 22 | * Creates an info object that can be passed to the engine exceptions. 23 | */ 24 | class exception_item final { 25 | friend class engine_error; 26 | friend class engine_exception; 27 | 28 | private: 29 | const char* description; // Exception description. 30 | const char* location; // Exception location. 31 | const unsigned int code; // Code of error 32 | const int64_t time; // Time of exception. 33 | 34 | exception_item() = delete; // Delete default constructor. 35 | ~exception_item() = default; // Default destructor. 36 | // Create a new exception item. 37 | exception_item(const std::string& d, const std::string& l, const unsigned int& c) : 38 | description(d.c_str()), location(l.c_str()), code(c), time(engine_time::check()) {}; 39 | }; 40 | 41 | /*! 42 | * \class engine_error 43 | * \brief Throws an engine runtime error. 44 | * 45 | * Exceptions thrown this way will terminate the engine. 46 | */ 47 | class engine_error final : public std::exception { 48 | private: 49 | const exception_item item; // Store the exception item. 50 | 51 | public: 52 | /*! 53 | * \brief Create a new runtime error object. Sets the location to Engine and code to 1. 54 | * \param d An exception description. 55 | */ 56 | engine_error(const std::string& d) : item(exception_item(d, "Engine", 1)) {}; 57 | 58 | engine_error() = delete; // Delete default constructor. 59 | virtual ~engine_error() = default; // Default destructor. 60 | 61 | /*! 62 | * \brief Returns the description of the thrown exception. 63 | * \return Description of thrown exception. 64 | */ 65 | const char* what() const noexcept override { 66 | return item.description; 67 | }; 68 | 69 | /*! 70 | * \brief Return the location the exception occured. 71 | * \return Location of thrown exception. 72 | */ 73 | const char* where() const noexcept { 74 | return item.location; 75 | }; 76 | 77 | /*! 78 | * \brief Return the time the exception occured. 79 | * \return Time of thrown exception. 80 | */ 81 | int64_t when() const noexcept { 82 | return item.time; 83 | }; 84 | }; 85 | 86 | /*! 87 | * \class engine_exception 88 | * \brief Throws an internal engine exception. 89 | * 90 | * Exceptions thrown this way will not terminate the engine. \n 91 | * If debugging is enabled, they will also be logged to file. 92 | */ 93 | class engine_exception final : public std::exception { 94 | private: 95 | const exception_item item; // Store the exception item. 96 | 97 | public: 98 | /*! 99 | * \brief Create an engine exception. 100 | * \param d Description of exception. 101 | * \param l Location in engine of exception. 102 | * \param c Code of exception. 103 | */ 104 | engine_exception(const std::string& d, const std::string& l, const unsigned int& c) : 105 | item(exception_item(d, l, c)) { 106 | if constexpr (build_options.debug_mode) { 107 | logger::log(item.description, item.location, item.code, item.time); 108 | } 109 | }; 110 | 111 | engine_exception() = delete; // Delete default constructor. 112 | virtual ~engine_exception() = default; // Default destructor. 113 | 114 | /*! 115 | * \brief Returns the description of the thrown exception. 116 | * \return Description of thrown exception. 117 | */ 118 | const char* what() const noexcept override { 119 | return item.description; 120 | }; 121 | 122 | /*! 123 | * \brief Return the location the exception occured. 124 | * \return Location of thrown exception. 125 | */ 126 | const char* where() const noexcept { 127 | return item.location; 128 | }; 129 | 130 | /*! 131 | * \brief Return the time the exception occured. 132 | * \return Time of thrown exception. 133 | */ 134 | int64_t when() const noexcept { 135 | return item.time; 136 | }; 137 | }; 138 | 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /include/silvergun/_debug/logger.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_LOGGER_HPP) 9 | #define SLV_LOGGER_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace slv { 20 | 21 | class engine; 22 | 23 | /*! 24 | * \class logger 25 | * \brief Logs exceptions to file. This option is built when the engine is in debug mode. 26 | */ 27 | class logger final { 28 | friend class engine; 29 | 30 | private: 31 | logger() = default; 32 | ~logger() = default; 33 | 34 | static void start(void) { 35 | std::time_t t = std::time(nullptr); 36 | std::ostringstream date_stream; 37 | date_stream << std::put_time(std::localtime(&t), "%d-%m-%Y_%H-%M-%S"); 38 | std::string date = date_stream.str(); 39 | std::cout << "Logging exceptions to: exceptions_" + date + ".log.csv\n"; 40 | log_file.open("exceptions_" + date + ".log.csv", std::ios::out | std::ios::trunc); 41 | log_file << "Description, Location, Time, Code" << std::endl; 42 | }; 43 | 44 | static void stop(void) { 45 | log_file.close(); 46 | }; 47 | 48 | inline static std::ofstream log_file; 49 | 50 | public: 51 | logger(const logger&) = delete; // Delete copy constructor. 52 | void operator=(logger const&) = delete; // Delete assignment operator. 53 | 54 | /*! 55 | * \brief Add exception information to the logger. 56 | * \param d Description of item. 57 | * \param l Location of item. 58 | * \param c Error code of item. 59 | * \param t Engine time of item. 60 | */ 61 | static const void log( 62 | const std::string& d, const std::string& l, 63 | const unsigned int& c, const int64_t& t) { 64 | log_file << d + ", " + l + ", " + std::to_string(c) + ", " + std::to_string(t) + "\n"; 65 | }; 66 | }; 67 | 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/silvergun/_globals/_defines.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_GLOBAL_DEFINES_HPP) 9 | #define SLV_GLOBAL_DEFINES_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | // Enable math defines for entire engine. 18 | #if !defined(_USE_MATH_DEFINES) 19 | #define _USE_MATH_DEFINES 20 | #endif 21 | 22 | // Define true & false for macro use. 23 | #if !defined(TRUE) 24 | #define TRUE (1) 25 | #endif 26 | #if !defined(FALSE) 27 | #define FALSE (0) 28 | #endif 29 | 30 | // Enable debug mode 31 | #if defined(SLV_BUILD_DEBUG) 32 | #define SLV_DEBUG_MODE TRUE 33 | #else 34 | #define SLV_DEBUG_MODE FALSE 35 | #endif 36 | 37 | // Require OpenGL 3.0 38 | #if !defined(SLV_REQUIRE_OPENGL_LATEST) 39 | #define SLV_OPENGL_LATEST TRUE 40 | #else 41 | #define SLV_OPENGL_LATEST FALSE 42 | #endif 43 | 44 | // Set the timer rate. 45 | // Number of ticks per second as a float. 46 | #if !defined(SLV_TICKS_PER_SECOND) 47 | #define SLV_TICKS_PER_SECOND (60.0f) 48 | #endif 49 | 50 | // Set max number of playing samples. 51 | #if !defined(SLV_MAX_PLAYING_SAMPLES) 52 | #define SLV_MAX_PLAYING_SAMPLES (12) 53 | #endif 54 | 55 | // Toggle keyboard building 56 | #if !defined(SLV_DISABLE_KEYBOARD) 57 | #define SLV_USE_KEYBOARD TRUE 58 | #else 59 | #define SLV_USE_KEYBOARD FALSE 60 | #endif 61 | 62 | // Toggle mouse building 63 | #if !defined(SLV_DISABLE_MOUSE) 64 | #define SLV_USE_MOUSE TRUE 65 | #else 66 | #define SLV_USE_MOUSE FALSE 67 | #endif 68 | 69 | // Toggle joystick building 70 | #if !defined(SLV_DISABLE_JOYSTICK) 71 | #define SLV_USE_JOYSTICK TRUE 72 | #else 73 | #define SLV_USE_JOYSTICK FALSE 74 | #endif 75 | 76 | // Toggle touch building 77 | #if !defined(SLV_DISABLE_TOUCH) 78 | #define SLV_USE_TOUCH TRUE 79 | #else 80 | #define SLV_USE_TOUCH FALSE 81 | #endif 82 | 83 | #if !SLV_USE_KEYBOARD && !SLV_USE_MOUSE && !SLV_USE_JOYSTICK && !SLV_USE_TOUCH 84 | #error Must define at least one input device to be used 85 | #endif 86 | 87 | namespace slv { 88 | 89 | /* 90 | * Build flags for configuring the engine. 91 | */ 92 | struct slv_build_options { 93 | inline constexpr static bool debug_mode = static_cast(SLV_DEBUG_MODE); 94 | inline constexpr static bool opengl_latest = static_cast(SLV_OPENGL_LATEST); 95 | inline constexpr static float ticks_per_sec = static_cast(SLV_TICKS_PER_SECOND); 96 | inline constexpr static int max_playing_samples = static_cast(SLV_MAX_PLAYING_SAMPLES); 97 | 98 | // Input options 99 | inline constexpr static bool keyboard_enabled = static_cast(SLV_USE_KEYBOARD); 100 | inline constexpr static bool mouse_enabled = static_cast(SLV_USE_MOUSE); 101 | inline constexpr static bool joystick_enabled = static_cast(SLV_USE_JOYSTICK); 102 | inline constexpr static bool touch_enabled = static_cast(SLV_USE_TOUCH); 103 | }; 104 | inline constexpr slv_build_options build_options; 105 | 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /include/silvergun/_globals/commands.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_COMMANDS_HPP) 9 | #define SLV_COMMANDS_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "silvergun/_globals/message.hpp" 17 | 18 | namespace slv { 19 | 20 | /*! 21 | * \class commands 22 | * \brief Container for storing engine commands expressed as a lambda. 23 | */ 24 | class commands final { 25 | private: 26 | // Container for commands. 27 | std::map>> _commands; 28 | 29 | public: 30 | commands() = default; // Default constructor. 31 | ~commands() = default; // Default destructor. 32 | 33 | /*! 34 | * \brief Add a command to the command processor. 35 | * \param cmd Command name to run. 36 | * \param nargs Minimum number of expected arguments. 37 | * \param func Lambda expression to run. 38 | * \return True on sucess, false on fail. 39 | */ 40 | bool add( 41 | const std::string& cmd, 42 | const std::size_t& nargs, 43 | const std::function& func 44 | ) { 45 | auto ret = _commands.insert(std::make_pair(cmd, std::make_pair(nargs, func))); 46 | return ret.second; 47 | }; 48 | 49 | /*! 50 | * \brief Process a list of messages. 51 | * \param messages List of messages to process. 52 | */ 53 | void process_messages(const message_container& messages) { 54 | for (auto& it: messages) { 55 | auto res = _commands.find(it.get_cmd()); 56 | // Check to make sure there are enough arguments to run the command. 57 | if (res != _commands.end() && it.num_args() >= res->second.first) 58 | res->second.second(it.get_args()); 59 | } 60 | }; 61 | }; 62 | 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/silvergun/_globals/engine_time.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_ENGINE_TIME_HPP) 9 | #define SLV_ENGINE_TIME_HPP 10 | 11 | #include 12 | 13 | namespace slv { 14 | 15 | /*! 16 | * \class engine_time 17 | * \brief Tracks current time of the engine. 18 | */ 19 | class engine_time final { 20 | friend class engine; 21 | 22 | private: 23 | // Sets the internal timer. Called internally by engine. 24 | static void set(const int64_t& t) { current_time = t; }; 25 | inline static int64_t current_time = 0; // Track game timer 26 | 27 | public: 28 | engine_time() = delete; // Delete constructor. 29 | ~engine_time() = delete; // Delete destructor. 30 | engine_time(const engine_time&) = delete; // Delete copy constructor. 31 | void operator=(engine_time const&) = delete; // Delete assignment operator. 32 | 33 | /*! 34 | * \brief Check the internal engine timer. 35 | * \return Timer value. 36 | */ 37 | static int64_t check(void) { return current_time; }; 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/silvergun/_globals/handlers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_HANDLERS_HPP) 9 | #define SLV_HANDLERS_HPP 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "silvergun/_globals/_defines.hpp" 17 | 18 | namespace slv::handler { 19 | 20 | /*! 21 | * Handler function template definitions. 22 | * These corospond to the various Allegro events. 23 | * See https://liballeg.org/a5docs/trunk/events.html for more info. 24 | */ 25 | using key = std::function; 26 | using mouse_axis = std::function; 29 | using mouse_button = std::function; 32 | using mouse_display = std::function; 34 | using joystick_axis = std::function; 35 | using joystick_button = std::function; 36 | using touch = std::function; 39 | 40 | } 41 | 42 | namespace slv { 43 | 44 | /*! 45 | * Handler scopes. 46 | * Defines when the handlers are to be used. 47 | */ 48 | enum handler_scopes { 49 | SCOPE_A, 50 | SCOPE_B, 51 | SCOPE_C, 52 | }; 53 | 54 | /*! 55 | * Handler events. 56 | * Select the event action. 57 | */ 58 | enum handler_events { 59 | EVENT_KEY_DOWN, //!< Event key down. 60 | EVENT_KEY_UP, //!< Event key up. 61 | 62 | EVENT_MOUSE_AXIS, //!< Event mouse axis. 63 | EVENT_MOUSE_BUTTON_DOWN, //!< Event mouse button down. 64 | EVENT_MOUSE_BUTTON_UP, //!< Event mouse button up. 65 | EVENT_MOUSE_WARPED, //!< Event mouse warped. 66 | EVENT_MOUSE_ENTER_DISPLAY, //!< Event mouse enters display. 67 | EVENT_MOUSE_LEAVE_DISPLAY, //!< Event mouse leaves display. 68 | 69 | EVENT_JOYSTICK_AXIS, //!< Event joystick axis. 70 | EVENT_JOYSTICK_BUTTON_DOWN, //!< Event joystick button down. 71 | EVENT_JOYSTICK_BUTTON_UP, //!< Event joystick button up. 72 | 73 | EVENT_TOUCH_BEGIN, //!< Event touch input begin. 74 | EVENT_TOUCH_END, //!< Event touch input end. 75 | EVENT_TOUCH_MOVE, //!< Event touch input moves. 76 | EVENT_TOUCH_CANCEL, //!< Event touch input canceled. 77 | 78 | HANDLER_EVENT_MAX 79 | }; 80 | 81 | } 82 | 83 | namespace slv { 84 | 85 | /*! 86 | * Handler types. 87 | * Defines which function type to choose for the handler. 88 | */ 89 | using handler_types = std::variant< 90 | handler::key, //!< Keyboard event type. 91 | handler::mouse_axis, //!< Mouse axis event type. 92 | handler::mouse_button, //!< Mouse button event type. 93 | handler::mouse_display, //!< Mouse display event type. 94 | handler::joystick_axis, //!< Joystick axis event type. 95 | handler::joystick_button, //!< Joystick button event type. 96 | handler::touch //!< Touch event type. 97 | >; 98 | 99 | // Template structs to store handlers 100 | template 101 | struct handlers {}; 102 | 103 | template 104 | struct handlers { 105 | inline static handler_types _handle = [](const int&, ALLEGRO_DISPLAY*) {}; 106 | }; 107 | 108 | template 109 | struct handlers { 110 | inline static handler_types _handle = [](const int&, const int&, const int&, const int&, 111 | const int&, const int&, const int&, const int&, const float&, ALLEGRO_DISPLAY*) {}; 112 | }; 113 | template 114 | struct handlers { 115 | inline static handler_types _handle = [](const int&, const int&, 116 | const int&, const int&, const unsigned int&, ALLEGRO_DISPLAY*) {}; 117 | }; 118 | template 119 | struct handlers { 120 | inline static handler_types _handle = [](const int&, const int&, 121 | const int&, const int&, ALLEGRO_DISPLAY*) {}; 122 | }; 123 | 124 | template 125 | struct handlers { 126 | inline static handler_types _handle = [](const int&, const int&, 127 | const float&, ALLEGRO_JOYSTICK*) {}; 128 | }; 129 | template 130 | struct handlers { 131 | inline static handler_types _handle = [](const int&, ALLEGRO_JOYSTICK*) {}; 132 | }; 133 | 134 | template 135 | struct handlers { 136 | inline static handler_types _handle = [](const int&, const float&, const float&, 137 | const float&, const float&, const bool&, ALLEGRO_DISPLAY*) {}; 138 | }; 139 | 140 | /*! 141 | * \brief Used to add an input handle. 142 | * \tparam S Handler scope. 143 | * \tparam IDX Event index. 144 | * \tparam T Handler type. 145 | * \param handle Input handler function expression. 146 | */ 147 | template 148 | constexpr void add_handler(const handler_types& handle) { 149 | static_assert(S == SCOPE_A || S == SCOPE_B || S == SCOPE_C, 150 | "Scope must be one of the following: SCOPE_A, SCOPE_B, SCOPE_C"); 151 | static_assert(IDX < HANDLER_EVENT_MAX, "Invalid Handler Event Index"); 152 | static_assert(std::is_same_v || 153 | std::is_same_v || 154 | std::is_same_v || 155 | std::is_same_v || 156 | std::is_same_v || 157 | std::is_same_v || 158 | std::is_same_v, 159 | "Type must be a valid handler"); 160 | if constexpr (std::is_same_v) 161 | static_assert(IDX == EVENT_KEY_DOWN || IDX == EVENT_KEY_UP, 162 | "Event Index must be a Key Up or Down Event"); 163 | else if constexpr (std::is_same_v) 164 | static_assert(IDX == EVENT_MOUSE_AXIS || IDX == EVENT_MOUSE_WARPED, 165 | "Event Index must be a Mouse Axes or Warped Event"); 166 | else if constexpr (std::is_same_v) 167 | static_assert(IDX == EVENT_MOUSE_BUTTON_DOWN || IDX == EVENT_MOUSE_BUTTON_UP, 168 | "Event Index must be a Mouse Button Up or Down Event"); 169 | else if constexpr (std::is_same_v) 170 | static_assert(IDX == EVENT_MOUSE_ENTER_DISPLAY || IDX == EVENT_MOUSE_LEAVE_DISPLAY, 171 | "Event Index must be a Mouse Enter or Leave Display Event"); 172 | else if constexpr (std::is_same_v) 173 | static_assert(IDX == EVENT_JOYSTICK_AXIS, 174 | "Event Index must be a Joystick Axes Event"); 175 | else if constexpr (std::is_same_v) 176 | static_assert(IDX == EVENT_JOYSTICK_BUTTON_DOWN || IDX == EVENT_JOYSTICK_BUTTON_UP, 177 | "Event Index must be a Joystick Button Up or Down Event"); 178 | else if constexpr (std::is_same_v) 179 | static_assert(IDX == EVENT_TOUCH_BEGIN || IDX == EVENT_TOUCH_END || 180 | IDX == EVENT_TOUCH_MOVE || IDX == EVENT_TOUCH_CANCEL, 181 | "Event Index must be a Touch Event"); 182 | handlers::_handle = handle; 183 | }; 184 | 185 | } 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /include/silvergun/_globals/message.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_MESSAGE_HPP) 9 | #define SLV_MESSAGE_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace slv { 17 | 18 | /*! 19 | * \typedef std::vector msg_args 20 | * Container to store each message argument separately. 21 | */ 22 | using msg_args = std::vector; 23 | 24 | /*! 25 | * \class message 26 | * \brief Define individual message objects. 27 | */ 28 | class message final { 29 | private: 30 | // Split arguments into a vector of strings. 31 | void split_args(const std::string& a) { 32 | if (a == "") args.push_back(""); 33 | else { 34 | std::stringstream arg_stream(a); 35 | std::string segment; 36 | 37 | while (std::getline(arg_stream, segment, ';')) { 38 | args.push_back(segment); 39 | } 40 | } 41 | }; 42 | 43 | int64_t timer; // Timer value that the message will be processed at 44 | std::string sys; // System that will process the message 45 | std::string to; // Message to entity field 46 | std::string from; // Message from entity field 47 | std::string cmd; // Message command 48 | msg_args args; // Message arguments 49 | 50 | public: 51 | message() = delete; // Delete default constructor. 52 | 53 | /*! 54 | * \brief Create a non-timed message. 55 | * \param s System. 56 | * \param c Command. 57 | * \param a Arguments delimited by ; 58 | */ 59 | message( 60 | const std::string& s, 61 | const std::string& c, 62 | const std::string& a 63 | ) : timer(-1), sys(s), to(""), from(""), cmd(c) { 64 | split_args(a); 65 | }; 66 | 67 | /*! 68 | * \brief Create a timed message. 69 | * \param e Timer value. 70 | * \param s System. 71 | * \param c Command. 72 | * \param a Arguments delimited by ; 73 | */ 74 | message( 75 | const int64_t& e, 76 | const std::string& s, 77 | const std::string& c, 78 | const std::string& a 79 | ) : timer(e), sys(s), to(""), from(""), cmd(c) { 80 | split_args(a); 81 | }; 82 | 83 | /*! 84 | * \brief Create a non-timed message with a to & from. 85 | * \param s System. 86 | * \param t To. 87 | * \param f From. 88 | * \param c Command. 89 | * \param a Arguments delimited by ; 90 | */ 91 | message( 92 | const std::string& s, 93 | const std::string& t, 94 | const std::string& f, 95 | const std::string& c, 96 | const std::string& a 97 | ) : timer(-1), sys(s), to(t), from(f), cmd(c) { 98 | split_args(a); 99 | }; 100 | 101 | /*! 102 | * \brief Create a timed message with a to & from. 103 | * \param e Timer value. 104 | * \param s System. 105 | * \param t To. 106 | * \param f From. 107 | * \param c Command. 108 | * \param a Arguments delimited by ; 109 | */ 110 | message( 111 | const int64_t& e, 112 | const std::string& s, 113 | const std::string& t, 114 | const std::string& f, 115 | const std::string& c, 116 | const std::string& a 117 | ) : timer(e), sys(s), to(t), from(f), cmd(c) { 118 | split_args(a); 119 | }; 120 | 121 | /* 122 | * Overload < operator to sort by timer value. 123 | */ 124 | bool operator<(const message& m) const { 125 | return timer < m.timer; 126 | }; 127 | 128 | /*! 129 | * \brief Get timer value. 130 | * \return The value of timer. 131 | */ 132 | int64_t get_timer(void) const { 133 | return timer; 134 | }; 135 | 136 | /*! 137 | * \brief Get system value. 138 | * \return The value of sys. 139 | */ 140 | const std::string get_sys(void) const { 141 | return sys; 142 | }; 143 | 144 | /*! 145 | * \brief Get to value. 146 | * \return The value of to. 147 | */ 148 | const std::string get_to(void) const { 149 | return to; 150 | }; 151 | 152 | /*! 153 | * \brief Get from value. 154 | * \return The value of from. 155 | */ 156 | const std::string get_from(void) const { 157 | return from; 158 | }; 159 | 160 | /*! 161 | * \brief Get command value. 162 | * \return The value of cmd. 163 | */ 164 | const std::string get_cmd(void) const { 165 | return cmd; 166 | }; 167 | 168 | /*! 169 | * \brief Get number of arguments. 170 | * \return The number of arguments. 171 | */ 172 | std::size_t num_args(void) const { 173 | return args.size(); 174 | }; 175 | 176 | /*! 177 | * \brief Get the arguments split into a vector. 178 | * \return The vector of the arguments. 179 | */ 180 | const msg_args get_args(void) const { 181 | return args; 182 | }; 183 | 184 | /*! 185 | * \brief Returns a single argument by pos from the argument list. 186 | * \param pos The position in the argument vector. 187 | * \return The argument string by position. 188 | */ 189 | const std::string get_arg(const std::size_t& pos) const { 190 | if (pos >= args.size()) return ""; // Out of range, return empty string. 191 | else return args[pos]; 192 | }; 193 | 194 | /*! 195 | * \brief Check if the event is synced to the timer. 196 | * \return Returns false if the timer value is -1, else true. 197 | */ 198 | bool is_timed_event(void) const { 199 | if (timer == -1) return false; 200 | else return true; 201 | }; 202 | }; 203 | 204 | /*! 205 | * \typedef std::vector message_container 206 | * Container to store a collection of messages. 207 | */ 208 | typedef std::vector message_container; 209 | 210 | } 211 | 212 | #endif 213 | -------------------------------------------------------------------------------- /include/silvergun/_globals/scene.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_SCENE_HPP) 9 | #define SLV_SCENE_HPP 10 | 11 | #include 12 | 13 | #include "silvergun/_globals/handlers.hpp" 14 | 15 | namespace slv { 16 | 17 | /*! 18 | * \class scene 19 | * \brief Extend this to create a scene. 20 | */ 21 | class scene { 22 | protected: 23 | /*! 24 | * \brief Construct a new scene. 25 | * \param n Scene name. 26 | * \param s Scene handler scope. 27 | */ 28 | scene(const std::string& n, const std::size_t& s) : name(n), scope(s) { 29 | assert(s == SCOPE_A || s == SCOPE_B || s == SCOPE_C && 30 | "Scope must be one of the following: SCOPE_A, SCOPE_B, SCOPE_C"); 31 | }; 32 | 33 | public: 34 | virtual ~scene() = default; // Default virtual destructor. 35 | scene(const scene&) = delete; // Delete copy constructor. 36 | void operator=(scene const&) = delete; // Delete assignment operator. 37 | 38 | /*! 39 | * \brief Load the scene. 40 | */ 41 | virtual void load(void) {}; 42 | 43 | /*! 44 | * \brief Unload the scene. 45 | */ 46 | virtual void unload(void) {}; 47 | 48 | /*! 49 | * \brief Custom engine loop code. 50 | */ 51 | virtual void loop(void) {}; 52 | 53 | const std::string name; //!< Scene name. 54 | const std::size_t scope; //!< Scene handler scope. 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/silvergun/_globals/slv_asset.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_ASSET_HPP) 9 | #define SLV_ASSET_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace slv { 20 | 21 | /*! 22 | * \tparam T Asset type. 23 | */ 24 | template 25 | using slv_asset = std::shared_ptr; 26 | 27 | /*! 28 | * \brief Create an Allegro bitmap asset of size width x height. 29 | * \tparam ALLEGRO_BITMAP Allegro bitmap structure. 30 | * \param w Width of new bitmap. 31 | * \param h Height of new bitmap. 32 | * \return A new Allegro bitmap asset. 33 | */ 34 | template 35 | inline static const slv_asset make_asset(const int& w, const int& h) { 36 | std::shared_ptr temp_ptr(al_create_bitmap(w, h), al_destroy_bitmap); 37 | return temp_ptr; 38 | }; 39 | 40 | /*! 41 | * \brief Create the Allegro built-in font. 42 | * \tparam ALLEGRO_FONT Allegro font structure. 43 | * \return A new Allegro font asset with the default font. 44 | */ 45 | template 46 | inline static const slv_asset make_asset() { 47 | std::shared_ptr temp_ptr(al_create_builtin_font(), al_destroy_font); 48 | return temp_ptr; 49 | }; 50 | 51 | /*! 52 | * \brief Create an Allegro font asset. 53 | * \tparam ALLEGRO_FONT Allegro font structure. 54 | * \param fname Filename to load. 55 | * \param size Size of text. 56 | * \param flags Font flags (see Allegro documentation on al_load_font). 57 | * \return A new Allegro font asset with the loaded font. 58 | */ 59 | template 60 | inline static const slv_asset make_asset( 61 | const std::string& fname, const int& size, const int& flags 62 | ) { 63 | std::shared_ptr temp_ptr(al_load_font(fname.c_str(), size, flags), al_destroy_font); 64 | return temp_ptr; 65 | }; 66 | 67 | /*! 68 | * \brief Create an Allegro audio stream asset. 69 | * \tparam ALLEGRO_AUDIO_STREAM Allegro audio stream structure. 70 | * \param fname Filename to load. 71 | * \param buffer Buffer size. 72 | * \param samples Number of samples (see Allegro documentation on al_load_audio_stream). 73 | * \return A new Allegro audio stream asset with the loaded file. 74 | */ 75 | template 76 | inline static const slv_asset make_asset( 77 | const std::string& fname, const std::size_t& buffer, const int& samples 78 | ) { 79 | std::shared_ptr temp_ptr(al_load_audio_stream(fname.c_str(), buffer, samples), al_destroy_audio_stream); 80 | return temp_ptr; 81 | }; 82 | 83 | /*! 84 | * \brief Create an Allegro asset from file. 85 | * \tparam T Type of Allegro asset. 86 | * \param fname Filename to load. 87 | * \return A new asset of loaded type. 88 | */ 89 | template 90 | inline static const slv_asset make_asset(const std::string& fname) { 91 | static_assert(std::is_same_v || 92 | std::is_same_v || 93 | std::is_same_v, "Must be an Allegro type to load by filename."); 94 | 95 | if constexpr (std::is_same_v) { 96 | std::shared_ptr temp_ptr(al_load_bitmap(fname.c_str()), al_destroy_bitmap); 97 | return temp_ptr; 98 | } 99 | 100 | if constexpr (std::is_same_v) { 101 | std::shared_ptr temp_ptr(al_load_sample(fname.c_str()), al_destroy_sample); 102 | return temp_ptr; 103 | } 104 | 105 | if constexpr (std::is_same_v) { 106 | std::shared_ptr temp_ptr(al_load_audio_stream(fname.c_str(), 4, 2048), al_destroy_audio_stream); 107 | return temp_ptr; 108 | } 109 | }; 110 | 111 | /*! 112 | * \brief Create an asset from an object. 113 | * \tparam T Object type. 114 | * \param obj The object to load as an asset. 115 | * \return The object as an asset. 116 | */ 117 | template 118 | inline static const slv_asset make_asset(T& obj) { 119 | std::shared_ptr temp_ptr(obj); 120 | return temp_ptr; 121 | }; 122 | 123 | /*! 124 | * \brief Create an asset from an incomplete type. 125 | * \tparam T Data structure. 126 | * \param func Function to create the asset with. 127 | * \param deleter Deleter function to clean up data. 128 | * \return A new asset of the loaded type. 129 | */ 130 | template 131 | inline static const slv_asset make_asset( 132 | std::function& func, std::function& deleter 133 | ) { 134 | std::shared_ptr temp_ptr(func, deleter); 135 | return temp_ptr; 136 | }; 137 | 138 | } // end namespace wte 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /include/silvergun/cmp/_components.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_COMPONENTS_HPP) 9 | #define SLV_COMPONENTS_HPP 10 | 11 | #include "silvergun/cmp/ai.hpp" 12 | #include "silvergun/cmp/background.hpp" 13 | #include "silvergun/cmp/bounding_box.hpp" 14 | #include "silvergun/cmp/dispatcher.hpp" 15 | #include "silvergun/cmp/hitbox.hpp" 16 | #include "silvergun/cmp/location.hpp" 17 | #include "silvergun/cmp/motion.hpp" 18 | #include "silvergun/cmp/overlay.hpp" 19 | #include "silvergun/cmp/sprite.hpp" 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/silvergun/cmp/ai.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_AI_HPP) 9 | #define SLV_CMP_AI_HPP 10 | 11 | #include 12 | 13 | #include "silvergun/cmp/component.hpp" 14 | 15 | #include "silvergun/mgr/messages.hpp" 16 | #include "silvergun/mgr/world.hpp" 17 | 18 | namespace slv::sys { 19 | class logic; 20 | } 21 | 22 | namespace slv::cmp { 23 | 24 | /*! 25 | * \class ai 26 | * \brief Tag components to be processed by the Logic system. 27 | * 28 | * Allows functions to be created to define the enabled or disabled logic. 29 | */ 30 | class ai final : public component { 31 | friend class sys::logic; 32 | 33 | private: 34 | const std::function enabled_ai; // AI to run when enabled. 35 | const std::function disabled_ai; // AI to run when disabled. 36 | 37 | public: 38 | /*! 39 | * \brief Create an AI component with enabled only AI. 40 | * \param func Function to define AI process. 41 | */ 42 | ai(const std::function& func) : 43 | enabled(true), enabled_ai(func), disabled_ai([](const entity_id& e_id){}) {}; 44 | 45 | /*! 46 | * \brief Create an AI component with enabled and disabled AI. 47 | * \param func_a Function to define enabled AI process. 48 | * \param func_b Function to define disabled AI process. 49 | */ 50 | ai( 51 | const std::function& func_a, 52 | const std::function& func_b 53 | ) : enabled(true), enabled_ai(func_a), disabled_ai(func_b) {}; 54 | 55 | ai() = delete; // Delete default constructor. 56 | ~ai() = default; // Default destructor. 57 | 58 | bool enabled; //!< Flag to enable or disable the entity. 59 | }; 60 | 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/silvergun/cmp/background.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_BACKGROUND_HPP) 9 | #define SLV_CMP_BACKGROUND_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include "silvergun/cmp/gfx.hpp" 18 | 19 | namespace slv::cmp::gfx { 20 | 21 | /*! 22 | * \class background 23 | * \brief Component for storing a Background image and defining its animation process. 24 | */ 25 | class background final : public gfx { 26 | public: 27 | /*! 28 | * \brief Create a static Background component. 29 | * \param bmp Bitmap for static background. 30 | * \param l Background layer. 31 | * \param x X position of background. 32 | * \param y Y position of background. 33 | */ 34 | background( 35 | slv_asset bmp, 36 | const std::size_t& l, 37 | const float& x, 38 | const float& y 39 | ) : gfx(bmp, l, [](const entity_id& e_id) {}), pos_x(x), pos_y(y) {}; 40 | 41 | /*! 42 | * \brief Create a Background component with custom animation. 43 | * \param bmp Bitmap for background. 44 | * \param l Background layer. 45 | * \param x X position of background. 46 | * \param y Y position of background. 47 | * \param func Animcation function. 48 | */ 49 | background( 50 | slv_asset bmp, 51 | const std::size_t& l, 52 | const float& x, 53 | const float& y, 54 | const std::function& func 55 | ) : gfx(bmp, l, func), pos_x(x), pos_y(y) {}; 56 | 57 | background() = delete; // Delete default constructor. 58 | ~background() = default; // Default destructor. 59 | 60 | float pos_x; //!< X position. 61 | float pos_y; //!< Y position. 62 | }; 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/silvergun/cmp/bounding_box.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_BOUNDING_BOX_HPP) 9 | #define SLV_CMP_BOUNDING_BOX_HPP 10 | 11 | #include "silvergun/cmp/component.hpp" 12 | 13 | namespace slv::cmp { 14 | 15 | /*! 16 | * \class bounding_box 17 | * \brief Set a bounding box for an entity. 18 | * 19 | * Entities can not move out of this box. 20 | */ 21 | class bounding_box final : public component { 22 | public: 23 | /*! 24 | * \brief Create a new Bounding Box component. 25 | * \param lx Left X 26 | * \param ly Left Y 27 | * \param rx Right X 28 | * \param ry Right Y 29 | */ 30 | bounding_box( 31 | const float& lx, 32 | const float& ly, 33 | const float& rx, 34 | const float& ry 35 | ) : min_x(lx), min_y(ly), max_x(rx), max_y(ry) {}; 36 | 37 | bounding_box() = delete; // Delete default constructor. 38 | ~bounding_box() = default; // Default destructor. 39 | 40 | float min_x; //!< Top left X position of bounding box. 41 | float min_y; //!< Top left Y position of bounding box. 42 | float max_x; //!< Bottom right X position of bounding box. 43 | float max_y; //!< Bottom right Y position of bounding box. 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/silvergun/cmp/component.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_COMPONENT_HPP) 9 | #define SLV_CMP_COMPONENT_HPP 10 | 11 | #include 12 | 13 | namespace slv::cmp { 14 | 15 | /*! 16 | * \class component 17 | * \brief Interface class for creating a component. 18 | * 19 | * Extend this to creata a component that can be loaded into the Entity Manager. 20 | */ 21 | class component { 22 | protected: 23 | component() = default; // Default constructor. 24 | 25 | public: 26 | virtual ~component() = default; // Default virtual destructor. 27 | component(const component&) = delete; // Delete copy constructor. 28 | void operator=(component const&) = delete; // Delete assignment operator. 29 | }; 30 | 31 | /*! 32 | * \typedef std::shared_ptr component_sptr 33 | * Component shared pointer. 34 | */ 35 | using component_sptr = std::shared_ptr; 36 | 37 | /*! 38 | * \typedef std::shared_ptr component_csptr 39 | * Constant component shared pointer. 40 | */ 41 | using component_csptr = std::shared_ptr; 42 | 43 | /*! 44 | * \typedef 45 | */ 46 | template 47 | using comp_ptr = std::shared_ptr; 48 | 49 | /*! 50 | * \typedef 51 | */ 52 | template 53 | using const_comp_ptr = std::shared_ptr; 54 | 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /include/silvergun/cmp/dispatcher.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_DISPATCHER_HPP) 9 | #define SLV_CMP_DISPATCHER_HPP 10 | 11 | #include 12 | 13 | #include "silvergun/cmp/component.hpp" 14 | 15 | #include "silvergun/_globals/message.hpp" 16 | #include "silvergun/mgr/messages.hpp" 17 | #include "silvergun/mgr/world.hpp" 18 | 19 | namespace slv::mgr { 20 | class messages; 21 | } 22 | 23 | namespace slv::cmp { 24 | 25 | /*! 26 | * \class dispatcher 27 | * \brief Tag components to receive messages. 28 | * 29 | * Define message processing in handle_msg lambda. 30 | */ 31 | class dispatcher final : public component { 32 | friend class mgr::messages; 33 | 34 | private: 35 | // Message handler. 36 | const std::function handle_msg; 37 | 38 | public: 39 | /*! 40 | * \brief Create a new Dispatcher component. 41 | * \param func Function to define message processing. 42 | */ 43 | dispatcher(const std::function& func) : handle_msg(func) {}; 44 | 45 | dispatcher() = delete; // Delete default constructor. 46 | ~dispatcher() = default; // Default destructor. 47 | }; 48 | 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /include/silvergun/cmp/gfx.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_ANIMATOR_HPP) 9 | #define SLV_CMP_ANIMATOR_HPP 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include "silvergun/cmp/component.hpp" 16 | 17 | #include "silvergun/_globals/slv_asset.hpp" 18 | #include "silvergun/mgr/world.hpp" 19 | 20 | namespace slv::mgr::gfx { 21 | class renderer; 22 | } 23 | 24 | namespace slv::sys::gfx { 25 | class animate; 26 | } 27 | 28 | namespace slv::cmp::gfx { 29 | 30 | /*! 31 | * \class gfx 32 | * \brief Interface class for components that display graphics. 33 | */ 34 | class gfx : public component { 35 | friend class mgr::gfx::renderer; 36 | friend class sys::gfx::animate; 37 | 38 | private: 39 | bool tinted; // Flag to set tint. 40 | ALLEGRO_COLOR tint_color; // Color of tint. 41 | 42 | // Animation function. 43 | const std::function animate; 44 | 45 | protected: 46 | /*! 47 | * \brief Extend to create a gfx component. 48 | * \param bmp Bitmap asset to use. 49 | * \param l Layer position. 50 | * \param func Animation function. 51 | */ 52 | gfx( 53 | slv_asset bmp, 54 | const std::size_t& l, 55 | const std::function& func 56 | ) : layer(l), visible(true), rotated(false), direction(0.0f), 57 | scale_factor_x(1.0f), scale_factor_y(1.0f), 58 | _bitmap(bmp), tinted(false), animate(func) {}; 59 | 60 | //! Stores the bitmap used by the animator. 61 | slv_asset _bitmap; 62 | 63 | public: 64 | gfx() = delete; // Delete default constructor. 65 | virtual ~gfx() = default; // Default virtual destructor. 66 | 67 | /*! 68 | * \brief Overload < operator to sort by layer value. 69 | * \param a Object to compare to. 70 | * \return True if <, false if > 71 | */ 72 | bool operator<(const gfx& a) const { 73 | return layer < a.layer; 74 | }; 75 | 76 | /*! 77 | * \brief Set drawing to the internal bitmap. 78 | */ 79 | void set_drawing(void) { al_set_target_bitmap(_bitmap.get()); }; 80 | 81 | /*! 82 | * \brief Set a tint color. 83 | * \param c Allegro color. 84 | */ 85 | void set_tint(const ALLEGRO_COLOR& c) { 86 | tint_color = c; 87 | tinted = true; 88 | }; 89 | 90 | /*! 91 | * \brief Get the tint color. 92 | * \return Allegro color. 93 | */ 94 | const ALLEGRO_COLOR get_tint(void) const { return tint_color; }; 95 | 96 | /*! 97 | * \brief Clear tint color. 98 | */ 99 | void clear_tint(void) { tinted = false; }; 100 | 101 | std::size_t layer; //!< Layer position. 102 | bool visible; //!< Flag to set visibility. 103 | bool rotated; //!< Rotation flag. 104 | float direction; //!< Direction to draw when rotated. 105 | float scale_factor_x; //!< X scale factor. 106 | float scale_factor_y; //!< Y scale factor. 107 | }; 108 | 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /include/silvergun/cmp/hitbox.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_HITBOX_HPP) 9 | #define SLV_CMP_HITBOX_HPP 10 | 11 | #include "silvergun/cmp/component.hpp" 12 | 13 | namespace slv::cmp { 14 | 15 | /*! 16 | * \class hitbox 17 | * \brief Component to add a hitbox for performing colisions on. 18 | */ 19 | class hitbox final : public component { 20 | public: 21 | /*! 22 | * \brief Create a new Hitbox component. 23 | * \param w Width of the hitbox in pixels. 24 | * \param h Height of the hitbox in pixels. 25 | * \param t Team value for the hitbox. 26 | */ 27 | hitbox( 28 | const float& w, 29 | const float& h, 30 | const std::size_t& t 31 | ) : width(w), height(h), team(t), solid(true) {}; 32 | 33 | /*! 34 | * \brief Create a new Hitbox component, set solid flag. 35 | * \param w Width of the hitbox in pixels. 36 | * \param h Height of the hitbox in pixels. 37 | * \param t Team value for the hitbox. 38 | * \param s Boolean value for if the hitbox is solid (enabled). 39 | */ 40 | hitbox( 41 | const float& w, 42 | const float& h, 43 | const std::size_t& t, 44 | const bool& s 45 | ) : width(w), height(h), team(t), solid(s) {}; 46 | 47 | hitbox() = delete; // Delete default constructor. 48 | ~hitbox() = default; // Default destructor. 49 | 50 | float width; //!< Width of the hitbox. 51 | float height; //!< Height of the hitbox. 52 | std::size_t team; //!< Team number. 53 | bool solid; //!< Solid (enabled) flag. 54 | }; 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/silvergun/cmp/location.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_LOCATION_HPP) 9 | #define SLV_CMP_LOCATION_HPP 10 | 11 | #include "silvergun/cmp/component.hpp" 12 | 13 | namespace slv::cmp { 14 | 15 | /*! 16 | * \class location 17 | * \brief Store the X/Y location of an entity in the arena. 18 | */ 19 | class location final : public component { 20 | public: 21 | /*! 22 | * \brief Create a new Location component. 23 | * \param x Horizontal location of the entity. 24 | * \param y Vertical location of the entity. 25 | */ 26 | location( 27 | const float& x, 28 | const float& y 29 | ) : pos_x(x), pos_y(y) {}; 30 | 31 | location() = delete; // Delete default constructor. 32 | ~location() = default; // Default destructor. 33 | 34 | float pos_x; //!< Entity X location. 35 | float pos_y; //!< Entity Y location. 36 | }; 37 | 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/silvergun/cmp/motion.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_MOTION_HPP) 9 | #define SLV_CMP_MOTION_HPP 10 | 11 | #include "silvergun/cmp/component.hpp" 12 | 13 | namespace slv::cmp { 14 | 15 | /*! 16 | * \class motion 17 | * \brief Store motion information (velocity and direction) of an entity. 18 | */ 19 | class motion final : public component { 20 | public: 21 | /*! 22 | * \brief Create a new Motion component with set direction and velocity. 23 | * \param d Direction in radians. 24 | * \param xv X velocity. 25 | * \param yv Y velocity. 26 | */ 27 | motion( 28 | const float& d, 29 | const float& xv, 30 | const float& yv 31 | ) : direction(d), x_vel(xv), y_vel(yv) {}; 32 | 33 | motion() = delete; // Delete default constructor. 34 | ~motion() = default; // Default destructor. 35 | 36 | float direction; //!< Angle of direction. 37 | float x_vel; //!< X velocity. 38 | float y_vel; //!< Y velocity. 39 | }; 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/silvergun/cmp/overlay.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_OVERLAY_HPP) 9 | #define SLV_CMP_OVERLAY_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include "silvergun/cmp/gfx.hpp" 19 | 20 | namespace slv::cmp::gfx { 21 | 22 | /*! 23 | * \class overlay 24 | * \brief Component for storing an overlay image and defining its animation process. 25 | */ 26 | class overlay final : public gfx { 27 | private: 28 | slv_asset overlay_font; // Font for overlay. 29 | 30 | public: 31 | /*! 32 | * \brief Create a new Overlay component. 33 | * \param bmp Bitmap asset to use. 34 | * \param font Font asset to use. 35 | * \param l Layer for sorting. 36 | * \param x Horizontal location of the overlay in pixels. 37 | * \param y Vertical location of the overlay in pixels. 38 | * \param func Function to define what is displayed in the overlay. 39 | */ 40 | overlay( 41 | slv_asset bmp, 42 | slv_asset font, 43 | const std::size_t& l, 44 | const float& x, 45 | const float& y, 46 | const std::function& func 47 | ) : gfx(bmp, l, func), pos_x(x), pos_y(y), overlay_font(font) {}; 48 | 49 | overlay() = delete; // Delete default constructor. 50 | ~overlay() = default; // Default destructor. 51 | 52 | /*! 53 | * \brief Draw text on the overlay. 54 | * \param txt Text to be displayed. 55 | * \param color Allegro color object. 56 | * \param x Horizontal location of the text. 57 | * \param y Vertical location of the text. 58 | * \param f Text flags for drawing - see Allegro docs on al_draw_text. 59 | */ 60 | void draw_text( 61 | const std::string& txt, 62 | const ALLEGRO_COLOR& color, 63 | const float& x, 64 | const float& y, 65 | const int& f 66 | ) { 67 | al_draw_text(overlay_font.get(), color, x, y, f, txt.c_str()); 68 | }; 69 | 70 | float pos_x; //!< X position. 71 | float pos_y; //!< Y position. 72 | }; 73 | 74 | } // end namespace wte::cmp 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/silvergun/cmp/sprite.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CMP_SPRITE_HPP) 9 | #define SLV_CMP_SPRITE_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include "silvergun/cmp/gfx.hpp" 20 | 21 | #include "silvergun/_debug/exceptions.hpp" 22 | #include "silvergun/_globals/_defines.hpp" 23 | #include "silvergun/_globals/engine_time.hpp" 24 | #include "silvergun/mgr/world.hpp" 25 | 26 | namespace slv::mgr::gfx { 27 | class renderer; 28 | } 29 | 30 | namespace slv::cmp::gfx { 31 | 32 | /*! 33 | * \class sprite 34 | * \brief Component for loading a sprite sheet and storing its animation frames. 35 | */ 36 | class sprite final : public gfx { 37 | friend class mgr::gfx::renderer; 38 | 39 | private: 40 | // Animation cycle index. 41 | std::map> cycles; 42 | 43 | float sprite_width, sprite_height; // Sprite width & height. 44 | float draw_offset_x, draw_offset_y; // Sprite draw offset x/y. 45 | float sprite_x, sprite_y; // Sprite location. 46 | int sheet_width, sheet_height; // Sprite sheet size (w/h). 47 | std::size_t start_frame, stop_frame; // Current start/stop frame postitions. 48 | std::size_t current_frame, rate; // Current frame counter and frame rate. 49 | 50 | public: 51 | /*! 52 | * \brief Create a new Sprite component. 53 | * \param l Layer for sorting. 54 | * \param sw Sprite width. 55 | * \param sh Sprite height. 56 | * \param dox Horizontal draw offset in relation to entity location. 57 | * \param doy Verticle draw offset in relation to entity location. 58 | * \param rt Rate in engine timer ticks for animation. 59 | */ 60 | sprite( 61 | slv_asset bmp, 62 | const std::size_t& l, 63 | const float& sw, 64 | const float& sh, 65 | const float& dox, 66 | const float& doy, 67 | const std::size_t& rt 68 | ) :gfx(bmp, l,[this](const entity_id& e_id) { 69 | // Define sprite animation process. 70 | if (engine_time::check() % rate == 0) { 71 | // Increment frame. 72 | current_frame++; 73 | // Loop frame. 74 | if (current_frame > stop_frame) { 75 | current_frame = start_frame; 76 | } 77 | // Calculate the X position in the sprite sheet. 78 | sprite_x = (float)((int)(current_frame * sprite_width + sheet_width) % sheet_width); 79 | // Calculate the Y position in the sprite sheet. 80 | sprite_y = (float)((int)((current_frame * sprite_width) / sheet_width) * sprite_height); 81 | } 82 | }), 83 | sprite_width(sw), sprite_height(sh), draw_offset_x(dox), draw_offset_y(doy), 84 | sprite_x(0.0f), sprite_y(0.0f), 85 | start_frame(0), stop_frame(0), current_frame(0), rate(rt) 86 | { 87 | if (rate == 0) rate = 1; 88 | sheet_width = al_get_bitmap_width(_bitmap.get()); 89 | sheet_height = al_get_bitmap_height(_bitmap.get()); 90 | }; 91 | 92 | sprite() = delete; // Delete default constructor. 93 | ~sprite() = default; // Default destructor. 94 | 95 | /*! 96 | * \brief Add animation cycle. 97 | * \param name Name of cycle. 98 | * \param start Start cell of cycle. 99 | * \param stop End cell of cycle. 100 | * \return True if created, false if not. 101 | */ 102 | bool add_cycle( 103 | const std::string& name, 104 | const std::size_t& start, 105 | const std::size_t& stop 106 | ) { 107 | auto ret = cycles.insert(std::make_pair(name, std::make_pair(start, stop))); 108 | return ret.second; 109 | }; 110 | 111 | /*! 112 | * \brief Set the active cycle. 113 | * \param name Name of cycle to set. 114 | * \return True if set, false if not. 115 | */ 116 | bool set_cycle(const std::string& name) { 117 | auto it = cycles.find(name); 118 | if (it != cycles.end()) { 119 | start_frame = it->second.first; 120 | stop_frame = it->second.second; 121 | return true; 122 | } else return false; 123 | }; 124 | }; 125 | 126 | } 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /include/silvergun/config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_CONFIG_HPP) 9 | #define SLV_CONFIG_HPP 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include "silvergun/_debug/exceptions.hpp" 16 | #include "silvergun/_globals/_defines.hpp" 17 | 18 | namespace slv::mgr { 19 | class audio; 20 | } 21 | 22 | namespace slv::mgr::gfx { 23 | class renderer; 24 | } 25 | 26 | namespace slv { 27 | 28 | /*! 29 | * \class config 30 | * \brief Store engine config variables in a globally accessible class. 31 | */ 32 | class config { 33 | friend class display; 34 | friend class engine; 35 | friend class input; 36 | friend class mgr::audio; 37 | friend class mgr::gfx::renderer; 38 | 39 | private: 40 | struct _flags { 41 | inline static bool is_running = true; 42 | inline static bool record_input = false; 43 | inline static bool keyboard_installed = false; 44 | inline static bool mouse_installed = false; 45 | inline static bool joystick_installed = false; 46 | inline static bool touch_installed = false; 47 | inline static bool audio_installed = false; 48 | inline static bool show_hitboxes = false; 49 | }; 50 | 51 | struct _volume { 52 | inline static float main = 1.0f; 53 | inline static float music = 1.0f; 54 | inline static float music_a = 1.0f; 55 | inline static float music_b = 1.0f; 56 | inline static float sample = 1.0f; 57 | inline static float voice = 1.0f; 58 | inline static float ambiance = 1.0f; 59 | }; 60 | 61 | struct _gfx { 62 | inline static int screen_w = 0, screen_h = 0; 63 | inline static int viewport_w = 0, viewport_h = 0; 64 | inline static std::size_t vsync = 2; 65 | inline static std::size_t display_mode = 0; 66 | inline static float scale_factor = 1.0f; 67 | }; 68 | 69 | inline static bool initialized = false; // Restrict to one instance. 70 | 71 | protected: 72 | config() { 73 | if (initialized == true) throw engine_error("Config instance already running!"); 74 | initialized = true; 75 | }; 76 | 77 | public: 78 | virtual ~config() = default; // Default virtual destructor. 79 | config(const config&) = delete; // Delete copy constructor. 80 | void operator=(config const&) = delete; // Delete assignment operator. 81 | 82 | /*! 83 | * \struct flags 84 | * \brief Engine flags. 85 | */ 86 | struct flags { 87 | inline static const bool& is_running = _flags::is_running; //!< Flag for if the program itself is running. 88 | inline static bool engine_paused = false; //!< Flag to check if the engine if paused. 89 | inline static const bool& record_input = _flags::record_input; //!< Flag to enable/disable input recording. 90 | inline static const bool& keyboard_installed = _flags::keyboard_installed; //!< Flag to check if a keyboard is installed. 91 | inline static const bool& mouse_installed = _flags::mouse_installed; //!< Flag to check if a mouse is installed. 92 | inline static const bool& joystick_installed = _flags::joystick_installed; //!< Flag to check if a joystick is installed. 93 | inline static const bool& touch_installed = _flags::touch_installed; //!< Flag to check if touch input is installed. 94 | inline static const bool& audio_installed = _flags::audio_installed; //!< Flag to check if audio was installed. 95 | inline static bool draw_fps = true; //!< Flag to check if fps should be drawn. 96 | inline static bool input_enabled = true; //!< Flag to check if game input is enabled. 97 | inline static const bool& show_hitboxes = _flags::show_hitboxes; //!< Flag to enable/disable hitbox rendering. 98 | }; 99 | 100 | /*! 101 | * \struct volume 102 | * \brief Volume levels. 103 | */ 104 | struct volume { 105 | inline static const float& main = _volume::main; //!< Main volume level. 106 | inline static const float& music = _volume::music; //!< Mix 1 volume level. 107 | inline static const float& music_a = _volume::music_a; //!< Mix 1a volume level. 108 | inline static const float& music_b = _volume::music_b; //!< Mix 1b volume level. 109 | inline static const float& sample = _volume::sample; //!< Mix 2 volume level. 110 | inline static const float& voice = _volume::voice; //!< Mix 3 volume level. 111 | inline static const float& ambiance = _volume::ambiance; //!< Mix 4 volume level. 112 | }; 113 | 114 | /*! 115 | * \struct gfx 116 | * \brief Graphics settings. 117 | */ 118 | struct gfx { 119 | inline static const int& screen_w = _gfx::screen_w; //!< Screen width. 120 | inline static const int& screen_h = _gfx::screen_h; //!< Screen height. 121 | inline static const int& viewport_w = _gfx::viewport_w; //!< Viewport width. 122 | inline static const int& viewport_h = _gfx::viewport_h; //!< Viewport height. 123 | inline static const std::size_t& vsync = _gfx::vsync; //!< Vsync setting. 124 | inline static const std::size_t& display_mode = _gfx::display_mode; //!< Display mode setting. 125 | inline static const float& scale_factor = _gfx::scale_factor; //!< Arena scale factor. 126 | }; 127 | }; 128 | 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /include/silvergun/display.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_DISPLAY_HPP) 9 | #define SLV_DISPLAY_HPP 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "silvergun/_debug/exceptions.hpp" 17 | #include "silvergun/_globals/_defines.hpp" 18 | #include "silvergun/mgr/renderer.hpp" 19 | 20 | namespace slv { 21 | 22 | /*! 23 | * \class display 24 | * \brief Handles control of the display. 25 | */ 26 | class display { 27 | friend class engine; 28 | 29 | public: 30 | virtual ~display() = default; // Default virtual destructor. 31 | display(const display&) = delete; // Delete copy constructor. 32 | void operator=(display const&) = delete; // Delete assignment operator. 33 | 34 | /*! 35 | * \brief Set the window title. 36 | * \param title Window title. 37 | */ 38 | static void set_window_title(const std::string& title) { 39 | window_title = title; 40 | }; 41 | 42 | /*! 43 | * \brief Set the scale factor. 44 | * \param f Scale factor value. 45 | */ 46 | static void set_scale_factor(float f) { 47 | if (f < 0.5f || f > 2.0f) f = 1.0f; 48 | config::_gfx::scale_factor = f; 49 | }; 50 | 51 | /*! 52 | * \brief Change the display mode. Requires engine restart. 53 | * \param m New display mode. 54 | */ 55 | static void set_display_mode(std::size_t m) { 56 | if (m > 1) m = 1; 57 | config::_gfx::display_mode = m; 58 | }; 59 | 60 | /*! 61 | * \brief Set the vsync setting. 62 | * \param v New vsync setting. 63 | */ 64 | static void set_vsync(std::size_t v) { 65 | if (v > 2) v = 0; 66 | config::_gfx::vsync = v; 67 | }; 68 | 69 | /*! 70 | * \brief Resize the display. 71 | * \param w Screen width. 72 | * \param h Screen height. 73 | */ 74 | static void resize_display(int w, int h) { 75 | if (w < 1) w = 1; 76 | if (h < 1) h = 1; 77 | config::_gfx::screen_w = w; 78 | config::_gfx::screen_h = h; 79 | al_resize_display(_display, config::gfx::screen_w, config::gfx::screen_h); 80 | if (!al_acknowledge_resize(_display)) 81 | throw engine_error("Failed to resize display!"); 82 | }; 83 | 84 | protected: 85 | display() { 86 | if (initialized == true) 87 | throw engine_error("Display instance already running!"); 88 | initialized = true; 89 | }; 90 | 91 | private: 92 | // Configure the display. 93 | static void create_display(int w, int h) { 94 | // Set a default screen size 95 | config::_gfx::screen_w = w; 96 | config::_gfx::screen_h = h; 97 | 98 | al_reset_new_display_options(); 99 | 100 | // Configure vsync options. Gfx driver may override this. 101 | // 0 - System decides | 1 - VSync on | 2 - VSync off 102 | if (config::gfx::vsync >= 0 && config::gfx::vsync <= 2) { 103 | al_set_new_display_option(ALLEGRO_VSYNC, config::gfx::vsync, ALLEGRO_SUGGEST); 104 | } else { 105 | al_set_new_display_option(ALLEGRO_VSYNC, 0, ALLEGRO_SUGGEST); 106 | } 107 | 108 | // Check if a display mode is set. 109 | if (config::gfx::display_mode == 1) { 110 | (build_options.opengl_latest ? 111 | al_set_new_display_flags(ALLEGRO_OPENGL_3_0 | ALLEGRO_FULLSCREEN_WINDOW): 112 | al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_FULLSCREEN_WINDOW)); 113 | } else { 114 | (build_options.opengl_latest ? 115 | al_set_new_display_flags(ALLEGRO_OPENGL_3_0 | ALLEGRO_WINDOWED): 116 | al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED)); 117 | } 118 | 119 | // Create the display. Full screen windowed defaults to the display resolution. 120 | _display = al_create_display(config::gfx::screen_w, config::gfx::screen_h); 121 | 122 | // Display failed to load, try a fallback. 123 | if (!_display) { 124 | (build_options.opengl_latest ? 125 | al_set_new_display_flags(ALLEGRO_OPENGL_3_0 | ALLEGRO_WINDOWED): 126 | al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED)); 127 | _display = al_create_display(config::gfx::screen_w, config::gfx::screen_h); 128 | if (!_display) throw engine_error("Failed to configure display!"); 129 | config::_gfx::display_mode = 0; 130 | config::_gfx::scale_factor = 1.0f; 131 | } 132 | 133 | // Set window title. 134 | al_set_window_title(_display, window_title.c_str()); 135 | 136 | // Set window icon. 137 | ALLEGRO_FILE* file; 138 | file = al_fopen("icon.bmp", "rb"); 139 | if (file) { 140 | ALLEGRO_BITMAP* icon_bitmap = al_load_bitmap_f(file, ".bmp"); 141 | al_set_display_icon(_display, icon_bitmap); 142 | al_destroy_bitmap(icon_bitmap); 143 | } 144 | al_fclose(file); 145 | }; 146 | 147 | // Destroy the display. 148 | static void destroy_display(void) { 149 | al_destroy_display(_display); 150 | }; 151 | 152 | // Title for application window. 153 | inline static std::string window_title = "Silvergun Game Engine"; 154 | inline static bool initialized = false; // Restrict to one instance. 155 | 156 | inline static ALLEGRO_DISPLAY* _display; // Allegro object for the display. 157 | }; 158 | 159 | } 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /include/silvergun/engine.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_ENGINE_HPP) 9 | #define SLV_ENGINE_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(__EMSCRIPTEN__) 18 | #include 19 | #include 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "silvergun/config.hpp" 31 | #include "silvergun/display.hpp" 32 | #include "silvergun/input.hpp" 33 | 34 | #include "silvergun/_debug/exceptions.hpp" 35 | #include "silvergun/_debug/logger.hpp" 36 | #include "silvergun/_globals/_defines.hpp" 37 | #include "silvergun/_globals/commands.hpp" 38 | #include "silvergun/_globals/engine_time.hpp" 39 | #include "silvergun/_globals/scene.hpp" 40 | #include "silvergun/_globals/slv_asset.hpp" 41 | #include "silvergun/mgr/_managers.hpp" 42 | 43 | namespace slv { 44 | 45 | void start_game(void); 46 | void stop_game(void); 47 | #if defined(__EMSCRIPTEN__) 48 | void em_looper(void); 49 | #endif 50 | 51 | /*! 52 | * \class engine 53 | * \brief The main engine class. 54 | * 55 | * Sets up various system objects used by the engine. 56 | * Contains the main game loop and members for managing the game and engine. 57 | */ 58 | class engine final : public config, public input, public display { 59 | friend void start_game(void); 60 | friend void stop_game(void); 61 | #if defined(__EMSCRIPTEN__) 62 | friend void em_looper(void); 63 | #endif 64 | 65 | private: 66 | engine() = default; 67 | ~engine() = default; 68 | 69 | /* 70 | * Main engine loop (single pass) 71 | */ 72 | static void main_loop(void) { 73 | input::check_events(current_scene->scope); // Check for input. 74 | 75 | // Pause / resume timer check. Also process the on_pause events. 76 | if (config::flags::engine_paused && al_get_timer_started(main_timer)) { 77 | al_stop_timer(main_timer); 78 | on_engine_pause(); 79 | } 80 | if (!config::flags::engine_paused && !al_get_timer_started(main_timer)) { 81 | on_engine_unpause(); 82 | al_resume_timer(main_timer); 83 | } 84 | 85 | ALLEGRO_EVENT event; 86 | if (al_get_next_event(main_event_queue, &event)) { 87 | switch (event.type) { 88 | // Call our game logic update on timer events. 89 | // Timer is only running when the game is running. 90 | case ALLEGRO_EVENT_TIMER: 91 | // Set the engine_time object to the current time. 92 | engine_time::set(al_get_timer_count(main_timer)); 93 | // Run all systems. 94 | mgr::systems::run(); 95 | // Process messages. 96 | mgr::messages::dispatch(); 97 | // Get any spawner messages and pass to handler. 98 | mgr::spawner::process_messages(mgr::messages::get("spawner")); 99 | break; 100 | // Check if display looses focus. 101 | case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: 102 | out_of_focus(); 103 | break; 104 | // Check if display returns to focus. 105 | case ALLEGRO_EVENT_DISPLAY_SWITCH_IN: 106 | back_in_focus(); 107 | break; 108 | // Force quit if the game window is closed. 109 | case ALLEGRO_EVENT_DISPLAY_CLOSE: 110 | stop(); // Stop game 111 | break; 112 | // Window has been resized. 113 | case ALLEGRO_EVENT_DISPLAY_RESIZE: 114 | al_acknowledge_resize(_display); 115 | break; 116 | } 117 | } 118 | 119 | // Run any custom scene code 120 | current_scene->loop(); 121 | 122 | // Render the screen. 123 | mgr::gfx::renderer::render(); 124 | // Process system messages 125 | cmds.process_messages(mgr::messages::get("system")); 126 | // Send audio messages to the audio queue. 127 | mgr::audio::process_messages(mgr::messages::get("audio")); 128 | // Delete unprocessed messages. 129 | mgr::messages::prune(); 130 | }; 131 | 132 | static void stop(void) { 133 | current_scene->unload(); 134 | 135 | config::_flags::is_running = false; 136 | }; 137 | 138 | // Scenes 139 | inline static std::vector> scenes; 140 | inline static std::shared_ptr current_scene = nullptr; 141 | 142 | // Engine commands 143 | inline static commands cmds; 144 | 145 | // Allegro objects used by the engine. 146 | inline static ALLEGRO_TIMER* main_timer = NULL; 147 | inline static ALLEGRO_EVENT_QUEUE* main_event_queue = NULL; 148 | 149 | // Restrict to one instance of the engine running. 150 | inline static bool initialized = false; 151 | 152 | public: 153 | engine(const engine&) = delete; // Delete copy constructor. 154 | void operator=(engine const&) = delete; // Delete assignment operator. 155 | 156 | /*! 157 | * \brief Initialize the engine. 158 | * \param width Initial screen width. 159 | * \param height Initial screen height. 160 | */ 161 | static void initialize(int width, int height) { 162 | std::cout << "Initializing Silvergun Game Engine...\n"; 163 | if (initialized == true) throw engine_error(display::window_title + " already running!"); 164 | initialized = true; 165 | 166 | std::cout << "Loading Allegro Game Library... "; 167 | // Initialize Allegro. 168 | if (!al_init()) throw engine_error("Allegro failed to load!"); 169 | std::cout << "OK!\n"; 170 | 171 | // Initialize additional Allegro components. 172 | std::cout << "Loading Allegro add-ons... "; 173 | if (!al_init_image_addon()) throw engine_error("Failed to load Allegro image addon!"); 174 | if (!al_init_font_addon()) throw engine_error("Failed to load Allegro font addon!"); 175 | std::cout << "OK!\n"; 176 | config::_flags::audio_installed = al_install_audio(); 177 | // Input detection. 178 | if constexpr (build_options.keyboard_enabled) 179 | config::_flags::keyboard_installed = al_install_keyboard(); 180 | if constexpr (build_options.mouse_enabled) 181 | config::_flags::mouse_installed = al_install_mouse(); 182 | if constexpr (build_options.joystick_enabled) 183 | config::_flags::joystick_installed = al_install_joystick(); 184 | if constexpr (build_options.touch_enabled) 185 | config::_flags::touch_installed = al_install_touch_input(); 186 | 187 | // Configure display. Called from display class. 188 | std::cout << "Configuring display... "; 189 | create_display(width, height); 190 | std::cout << "OK!\n"; 191 | 192 | // Disable pesky screensavers. 193 | al_inhibit_screensaver(true); 194 | 195 | std::cout << "Creating main timer and event queue... "; 196 | // Configure main timer. 197 | main_timer = al_create_timer(1.0f / build_options.ticks_per_sec); 198 | if (!main_timer) throw engine_error("Failed to create timer!"); 199 | // Configure main event queue. 200 | main_event_queue = al_create_event_queue(); 201 | if (!main_event_queue) throw engine_error("Failed to create main event queue!"); 202 | std::cout << "OK!\n"; 203 | 204 | // Register event sources. 205 | al_register_event_source(main_event_queue, al_get_display_event_source(_display)); 206 | al_register_event_source(main_event_queue, al_get_timer_event_source(main_timer)); 207 | 208 | // Create the input event queue 209 | input::create_event_queue(); 210 | 211 | // Allegro extras 212 | al_init_primitives_addon(); 213 | if (config::flags::audio_installed) al_init_acodec_addon(); 214 | 215 | // Load systems and prevent further systems from being loaded. 216 | std::cout << "Loading systems... "; 217 | load_systems(); 218 | mgr::systems::finalized = true; 219 | if (mgr::systems::empty()) throw engine_error("No systems have been loaded!"); 220 | std::cout << "OK!\n"; 221 | 222 | std::cout << "Loading audio... "; 223 | mgr::audio::initialize(); 224 | std::cout << "OK!\n"; 225 | 226 | // Generate Allegro's default font and load into asset mgr. 227 | mgr::assets::load("slv_default_font", make_asset()); 228 | 229 | std::cout << "Initializing graphics... "; 230 | mgr::gfx::renderer::set_viewport_size(width, height); 231 | mgr::gfx::renderer::initialize(); 232 | std::cout << "OK!\n"; 233 | 234 | // Engine (system) commands 235 | cmds.add("load-script", 1, [](const msg_args& args) { 236 | mgr::messages::load_script(args[0]); 237 | }); 238 | cmds.add("load-scene", 1, [](const msg_args& args) { 239 | engine::load_scene(args[0]); 240 | }); 241 | cmds.add("enable-input", 0, [](const msg_args& args) { 242 | config::flags::input_enabled = true; 243 | }); 244 | cmds.add("disable-input", 0, [](const msg_args& args) { 245 | config::flags::input_enabled = false; 246 | }); 247 | 248 | if constexpr (build_options.debug_mode) { 249 | std::cout << "DEBUG MODE --- LOGGING ENABLED\n"; 250 | mgr::messages::message_log_start(); 251 | logger::start(); 252 | } 253 | 254 | config::flags::engine_paused = false; 255 | config::_flags::is_running = true; 256 | std::cout << "Engine started successfully!\n"; 257 | 258 | al_stop_timer(main_timer); 259 | al_set_timer_count(main_timer, 0); 260 | engine_time::set(al_get_timer_count(main_timer)); 261 | al_start_timer(main_timer); 262 | }; 263 | 264 | /*! 265 | * \brief De-initialize the engine. 266 | */ 267 | static void deinitialize(void) { 268 | std::cout << "\nDeinitializing Silvergun Game Engine...\n"; 269 | 270 | config::_flags::is_running = false; 271 | 272 | mgr::world::clear(); 273 | mgr::audio::deinitialize(); 274 | mgr::gfx::renderer::deinitialize(); 275 | mgr::assets::clear_al_objects(); 276 | 277 | std::cout << "Cleaning up engine objects... "; 278 | al_destroy_timer(main_timer); 279 | al_destroy_event_queue(main_event_queue); 280 | input::destroy_event_queue(); 281 | destroy_display(); 282 | al_inhibit_screensaver(false); 283 | std::cout << "OK!\n"; 284 | std::cout << "Stopping Allegro... "; 285 | al_shutdown_font_addon(); 286 | if (config::flags::audio_installed) al_uninstall_audio(); 287 | al_shutdown_primitives_addon(); 288 | al_uninstall_system(); 289 | std::cout << "OK!\n"; 290 | 291 | if constexpr (build_options.debug_mode) { 292 | logger::stop(); 293 | mgr::messages::message_log_stop(); 294 | } 295 | 296 | initialized = false; 297 | std::cout << "Good bye!\n"; 298 | }; 299 | 300 | /*! 301 | * \brief Add a scene. 302 | */ 303 | template 304 | static void add_scene(Args... args) { 305 | scenes.push_back(std::make_shared(args...)); 306 | }; 307 | 308 | /*! 309 | * \brief Load a scene. 310 | */ 311 | static void load_scene(const std::string& name) { 312 | if (current_scene != nullptr) current_scene->unload(); 313 | mgr::world::clear(); 314 | mgr::messages::clear(); 315 | 316 | const auto find_scene = [name](const std::shared_ptr& s) { return s->name == name; }; 317 | if (auto it = std::find_if(scenes.begin(), scenes.end(), find_scene); it != scenes.end()) { 318 | current_scene = *it; 319 | } else { 320 | throw engine_error("Scene " + name + " does not exist!"); 321 | } 322 | 323 | current_scene->load(); 324 | }; 325 | 326 | //! Define this to load all systems to be used by the game. 327 | inline static std::function load_systems = [](){}; 328 | //! Optional: On engine pause handler. 329 | inline static std::function on_engine_pause = [](){}; 330 | //! Optional: On engine unpause handler. 331 | inline static std::function on_engine_unpause = [](){}; 332 | //! Optional: Window out of focus handler. 333 | inline static std::function out_of_focus = [](){}; 334 | //! Optional: Window back in focus handler. 335 | inline static std::function back_in_focus = [](){}; 336 | }; 337 | 338 | #if defined(__EMSCRIPTEN__) 339 | inline void em_looper(void) { 340 | engine::main_loop(); 341 | if (!config::flags::is_running) emscripten_cancel_main_loop(); 342 | } 343 | #endif 344 | 345 | /*! 346 | * \brief The main engine loop. 347 | */ 348 | inline void start_game(void) { 349 | // MAIN ENGINE LOOP 350 | #if defined(__EMSCRIPTEN__) 351 | emscripten_set_main_loop(&em_looper, -1, true); 352 | #else 353 | while (config::flags::is_running) engine::main_loop(); 354 | #endif 355 | } 356 | 357 | /*! 358 | * \brief Stop the running game. 359 | */ 360 | inline void stop_game(void) { 361 | engine::stop(); 362 | } 363 | 364 | } // end namespace slv 365 | 366 | #endif 367 | -------------------------------------------------------------------------------- /include/silvergun/input.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_INPUT_HPP) 9 | #define SLV_INPUT_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include "silvergun/_debug/exceptions.hpp" 23 | #include "silvergun/_globals/_defines.hpp" 24 | #include "silvergun/_globals/engine_time.hpp" 25 | #include "silvergun/_globals/handlers.hpp" 26 | #include "silvergun/config.hpp" 27 | 28 | namespace slv { 29 | 30 | /*! 31 | * \class input 32 | * \brief Manage the input queue and process events. 33 | */ 34 | class input { 35 | friend class engine; 36 | 37 | public: 38 | virtual ~input() = default; // Default virtual destructor. 39 | input(const input&) = delete; // Delete copy constructor. 40 | void operator=(input const&) = delete; // Delete assignment operator. 41 | 42 | /*! 43 | * \brief Start input recording. 44 | */ 45 | static void start_recording(void) { 46 | input_event_file.open("input_events", std::ios::binary | std::ofstream::app); 47 | config::_flags::record_input = true; 48 | }; 49 | 50 | /*! 51 | * \brief Stop input recording. 52 | */ 53 | static void stop_recording(void) { 54 | if (input_event_file.is_open()) input_event_file.close(); 55 | config::_flags::record_input = false; 56 | }; 57 | 58 | protected: 59 | // Constructor 60 | input() { 61 | if (initialized == true) throw engine_error("Input instance already running!"); 62 | initialized = true; 63 | }; 64 | 65 | private: 66 | template 67 | constexpr inline static void run_handles(const ALLEGRO_EVENT& event) { 68 | // Keyboard events 69 | if constexpr (build_options.keyboard_enabled) { 70 | if (event.type == ALLEGRO_EVENT_KEY_DOWN) { 71 | std::get(handlers::_handle)( 72 | event.keyboard.keycode, event.keyboard.display); 73 | return; 74 | } 75 | if (event.type == ALLEGRO_EVENT_KEY_UP) { 76 | std::get(handlers::_handle)( 77 | event.keyboard.keycode, event.keyboard.display); 78 | return; 79 | } 80 | } 81 | 82 | // Mouse events 83 | if constexpr (build_options.mouse_enabled) { 84 | if (event.type == ALLEGRO_EVENT_MOUSE_AXES) { 85 | std::get(handlers::_handle)( 86 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 87 | event.mouse.dx, event.mouse.dy, event.mouse.dz, event.mouse.dw, 88 | event.mouse.pressure, event.mouse.display); 89 | return; 90 | } 91 | if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) { 92 | std::get(handlers::_handle)( 93 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 94 | event.mouse.button, event.mouse.display); 95 | return; 96 | } 97 | if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { 98 | std::get(handlers::_handle)( 99 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 100 | event.mouse.button, event.mouse.display); 101 | return; 102 | } 103 | if (event.type == ALLEGRO_EVENT_MOUSE_WARPED) { 104 | std::get(handlers::_handle)( 105 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 106 | event.mouse.dx, event.mouse.dy, event.mouse.dz, event.mouse.dw, 107 | event.mouse.pressure, event.mouse.display); 108 | return; 109 | } 110 | if (event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { 111 | std::get(handlers::_handle)( 112 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 113 | event.mouse.dx, event.mouse.dy, event.mouse.dz, event.mouse.dw, 114 | event.mouse.pressure, event.mouse.display); 115 | return; 116 | } 117 | if (event.type == ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY) { 118 | std::get(handlers::_handle)( 119 | event.mouse.x, event.mouse.y, event.mouse.z, event.mouse.w, 120 | event.mouse.dx, event.mouse.dy, event.mouse.dz, event.mouse.dw, 121 | event.mouse.pressure, event.mouse.display); 122 | return; 123 | } 124 | } 125 | 126 | // Joystick events 127 | if constexpr (build_options.joystick_enabled) { 128 | if (event.type == ALLEGRO_EVENT_JOYSTICK_AXIS) { 129 | std::get(handlers::_handle)( 130 | event.joystick.stick, event.joystick.axis, event.joystick.pos, event.joystick.id); 131 | return; 132 | } 133 | if (event.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN) { 134 | std::get(handlers::_handle)( 135 | event.joystick.button, event.joystick.id); 136 | return; 137 | } 138 | if (event.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_UP) { 139 | std::get(handlers::_handle)( 140 | event.joystick.button, event.joystick.id); 141 | return; 142 | } 143 | } 144 | 145 | // Touch events 146 | if constexpr (build_options.touch_enabled) { 147 | if (event.type == ALLEGRO_EVENT_TOUCH_BEGIN) { 148 | std::get(handlers::_handle)( 149 | event.touch.id, event.touch.x, event.touch.y, event.touch.dx, event.touch.dy, event.touch.primary, event.touch.display); 150 | return; 151 | } 152 | if (event.type == ALLEGRO_EVENT_TOUCH_END) { 153 | std::get(handlers::_handle)( 154 | event.touch.id, event.touch.x, event.touch.y, event.touch.dx, event.touch.dy, event.touch.primary, event.touch.display); 155 | return; 156 | } 157 | if (event.type == ALLEGRO_EVENT_TOUCH_MOVE) { 158 | std::get(handlers::_handle)( 159 | event.touch.id, event.touch.x, event.touch.y, event.touch.dx, event.touch.dy, event.touch.primary, event.touch.display); 160 | return; 161 | } 162 | if (event.type == ALLEGRO_EVENT_TOUCH_CANCEL) { 163 | std::get(handlers::_handle)( 164 | event.touch.id, event.touch.x, event.touch.y, event.touch.dx, event.touch.dy, event.touch.primary, event.touch.display); 165 | return; 166 | } 167 | } 168 | }; 169 | 170 | // Create the input queue. 171 | static void create_event_queue(void) { 172 | input_event_queue = al_create_event_queue(); 173 | if (!input_event_queue) throw engine_error("Failed to create input event queue!"); 174 | 175 | if (build_options.keyboard_enabled && config::flags::keyboard_installed) 176 | al_register_event_source(input_event_queue, al_get_keyboard_event_source()); 177 | if (build_options.mouse_enabled && config::flags::mouse_installed) 178 | al_register_event_source(input_event_queue, al_get_mouse_event_source()); 179 | if (build_options.joystick_enabled && config::flags::joystick_installed) 180 | al_register_event_source(input_event_queue, al_get_joystick_event_source()); 181 | if (build_options.touch_enabled && config::flags::touch_installed) 182 | al_register_event_source(input_event_queue, al_get_touch_input_event_source()); 183 | }; 184 | 185 | // Destroy the input queue. 186 | static void destroy_event_queue(void) { 187 | al_destroy_event_queue(input_event_queue); 188 | }; 189 | 190 | // Record input events 191 | static void record_event(const int64_t& time, const ALLEGRO_EVENT& event) { 192 | input_event_file.write(reinterpret_cast(time), sizeof(int64_t)); 193 | input_event_file.write(reinterpret_cast(sizeof(event)), sizeof(std::size_t)); 194 | input_event_file.write(reinterpret_cast(&event), sizeof(event)); 195 | }; 196 | 197 | // Check the input queue for events. 198 | static void check_events(const std::size_t& scope) { 199 | ALLEGRO_EVENT event; 200 | while (al_get_next_event(input_event_queue, &event)) { 201 | if (config::flags::input_enabled) { 202 | // Record input if enabled. 203 | if (config::flags::record_input) record_event(engine_time::check(), event); 204 | // Run the handles 205 | switch (scope) { 206 | case 0: 207 | run_handles(event); 208 | break; 209 | case 1: 210 | run_handles(event); 211 | break; 212 | case 2: 213 | run_handles(event); 214 | break; 215 | } 216 | } 217 | } 218 | }; 219 | 220 | inline static ALLEGRO_EVENT_QUEUE* input_event_queue; // Input event queue. 221 | inline static std::ofstream input_event_file; // Event record file. 222 | inline static bool initialized = false; // Restrict to one instance. 223 | }; 224 | 225 | } 226 | 227 | #endif 228 | -------------------------------------------------------------------------------- /include/silvergun/mgr/_managers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_MGR_MANAGERS_HPP) 9 | #define SLV_MGR_MANAGERS_HPP 10 | 11 | #include "silvergun/mgr/assets.hpp" 12 | #include "silvergun/mgr/audio.hpp" 13 | #include "silvergun/mgr/messages.hpp" 14 | #include "silvergun/mgr/renderer.hpp" 15 | #include "silvergun/mgr/spawner.hpp" 16 | #include "silvergun/mgr/systems.hpp" 17 | #include "silvergun/mgr/variables.hpp" 18 | #include "silvergun/mgr/world.hpp" 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/silvergun/mgr/assets.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_MGR_ASSETS_HPP) 9 | #define SLV_MGR_ASSETS_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "silvergun/mgr/manager.hpp" 19 | 20 | #include "silvergun/_debug/exceptions.hpp" 21 | #include "silvergun/_globals/_defines.hpp" 22 | #include "silvergun/_globals/engine_time.hpp" 23 | #include "silvergun/_globals/slv_asset.hpp" 24 | 25 | namespace slv { 26 | class engine; 27 | } 28 | 29 | namespace slv::mgr { 30 | 31 | template 32 | using asset_map = std::map>; 33 | 34 | /*! 35 | * \class assets 36 | * \brief Stores an index of assets. 37 | * \tparam ...Types Types of assets used in game code. 38 | */ 39 | class assets final : private manager { 40 | friend class slv::engine; 41 | 42 | private: 43 | assets() = default; 44 | ~assets() = default; 45 | 46 | // Engine calls this during de-init to clean up. 47 | inline static void clear_al_objects(void) { 48 | for (auto& it : _assets) { 49 | it.second.reset(); 50 | } 51 | for (auto& it : _assets) { 52 | it.second.reset(); 53 | } 54 | for (auto& it : _assets) { 55 | it.second.reset(); 56 | } 57 | for (auto& it : _assets) { 58 | it.second.reset(); 59 | } 60 | 61 | _assets.clear(); 62 | _assets.clear(); 63 | _assets.clear(); 64 | _assets.clear(); 65 | }; 66 | 67 | // Store each asset map. 68 | template 69 | inline static asset_map _assets; 70 | 71 | public: 72 | /*! 73 | * \brief Load an existing asset. 74 | * \tparam T Asset type to add. 75 | * \param label Reference label for asset. 76 | * \param obj Asset to add. 77 | * \return True if loaded. False if not. 78 | */ 79 | template 80 | inline static bool load( 81 | const std::string& label, 82 | const slv_asset obj 83 | ) { 84 | auto ret = _assets.insert(std::make_pair(label, std::move(obj))); 85 | return ret.second; 86 | }; 87 | 88 | /*! 89 | * \brief Unload an asset. 90 | * \tparam T Asset type to unload. 91 | * \param label Reference label for asset. 92 | * \return True if removed, false if not. 93 | */ 94 | template 95 | inline static bool unload( 96 | const std::string& label 97 | ) { 98 | auto it = _assets.find(label); 99 | if (it != _assets.end()) { 100 | _assets.erase(it); 101 | return true; 102 | } 103 | return false; 104 | }; 105 | 106 | /*! 107 | * \brief Get an asset by reference label. 108 | * \tparam T Asset type to get. 109 | * \param label Reference label for asset. 110 | * \return Shared pointer to asset. 111 | * \exception Asset not found. 112 | */ 113 | template 114 | inline static const slv_asset get( 115 | const std::string& label 116 | ) { 117 | try { 118 | return _assets.at(label); 119 | } catch(std::out_of_range& e) { 120 | std::string err_msg = "Asset not found: " + label; 121 | throw engine_exception(err_msg, "Assets", 4); 122 | } catch(...) { 123 | std::string err_msg = "Asset error: " + label; 124 | throw engine_exception(err_msg, "Assets", 4); 125 | } 126 | }; 127 | }; 128 | 129 | template <> inline bool manager::initialized = false; 130 | 131 | } 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /include/silvergun/mgr/audio.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * silvergun 3 | * -------- 4 | * By Matthew Evans 5 | * See LICENSE.md for copyright information. 6 | */ 7 | 8 | #if !defined(SLV_MGR_AUDIO_HPP) 9 | #define SLV_MGR_AUDIO_HPP 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include "silvergun/mgr/manager.hpp" 18 | 19 | #include "silvergun/_globals/_defines.hpp" 20 | #include "silvergun/_globals/commands.hpp" 21 | #include "silvergun/_globals/message.hpp" 22 | #include "silvergun/_globals/slv_asset.hpp" 23 | #include "silvergun/mgr/assets.hpp" 24 | #include "silvergun/config.hpp" 25 | 26 | namespace slv { 27 | class engine; 28 | } 29 | 30 | namespace slv::mgr { 31 | 32 | /*! 33 | * \class audio 34 | * \brief Handles audio playback. 35 | * 36 | * Messages get passed from the main engine loop via process_messages(). \n 37 | * Also can be controlled directly via function calls. \n 38 | * \n 39 | * The manager creates the following mixers: \n 40 | * Mixer Main - All other mixers attach to this. \n 41 | * Mixer 1 - Play music - Load a file and play in a loop. Looping can be disabled. \n 42 | * Mixer 2 - Play samples - Has set number of samples that can be loaded in. \n 43 | * Mixer 3 - Play voice - Load a file and play once. \n 44 | * Mixer 4 - Play ambiance - Load a file and play in a loop. Looping can be disabled. 45 | */ 46 | class audio final : private manager