2 #include <SDL2/SDL_mixer.h>
3 #include "system/stacktrace.h"
7 #include "game/level.h"
8 #include "game/sound_samples.h"
9 #include "game/level_picker.h"
10 #include "system/log.h"
11 #include "system/lt.h"
12 #include "system/nth_alloc.h"
13 #include "ui/console.h"
14 #include "ui/edit_field.h"
17 typedef enum Game_state {
18 GAME_STATE_RUNNING = 0,
21 GAME_STATE_LEVEL_PICKER,
29 LevelPicker *level_picker;
31 char *level_file_path;
32 Sound_samples *sound_samples;
36 SDL_Renderer *renderer;
39 Game *create_game(const char *level_file_path,
40 const char *sound_sample_files[],
41 size_t sound_sample_files_count,
42 SDL_Renderer *renderer)
44 trace_assert(level_file_path);
46 Lt *const lt = create_lt();
51 Game *game = PUSH_LT(lt, nth_alloc(sizeof(Game)), free);
57 game->state = GAME_STATE_RUNNING;
59 game->level_picker = PUSH_LT(
61 create_level_picker(level_file_path),
62 destroy_level_picker);
63 if (game->level_picker == NULL) {
67 game->level = PUSH_LT(
69 create_level_from_file(level_file_path),
71 if (game->level == NULL) {
75 game->level_file_path = PUSH_LT(
77 string_duplicate(level_file_path, NULL),
79 if (game->level_file_path == NULL) {
83 game->sound_samples = PUSH_LT(
87 sound_sample_files_count),
88 destroy_sound_samples);
89 if (game->sound_samples == NULL) {
95 create_sprite_font_from_file(
96 "fonts/charmap-oldschool.bmp",
99 if (game->font == NULL) {
103 game->camera = PUSH_LT(
105 create_camera(renderer, game->font),
107 if (game->camera == NULL) {
111 game->console = PUSH_LT(
113 create_console(game->level, game->font),
115 if (game->console == NULL) {
119 game->renderer = renderer;
124 void destroy_game(Game *game)
127 RETURN_LT0(game->lt);
130 int game_render(const Game *game)
134 switch(game->state) {
135 case GAME_STATE_RUNNING:
136 case GAME_STATE_PAUSE: {
137 if (level_render(game->level, game->camera) < 0) {
142 case GAME_STATE_CONSOLE: {
143 if (level_render(game->level, game->camera) < 0) {
147 if (console_render(game->console, game->renderer) < 0) {
152 case GAME_STATE_LEVEL_PICKER: {
153 if (level_picker_render(game->level_picker, game->renderer) < 0) {
158 case GAME_STATE_QUIT: break;
164 int game_sound(Game *game)
166 return level_sound(game->level, game->sound_samples);
169 int game_update(Game *game, float delta_time)
172 trace_assert(delta_time > 0.0f);
174 switch (game->state) {
175 case GAME_STATE_RUNNING: {
176 if (level_update(game->level, delta_time) < 0) {
180 if (level_enter_camera_event(game->level, game->camera) < 0) {
186 case GAME_STATE_CONSOLE: {
187 if (level_update(game->level, delta_time) < 0) {
191 if (level_enter_camera_event(game->level, game->camera) < 0) {
195 if (console_update(game->console, delta_time) < 0) {
200 case GAME_STATE_LEVEL_PICKER: {
201 if (level_picker_update(game->level_picker, delta_time) < 0) {
206 case GAME_STATE_PAUSE:
207 case GAME_STATE_QUIT:
215 static int game_event_pause(Game *game, const SDL_Event *event)
220 switch (event->type) {
222 game->state = GAME_STATE_QUIT;
226 switch (event->key.keysym.sym) {
228 game->state = GAME_STATE_RUNNING;
229 camera_toggle_blackwhite_mode(game->camera);
230 sound_samples_toggle_pause(game->sound_samples);
233 camera_toggle_debug_mode(game->camera);
234 level_toggle_debug_mode(game->level);
240 return level_event(game->level, event);
243 static int game_event_running(Game *game, const SDL_Event *event)
248 switch (event->type) {
250 game->state = GAME_STATE_QUIT;
254 switch (event->key.keysym.sym) {
256 log_info("Reloading the level from '%s'...\n", game->level_file_path);
258 game->level = RESET_LT(
261 create_level_from_file(
262 game->level_file_path));
264 if (game->level == NULL) {
265 log_fail("Could not reload level %s\n", game->level_file_path);
266 game->state = GAME_STATE_QUIT;
270 camera_disable_debug_mode(game->camera);
275 log_info("Reloading the level's platforms from '%s'...\n", game->level_file_path);
276 if (level_reload_preserve_player(game->level, game->level_file_path) < 0) {
277 log_fail("Could not reload level %s\n", game->level_file_path);
278 game->state = GAME_STATE_QUIT;
284 game->state = GAME_STATE_PAUSE;
285 camera_toggle_blackwhite_mode(game->camera);
286 sound_samples_toggle_pause(game->sound_samples);
290 camera_toggle_debug_mode(game->camera);
291 level_toggle_debug_mode(game->level);
296 switch (event->key.keysym.sym) {
299 SDL_StartTextInput();
300 game->state = GAME_STATE_CONSOLE;
301 console_slide_down(game->console);
308 return level_event(game->level, event);
311 static int game_event_console(Game *game, const SDL_Event *event)
313 switch (event->type) {
315 game->state = GAME_STATE_QUIT;
319 switch (event->key.keysym.sym) {
322 game->state = GAME_STATE_RUNNING;
331 return console_handle_event(game->console, event);
334 static int game_event_level_picker(Game *game, const SDL_Event *event)
339 switch (event->type) {
341 game->state = GAME_STATE_QUIT;
345 return level_picker_event(game->level_picker, event);
349 int game_event(Game *game, const SDL_Event *event)
354 switch (game->state) {
355 case GAME_STATE_RUNNING:
356 return game_event_running(game, event);
358 case GAME_STATE_PAUSE:
359 return game_event_pause(game, event);
361 case GAME_STATE_CONSOLE:
362 return game_event_console(game, event);
364 case GAME_STATE_LEVEL_PICKER:
365 return game_event_level_picker(game, event);
374 int game_input(Game *game,
375 const Uint8 *const keyboard_state,
376 SDL_Joystick *the_stick_of_joy)
379 trace_assert(keyboard_state);
381 if (game->state == GAME_STATE_QUIT ||
382 game->state == GAME_STATE_PAUSE ||
383 game->state == GAME_STATE_CONSOLE) {
387 return level_input(game->level, keyboard_state, the_stick_of_joy);
390 int game_over_check(const Game *game)
392 return game->state == GAME_STATE_QUIT;