#include "Driver.h" #include "Tetris.h" #include "GameUtil.h" #include "pieces.h" static tetris_t game_container; static uint8_t clean_board[height][width] = { {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,}, {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,}, {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,}, {0,0,0,0,0,0,0,0,}, }; static void copy_board (tetris_t *game, uint8_t board[height][width]) { int i, j; for (i = 0; i < height; i++) for (j = 0; j < width; j++) game->board[i][j] = board[i][j]; } static int intersect (tetris_t *game, piece_t *piece) { int i = 0; int j = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { int row = piece->row + i; int col = piece->col + j; if (piece->mat[i][j] && !inside(row, col)) return 1; if (inside(row, col) && game->board[row][col] && piece->mat[i][j]) return 1; } } return 0; } static void add (tetris_t *game, piece_t *piece) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { int row = piece->row + i; int col = piece->col + j; if (inside(row, col) && piece->mat[i][j]) game->board[row][col] = 1; } } } static void rem (tetris_t *game, piece_t *piece) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { int row = piece->row + i; int col = piece->col + j; if (inside(row, col) && piece->mat[i][j]) game->board[row][col] = 0; } } } static int go_down (tetris_t *game) { int ret = 1; rem(game, &game->curr_piece); game->curr_piece.row++; if (intersect(game, &game->curr_piece)) { game->curr_piece.row--; ret = 0; } add(game, &game->curr_piece); return ret; } static piece_t rot_left (piece_t *piece) { int next_rot = piece->rot - 1; if (next_rot < 0) next_rot = 3; piece_t ret = all_pieces[piece->id][next_rot]; ret.col = piece->col; ret.row = piece->row; return ret; } static piece_t rot_right (piece_t *piece) { int next_rot = piece->rot + 1; if (next_rot > 3) next_rot = 0; piece_t ret = all_pieces[piece->id][next_rot]; ret.col = piece->col; ret.row = piece->row; return ret; } static void turn_left (tetris_t *game) { rem(game, &game->curr_piece); game->curr_piece = rot_left(&game->curr_piece); if (intersect(game, &game->curr_piece)) { game->curr_piece = rot_right(&game->curr_piece); } add(game, &game->curr_piece); } // static void turn_right (tetris_t *game) { // rem(game, &game->curr_piece); // game->curr_piece = rot_right(&game->curr_piece); // if (intersect(game, &game->curr_piece)) { // game->curr_piece = rot_left(&game->curr_piece); // } // add(game, &game->curr_piece); // } static void move_left (tetris_t *game) { rem(game, &game->curr_piece); game->curr_piece.col--; if (intersect(game, &game->curr_piece)) { game->curr_piece.col++; } add(game, &game->curr_piece); } static void move_right (tetris_t *game) { rem(game, &game->curr_piece); game->curr_piece.col++; if (intersect(game, &game->curr_piece)) { game->curr_piece.col--; } add(game, &game->curr_piece); } static int is_line_hole (tetris_t *game, int line) { int j; for (j = 0; j < width; j++) if (!game->board[line][j]) return 0; return 1; } static void remove_line (tetris_t *game, int line) { int j; if (line > 0 && is_line_hole(game, line - 1)) remove_line(game, line - 1); for (j = 0; j < width; j++) { game->board[line][j] = line - 1 >= 0 ? game->board[line - 1][j] : 0; if (line - 1 >= 0) game->board[line - 1][j] = 1; } } static void remove_hole_lines (tetris_t *game) { int i; for (i = height - 1; i >= 0; i--) { if (is_line_hole(game, i)) remove_line(game, i); } } static void update_score (tetris_t *game) { game->board[0][0] = !!(game->score & (1 << 0)); game->board[0][1] = !!(game->score & (1 << 1)); game->board[0][2] = !!(game->score & (1 << 2)); game->board[0][3] = !!(game->score & (1 << 3)); game->board[0][4] = !!(game->score & (1 << 4)); game->board[0][5] = !!(game->score & (1 << 5)); game->board[0][6] = !!(game->score & (1 << 6)); game->board[0][7] = !!(game->score & (1 << 7)); } int tetris_init () { tetris_t *game = &game_container; if (!game) return -1; copy_board(game, clean_board); game->started = 0; game->seed = 2132; game->curr_piece = all_pieces[rand(&game->seed) % 7][rand(&game->seed) % 4]; game->key_state[0] = game->key_state[1] = game->key_state[2] = game->key_state[3] = 0; return 0; } int tetris_update () { tetris_t *game = &game_container; static int update_down = 0; static int speed_up = DEF_SPEED; if (game->started == 0) { game->curr_piece.row = 1; game->curr_piece.col = 2; game->score = 0; if (press_once(game->key_state, KEY_UP)) { copy_board(game, clean_board); // exiting return 1; } if (press_once(game->key_state, KEY_DOWN)) { game->started = 1; copy_board(game, clean_board); } add(game, &game->curr_piece); } if (game->started == 2) { update_down = 0; if (press_once(game->key_state, KEY_UP)) { game->started = 0; copy_board(game, clean_board); } } else if (game->started == 1) { if (press_once(game->key_state, KEY_UP)) turn_left(game); if (press_once(game->key_state, KEY_DOWN)) speed_up = 1; // turn_right(game); if (press_once(game->key_state, KEY_LEFT)) move_left(game); if (press_once(game->key_state, KEY_RIGHT)) move_right(game); if (update_down++ % speed_up == 0 && !go_down(game)) { game->score++; int score = game->score; game->score = 0; update_score(game); speed_up = DEF_SPEED; remove_hole_lines(game); game->score = score; update_score(game); game->curr_piece = all_pieces[rand(&game->seed) % 7][rand(&game->seed) % 4]; game->curr_piece.row = 1; game->curr_piece.col = 2; if (intersect(game, &game->curr_piece)) { game->started = 2; } /* spawn a new piece */ } } draw_board(game->board); return 0; }