diff --git a/engine/gui.c b/engine/gui.c index 9f24002..8a534b2 100644 --- a/engine/gui.c +++ b/engine/gui.c @@ -684,15 +684,18 @@ bool vert_scrollarea_n_items(VertScrollArea_t* scroll_area, unsigned int n_items return true; } -void vert_scrollarea_insert_item(VertScrollArea_t* scroll_area, char* str, unsigned int item_idx) +void vert_scrollarea_insert_item(VertScrollArea_t* scroll_area, char* str, unsigned int item_idx, Color colour) { if (item_idx >= scroll_area->max_items) return; + float y_pos = scroll_area->item_padding + (scroll_area->item_height + scroll_area->item_padding) * item_idx; + + //DrawRectangle(0, y_pos, scroll_area->display_area.width, scroll_area->item_height, BLANK); DrawTextEx( scroll_area->comp.font, str, - (Vector2){0, scroll_area->item_padding + (scroll_area->item_height + scroll_area->item_padding) * item_idx} - , scroll_area->item_height, 0, BLACK); + (Vector2){0, y_pos} + , scroll_area->item_height, 0, colour); } unsigned int vert_scrollarea_set_pos(VertScrollArea_t* scroll_area, Vector2 pos) diff --git a/engine/gui.h b/engine/gui.h index d46d2af..7ea6cab 100644 --- a/engine/gui.h +++ b/engine/gui.h @@ -35,7 +35,7 @@ void init_UI(void); void vert_scrollarea_init(VertScrollArea_t* scroll_area, Rectangle display_area, Vector2 canvas_dims); void vert_scrollarea_set_item_dims(VertScrollArea_t* scroll_area, unsigned int item_height, unsigned int item_padding); bool vert_scrollarea_n_items(VertScrollArea_t* scroll_area, unsigned int n_items); -void vert_scrollarea_insert_item(VertScrollArea_t* scroll_area, char* str, unsigned int item_idx); +void vert_scrollarea_insert_item(VertScrollArea_t* scroll_area, char* str, unsigned int item_idx, Color colour); unsigned int vert_scrollarea_set_pos(VertScrollArea_t* scroll_area, Vector2 pos); void vert_scrollarea_refocus(VertScrollArea_t* scroll_area); void vert_scrollarea_render(VertScrollArea_t* scroll_area); diff --git a/scenes/CMakeLists.txt b/scenes/CMakeLists.txt index d8c7bdd..50b0fa8 100644 --- a/scenes/CMakeLists.txt +++ b/scenes/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(lib_scenes STATIC scene_systems.c camera_systems.c engine_impl.c + save_data.c ) target_include_directories(lib_scenes PUBLIC diff --git a/scenes/constants.h b/scenes/constants.h index 8e9f463..e03aaa4 100644 --- a/scenes/constants.h +++ b/scenes/constants.h @@ -58,4 +58,5 @@ static const uint8_t CONNECTIVITY_TILE_MAPPING[16] = { }; #define ANIM_FRAME_RATE (1.0f/24) +#define SAVE_FILE_NAME "save.dat" #endif // __CONSTANTS_H diff --git a/scenes/game_scene.c b/scenes/game_scene.c index 0bb4e67..ee1035a 100644 --- a/scenes/game_scene.c +++ b/scenes/game_scene.c @@ -2,6 +2,7 @@ #include "keymaps.h" #include "scene_impl.h" +#include "save_data.h" #include "game_systems.h" #include "water_flow.h" #include "constants.h" @@ -530,6 +531,7 @@ static void at_level_start(Scene_t* scene) static void at_level_complete(Scene_t* scene) { LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data); + set_level_completed(data->current_level, true); data->sm.fractional += scene->delta_time; if (data->sm.fractional > 1.0f) { diff --git a/scenes/level_select_scene.c b/scenes/level_select_scene.c index b3cb11a..09f8108 100644 --- a/scenes/level_select_scene.c +++ b/scenes/level_select_scene.c @@ -3,6 +3,7 @@ #include "gui.h" #include "raymath.h" #include +#include "save_data.h" #define LEVEL_PREVIEW_SIZE 430 static void level_select_render_func(Scene_t* scene) @@ -257,15 +258,55 @@ static void level_select_action_remap_func(Scene_t* scene) sc_map_put_64(&scene->action_map, KEY_ENTER, ACTION_CONFIRM); } +static void render_scroll_canvas(LevelSelectSceneData_t* data) +{ + // Hardcoded buffer size + char buf[48]; + ScrollAreaRenderBegin(&data->scroll_area); + ClearBackground(BLANK); + if (data->level_pack != NULL) + { + vert_scrollarea_n_items(&data->scroll_area, data->level_pack->n_levels); + for (unsigned int i = 0; i < data->level_pack->n_levels; ++i) + { + vert_scrollarea_insert_item(&data->scroll_area, data->level_pack->levels[i].level_name, i, (is_level_completed(i)) ? GREEN : BLACK); + } + for (unsigned int i = data->level_pack->n_levels; i < data->scroll_area.max_items; ++i) + { + vert_scrollarea_insert_item(&data->scroll_area, "---", i, BLACK); + } + } + else + { + for (unsigned int i = 0; i < data->scroll_area.max_items; ++i) + { + sprintf(buf, "Level %u", i); + vert_scrollarea_insert_item(&data->scroll_area, buf, i, BLACK); + } + } + ScrollAreaRenderEnd(); +} + +static void reset_level_selection_scene(Scene_t* scene) +{ + LevelSelectSceneData_t* data = &(CONTAINER_OF(scene, LevelSelectScene_t, scene)->data); + // Re-draw the canvas, in case of completion update + render_scroll_canvas(data); + + data->scroll_area.curr_selection = 0; + data->update_preview = true; +} + #define FONT_SIZE 22 #define TEXT_PADDING 3 #define SCROLL_TOTAL_HEIGHT 800 void init_level_select_scene(LevelSelectScene_t* scene) { init_scene(&scene->scene, &level_select_do_action, 0); + scene->scene.reset_function = &reset_level_selection_scene; scene->data.preview = LoadRenderTexture(LEVEL_PREVIEW_SIZE, LEVEL_PREVIEW_SIZE); scene->data.update_preview = true; - scene->scene.action_remap_function = level_select_action_remap_func; + scene->scene.action_remap_function = &level_select_action_remap_func; add_scene_layer( &scene->scene, scene->scene.engine->intended_window_size.x, scene->scene.engine->intended_window_size.y, @@ -283,30 +324,8 @@ void init_level_select_scene(LevelSelectScene_t* scene) if (menu_font != NULL) { scene->data.scroll_area.comp.font = *menu_font; } - char buf[32]; - ScrollAreaRenderBegin(&scene->data.scroll_area); - ClearBackground(BLANK); - if (scene->data.level_pack != NULL) - { - vert_scrollarea_n_items(&scene->data.scroll_area, scene->data.level_pack->n_levels); - for (unsigned int i = 0; i < scene->data.level_pack->n_levels; ++i) - { - vert_scrollarea_insert_item(&scene->data.scroll_area, scene->data.level_pack->levels[i].level_name, i); - } - for (unsigned int i = scene->data.level_pack->n_levels; i < scene->data.scroll_area.max_items; ++i) - { - vert_scrollarea_insert_item(&scene->data.scroll_area, "---", i); - } - } - else - { - for (unsigned int i = 0; i < scene->data.scroll_area.max_items; ++i) - { - sprintf(buf, "Level %u", i); - vert_scrollarea_insert_item(&scene->data.scroll_area, buf, i); - } - } - ScrollAreaRenderEnd(); + + render_scroll_canvas(&scene->data); sc_array_add(&scene->scene.systems, &level_preview_render_func); sc_array_add(&scene->scene.systems, &level_select_render_func); diff --git a/scenes/menu_scene.c b/scenes/menu_scene.c index 3205047..ab1ecd3 100644 --- a/scenes/menu_scene.c +++ b/scenes/menu_scene.c @@ -53,7 +53,7 @@ static void exec_component_function(Scene_t* scene, int sel) switch(sel) { case 0: - change_scene(scene->engine, LEVEL_SELECT_SCENE); + change_scene_ext(scene->engine, LEVEL_SELECT_SCENE, true); break; case 1: change_scene_ext(scene->engine, OPTIONS_SCENE, true); diff --git a/scenes/save_data.c b/scenes/save_data.c new file mode 100644 index 0000000..a65fbd7 --- /dev/null +++ b/scenes/save_data.c @@ -0,0 +1,47 @@ +#include "save_data.h" +#include "constants.h" + +// Bit flags for level completion. +// Expect 30 levels. +// Could use a 32bit integer though. +// Using array to allow arbitrary length of flags. + +#define NUMBER_OF_BYTES 4 +static uint8_t completion_flags[NUMBER_OF_BYTES] = {0}; + +int load_savedata(uint8_t* bytes, size_t len) +{ + return 0; +} + +int writeout_savedata(uint8_t* bytes, size_t len) +{ + return 0; +} + +bool is_level_completed(uint32_t level_num) +{ + // 0-indexed + + uint32_t byte_num = level_num >> 3; + if (byte_num >= NUMBER_OF_BYTES) return false; + + uint32_t bit_num = level_num % 8; + return ((completion_flags[byte_num] >> bit_num) & 1) > 0; +} + +void set_level_completed(uint32_t level_num, bool complete) +{ + uint32_t byte_num = level_num >> 3; + if (byte_num >= NUMBER_OF_BYTES) return; + + uint32_t bit_num = level_num % 8; + if (complete) + { + completion_flags[byte_num] |= (1 < +#include +#include + +int load_savedata(uint8_t* bytes, size_t len); +int writeout_savedata(uint8_t* bytes, size_t len); + +bool is_level_completed(uint32_t level_num); +void set_level_completed(uint32_t level_num, bool complete); + +#endif // SAVEDATA_SCENES_H