mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-11 19:33:30 -07:00
Merge branch 'pr/383' into 420
This commit is contained in:
@@ -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) {
|
||||
@@ -34,35 +35,18 @@ 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;
|
||||
}
|
||||
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) {
|
||||
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)) {
|
||||
@@ -110,8 +94,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;
|
||||
@@ -122,8 +105,12 @@ bool snake_game_init_game_from_file(SnakeState* const snake_state) {
|
||||
}
|
||||
furi_string_free(file_type);
|
||||
|
||||
|
||||
uint32_t temp;
|
||||
if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <furi.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#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
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -78,7 +78,7 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) {
|
||||
if(snake_state->state != GameStateGameOver) {
|
||||
char buffer2[6];
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
snprintf(buffer2, sizeof(buffer2), "%u", snake_state->len - 7);
|
||||
snprintf(buffer2, sizeof(buffer2), "%u", snake_state->len);
|
||||
canvas_draw_str_aligned(canvas, 124, 10, AlignRight, AlignBottom, buffer2);
|
||||
}
|
||||
// Game Over banner
|
||||
@@ -95,7 +95,7 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) {
|
||||
|
||||
char buffer[18];
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
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);
|
||||
@@ -233,6 +233,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) {
|
||||
@@ -249,9 +261,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 {
|
||||
@@ -262,9 +272,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;
|
||||
}
|
||||
|
||||
@@ -272,9 +280,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;
|
||||
}
|
||||
}
|
||||
@@ -294,7 +300,10 @@ int32_t snake_game_app(void* p) {
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent));
|
||||
|
||||
SnakeState* snake_state = malloc(sizeof(SnakeState));
|
||||
if(!snake_game_init_game_from_file(snake_state)) snake_game_init_game(snake_state);
|
||||
snake_state->isNewHighscore = false;
|
||||
snake_state->highscore = 0;
|
||||
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))) {
|
||||
@@ -367,6 +376,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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user