From 4477c1db42b579a441bf0a62bed2f627176f1c76 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 14 Apr 2019 20:10:23 -0400 Subject: add next piece delay for when a line is cleared + cleanup --- core/src/cetris.c | 105 ++++++++++++++++++++++++++++++------------------------ core/src/input.c | 2 +- core/src/matrix.c | 31 +++++++++------- core/src/test.c | 2 +- 4 files changed, 79 insertions(+), 61 deletions(-) (limited to 'core/src') diff --git a/core/src/cetris.c b/core/src/cetris.c index a3f2ded..4e404d6 100644 --- a/core/src/cetris.c +++ b/core/src/cetris.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -16,10 +15,9 @@ /* FUNCTION PROTOTYPES */ -static void init_piece_queue(struct cetris_game* g); -static void shuffle_queue(struct cetris_game* g); -static void set_constants(struct cetris_game* g); -static void add_score(struct cetris_game* g, u8 lines); +static void init_piece_queue(cetris_game* g); +static void shuffle_queue(cetris_game* g); +static void add_score(cetris_game* g, u8 lines); /* LEVEL DROP SPEED VALUES */ @@ -29,34 +27,20 @@ static const u32 level_drop_delay[20] = { /* GAME FUNCTIONS */ -void init_game(struct cetris_game* g) { - srand(time(NULL)); +void init_game(cetris_game* g) { + + /* check for config errors */ + assert(CETRIS_NEXT_PIECE_DELAY >= CETRIS_LINE_CLEAR_DELAY); - memset(g->board, 0, sizeof(slot) * CETRIS_BOARD_X * CETRIS_BOARD_Y); + srand(time(NULL)); #ifdef BUILD_TESTS apply_test_board(g, TSPIN_NO_LINES); #endif - g->tick = 0; - g->next_drop_tick = level_drop_delay[0]; - - g->current_index = 0; + memset(g, 0, sizeof(cetris_game)); - memset(g->held_moves, 0, sizeof(bool) * 7); - g->das_repeat = 0; - g->prev_das_move = 0; - g->das_move_tick = 0; - g->down_move_tick = 0; - - g->lines = 0; - g->level = 1; - g->game_over = false; - - g->tspin = false; - g->mini_tspin = false; - - g->score = 0; + g->level = CETRIS_STARTING_LEVEL; init_piece_queue(g); shuffle_queue(g); @@ -64,34 +48,46 @@ void init_game(struct cetris_game* g) { next_piece(g); } -void init_piece_queue(struct cetris_game* g) { +void init_piece_queue(cetris_game* g) { for (u8 i = 0; i < 7; i++) { g->piece_queue[i].t = i; g->piece_queue[i].c = i + 1; memcpy(g->piece_queue[i].m, default_matrices[i], sizeof(piece_matrix)); g->piece_queue[i].r = INIT; g->piece_queue[i].lock_tick = 0; - g->piece_queue[i].pos = (vec2){CETRIS_INITIAL_X, CETRIS_INITIAL_Y - CETRIS_INITIAL_Y_OFFSET}; + g->piece_queue[i].locked = false; g->piece_queue[i].ghost_y = 0; + g->piece_queue[i].pos = (vec2){CETRIS_INITIAL_X, CETRIS_INITIAL_Y - CETRIS_INITIAL_Y_OFFSET}; } } -void shuffle_queue(struct cetris_game* g) { +void shuffle_queue(cetris_game* g) { for (u8 i = 0; i < 7; i++) { - struct tetrimino t = g->piece_queue[i]; + tetrimino t = g->piece_queue[i]; u8 rand_index = rand() % 7; g->piece_queue[i] = g->piece_queue[rand_index]; g->piece_queue[rand_index] = t; } } -void update_game_tick(struct cetris_game* g) { +void update_game_tick(cetris_game* g) { if (g->game_over) return; + g->tick++; + + if (g->next_piece_tick && g->tick >= g->next_piece_tick) { + next_piece(g); + } + + if (g->next_piece_tick) return; + bool did_move = false; if (g->tick >= g->next_drop_tick || !g->next_drop_tick) { - if (g->next_drop_tick) move_current(g, DOWN); - did_move = true; + if (g->next_drop_tick) { + move_current(g, DOWN); + did_move = true; + } + if (g->level <= 20) { g->next_drop_tick = g->tick + level_drop_delay[g->level - 1]; } else { @@ -100,10 +96,11 @@ void update_game_tick(struct cetris_game* g) { } /* lock piece if it was hovering for CETRIS_LOCK_DELAY */ - if (g->current.lock_tick && g->current.lock_tick <= g->tick) { + if (!g->next_piece_tick && g->current.lock_tick && g->current.lock_tick <= g->tick) { g->current.pos.y++; if (check_matrix(g, &g->current.m) <= 0) { - next_piece(g); + lock_current(g); + did_move = true; } g->current.pos.y--; g->current.lock_tick = 0; @@ -114,14 +111,11 @@ void update_game_tick(struct cetris_game* g) { } if (did_move) update_board(g); - - g->tick++; } -void next_piece(struct cetris_game* g) { - set_constants(g); - +void next_piece(cetris_game* g) { g->next_drop_tick = 0; + g->next_piece_tick = 0; g->current = g->piece_queue[g->current_index]; if (check_matrix(g, &g->current.m) <= 0) { @@ -133,17 +127,21 @@ void next_piece(struct cetris_game* g) { g->current_index = 0; shuffle_queue(g); } + + update_board(g); } -void set_constants(struct cetris_game* g) { +void lock_current(cetris_game* g) { + g->current.locked = true; for (u8 x = 0; x < CETRIS_BOARD_X; x++) { for (u8 y = 0; y < CETRIS_BOARD_Y; y++) { if (g->board[x][y].occupied) g->board[x][y].constant = 1; } } + update_board(g); } -void make_ghosts(struct cetris_game* g) { +void make_ghosts(cetris_game* g) { u8 orig_y = g->current.pos.y; while (true) { g->current.pos.y++; @@ -155,7 +153,9 @@ void make_ghosts(struct cetris_game* g) { } } -void update_board(struct cetris_game* g) { +void update_board(cetris_game* g) { + if (g->game_over) return; + u8 lines_cleared = 0; for (u8 y = 0; y < CETRIS_BOARD_Y; y++) { bool clear_line = true; @@ -175,15 +175,26 @@ void update_board(struct cetris_game* g) { g->board[x][s + 1] = g->board[x][s]; } } + } + if (clear_line) { + g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY; lines_cleared++; } - if (clear_line) g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY; } make_ghosts(g); set_matrix(g, &g->current.m); assert(lines_cleared <= 4); + + if (g->current.locked && !g->next_piece_tick) { + if (lines_cleared > 0) { + g->next_piece_tick = g->tick + CETRIS_NEXT_PIECE_DELAY; + } else { + next_piece(g); + } + } + if (lines_cleared > 0 || g->tspin || g->mini_tspin) { add_score(g, lines_cleared); if (lines_cleared > 0) { @@ -195,7 +206,7 @@ void update_board(struct cetris_game* g) { /* SCORE FUNCTIONS */ -void add_score(struct cetris_game* g, u8 lines) { +void add_score(cetris_game* g, u8 lines) { if (!g->tspin && !g->mini_tspin) { switch (lines) { case 1: g->score += 100 * g->level; break; @@ -223,7 +234,7 @@ void add_score(struct cetris_game* g, u8 lines) { /* MOVEMENT FUNCTIONS */ -void move_piece(struct cetris_game* g, input_t move) { +void move_piece(cetris_game* g, input_t move) { if (!g->held_moves[move]) { switch (move) { case LEFT: @@ -246,7 +257,7 @@ void move_piece(struct cetris_game* g, input_t move) { g->held_moves[move] = true; } -void stop_holding(struct cetris_game* g, input_t move) { +void stop_holding(cetris_game* g, input_t move) { g->held_moves[move] = false; if (move == RIGHT || move == LEFT) { g->das_move_tick = 0; diff --git a/core/src/input.c b/core/src/input.c index 2904158..65dead1 100644 --- a/core/src/input.c +++ b/core/src/input.c @@ -6,7 +6,7 @@ #include "matrix.h" #include "cetris.h" -bool handle_inputs(struct cetris_game* g) { +bool handle_inputs(cetris_game* g) { if ((g->held_moves[RIGHT] || g->held_moves[LEFT]) && !g->das_move_tick) { if (g->das_repeat == 0) { g->das_move_tick = g->tick + CETRIS_DAS_DELAY; diff --git a/core/src/matrix.c b/core/src/matrix.c index 86e9ad2..caae107 100644 --- a/core/src/matrix.c +++ b/core/src/matrix.c @@ -88,8 +88,8 @@ const vec2 basic_movements[5] = { {0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, USER_DOWN, RIGHT, LEFT }; -void move_current(struct cetris_game* g, input_t move) { - if (g->game_over) return; +void move_current(cetris_game* g, input_t move) { + if (g->game_over || g->next_piece_tick) return; g->current.pos.y += basic_movements[move].y; g->current.pos.x += basic_movements[move].x; @@ -108,7 +108,7 @@ void move_current(struct cetris_game* g, input_t move) { update_board(g); } -i8 check_matrix(struct cetris_game* g, piece_matrix *m) { +i8 check_matrix(cetris_game* g, piece_matrix* m) { for (i8 y = 0; y < 4; y++) { for (i8 x = 0; x < 4; x++) { vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y}; @@ -124,7 +124,7 @@ i8 check_matrix(struct cetris_game* g, piece_matrix *m) { return 1; } -void set_matrix(struct cetris_game *g, piece_matrix *m) { +void set_matrix(cetris_game* g, piece_matrix* m) { for (i8 y = 0; y < 4; y++) { for (i8 x = 0; x < 4; x++) { vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y}; @@ -134,15 +134,17 @@ void set_matrix(struct cetris_game *g, piece_matrix *m) { g->board[r.x][r.y].c = g->current.c; } if (g->current.ghost_y + y >= 0) { - g->board[r.x][g->current.ghost_y + y].ghost = true; + if (r.y != (g->current.ghost_y + y)) { + g->board[r.x][g->current.ghost_y + y].ghost = true; + } } } } } } -void hard_drop(struct cetris_game* g) { - if (g->game_over) return; +void hard_drop(cetris_game* g) { + if (g->game_over || g->next_piece_tick) return; bool drop = false; u8 drop_count = 0; @@ -159,11 +161,11 @@ void hard_drop(struct cetris_game* g) { g->score += 2 * drop_count; // 2 score for each hard-drop'd cell update_board(g); - next_piece(g); + lock_current(g); } -void rotate_matrix(struct cetris_game* g, bool clockwise) { - if (g->game_over) return; +void rotate_matrix(cetris_game* g, bool clockwise) { + if (g->game_over || g->next_piece_tick) return; if (g->current.t == O) return; rstate next = 0; @@ -213,8 +215,11 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) { u8 new_y = (clockwise) ? 2 + (x - 1) : 2 - (x - 1); if (g->current.t == I) { - if (clockwise) new_y--; - else new_x++; + if (clockwise) { + new_y--; + } else { + new_x++; + } } m[new_y][new_x] = 1; @@ -231,8 +236,10 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) { } else { kick = srs_wall_kicks[wall_kick][i]; } + g->current.pos.x += kick.x; g->current.pos.y += kick.y; + if (check_matrix(g, &m) > 0) { set_current = true; if (i > 0) did_kick = true; diff --git a/core/src/test.c b/core/src/test.c index 7db2fe5..bad50d8 100644 --- a/core/src/test.c +++ b/core/src/test.c @@ -47,7 +47,7 @@ u8 tspin_no_lines_board[20][10] = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 } }; -void apply_test_board(struct cetris_game* g, enum tests t) { +void apply_test_board(cetris_game* g, test t) { u8 (*board)[20][10]; switch (t) { case TSPIN: -- cgit v1.2.3-101-g0448