X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame%2Flevel.c;h=eecb1b34e67adbe455bf09ef2549ebdf2d37ecd2;hb=da902a6cec105931fa5402b12471d5cc9f9b2474;hp=4bb12d19cfd73928556e422bbfa64d40efb28965;hpb=c80e8da88a131d18c3390a5f60022a364b692158;p=nothing.git diff --git a/src/game/level.c b/src/game/level.c index 4bb12d19..eecb1b34 100644 --- a/src/game/level.c +++ b/src/game/level.c @@ -1,172 +1,232 @@ #include #include +#include "color.h" +#include "game/camera.h" #include "game/level.h" #include "game/level/background.h" -#include "game/level/camera.h" +#include "game/level/boxes.h" #include "game/level/goals.h" +#include "game/level/labels.h" #include "game/level/lava.h" +#include "game/level/physical_world.h" #include "game/level/platforms.h" #include "game/level/player.h" -#include "system/error.h" +#include "game/level/regions.h" +#include "system/line_stream.h" #include "system/lt.h" +#include "system/lt/lt_adapters.h" +#include "system/nth_alloc.h" -/* TODO(#118): Level doesn't play the Nothing and Something sounds when the goal get into view */ +#define LEVEL_LINE_MAX_LENGTH 512 -struct level_t +struct Level { - lt_t *lt; - player_t *player; - platforms_t *platforms; - camera_t *camera; - goals_t *goals; - lava_t *lava; - color_t background_color; - platforms_t *back_platforms; - background_t *background; + Lt *lt; + + Physical_world *physical_world; + Player *player; + Platforms *platforms; + Goals *goals; + Lava *lava; + Platforms *back_platforms; + Background *background; + Boxes *boxes; + Labels *labels; + Regions *regions; }; -level_t *create_level_from_file(const char *file_name) +Level *create_level_from_file(const char *file_name) { assert(file_name); - lt_t *const lt = create_lt(); + Lt *const lt = create_lt(); if (lt == NULL) { return NULL; } - level_t *const level = PUSH_LT(lt, malloc(sizeof(level_t)), free); + Level *const level = PUSH_LT(lt, nth_alloc(sizeof(Level)), free); if (level == NULL) { - throw_error(ERROR_TYPE_LIBC); RETURN_LT(lt, NULL); } - FILE *level_file = PUSH_LT(lt, fopen(file_name, "r"), fclose); - if (level_file == NULL) { - throw_error(ERROR_TYPE_LIBC); + LineStream *level_stream = PUSH_LT( + lt, + create_line_stream( + file_name, + "r", + LEVEL_LINE_MAX_LENGTH), + destroy_line_stream); + if (level_stream == NULL) { RETURN_LT(lt, NULL); } - - char color[7]; - if (fscanf(level_file, "%6s", color) == EOF) { - throw_error(ERROR_TYPE_LIBC); + level->background = PUSH_LT( + lt, + create_background_from_line_stream(level_stream), + destroy_background); + if (level->background == NULL) { RETURN_LT(lt, NULL); } - level->background_color = color_from_hexstr(color); - level->player = PUSH_LT(lt, create_player_from_stream(level_file), destroy_player); + level->player = PUSH_LT( + lt, + create_player_from_line_stream(level_stream), + destroy_player); if (level->player == NULL) { RETURN_LT(lt, NULL); } - level->platforms = PUSH_LT(lt, create_platforms_from_stream(level_file), destroy_platforms); + level->platforms = PUSH_LT( + lt, + create_platforms_from_line_stream(level_stream), + destroy_platforms); if (level->platforms == NULL) { RETURN_LT(lt, NULL); } - level->goals = PUSH_LT(lt, create_goals_from_stream(level_file), destroy_goals); + level->goals = PUSH_LT( + lt, + create_goals_from_line_stream(level_stream), + destroy_goals); if (level->goals == NULL) { RETURN_LT(lt, NULL); } - level->lava = PUSH_LT(lt, create_lava_from_stream(level_file), destroy_lava); + level->lava = PUSH_LT( + lt, + create_lava_from_line_stream(level_stream), + destroy_lava); if (level->lava == NULL) { RETURN_LT(lt, NULL); } - level->back_platforms = PUSH_LT(lt, create_platforms_from_stream(level_file), destroy_platforms); + level->back_platforms = PUSH_LT( + lt, + create_platforms_from_line_stream(level_stream), + destroy_platforms); if (level->back_platforms == NULL) { RETURN_LT(lt, NULL); } - level->camera = PUSH_LT(lt, create_camera(vec(0.0f, 0.0f)), destroy_camera); - if (level->camera == NULL) { + level->boxes = PUSH_LT( + lt, + create_boxes_from_line_stream(level_stream), + destroy_boxes); + if (level->boxes == NULL) { RETURN_LT(lt, NULL); } - level->background = PUSH_LT(lt, create_background(level->background_color), destroy_background); - if (level->background == NULL) { + level->labels = PUSH_LT( + lt, + create_labels_from_line_stream(level_stream), + destroy_labels); + if (level->labels == NULL) { + RETURN_LT(lt, NULL); + } + + level->regions = PUSH_LT( + lt, + create_regions_from_line_stream(level_stream, level), + destroy_regions); + if (level->regions == NULL) { + RETURN_LT(lt, NULL); + } + + level->physical_world = PUSH_LT(lt, create_physical_world(), destroy_physical_world); + if (level->physical_world == NULL) { RETURN_LT(lt, NULL); } + if (physical_world_add_solid( + level->physical_world, + player_as_solid(level->player)) < 0) { RETURN_LT(lt, NULL); } + if (boxes_add_to_physical_world( + level->boxes, + level->physical_world) < 0) { RETURN_LT(lt, NULL); } level->lt = lt; - fclose(RELEASE_LT(lt, level_file)); + destroy_line_stream(RELEASE_LT(lt, level_stream)); return level; } -void destroy_level(level_t *level) +void destroy_level(Level *level) { assert(level); RETURN_LT0(level->lt); } -int level_render(const level_t *level, SDL_Renderer *renderer) +int level_render(const Level *level, Camera *camera) { assert(level); - assert(renderer); - if (camera_clear_background(level->camera, renderer, level->background_color) < 0) { + player_focus_camera(level->player, camera); + + if (background_render(level->background, camera) < 0) { return -1; } - const rect_t view_port = camera_view_port(level->camera, renderer); - - background_move_to(level->background, vec(view_port.x + view_port.w * 0.5f, - view_port.y + view_port.h * 0.5f)); + if (platforms_render(level->back_platforms, camera) < 0) { + return -1; + } - if (background_render(level->background, renderer, level->camera) < 0) { + if (player_render(level->player, camera) < 0) { return -1; } - if (platforms_render(level->back_platforms, renderer, level->camera) < 0) { + if (boxes_render(level->boxes, camera) < 0) { return -1; } - if (player_render(level->player, renderer, level->camera) < 0) { + if (lava_render(level->lava, camera) < 0) { return -1; } - if (lava_render(level->lava, renderer, level->camera) < 0) { + if (platforms_render(level->platforms, camera) < 0) { return -1; } - if (platforms_render(level->platforms, renderer, level->camera) < 0) { + if (goals_render(level->goals, camera) < 0) { return -1; } - if (goals_render(level->goals, renderer, level->camera) < 0) { + if (labels_render(level->labels, camera) < 0) { return -1; } - /* TODO(#157): goals_cue is not supposed to be invoked in level_render - * - * But I simply couldn't find a better place for it. - */ - goals_cue(level->goals, renderer, level->camera); + if (regions_render(level->regions, camera) < 0) { + return -1; + } return 0; } -int level_update(level_t *level, float delta_time) +int level_update(Level *level, float delta_time) { assert(level); assert(delta_time > 0); - player_update(level->player, level->platforms, delta_time); - player_focus_camera(level->player, level->camera); + physical_world_apply_gravity(level->physical_world); + boxes_float_in_lava(level->boxes, level->lava); + + boxes_update(level->boxes, delta_time); + player_update(level->player, delta_time); + + physical_world_collide_solids(level->physical_world, level->platforms); + player_hide_goals(level->player, level->goals); player_die_from_lava(level->player, level->lava); + regions_player_enter(level->regions, level->player); + regions_player_leave(level->regions, level->player); goals_update(level->goals, delta_time); - goals_checkpoint(level->goals, level->player); lava_update(level->lava, delta_time); + labels_update(level->labels, delta_time); return 0; } -int level_event(level_t *level, const SDL_Event *event) +int level_event(Level *level, const SDL_Event *event) { assert(level); assert(event); @@ -190,7 +250,7 @@ int level_event(level_t *level, const SDL_Event *event) return 0; } -int level_input(level_t *level, +int level_input(Level *level, const Uint8 *const keyboard_state, SDL_Joystick *the_stick_of_joy) { @@ -213,80 +273,158 @@ int level_input(level_t *level, return 0; } -void level_toggle_debug_mode(level_t *level) -{ - camera_toggle_debug_mode(level->camera); -} - -void level_toggle_pause_mode(level_t *level) +int level_reload_preserve_player(Level *level, const char *file_name) { - camera_toggle_blackwhite_mode(level->camera); -} - -int level_reload_preserve_player(level_t *level, const char *file_name) -{ - lt_t * const lt = create_lt(); + Lt * const lt = create_lt(); if (lt == NULL) { return -1; } /* TODO(#104): duplicate code in create_level_from_file and level_reload_preserve_player */ - FILE * const level_file = PUSH_LT(lt, fopen(file_name, "r"), fclose); - if (level_file == NULL) { - throw_error(ERROR_TYPE_LIBC); + LineStream * const level_stream = PUSH_LT( + lt, + create_line_stream( + file_name, + "r", + LEVEL_LINE_MAX_LENGTH), + destroy_line_stream); + if (level_stream == NULL) { RETURN_LT(lt, -1); } - char color[7]; - if (fscanf(level_file, "%6s", color) == EOF) { - throw_error(ERROR_TYPE_LIBC); + Background * const background = create_background_from_line_stream(level_stream); + if (background == NULL) { RETURN_LT(lt, -1); } - level->background_color = color_from_hexstr(color); + level->background = RESET_LT(level->lt, level->background, background); - player_t * const skipped_player = create_player_from_stream(level_file); + Player * const skipped_player = create_player_from_line_stream(level_stream); if (skipped_player == NULL) { RETURN_LT(lt, -1); } destroy_player(skipped_player); - platforms_t * const platforms = create_platforms_from_stream(level_file); + Platforms * const platforms = create_platforms_from_line_stream(level_stream); if (platforms == NULL) { RETURN_LT(lt, -1); } level->platforms = RESET_LT(level->lt, level->platforms, platforms); - goals_t * const goals = create_goals_from_stream(level_file); + Goals * const goals = create_goals_from_line_stream(level_stream); if (goals == NULL) { RETURN_LT(lt, -1); } level->goals = RESET_LT(level->lt, level->goals, goals); - lava_t * const lava = create_lava_from_stream(level_file); + Lava * const lava = create_lava_from_line_stream(level_stream); if (lava == NULL) { RETURN_LT(lt, -1); } level->lava = RESET_LT(level->lt, level->lava, lava); - platforms_t * const back_platforms = create_platforms_from_stream(level_file); + Platforms * const back_platforms = create_platforms_from_line_stream(level_stream); if (back_platforms == NULL) { RETURN_LT(lt, -1); } level->back_platforms = RESET_LT(level->lt, level->back_platforms, back_platforms); + Boxes * const boxes = create_boxes_from_line_stream(level_stream); + if (boxes == NULL) { + RETURN_LT(lt, -1); + } + level->boxes = RESET_LT(level->lt, level->boxes, boxes); + + Labels * const labels = create_labels_from_line_stream(level_stream); + if (labels == NULL) { + RETURN_LT(lt, -1); + } + level->labels = RESET_LT(level->lt, level->labels, labels); + + Regions * const regions = create_regions_from_line_stream(level_stream, level); + if (regions == NULL) { + RETURN_LT(lt, -1); + } + level->regions = RESET_LT(level->lt, level->regions, regions); + + physical_world_clean(level->physical_world); + if (physical_world_add_solid( + level->physical_world, + player_as_solid(level->player)) < 0) { RETURN_LT(lt, -1); } + if (boxes_add_to_physical_world( + level->boxes, + level->physical_world) < 0) { RETURN_LT(lt, -1); } + RETURN_LT(lt, 0); } -int level_sound(level_t *level, sound_medium_t *sound_medium) +int level_sound(Level *level, Sound_samples *sound_samples) { - if (goals_sound(level->goals, sound_medium) < 0) { + if (goals_sound(level->goals, sound_samples) < 0) { return -1; } - if (player_sound(level->player, sound_medium) < 0) { + if (player_sound(level->player, sound_samples) < 0) { return -1; } return 0; } + +void level_toggle_debug_mode(Level *level) +{ + background_toggle_debug_mode(level->background); +} + +int level_enter_camera_event(Level *level, + const Camera *camera) +{ + goals_cue(level->goals, camera); + goals_checkpoint(level->goals, level->player); + labels_enter_camera_event(level->labels, camera); + return 0; +} + +Rigid_rect *level_rigid_rect(Level *level, + const char *rigid_rect_id) +{ + assert(level); + assert(rigid_rect_id); + + Rigid_rect *rigid_rect = player_rigid_rect(level->player, + rigid_rect_id); + if (rigid_rect != NULL) { + return rigid_rect; + } + + rigid_rect = boxes_rigid_rect(level->boxes, rigid_rect_id); + if (rigid_rect != NULL) { + return rigid_rect; + } + + return NULL; +} + +void level_hide_goal(Level *level, const char *goal_id) +{ + goals_hide(level->goals, goal_id); +} + +void level_show_goal(Level *level, const char *goal_id) +{ + goals_show(level->goals, goal_id); +} + +long int level_player_jump_count(Level *level) +{ + assert(level); + return player_jump_count(level->player); +} + +void level_hide_label(Level *level, const char *label_id) +{ + assert(level); + assert(label_id); + + /* TODO: level_hide_label is not implemented */ +}