ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
core.cpp
Go to the documentation of this file.
2
3#include <SDL3/SDL.h>
4#include <SDL3_mixer/SDL_mixer.h>
5#include <SDL3_ttf/SDL_ttf.h>
6#include <algorithm>
7#include <iostream>
8
10#include "./asw/modules/input.h"
11#include "./asw/modules/util.h"
12
13bool asw::core::exit = false;
14
17
18 auto& mouse = asw::input::mouse;
19 auto& keyboard = asw::input::keyboard;
20 auto& controller = asw::input::controller;
21
22 SDL_Event e;
23
24 while (SDL_PollEvent(&e)) {
25 switch (e.type) {
26 case SDL_EVENT_WINDOW_RESIZED: {
28 break;
29 }
30
31 // Maintain aspect ratio
32 SDL_Point window_size;
33 SDL_GetRenderOutputSize(asw::display::renderer, &window_size.x,
34 &window_size.y);
35
36 SDL_Point render_size;
37 SDL_GetRenderLogicalPresentation(asw::display::renderer, &render_size.x,
38 &render_size.y, nullptr);
39
40 const auto x_scale = static_cast<float>(window_size.x) /
41 static_cast<float>(render_size.x);
42
43 const auto y_scale = static_cast<float>(window_size.y) /
44 static_cast<float>(render_size.y);
45
46 const auto scale = std::min(x_scale, y_scale);
47
48 SDL_SetWindowSize(asw::display::window,
49 static_cast<float>(render_size.x) * scale,
50 static_cast<float>(render_size.y) * scale);
51 break;
52 }
53
54 case SDL_EVENT_KEY_DOWN: {
55 if (!e.key.repeat) {
56 keyboard.pressed[e.key.scancode] = true;
57 keyboard.down[e.key.scancode] = true;
58 keyboard.anyPressed = true;
59 keyboard.lastPressed = e.key.scancode;
60 }
61 break;
62 }
63
64 case SDL_EVENT_KEY_UP: {
65 if (!e.key.repeat) {
66 keyboard.released[e.key.scancode] = true;
67 keyboard.down[e.key.scancode] = false;
68 }
69 break;
70 }
71
72 case SDL_EVENT_MOUSE_BUTTON_DOWN: {
73 const auto button = static_cast<int>(e.button.button);
74 mouse.pressed[button] = true;
75 mouse.down[button] = true;
76 mouse.anyPressed = true;
77 mouse.lastPressed = button;
78 break;
79 }
80
81 case SDL_EVENT_MOUSE_BUTTON_UP: {
82 auto button = static_cast<int>(e.button.button);
83 mouse.released[button] = true;
84 mouse.down[button] = false;
85 break;
86 }
87
88 case SDL_EVENT_MOUSE_MOTION: {
89 // Ensure scale is applied to mouse coordinates
90 SDL_ConvertEventToRenderCoordinates(asw::display::renderer, &e);
91 mouse.xChange = e.motion.xrel;
92 mouse.yChange = e.motion.yrel;
93 mouse.x = e.motion.x;
94 mouse.y = e.motion.y;
95 break;
96 }
97
98 case SDL_EVENT_MOUSE_WHEEL: {
99 mouse.z = e.wheel.y;
100 break;
101 }
102
103 case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
104 if (e.gaxis.which >= asw::input::MAX_CONTROLLERS) {
105 break;
106 }
107
108 auto motion = e.gaxis.value / 32768.0f;
109 auto& current = controller[e.gaxis.which];
110
111 if (motion > current.deadZone) {
112 current.axis[e.gaxis.axis] = motion;
113 } else if (motion < -current.deadZone) {
114 current.axis[e.gaxis.axis] = motion;
115 } else {
116 current.axis[e.gaxis.axis] = 0.0f;
117 }
118
119 break;
120 }
121
122 case SDL_EVENT_GAMEPAD_BUTTON_DOWN: {
123 if (e.gbutton.which >= asw::input::MAX_CONTROLLERS) {
124 break;
125 }
126
127 auto button = static_cast<int>(e.gbutton.button);
128 controller[e.gbutton.which].pressed[button] = true;
129 controller[e.gbutton.which].down[button] = true;
130 controller[e.gbutton.which].anyPressed = true;
131 controller[e.gbutton.which].lastPressed = button;
132 break;
133 }
134
135 case SDL_EVENT_GAMEPAD_BUTTON_UP: {
136 if (e.gbutton.which >= asw::input::MAX_CONTROLLERS) {
137 break;
138 }
139
140 auto button = static_cast<int>(e.gbutton.button);
141 controller[e.gbutton.which].released[button] = true;
142 controller[e.gbutton.which].down[button] = false;
143 break;
144 }
145
146 case SDL_EVENT_GAMEPAD_ADDED: {
147 if (e.gdevice.which >= asw::input::MAX_CONTROLLERS ||
148 !SDL_IsGamepad(e.gdevice.which) ||
149 SDL_OpenGamepad(e.gdevice.which) == nullptr) {
150 // TODO: Log error
151 break;
152 }
153
154 SDL_OpenGamepad(e.gdevice.which);
155
156 break;
157 }
158
159 case SDL_EVENT_GAMEPAD_REMOVED: {
160 if (e.gdevice.which >= asw::input::MAX_CONTROLLERS) {
161 break;
162 }
163
164 auto* controller = SDL_GetGamepadFromID(e.gdevice.which);
165
166 if (controller) {
167 SDL_CloseGamepad(controller);
168 }
169
170 break;
171 }
172
173 case SDL_EVENT_QUIT: {
174 exit = true;
175 break;
176 }
177
178 default:
179 break;
180 }
181 }
182}
183
184void asw::core::init(int width, int height, int scale) {
185 if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) {
186 asw::util::abortOnError("SDL_Init");
187 }
188
189 if (!TTF_Init()) {
190 asw::util::abortOnError("TTF_Init");
191 }
192
193 // Initialize SDL_mixer
194 SDL_AudioSpec spec;
195 spec.format = SDL_AUDIO_S16LE;
196 spec.freq = 44100;
197 spec.channels = 2;
198
199 if (!Mix_OpenAudio(0, &spec)) {
200 asw::util::abortOnError("Mix_OpenAudio");
201 }
202
204 SDL_CreateWindow("", width * scale, height * scale, SDL_WINDOW_RESIZABLE);
205
206 if (asw::display::window == nullptr) {
207 asw::util::abortOnError("WINDOW");
208 }
209
210 // Hints
211 SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
212
213 // Get window surface
214 asw::display::renderer = SDL_CreateRenderer(asw::display::window, nullptr);
215
216 SDL_SetRenderLogicalPresentation(asw::display::renderer, width, height,
217 SDL_LOGICAL_PRESENTATION_LETTERBOX);
218}
219
221 std::cout << "ASW Info\n";
222 std::cout << "========\n";
223
224 const char* renderer_name = "None";
226 renderer_name = SDL_GetRendererName(asw::display::renderer);
227 }
228
229 const bool is_software = false; // info.flags & SDL_SOFTWARE_RENDERER;
230 const bool is_accelerated = !is_software;
231 const bool is_target_texture = true;
232 const bool is_vsync = true; // info.flags & SDL_RENDERER_PRESENTVSYNC;
233
234 std::cout << "SDL Version: " << SDL_MAJOR_VERSION << "." << SDL_MINOR_VERSION
235 << "." << SDL_MICRO_VERSION << "\n";
236
237 std::cout << "Renderer: " << renderer_name << "\n";
238 std::cout << "Accelerated: " << is_accelerated << "\n";
239 std::cout << "Software: " << is_software << "\n";
240 std::cout << "Target Texture: " << is_target_texture << "\n";
241 std::cout << "Vsync: " << is_vsync << "\n";
242}
Core routines including main loop and initialization.
Display and window routines for the ASW library.
Input module for the ASW library.
bool exit
When set to true, exits the main loop.
Definition core.cpp:13
void print_info()
Prints information about the core module.
Definition core.cpp:220
void init(int width, int height, int scale=1)
Initializes the core module.
Definition core.cpp:184
void update()
Updates core module functionality.
Definition core.cpp:15
asw::Renderer * renderer
The renderer for the display module.
Definition display.cpp:9
asw::Window * window
The window for the display module.
Definition display.cpp:10
void reset()
Reset all input states. Called by the core.
Definition input.cpp:10
constexpr int MAX_CONTROLLERS
Maximum number of controllers supported.
Definition input.h:471
std::array< ControllerState, MAX_CONTROLLERS > controller
Global controller state.
Definition input.cpp:8
MouseState mouse
Global mouse state.
Definition input.cpp:5
KeyState keyboard
Global keyboard state.
Definition input.cpp:3
void abortOnError(const std::string &message)
Abort program and display error message.
Definition util.cpp:6
General utility functions.