diff options
author | turnipgod | 2025-03-03 19:56:31 -0500 |
---|---|---|
committer | turnipgod | 2025-03-03 19:56:31 -0500 |
commit | df24be9450f1221eea839b3c64982a0624627970 (patch) | |
tree | dd695633ea45e2acb7c31bb916f30f7cd52b7538 | |
parent | a92899722ff9ef080fb9f6614020003ae9d918da (diff) |
added lockdown timer, added super rotation system piece_queue
-rw-r--r-- | inc/tetromino.h | 86 | ||||
-rw-r--r-- | src/main.c | 125 |
2 files changed, 184 insertions, 27 deletions
diff --git a/inc/tetromino.h b/inc/tetromino.h index 30d55a3..04f21d3 100644 --- a/inc/tetromino.h +++ b/inc/tetromino.h @@ -20,6 +20,8 @@ struct Tetromino { int size; struct Color color; int directions[4][4][4]; + int cw_kick_table[4][10]; + int ccw_kick_table[4][10]; }; struct Tetromino tetrominos[7] = { @@ -52,6 +54,18 @@ struct Tetromino tetrominos[7] = { {0, 1, 0, 0}, {0, 1, 0, 0} } + }, + .cw_kick_table = { + {+0,+0, -2,+0, +1,+0, -2,-1, +1,+2}, + {+0,+0, -1,+0, +2,+0, -1,+2, +2,-1}, + {+0,+0, +2,+0, -1,+0, +2,+1, -1,-2}, + {+0,+0, +1,+0, -2,+0, +1,-2, -2,+1} + }, + .ccw_kick_table = { + {+0,+0, -1,+0, +2,+0, -1,+2, +2,-1}, + {+0,+0, +2,+0, -1,+0, +2,+1, -1,-2}, + {+0,+0, +1,+0, -2,+0, +1,-2, -2,+1}, + {+0,+0, -2,+0, +1,+0, -2,-1, +1,+2} } }, [J] = { @@ -78,6 +92,18 @@ struct Tetromino tetrominos[7] = { {0, 1, 0}, {0, 1, 0} } + }, + .cw_kick_table = { + {+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} + }, + .ccw_kick_table = { + {+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} } }, [L] = { @@ -104,6 +130,18 @@ struct Tetromino tetrominos[7] = { {0, 1, 0}, {1, 1, 0} } + }, + .cw_kick_table = { + {+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} + }, + .ccw_kick_table = { + {+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} } }, [O] = { @@ -130,6 +168,18 @@ struct Tetromino tetrominos[7] = { {0, 1, 1}, {0, 1, 1} } + }, + .cw_kick_table = { + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0} + }, + .ccw_kick_table = { + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0}, + {+0,+0, +0,+0, +0,+0, +0,+0, +0,+0} } }, [S] = { @@ -156,6 +206,18 @@ struct Tetromino tetrominos[7] = { {1, 1, 0}, {1, 0, 0} } + }, + .cw_kick_table = { + {+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} + }, + .ccw_kick_table = { + {+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} } }, [T] = { @@ -182,6 +244,18 @@ struct Tetromino tetrominos[7] = { {1, 1, 0}, {0, 1, 0} } + }, + .cw_kick_table = { + {+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} + }, + .ccw_kick_table = { + {+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} } }, [Z] = { @@ -208,6 +282,18 @@ struct Tetromino tetrominos[7] = { {1, 1, 0}, {0, 1, 0} } + }, + .cw_kick_table = { + {+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} + }, + .ccw_kick_table = { + {+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} } } }; diff --git a/src/main.c b/src/main.c index 82e9e90..9ef03f0 100644 --- a/src/main.c +++ b/src/main.c @@ -12,6 +12,8 @@ #define BLOCK_SIZE 25 #define FALL_TICK 0.2 +#define SOFT_DROP_MULT 4 +#define LOCK_TICK 0.5 enum Phases { GENERATION, @@ -40,12 +42,32 @@ int current_bag = 0; int current_piece_index = 0; int hold = 7; int held = 0; +int hard_drop = 0; +double phase_time = 0.0; void draw_block(int x, int y, int width, int height, struct Color color) { DrawRectangle(x, -y + SCREEN_HEIGHT - height, width, height, color); } +int is_overlap(int x, int y) +{ + for (int i = 0; i < tetrominos[current_piece.type].size; i++) { + for (int j = 0; j < tetrominos[current_piece.type].size; j++) { + if (tetrominos[current_piece.type].directions[current_piece.rotation][j][i] == 1) { + if (current_piece.pos_x + i - 1 + x >= MATRIX_WIDTH + || current_piece.pos_x + i - 1 + x < 0 + || current_piece.pos_y + j - 1 + y < 0 + || (!ColorIsEqual(BLACK, matrix[current_piece.pos_x + i - 1 + x][current_piece.pos_y + j - 1 + y]) + && !ColorIsEqual(WHITE, matrix[current_piece.pos_x + i - 1 + x][current_piece.pos_y + j - 1 + y]))) { + return 1; + } + } + } + } + return 0; +} + void render_matrix(void) { int matrix_origin_x = (SCREEN_WIDTH/2 - (MATRIX_WIDTH * BLOCK_SIZE))/2; @@ -73,6 +95,33 @@ void render_matrix(void) } } + /* draw ghost piece */ + int ghost_y = 0; + while(!is_overlap(0, ghost_y)) { + ghost_y--; + } + + for (int i = 0; i < tetrominos[current_piece.type].size; i++) { + for (int j = 0; j < tetrominos[current_piece.type].size; j++) { + if (tetrominos[current_piece.type].directions[current_piece.rotation][j][i] == 1) { + draw_block( + (matrix_origin_x + ((current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 3 + ,(matrix_origin_y + ((current_piece.pos_y + j + ghost_y) * BLOCK_SIZE)) + 3 + ,BLOCK_SIZE - 6 + ,BLOCK_SIZE - 6 + ,tetrominos[current_piece.type].color + ); + draw_block( + (matrix_origin_x + ((current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 4 + ,(matrix_origin_y + ((current_piece.pos_y + j + ghost_y) * BLOCK_SIZE)) + 4 + ,BLOCK_SIZE - 8 + ,BLOCK_SIZE - 8 + ,BLACK + ); + } + } + } + /* draw current piece */ for (int i = 0; i < tetrominos[current_piece.type].size; i++) { for (int j = 0; j < tetrominos[current_piece.type].size; j++) { @@ -152,24 +201,6 @@ void shuffle_bag(int *bag) } } -int is_overlap(int x, int y) -{ - for (int i = 0; i < tetrominos[current_piece.type].size; i++) { - for (int j = 0; j < tetrominos[current_piece.type].size; j++) { - if (tetrominos[current_piece.type].directions[current_piece.rotation][j][i] == 1) { - if (current_piece.pos_x + i - 1 + x >= MATRIX_WIDTH - || current_piece.pos_x + i - 1 + x < 0 - || current_piece.pos_y + j - 1 + y < 0 - || (!ColorIsEqual(BLACK, matrix[current_piece.pos_x + i - 1 + x][current_piece.pos_y + j - 1 + y]) - && !ColorIsEqual(WHITE, matrix[current_piece.pos_x + i - 1 + x][current_piece.pos_y + j - 1 + y]))) { - return 1; - } - } - } - } - return 0; -} - void generation_phase(void) { // bag generation @@ -204,6 +235,7 @@ void handle_hold(void) current_piece.type = hold; hold = temp; } + game_phase = FALL; current_piece.rotation = NORTH; current_piece.pos_x = 4; current_piece.pos_y = 20; @@ -219,10 +251,24 @@ void handle_rotate(void) static int rotated_cw = 0; static int rotated_ccw = 0; if (game_phase == FALL || game_phase == LOCK) { + int *kick_table; + int can_rotate = 0; + int i; if (IsKeyDown(KEY_L) && !rotated_cw) { + kick_table = tetrominos[current_piece.type].cw_kick_table[current_piece.rotation]; current_piece.rotation++; current_piece.rotation = current_piece.rotation % 4; - if (is_overlap(0, 0)) { + for (i = 0; i < 10 && !can_rotate; i += 2) { + if (!is_overlap(kick_table[i], kick_table[i+1])) { + current_piece.pos_x += kick_table[i]; + current_piece.pos_y += kick_table[i+1]; + can_rotate = 1; + if (game_phase == LOCK) { + phase_time = 0.0; + } + } + } + if (!can_rotate) { current_piece.rotation--; if (current_piece.rotation < 0) current_piece.rotation = 3; } @@ -232,9 +278,20 @@ void handle_rotate(void) rotated_cw = 0; } if (IsKeyDown(KEY_J) && !rotated_ccw) { + kick_table = tetrominos[current_piece.type].ccw_kick_table[current_piece.rotation]; current_piece.rotation--; if (current_piece.rotation < 0) current_piece.rotation = 3; - if (is_overlap(0, 0)) { + for (i = 0; i < 10 && !can_rotate; i += 2) { + if (!is_overlap(kick_table[i], kick_table[i+1])) { + current_piece.pos_x += kick_table[i]; + current_piece.pos_y += kick_table[i+1]; + can_rotate = 1; + if (game_phase == LOCK) { + phase_time = 0.0; + } + } + } + if (!can_rotate) { current_piece.rotation++; current_piece.rotation = current_piece.rotation % 4; } @@ -251,6 +308,9 @@ void move_right(void) if (is_overlap(1, 0)) { return; } + if (game_phase == LOCK) { + phase_time = 0.0; + } current_piece.pos_x++; } @@ -259,6 +319,9 @@ void move_left(void) if (is_overlap(-1, 0)) { return; } + if (game_phase == LOCK) { + phase_time = 0.0; + } current_piece.pos_x--; } @@ -297,10 +360,9 @@ void move_piece_to_matrix(void) void handle_fall(void) { - static double phase_time = 0.0; + phase_time += GetFrameTime(); if (game_phase == FALL) { - phase_time += GetFrameTime(); - if ((!IsKeyDown(KEY_S) && phase_time < FALL_TICK) || phase_time < FALL_TICK * 0.5) { + if (!hard_drop && ((!IsKeyDown(KEY_S) && phase_time < FALL_TICK) || phase_time < FALL_TICK / SOFT_DROP_MULT)) { return; } else { phase_time = 0.0; @@ -308,21 +370,30 @@ void handle_fall(void) } if (is_overlap(0, -1)) { + game_phase = LOCK; + } else { + game_phase = FALL; + current_piece.pos_y--; + } + + if (is_overlap(0, -1) && (phase_time >= LOCK_TICK || hard_drop)) { move_piece_to_matrix(); generation_phase(); held = 0; + game_phase = FALL; + phase_time = 0.0; + hard_drop = 0; return; - } - - current_piece.pos_y--; + } } void handle_hard_drop(void) { static int dropped = 0; - if (game_phase == FALL) { + if (game_phase == FALL || game_phase == LOCK) { if (IsKeyDown(KEY_W) && !dropped) { dropped = 1; + hard_drop = 1; while(!is_overlap(0, -1)) { current_piece.pos_y--; } |