mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-23 05:24:46 -07:00
code formatted
This commit is contained in:
@@ -22,35 +22,24 @@ typedef struct Point {
|
||||
|
||||
// Rotation logic taken from
|
||||
// https://www.youtube.com/watch?v=yIpk5TJ_uaI
|
||||
typedef enum {
|
||||
OffsetTypeCommon,
|
||||
OffsetTypeI,
|
||||
OffsetTypeO
|
||||
} OffsetType;
|
||||
typedef enum { OffsetTypeCommon, OffsetTypeI, OffsetTypeO } OffsetType;
|
||||
|
||||
// Since we only support rotating clockwise, these are actual translation values,
|
||||
// not values to be subtracted to get translation values
|
||||
|
||||
static const Point rotOffsetTranslation[3][4][5] = {
|
||||
{
|
||||
{ {0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2} },
|
||||
{ {0,0}, {1,0}, {1,1}, {0,-2}, {1,-2} },
|
||||
{ {0,0}, {1,0}, {1,-1}, {0,2}, {1,2} },
|
||||
{ {0,0}, {-1,0}, {-1,1}, {0,-2}, {-1,-2} }
|
||||
},
|
||||
{
|
||||
{ {1,0}, {-1,0}, {2,0}, {-1,1}, {2,-2} },
|
||||
{ {0,1}, {-1,1}, {2,1}, {-1,-1}, {2,2} },
|
||||
{ {-1,0}, {1,0}, {-2,0}, {1,-1}, {-2,2} },
|
||||
{ {0,-1}, {1,-1}, {-2,-1}, {1,1}, {-2,-2} }
|
||||
},
|
||||
{
|
||||
{ {0,-1}, {0,0}, {0,0}, {0,0}, {0,0} },
|
||||
{ {1,0}, {0,0}, {0,0}, {0,0}, {0,0} },
|
||||
{ {0,1}, {0,0}, {0,0}, {0,0}, {0,0} },
|
||||
{ {-1,0}, {0,0}, {0,0}, {0,0}, {0,0} }
|
||||
}
|
||||
};
|
||||
{{{0, 0}, {-1, 0}, {-1, -1}, {0, 2}, {-1, 2}},
|
||||
{{0, 0}, {1, 0}, {1, 1}, {0, -2}, {1, -2}},
|
||||
{{0, 0}, {1, 0}, {1, -1}, {0, 2}, {1, 2}},
|
||||
{{0, 0}, {-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}},
|
||||
{{{1, 0}, {-1, 0}, {2, 0}, {-1, 1}, {2, -2}},
|
||||
{{0, 1}, {-1, 1}, {2, 1}, {-1, -1}, {2, 2}},
|
||||
{{-1, 0}, {1, 0}, {-2, 0}, {1, -1}, {-2, 2}},
|
||||
{{0, -1}, {1, -1}, {-2, -1}, {1, 1}, {-2, -2}}},
|
||||
{{{0, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
{{0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
{{-1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}};
|
||||
|
||||
typedef struct {
|
||||
Point p[4];
|
||||
@@ -60,19 +49,16 @@ typedef struct {
|
||||
|
||||
// Shapes @ spawn locations, rotation point first
|
||||
static Piece shapes[] = {
|
||||
{ .p = {{5, 1}, {4, 0}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // Z
|
||||
{ .p = {{5, 1}, {4, 1}, {5, 0}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // S
|
||||
{ .p = {{5, 1}, {4, 1}, {6, 1}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // L
|
||||
{ .p = {{5, 1}, {4, 0}, {4, 1}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // J
|
||||
{ .p = {{5, 1}, {4, 1}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // T
|
||||
{ .p = {{5, 1}, {4, 1}, {6, 1}, {7, 1}}, .rotIdx = 0, .offsetType = OffsetTypeI }, // I
|
||||
{ .p = {{5, 1}, {5, 0}, {6, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeO } // O
|
||||
{.p = {{5, 1}, {4, 0}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // Z
|
||||
{.p = {{5, 1}, {4, 1}, {5, 0}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // S
|
||||
{.p = {{5, 1}, {4, 1}, {6, 1}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // L
|
||||
{.p = {{5, 1}, {4, 0}, {4, 1}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // J
|
||||
{.p = {{5, 1}, {4, 1}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // T
|
||||
{.p = {{5, 1}, {4, 1}, {6, 1}, {7, 1}}, .rotIdx = 0, .offsetType = OffsetTypeI}, // I
|
||||
{.p = {{5, 1}, {5, 0}, {6, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeO} // O
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GameStatePlaying,
|
||||
GameStateGameOver
|
||||
} GameState;
|
||||
typedef enum { GameStatePlaying, GameStateGameOver } GameState;
|
||||
|
||||
typedef struct {
|
||||
bool playField[FIELD_HEIGHT][FIELD_WIDTH];
|
||||
@@ -106,35 +92,31 @@ static void tetris_game_draw_border(Canvas* const canvas) {
|
||||
static void tetris_game_draw_playfield(Canvas* const canvas, const TetrisState* tetris_state) {
|
||||
// Playfield: 11 x 24
|
||||
|
||||
for (int y = 0; y < FIELD_HEIGHT; y++) {
|
||||
for (int x = 0; x < FIELD_WIDTH; x++) {
|
||||
if (tetris_state->playField[y][x]) {
|
||||
for(int y = 0; y < FIELD_HEIGHT; y++) {
|
||||
for(int x = 0; x < FIELD_WIDTH; x++) {
|
||||
if(tetris_state->playField[y][x]) {
|
||||
uint16_t xOffset = x * 5;
|
||||
uint16_t yOffset = y * 5;
|
||||
|
||||
canvas_draw_rframe(
|
||||
canvas,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + xOffset,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset - 1,
|
||||
BLOCK_WIDTH,
|
||||
canvas,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + xOffset,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset - 1,
|
||||
BLOCK_WIDTH,
|
||||
BLOCK_HEIGHT,
|
||||
1
|
||||
);
|
||||
1);
|
||||
canvas_draw_dot(
|
||||
canvas,
|
||||
canvas,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1
|
||||
);
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1);
|
||||
canvas_draw_dot(
|
||||
canvas,
|
||||
canvas,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + xOffset + 3,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1
|
||||
);
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1);
|
||||
canvas_draw_dot(
|
||||
canvas,
|
||||
canvas,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2,
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 2
|
||||
);
|
||||
BORDER_OFFSET + MARGIN_OFFSET + yOffset + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,8 +155,8 @@ static void tetris_game_render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 32, 73, AlignCenter, AlignBottom, buffer);
|
||||
}
|
||||
release_mutex((ValueMutex *)ctx, tetris_state);
|
||||
}
|
||||
release_mutex((ValueMutex*)ctx, tetris_state);
|
||||
}
|
||||
|
||||
static void tetris_game_input_callback(InputEvent* input_event, osMessageQueueId_t event_queue) {
|
||||
furi_assert(event_queue);
|
||||
@@ -195,7 +177,7 @@ static void tetris_game_init_state(TetrisState* tetris_state) {
|
||||
}
|
||||
|
||||
static void tetris_game_remove_curr_piece(TetrisState* tetris_state) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
uint8_t x = tetris_state->currPiece.p[i].x;
|
||||
uint8_t y = tetris_state->currPiece.p[i].y;
|
||||
|
||||
@@ -204,7 +186,7 @@ static void tetris_game_remove_curr_piece(TetrisState* tetris_state) {
|
||||
}
|
||||
|
||||
static void tetris_game_render_curr_piece(TetrisState* tetris_state) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
uint8_t x = tetris_state->currPiece.p[i].x;
|
||||
uint8_t y = tetris_state->currPiece.p[i].y;
|
||||
|
||||
@@ -218,7 +200,7 @@ static void tetris_game_rotate_shape(Point currShape[], Point newShape[]) {
|
||||
newShape[i] = currShape[i];
|
||||
}
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
for(int i = 1; i < 4; i++) {
|
||||
int8_t relX = currShape[i].x - currShape[0].x;
|
||||
int8_t relY = currShape[i].y - currShape[0].y;
|
||||
|
||||
@@ -239,19 +221,20 @@ static void tetris_game_apply_kick(Point points[], Point kick) {
|
||||
}
|
||||
|
||||
static bool tetris_game_is_valid_pos(TetrisState* tetris_state, Point* shape) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if(shape[i].x < 0 || shape[i].x > (FIELD_WIDTH - 1) || tetris_state->playField[shape[i].y][shape[i].x] == true) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(shape[i].x < 0 || shape[i].x > (FIELD_WIDTH - 1) ||
|
||||
tetris_state->playField[shape[i].y][shape[i].x] == true) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tetris_game_try_rotation(TetrisState* tetris_state, Piece *newPiece) {
|
||||
static void tetris_game_try_rotation(TetrisState* tetris_state, Piece* newPiece) {
|
||||
uint8_t currRotIdx = tetris_state->currPiece.rotIdx;
|
||||
|
||||
Point *rotatedShape = malloc(sizeof(Point) * 4);
|
||||
Point *kickedShape = malloc(sizeof(Point) * 4);
|
||||
Point* rotatedShape = malloc(sizeof(Point) * 4);
|
||||
Point* kickedShape = malloc(sizeof(Point) * 4);
|
||||
|
||||
memcpy(rotatedShape, &tetris_state->currPiece.p, sizeof(tetris_state->currPiece.p));
|
||||
|
||||
@@ -259,7 +242,8 @@ static void tetris_game_try_rotation(TetrisState* tetris_state, Piece *newPiece)
|
||||
|
||||
for(int i = 0; i < 5; i++) {
|
||||
memcpy(kickedShape, rotatedShape, (sizeof(Point) * 4));
|
||||
tetris_game_apply_kick(kickedShape, rotOffsetTranslation[newPiece->offsetType][currRotIdx][i]);
|
||||
tetris_game_apply_kick(
|
||||
kickedShape, rotOffsetTranslation[newPiece->offsetType][currRotIdx][i]);
|
||||
|
||||
if(tetris_game_is_valid_pos(tetris_state, kickedShape)) {
|
||||
memcpy(&newPiece->p, kickedShape, sizeof(newPiece->p));
|
||||
@@ -273,13 +257,13 @@ static void tetris_game_try_rotation(TetrisState* tetris_state, Piece *newPiece)
|
||||
|
||||
static bool tetris_game_row_is_line(bool row[]) {
|
||||
for(int i = 0; i < FIELD_WIDTH; i++) {
|
||||
if(row[i] == false)
|
||||
return false;
|
||||
if(row[i] == false) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tetris_game_check_for_lines(TetrisState* tetris_state, uint8_t* lines, uint8_t* numLines) {
|
||||
static void
|
||||
tetris_game_check_for_lines(TetrisState* tetris_state, uint8_t* lines, uint8_t* numLines) {
|
||||
for(int i = 0; i < FIELD_HEIGHT; i++) {
|
||||
if(tetris_game_row_is_line(tetris_state->playField[i])) {
|
||||
*(lines++) = i;
|
||||
@@ -289,9 +273,9 @@ static void tetris_game_check_for_lines(TetrisState* tetris_state, uint8_t* line
|
||||
}
|
||||
|
||||
static bool tetris_game_piece_at_bottom(TetrisState* tetris_state, Piece* newPiece) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Point *pos = (Point *)&newPiece->p;
|
||||
if (pos[i].y >= FIELD_HEIGHT || tetris_state->playField[pos[i].y][pos[i].x] == true) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
Point* pos = (Point*)&newPiece->p;
|
||||
if(pos[i].y >= FIELD_HEIGHT || tetris_state->playField[pos[i].y][pos[i].x] == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -305,9 +289,9 @@ static void tetris_game_update_timer_callback(osMessageQueueId_t event_queue) {
|
||||
osMessageQueuePut(event_queue, &event, 0, osWaitForever);
|
||||
}
|
||||
|
||||
static void tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece, bool wasDownMove) {
|
||||
if(tetris_state->gameState == GameStateGameOver)
|
||||
return;
|
||||
static void
|
||||
tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece, bool wasDownMove) {
|
||||
if(tetris_state->gameState == GameStateGameOver) return;
|
||||
|
||||
tetris_game_remove_curr_piece(tetris_state);
|
||||
|
||||
@@ -317,20 +301,20 @@ static void tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece,
|
||||
|
||||
tetris_game_render_curr_piece(tetris_state);
|
||||
uint8_t numLines = 0;
|
||||
uint8_t lines[] = { 0,0,0,0 };
|
||||
uint8_t lines[] = {0, 0, 0, 0};
|
||||
|
||||
tetris_game_check_for_lines(tetris_state, lines, &numLines);
|
||||
if(numLines > 0) {
|
||||
for(int i = 0; i < numLines; i++) {
|
||||
|
||||
// zero out row
|
||||
for(int j = 0; j < FIELD_WIDTH; j++) {
|
||||
tetris_state->playField[lines[i]][j] = false;
|
||||
}
|
||||
// move all above rows down
|
||||
for(int k = lines[i]; k >= 0 ; k--) {
|
||||
for(int k = lines[i]; k >= 0; k--) {
|
||||
for(int m = 0; m < FIELD_WIDTH; m++) {
|
||||
tetris_state->playField[k][m] = (k == 0) ? false : tetris_state->playField[k-1][m];
|
||||
tetris_state->playField[k][m] =
|
||||
(k == 0) ? false : tetris_state->playField[k - 1][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,7 +344,6 @@ static void tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece,
|
||||
tetris_game_render_curr_piece(tetris_state);
|
||||
}
|
||||
|
||||
|
||||
int32_t tetris_game_app() {
|
||||
srand(DWT->CYCCNT);
|
||||
|
||||
@@ -392,12 +375,13 @@ int32_t tetris_game_app() {
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
tetris_state->timer = osTimerNew(tetris_game_update_timer_callback, osTimerPeriodic, event_queue, NULL);
|
||||
tetris_state->timer =
|
||||
osTimerNew(tetris_game_update_timer_callback, osTimerPeriodic, event_queue, NULL);
|
||||
tetris_game_init_state(tetris_state);
|
||||
|
||||
TetrisEvent event;
|
||||
|
||||
Piece *newPiece = malloc(sizeof(Piece));
|
||||
Piece* newPiece = malloc(sizeof(Piece));
|
||||
uint8_t downRepeatCounter = 0;
|
||||
|
||||
for(bool processing = true; processing;) {
|
||||
@@ -411,8 +395,8 @@ int32_t tetris_game_app() {
|
||||
|
||||
if(!furi_hal_gpio_read(&gpio_button_right)) {
|
||||
if(downRepeatCounter > 3) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].y += 1;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].y += 1;
|
||||
}
|
||||
downRepeatCounter = 0;
|
||||
wasDownMove = true;
|
||||
@@ -423,19 +407,20 @@ int32_t tetris_game_app() {
|
||||
|
||||
if(event_status == osOK) {
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypePress || event.input.type == InputTypeLong || event.input.type == InputTypeRepeat) {
|
||||
if(event.input.type == InputTypePress || event.input.type == InputTypeLong ||
|
||||
event.input.type == InputTypeRepeat) {
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyRight:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].x += 1;
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].x -= 1;
|
||||
}
|
||||
break;
|
||||
@@ -457,8 +442,8 @@ int32_t tetris_game_app() {
|
||||
// TODO: This is inverted. it returns true when the button is not pressed.
|
||||
// see macro in input.c and do that
|
||||
if(furi_hal_gpio_read(&gpio_button_right)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].y += 1;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
newPiece->p[i].y += 1;
|
||||
}
|
||||
wasDownMove = true;
|
||||
}
|
||||
@@ -471,7 +456,7 @@ int32_t tetris_game_app() {
|
||||
release_mutex(&state_mutex, tetris_state);
|
||||
}
|
||||
|
||||
osTimerDelete(tetris_state->timer);
|
||||
osTimerDelete(tetris_state->timer);
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
|
||||
Reference in New Issue
Block a user