From 2d3a51877ba45ed5a64d2c9acee3d3300f55c5fa Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 13 Apr 2019 17:12:12 -0400 Subject: general cleanup and add ghost piece for preview --- core/src/cetris.c | 118 +++++++++++++++++++++++++++++++----------------------- core/src/input.c | 12 +++--- core/src/matrix.c | 100 ++++++++++++++++++++++----------------------- core/src/test.c | 4 +- 4 files changed, 128 insertions(+), 106 deletions(-) (limited to 'core/src') diff --git a/core/src/cetris.c b/core/src/cetris.c index 5466327..a3f2ded 100644 --- a/core/src/cetris.c +++ b/core/src/cetris.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -20,6 +19,7 @@ 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); /* LEVEL DROP SPEED VALUES */ @@ -71,7 +71,8 @@ void init_piece_queue(struct cetris_game* g) { 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){3, 20}; // y = 22 - 1 for matrix + g->piece_queue[i].pos = (vec2){CETRIS_INITIAL_X, CETRIS_INITIAL_Y - CETRIS_INITIAL_Y_OFFSET}; + g->piece_queue[i].ghost_y = 0; } } @@ -88,16 +89,20 @@ void update_game_tick(struct cetris_game* g) { if (g->game_over) return; bool did_move = false; - if (g->tick == g->next_drop_tick) { - move_current(g, basic_movements[DOWN]); + if (g->tick >= g->next_drop_tick || !g->next_drop_tick) { + if (g->next_drop_tick) move_current(g, DOWN); did_move = true; - g->next_drop_tick = g->tick + level_drop_delay[g->level - 1]; + if (g->level <= 20) { + g->next_drop_tick = g->tick + level_drop_delay[g->level - 1]; + } else { + g->next_drop_tick = g->tick + level_drop_delay[19]; + } } /* lock piece if it was hovering for CETRIS_LOCK_DELAY */ if (g->current.lock_tick && g->current.lock_tick <= g->tick) { g->current.pos.y++; - if (check_new_matrix(g, g->current.m) <= 0) { + if (check_matrix(g, &g->current.m) <= 0) { next_piece(g); } g->current.pos.y--; @@ -108,16 +113,18 @@ void update_game_tick(struct cetris_game* g) { did_move = true; } - if (did_move) wipe_board(g); + if (did_move) update_board(g); g->tick++; } void next_piece(struct cetris_game* g) { set_constants(g); + + g->next_drop_tick = 0; g->current = g->piece_queue[g->current_index]; - if (check_new_matrix(g, g->current.m) <= 0) { + if (check_matrix(g, &g->current.m) <= 0) { g->game_over = true; } g->current_index++; @@ -136,34 +143,20 @@ void set_constants(struct cetris_game* g) { } } -void add_score(struct cetris_game* g, u8 lines) { - if (!g->tspin && !g->mini_tspin) { - switch (lines) { - case 1: g->score += 100 * g->level; break; - case 2: g->score += 300 * g->level; break; - case 3: g->score += 500 * g->level; break; - case 4: g->score += 800 * g->level; break; - } - } else if (g->tspin) { - switch (lines) { - case 0: g->score += 400 * g->level; break; - case 1: g->score += 800 * g->level; break; - case 2: g->score += 1200 * g->level; break; - case 3: g->score += 1600 * g->level; break; - } - g->tspin = false; - } else if (g->mini_tspin) { - switch (lines) { - case 0: g->score += 100 * g->level; break; - case 1: g->score += 200 * g->level; break; - case 2: g->score += 400 * g->level; break; +void make_ghosts(struct cetris_game* g) { + u8 orig_y = g->current.pos.y; + while (true) { + g->current.pos.y++; + if (check_matrix(g, &g->current.m) <= 0) { + g->current.ghost_y = g->current.pos.y - 1; + g->current.pos.y = orig_y; + break; } - g->mini_tspin = false; } } -void wipe_board(struct cetris_game* g) { - uint32_t lines_cleared = 0; +void update_board(struct cetris_game* g) { + u8 lines_cleared = 0; for (u8 y = 0; y < CETRIS_BOARD_Y; y++) { bool clear_line = true; for (u8 x = 0; x < CETRIS_BOARD_X; x++) { @@ -171,34 +164,60 @@ void wipe_board(struct cetris_game* g) { memset(&g->board[x][y], 0, sizeof(slot)); } - if (g->board[x][y].remove_tick && g->board[x][y].remove_tick <= g->tick) { - memset(&g->board[x][y], 0, sizeof(slot)); - for (i8 s = y - 1; s >= 0; s--) { - g->board[x][s + 1] = g->board[x][s]; - } - } - - if (!g->board[x][y].occupied || g->board[x][y].remove_tick > 0) { + if (!g->board[x][y].occupied || g->board[0][y].remove_tick > 0) { clear_line = false; } } - if (clear_line) { - lines_cleared++; - for (u8 x = 0; x < CETRIS_BOARD_X; x++) { - g->board[x][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY; + // remove tick only tracked on first block of line + if (g->board[0][y].remove_tick && g->board[0][y].remove_tick <= g->tick) { + for (i8 s = y - 1; s >= 0; s--) { + for (u8 x = 0; x < CETRIS_BOARD_X; x++) { + g->board[x][s + 1] = g->board[x][s]; + } } + lines_cleared++; } + if (clear_line) g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY; } - overlay_current_matrix(g); + make_ghosts(g); + set_matrix(g, &g->current.m); assert(lines_cleared <= 4); - if (lines_cleared > 0) { + if (lines_cleared > 0 || g->tspin || g->mini_tspin) { add_score(g, lines_cleared); if (lines_cleared > 0) { g->lines += lines_cleared; - if (g->lines >= (g->level * 10) && g->level <= 20) g->level++; + if (g->lines >= (g->level * 10)) g->level++; + } + } +} + +/* SCORE FUNCTIONS */ + +void add_score(struct cetris_game* g, u8 lines) { + if (!g->tspin && !g->mini_tspin) { + switch (lines) { + case 1: g->score += 100 * g->level; break; + case 2: g->score += 300 * g->level; break; + case 3: g->score += 500 * g->level; break; + case 4: g->score += 800 * g->level; break; } + } else if (g->tspin) { + switch (lines) { + case 0: g->score += 400 * g->level; break; + case 1: g->score += 800 * g->level; break; + case 2: g->score += 1200 * g->level; break; + case 3: g->score += 1600 * g->level; break; + } + g->tspin = false; + } else if (g->mini_tspin) { + switch (lines) { + case 0: g->score += 100 * g->level; break; + case 1: g->score += 200 * g->level; break; + case 2: g->score += 400 * g->level; break; + } + g->mini_tspin = false; } } @@ -210,7 +229,8 @@ void move_piece(struct cetris_game* g, input_t move) { case LEFT: case RIGHT: case DOWN: - move_current(g, basic_movements[move]); + case USER_DOWN: + move_current(g, move); break; case HARD_DROP: hard_drop(g); @@ -231,5 +251,5 @@ void stop_holding(struct cetris_game* g, input_t move) { if (move == RIGHT || move == LEFT) { g->das_move_tick = 0; g->das_repeat = 0; - } else if (move == DOWN) g->down_move_tick = 0; + } else if (move == USER_DOWN) g->down_move_tick = 0; } diff --git a/core/src/input.c b/core/src/input.c index edcd450..2904158 100644 --- a/core/src/input.c +++ b/core/src/input.c @@ -15,7 +15,7 @@ bool handle_inputs(struct cetris_game* g) { } } - if (g->held_moves[DOWN] && !g->down_move_tick) { + if (g->held_moves[USER_DOWN] && !g->down_move_tick) { g->down_move_tick = g->tick + CETRIS_DROP_PERIOD; } @@ -24,14 +24,14 @@ bool handle_inputs(struct cetris_game* g) { if (g->held_moves[RIGHT]) { if (g->prev_das_move == RIGHT || g->das_repeat == 0) g->das_repeat++; else g->das_repeat = 0; - move_current(g, basic_movements[RIGHT]); + move_current(g, RIGHT); g->prev_das_move = RIGHT; } if (g->held_moves[LEFT]) { if (g->prev_das_move == LEFT || g->das_repeat == 0) g->das_repeat++; else g->das_repeat = 0; - move_current(g, basic_movements[LEFT]); + move_current(g, LEFT); g->prev_das_move = LEFT; } @@ -40,12 +40,12 @@ bool handle_inputs(struct cetris_game* g) { } if (g->down_move_tick && g->tick >= g->down_move_tick) { - if (g->held_moves[DOWN]) { - move_current(g, basic_movements[DOWN]); + if (g->held_moves[USER_DOWN]) { + move_current(g, USER_DOWN); + did_move = true; } g->down_move_tick = 0; - did_move = true; } return did_move; } diff --git a/core/src/matrix.c b/core/src/matrix.c index 265fe05..86e9ad2 100644 --- a/core/src/matrix.c +++ b/core/src/matrix.c @@ -84,36 +84,58 @@ const piece_matrix default_matrices[7] = { /* MATRIX MODIFICATION */ -const vec2 basic_movements[4] = { - {0, 0}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, RIGHT, LEFT +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, vec2 offset) { +void move_current(struct cetris_game* g, input_t move) { if (g->game_over) return; - g->current.pos.y += offset.y; - g->current.pos.x += offset.x; + g->current.pos.y += basic_movements[move].y; + g->current.pos.x += basic_movements[move].x; - int32_t check = check_new_matrix(g, g->current.m); + i8 check = check_matrix(g, &g->current.m); if (check <= 0) { - g->current.pos.y -= offset.y; - g->current.pos.x -= offset.x; + g->current.pos.y -= basic_movements[move].y; + g->current.pos.x -= basic_movements[move].x; - if (check == -1 && g->current.lock_tick == 0) { - g->current.lock_tick = g->tick + 30; + if (move == USER_DOWN) g->score++; + if (move == DOWN && check == -1 && !g->current.lock_tick) { + g->current.lock_tick = g->tick + CETRIS_LOCK_DELAY; } } - wipe_board(g); + update_board(g); } -void overlay_current_matrix(struct cetris_game* g) { - for (uint32_t y = 0; y < 4; y++) { - for (uint32_t x = 0; x < 4; x++) { +i8 check_matrix(struct 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}; - if (g->current.m[y][x]) { - g->board[r.x][r.y].occupied = 1; - g->board[r.x][r.y].c = g->current.c; + if (r.y < 0) continue; + if ((*m)[y][x]) { + if (r.x >= CETRIS_BOARD_X || r.x < 0) return 0; + if (r.y >= CETRIS_BOARD_Y) return -1; + if (g->board[r.x][r.y].occupied && + g->board[r.x][r.y].constant) return -1; + } + } + } + return 1; +} + +void set_matrix(struct 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}; + if ((*m)[y][x]) { + if (r.y >= 0) { + g->board[r.x][r.y].occupied = true; + 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; + } } } } @@ -127,17 +149,16 @@ void hard_drop(struct cetris_game* g) { while (!drop) { g->current.pos.y++; drop_count++; - i8 check = check_new_matrix(g, g->current.m); - if (check <= 0) { + if (check_matrix(g, &g->current.m) <= 0) { g->current.pos.y--; drop_count--; drop = true; } } - g->score += 2 * drop_count; // 2 score for each harddrop cell + g->score += 2 * drop_count; // 2 score for each hard-drop'd cell - wipe_board(g); + update_board(g); next_piece(g); } @@ -145,7 +166,7 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) { if (g->game_over) return; if (g->current.t == O) return; - rstate next; + rstate next = 0; u8 wall_kick = 0; switch (g->current.r) { case INIT: @@ -212,7 +233,7 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) { } g->current.pos.x += kick.x; g->current.pos.y += kick.y; - if (check_new_matrix(g, m) > 0) { + if (check_matrix(g, &m) > 0) { set_current = true; if (i > 0) did_kick = true; break; @@ -223,47 +244,28 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) { } if (set_current) { + /* check for tspin */ if (g->current.t == T) { - u8 did_tspin = 1; - for (u8 i = 0; i < 4; i++) { + bool did_tspin = true; + for (int i = 1; i < 5; i++) { g->current.pos.x += basic_movements[i].x; g->current.pos.y += basic_movements[i].y; - if (check_new_matrix(g, m) == 1) - did_tspin = 0; + if (check_matrix(g, &m) == 1) did_tspin = false; g->current.pos.x -= basic_movements[i].x; g->current.pos.y -= basic_movements[i].y; } if (did_tspin) { - if (did_kick) g->mini_tspin = 1; - else g->tspin = 1; + if (did_kick) g->mini_tspin = true; + else g->tspin = true; } } g->current.r = next; memcpy(g->current.m, m, sizeof(piece_matrix)); - wipe_board(g); + update_board(g); } } - -i8 check_new_matrix(struct cetris_game* g, piece_matrix m) { - for (u8 x = 0; x < 4; x++) { - for (u8 y = 0; y < 4; y++) { - vec2 r = (vec2){g->current.pos.x + x, g->current.pos.y + y}; - if (m[y][x]) { - if (r.x > CETRIS_BOARD_X - 1 || r.x < 0) - return 0; - - if (r.y > CETRIS_BOARD_Y - 1 || r.y < 0) - return -1; - - if (g->board[r.x][r.y].occupied && g->board[r.x][r.y].constant) - return -1; - } - } - } - return 1; -} diff --git a/core/src/test.c b/core/src/test.c index e9ce23e..7db2fe5 100644 --- a/core/src/test.c +++ b/core/src/test.c @@ -59,9 +59,9 @@ void apply_test_board(struct cetris_game* g, enum tests t) { default: return; } - for (u8 y = CETRIS_BOARD_VISABLE; y < CETRIS_BOARD_Y; y++) { + for (u8 y = 0; y < CETRIS_BOARD_Y; y++) { for (u8 x = 0; x < 10; x++) { - if ((*board)[y - CETRIS_BOARD_VISABLE][x]) { + if ((*board)[y][x]) { g->board[x][y].occupied = 1; g->board[x][y].constant = 1; g->board[x][y].c = COLOR_I; -- cgit v1.2.3-101-g0448