1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

make arkanoid (not) great again

and small changes for other games
This commit is contained in:
MX
2022-08-07 09:59:03 +03:00
parent 2210b6b3aa
commit 044338b8f2
9 changed files with 294 additions and 365 deletions

91
.github/CODEOWNERS vendored
View File

@@ -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

View File

@@ -1,20 +1,19 @@
name: Bug report
description: File a bug reports regarding the firmware.
labels: ['bug']
labels: ["bug"]
body:
- type: markdown
- 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
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
- type: textarea
id: repro
attributes:
label: Reproduction
@@ -26,20 +25,20 @@ body:
4. It burns
validations:
required: true
- type: input
- type: input
id: target
attributes:
label: Target
description: Specify the target
# Target seems to be largely ignored by outside sources.
- type: textarea
- type: textarea
id: logs
attributes:
label: Logs
description: Attach your debug logs here
render: Text
# Avoid rendering as Markdown here.
- type: textarea
- type: textarea
id: anything-else
attributes:
label: Anything else?

View File

@@ -1,12 +1,11 @@
name: Enhancements
description: Suggest improvements for any existing functionality within the firmware.
body:
- type: markdown
- 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
- type: textarea
id: proposal
attributes:
label: "Describe the enhancement you're suggesting."
@@ -14,7 +13,7 @@ body:
Feel free to describe in as much detail as you wish.
validations:
required: true
- type: textarea
- type: textarea
id: anything-else
attributes:
label: Anything else?

View File

@@ -1,13 +1,12 @@
name: Feature Request
description: For feature requests regarding the firmware.
labels: ['feature request']
labels: ["feature request"]
body:
- type: markdown
- 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
- type: textarea
id: proposal
attributes:
label: "Description of the feature you're suggesting."
@@ -17,7 +16,7 @@ body:
- Note whetever it is to extend existing functionality or introduce new functionality.
validations:
required: true
- type: textarea
- type: textarea
id: anything-else
attributes:
label: Anything else?

View File

@@ -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

View File

@@ -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,
)

View File

@@ -3,61 +3,53 @@
#include <input/input.h>
#include <stdlib.h>
#include <gui/view.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#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);

View File

@@ -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);

View File

@@ -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,
)