Add images to rock paper scissors game.
@ -2,9 +2,9 @@
|
|||||||
## Status
|
## Status
|
||||||
This is current a work in progress.
|
This is current a work in progress.
|
||||||
- Most of the game logic is complete (two flippers should be able to play each other.)
|
- Most of the game logic is complete (two flippers should be able to play each other.)
|
||||||
|
- UI to show images instead of text.
|
||||||
|
|
||||||
Remaining work:
|
Remaining work:
|
||||||
- UI to show images instead of text.
|
|
||||||
- Tone when button pressed.
|
- Tone when button pressed.
|
||||||
- Show games found & let user pick the game to join.
|
- Show games found & let user pick the game to join.
|
||||||
- Log joined game into SD card.
|
- Log joined game into SD card.
|
||||||
@ -35,6 +35,8 @@ These directions assume you are starting at the flipper desktop. If not, please
|
|||||||
|
|
||||||
- Do the same steps on your second Flipper.
|
- Do the same steps on your second Flipper.
|
||||||
|
|
||||||
|
- On one of the flippers press Left arrow to join the game.
|
||||||
|
|
||||||
- Once two players are joined:
|
- Once two players are joined:
|
||||||
- Press "OK" to send "1". The other player should also press "OK" to send "1" back (at the same time!)
|
- Press "OK" to send "1". The other player should also press "OK" to send "1" back (at the same time!)
|
||||||
- Press "OK" to send "2". The other player should also press "OK" to send "2" back (at the same time!)
|
- Press "OK" to send "2". The other player should also press "OK" to send "2" back (at the same time!)
|
||||||
|
BIN
subghz/plugins/rock_paper_scissors/images/BLE_Pairing_128x64.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/DolphinNice_96x59.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.1 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Count.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Looking.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Paper.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Ready.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Rock.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Local_Scissors.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Remote_Count.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Remote_Paper.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Remote_Ready.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Remote_Rock.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
subghz/plugins/rock_paper_scissors/images/Remote_Scissors.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
@ -14,10 +14,12 @@ Down - Scissors
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "rock_paper_scissors_icons.h"
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <furi_hal_resources.h>
|
#include <furi_hal_resources.h>
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
|
#include <gui/icon.h>
|
||||||
#include <locale/locale.h>
|
#include <locale/locale.h>
|
||||||
|
|
||||||
#include <lib/subghz/subghz_tx_rx_worker.h>
|
#include <lib/subghz/subghz_tx_rx_worker.h>
|
||||||
@ -38,6 +40,25 @@ Down - Scissors
|
|||||||
// The major version must be a single character (it can be anything - like '1' or 'A' or 'a').
|
// The major version must be a single character (it can be anything - like '1' or 'A' or 'a').
|
||||||
#define MAJOR_VERSION 'A'
|
#define MAJOR_VERSION 'A'
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DolphinLocalLooking = 0,
|
||||||
|
DolphinLocalReady,
|
||||||
|
DolphinLocalCount,
|
||||||
|
DolphinLocalRock,
|
||||||
|
DolphinLocalPaper,
|
||||||
|
DolphinLocalScissors,
|
||||||
|
DolphinRemoteReady,
|
||||||
|
DolphinRemoteCount,
|
||||||
|
DolphinRemoteRock,
|
||||||
|
DolphinRemotePaper,
|
||||||
|
DolphinRemoteScissors,
|
||||||
|
} DolphinImageIndex;
|
||||||
|
|
||||||
|
const Icon* images[] = {
|
||||||
|
&I_Local_Looking, &I_Local_Ready,
|
||||||
|
&I_Local_Count, &I_Local_Rock, &I_Local_Paper, &I_Local_Scissors,
|
||||||
|
&I_Remote_Ready, &I_Remote_Count, &I_Remote_Rock, &I_Remote_Paper, &I_Remote_Scissors };
|
||||||
|
|
||||||
// The various moves a player can make.
|
// The various moves a player can make.
|
||||||
// Some moves may be invalid depending on the current game state.
|
// Some moves may be invalid depending on the current game state.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -269,97 +290,167 @@ static void rps_render_callback(Canvas* canvas, void* ctx) {
|
|||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
|
||||||
// Temporary - Just show game text.
|
switch (remotePlayer) {
|
||||||
switch (localPlayer) {
|
|
||||||
case StateLookingForPlayer:
|
|
||||||
furi_string_printf(data->buffer, "Waiting for join: %d", data->gameNumber);
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, furi_string_get_cstr(data->buffer));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateReady:
|
case StateReady:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Press OK for 1.");
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteReady]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StateCount1:
|
case StateCount1:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Press OK for 2.");
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteCount]);
|
||||||
|
canvas_draw_str_aligned(canvas, 70, 15, AlignLeft, AlignTop, "1");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StateCount2:
|
case StateCount2:
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteCount]);
|
||||||
canvas_draw_str_aligned(canvas, 5, 10, AlignLeft, AlignTop, "^ Rock");
|
canvas_draw_str_aligned(canvas, 70, 15, AlignLeft, AlignTop, "2");
|
||||||
canvas_draw_str_aligned(canvas, 50, 30, AlignLeft, AlignTop, "> Paper");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 50, AlignLeft, AlignTop, "v Scissors");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StateRock:
|
case StateRock:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Rock");
|
case StateTieRock:
|
||||||
|
case StateWonRock:
|
||||||
|
case StateLostRock:
|
||||||
|
if (StateCount2 != localPlayer) {
|
||||||
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteRock]);
|
||||||
|
canvas_draw_str_aligned(canvas, 70, 55, AlignLeft, AlignTop, "Rock");
|
||||||
|
} else {
|
||||||
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteCount]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StatePaper:
|
case StatePaper:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Paper");
|
case StateTiePaper:
|
||||||
|
case StateWonPaper:
|
||||||
|
case StateLostPaper:
|
||||||
|
if (StateCount2 != localPlayer) {
|
||||||
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemotePaper]);
|
||||||
|
canvas_draw_str_aligned(canvas, 70, 55, AlignLeft, AlignTop, "Paper");
|
||||||
|
} else {
|
||||||
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteCount]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StateScissors:
|
case StateScissors:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Scissors");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateWonRock:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You won!!!");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Rock v. Scissors");
|
|
||||||
break;
|
|
||||||
case StateWonPaper:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You won!!!");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Paper v. Rock");
|
|
||||||
break;
|
|
||||||
case StateWonScissors:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You won!!!");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Scissors v. Paper");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateTieRock:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You tied!");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Rock v. Rock");
|
|
||||||
break;
|
|
||||||
case StateTiePaper:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You tied!");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Paper v. Paper");
|
|
||||||
break;
|
|
||||||
case StateTieScissors:
|
case StateTieScissors:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You tied!");
|
case StateWonScissors:
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Scissors v. Scissors");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateLostRock:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You lost.");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Rock v. Paper");
|
|
||||||
break;
|
|
||||||
case StateLostPaper:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You lost.");
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Paper v. Scissors");
|
|
||||||
break;
|
|
||||||
case StateLostScissors:
|
case StateLostScissors:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "You lost.");
|
if (StateCount2 != localPlayer) {
|
||||||
canvas_draw_str_aligned(canvas, 5, 30, AlignLeft, AlignTop, "Scissors v. Rock");
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteScissors]);
|
||||||
break;
|
canvas_draw_str_aligned(canvas, 70, 55, AlignLeft, AlignTop, "Scissors");
|
||||||
|
} else {
|
||||||
case StateError:
|
canvas_draw_icon(canvas, 64, 0, images[DolphinRemoteCount]);
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Unknown error");
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case StateErrorLocalFast:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Too fast!");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateErrorRemoteFast:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Remote too fast!");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StateErrorRemoteTimeout:
|
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Remote timeout.");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignTop, "Unexpected.");
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (localPlayer) {
|
||||||
|
case StateLookingForPlayer:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalLooking]);
|
||||||
|
furi_string_printf(data->buffer, "Waiting for player, game %03d.", data->gameNumber);
|
||||||
|
canvas_draw_str_aligned(canvas, 0, 55, AlignLeft, AlignTop, furi_string_get_cstr(data->buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateReady:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalReady]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Press OK for 1.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateCount1:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalCount]);
|
||||||
|
canvas_draw_str_aligned(canvas, 50, 15, AlignLeft, AlignTop, "1");
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Press OK for 2.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateCount2:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalCount]);
|
||||||
|
canvas_draw_str_aligned(canvas, 50, 15, AlignLeft, AlignTop, "2");
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "^Rock >Paper vScissor");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateRock:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalRock]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Rock");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StatePaper:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalPaper]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Paper");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateScissors:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalScissors]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Scissors");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateWonRock:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalRock]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Rock");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You won!!!");
|
||||||
|
break;
|
||||||
|
case StateWonPaper:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalPaper]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Paper");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You won!!!");
|
||||||
|
break;
|
||||||
|
case StateWonScissors:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalScissors]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Scissors");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You won!!!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateTieRock:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalRock]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Rock");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You tied!");
|
||||||
|
break;
|
||||||
|
case StateTiePaper:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalPaper]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Paper");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You tied!");
|
||||||
|
break;
|
||||||
|
case StateTieScissors:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalScissors]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Scissors");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You tied!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateLostRock:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalRock]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Rock");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You lost.");
|
||||||
|
break;
|
||||||
|
case StateLostPaper:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalPaper]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Paper");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You lost.");
|
||||||
|
break;
|
||||||
|
case StateLostScissors:
|
||||||
|
canvas_draw_icon(canvas, 0, 0, images[DolphinLocalScissors]);
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Scissors");
|
||||||
|
canvas_draw_str_aligned(canvas, 38, 5, AlignLeft, AlignTop, "You lost.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateError:
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Unknown error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateErrorLocalFast:
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Too fast!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateErrorRemoteFast:
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Remote too fast!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StateErrorRemoteTimeout:
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Remote timeout.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
canvas_draw_str_aligned(canvas, 5, 55, AlignLeft, AlignTop, "Unexpected.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +588,7 @@ static bool isError(GameState state) {
|
|||||||
// Temporary timings, since I don't have second Flipper & send commands via laptop.
|
// Temporary timings, since I don't have second Flipper & send commands via laptop.
|
||||||
#define DURATION_NO_MOVE_DETECTED_ERROR 60000
|
#define DURATION_NO_MOVE_DETECTED_ERROR 60000
|
||||||
#define DURATION_SHOW_ERROR 3000
|
#define DURATION_SHOW_ERROR 3000
|
||||||
#define DURATION_SHOW_MOVES 5000
|
#define DURATION_SHOW_MOVES 500
|
||||||
#define DURATION_WIN_LOSS_TIE 10000
|
#define DURATION_WIN_LOSS_TIE 10000
|
||||||
|
|
||||||
// Updates the state machine, if needed.
|
// Updates the state machine, if needed.
|
||||||
@ -834,6 +925,7 @@ int32_t rock_paper_scissors_app(void* p) {
|
|||||||
joinGameNumber = game_context->data->gameNumber;
|
joinGameNumber = game_context->data->gameNumber;
|
||||||
if(furi_mutex_acquire(game_context->mutex, FuriWaitForever) == FuriStatusOk) {
|
if(furi_mutex_acquire(game_context->mutex, FuriWaitForever) == FuriStatusOk) {
|
||||||
rps_broadcast_join(game_context, joinGameNumber);
|
rps_broadcast_join(game_context, joinGameNumber);
|
||||||
|
rps_state_machine_remote_joined(game_context);
|
||||||
furi_mutex_release(game_context->mutex);
|
furi_mutex_release(game_context->mutex);
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(TAG, "Failed to aquire mutex.");
|
FURI_LOG_E(TAG, "Failed to aquire mutex.");
|
||||||
|