Wizard Engine
2D cross-platform game engine built around SDL2
 
Loading...
Searching...
No Matches
engine.cpp
1/*
2 Wizard Engine
3 Copyright (C) 2023-2024 Zana Domán
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
23#define __WIZARD_ENGINE_INTERNAL__
24
36
37std::vector<SDL_Event> wze::engine::_events = {};
38
39void wze::engine::play_intro() {
40 // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
41 static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8);
42 constexpr size_t logo_hash =
43 sizeof(size_t) == 4 ? 291788640 : 14466144734576808089U;
44 constexpr float scale = .6;
45 constexpr float speed = .1;
46
47 std::shared_ptr<image> logo;
48 float size;
49 sprite intro;
50 float opacity;
51
52 logo = assets::load_image("./wizard_engine/logo.png");
53 if (assets::hash_image(logo) != logo_hash) {
54 throw exception("Invalid ./wizard_engine/logo.png");
55 }
56
57 size = (float)std::min(window::width(), window::height()) * scale;
58 intro = sprite(0, 0, 0, 0, size, size, false, assets::create_texture(logo));
59
60 opacity = 0;
61 while (opacity <= std::numeric_limits<uint8_t>::max()) {
62 intro.set_color_a((uint8_t)opacity);
63 if (!update()) {
64 return;
65 }
66 opacity += speed * timer::delta_time();
67 }
68
69 opacity = std::numeric_limits<uint8_t>::max();
70 while (0 <= opacity) {
71 intro.set_color_a((uint8_t)opacity);
72 if (!update()) {
73 return;
74 }
75 opacity -= speed * timer::delta_time();
76 }
77}
78
79std::vector<SDL_Event> const& wze::engine::events() {
80 return _events;
81}
82
83void wze::engine::initialize(std::string const& title, uint16_t width,
84 uint16_t height) {
85 constexpr uint16_t MIX_DEFAULT_CHUNKSIZE = 4096;
86
87 std::set_terminate([]() -> void {
88 std::function<void(char const*)> log;
89 std::exception_ptr exception_ptr;
90
91 log = [](char const* message) -> void {
92 engine::log(message, LOG_LEVEL_CRITICAL);
93 if ((bool)SDL_ShowSimpleMessageBox(
94 SDL_MESSAGEBOX_ERROR,
95 (bool)window::base() ? SDL_GetWindowTitle(window::base())
96 : "Wizard Engine",
97 message, nullptr)) {
98 engine::log(SDL_GetError(), LOG_LEVEL_CRITICAL);
99 }
100 };
101
102 exception_ptr = std::current_exception();
103 if (exception_ptr) {
104 try {
105 std::rethrow_exception(exception_ptr);
106 } catch (std::exception const& exception) {
107 log(exception.what());
108 } catch (...) {
109 log("Unknown exception");
110 }
111 } else {
112 log("Unknown error");
113 }
114
115 abort();
116 });
117
118#ifdef __ANDROID__
119 if (!(bool)SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft")) {
120 throw exception(SDL_GetError());
121 }
122#endif /* __ANDROID__ */
123 if ((bool)SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO |
124 SDL_INIT_EVENTS | SDL_INIT_JOYSTICK |
125 SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR)) {
126 throw exception(SDL_GetError());
127 }
128#ifndef __EMSCRIPTEN__
129 if (IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG) !=
130 (IMG_INIT_JPG | IMG_INIT_PNG)) {
131 throw exception(IMG_GetError());
132 }
133#endif /* __EMSCRIPTEN__ */
134 if ((Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) ||
135 (bool)Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
136 MIX_DEFAULT_CHANNELS, MIX_DEFAULT_CHUNKSIZE)) {
137 throw exception(Mix_GetError());
138 }
139 if ((bool)TTF_Init()) {
140 throw exception(TTF_GetError());
141 }
142 if ((bool)SDLNet_Init()) {
143 throw exception(SDLNet_GetError());
144 }
145
146 _events = {};
147 window::initialize(title, width, height);
148 camera::initialize();
149 renderer::initialize();
150 input::initialize();
151 play_intro();
152}
153
154bool wze::engine::update() {
155 SDL_Event event;
156
157 renderer::update();
158 audio::update();
159 timer::update();
160
161 _events.clear();
162 while ((bool)SDL_PollEvent(&event)) {
163 if (event.type == SDL_QUIT) {
164 return false;
165 }
166 _events.push_back(event);
167 }
168
169 input::update();
170
171 return true;
172}
173
174void wze::engine::log(char const* message, log_level log_level) {
175 // NOLINTNEXTLINE(hicpp-vararg,cppcoreguidelines-pro-type-vararg)
176 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, (SDL_LogPriority)log_level,
177 "%s", message);
178}
179
180void wze::engine::log(std::string const& message, log_level log_level) {
181 log(message.c_str(), log_level);
182}
Image file in host memory.
Subsystem to handle global audio.
Subsystem to handle transformations and spatial projections.
static float delta_time()
Gets the current delta time in milliseconds.
Definition timer.cpp:41
Master singleton of the Wizard Engine.
Generic exception.
Touchscreen finger data.
Math modul.
log_level
Log levels.
Definition enums.hpp:337
Subsystem to handle graphics.
Renderable animatable component.
Timer modul.
Subsystem to handle game window.