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)