From 1540853283b8735987193a4991fe1938a69fdf6e Mon Sep 17 00:00:00 2001 From: Derek Jamison Date: Thu, 23 Mar 2023 16:50:56 -0400 Subject: [PATCH] Play again prompt at end of game. --- .../rock_paper_scissors/rock_paper_scissors.c | 111 +++++++++++++++--- .../rock_paper_scissors/rock_paper_scissors.h | 4 +- 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c index 5b6644d..bec932f 100644 --- a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c +++ b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c @@ -83,8 +83,9 @@ static void } // Play a song -static void play_song(GameState state) { +static void play_song(GameContext* game_context) { if(furi_hal_speaker_acquire(1000)) { + GameState state = game_context->data->local_player; const float volume = 1.0f; const uint32_t playQtr = 500; const uint32_t delayQtr = 100; @@ -104,6 +105,9 @@ static void play_song(GameState state) { furi_hal_speaker_stop(); furi_hal_speaker_release(); + + GameEvent event = {.type = GameEventSongEnded, .tick = furi_get_tick()}; + furi_message_queue_put(game_context->queue, &event, FuriWaitForever); } } @@ -853,6 +857,63 @@ static void rps_render_input_text(Canvas* canvas, void* ctx) { } } +static void rps_render_game_result(Canvas* canvas, void* ctx) { + GameContext* game_context = ctx; + UNUSED(game_context); + + canvas_clear(canvas); + canvas_set_font(canvas, FontKeyboard); + canvas_set_color(canvas, ColorBlack); + + canvas_set_font(canvas, FontPrimary); + + char* message; + if(isWin(game_context->data->local_player)) { + message = "YOU WIN!!!"; + } else if(isLoss(game_context->data->local_player)) { + message = "YOU LOST."; + } else { + message = "DRAW!"; + } + canvas_draw_str_aligned(canvas, 40, 0, AlignLeft, AlignTop, message); + + canvas_draw_str_aligned( + canvas, 0, 12, AlignLeft, AlignTop, furi_string_get_cstr(game_context->data->remote_name)); + + canvas_set_font(canvas, FontSecondary); + char ch = furi_string_get_char(game_context->data->remote_contact, 0); + for(unsigned int i = 0; i < sizeof(contact_list) / sizeof(contact_list[0]); i++) { + if(contact_list[i][0] == ch) { + canvas_draw_str_aligned(canvas, 0, 26, AlignLeft, AlignTop, contact_list[i] + 1); + ch = 0; + break; + } + } + if(ch) { + char id[2] = {ch, 0}; + canvas_draw_str_aligned(canvas, 0, 26, AlignLeft, AlignTop, id); + } + + canvas_draw_str_aligned( + canvas, + 0, + 38, + AlignLeft, + AlignTop, + furi_string_get_cstr(game_context->data->remote_contact) + 1); + + canvas_draw_str_aligned(canvas, 18, 53, AlignLeft, AlignTop, "Play Again?"); + + canvas_draw_box(canvas, 70, 53, 30, 9); + canvas_set_color(canvas, ColorWhite); + if(game_context->data->keyboard_col == 0) { + canvas_draw_str_aligned(canvas, 73, 54, AlignLeft, AlignTop, " Yes >"); + } else { + canvas_draw_str_aligned(canvas, 73, 54, AlignLeft, AlignTop, "< No"); + } + canvas_set_color(canvas, ColorBlack); +} + // We register this callback to get invoked whenever we need to render the screen. // We render the UI on this callback thread. // @param canvas rendering surface of the Flipper Zero. @@ -877,6 +938,8 @@ static void rps_render_callback(Canvas* canvas, void* ctx) { rps_render_input_text(canvas, game_context); } else if(game_context->data->screen_state == ScreenChooseSocial) { rps_render_choose_social(canvas, game_context); + } else if(game_context->data->screen_state == ScreenFinishedGame) { + rps_render_game_result(canvas, game_context); } } @@ -1058,19 +1121,6 @@ static void rps_state_machine_update(GameContext* game_context) { return; } - // TEMP - After Win, Loss, Tie - we reset back to Ready. - if(isResult(d->local_player) && (duration(d->local_move_tick) > DURATION_WIN_LOSS_TIE)) { - d->remote_player = StateReady; - d->remote_move_tick = furi_get_tick(); - d->local_player = StateReady; - d->local_move_tick = furi_get_tick(); - d->screen_state = ScreenPlayingGame; - - // Should we tell other player we are Ready? - FURI_LOG_I(TAG, "Ready for next game."); - return; - } - // Check for winner. if(isFinalMove(d->local_player) && isFinalMove(d->remote_player) && (duration(d->local_move_tick) > DURATION_SHOW_MOVES)) { @@ -2278,6 +2328,32 @@ int32_t rock_paper_scissors_app(void* p) { FURI_LOG_T(TAG, "No support for key %d", event.input.key); break; } + } else if( + game_context->data->screen_state == ScreenFinishedGame && + event.input.type == InputTypeShort) { + switch(event.input.key) { + case InputKeyLeft: + game_context->data->keyboard_col = 0; // YES + break; + case InputKeyRight: + game_context->data->keyboard_col = 1; // NO + break; + case InputKeyOk: + if(game_context->data->keyboard_col == 1) { + game_context->data->local_player = StateMainMenuHost; + game_context->data->remote_player = StateUnknown; + game_context->data->screen_state = ScreenMainMenu; + } else { + game_context->data->remote_player = StateReady; + game_context->data->remote_move_tick = furi_get_tick(); + game_context->data->local_player = StateReady; + game_context->data->local_move_tick = furi_get_tick(); + game_context->data->screen_state = ScreenPlayingGame; + } + break; + default: + break; + } } else if( game_context->data->screen_state == ScreenPastGames && event.input.type == InputTypeShort) { @@ -2320,7 +2396,12 @@ int32_t rock_paper_scissors_app(void* p) { break; case GameEventPlaySong: save_result(game_context); - play_song(game_context->data->local_player); + play_song(game_context); + break; + case GameEventSongEnded: + if(isResult(game_context->data->local_player)) { + game_context->data->screen_state = ScreenFinishedGame; + } break; case GameEventDataDetected: rps_receive_data(game_context, event.tick); diff --git a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h index 668ebb3..8f389e4 100644 --- a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h +++ b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h @@ -157,6 +157,7 @@ typedef enum { ScreenMainMenu, ScreenHostGame, ScreenPlayingGame, + ScreenFinishedGame, ScreenError, ScreenJoinGame, ScreenChooseSocial, @@ -187,6 +188,7 @@ typedef enum { GameEventRemoteMove, GameEventSendMove, GameEventPlaySong, + GameEventSongEnded, } GameEventType; static const char* contact_list[] = { @@ -328,7 +330,7 @@ static void play_note(float frequency, float volume, uint32_t durationPlay, uint32_t durationPause); // Play a song -static void play_song(GameState state); +static void play_song(GameContext* game_context); // We register this callback to get invoked whenever new subghz data is received. // Queue a GameEventDataDetected message.