From 7ffa5fda8dd370d012d8ea37a553eefbdcec5711 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Mon, 24 Oct 2022 18:17:18 +0200 Subject: [PATCH 01/10] Snake Plugin: Move structs to types header --- .../plugins/snake_game/helpers/snake_types.h | 49 +++++++++++++++++++ applications/plugins/snake_game/snake_game.c | 48 +----------------- 2 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 applications/plugins/snake_game/helpers/snake_types.h diff --git a/applications/plugins/snake_game/helpers/snake_types.h b/applications/plugins/snake_game/helpers/snake_types.h new file mode 100644 index 00000000000..da36389701c --- /dev/null +++ b/applications/plugins/snake_game/helpers/snake_types.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +typedef struct { + // +-----x + // | + // | + // y + uint8_t x; + uint8_t y; +} Point; + +typedef enum { + GameStateLife, + + // https://melmagazine.com/en-us/story/snake-nokia-6110-oral-history-taneli-armanto + // Armanto: While testing the early versions of the game, I noticed it was hard + // to control the snake upon getting close to and edge but not crashing — especially + // in the highest speed levels. I wanted the highest level to be as fast as I could + // possibly make the device "run," but on the other hand, I wanted to be friendly + // and help the player manage that level. Otherwise it might not be fun to play. So + // I implemented a little delay. A few milliseconds of extra time right before + // the player crashes, during which she can still change the directions. And if + // she does, the game continues. + GameStateLastChance, + + GameStateGameOver, +} GameState; + +// Note: do not change without purpose. Current values are used in smart +// orthogonality calculation in `snake_game_get_turn_snake`. +typedef enum { + DirectionUp, + DirectionRight, + DirectionDown, + DirectionLeft, +} Direction; + +#define MAX_SNAKE_LEN 253 + +typedef struct { + Point points[MAX_SNAKE_LEN]; + uint16_t len; + Direction currentMovement; + Direction nextMovement; // if backward of currentMovement, ignore + Point fruit; + GameState state; +} SnakeState; diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 283d017ed6f..fdd87b504e6 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -1,3 +1,5 @@ +#include "helpers/snake_types.h" + #include #include #include @@ -6,52 +8,6 @@ #include #include -typedef struct { - // +-----x - // | - // | - // y - uint8_t x; - uint8_t y; -} Point; - -typedef enum { - GameStateLife, - - // https://melmagazine.com/en-us/story/snake-nokia-6110-oral-history-taneli-armanto - // Armanto: While testing the early versions of the game, I noticed it was hard - // to control the snake upon getting close to and edge but not crashing — especially - // in the highest speed levels. I wanted the highest level to be as fast as I could - // possibly make the device "run," but on the other hand, I wanted to be friendly - // and help the player manage that level. Otherwise it might not be fun to play. So - // I implemented a little delay. A few milliseconds of extra time right before - // the player crashes, during which she can still change the directions. And if - // she does, the game continues. - GameStateLastChance, - - GameStateGameOver, -} GameState; - -// Note: do not change without purpose. Current values are used in smart -// orthogonality calculation in `snake_game_get_turn_snake`. -typedef enum { - DirectionUp, - DirectionRight, - DirectionDown, - DirectionLeft, -} Direction; - -#define MAX_SNAKE_LEN 253 - -typedef struct { - Point points[MAX_SNAKE_LEN]; - uint16_t len; - Direction currentMovement; - Direction nextMovement; // if backward of currentMovement, ignore - Point fruit; - GameState state; -} SnakeState; - typedef enum { EventTypeTick, EventTypeKey, From 1a34dac8bac68d95e0af5d4f8c96b2804030f74f Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Mon, 24 Oct 2022 18:20:03 +0200 Subject: [PATCH 02/10] Snake Plugin: Implement #1041, save game state on pause --- .../plugins/snake_game/application.fam | 8 +- .../snake_game/helpers/snake_file_handler.c | 143 ++++++++++++++++++ .../snake_game/helpers/snake_file_handler.h | 20 +++ applications/plugins/snake_game/snake_game.c | 6 +- 4 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 applications/plugins/snake_game/helpers/snake_file_handler.c create mode 100644 applications/plugins/snake_game/helpers/snake_file_handler.h diff --git a/applications/plugins/snake_game/application.fam b/applications/plugins/snake_game/application.fam index d55f53bb14f..d0378ac1199 100644 --- a/applications/plugins/snake_game/application.fam +++ b/applications/plugins/snake_game/application.fam @@ -4,8 +4,12 @@ App( apptype=FlipperAppType.PLUGIN, entry_point="snake_game_app", cdefines=["APP_SNAKE_GAME"], - requires=["gui"], - stack_size=1 * 1024, + requires=[ + "gui", + "notification", + "storage", + ], + stack_size=2 * 1024, order=30, fap_icon="snake_10px.png", fap_category="Games", diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c new file mode 100644 index 00000000000..415c840de59 --- /dev/null +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -0,0 +1,143 @@ +#include "snake_file_handler.h" + +#include +#include + +static void snake_game_close_file(FlipperFormat* file) { + if(file == NULL){ + furi_record_close(RECORD_STORAGE); + return; + } + flipper_format_file_close(file); + flipper_format_free(file); + furi_record_close(RECORD_STORAGE); +} + +static FlipperFormat* snake_game_open_file(Storage* storage) { + FlipperFormat* file = flipper_format_file_alloc(storage); + + if(storage_common_stat(storage, SNAKE_GAME_FILE_PATH, NULL) == FSE_OK) { + if(!flipper_format_file_open_existing(file, SNAKE_GAME_FILE_PATH)) { + snake_game_close_file(file); + return NULL; + } + } else { + if(!flipper_format_file_open_new(file, SNAKE_GAME_FILE_PATH)) { + snake_game_close_file(file); + return NULL; + } + + flipper_format_write_header_cstr(file, SNAKE_GAME_FILE_HEADER, SNAKE_GAME_FILE_ACTUAL_VERSION); + flipper_format_rewind(file); + } + return file; +} + +void snake_game_save_game_to_file(SnakeState* const snake_state) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* file = snake_game_open_file(storage); + + uint32_t temp = snake_state->len; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN,&temp, 1)){ + snake_game_close_file(file); + return; + } + + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++){ + temp_array[a++] = snake_state->points[i].x; + temp_array[a++] = snake_state->points[i].y; + } + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)){ + snake_game_close_file(file); + return; + } + + temp = snake_state->currentMovement; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT,&temp, 1)){ + snake_game_close_file(file); + return; + } + + temp = snake_state->nextMovement; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT,&temp, 1)){ + snake_game_close_file(file); + return; + } + + array_size = 2; + uint32_t temp_point_array[array_size]; + temp_point_array[0] = snake_state->fruit.x; + temp_point_array[1] = snake_state->fruit.y; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)){ + snake_game_close_file(file); + return; + } + + snake_game_close_file(file); +} + +bool snake_game_init_game_from_file(SnakeState* const snake_state) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* file = snake_game_open_file(storage); + + FuriString* file_type = furi_string_alloc(); + uint32_t version = 1; + if(!flipper_format_read_header(file, file_type, &version)) { + furi_string_free(file_type); + snake_game_close_file(file); + return false; + } + furi_string_free(file_type); + + uint32_t temp; + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)){ + snake_game_close_file(file); + return false; + } + snake_state->len = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_LEN); + + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)){ + snake_game_close_file(file); + return false; + } + + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++){ + snake_state->points[i].x = temp_array[a++]; + snake_state->points[i].y = temp_array[a++]; + } + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); + + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)){ + snake_game_close_file(file); + return false; + } + snake_state->currentMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); + + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)){ + snake_game_close_file(file); + return false; + } + snake_state->nextMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); + + + array_size = 2; + uint32_t temp_point_array[array_size]; + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)){ + snake_game_close_file(file); + return false; + } + snake_state->fruit.x = temp_point_array[0]; + snake_state->fruit.y = temp_point_array[1]; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS); + + snake_game_close_file(file); + + return true; +} diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h new file mode 100644 index 00000000000..3a89114c31c --- /dev/null +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -0,0 +1,20 @@ +#pragma once + +#include "snake_types.h" +#include +#include + +#define SNAKE_GAME_FILE_PATH "/ext/apps/games/snake.stat" + +#define SNAKE_GAME_FILE_HEADER "Flipper Snake plugin run file" +#define SNAKE_GAME_FILE_ACTUAL_VERSION 1 + +#define SNAKE_GAME_CONFIG_KEY_POINTS "SnakePoints" +#define SNAKE_GAME_CONFIG_KEY_LEN "SnakeLen" +#define SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT "CurrentMovement" +#define SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT "NextMovement" +#define SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS "FruitPoints" + +void snake_game_save_game_to_file(SnakeState* const snake_state); + +bool snake_game_init_game_from_file(SnakeState* const snake_state); diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index fdd87b504e6..0b6cd85f369 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -1,3 +1,4 @@ +#include "helpers/snake_file_handler.h" #include "helpers/snake_types.h" #include @@ -279,7 +280,8 @@ int32_t snake_game_app(void* p) { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent)); SnakeState* snake_state = malloc(sizeof(SnakeState)); - snake_game_init_game(snake_state); + if(!snake_game_init_game_from_file(snake_state)) + snake_game_init_game(snake_state); ValueMutex state_mutex; if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) { @@ -334,6 +336,8 @@ int32_t snake_game_app(void* p) { } break; case InputKeyBack: + if(snake_state->state == GameStateLife) + snake_game_save_game_to_file(snake_state); processing = false; break; } From 47cbdac7b1b713e7a8ba9eeb317060cf7ba43cb1 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Mon, 24 Oct 2022 18:20:57 +0200 Subject: [PATCH 03/10] Snake Plugin: Add highscore info --- .../snake_game/helpers/snake_file_handler.c | 26 +++++++++++++++++++ .../snake_game/helpers/snake_file_handler.h | 3 +++ .../plugins/snake_game/helpers/snake_types.h | 1 + applications/plugins/snake_game/snake_game.c | 12 ++++++--- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index 415c840de59..efc3b2e94db 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -33,6 +33,32 @@ static FlipperFormat* snake_game_open_file(Storage* storage) { return file; } +int16_t snake_game_save_score_to_file(int32_t len) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* file = snake_game_open_file(storage); + + len = len - 7; + int32_t temp; + if(!flipper_format_read_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)){ + if(!flipper_format_insert_or_update_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &len, 1)){ + snake_game_close_file(file); + return -1; + } + }else{ + if(len > temp){ + flipper_format_rewind(file); + if(!flipper_format_insert_or_update_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &len, 1)){ + snake_game_close_file(file); + return -1; + } + }else{ + len = temp; + } + } + snake_game_close_file(file); + return len; +} + void snake_game_save_game_to_file(SnakeState* const snake_state) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = snake_game_open_file(storage); diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index 3a89114c31c..fbcc7131e86 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -14,6 +14,9 @@ #define SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT "CurrentMovement" #define SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT "NextMovement" #define SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS "FruitPoints" +#define SNAKE_GAME_CONFIG_HIGHSCORE "Highscore" + +int16_t snake_game_save_score_to_file(int32_t length); void snake_game_save_game_to_file(SnakeState* const snake_state); diff --git a/applications/plugins/snake_game/helpers/snake_types.h b/applications/plugins/snake_game/helpers/snake_types.h index da36389701c..f5768311f71 100644 --- a/applications/plugins/snake_game/helpers/snake_types.h +++ b/applications/plugins/snake_game/helpers/snake_types.h @@ -42,6 +42,7 @@ typedef enum { typedef struct { Point points[MAX_SNAKE_LEN]; uint16_t len; + int16_t highscore; Direction currentMovement; Direction nextMovement; // if backward of currentMovement, ignore Point fruit; diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 0b6cd85f369..b316fb77d38 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -77,18 +77,21 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) { if(snake_state->state == GameStateGameOver) { // Screen is 128x64 px canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); + canvas_draw_box(canvas, 32, 20, 64, 34); canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); + canvas_draw_frame(canvas, 32, 20, 64, 34); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 37, 31, "Game Over"); canvas_set_font(canvas, FontSecondary); - char buffer[12]; + char buffer[18]; snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7); canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); + + snprintf(buffer, sizeof(buffer), "Highscore: %d", snake_state->highscore); + canvas_draw_str_aligned(canvas, 64, 51, AlignCenter, AlignBottom, buffer); } release_mutex((ValueMutex*)ctx, snake_state); @@ -239,6 +242,7 @@ static void return; } else if(snake_state->state == GameStateLastChance) { snake_state->state = GameStateGameOver; + snake_state->highscore = snake_game_save_score_to_file(snake_state->len); notification_message_block(notification, &sequence_fail); return; } @@ -251,6 +255,7 @@ static void crush = snake_game_collision_with_tail(snake_state, next_step); if(crush) { snake_state->state = GameStateGameOver; + snake_state->highscore = snake_game_save_score_to_file(snake_state->len); notification_message_block(notification, &sequence_fail); return; } @@ -260,6 +265,7 @@ static void snake_state->len++; if(snake_state->len >= MAX_SNAKE_LEN) { snake_state->state = GameStateGameOver; + snake_state->highscore = snake_game_save_score_to_file(snake_state->len); notification_message_block(notification, &sequence_fail); return; } From 65fdda1f8abeaa7ccf45a2f1148f074ab91f0cb2 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Wed, 26 Oct 2022 19:30:01 +0200 Subject: [PATCH 04/10] Snake Plugin: change file path --- applications/plugins/snake_game/helpers/snake_file_handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index fbcc7131e86..7ae367506cf 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -4,7 +4,7 @@ #include #include -#define SNAKE_GAME_FILE_PATH "/ext/apps/games/snake.stat" +#define SNAKE_GAME_FILE_PATH "/ext/apps/games/.snake" #define SNAKE_GAME_FILE_HEADER "Flipper Snake plugin run file" #define SNAKE_GAME_FILE_ACTUAL_VERSION 1 From 8304605551aab1fa3b9f7d194e995c66aa62fd12 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Wed, 26 Oct 2022 19:30:38 +0200 Subject: [PATCH 05/10] Snake Plugin: put Storage handeling in openfile function --- .../plugins/snake_game/helpers/snake_file_handler.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index efc3b2e94db..1393162602f 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -13,7 +13,8 @@ static void snake_game_close_file(FlipperFormat* file) { furi_record_close(RECORD_STORAGE); } -static FlipperFormat* snake_game_open_file(Storage* storage) { +static FlipperFormat* snake_game_open_file() { + Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); if(storage_common_stat(storage, SNAKE_GAME_FILE_PATH, NULL) == FSE_OK) { @@ -60,8 +61,7 @@ int16_t snake_game_save_score_to_file(int32_t len) { } void snake_game_save_game_to_file(SnakeState* const snake_state) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = snake_game_open_file(storage); + FlipperFormat* file = snake_game_open_file(); uint32_t temp = snake_state->len; if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN,&temp, 1)){ @@ -105,8 +105,7 @@ void snake_game_save_game_to_file(SnakeState* const snake_state) { } bool snake_game_init_game_from_file(SnakeState* const snake_state) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = snake_game_open_file(storage); + FlipperFormat* file = snake_game_open_file(); FuriString* file_type = furi_string_alloc(); uint32_t version = 1; @@ -152,7 +151,6 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) { snake_state->nextMovement = temp; flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); - array_size = 2; uint32_t temp_point_array[array_size]; if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)){ From b97affa562293832106ecc750dd72500ee4baebf Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Wed, 26 Oct 2022 19:31:12 +0200 Subject: [PATCH 06/10] Snake Plugin: put state game over handeling into function --- applications/plugins/snake_game/snake_game.c | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index b316fb77d38..3405a7b2654 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -87,7 +87,7 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) { canvas_set_font(canvas, FontSecondary); char buffer[18]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7); + snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len); canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); snprintf(buffer, sizeof(buffer), "Highscore: %d", snake_state->highscore); @@ -222,6 +222,18 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex snake_state->points[0] = next_step; } +static void snake_game_game_over(SnakeState* const snake_state, NotificationApp* notification) { + snake_state->state = GameStateGameOver; + snake_state->len = snake_state->len -7; + if(snake_state->len > snake_state->highscore){ + snake_state->isNewHighscore = true; + snake_state->highscore = snake_state->len; + } + + notification_message_block(notification, &sequence_fail); + +} + static void snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { if(snake_state->state == GameStateGameOver) { @@ -241,9 +253,7 @@ static void snake_state->state = GameStateLastChance; return; } else if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateGameOver; - snake_state->highscore = snake_game_save_score_to_file(snake_state->len); - notification_message_block(notification, &sequence_fail); + snake_game_game_over(snake_state, notification); return; } } else { @@ -254,9 +264,7 @@ static void crush = snake_game_collision_with_tail(snake_state, next_step); if(crush) { - snake_state->state = GameStateGameOver; - snake_state->highscore = snake_game_save_score_to_file(snake_state->len); - notification_message_block(notification, &sequence_fail); + snake_game_game_over(snake_state, notification); return; } @@ -264,9 +272,7 @@ static void if(eatFruit) { snake_state->len++; if(snake_state->len >= MAX_SNAKE_LEN) { - snake_state->state = GameStateGameOver; - snake_state->highscore = snake_game_save_score_to_file(snake_state->len); - notification_message_block(notification, &sequence_fail); + snake_game_game_over(snake_state, notification); return; } } From b5899e8aa24fb1527865ef71733df0658492ebe9 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Wed, 26 Oct 2022 19:31:51 +0200 Subject: [PATCH 07/10] Snake Plugin: get Highscore on start and only write to file if new highscore --- .../snake_game/helpers/snake_file_handler.c | 32 ++++++------------- .../snake_game/helpers/snake_file_handler.h | 2 +- .../plugins/snake_game/helpers/snake_types.h | 1 + applications/plugins/snake_game/snake_game.c | 4 +++ 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index 1393162602f..79405cbf4f5 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -34,30 +34,14 @@ static FlipperFormat* snake_game_open_file() { return file; } -int16_t snake_game_save_score_to_file(int32_t len) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = snake_game_open_file(storage); - - len = len - 7; - int32_t temp; - if(!flipper_format_read_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)){ - if(!flipper_format_insert_or_update_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &len, 1)){ - snake_game_close_file(file); - return -1; - } - }else{ - if(len > temp){ - flipper_format_rewind(file); - if(!flipper_format_insert_or_update_int32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &len, 1)){ - snake_game_close_file(file); - return -1; - } - }else{ - len = temp; - } +void snake_game_save_score_to_file(int16_t highscore) { + FlipperFormat* file = snake_game_open_file(); + uint32_t temp = highscore; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE,&temp, 1)){ + snake_game_close_file(file); + return; } snake_game_close_file(file); - return len; } void snake_game_save_game_to_file(SnakeState* const snake_state) { @@ -116,7 +100,11 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) { } furi_string_free(file_type); + uint32_t temp; + snake_state->highscore = (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; + flipper_format_rewind(file); + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)){ snake_game_close_file(file); return false; diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index 7ae367506cf..25cda450682 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -16,7 +16,7 @@ #define SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS "FruitPoints" #define SNAKE_GAME_CONFIG_HIGHSCORE "Highscore" -int16_t snake_game_save_score_to_file(int32_t length); +void snake_game_save_score_to_file(int16_t highscore); void snake_game_save_game_to_file(SnakeState* const snake_state); diff --git a/applications/plugins/snake_game/helpers/snake_types.h b/applications/plugins/snake_game/helpers/snake_types.h index f5768311f71..08682f58581 100644 --- a/applications/plugins/snake_game/helpers/snake_types.h +++ b/applications/plugins/snake_game/helpers/snake_types.h @@ -42,6 +42,7 @@ typedef enum { typedef struct { Point points[MAX_SNAKE_LEN]; uint16_t len; + bool isNewHighscore; int16_t highscore; Direction currentMovement; Direction nextMovement; // if backward of currentMovement, ignore diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 3405a7b2654..5658c1ac1d8 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -292,6 +292,8 @@ int32_t snake_game_app(void* p) { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent)); SnakeState* snake_state = malloc(sizeof(SnakeState)); + snake_state->isNewHighscore = false; + snake_state->highscore = 0; if(!snake_game_init_game_from_file(snake_state)) snake_game_init_game(snake_state); @@ -365,6 +367,8 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } + if(snake_state->isNewHighscore) + snake_game_save_score_to_file(snake_state->highscore); // Wait for all notifications to be played and return backlight to normal state notification_message_block(notification, &sequence_display_backlight_enforce_auto); From 7776c360486e4b08e66c27f8a547cbdf92cfec95 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Tue, 1 Nov 2022 15:42:46 +0100 Subject: [PATCH 08/10] Snake Plugin: Formating clang-format --- .../snake_game/helpers/snake_file_handler.c | 56 ++++++++++--------- applications/plugins/snake_game/snake_game.c | 14 +++-- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index 79405cbf4f5..3a1ea74555d 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -4,7 +4,7 @@ #include static void snake_game_close_file(FlipperFormat* file) { - if(file == NULL){ + if(file == NULL) { furi_record_close(RECORD_STORAGE); return; } @@ -28,7 +28,8 @@ static FlipperFormat* snake_game_open_file() { return NULL; } - flipper_format_write_header_cstr(file, SNAKE_GAME_FILE_HEADER, SNAKE_GAME_FILE_ACTUAL_VERSION); + flipper_format_write_header_cstr( + file, SNAKE_GAME_FILE_HEADER, SNAKE_GAME_FILE_ACTUAL_VERSION); flipper_format_rewind(file); } return file; @@ -37,7 +38,7 @@ static FlipperFormat* snake_game_open_file() { void snake_game_save_score_to_file(int16_t highscore) { FlipperFormat* file = snake_game_open_file(); uint32_t temp = highscore; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE,&temp, 1)){ + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) { snake_game_close_file(file); return; } @@ -48,41 +49,45 @@ void snake_game_save_game_to_file(SnakeState* const snake_state) { FlipperFormat* file = snake_game_open_file(); uint32_t temp = snake_state->len; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN,&temp, 1)){ + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { snake_game_close_file(file); return; } uint16_t array_size = snake_state->len * 2; uint32_t temp_array[array_size]; - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++){ + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { temp_array[a++] = snake_state->points[i].x; temp_array[a++] = snake_state->points[i].y; } - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)){ - snake_game_close_file(file); - return; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { + snake_game_close_file(file); + return; } temp = snake_state->currentMovement; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT,&temp, 1)){ - snake_game_close_file(file); - return; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; } temp = snake_state->nextMovement; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT,&temp, 1)){ - snake_game_close_file(file); - return; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; } array_size = 2; uint32_t temp_point_array[array_size]; temp_point_array[0] = snake_state->fruit.x; temp_point_array[1] = snake_state->fruit.y; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)){ - snake_game_close_file(file); - return; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { + snake_game_close_file(file); + return; } snake_game_close_file(file); @@ -100,12 +105,12 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) { } furi_string_free(file_type); - uint32_t temp; - snake_state->highscore = (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; + snake_state->highscore = + (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; flipper_format_rewind(file); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)){ + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { snake_game_close_file(file); return false; } @@ -114,25 +119,25 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) { uint16_t array_size = snake_state->len * 2; uint32_t temp_array[array_size]; - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)){ + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { snake_game_close_file(file); return false; } - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++){ + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { snake_state->points[i].x = temp_array[a++]; snake_state->points[i].y = temp_array[a++]; } flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)){ + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { snake_game_close_file(file); return false; } snake_state->currentMovement = temp; flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)){ + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { snake_game_close_file(file); return false; } @@ -141,7 +146,8 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) { array_size = 2; uint32_t temp_point_array[array_size]; - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)){ + if(!flipper_format_read_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { snake_game_close_file(file); return false; } diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 5658c1ac1d8..623ccea1019 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -224,14 +224,13 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex static void snake_game_game_over(SnakeState* const snake_state, NotificationApp* notification) { snake_state->state = GameStateGameOver; - snake_state->len = snake_state->len -7; - if(snake_state->len > snake_state->highscore){ + snake_state->len = snake_state->len - 7; + if(snake_state->len > snake_state->highscore) { snake_state->isNewHighscore = true; snake_state->highscore = snake_state->len; } notification_message_block(notification, &sequence_fail); - } static void @@ -294,8 +293,9 @@ int32_t snake_game_app(void* p) { SnakeState* snake_state = malloc(sizeof(SnakeState)); snake_state->isNewHighscore = false; snake_state->highscore = 0; - if(!snake_game_init_game_from_file(snake_state)) + if(!snake_game_init_game_from_file(snake_state)) { snake_game_init_game(snake_state); + } ValueMutex state_mutex; if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) { @@ -350,8 +350,9 @@ int32_t snake_game_app(void* p) { } break; case InputKeyBack: - if(snake_state->state == GameStateLife) + if(snake_state->state == GameStateLife) { snake_game_save_game_to_file(snake_state); + } processing = false; break; } @@ -367,8 +368,9 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } - if(snake_state->isNewHighscore) + if(snake_state->isNewHighscore) { snake_game_save_score_to_file(snake_state->highscore); + } // Wait for all notifications to be played and return backlight to normal state notification_message_block(notification, &sequence_display_backlight_enforce_auto); From 86c81086989aa0c251b986967f5acf401eae05b2 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Mon, 14 Nov 2022 09:59:33 +0100 Subject: [PATCH 09/10] Snake Plugin: move storage to /ext/apps_data/snake_game --- .../plugins/snake_game/helpers/snake_file_handler.c | 11 +++++++++++ .../plugins/snake_game/helpers/snake_file_handler.h | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index 3a1ea74555d..a60463c17df 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -23,6 +23,17 @@ static FlipperFormat* snake_game_open_file() { return NULL; } } else { + if(storage_common_stat(storage, APPS_DATA, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, APPS_DATA)) { + return NULL; + } + } + if(storage_common_stat(storage, SNAKE_GAME_FILE_DIR_PATH, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, SNAKE_GAME_FILE_DIR_PATH)) { + return NULL; + } + } + if(!flipper_format_file_open_new(file, SNAKE_GAME_FILE_PATH)) { snake_game_close_file(file); return NULL; diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index 25cda450682..586d9df9411 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -4,7 +4,9 @@ #include #include -#define SNAKE_GAME_FILE_PATH "/ext/apps/games/.snake" +#define APPS_DATA EXT_PATH("apps_data") +#define SNAKE_GAME_FILE_DIR_PATH APPS_DATA "/snake_game" +#define SNAKE_GAME_FILE_PATH SNAKE_GAME_FILE_DIR_PATH "/.snake" #define SNAKE_GAME_FILE_HEADER "Flipper Snake plugin run file" #define SNAKE_GAME_FILE_ACTUAL_VERSION 1 From 46170549ca9dc21767ef1442ec92b7abebd7e07b Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Mon, 14 Nov 2022 10:02:59 +0100 Subject: [PATCH 10/10] Snake Plugin: Check if File could be opened, if not return --- .../snake_game/helpers/snake_file_handler.c | 193 +++++++++--------- .../snake_game/helpers/snake_file_handler.h | 4 +- 2 files changed, 103 insertions(+), 94 deletions(-) diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index a60463c17df..569bd8738ea 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -48,125 +48,134 @@ static FlipperFormat* snake_game_open_file() { void snake_game_save_score_to_file(int16_t highscore) { FlipperFormat* file = snake_game_open_file(); - uint32_t temp = highscore; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) { + if(file != NULL) { + uint32_t temp = highscore; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) { + snake_game_close_file(file); + return; + } snake_game_close_file(file); - return; } - snake_game_close_file(file); } void snake_game_save_game_to_file(SnakeState* const snake_state) { FlipperFormat* file = snake_game_open_file(); - uint32_t temp = snake_state->len; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { - snake_game_close_file(file); - return; - } + if(file != NULL) { + uint32_t temp = snake_state->len; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { + snake_game_close_file(file); + return; + } - uint16_t array_size = snake_state->len * 2; - uint32_t temp_array[array_size]; - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { - temp_array[a++] = snake_state->points[i].x; - temp_array[a++] = snake_state->points[i].y; - } - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { - snake_game_close_file(file); - return; - } + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { + temp_array[a++] = snake_state->points[i].x; + temp_array[a++] = snake_state->points[i].y; + } + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { + snake_game_close_file(file); + return; + } - temp = snake_state->currentMovement; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return; - } + temp = snake_state->currentMovement; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; + } - temp = snake_state->nextMovement; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return; - } + temp = snake_state->nextMovement; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; + } + + array_size = 2; + uint32_t temp_point_array[array_size]; + temp_point_array[0] = snake_state->fruit.x; + temp_point_array[1] = snake_state->fruit.y; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { + snake_game_close_file(file); + return; + } - array_size = 2; - uint32_t temp_point_array[array_size]; - temp_point_array[0] = snake_state->fruit.x; - temp_point_array[1] = snake_state->fruit.y; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { snake_game_close_file(file); - return; } - - snake_game_close_file(file); } bool snake_game_init_game_from_file(SnakeState* const snake_state) { FlipperFormat* file = snake_game_open_file(); - FuriString* file_type = furi_string_alloc(); - uint32_t version = 1; - if(!flipper_format_read_header(file, file_type, &version)) { + if(file != NULL) { + FuriString* file_type = furi_string_alloc(); + uint32_t version = 1; + if(!flipper_format_read_header(file, file_type, &version)) { + furi_string_free(file_type); + snake_game_close_file(file); + return false; + } furi_string_free(file_type); - snake_game_close_file(file); - return false; - } - furi_string_free(file_type); - uint32_t temp; - snake_state->highscore = - (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; - flipper_format_rewind(file); + uint32_t temp; + snake_state->highscore = + (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; + flipper_format_rewind(file); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->len = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_LEN); + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->len = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_LEN); - uint16_t array_size = snake_state->len * 2; - uint32_t temp_array[array_size]; - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { - snake_game_close_file(file); - return false; - } + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + if(!flipper_format_read_uint32( + file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { + snake_game_close_file(file); + return false; + } - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { - snake_state->points[i].x = temp_array[a++]; - snake_state->points[i].y = temp_array[a++]; - } - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { + snake_state->points[i].x = temp_array[a++]; + snake_state->points[i].y = temp_array[a++]; + } + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->currentMovement = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->currentMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->nextMovement = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->nextMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); + + array_size = 2; + uint32_t temp_point_array[array_size]; + if(!flipper_format_read_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { + snake_game_close_file(file); + return false; + } + snake_state->fruit.x = temp_point_array[0]; + snake_state->fruit.y = temp_point_array[1]; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS); - array_size = 2; - uint32_t temp_point_array[array_size]; - if(!flipper_format_read_uint32( - file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { snake_game_close_file(file); - return false; - } - snake_state->fruit.x = temp_point_array[0]; - snake_state->fruit.y = temp_point_array[1]; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS); - snake_game_close_file(file); + return true; + } - return true; + return false; } diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index 586d9df9411..178d5d8e0a3 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -4,8 +4,8 @@ #include #include -#define APPS_DATA EXT_PATH("apps_data") -#define SNAKE_GAME_FILE_DIR_PATH APPS_DATA "/snake_game" +#define APPS_DATA EXT_PATH("apps_data") +#define SNAKE_GAME_FILE_DIR_PATH APPS_DATA "/snake_game" #define SNAKE_GAME_FILE_PATH SNAKE_GAME_FILE_DIR_PATH "/.snake" #define SNAKE_GAME_FILE_HEADER "Flipper Snake plugin run file"