From 99380add06bfdf0b00481eb9bf5dff688ec06486 Mon Sep 17 00:00:00 2001
From: Ian Milan <98004719+DevMilanIan@users.noreply.github.com>
Date: Sat, 6 Aug 2022 21:37:26 -0400
Subject: [PATCH 1/4] Fixes and improvements
Add a visual representation of your lives, a score counter, and prevent NULL pointer dereference upon relaunch
---
applications/arkanoid/arkanoid_game.c | 65 ++++++++++++++++++++-------
1 file changed, 48 insertions(+), 17 deletions(-)
diff --git a/applications/arkanoid/arkanoid_game.c b/applications/arkanoid/arkanoid_game.c
index 419794a10..152bf0fcb 100644
--- a/applications/arkanoid/arkanoid_game.c
+++ b/applications/arkanoid/arkanoid_game.c
@@ -21,7 +21,7 @@ int lives = 3; //Amount of lives
int level = 1; //Current level
unsigned int score = 0; //Score for the game
unsigned int brickCount; //Amount of bricks hit
-int pad, pad2, pad3; //Button press buffer used to stop pause repeating
+int pad1, pad2, pad3; //Button press buffer used to stop pause repeating
int oldpad, oldpad2, oldpad3;
char text[16]; //General string buffer
bool start = false; //If in menu or in game
@@ -115,9 +115,6 @@ void move_ball(Canvas* canvas) {
released = false;
lives--;
- snprintf(text, sizeof(text), "LIVES:%u", lives);
- canvas_draw_str(canvas, 0, 90, text);
-
// arduboy.tunes.tone(175, 250);
if(rand_range(0, 2) == 0) {
dx = 1;
@@ -165,10 +162,7 @@ void move_ball(Canvas* canvas) {
//If A collison has occured
if(topBall <= bottomBrick && bottomBall >= topBrick &&
leftBall <= rightBrick && rightBall >= leftBrick) {
- // Draw score
score += (level * 10);
- snprintf(text, sizeof(text), "SCORE:%u", score);
- canvas_draw_str(canvas, 80, 90, text);
brickCount++;
isHit[row][column] = true;
@@ -209,8 +203,42 @@ void move_ball(Canvas* canvas) {
}
void draw_lives(Canvas* canvas) {
- snprintf(text, sizeof(text), "LIVES:%u", lives);
- canvas_draw_str(canvas, 0, 90, text);
+ if(lives == 3) {
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
+
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12);
+
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 15);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 15);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 16);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 16);
+ } else if(lives == 2) {
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
+
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12);
+ } else {
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
+ canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
+ canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
+ }
+}
+
+void draw_score(Canvas* canvas) {
+ snprintf(text, sizeof(text), "%u", score);
+ canvas_draw_str_aligned(canvas, FLIPPER_LCD_WIDTH - 2, FLIPPER_LCD_HEIGHT - 6, AlignRight, AlignBottom, text);
}
void draw_ball(Canvas* canvas) {
@@ -286,8 +314,9 @@ static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
if(lives > 0) {
draw_paddle(canvas);
-
draw_ball(canvas);
+ draw_score(canvas);
+ draw_lives(canvas);
if(brickCount == ROWS * COLUMNS) {
level++;
@@ -320,6 +349,7 @@ static void arkanoid_update_timer_callback(FuriMessageQueue* event_queue) {
int32_t arkanoid_game_app(void* p) {
UNUSED(p);
+ int32_t return_code = 0;
// Set random seed from interrupts
srand(DWT->CYCCNT);
@@ -331,8 +361,8 @@ int32_t arkanoid_game_app(void* p) {
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, arkanoid_state, sizeof(ArkanoidState))) {
FURI_LOG_E(TAG, "Cannot create mutex\r\n");
- free(arkanoid_state);
- return 255;
+ return_code = 255;
+ goto free_and_exit;
}
// Set system callbacks
@@ -401,15 +431,16 @@ int32_t arkanoid_game_app(void* p) {
view_port_update(view_port);
release_mutex(&state_mutex, arkanoid_state);
}
-
furi_timer_free(timer);
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close("gui");
view_port_free(view_port);
- furi_message_queue_free(event_queue);
delete_mutex(&state_mutex);
- free(arkanoid_state);
- return 0;
-}
\ No newline at end of file
+free_and_exit:
+ free(arkanoid_state);
+ furi_message_queue_free(event_queue);
+
+ return return_code;
+}
From 044338b8f2dc9cbcd5acedea7776679b9f738f14 Mon Sep 17 00:00:00 2001
From: MX <10697207+xMasterX@users.noreply.github.com>
Date: Sun, 7 Aug 2022 09:59:03 +0300
Subject: [PATCH 2/4] make arkanoid (not) great again
and small changes for other games
---
.github/CODEOWNERS | 91 -----
.github/ISSUE_TEMPLATE/01_bug_report.yml | 85 ++--
.github/ISSUE_TEMPLATE/02_enhancements.yml | 35 +-
.github/ISSUE_TEMPLATE/03_feature_request.yml | 41 +-
.github/ISSUE_TEMPLATE/config.yml | 9 +-
applications/arkanoid/application.fam | 2 +-
applications/arkanoid/arkanoid_game.c | 372 +++++++++---------
applications/snake_game/snake_game.c | 22 +-
applications/tetris_game/application.fam | 2 +-
9 files changed, 294 insertions(+), 365 deletions(-)
delete mode 100644 .github/CODEOWNERS
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 71acb5f14..000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,91 +0,0 @@
-# Who owns all the fish by default
-* @skotopes @DrZlo13 @hedger
-
-# Apps
-/applications/about/ @skotopes @DrZlo13 @hedger
-/applications/accessor/ @skotopes @DrZlo13 @hedger
-/applications/archive/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/bad_usb/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/bt/ @skotopes @DrZlo13 @hedger @gornekich
-/applications/cli/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/crypto/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/debug_tools/ @skotopes @DrZlo13 @hedger
-/applications/desktop/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/dialogs/ @skotopes @DrZlo13 @hedger
-/applications/dolphin/ @skotopes @DrZlo13 @hedger
-/applications/gpio/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/gui/ @skotopes @DrZlo13 @hedger
-/applications/ibutton/ @skotopes @DrZlo13 @hedger @gsurkov
-/applications/infrared/ @skotopes @DrZlo13 @hedger @gsurkov
-/applications/infrared_monitor/ @skotopes @DrZlo13 @hedger @gsurkov
-/applications/input/ @skotopes @DrZlo13 @hedger
-/applications/lfrfid/ @skotopes @DrZlo13 @hedger
-/applications/lfrfid_debug/ @skotopes @DrZlo13 @hedger
-/applications/loader/ @skotopes @DrZlo13 @hedger
-/applications/music_player/ @skotopes @DrZlo13 @hedger
-/applications/nfc/ @skotopes @DrZlo13 @hedger @gornekich
-/applications/notification/ @skotopes @DrZlo13 @hedger
-/applications/power/ @skotopes @DrZlo13 @hedger
-/applications/rpc/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/snake_game/ @skotopes @DrZlo13 @hedger
-/applications/storage/ @skotopes @DrZlo13 @hedger
-/applications/storage_settings/ @skotopes @DrZlo13 @hedger
-/applications/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm
-/applications/system/ @skotopes @DrZlo13 @hedger
-/applications/u2f/ @skotopes @DrZlo13 @hedger @nminaylov
-/applications/unit_tests/ @skotopes @DrZlo13 @hedger
-/applications/updater/ @skotopes @DrZlo13 @hedger
-
-# Assets
-/assets/ @skotopes @DrZlo13 @hedger
-
-# Furi Core
-/furi/ @skotopes @DrZlo13 @hedger
-
-# Debug tools and plugins
-/debug/ @skotopes @DrZlo13 @hedger
-
-# Docker
-/docker/ @skotopes @DrZlo13 @hedger @aprosvetova
-/docker-compose.yml @skotopes @DrZlo13 @hedger @aprosvetova
-
-# Documentation
-/documentation/ @skotopes @DrZlo13 @hedger @aprosvetova
-
-# Firmware targets
-/firmware/ @skotopes @DrZlo13 @hedger
-
-# Lib
-/lib/FreeRTOS-Kernel/ @skotopes @DrZlo13 @hedger
-/lib/FreeRTOS-glue/ @skotopes @DrZlo13 @hedger
-/lib/ST25RFAL002/ @skotopes @DrZlo13 @hedger @gornekich
-/lib/STM32CubeWB/ @skotopes @DrZlo13 @hedger @gornekich
-/lib/app-scened-template/ @skotopes @DrZlo13 @hedger
-/lib/callback-connector/ @skotopes @DrZlo13 @hedger
-/lib/digital_signal/ @skotopes @DrZlo13 @hedger @gornekich
-/lib/drivers/ @skotopes @DrZlo13 @hedger
-/lib/fatfs/ @skotopes @DrZlo13 @hedger
-/lib/flipper_format/ @skotopes @DrZlo13 @hedger
-/lib/fnv1a-hash/ @skotopes @DrZlo13 @hedger
-/lib/heatshrink/ @skotopes @DrZlo13 @hedger
-/lib/infrared/ @skotopes @DrZlo13 @hedger @gsurkov
-/lib/libusb_stm32/ @skotopes @DrZlo13 @hedger @nminaylov
-/lib/littlefs/ @skotopes @DrZlo13 @hedger
-/lib/lfs_config.h @skotopes @DrZlo13 @hedger
-/lib/micro-ecc/ @skotopes @DrZlo13 @hedger @nminaylov
-/lib/microtar/ @skotopes @DrZlo13 @hedger
-/lib/mlib/ @skotopes @DrZlo13 @hedger
-/lib/nanopb/ @skotopes @DrZlo13 @hedger
-/lib/nfc/ @skotopes @DrZlo13 @hedger @gornekich
-/lib/one_wire/ @skotopes @DrZlo13 @hedger
-/lib/qrcode/ @skotopes @DrZlo13 @hedger
-/lib/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm
-/lib/toolbox/ @skotopes @DrZlo13 @hedger
-/lib/u8g2/ @skotopes @DrZlo13 @hedger
-/lib/update_util/ @skotopes @DrZlo13 @hedger
-
-# Make tools
-/make/ @skotopes @DrZlo13 @hedger @aprosvetova
-
-# Helper scripts
-/scripts/ @skotopes @DrZlo13 @hedger
diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml
index 844d62c48..a5a8b9828 100644
--- a/.github/ISSUE_TEMPLATE/01_bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml
@@ -1,46 +1,45 @@
name: Bug report
description: File a bug reports regarding the firmware.
-labels: ['bug']
+labels: ["bug"]
body:
-- type: markdown
- attributes:
- value: |
- Thank you for taking the time to fill out an issue, this template is meant for any issues related to the Flipper Zero firmware.
- If you require help with the Flipper zero and its firmware, we ask that you join [our forum](https://forum.flipperzero.one)
-- type: textarea
- id: description
- attributes:
- label: Describe the bug.
- description: "A clear and concise description of what the bug is."
- validations:
- required: true
-- type: textarea
- id: repro
- attributes:
- label: Reproduction
- description: "How can this bug be reproduced?"
- placeholder: |
- 1. Switch on...
- 2. Press button '....'
- 3. Wait for the moon phase
- 4. It burns
- validations:
- required: true
-- type: input
- id: target
- attributes:
- label: Target
- description: Specify the target
- # Target seems to be largely ignored by outside sources.
-- type: textarea
- id: logs
- attributes:
- label: Logs
- description: Attach your debug logs here
- render: Text
- # Avoid rendering as Markdown here.
-- type: textarea
- id: anything-else
- attributes:
- label: Anything else?
- description: Let us know if you have anything else to share.
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to fill out an issue, this template is meant for any issues related to the Flipper Zero unleashed firmware.
+ - type: textarea
+ id: description
+ attributes:
+ label: Describe the bug.
+ description: "A clear and concise description of what the bug is."
+ validations:
+ required: true
+ - type: textarea
+ id: repro
+ attributes:
+ label: Reproduction
+ description: "How can this bug be reproduced?"
+ placeholder: |
+ 1. Switch on...
+ 2. Press button '....'
+ 3. Wait for the moon phase
+ 4. It burns
+ validations:
+ required: true
+ - type: input
+ id: target
+ attributes:
+ label: Target
+ description: Specify the target
+ # Target seems to be largely ignored by outside sources.
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ description: Attach your debug logs here
+ render: Text
+ # Avoid rendering as Markdown here.
+ - type: textarea
+ id: anything-else
+ attributes:
+ label: Anything else?
+ description: Let us know if you have anything else to share.
diff --git a/.github/ISSUE_TEMPLATE/02_enhancements.yml b/.github/ISSUE_TEMPLATE/02_enhancements.yml
index 1768e193c..643d11cfb 100644
--- a/.github/ISSUE_TEMPLATE/02_enhancements.yml
+++ b/.github/ISSUE_TEMPLATE/02_enhancements.yml
@@ -1,21 +1,20 @@
name: Enhancements
description: Suggest improvements for any existing functionality within the firmware.
body:
-- type: markdown
- attributes:
- value: |
- Thank you for taking the time to fill out an issue. This template is meant for feature requests and improvements to already existing functionality.
- If you require help with the Flipper zero and its firmware, we ask that you join [our forum](https://forum.flipperzero.one)
-- type: textarea
- id: proposal
- attributes:
- label: "Describe the enhancement you're suggesting."
- description: |
- Feel free to describe in as much detail as you wish.
- validations:
- required: true
-- type: textarea
- id: anything-else
- attributes:
- label: Anything else?
- description: Let us know if you have anything else to share.
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to fill out an issue. This template is meant for feature requests and improvements to already existing functionality.
+ - type: textarea
+ id: proposal
+ attributes:
+ label: "Describe the enhancement you're suggesting."
+ description: |
+ Feel free to describe in as much detail as you wish.
+ validations:
+ required: true
+ - type: textarea
+ id: anything-else
+ attributes:
+ label: Anything else?
+ description: Let us know if you have anything else to share.
diff --git a/.github/ISSUE_TEMPLATE/03_feature_request.yml b/.github/ISSUE_TEMPLATE/03_feature_request.yml
index 2af114547..91100bce3 100644
--- a/.github/ISSUE_TEMPLATE/03_feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/03_feature_request.yml
@@ -1,24 +1,23 @@
name: Feature Request
description: For feature requests regarding the firmware.
-labels: ['feature request']
+labels: ["feature request"]
body:
-- type: markdown
- attributes:
- value: |
- Thank you for taking the time to fill out an issue, this template is meant for any feature suggestions.
- If you require help with the Flipper zero and its firmware, we ask that you join [our forum](https://forum.flipperzero.one)
-- type: textarea
- id: proposal
- attributes:
- label: "Description of the feature you're suggesting."
- description: |
- Please describe your feature request in as many details as possible.
- - Describe what it should do.
- - Note whetever it is to extend existing functionality or introduce new functionality.
- validations:
- required: true
-- type: textarea
- id: anything-else
- attributes:
- label: Anything else?
- description: Let us know if you have anything else to share.
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to fill out an issue, this template is meant for any feature suggestions.
+ - type: textarea
+ id: proposal
+ attributes:
+ label: "Description of the feature you're suggesting."
+ description: |
+ Please describe your feature request in as many details as possible.
+ - Describe what it should do.
+ - Note whetever it is to extend existing functionality or introduce new functionality.
+ validations:
+ required: true
+ - type: textarea
+ id: anything-else
+ attributes:
+ label: Anything else?
+ description: Let us know if you have anything else to share.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 55ff9d29e..2c7ccdfda 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,8 @@
blank_issues_enabled: true
contact_links:
- - name: Need help?
- url: https://forum.flipperzero.one
- about: For any question regarding on how to use the Flipper Zero and its firmware.
+ - name: Telegram
+ url: https://t.me/flipperzero_unofficial
+ about: Unofficial Telegram chat
+ - name: Discord
+ url: https://discord.gg/58D6E8BtTU
+ about: Unofficial Discord Community
diff --git a/applications/arkanoid/application.fam b/applications/arkanoid/application.fam
index fc7aeee4a..1d43561fd 100644
--- a/applications/arkanoid/application.fam
+++ b/applications/arkanoid/application.fam
@@ -5,6 +5,6 @@ App(
entry_point="arkanoid_game_app",
cdefines=["APP_ARKANOID_GAME"],
requires=["gui"],
- stack_size=1 * 1024,
+ stack_size=3 * 1024,
order=30,
)
diff --git a/applications/arkanoid/arkanoid_game.c b/applications/arkanoid/arkanoid_game.c
index 152bf0fcb..27dd13c24 100644
--- a/applications/arkanoid/arkanoid_game.c
+++ b/applications/arkanoid/arkanoid_game.c
@@ -3,61 +3,53 @@
#include
#include
#include
+#include
+#include
#define TAG "Arkanoid"
-unsigned int COLUMNS = 13; //Columns of bricks
-unsigned int ROWS = 4; //Rows of bricks
-int dx = -1; //Initial movement of ball
-int dy = -1; //Initial movement of ball
-int xb; //Balls starting possition
-int yb; //Balls starting possition
-bool released; //If the ball has been released by the player
-bool paused = false; //If the game has been paused
-int xPaddle; //X position of paddle
-bool isHit[4][13]; //Array of if bricks are hit or not
-bool bounced = false; //Used to fix double bounce glitch
-int lives = 3; //Amount of lives
-int level = 1; //Current level
-unsigned int score = 0; //Score for the game
-unsigned int brickCount; //Amount of bricks hit
-int pad1, pad2, pad3; //Button press buffer used to stop pause repeating
-int oldpad, oldpad2, oldpad3;
-char text[16]; //General string buffer
-bool start = false; //If in menu or in game
-bool initialDraw = false; //If the inital draw has happened
-char initials[3]; //Initials used in high score
-
-//Ball Bounds used in collision detection
-int leftBall;
-int rightBall;
-int topBall;
-int bottomBall;
-
-//Brick Bounds used in collision detection
-int leftBrick;
-int rightBrick;
-int topBrick;
-int bottomBrick;
-
-int tick;
-
#define FLIPPER_LCD_WIDTH 128
#define FLIPPER_LCD_HEIGHT 64
typedef enum { EventTypeTick, EventTypeKey } EventType;
-typedef enum { DirectionUp, DirectionRight, DirectionDown, DirectionLeft } Direction;
-
-typedef enum { GameStatePlaying, GameStateGameOver } GameState;
+typedef struct {
+ //Brick Bounds used in collision detection
+ int leftBrick;
+ int rightBrick;
+ int topBrick;
+ int bottomBrick;
+ bool isHit[4][13]; //Array of if bricks are hit or not
+} BrickState;
typedef struct {
- int x;
- int y;
-} Point;
+ int dx; //Initial movement of ball
+ int dy; //Initial movement of ball
+ int xb; //Balls starting possition
+ int yb; //Balls starting possition
+ bool released; //If the ball has been released by the player
+ //Ball Bounds used in collision detection
+ int leftBall;
+ int rightBall;
+ int topBall;
+ int bottomBall;
+} BallState;
typedef struct {
- GameState game_state;
+ BallState ball_state;
+ BrickState brick_state;
+ NotificationApp* notify;
+ unsigned int COLUMNS; //Columns of bricks
+ unsigned int ROWS; //Rows of bricks
+ bool initialDraw; //If the inital draw has happened
+ int xPaddle; //X position of paddle
+ char text[16]; //General string buffer
+ bool bounced; //Used to fix double bounce glitch
+ int lives; //Amount of lives
+ int level; //Current level
+ unsigned int score; //Score for the game
+ unsigned int brickCount; //Amount of bricks hit
+ int tick; //Tick counter
} ArkanoidState;
typedef struct {
@@ -65,128 +57,128 @@ typedef struct {
InputEvent input;
} GameEvent;
+static const NotificationSequence sequence_short_sound = {
+ &message_note_c5,
+ &message_delay_50,
+ &message_sound_off,
+ NULL,
+};
+
// generate number in range [min,max)
int rand_range(int min, int max) {
int number = min + rand() % (max - min);
return number;
}
-void intro(Canvas* canvas) {
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 46, 0, "Arkanoid");
-
- //arduboy.tunes.tone(987, 160);
- //delay(160);
- //arduboy.tunes.tone(1318, 400);
- //delay(2000);
-}
-
-void move_ball(Canvas* canvas) {
- tick++;
- if(released) {
+void move_ball(Canvas* canvas, ArkanoidState* st) {
+ st->tick++;
+ if(st->ball_state.released) {
//Move ball
- if(abs(dx) == 2) {
- xb += dx / 2;
+ if(abs(st->ball_state.dx) == 2) {
+ st->ball_state.xb += st->ball_state.dx / 2;
// 2x speed is really 1.5 speed
- if(tick % 2 == 0) xb += dx / 2;
+ if(st->tick % 2 == 0) st->ball_state.xb += st->ball_state.dx / 2;
} else {
- xb += dx;
+ st->ball_state.xb += st->ball_state.dx;
}
- yb = yb + dy;
+ st->ball_state.yb = st->ball_state.yb + st->ball_state.dy;
//Set bounds
- leftBall = xb;
- rightBall = xb + 2;
- topBall = yb;
- bottomBall = yb + 2;
+ st->ball_state.leftBall = st->ball_state.xb;
+ st->ball_state.rightBall = st->ball_state.xb + 2;
+ st->ball_state.topBall = st->ball_state.yb;
+ st->ball_state.bottomBall = st->ball_state.yb + 2;
//Bounce off top edge
- if(yb <= 0) {
- yb = 2;
- dy = -dy;
- // arduboy.tunes.tone(523, 250);
+ if(st->ball_state.yb <= 0) {
+ st->ball_state.yb = 2;
+ st->ball_state.dy = -st->ball_state.dy;
}
//Lose a life if bottom edge hit
- if(yb >= FLIPPER_LCD_HEIGHT) {
- canvas_draw_frame(canvas, xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
- xPaddle = 54;
- yb = 60;
- released = false;
- lives--;
+ if(st->ball_state.yb >= FLIPPER_LCD_HEIGHT) {
+ canvas_draw_frame(canvas, st->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
+ st->xPaddle = 54;
+ st->ball_state.yb = 60;
+ st->ball_state.released = false;
+ st->lives--;
- // arduboy.tunes.tone(175, 250);
if(rand_range(0, 2) == 0) {
- dx = 1;
+ st->ball_state.dx = 1;
} else {
- dx = -1;
+ st->ball_state.dx = -1;
}
}
//Bounce off left side
- if(xb <= 0) {
- xb = 2;
- dx = -dx;
- // arduboy.tunes.tone(523, 250);
+ if(st->ball_state.xb <= 0) {
+ st->ball_state.xb = 2;
+ st->ball_state.dx = -st->ball_state.dx;
}
//Bounce off right side
- if(xb >= FLIPPER_LCD_WIDTH - 2) {
- xb = FLIPPER_LCD_WIDTH - 4;
- dx = -dx;
+ if(st->ball_state.xb >= FLIPPER_LCD_WIDTH - 2) {
+ st->ball_state.xb = FLIPPER_LCD_WIDTH - 4;
+ st->ball_state.dx = -st->ball_state.dx;
// arduboy.tunes.tone(523, 250);
}
//Bounce off paddle
- if(xb + 1 >= xPaddle && xb <= xPaddle + 12 && yb + 2 >= FLIPPER_LCD_HEIGHT - 1 &&
- yb <= FLIPPER_LCD_HEIGHT) {
- dy = -dy;
- dx = ((xb - (xPaddle + 6)) / 3); //Applies spin on the ball
- // prevent straight bounce
- if(dx == 0) {
- dx = (rand_range(0, 2) == 1) ? 1 : -1;
+ if(st->ball_state.xb + 1 >= st->xPaddle && st->ball_state.xb <= st->xPaddle + 12 &&
+ st->ball_state.yb + 2 >= FLIPPER_LCD_HEIGHT - 1 &&
+ st->ball_state.yb <= FLIPPER_LCD_HEIGHT) {
+ st->ball_state.dy = -st->ball_state.dy;
+ st->ball_state.dx =
+ ((st->ball_state.xb - (st->xPaddle + 6)) / 3); //Applies spin on the ball
+ // prevent straight bounce, but not prevent roguuemaster from stealing
+ if(st->ball_state.dx == 0) {
+ st->ball_state.dx = (rand_range(0, 2) == 1) ? 1 : -1;
}
- // arduboy.tunes.tone(200, 250);
}
//Bounce off Bricks
- for(unsigned int row = 0; row < ROWS; row++) {
- for(unsigned int column = 0; column < COLUMNS; column++) {
- if(!isHit[row][column]) {
+ for(unsigned int row = 0; row < st->ROWS; row++) {
+ for(unsigned int column = 0; column < st->COLUMNS; column++) {
+ if(!st->brick_state.isHit[row][column]) {
//Sets Brick bounds
- leftBrick = 10 * column;
- rightBrick = 10 * column + 10;
- topBrick = 6 * row + 1;
- bottomBrick = 6 * row + 7;
+ st->brick_state.leftBrick = 10 * column;
+ st->brick_state.rightBrick = 10 * column + 10;
+ st->brick_state.topBrick = 6 * row + 1;
+ st->brick_state.bottomBrick = 6 * row + 7;
//If A collison has occured
- if(topBall <= bottomBrick && bottomBall >= topBrick &&
- leftBall <= rightBrick && rightBall >= leftBrick) {
- score += (level * 10);
+ if(st->ball_state.topBall <= st->brick_state.bottomBrick &&
+ st->ball_state.bottomBall >= st->brick_state.topBrick &&
+ st->ball_state.leftBall <= st->brick_state.rightBrick &&
+ st->ball_state.rightBall >= st->brick_state.leftBrick) {
+ st->score += st->level;
+ // Blink led when we hit some brick
+ notification_message(st->notify, &sequence_short_sound);
+ notification_message(st->notify, &sequence_blink_white_100);
- brickCount++;
- isHit[row][column] = true;
+ st->brickCount++;
+ st->brick_state.isHit[row][column] = true;
canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4);
//Vertical collision
- if(bottomBall > bottomBrick || topBall < topBrick) {
+ if(st->ball_state.bottomBall > st->brick_state.bottomBrick ||
+ st->ball_state.topBall < st->brick_state.topBrick) {
//Only bounce once each ball move
- if(!bounced) {
- dy = -dy;
- yb += dy;
- bounced = true;
- // arduboy.tunes.tone(261, 250);
+ if(!st->bounced) {
+ st->ball_state.dy = -st->ball_state.dy;
+ st->ball_state.yb += st->ball_state.dy;
+ st->bounced = true;
}
}
//Hoizontal collision
- if(leftBall < leftBrick || rightBall > rightBrick) {
+ if(st->ball_state.leftBall < st->brick_state.leftBrick ||
+ st->ball_state.rightBall > st->brick_state.rightBrick) {
//Only bounce once brick each ball move
- if(!bounced) {
- dx = -dx;
- xb += dx;
- bounced = true;
- // arduboy.tunes.tone(261, 250);
+ if(!st->bounced) {
+ st->ball_state.dx = -st->ball_state.dx;
+ st->ball_state.xb += st->ball_state.dx;
+ st->bounced = true;
}
}
}
@@ -195,15 +187,15 @@ void move_ball(Canvas* canvas) {
}
//Reset Bounce
- bounced = false;
+ st->bounced = false;
} else {
//Ball follows paddle
- xb = xPaddle + 5;
+ st->ball_state.xb = st->xPaddle + 5;
}
}
-void draw_lives(Canvas* canvas) {
- if(lives == 3) {
+void draw_lives(Canvas* canvas, ArkanoidState* arkanoid_state) {
+ if(arkanoid_state->lives == 3) {
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
@@ -218,7 +210,7 @@ void draw_lives(Canvas* canvas) {
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 15);
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 16);
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 16);
- } else if(lives == 2) {
+ } else if(arkanoid_state->lives == 2) {
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
@@ -236,98 +228,115 @@ void draw_lives(Canvas* canvas) {
}
}
-void draw_score(Canvas* canvas) {
- snprintf(text, sizeof(text), "%u", score);
- canvas_draw_str_aligned(canvas, FLIPPER_LCD_WIDTH - 2, FLIPPER_LCD_HEIGHT - 6, AlignRight, AlignBottom, text);
+void draw_score(Canvas* canvas, ArkanoidState* arkanoid_state) {
+ snprintf(arkanoid_state->text, sizeof(arkanoid_state->text), "%u", arkanoid_state->score);
+ canvas_draw_str_aligned(
+ canvas,
+ FLIPPER_LCD_WIDTH - 2,
+ FLIPPER_LCD_HEIGHT - 6,
+ AlignRight,
+ AlignBottom,
+ arkanoid_state->text);
}
-void draw_ball(Canvas* canvas) {
- canvas_draw_dot(canvas, xb, yb);
- canvas_draw_dot(canvas, xb + 1, yb);
- canvas_draw_dot(canvas, xb, yb + 1);
- canvas_draw_dot(canvas, xb + 1, yb + 1);
+void draw_ball(Canvas* canvas, ArkanoidState* ast) {
+ canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb);
+ canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb);
+ canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb + 1);
+ canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb + 1);
- move_ball(canvas);
+ move_ball(canvas, ast);
}
-void draw_paddle(Canvas* canvas) {
- canvas_draw_frame(canvas, xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
+void draw_paddle(Canvas* canvas, ArkanoidState* arkanoid_state) {
+ canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
}
-void reset_level(Canvas* canvas) {
+void reset_level(Canvas* canvas, ArkanoidState* arkanoid_state) {
//Undraw paddle
- canvas_draw_frame(canvas, xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
+ canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
//Undraw ball
- canvas_draw_dot(canvas, xb, yb);
- canvas_draw_dot(canvas, xb + 1, yb);
- canvas_draw_dot(canvas, xb, yb + 1);
- canvas_draw_dot(canvas, xb + 1, yb + 1);
+ canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb);
+ canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb);
+ canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb + 1);
+ canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb + 1);
//Alter various variables to reset the game
- xPaddle = 54;
- yb = 60;
- brickCount = 0;
- released = false;
+ arkanoid_state->xPaddle = 54;
+ arkanoid_state->ball_state.yb = 60;
+ arkanoid_state->brickCount = 0;
+ arkanoid_state->ball_state.released = false;
// Reset all brick hit states
- for(unsigned int row = 0; row < ROWS; row++) {
- for(unsigned int column = 0; column < COLUMNS; column++) {
- isHit[row][column] = false;
+ for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) {
+ for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) {
+ arkanoid_state->brick_state.isHit[row][column] = false;
}
}
}
-static void arkanoid_state_init(ArkanoidState* const arkanoid_state) {
+static void arkanoid_state_init(ArkanoidState* arkanoid_state) {
+ // Init notification
+ arkanoid_state->notify = furi_record_open(RECORD_NOTIFICATION);
+
// Set the initial game state
- arkanoid_state->game_state = GameStatePlaying;
+ arkanoid_state->COLUMNS = 13;
+ arkanoid_state->ROWS = 4;
+ arkanoid_state->ball_state.dx = -1;
+ arkanoid_state->ball_state.dy = -1;
+ arkanoid_state->bounced = false;
+ arkanoid_state->lives = 3;
+ arkanoid_state->level = 1;
+ arkanoid_state->score = 0;
+ arkanoid_state->COLUMNS = 13;
+ arkanoid_state->COLUMNS = 13;
// Reset initial state
- initialDraw = false;
+ arkanoid_state->initialDraw = false;
}
static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
- const ArkanoidState* arkanoid_state = acquire_mutex((ValueMutex*)ctx, 25);
+ ArkanoidState* arkanoid_state = acquire_mutex((ValueMutex*)ctx, 25);
if(arkanoid_state == NULL) {
return;
}
//Initial level draw
- if(!initialDraw) {
- initialDraw = true;
+ if(!arkanoid_state->initialDraw) {
+ arkanoid_state->initialDraw = true;
// Set default font for text
- canvas_set_font(canvas, FontPrimary);
+ canvas_set_font(canvas, FontSecondary);
//Draws the new level
- reset_level(canvas);
+ reset_level(canvas, arkanoid_state);
}
//Draws new bricks and resets their values
- for(unsigned int row = 0; row < ROWS; row++) {
- for(unsigned int column = 0; column < COLUMNS; column++) {
- if(!isHit[row][column]) {
+ for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) {
+ for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) {
+ if(!arkanoid_state->brick_state.isHit[row][column]) {
canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4);
}
}
}
- if(lives > 0) {
- draw_paddle(canvas);
- draw_ball(canvas);
- draw_score(canvas);
- draw_lives(canvas);
+ if(arkanoid_state->lives > 0) {
+ draw_paddle(canvas, arkanoid_state);
+ draw_ball(canvas, arkanoid_state);
+ draw_score(canvas, arkanoid_state);
+ draw_lives(canvas, arkanoid_state);
- if(brickCount == ROWS * COLUMNS) {
- level++;
- reset_level(canvas);
+ if(arkanoid_state->brickCount == arkanoid_state->ROWS * arkanoid_state->COLUMNS) {
+ arkanoid_state->level++;
+ reset_level(canvas, arkanoid_state);
}
} else {
- reset_level(canvas);
- initialDraw = false;
- start = false;
- lives = 3;
- score = 0;
+ reset_level(canvas, arkanoid_state);
+ arkanoid_state->initialDraw = false;
+ arkanoid_state->lives = 3;
+ arkanoid_state->score = 0;
}
release_mutex((ValueMutex*)ctx, arkanoid_state);
@@ -375,7 +384,7 @@ int32_t arkanoid_game_app(void* p) {
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 22);
// Open GUI and register view_port
- Gui* gui = furi_record_open("gui");
+ Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
GameEvent event;
@@ -393,13 +402,13 @@ int32_t arkanoid_game_app(void* p) {
processing = false;
break;
case InputKeyRight:
- if(xPaddle < FLIPPER_LCD_WIDTH - 12) {
- xPaddle += 8;
+ if(arkanoid_state->xPaddle < FLIPPER_LCD_WIDTH - 12) {
+ arkanoid_state->xPaddle += 8;
}
break;
case InputKeyLeft:
- if(xPaddle > 0) {
- xPaddle -= 8;
+ if(arkanoid_state->xPaddle > 0) {
+ arkanoid_state->xPaddle -= 8;
}
break;
case InputKeyUp:
@@ -408,24 +417,24 @@ int32_t arkanoid_game_app(void* p) {
break;
case InputKeyOk:
//Release ball if FIRE pressed
- released = true;
+ arkanoid_state->ball_state.released = true;
//Apply random direction to ball on release
if(rand_range(0, 2) == 0) {
- dx = 1;
+ arkanoid_state->ball_state.dx = 1;
} else {
- dx = -1;
+ arkanoid_state->ball_state.dx = -1;
}
//Makes sure the ball heads upwards
- dy = -1;
+ arkanoid_state->ball_state.dy = -1;
break;
}
}
}
} else {
// Event timeout
- FURI_LOG_D(TAG, "osMessageQueue: Event timeout");
+ FURI_LOG_D(TAG, "furi_message_queue: Event timeout");
}
view_port_update(view_port);
@@ -434,7 +443,8 @@ int32_t arkanoid_game_app(void* p) {
furi_timer_free(timer);
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
- furi_record_close("gui");
+ furi_record_close(RECORD_GUI);
+ furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port);
delete_mutex(&state_mutex);
diff --git a/applications/snake_game/snake_game.c b/applications/snake_game/snake_game.c
index 9ad18c632..dfb2716d5 100644
--- a/applications/snake_game/snake_game.c
+++ b/applications/snake_game/snake_game.c
@@ -61,6 +61,15 @@ typedef struct {
InputEvent input;
} SnakeEvent;
+static const NotificationSequence sequence_short_vibro_and_sound = {
+ &message_vibro_on,
+ &message_note_c5,
+ &message_delay_50,
+ &message_sound_off,
+ &message_vibro_off,
+ NULL,
+};
+
static void snake_game_render_callback(Canvas* const canvas, void* ctx) {
const SnakeState* snake_state = acquire_mutex((ValueMutex*)ctx, 25);
if(snake_state == NULL) {
@@ -238,7 +247,7 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex
snake_state->points[0] = next_step;
}
-static void snake_game_process_game_step(SnakeState* const snake_state) {
+static void snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notify) {
if(snake_state->state == GameStateGameOver) {
return;
}
@@ -273,10 +282,8 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y);
if(eatFruit) {
- NotificationApp* notification = furi_record_open("notification");
- notification_message(notification, &sequence_single_vibro);
- notification_message(notification, &sequence_blink_white_100);
- furi_record_close("notification");
+ notification_message(notify, &sequence_short_vibro_and_sound);
+ notification_message(notify, &sequence_blink_white_100);
snake_state->len++;
if(snake_state->len >= MAX_SNAKE_LEN) {
@@ -320,6 +327,8 @@ int32_t snake_game_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+ NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
+
SnakeEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
@@ -354,7 +363,7 @@ int32_t snake_game_app(void* p) {
}
}
} else if(event.type == EventTypeTick) {
- snake_game_process_game_step(snake_state);
+ snake_game_process_game_step(snake_state, notification);
}
} else {
// event timeout
@@ -368,6 +377,7 @@ int32_t snake_game_app(void* p) {
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close(RECORD_GUI);
+ furi_record_close(RECORD_NOTIFICATION);
view_port_free(view_port);
furi_message_queue_free(event_queue);
delete_mutex(&state_mutex);
diff --git a/applications/tetris_game/application.fam b/applications/tetris_game/application.fam
index 406e13eac..496662b30 100644
--- a/applications/tetris_game/application.fam
+++ b/applications/tetris_game/application.fam
@@ -5,6 +5,6 @@ App(
entry_point="tetris_game_app",
cdefines=["APP_TETRIS_GAME"],
requires=["gui"],
- stack_size=1 * 1024,
+ stack_size=2 * 1024,
order=20,
)
From baf0214ed1bede74b3580530caf7bcd3f21b7361 Mon Sep 17 00:00:00 2001
From: MX <10697207+xMasterX@users.noreply.github.com>
Date: Sun, 7 Aug 2022 10:52:03 +0300
Subject: [PATCH 3/4] not use global vars anymore & other fixes
in tictactoe game / snake / arkanoid
---
applications/arkanoid/application.fam | 2 +-
applications/arkanoid/arkanoid_game.c | 2 +-
applications/snake_game/snake_game.c | 2 +-
applications/tictactoe_game/tictactoe_game.c | 306 ++++++++++---------
4 files changed, 173 insertions(+), 139 deletions(-)
diff --git a/applications/arkanoid/application.fam b/applications/arkanoid/application.fam
index 1d43561fd..6c4600b4b 100644
--- a/applications/arkanoid/application.fam
+++ b/applications/arkanoid/application.fam
@@ -5,6 +5,6 @@ App(
entry_point="arkanoid_game_app",
cdefines=["APP_ARKANOID_GAME"],
requires=["gui"],
- stack_size=3 * 1024,
+ stack_size=4 * 1024,
order=30,
)
diff --git a/applications/arkanoid/arkanoid_game.c b/applications/arkanoid/arkanoid_game.c
index 27dd13c24..5260a24e4 100644
--- a/applications/arkanoid/arkanoid_game.c
+++ b/applications/arkanoid/arkanoid_game.c
@@ -154,7 +154,7 @@ void move_ball(Canvas* canvas, ArkanoidState* st) {
st->score += st->level;
// Blink led when we hit some brick
notification_message(st->notify, &sequence_short_sound);
- notification_message(st->notify, &sequence_blink_white_100);
+ //notification_message(st->notify, &sequence_blink_white_100);
st->brickCount++;
st->brick_state.isHit[row][column] = true;
diff --git a/applications/snake_game/snake_game.c b/applications/snake_game/snake_game.c
index dfb2716d5..e247ca367 100644
--- a/applications/snake_game/snake_game.c
+++ b/applications/snake_game/snake_game.c
@@ -283,7 +283,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state, Notifica
bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y);
if(eatFruit) {
notification_message(notify, &sequence_short_vibro_and_sound);
- notification_message(notify, &sequence_blink_white_100);
+ //notification_message(notify, &sequence_blink_white_100);
snake_state->len++;
if(snake_state->len >= MAX_SNAKE_LEN) {
diff --git a/applications/tictactoe_game/tictactoe_game.c b/applications/tictactoe_game/tictactoe_game.c
index d655dd676..0dbe2a5a6 100644
--- a/applications/tictactoe_game/tictactoe_game.c
+++ b/applications/tictactoe_game/tictactoe_game.c
@@ -6,33 +6,28 @@
#define TAG "TicTacToe"
-uint8_t selBoxX;
-uint8_t selBoxY;
-
-uint8_t selX = 2;
-uint8_t selY = 2;
-
-uint16_t scoreX;
-uint16_t scoreO;
-
-char player = 'X';
-
-char field[3][3];
-bool fieldx[3][3];
-
-const uint8_t coords[3] = {6, 27, 48};
-
-bool button_state = false;
-
typedef enum { EventTypeTick, EventTypeKey } EventType;
-typedef enum { DirectionUp, DirectionRight, DirectionDown, DirectionLeft } Direction;
-
-typedef enum { GameStatePlaying, GameStateGameOver } GameState;
-
typedef struct {
- GameState game_state;
FuriTimer* timer;
+ uint8_t selBoxX;
+ uint8_t selBoxY;
+
+ uint8_t selX;
+ uint8_t selY;
+
+ uint16_t scoreX;
+ uint16_t scoreO;
+
+ char player;
+
+ char field[3][3];
+ bool fieldx[3][3];
+
+ uint8_t coords[3];
+
+ bool button_state;
+
} TicTacToeState;
typedef struct {
@@ -49,15 +44,15 @@ void drawCircle(Canvas* const canvas, uint8_t x, uint8_t y) {
canvas_draw_circle(canvas, x + 4, y + 5, 5);
}
-void player_switch() {
- if(player == 'O') {
- player = 'X';
- } else if(player == 'X') {
- player = 'O';
+void player_switch(TicTacToeState* ts) {
+ if(ts->player == 'O') {
+ ts->player = 'X';
+ } else if(ts->player == 'X') {
+ ts->player = 'O';
}
}
-void tictactoe_draw(Canvas* canvas) {
+void tictactoe_draw(Canvas* canvas, TicTacToeState* ts) {
// Draws the game field
canvas_draw_frame(canvas, 0, 0, 64, 64); // frame
canvas_draw_line(canvas, 0, 21, 63, 21); // horizontal line
@@ -68,34 +63,34 @@ void tictactoe_draw(Canvas* canvas) {
// Draws the game field elements (X or O)
for(uint8_t i = 0; i <= 2; i++) {
for(uint8_t j = 0; j <= 2; j++) {
- if(field[i][j] == 'O') {
- drawCircle(canvas, coords[i], coords[j]);
- } else if(field[i][j] == 'X') {
- drawCross(canvas, coords[i], coords[j]);
+ if(ts->field[i][j] == 'O') {
+ drawCircle(canvas, ts->coords[i], ts->coords[j]);
+ } else if(ts->field[i][j] == 'X') {
+ drawCross(canvas, ts->coords[i], ts->coords[j]);
}
}
}
// Draws the selection box
- if(selX == 1) {
- selBoxX = 1;
- } else if(selX == 2) {
- selBoxX = 22;
- } else if(selX == 3) {
- selBoxX = 43;
+ if(ts->selX == 1) {
+ ts->selBoxX = 1;
+ } else if(ts->selX == 2) {
+ ts->selBoxX = 22;
+ } else if(ts->selX == 3) {
+ ts->selBoxX = 43;
}
- if(selY == 1) {
- selBoxY = 1;
- } else if(selY == 2) {
- selBoxY = 22;
- } else if(selY == 3) {
- selBoxY = 43;
+ if(ts->selY == 1) {
+ ts->selBoxY = 1;
+ } else if(ts->selY == 2) {
+ ts->selBoxY = 22;
+ } else if(ts->selY == 3) {
+ ts->selBoxY = 43;
}
canvas_set_color(canvas, ColorBlack);
- canvas_draw_frame(canvas, selBoxX, selBoxY, 20, 20);
- canvas_draw_frame(canvas, selBoxX + 1, selBoxY + 1, 18, 18);
+ canvas_draw_frame(canvas, ts->selBoxX, ts->selBoxY, 20, 20);
+ canvas_draw_frame(canvas, ts->selBoxX + 1, ts->selBoxY + 1, 18, 18);
// Draws the sidebar
canvas_set_font(canvas, FontPrimary);
@@ -103,105 +98,112 @@ void tictactoe_draw(Canvas* canvas) {
canvas_draw_str(canvas, 75, 24, "X:");
char scoreXBuffer[10];
- snprintf(scoreXBuffer, sizeof(scoreXBuffer), "%d", scoreX);
+ snprintf(scoreXBuffer, sizeof(scoreXBuffer), "%d", ts->scoreX);
canvas_draw_str(canvas, 88, 24, scoreXBuffer);
canvas_draw_str(canvas, 75, 35, "O:");
char scoreOBuffer[10];
- snprintf(scoreOBuffer, sizeof(scoreOBuffer), "%d", scoreO);
+ snprintf(scoreOBuffer, sizeof(scoreOBuffer), "%d", ts->scoreO);
canvas_draw_str(canvas, 88, 35, scoreOBuffer);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 75, 46, "Player:");
- if(player == 'X') {
+ if(ts->player == 'X') {
drawCross(canvas, 93, 50);
- } else if(player == 'O') {
+ } else if(ts->player == 'O') {
drawCircle(canvas, 93, 50);
}
}
-void clear_game_field() {
+void clear_game_field(TicTacToeState* ts) {
// Clears the game field arrays
for(uint8_t i = 0; i <= 2; i++) {
for(uint8_t j = 0; j <= 2; j++) {
- field[i][j] = ' ';
- fieldx[i][j] = false;
+ ts->field[i][j] = ' ';
+ ts->fieldx[i][j] = false;
}
}
- selX = 2; // Centers the selection box on X axis
- selY = 2; // Centers the selection box on Y axis
+ ts->selX = 2; // Centers the selection box on X axis
+ ts->selY = 2; // Centers the selection box on Y axis
}
-void reset_game_data() {
- scoreO = 0;
- scoreX = 0;
- player = 'X';
+void reset_game_data(TicTacToeState* ts) {
+ ts->scoreO = 0;
+ ts->scoreX = 0;
+ ts->player = 'X';
}
-void draw_win(Canvas* canvas, char player) {
+void draw_win(Canvas* canvas, char player, TicTacToeState* ts) {
// Handles the score table
if(player == 'X') {
- scoreX++;
+ ts->scoreX++;
} else if(player == 'O') {
- scoreO++;
+ ts->scoreO++;
}
// Switches the players
- player_switch();
+ player_switch(ts);
// Draws the board with players switched
- tictactoe_draw(canvas);
+ tictactoe_draw(canvas, ts);
// Clear the game field
- clear_game_field();
+ clear_game_field(ts);
// Draw the new board
- tictactoe_draw(canvas);
+ tictactoe_draw(canvas, ts);
}
-static void tictactoe_state_init(TicTacToeState* const tictactoe_state) {
+static void tictactoe_state_init(TicTacToeState* tictactoe_state) {
// Set the initial game state
- tictactoe_state->game_state = GameStatePlaying;
+ tictactoe_state->selX = 2;
+ tictactoe_state->selY = 2;
+ tictactoe_state->player = 'X';
+ tictactoe_state->coords[0] = 6;
+ tictactoe_state->coords[1] = 27;
+ tictactoe_state->coords[2] = 48;
+ tictactoe_state->button_state = false;
- clear_game_field();
+ clear_game_field(tictactoe_state);
- reset_game_data();
+ reset_game_data(tictactoe_state);
}
static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) {
- const TicTacToeState* tictactoe_state = acquire_mutex((ValueMutex*)ctx, 25);
- if(tictactoe_state == NULL) {
+ TicTacToeState* ticst = acquire_mutex((ValueMutex*)ctx, 25);
+ if(ticst == NULL) {
return;
}
- if(selX > 3) {
- selX = 3;
- } else if(selX < 1) {
- selX = 1;
+ if(ticst->selX > 3) {
+ ticst->selX = 3;
+ } else if(ticst->selX < 1) {
+ ticst->selX = 1;
}
- if(selY > 3) {
- selY = 3;
- } else if(selY < 1) {
- selY = 1;
+ if(ticst->selY > 3) {
+ ticst->selY = 3;
+ } else if(ticst->selY < 1) {
+ ticst->selY = 1;
}
// Assigns the game field elements their value (X or O) when the OK button is pressed
- if(button_state) {
- button_state = false;
+ if(ticst->button_state) {
+ ticst->button_state = false;
for(uint8_t i = 0; i <= 2; i++) {
for(uint8_t j = 0; j <= 2; j++) {
- if((selX == i + 1) && (selY == j + 1) && (fieldx[i][j] == false)) {
- if(player == 'X') {
- field[i][j] = 'X';
- fieldx[i][j] = true;
- player_switch();
- } else if(player == 'O') {
- field[i][j] = 'O';
- fieldx[i][j] = true;
- player_switch();
+ if((ticst->selX == i + 1) && (ticst->selY == j + 1) &&
+ (ticst->fieldx[i][j] == false)) {
+ if(ticst->player == 'X') {
+ ticst->field[i][j] = 'X';
+ ticst->fieldx[i][j] = true;
+ player_switch(ticst);
+ } else if(ticst->player == 'O') {
+ ticst->field[i][j] = 'O';
+ ticst->fieldx[i][j] = true;
+ player_switch(ticst);
}
}
}
@@ -209,48 +211,80 @@ static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) {
}
// Checks the game field for winning combinations
- if((field[0][0] == 'X') && (field[1][0] == 'X') && (field[2][0] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[0][1] == 'X') && (field[1][1] == 'X') && (field[2][1] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[0][2] == 'X') && (field[1][2] == 'X') && (field[2][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[0][0] == 'X') && (field[0][1] == 'X') && (field[0][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[1][0] == 'X') && (field[1][1] == 'X') && (field[1][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[2][0] == 'X') && (field[2][1] == 'X') && (field[2][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[0][0] == 'X') && (field[1][1] == 'X') && (field[2][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[2][0] == 'X') && (field[1][1] == 'X') && (field[0][2] == 'X')) {
- draw_win(canvas, 'X');
- } else if((field[0][0] == 'O') && (field[1][0] == 'O') && (field[2][0] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[0][1] == 'O') && (field[1][1] == 'O') && (field[2][1] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[0][2] == 'O') && (field[1][2] == 'O') && (field[2][2] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[0][0] == 'O') && (field[0][1] == 'O') && (field[0][2] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[1][0] == 'O') && (field[1][1] == 'O') && (field[1][2] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[2][0] == 'O') && (field[2][1] == 'O') && (field[2][2] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[0][0] == 'O') && (field[1][1] == 'O') && (field[2][2] == 'O')) {
- draw_win(canvas, 'O');
- } else if((field[2][0] == 'O') && (field[1][1] == 'O') && (field[0][2] == 'O')) {
- draw_win(canvas, 'O');
+ if((ticst->field[0][0] == 'X') && (ticst->field[1][0] == 'X') && (ticst->field[2][0] == 'X')) {
+ draw_win(canvas, 'X', ticst);
} else if(
- (fieldx[0][0] == true) && (fieldx[0][1] == true) && (fieldx[0][2] == true) &&
- (fieldx[1][0] == true) && (fieldx[1][1] == true) && (fieldx[1][2] == true) &&
- (fieldx[2][0] == true) && (fieldx[2][1] == true) && (fieldx[2][2] == true)) {
- draw_win(canvas, 'T');
+ (ticst->field[0][1] == 'X') && (ticst->field[1][1] == 'X') &&
+ (ticst->field[2][1] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[0][2] == 'X') && (ticst->field[1][2] == 'X') &&
+ (ticst->field[2][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[0][0] == 'X') && (ticst->field[0][1] == 'X') &&
+ (ticst->field[0][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[1][0] == 'X') && (ticst->field[1][1] == 'X') &&
+ (ticst->field[1][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[2][0] == 'X') && (ticst->field[2][1] == 'X') &&
+ (ticst->field[2][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[0][0] == 'X') && (ticst->field[1][1] == 'X') &&
+ (ticst->field[2][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[2][0] == 'X') && (ticst->field[1][1] == 'X') &&
+ (ticst->field[0][2] == 'X')) {
+ draw_win(canvas, 'X', ticst);
+ } else if(
+ (ticst->field[0][0] == 'O') && (ticst->field[1][0] == 'O') &&
+ (ticst->field[2][0] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[0][1] == 'O') && (ticst->field[1][1] == 'O') &&
+ (ticst->field[2][1] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[0][2] == 'O') && (ticst->field[1][2] == 'O') &&
+ (ticst->field[2][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[0][0] == 'O') && (ticst->field[0][1] == 'O') &&
+ (ticst->field[0][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[1][0] == 'O') && (ticst->field[1][1] == 'O') &&
+ (ticst->field[1][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[2][0] == 'O') && (ticst->field[2][1] == 'O') &&
+ (ticst->field[2][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[0][0] == 'O') && (ticst->field[1][1] == 'O') &&
+ (ticst->field[2][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->field[2][0] == 'O') && (ticst->field[1][1] == 'O') &&
+ (ticst->field[0][2] == 'O')) {
+ draw_win(canvas, 'O', ticst);
+ } else if(
+ (ticst->fieldx[0][0] == true) && (ticst->fieldx[0][1] == true) &&
+ (ticst->fieldx[0][2] == true) && (ticst->fieldx[1][0] == true) &&
+ (ticst->fieldx[1][1] == true) && (ticst->fieldx[1][2] == true) &&
+ (ticst->fieldx[2][0] == true) && (ticst->fieldx[2][1] == true) &&
+ (ticst->fieldx[2][2] == true)) {
+ draw_win(canvas, 'T', ticst);
}
- tictactoe_draw(canvas);
+ tictactoe_draw(canvas, ticst);
- release_mutex((ValueMutex*)ctx, tictactoe_state);
+ release_mutex((ValueMutex*)ctx, ticst);
}
static void tictactoe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
@@ -310,26 +344,26 @@ int32_t tictactoe_game_app(void* p) {
processing = false;
break;
case InputKeyRight:
- selX++;
+ tictactoe_state->selX++;
break;
case InputKeyLeft:
- selX--;
+ tictactoe_state->selX--;
break;
case InputKeyUp:
- selY--;
+ tictactoe_state->selY--;
break;
case InputKeyDown:
- selY++;
+ tictactoe_state->selY++;
break;
case InputKeyOk:
- button_state = true;
+ tictactoe_state->button_state = true;
break;
}
}
}
} else {
// Event timeout
- FURI_LOG_D(TAG, "osMessageQueue: Event timeout");
+ FURI_LOG_D(TAG, "furi_message_queue: Event timeout");
}
view_port_update(view_port);
From ec12be2c2aea3989c363a5a8f39b64a77aecd586 Mon Sep 17 00:00:00 2001
From: MX <10697207+xMasterX@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:08:26 +0300
Subject: [PATCH 4/4] update docs
---
documentation/HowToInstall.md | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/documentation/HowToInstall.md b/documentation/HowToInstall.md
index c073ee7de..956b8ef65 100644
--- a/documentation/HowToInstall.md
+++ b/documentation/HowToInstall.md
@@ -11,6 +11,20 @@
+## With Web Updater
+
+- Be sure you updated to latest official release before, and verify that microSD card is installed
+- Open latest release page - [Releases](https://github.com/Eng1n33r/flipperzero-firmware/releases/latest)
+- Connect your device and select `Install via Web Updater`
+after that on web updater page - press `Connect` button
+- Press `Install` button
+
+- And wait, if all flashed successfully - you will have all needed assets pre installed
+- Done
+
+
+
+
## With offline update on flipper
### **Replace (CURRENT VERSION) with version that you downloaded from releases**
@@ -59,7 +73,7 @@ then select **`flipper-z-f7-full-(CURRENT VERSION).dfu`**
# After install:
-- ### If you installed using .dfu - unpack files from archive `sd-card-(CURRENT VERSION).zip` to your microSD card
-
+
+- ## [Read instructions how to use plugins and more](https://github.com/Eng1n33r/flipperzero-firmware#instructions)
- ## [How To: Configure UniversalRF Remix App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/UniRFRemix.md)