10 #include <game_manager/game_manager.hpp>
12 #include <SDL_events.h>
16 static bool singleton_initialized =
false;
25 if (singleton_initialized) {
26 throw std::runtime_error(
"The game manager cannot be initialized more than once!");
28 singleton_initialized =
true;
32 gMessage_bus.
subscribe(LOAD_LEVEL, &msg_sub);
33 gMessage_bus.
subscribe(START_LEVEL, &msg_sub);
34 gMessage_bus.
subscribe(UNLOAD_LEVEL, &msg_sub);
35 gMessage_bus.
subscribe(RELOAD_LEVEL, &msg_sub);
36 gMessage_bus.
subscribe(KEY_PRESSED, &msg_sub);
37 gMessage_bus.
subscribe(KEY_HELD, &msg_sub);
38 gMessage_bus.
subscribe(KEY_RELEASED, &msg_sub);
39 gMessage_bus.
subscribe(MOUSE_X, &msg_sub);
40 gMessage_bus.
subscribe(MOUSE_Y, &msg_sub);
41 gMessage_bus.
subscribe(LEFT_TRIGGER, &msg_sub);
42 gMessage_bus.
subscribe(RIGHT_TRIGGER, &msg_sub);
43 gMessage_bus.
subscribe(LEFT_STICK_HORIZONTAL, &msg_sub);
44 gMessage_bus.
subscribe(LEFT_STICK_VERTICAL, &msg_sub);
45 gMessage_bus.
subscribe(RIGHT_STICK_HORIZONTAL, &msg_sub);
46 gMessage_bus.
subscribe(RIGHT_STICK_VERTICAL, &msg_sub);
47 gMessage_bus.
subscribe(VSYNC_STATE, &msg_sub);
48 gMessage_bus.
subscribe(END_GAME, &msg_sub);
49 gMessage_bus.
subscribe(MUSIC_VOLUME_LEVEL, &msg_sub);
50 gMessage_bus.
subscribe(SOUNDS_VOLUME_LEVEL, &msg_sub);
51 gMessage_bus.
subscribe(SHOW_MOUSE, &msg_sub);
52 gMessage_bus.
subscribe(EXECUTE_SCRIPT, &msg_sub);
53 gMessage_bus.
subscribe(FULLSCREEN_STATUS, &msg_sub);
54 gMessage_bus.
subscribe(AUDIO_ENABLED, &msg_sub);
55 gMessage_bus.
subscribe(VIRTUAL_SCREEN_COORDINATES, &msg_sub);
56 gMessage_bus.
subscribe(REAL_SCREEN_COORDINATES, &msg_sub);
62 gScript_backend.
initialize(&gMessage_bus,
this);
64 game_is_running_ =
true;
70 void game_manager::reset_keys() {
71 keys_pressed_data.reset();
72 keys_held_data.reset();
73 keys_released_data.reset();
79 void game_manager::handle_messages() {
81 while (temp !=
nullptr) {
82 switch (temp->msg_name) {
84 load_level(*
static_cast<std::string *
>(temp->get_data()));
87 reload_level(*
static_cast<std::string *
>(temp->get_data()));
90 start_level(*
static_cast<std::string *
>(temp->get_data()));
93 unload_level(*
static_cast<std::string *
>(temp->get_data()));
96 uint8_t key_index = temp->base_data0;
97 keys_pressed_data[key_index] =
true;
98 keys_held_data[key_index] =
false;
99 keys_released_data[key_index] =
false;
103 uint8_t key_index = temp->base_data0;
104 keys_pressed_data[key_index] =
false;
105 keys_held_data[key_index] =
true;
106 keys_released_data[key_index] =
false;
110 uint8_t key_index = temp->base_data0;
111 keys_pressed_data[key_index] =
false;
112 keys_held_data[key_index] =
false;
113 keys_released_data[key_index] =
true;
117 mouse_x =
static_cast<int32_t
>(temp->base_data0);
120 mouse_y =
static_cast<int32_t
>(temp->base_data0);
123 left_trigger =
static_cast<int16_t
>(temp->base_data0);
126 right_trigger =
static_cast<int16_t
>(temp->base_data0);
128 case LEFT_STICK_VERTICAL:
129 left_stick_vertical =
static_cast<int16_t
>(temp->base_data0);
131 case LEFT_STICK_HORIZONTAL:
132 left_stick_horizontal =
static_cast<int16_t
>(temp->base_data0);
134 case RIGHT_STICK_VERTICAL:
135 right_stick_vertical =
static_cast<int16_t
>(temp->base_data0);
137 case RIGHT_STICK_HORIZONTAL:
138 right_stick_horizontal =
static_cast<int16_t
>(temp->base_data0);
140 case MUSIC_VOLUME_LEVEL:
141 music_volume_level =
static_cast<uint8_t
>(temp->base_data0);
143 case SOUNDS_VOLUME_LEVEL:
144 sounds_volume_level =
static_cast<uint8_t
>(temp->base_data0);
147 audio_enabled =
static_cast<bool>(temp->base_data0);
150 vsync_flag =
static_cast<bool>(temp->base_data0);
153 game_is_running_ =
false;
156 SDL_ShowCursor(
static_cast<bool>(temp->base_data0));
158 case EXECUTE_SCRIPT: {
159 auto script =
static_cast<std::string *
>(temp->get_data());
163 case FULLSCREEN_STATUS:
164 fullscreen_status =
static_cast<bool>(temp->base_data0);
166 case VIRTUAL_SCREEN_COORDINATES: {
167 auto data = temp->base_data0;
168 v_width = data & 0x0000ffffU;
169 v_height = (data >> 16U) & 0x0000ffffU;
172 case REAL_SCREEN_COORDINATES: {
173 auto data = temp->base_data0;
174 w_width = data & 0x0000ffffU;
175 w_height = (data >> 16U) & 0x0000ffffU;
188 int8_t game_manager::load_level(
const std::string &level_name) {
191 for (
auto &i: levels) {
192 if (i.get_name() == level_name) {
198 auto temp =
ST::level(level_name, &gMessage_bus);
199 if (temp.load() != 0) {
201 "Level with name " + level_name +
" could not be loaded!")));
204 levels.emplace_back(temp);
208 for (
auto &level: levels) {
209 if (level.
get_name() == active_level) {
210 current_level_pointer = &level;
221 void game_manager::unload_level(
const std::string &level_name) {
222 for (uint64_t i = 0; i < levels.size(); ++i) {
223 if (levels[i].get_name() == level_name) {
225 levels.erase(levels.begin() + i);
232 for (
auto &level: levels) {
233 if (level.
get_name() == active_level) {
234 current_level_pointer = &level;
245 void game_manager::reload_level(
const std::string &level_name) {
246 for (
auto &level: levels) {
247 if (level.
get_name() == level_name) {
259 void game_manager::start_level(
const std::string &level_name) {
262 bool is_loaded =
false;
263 for (
auto &level: levels) {
264 if (level.
get_name() == level_name) {
265 current_level_pointer = &level;
272 if (load_level(level_name) == 0) {
273 for (
auto &level: levels) {
274 if (level.
get_name() == level_name) {
275 current_level_pointer = &level;
280 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"Error starting level " + level_name)));
285 gScript_backend.
close();
286 gScript_backend.
initialize(&gMessage_bus,
this);
287 active_level = level_name;
289 current_level_pointer->lights.clear();
290 current_level_pointer->entities.clear();
291 current_level_pointer->text_objects.clear();
294 current_level_pointer->camera.x = 0;
295 current_level_pointer->camera.y = 0;
296 current_level_pointer->camera.limitX2 = v_width;
297 current_level_pointer->camera.limitY2 = v_height;
299 std::string temp =
"game/levels/";
300 temp = temp + active_level;
301 temp = temp +
"/level.lua";
309 gScript_backend.
close();
310 singleton_initialized =
false;
325 return right_trigger;
332 return left_stick_horizontal;
339 return left_stick_vertical;
346 return right_stick_vertical;
353 return right_stick_horizontal;
364 if (current_level_pointer->entities[
id].velocity_x > 0) {
365 if (current_level_pointer->camera.x <
366 current_level_pointer->entities[
id].x - v_width / 4 - current_level_pointer->entities[
id].velocity_x) {
367 current_level_pointer->camera.x += current_level_pointer->entities[id].velocity_x + 5;
369 current_level_pointer->camera.x = current_level_pointer->entities[id].x - v_width / 4;
371 }
else if (current_level_pointer->entities[
id].velocity_x < 0) {
372 if (current_level_pointer->camera.x >
373 current_level_pointer->entities[
id].x - v_width / 2 - current_level_pointer->entities[
id].velocity_x) {
374 current_level_pointer->camera.x += current_level_pointer->entities[id].velocity_x - 5;
376 current_level_pointer->camera.x = current_level_pointer->entities[id].x - v_width / 2;
382 current_level_pointer->camera.y = current_level_pointer->entities[id].y - v_height;
384 uint8_t limit_x1_check = current_level_pointer->camera.x < current_level_pointer->camera.limitX1 + 1;
385 uint8_t limit_x2_check = current_level_pointer->camera.x > current_level_pointer->camera.limitX2 - 1;
386 uint8_t limit_y1_check = current_level_pointer->camera.y < current_level_pointer->camera.limitY1 + 1;
387 uint8_t limit_y2_check = current_level_pointer->camera.y > current_level_pointer->camera.limitY2 - 1;
389 current_level_pointer->camera.x =
390 limit_x1_check * (current_level_pointer->camera.limitX1 + 1) +
391 !limit_x1_check * current_level_pointer->camera.x;
392 current_level_pointer->camera.x =
393 limit_x2_check * (current_level_pointer->camera.limitX2 - 1) +
394 !limit_x2_check * current_level_pointer->camera.x;
395 current_level_pointer->camera.y =
396 limit_y1_check * (current_level_pointer->camera.limitY1 + 1) +
397 !limit_y1_check * current_level_pointer->camera.y;
398 current_level_pointer->camera.y =
399 limit_y2_check * (current_level_pointer->camera.limitY2 - 1) +
400 !limit_y2_check * current_level_pointer->camera.y;
422 void game_manager::run_level_loop() {
430 return current_level_pointer;
439 return game_is_running_;
464 for (ST::key key: current_level_pointer->actions_buttons[arg]) {
465 if (keys_pressed_data[
static_cast<uint8_t
>(key)]) {
478 for (ST::key key: current_level_pointer->actions_buttons[arg]) {
479 if (keys_held_data[
static_cast<uint8_t
>(key)]) {
492 for (ST::key key: current_level_pointer->actions_buttons[arg]) {
493 if (keys_released_data[
static_cast<uint8_t
>(key)]) {
502 void game_manager::save_state(
const std::string &filepath) {
503 std::ofstream save_file;
504 save_file.open(filepath);
506 save_file <<
"L" + current_level_pointer->
get_name();
507 save_file <<
"CX" + std::to_string(current_level_pointer->camera.x);
508 save_file <<
"CY" + std::to_string(current_level_pointer->camera.y);
510 for (uint8_t i = 0; i < PARALLAX_BG_LAYERS; i++) {
511 save_file <<
"B" + std::to_string(i) + std::to_string(current_level_pointer->background[i]);
514 save_file <<
"BCR" + std::to_string(current_level_pointer->background_color.r) +
515 "G" + std::to_string(current_level_pointer->background_color.g) +
516 "B" + std::to_string(current_level_pointer->background_color.b) +
517 "A" + std::to_string(current_level_pointer->background_color.a);
518 save_file <<
"O" + std::to_string(current_level_pointer->overlay);
519 save_file <<
"OSN" + std::to_string(current_level_pointer->overlay_sprite_num);
521 for (
const auto &entity: current_level_pointer->entities) {
522 save_file <<
"X" + std::to_string(entity.x);
523 save_file <<
"Y" + std::to_string(entity.y);
524 save_file <<
"VX" + std::to_string(entity.velocity_x);
525 save_file <<
"VY" + std::to_string(entity.velocity_y);
526 save_file <<
"A" + std::to_string(entity.animation);
527 save_file <<
"AN" + std::to_string(entity.animation_num);
528 save_file <<
"SN" + std::to_string(entity.sprite_num);
529 save_file <<
"TH" + std::to_string(entity.tex_h);
530 save_file <<
"TW" + std::to_string(entity.tex_w);
531 save_file <<
"TSX" + std::to_string(entity.tex_scale_x);
532 save_file <<
"TSY" + std::to_string(entity.tex_scale_y);
533 save_file <<
"T" + std::to_string(entity.texture);
534 save_file <<
"S" + std::to_string(entity.is_static());
535 save_file <<
"V" + std::to_string(entity.is_visible());
536 save_file <<
"P" + std::to_string(entity.is_affected_by_physics());
537 save_file <<
"A" + std::to_string(entity.is_active());
541 for (
const auto &light: current_level_pointer->lights) {
542 save_file <<
"X" + std::to_string(light.origin_x);
543 save_file <<
"Y" + std::to_string(light.origin_y);
544 save_file <<
"S" + std::to_string(light.is_static);
545 save_file <<
"B" + std::to_string(light.brightness);
546 save_file <<
"I" + std::to_string(light.intensity);
547 save_file <<
"R" + std::to_string(light.radius);
551 for (
const auto &text_object: current_level_pointer->text_objects) {
552 save_file <<
"X" + std::to_string(text_object.x);
553 save_file <<
"Y" + std::to_string(text_object.y);
554 save_file <<
"T" + text_object.text_string;
555 save_file <<
"V" + std::to_string(text_object.is_visible);
556 save_file <<
"F" + std::to_string(text_object.font);
557 save_file <<
"CR" + std::to_string(text_object.color.r) +
558 "G" + std::to_string(text_object.color.g) +
559 "B" + std::to_string(text_object.color.b) +
560 "A" + std::to_string(text_object.color.a);
This object contains all the data for a level and provides functions for loading and unloading a leve...
std::string get_name() const
bool key_released(uint16_t arg) const
uint16_t get_internal_width() const
void center_camera_on_entity(uint64_t id)
uint16_t get_window_height() const
int16_t get_left_stick_vertical() const
bool key_held(uint16_t arg) const
int16_t get_left_trigger() const
int32_t get_mouse_x() const
int16_t get_right_stick_vertical() const
int16_t get_left_stick_horizontal() const
ST::level * get_level() const
uint16_t get_window_width() const
bool game_is_running() const
uint16_t get_internal_height() const
int32_t get_mouse_y() const
bool key_pressed(uint16_t arg) const
int16_t get_right_trigger() const
game_manager(message_bus &msg_bus)
int16_t get_right_stick_horizontal() const
std::string get_active_level() const
int initialize(message_bus *msg_bus, game_manager *game_mngr)
void run_global(const std::string &arg)
int8_t run_file(const std::string &file)
int8_t run_script(const std::string &script)
The central messaging system of the engine. All subsystem make extensive use of it.
void subscribe(uint8_t msg, subscriber *sub)
void send_msg(message *msg)
A message object passed around in the message bus. Holds anything created with make_data<>().
message * get_next_message()