5 #include "./game/level/player.h"
6 #include "./game/level/platforms.h"
7 #include "./game/level.h"
13 /* TODO(#118): Level doesn't play the Nothing and Something sounds when the goal get into view */
19 platforms_t *platforms;
23 color_t background_color;
26 level_t *create_level_from_file(const char *file_name)
30 lt_t *const lt = create_lt();
35 level_t *const level = PUSH_LT(lt, malloc(sizeof(level_t)), free);
37 throw_error(ERROR_TYPE_LIBC);
41 FILE *level_file = PUSH_LT(lt, fopen(file_name, "r"), fclose);
42 if (level_file == NULL) {
43 throw_error(ERROR_TYPE_LIBC);
48 if (fscanf(level_file, "%6s", color) == EOF) {
49 throw_error(ERROR_TYPE_LIBC);
52 level->background_color = color_from_hexstr(color);
54 level->player = PUSH_LT(lt, create_player_from_stream(level_file), destroy_player);
55 if (level->player == NULL) {
59 level->platforms = PUSH_LT(lt, create_platforms_from_stream(level_file), destroy_platforms);
60 if (level->platforms == NULL) {
64 level->goals = PUSH_LT(lt, create_goals_from_stream(level_file), destroy_goals);
65 if (level->goals == NULL) {
69 level->lava = PUSH_LT(lt, create_lava_from_stream(level_file), destroy_lava);
70 if (level->lava == NULL) {
74 level->camera = PUSH_LT(lt, create_camera(vec(0.0f, 0.0f)), destroy_camera);
75 if (level->camera == NULL) {
81 fclose(RELEASE_LT(lt, level_file));
86 void destroy_level(level_t *level)
89 RETURN_LT0(level->lt);
92 int level_render(const level_t *level, SDL_Renderer *renderer)
97 if (camera_clear_background(level->camera, renderer, level->background_color) < 0) {
101 if (player_render(level->player, renderer, level->camera) < 0) {
105 if (lava_render(level->lava, renderer, level->camera) < 0) {
109 if (platforms_render(level->platforms, renderer, level->camera) < 0) {
113 if (goals_render(level->goals, renderer, level->camera) < 0) {
117 /* TODO(#157): goals_cue is not supposed to be invoked in level_render
119 * But I simply couldn't find a better place for it.
121 goals_cue(level->goals, renderer, level->camera);
126 int level_update(level_t *level, float delta_time)
129 assert(delta_time > 0);
131 player_update(level->player, level->platforms, delta_time);
132 player_focus_camera(level->player, level->camera);
133 player_hide_goals(level->player, level->goals);
134 player_die_from_lava(level->player, level->lava);
136 goals_update(level->goals, delta_time);
137 goals_checkpoint(level->goals, level->player);
138 lava_update(level->lava, delta_time);
143 int level_event(level_t *level, const SDL_Event *event)
148 switch (event->type) {
150 switch (event->key.keysym.sym) {
152 player_jump(level->player);
157 case SDL_JOYBUTTONDOWN:
158 if (event->jbutton.button == 1) {
159 player_jump(level->player);
167 int level_input(level_t *level,
168 const Uint8 *const keyboard_state,
169 SDL_Joystick *the_stick_of_joy)
172 assert(keyboard_state);
173 (void) the_stick_of_joy;
175 if (keyboard_state[SDL_SCANCODE_A]) {
176 player_move_left(level->player);
177 } else if (keyboard_state[SDL_SCANCODE_D]) {
178 player_move_right(level->player);
179 } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) < 0) {
180 player_move_left(level->player);
181 } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) > 0) {
182 player_move_right(level->player);
184 player_stop(level->player);
190 void level_toggle_debug_mode(level_t *level)
192 camera_toggle_debug_mode(level->camera);
195 void level_toggle_pause_mode(level_t *level)
197 camera_toggle_blackwhite_mode(level->camera);
200 int level_reload_preserve_player(level_t *level, const char *file_name)
202 lt_t * const lt = create_lt();
207 /* TODO(#104): duplicate code in create_level_from_file and level_reload_preserve_player */
209 FILE * const level_file = PUSH_LT(lt, fopen(file_name, "r"), fclose);
210 if (level_file == NULL) {
211 throw_error(ERROR_TYPE_LIBC);
216 if (fscanf(level_file, "%6s", color) == EOF) {
217 throw_error(ERROR_TYPE_LIBC);
220 level->background_color = color_from_hexstr(color);
222 player_t * const skipped_player = create_player_from_stream(level_file);
223 if (skipped_player == NULL) {
226 destroy_player(skipped_player);
228 platforms_t * const platforms = create_platforms_from_stream(level_file);
229 if (platforms == NULL) {
232 level->platforms = RESET_LT(level->lt, level->platforms, platforms);
234 goals_t * const goals = create_goals_from_stream(level_file);
238 level->goals = RESET_LT(level->lt, level->goals, goals);
240 lava_t * const lava = create_lava_from_stream(level_file);
248 int level_sound(level_t *level, sound_medium_t *sound_medium)
250 if (goals_sound(level->goals, sound_medium) < 0) {