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: {
27 // Maintain aspect ratio
28 SDL_Point window_size;
29 SDL_GetRenderOutputSize(asw::display::renderer, &window_size.x,
30 &window_size.y);
31
32 SDL_Point render_size;
33 SDL_GetRenderLogicalPresentation(asw::display::renderer, &render_size.x,
34 &render_size.y, nullptr);
35
36 const auto x_scale = static_cast<float>(window_size.x) /
37 static_cast<float>(render_size.x);
38
39 const auto y_scale = static_cast<float>(window_size.y) /
40 static_cast<float>(render_size.y);
41
42 const auto scale = std::min(x_scale, y_scale);
43
44 SDL_SetWindowSize(asw::display::window,
45 static_cast<float>(render_size.x) * scale,
46 static_cast<float>(render_size.y) * scale);
47 break;
48 }
49
50 case SDL_EVENT_KEY_DOWN: {
51 if (!e.key.repeat) {
52 keyboard.pressed[e.key.scancode] = true;
53 keyboard.down[e.key.scancode] = true;
54 keyboard.anyPressed = true;
55 keyboard.lastPressed = e.key.scancode;
56 }
57 break;
58 }
59
60 case SDL_EVENT_KEY_UP: {
61 if (!e.key.repeat) {
62 keyboard.released[e.key.scancode] = true;
63 keyboard.down[e.key.scancode] = false;
64 }
65 break;
66 }
67
68 case SDL_EVENT_MOUSE_BUTTON_DOWN: {
69 const auto button = static_cast<int>(e.button.button);
70 mouse.pressed[button] = true;
71 mouse.down[button] = true;
72 mouse.anyPressed = true;
73 mouse.lastPressed = button;
74 break;
75 }
76
77 case SDL_EVENT_MOUSE_BUTTON_UP: {
78 auto button = static_cast<int>(e.button.button);
79 mouse.released[button] = true;
80 mouse.down[button] = false;
81 break;
82 }
83
84 case SDL_EVENT_MOUSE_MOTION: {
85 // Ensure scale is applied to mouse coordinates
86 SDL_ConvertEventToRenderCoordinates(asw::display::renderer, &e);
87 mouse.xChange = e.motion.xrel;
88 mouse.yChange = e.motion.yrel;
89 mouse.x = e.motion.x;
90 mouse.y = e.motion.y;
91 break;
92 }
93
94 case SDL_EVENT_MOUSE_WHEEL: {
95 mouse.z = e.wheel.y;
96 break;
97 }
98
99 case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
100 if (e.gaxis.which >= asw::input::MAX_CONTROLLERS) {
101 break;
102 }
103
104 auto motion = e.gaxis.value / 32768.0f;
105 auto& current = controller[e.gaxis.which];
106
107 if (motion > current.deadZone) {
108 current.axis[e.gaxis.axis] = motion;
109 } else if (motion < -current.deadZone) {
110 current.axis[e.gaxis.axis] = motion;
111 } else {
112 current.axis[e.gaxis.axis] = 0.0f;
113 }
114
115 break;
116 }
117
118 case SDL_EVENT_GAMEPAD_BUTTON_DOWN: {
119 if (e.gbutton.which >= asw::input::MAX_CONTROLLERS) {
120 break;
121 }
122
123 auto button = static_cast<int>(e.gbutton.button);
124 controller[e.gbutton.which].pressed[button] = true;
125 controller[e.gbutton.which].down[button] = true;
126 controller[e.gbutton.which].anyPressed = true;
127 controller[e.gbutton.which].lastPressed = button;
128 break;
129 }
130
131 case SDL_EVENT_GAMEPAD_BUTTON_UP: {
132 if (e.gbutton.which >= asw::input::MAX_CONTROLLERS) {
133 break;
134 }
135
136 auto button = static_cast<int>(e.gbutton.button);
137 controller[e.gbutton.which].released[button] = true;
138 controller[e.gbutton.which].down[button] = false;
139 break;
140 }
141
142 case SDL_EVENT_GAMEPAD_ADDED: {
143 if (e.gdevice.which >= asw::input::MAX_CONTROLLERS ||
144 !SDL_IsGamepad(e.gdevice.which) ||
145 SDL_OpenGamepad(e.gdevice.which) == nullptr) {
146 // TODO: Log error
147 break;
148 }
149
150 SDL_OpenGamepad(e.gdevice.which);
151
152 break;
153 }
154
155 case SDL_EVENT_GAMEPAD_REMOVED: {
156 if (e.gdevice.which >= asw::input::MAX_CONTROLLERS) {
157 break;
158 }
159
160 auto* controller = SDL_GetGamepadFromID(e.gdevice.which);
161
162 if (controller) {
163 SDL_CloseGamepad(controller);
164 }
165
166 break;
167 }
168
169 case SDL_EVENT_QUIT: {
170 exit = true;
171 break;
172 }
173
174 default:
175 break;
176 }
177 }
178}
179
180void asw::core::init(int width, int height, int scale) {
181 if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) {
182 asw::util::abortOnError("SDL_Init");
183 }
184
185 if (!TTF_Init()) {
186 asw::util::abortOnError("TTF_Init");
187 }
188
189 // Initialize SDL_mixer
190 SDL_AudioSpec spec;
191 spec.format = SDL_AUDIO_S16LE;
192 spec.freq = 44100;
193 spec.channels = 2;
194
195 if (!Mix_OpenAudio(0, &spec)) {
196 asw::util::abortOnError("Mix_OpenAudio");
197 }
198
200 SDL_CreateWindow("", width * scale, height * scale, SDL_WINDOW_RESIZABLE);
201
202 if (asw::display::window == nullptr) {
203 asw::util::abortOnError("WINDOW");
204 }
205
206 // Hints
207 SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
208
209 // Get window surface
210 asw::display::renderer = SDL_CreateRenderer(asw::display::window, nullptr);
211
212 SDL_SetRenderLogicalPresentation(asw::display::renderer, width, height,
213 SDL_LOGICAL_PRESENTATION_LETTERBOX);
214}
215
217 std::cout << "ASW Info\n";
218 std::cout << "========\n";
219
220 const auto* const renderer_name = SDL_GetRendererName(asw::display::renderer);
221
222 const bool is_software = false; // info.flags & SDL_SOFTWARE_RENDERER;
223 const bool is_accelerated = !is_software;
224 const bool is_target_texture = true;
225 const bool is_vsync = true; // info.flags & SDL_RENDERER_PRESENTVSYNC;
226
227 std::cout << "SDL Version: " << SDL_MAJOR_VERSION << "." << SDL_MINOR_VERSION
228 << "." << SDL_MICRO_VERSION << "\n";
229
230 std::cout << "Renderer: " << renderer_name << "\n";
231 std::cout << "Accelerated: " << is_accelerated << "\n";
232 std::cout << "Software: " << is_software << "\n";
233 std::cout << "Target Texture: " << is_target_texture << "\n";
234 std::cout << "Vsync: " << is_vsync << "\n";
235}
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:216
void init(int width, int height, int scale=1)
Initializes the core module.
Definition core.cpp:180
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.