#include "step2.h" static const char *TAG = "step2"; static lv_obj_t* scr; static lv_obj_t* img; static bool invisible_blocks = false; static const int height = 22; static const int width = 10; static int board[height][width] = {0}; static bool game = true; static int score = 0; static int piece = 0; static int piece_rotation = 0; static int piece_location[] = {0, 0}; static int piece_nodes[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, }; std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> piece_dist(2, 7); static void generate_block(void); static void show_board(void); static void get_node_locations(void); static void line_clear(int height); static void check_line_clears(void); static void place_piece(void); static void move_left(void); static void move_right(void); static void drop(void); static void rotate_block(void); static int bbcc(int i) { // [0,1,2,3] -> [ 0, 0,+1,+1] return (i/2); } static int bccb(int i) { // [0,1,2,3] -> [ 0,+1,+1, 0] return (((i+1)/2)%2); } static int cbbc(int i) { // [0,1,2,3] -> [+1, 0, 0,+1] return (1-(((i+1)/2)%2)); } static int ccbb(int i) { // [0,1,2,3] -> [+1,+1, 0, 0] return (1-i/2); } static int acca(int i) { // [0,1,2,3] -> [-1,+1,+1,-1] return (((((i+1)/2)%2)*2)-1); } static int aacc(int i) { // [0,1,2,3] -> [-1,-1,+1,+1] return (((i/2)*2)-1); } static int babc(int i) { // [0,1,2,3] -> [ 0,+1, 0,-1] const int map[] = {0, 1, 0, -1}; return map[i]; } static int abcb(int i) { // [0,1,2,3] -> [-1, 0,+1, 0] const int map[] = {-1, 0, 1, 0}; return map[i]; } static int acdb(int i) { // [0,1,2,3] -> [-1,+1,+2, 0] return (acca(i) + bbcc(i)); } static int bacd(int i) { // [0,1,2,3] -> [ 0,-1,+1,+2] return (babc(i) + bbcc(i)); } static int dcab(int i) { // [0,1,2,3] -> [+2,+1,-1, 0] return (-abcb(i) + ccbb(i)); } static int bdca(int i) { // [0,1,2,3] -> [ 0,+2,+1,-1] return (acca(i) + ccbb(i)); } static void init_screen(void) { LV_IMG_DECLARE(tetris); // scr = lv_obj_create(screen); img = lv_img_create(lv_scr_act()); lv_img_set_src(img, &tetris); lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); // play_raw(MOUNT_POINT "/tetris.pcm"); } static void deinit_screen(void) { lv_obj_clean(scr); } void step2(void) { init_screen(); generate_block(); ButtonKey button; while(game) { show_board(); if (get_pressed_button(&button)) { switch (button) { case ButtonKey::b1: move_left(); break; case ButtonKey::b2: move_right(); break; case ButtonKey::b3: drop(); break; case ButtonKey::b4: rotate_block(); break; } } vTaskDelay(pdMS_TO_TICKS(500)); } // game over ESP_LOGI(TAG, "Game Over. Score: %d", score); deinit_screen(); } static void show_board(void) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { if (board[h][w] == 9) { board[h][w] = 0; } } } for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; board[p[0]][p[1]] = 9; } for (int h = height-1; h >= 0; h--) { for (int w = 0; w < width; w++) { printf("|%c|", board[h][w] == 9 ? 'X' : (invisible_blocks ? '0' : ('0' + board[h][w]))); } printf("|\n"); } printf("\n"); } static void generate_block(void) { int new_piece = piece_dist(gen); if (new_piece == piece) { new_piece = 1; } piece = new_piece; piece_rotation = 0; piece_location[0] = 20; piece_location[1] = 4; get_node_locations(); for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (board[p[0]][p[1]] != 0) { game = false; return; } } } } } static void rotate_block(void) { piece_rotation++; if (piece_rotation > 3) { piece_rotation = 0; } get_node_locations(); bool overlap = false; for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (p[0] < 0) { overlap = true; break; } else if (board[p[0]][p[1]] != 0 && board[p[0]][p[1]] != 9) { overlap = true; break; } } if (overlap) { piece_location[0]++; get_node_locations(); bool overlap2 = false; for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (p[0] < 0) { overlap2 = true; break; } else if (board[p[0]][p[1]] != 0 && board[p[0]][p[1]] != 9) { overlap2 = true; break; } } if (overlap2) { piece_rotation--; if (piece_rotation < 0) { piece_rotation += 4; } piece_location[0]--; get_node_locations(); } } } static void move_left(void) { for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (p[1] == 0) { return; } } piece_location[1]--; get_node_locations(); } static void move_right(void) { for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (p[1] == width-1) { return; } } piece_location[1]++; get_node_locations(); } static void drop(void) { for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { int* p = piece_nodes[i]; if (p[0] == 0) { place_piece(); check_line_clears(); generate_block(); return; } else if (board[p[0]-1][p[1]] != 0 && board[p[0]-1][p[1]] != 9) { place_piece(); check_line_clears(); generate_block(); return; } } piece_location[0]--; get_node_locations(); } static void place_piece(void) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { if (board[h][w] == 9) { board[h][w] = piece; } } } ESP_LOGI(TAG, "Placed Piece: %d", piece); } static void get_node_locations() { piece_nodes[0][0] = piece_location[0]; piece_nodes[0][1] = piece_location[1]; if (piece == 1) { piece_nodes[0][0] = piece_location[0]-bacd(piece_rotation); piece_nodes[0][1] = piece_location[1]+acdb(piece_rotation); piece_nodes[1][0] = piece_location[0]-bbcc(piece_rotation); piece_nodes[1][1] = piece_location[1]+bccb(piece_rotation); piece_nodes[2][0] = piece_location[0]-bccb(piece_rotation); piece_nodes[2][1] = piece_location[1]+ccbb(piece_rotation); piece_nodes[3][0] = piece_location[0]-bdca(piece_rotation); piece_nodes[3][1] = piece_location[1]+dcab(piece_rotation); } else if (piece == 2) { piece_nodes[1][0] = piece_location[0]-babc(piece_rotation); piece_nodes[1][1] = piece_location[1]+abcb(piece_rotation); piece_nodes[2][0] = piece_location[0]+babc(piece_rotation); piece_nodes[2][1] = piece_location[1]-abcb(piece_rotation); piece_nodes[3][0] = piece_location[0]-aacc(piece_rotation); piece_nodes[3][1] = piece_location[1]+acca(piece_rotation); } else if (piece == 3) { piece_nodes[1][0] = piece_location[0]-babc(piece_rotation); piece_nodes[1][1] = piece_location[1]+abcb(piece_rotation); piece_nodes[2][0] = piece_location[0]+babc(piece_rotation); piece_nodes[2][1] = piece_location[1]-abcb(piece_rotation); piece_nodes[3][0] = piece_location[0]-acca(piece_rotation); piece_nodes[3][1] = piece_location[1]-aacc(piece_rotation); } else if (piece == 4) { piece_nodes[1][0] = piece_location[0]+1; piece_nodes[1][1] = piece_location[1]; piece_nodes[2][0] = piece_location[0]; piece_nodes[2][1] = piece_location[1]+1; piece_nodes[3][0] = piece_location[0]+1; piece_nodes[3][1] = piece_location[1]+1; } else if (piece == 5) { piece_nodes[1][0] = piece_location[0]-babc(piece_rotation); piece_nodes[1][1] = piece_location[1]+abcb(piece_rotation); piece_nodes[2][0] = piece_location[0]-abcb(piece_rotation); piece_nodes[2][1] = piece_location[1]-babc(piece_rotation); piece_nodes[3][0] = piece_location[0]-acca(piece_rotation); piece_nodes[3][1] = piece_location[1]-aacc(piece_rotation); } else if (piece == 6) { piece_nodes[1][0] = piece_location[0]-babc(piece_rotation); piece_nodes[1][1] = piece_location[1]+abcb(piece_rotation); piece_nodes[2][0] = piece_location[0]-abcb(piece_rotation); piece_nodes[2][1] = piece_location[1]-babc(piece_rotation); piece_nodes[3][0] = piece_location[0]+babc(piece_rotation); piece_nodes[3][1] = piece_location[1]-abcb(piece_rotation); } else if (piece == 7) { piece_nodes[1][0] = piece_location[0]+babc(piece_rotation); piece_nodes[1][1] = piece_location[1]-abcb(piece_rotation); piece_nodes[2][0] = piece_location[0]-abcb(piece_rotation); piece_nodes[2][1] = piece_location[1]-babc(piece_rotation); piece_nodes[3][0] = piece_location[0]-aacc(piece_rotation); piece_nodes[3][1] = piece_location[1]+acca(piece_rotation); } } static void check_line_clears(void) { for (int h = height-2; h >= 0; h--) { for (int w = 0; w < width; w++) { if (board[h][w] != 0 && board[h][w] != 9) { if (w == width-1) { line_clear(h); } } else { break; } } } } static void line_clear(int height) { for (int h = height; h < height-1; h++) { for (int w = 0; w < width; w++) { board[h][w] = board[h+1][w]; } } score++; }