summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c423
1 files changed, 226 insertions, 197 deletions
diff --git a/src/main.c b/src/main.c
index 9ef03f0..fc42c4f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -11,8 +11,8 @@
#define BLOCK_SIZE 25
-#define FALL_TICK 0.2
-#define SOFT_DROP_MULT 4
+#define FALL_TICK 0.3
+#define SOFT_DROP_MULT 4.0
#define LOCK_TICK 0.5
enum Phases {
@@ -20,13 +20,19 @@ enum Phases {
FALL,
LOCK,
PATTERN,
- MARK,
- ITERATE,
- ANIMATE,
- ELIMINATE,
- COMPLETE
+ //MARK,
+ //ITERATE,
+ //ANIMATE,
+ //ELIMINATE,
+ //COMPLETE
} game_phase;
+enum InputResult {
+ NONE = 0,
+ MOVED,
+ HARD_DROPPED
+};
+
#include "tetromino.h"
struct {
@@ -42,8 +48,8 @@ int current_bag = 0;
int current_piece_index = 0;
int hold = 7;
int held = 0;
-int hard_drop = 0;
-double phase_time = 0.0;
+double phase_time;
+double fall_tick;
void draw_block(int x, int y, int width, int height, struct Color color)
{
@@ -95,48 +101,50 @@ void render_matrix(void)
}
}
- /* draw ghost piece */
int ghost_y = 0;
- while(!is_overlap(0, ghost_y)) {
- ghost_y--;
- }
+ if (game_phase == FALL || game_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) {
- 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
- );
+ 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++) {
- 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)) + 1
- ,(matrix_origin_y + ((current_piece.pos_y + j - 1) * BLOCK_SIZE)) + 1
- ,BLOCK_SIZE - 2
- ,BLOCK_SIZE - 2
- ,tetrominos[current_piece.type].color
- );
+ /* 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) {
+ 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
+ ,BLOCK_SIZE - 2
+ ,BLOCK_SIZE - 2
+ ,tetrominos[current_piece.type].color
+ );
+ }
}
}
}
+
/* draw piece hold */
draw_block(
SCREEN_WIDTH/2 + 1 - (BLOCK_SIZE),
@@ -203,6 +211,9 @@ void shuffle_bag(int *bag)
void generation_phase(void)
{
+ if (phase_time < 0.2) {
+ return;
+ }
// bag generation
if (current_piece_index == 14) {
shuffle_bag(&(piece_queue[7]));
@@ -217,14 +228,73 @@ void generation_phase(void)
current_piece.rotation = NORTH;
current_piece.pos_x = 4;
current_piece.pos_y = 20;
- if (is_overlap(0,0)) {
- CloseWindow();
+ held = 0;
+ phase_time = 0.0;
+ game_phase = FALL;
+}
+
+int rotate_piece(int dir)
+{
+ int *kick_table;
+ int i;
+ int can_rotate = 0;
+
+ if (dir == 1) {
+ kick_table = tetrominos[current_piece.type].cw_kick_table[current_piece.rotation];
+ } else if (dir == -1) {
+ kick_table = tetrominos[current_piece.type].ccw_kick_table[current_piece.rotation];
+ }
+
+ current_piece.rotation += dir;
+ if (current_piece.rotation < 0) {
+ current_piece.rotation = 3;
+ } else {
+ current_piece.rotation = current_piece.rotation % 4;
+ }
+
+ 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 (!can_rotate) {
+ current_piece.rotation -= dir;
+ if (current_piece.rotation < 0) {
+ current_piece.rotation = 3;
+ } else {
+ current_piece.rotation = current_piece.rotation % 4;
+ }
+ }
+
+ return can_rotate;
+}
+
+int move_piece(int dir)
+{
+ if (is_overlap(dir, 0)) {
+ return 0;
+ }
+ current_piece.pos_x += dir;
+ return 1;
}
-void handle_hold(void)
+void move_piece_to_matrix(void)
{
- if (IsKeyDown(KEY_SPACE) && !held) {
+ 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;
+ }
+ }
+ }
+}
+
+void hold_piece(void)
+{
+ if (!held) {
if (hold == 7) {
hold = current_piece.type;
current_piece.type = piece_queue[current_piece_index];
@@ -235,6 +305,7 @@ void handle_hold(void)
current_piece.type = hold;
hold = temp;
}
+ phase_time = 0.0;
game_phase = FALL;
current_piece.rotation = NORTH;
current_piece.pos_x = 4;
@@ -246,165 +317,108 @@ void handle_hold(void)
}
}
-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;
- 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;
- }
- rotated_cw = 1;
- }
- if (IsKeyUp(KEY_L)) {
- 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;
- 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;
- }
- rotated_ccw = 1;
- }
- if (IsKeyUp(KEY_J)) {
- rotated_ccw = 0;
+int handle_input(void) {
+ static int moved_l = 0;
+ static int moved_r = 0;
+ static int moved_cw = 0;
+ static int moved_ccw = 0;
+ static int hard_dropped = 0;
+
+ if (IsKeyDown(KEY_A)) {
+ if (!moved_l) {
+ moved_l = move_piece(-1);
+ return MOVED;
}
+ } else {
+ moved_l = 0;
}
-}
-void move_right(void)
-{
- if (is_overlap(1, 0)) {
- return;
- }
- if (game_phase == LOCK) {
- phase_time = 0.0;
+ if (IsKeyDown(KEY_D)) {
+ if (!moved_r) {
+ moved_r = move_piece(+1);
+ return MOVED;
+ }
+ } else {
+ moved_r = 0;
}
- current_piece.pos_x++;
-}
-void move_left(void)
-{
- if (is_overlap(-1, 0)) {
- return;
- }
- if (game_phase == LOCK) {
- phase_time = 0.0;
+ if (IsKeyDown(KEY_L)) {
+ if (!moved_cw) {
+ moved_cw = rotate_piece(+1);
+ return MOVED;
+ }
+ } else {
+ moved_cw = 0;
}
- current_piece.pos_x--;
-}
-void handle_lr(void)
-{
- static int moved_right = 0;
- static int moved_left = 0;
- if (game_phase == FALL || game_phase == LOCK) {
- if (IsKeyDown(KEY_D) && !moved_right) {
- move_right();
- moved_right = 1;
- }
- if (IsKeyUp(KEY_D)) {
- moved_right = 0;
- }
- if (IsKeyDown(KEY_A) && !moved_left) {
- move_left();
- moved_left = 1;
- }
- if (IsKeyUp(KEY_A)) {
- moved_left = 0;
+ if (IsKeyDown(KEY_J)) {
+ if (!moved_ccw) {
+ moved_ccw = rotate_piece(-1);
+ return MOVED;
}
+ } else {
+ moved_ccw = 0;
}
-}
-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;
+ if (IsKeyDown(KEY_W)) {
+ if (!hard_dropped) {
+ hard_dropped = 1;
+ while (!is_overlap(0, -1)) {
+ current_piece.pos_y--;
}
+ return HARD_DROPPED;
}
+ } else {
+ hard_dropped = 0;
}
-}
-void handle_fall(void)
-{
- phase_time += GetFrameTime();
- if (game_phase == FALL) {
- if (!hard_drop && ((!IsKeyDown(KEY_S) && phase_time < FALL_TICK) || phase_time < FALL_TICK / SOFT_DROP_MULT)) {
- return;
- } else {
- phase_time = 0.0;
- }
+ if (IsKeyDown(KEY_S)) {
+ fall_tick = FALL_TICK / SOFT_DROP_MULT;
+ } else {
+ fall_tick = FALL_TICK;
}
- if (is_overlap(0, -1)) {
- game_phase = LOCK;
- } else {
- game_phase = FALL;
- current_piece.pos_y--;
+ if (IsKeyDown(KEY_SPACE)) {
+ hold_piece();
}
- if (is_overlap(0, -1) && (phase_time >= LOCK_TICK || hard_drop)) {
- move_piece_to_matrix();
- generation_phase();
- held = 0;
+ return NONE;
+}
+
+void lock_phase(void) {
+ enum InputResult action = handle_input();
+ if (action == MOVED) {
+ 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) {
+ move_piece_to_matrix();
phase_time = 0.0;
- hard_drop = 0;
- return;
- }
+ game_phase = PATTERN;
+ }
}
-void handle_hard_drop(void)
+void fall_phase(void)
{
- static int dropped = 0;
- 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--;
- }
- }
- if (IsKeyUp(KEY_W)) {
- dropped = 0;
+ enum InputResult action = handle_input();
+ if (action == HARD_DROPPED) {
+ phase_time = 0.0;
+ game_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--;
}
}
}
-void clear_line(int line) {
+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];
@@ -415,8 +429,9 @@ void clear_line(int line) {
}
}
-void handle_line_clears(void)
+void pattern_phase(void)
{
+ move_piece_to_matrix();
for (int y = 0; y < MATRIX_HEIGHT; y++) {
int line_full = 1;
for (int x = 0; x < MATRIX_WIDTH; x++) {
@@ -425,9 +440,30 @@ void handle_line_clears(void)
}
}
if (line_full) {
- clear_line(y);
+ clear_line(y--);
}
}
+ phase_time = 0.0;
+ game_phase = GENERATION;
+}
+
+void game_logic(void)
+{
+ phase_time += GetFrameTime();
+ switch (game_phase) {
+ case GENERATION:
+ generation_phase();
+ break;
+ case FALL:
+ fall_phase();
+ break;
+ case LOCK:
+ lock_phase();
+ break;
+ case PATTERN:
+ pattern_phase();
+ break;
+ }
}
int main(void)
@@ -436,30 +472,23 @@ int main(void)
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "~turnipGod's Tetris");
- // set all blocks to white
+ // set default block colors
for (int y = 0; y < 40; y++) {
for (int x = 0; x < 10; x++) {
- matrix[x][y] = WHITE;
- }
- }
-
- for (int y = 0; y < 20; y++) {
- for (int x = 0; x < 10; x++) {
- matrix[x][y] = BLACK;
+ if (y < 20) {
+ matrix[x][y] = BLACK;
+ } else {
+ matrix[x][y] = WHITE;
+ }
}
}
- game_phase = FALL;
shuffle_bag(piece_queue);
shuffle_bag(&(piece_queue[7]));
- generation_phase();
+ phase_time = 0.0;
+ game_phase = GENERATION;
while (!WindowShouldClose()) {
- handle_lr();
- handle_rotate();
- handle_hold();
- handle_hard_drop();
- handle_fall();
- handle_line_clears();
+ game_logic();
BeginDrawing();
ClearBackground(WHITE);
render_matrix();