diff options
author | turnipgod | 2025-03-04 17:14:20 -0500 |
---|---|---|
committer | turnipgod | 2025-03-04 17:14:20 -0500 |
commit | 359c47fa7573ba214f3b2e00a19fe2fd4c90e0d2 (patch) | |
tree | a2a45cefe6352031242d9b2e2fb0754b3ea1f87a | |
parent | 5e08a05586a62e7da5acf07a2ea511fff948b142 (diff) |
some clean-up
-rw-r--r-- | src/main.c | 390 |
1 files changed, 221 insertions, 169 deletions
diff --git a/src/main.c b/src/main.c index 268c53e..2fee6bd 100644 --- a/src/main.c +++ b/src/main.c @@ -15,19 +15,6 @@ #define SOFT_DROP_MULT 4.0 #define LOCK_TICK 0.5 -enum Phases { - GENERATION, - FALL, - LOCK, - PATTERN, - //MARK, - //ITERATE, - //ANIMATE, - //ELIMINATE, - //COMPLETE, - GAME_OVER, -} game_phase; - enum InputResult { NONE = 0, MOVED, @@ -37,21 +24,32 @@ enum InputResult { #include "tetromino.h" struct { - int pos_x; - int pos_y; - int rotation; - int type; -} current_piece; - -struct Color matrix[MATRIX_WIDTH][MATRIX_HEIGHT]; -int piece_queue[TETROMINO_COUNT*2]; -int current_bag = 0; -int current_piece_index = 0; -int hold = 7; -int held = 0; -int game_over = 0; -double phase_time; -double fall_tick; + enum { + GENERATION, + FALL, + LOCK, + PATTERN, + //MARK, + //ITERATE, + //ANIMATE, + //ELIMINATE, + //COMPLETE, + GAME_OVER, + } phase; + struct Color matrix[MATRIX_WIDTH][MATRIX_HEIGHT]; + struct { + int pos_x; + int pos_y; + int rotation; + int type; + } current_piece; + int piece_queue[TETROMINO_COUNT*2]; + int current_piece_index; + int hold_piece; + int held; + double phase_time; + double fall_tick; +} game_state; void draw_block(int x, int y, int width, int height, struct Color color) { @@ -60,14 +58,25 @@ void draw_block(int x, int y, int width, int height, struct Color 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]))) { + int piece = game_state.current_piece.type; + int p_x = game_state.current_piece.pos_x; + int p_y = game_state.current_piece.pos_y; + int rot = game_state.current_piece.rotation; + int c_x; + int c_y; + int i; + int j; + + for (i = 0; i < tetrominos[piece].size; i++) { + for (j = 0; j < tetrominos[piece].size; j++) { + if (tetrominos[piece].directions[rot][j][i] == 1) { + c_x = p_x + i - 1 + x; + c_y = p_y + j - 1 + y; + if (p_x + i - 1 + x >= MATRIX_WIDTH + || p_x + i - 1 + x < 0 + || p_y + j - 1 + y < 0 + || (!ColorIsEqual(BLACK, game_state.matrix[c_x][c_y]) + && !ColorIsEqual(WHITE, game_state.matrix[c_x][c_y]))) { return 1; } } @@ -98,31 +107,31 @@ void render_matrix(void) ,matrix_origin_y + j * BLOCK_SIZE + 1 ,BLOCK_SIZE - 2 ,BLOCK_SIZE - 2 - ,matrix[i][j] + ,game_state.matrix[i][j] ); } } int ghost_y = 0; - if (game_phase == FALL || game_phase == LOCK) { + if (game_state.phase == FALL || game_state.phase == LOCK) { /* draw ghost piece */ 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) { + for (int i = 0; i < tetrominos[game_state.current_piece.type].size; i++) { + for (int j = 0; j < tetrominos[game_state.current_piece.type].size; j++) { + if (tetrominos[game_state.current_piece.type].directions[game_state.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 + (matrix_origin_x + ((game_state.current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 3 + ,(matrix_origin_y + ((game_state.current_piece.pos_y + j + ghost_y) * BLOCK_SIZE)) + 3 ,BLOCK_SIZE - 6 ,BLOCK_SIZE - 6 - ,tetrominos[current_piece.type].color + ,tetrominos[game_state.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 + (matrix_origin_x + ((game_state.current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 4 + ,(matrix_origin_y + ((game_state.current_piece.pos_y + j + ghost_y) * BLOCK_SIZE)) + 4 ,BLOCK_SIZE - 8 ,BLOCK_SIZE - 8 ,BLACK @@ -131,15 +140,15 @@ void render_matrix(void) } } /* 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++) { - if (tetrominos[current_piece.type].directions[current_piece.rotation][j][i] == 1) { + for (int i = 0; i < tetrominos[game_state.current_piece.type].size; i++) { + for (int j = 0; j < tetrominos[game_state.current_piece.type].size; j++) { + if (tetrominos[game_state.current_piece.type].directions[game_state.current_piece.rotation][j][i] == 1) { draw_block( - (matrix_origin_x + ((current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 1 - ,(matrix_origin_y + ((current_piece.pos_y + j - 1) * BLOCK_SIZE)) + 1 + (matrix_origin_x + ((game_state.current_piece.pos_x + i - 1) * BLOCK_SIZE)) + 1 + ,(matrix_origin_y + ((game_state.current_piece.pos_y + j - 1) * BLOCK_SIZE)) + 1 ,BLOCK_SIZE - 2 ,BLOCK_SIZE - 2 - ,tetrominos[current_piece.type].color + ,tetrominos[game_state.current_piece.type].color ); } } @@ -155,18 +164,18 @@ void render_matrix(void) 4*BLOCK_SIZE, BLACK ); - if (hold != 7) { - for (int i = 0; i < tetrominos[hold].size; i++) { - for (int j = 0; j < tetrominos[hold].size; j++) { - if (tetrominos[hold].directions[NORTH][j][i] == 1) { + if (game_state.hold_piece != 7) { + for (int i = 0; i < tetrominos[game_state.hold_piece].size; i++) { + for (int j = 0; j < tetrominos[game_state.hold_piece].size; j++) { + if (tetrominos[game_state.hold_piece].directions[NORTH][j][i] == 1) { draw_block( ((matrix_origin_x - BLOCK_SIZE * 5) + (i * BLOCK_SIZE)) + 1 - + ((hold != I && hold != O)?(BLOCK_SIZE/2):0) + + ((game_state.hold_piece != I && game_state.hold_piece != O)?(BLOCK_SIZE/2):0) ,matrix_origin_y + (MATRIX_HEIGHT/2 * BLOCK_SIZE) + ((j-4) * BLOCK_SIZE) - - ((hold == I)?BLOCK_SIZE/2:0) + - ((game_state.hold_piece == I)?BLOCK_SIZE/2:0) ,BLOCK_SIZE - 2 ,BLOCK_SIZE - 2 - ,tetrominos[hold].color + ,tetrominos[game_state.hold_piece].color ); } } @@ -182,16 +191,17 @@ void render_matrix(void) BLACK ); for (int y = 0; y < 5; y++) { - for (int i = 0; i < tetrominos[piece_queue[(y+current_piece_index)%14]].size; i++) { - for (int j = 0; j < tetrominos[piece_queue[(y+current_piece_index)%14]].size; j++) { - if (tetrominos[piece_queue[(y+current_piece_index)%14]].directions[NORTH][j][i] == 1) { + for (int i = 0; i < tetrominos[game_state.piece_queue[(y+game_state.current_piece_index)%14]].size; i++) { + for (int j = 0; j < tetrominos[game_state.piece_queue[(y+game_state.current_piece_index)%14]].size; j++) { + if (tetrominos[game_state.piece_queue[(y+game_state.current_piece_index)%14]].directions[NORTH][j][i] == 1) { draw_block( (((SCREEN_WIDTH/2 + 1 - (BLOCK_SIZE)) + (i * BLOCK_SIZE)) + 1) + (BLOCK_SIZE * 4) - + ((piece_queue[(y+current_piece_index)%14] != I && piece_queue[(y+current_piece_index)%14] != O)?(BLOCK_SIZE/2):0) - ,((matrix_origin_y + MATRIX_HEIGHT/2 * BLOCK_SIZE - 15 * BLOCK_SIZE) + ((j - 1) * BLOCK_SIZE)) + 1 + ((3 - y) * BLOCK_SIZE * 4) - ((piece_queue[(y+current_piece_index)%14] == I)?BLOCK_SIZE/2:0) + + ((game_state.piece_queue[(y+game_state.current_piece_index)%14] != I && game_state.piece_queue[(y+game_state.current_piece_index)%14] != O)?(BLOCK_SIZE/2):0) + ,((matrix_origin_y + MATRIX_HEIGHT/2 * BLOCK_SIZE - 15 * BLOCK_SIZE) + ((j - 1) * BLOCK_SIZE)) + 1 + ((3 - y) * BLOCK_SIZE * 4) + - ((game_state.piece_queue[(y+game_state.current_piece_index)%14] == I)?BLOCK_SIZE/2:0) ,BLOCK_SIZE - 2 ,BLOCK_SIZE - 2 - ,tetrominos[piece_queue[(y+current_piece_index)%14]].color + ,tetrominos[game_state.piece_queue[(y+game_state.current_piece_index)%14]].color ); } } @@ -201,12 +211,17 @@ void render_matrix(void) void shuffle_bag(int *bag) { - for (int i = 0; i < TETROMINO_COUNT; i++) { + int i; + int r; + int t; + + for (i = 0; i < TETROMINO_COUNT; i++) { bag[i] = i; } - for (int i = 0; i < TETROMINO_COUNT; i++) { - int r = i + rand() / (RAND_MAX / (TETROMINO_COUNT - i) + 1); - int t = bag[r]; + + for (i = 0; i < TETROMINO_COUNT; i++) { + r = i + rand() / (RAND_MAX / (TETROMINO_COUNT - i) + 1); + t = bag[r]; bag[r] = bag[i]; bag[i] = t; } @@ -214,31 +229,32 @@ void shuffle_bag(int *bag) void generation_phase(void) { - if (phase_time < 0.2) { + if (game_state.phase_time < 0.2) { return; } // bag generation - if (current_piece_index == 14) { - shuffle_bag(&(piece_queue[7])); - current_piece_index = 0; + if (game_state.current_piece_index == 14) { + shuffle_bag(&(game_state.piece_queue[7])); + game_state.current_piece_index = 0; } - if (current_piece_index == 7) { - shuffle_bag(piece_queue); + if (game_state.current_piece_index == 7) { + shuffle_bag(game_state.piece_queue); } // set current piece - current_piece.type = piece_queue[current_piece_index++]; - current_piece.rotation = NORTH; - current_piece.pos_x = 4; - current_piece.pos_y = 20; - held = 0; - phase_time = 0.0; + game_state.current_piece.type = + game_state.piece_queue[game_state.current_piece_index++]; + game_state.current_piece.rotation = NORTH; + game_state.current_piece.pos_x = 4; + game_state.current_piece.pos_y = 20; + game_state.held = 0; + game_state.phase_time = 0.0; // blockout lose condition if (is_overlap(0, 0)) { - game_phase = GAME_OVER; + game_state.phase = GAME_OVER; } else { - game_phase = FALL; + game_state.phase = FALL; } } @@ -247,35 +263,34 @@ int rotate_piece(int dir) int *kick_table; int i; int can_rotate = 0; + int piece = game_state.current_piece.type; + int rot = game_state.current_piece.rotation; + int init_rot = game_state.current_piece.rotation; if (dir == 1) { - kick_table = tetrominos[current_piece.type].cw_kick_table[current_piece.rotation]; + kick_table = tetrominos[piece].cw_kick_table[rot]; } else if (dir == -1) { - kick_table = tetrominos[current_piece.type].ccw_kick_table[current_piece.rotation]; + kick_table = tetrominos[piece].ccw_kick_table[rot]; } - current_piece.rotation += dir; - if (current_piece.rotation < 0) { - current_piece.rotation = 3; + rot += dir; + if (rot < 0) { + rot = 3; } else { - current_piece.rotation = current_piece.rotation % 4; + rot = rot % 4; } + game_state.current_piece.rotation = rot; 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]; + game_state.current_piece.pos_x += kick_table[i]; + game_state.current_piece.pos_y += kick_table[i+1]; can_rotate = 1; } } if (!can_rotate) { - current_piece.rotation -= dir; - if (current_piece.rotation < 0) { - current_piece.rotation = 3; - } else { - current_piece.rotation = current_piece.rotation % 4; - } + game_state.current_piece.rotation = init_rot; } return can_rotate; @@ -286,16 +301,24 @@ int move_piece(int dir) if (is_overlap(dir, 0)) { return 0; } - current_piece.pos_x += dir; + game_state.current_piece.pos_x += dir; return 1; } void move_piece_to_matrix(void) { - 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) { - matrix[current_piece.pos_x + i - 1][current_piece.pos_y + j - 1] = tetrominos[current_piece.type].color; + int piece = game_state.current_piece.type; + int rot = game_state.current_piece.rotation; + int x = game_state.current_piece.pos_x; + int y = game_state.current_piece.pos_y; + int i; + int j; + + for (i = 0; i < tetrominos[piece].size; i++) { + for (j = 0; j < tetrominos[piece].size; j++) { + if (tetrominos[piece].directions[rot][j][i] == 1) { + game_state.matrix[x + i - 1][y + j - 1] = + tetrominos[piece].color; } } } @@ -303,26 +326,30 @@ void move_piece_to_matrix(void) void hold_piece(void) { - if (!held) { - if (hold == 7) { - hold = current_piece.type; - current_piece.type = piece_queue[current_piece_index]; - current_piece_index++; - current_piece_index = current_piece_index % 14; + int temp; + + if (!game_state.held) { + if (game_state.hold_piece == 7) { + game_state.hold_piece = game_state.current_piece.type; + game_state.current_piece.type = + game_state.piece_queue[game_state.current_piece_index]; + game_state.current_piece_index++; + game_state.current_piece_index = + game_state.current_piece_index % 14; } else { - int temp = current_piece.type; - current_piece.type = hold; - hold = temp; + temp = game_state.current_piece.type; + game_state.current_piece.type = game_state.hold_piece; + game_state.hold_piece = temp; } - phase_time = 0.0; - game_phase = FALL; - current_piece.rotation = NORTH; - current_piece.pos_x = 4; - current_piece.pos_y = 20; + game_state.phase_time = 0.0; + game_state.phase = FALL; + game_state.current_piece.rotation = NORTH; + game_state.current_piece.pos_x = 4; + game_state.current_piece.pos_y = 20; if (is_overlap(0,0)) { CloseWindow(); } - held = 1; + game_state.held = 1; } } @@ -373,7 +400,7 @@ int handle_input(void) { if (!hard_dropped) { hard_dropped = 1; while (!is_overlap(0, -1)) { - current_piece.pos_y--; + game_state.current_piece.pos_y--; } return HARD_DROPPED; } @@ -382,9 +409,9 @@ int handle_input(void) { } if (IsKeyDown(KEY_S)) { - fall_tick = FALL_TICK / SOFT_DROP_MULT; + game_state.fall_tick = FALL_TICK / SOFT_DROP_MULT; } else { - fall_tick = FALL_TICK; + game_state.fall_tick = FALL_TICK; } if (IsKeyDown(KEY_SPACE)) { @@ -397,15 +424,15 @@ int handle_input(void) { void lock_phase(void) { enum InputResult action = handle_input(); if (action == MOVED) { - phase_time = 0.0; + game_state.phase_time = 0.0; } if (!is_overlap(0, -1)) { - phase_time = 0.0; - game_phase = FALL; - } else if (phase_time >= LOCK_TICK || action == HARD_DROPPED) { + game_state.phase_time = 0.0; + game_state.phase = FALL; + } else if (game_state.phase_time >= LOCK_TICK || action == HARD_DROPPED) { move_piece_to_matrix(); - phase_time = 0.0; - game_phase = PATTERN; + game_state.phase_time = 0.0; + game_state.phase = PATTERN; } } @@ -413,26 +440,30 @@ void fall_phase(void) { enum InputResult action = handle_input(); if (action == HARD_DROPPED) { - phase_time = 0.0; - game_phase = PATTERN; + game_state.phase_time = 0.0; + game_state.phase = PATTERN; } else { if (is_overlap(0, -1)) { - phase_time = 0.0; - game_phase = LOCK; - } else if (phase_time >= fall_tick || action == HARD_DROPPED) { - phase_time = 0.0; - current_piece.pos_y--; + game_state.phase_time = 0.0; + game_state.phase = LOCK; + } else if (game_state.phase_time >= game_state.fall_tick + || action == HARD_DROPPED) { + game_state.phase_time = 0.0; + game_state.current_piece.pos_y--; } } } void clear_line(int line) { - for (int y = line; y < MATRIX_HEIGHT - 1; y++) { - for (int x = 0; x < MATRIX_WIDTH; x++) { - matrix[x][y] = matrix[x][y+1]; - if (ColorIsEqual(matrix[x][y], WHITE) && y < 20) { - matrix[x][y] = BLACK; + int y; + int x; + + for (y = line; y < MATRIX_HEIGHT - 1; y++) { + for (x = 0; x < MATRIX_WIDTH; x++) { + game_state.matrix[x][y] = game_state.matrix[x][y+1]; + if (ColorIsEqual(game_state.matrix[x][y], WHITE) && y < 20) { + game_state.matrix[x][y] = BLACK; } } } @@ -440,13 +471,17 @@ void clear_line(int line) int check_lockout(void) { + int piece = game_state.current_piece.type; + int rot = game_state.current_piece.rotation; + int y = game_state.current_piece.pos_y; int fully_above = 1; - 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_y + j - 1 < 20) { - fully_above = 0; - } + int i; + int j; + + for (i = 0; i < tetrominos[piece].size; i++) { + for (j = 0; j < tetrominos[piece].size; j++) { + if (tetrominos[piece].directions[rot][j][i] == 1) { + if (y + j - 1 < 20) fully_above = 0; } } } @@ -455,17 +490,22 @@ int check_lockout(void) void pattern_phase(void) { + int y; + int x; + int line_full; + if (check_lockout()) { - phase_time = 0.0; - game_phase = GAME_OVER; + game_state.phase_time = 0.0; + game_state.phase = GAME_OVER; return; } move_piece_to_matrix(); - for (int y = 0; y < MATRIX_HEIGHT; y++) { - int line_full = 1; - for (int x = 0; x < MATRIX_WIDTH; x++) { - if (ColorIsEqual(matrix[x][y], BLACK) || ColorIsEqual(matrix[x][y], WHITE)) { + for (y = 0; y < MATRIX_HEIGHT; y++) { + line_full = 1; + for (x = 0; x < MATRIX_WIDTH; x++) { + if (ColorIsEqual(game_state.matrix[x][y], BLACK) + || ColorIsEqual(game_state.matrix[x][y], WHITE)) { line_full = 0; } } @@ -473,14 +513,14 @@ void pattern_phase(void) clear_line(y--); } } - phase_time = 0.0; - game_phase = GENERATION; + game_state.phase_time = 0.0; + game_state.phase = GENERATION; } void game_logic(void) { - phase_time += GetFrameTime(); - switch (game_phase) { + game_state.phase_time += GetFrameTime(); + switch (game_state.phase) { case GENERATION: generation_phase(); break; @@ -494,34 +534,46 @@ void game_logic(void) pattern_phase(); break; case GAME_OVER: - game_over = 1; break; } } -int main(void) +void init(void) { - srand(time(NULL)); - InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "~turnipGod's Tetris"); - SetTargetFPS(60); - + int y; + int x; // set default block colors - for (int y = 0; y < 40; y++) { - for (int x = 0; x < 10; x++) { + for (y = 0; y < 40; y++) { + for (x = 0; x < 10; x++) { if (y < 20) { - matrix[x][y] = BLACK; + game_state.matrix[x][y] = BLACK; } else { - matrix[x][y] = WHITE; + game_state.matrix[x][y] = WHITE; } } } - shuffle_bag(piece_queue); - shuffle_bag(&(piece_queue[7])); - phase_time = 0.0; - game_phase = GENERATION; - while (!WindowShouldClose() && !game_over) { + shuffle_bag(game_state.piece_queue); + shuffle_bag(&(game_state.piece_queue[7])); + game_state.phase_time = 0.0; + game_state.phase = GENERATION; + game_state.hold_piece = 7; + game_state.current_piece_index = 0; + game_state.held = 0; + game_state.fall_tick = FALL_TICK; + +} + +int main(void) +{ + srand(time(NULL)); + InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "~turnipGod's Tetris"); + SetTargetFPS(60); + + init(); + + while (!WindowShouldClose() && game_state.phase != GAME_OVER) { game_logic(); BeginDrawing(); ClearBackground(WHITE); |