#include #include #include #include "raylib.h" /* * each cube is 1 unit, so FACT is used as a scale factor for the size of the * screen */ #define WIDTH 10 #define HEIGHT 22 #define VIS_HEIGHT 20 #define FACT 40 /* since the game only moves on a block per block basis, no smoothness is * necessary, so the only thing FPS controls is how fast the blocks move left * and right, due to how often it polls */ #define FPS 30 #define CYAN CLITERAL(Color){ 0, 255, 255, 255 } typedef struct Vector2Int { int x, y; } Vector2Int; typedef struct Tetromino { Color colour; Vector2Int pos[4]; // position of 4 cubes making the tetromino } Tetromino; void Draw2DGrid(Color grid[WIDTH][HEIGHT]); int main(void){ int const width = WIDTH * FACT, height = HEIGHT * FACT, vis_height = VIS_HEIGHT * FACT; Color grid[WIDTH][HEIGHT]; // if colour is WHITE, the position is empty int interval = FPS, count, i, j; Tetromino cur_trmno; // trnmo is faster and easier to write than tetromino bool gen_trmno = true; srand(time(NULL)); for (i = 0; i < WIDTH; i++) for (j = 0; j < HEIGHT; j++) grid[i][j] = WHITE; InitWindow(width, height, "retris"); SetTargetFPS(FPS); for (count = 0; !WindowShouldClose(); count++) { if (gen_trmno) { switch (rand() % 7) { case 0: // I-tetromino cur_trmno.colour = CYAN; for (i = 0; i < 4; i++) { cur_trmno.pos[i].x = WIDTH / 2; cur_trmno.pos[i].y = i; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } break; case 1: // O-tetromino cur_trmno.colour = YELLOW; for (i = 0; i < 4; i += 2) { cur_trmno.pos[i].x = WIDTH / 2; cur_trmno.pos[i].y = 1 - i / 2; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; cur_trmno.pos[i+1].x = WIDTH / 2 + 1; cur_trmno.pos[i+1].y = 1 - i / 2; grid[cur_trmno.pos[i+1].x][cur_trmno.pos[i+1].y] = cur_trmno.colour; } break; case 2: // L-tetromino cur_trmno.colour = ORANGE; for (i = 0; i < 3; i++) { cur_trmno.pos[i].x = WIDTH / 2; cur_trmno.pos[i].y = i; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } cur_trmno.pos[3].x = WIDTH / 2 + 1; cur_trmno.pos[3].y = 2; grid[cur_trmno.pos[3].x][cur_trmno.pos[3].y] = cur_trmno.colour; break; case 3: // J-tetromino cur_trmno.colour = DARKBLUE; for (i = 0; i < 3; i++) { cur_trmno.pos[i].x = WIDTH / 2; cur_trmno.pos[i].y = i; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } cur_trmno.pos[3].x = WIDTH / 2 - 1; cur_trmno.pos[3].y = 2; grid[cur_trmno.pos[3].x][cur_trmno.pos[3].y] = cur_trmno.colour; break; case 4: // T-tetromino cur_trmno.colour = PURPLE; for (i = 0; i < 3; i++) { cur_trmno.pos[i].x = WIDTH / 2 - 1 + i; cur_trmno.pos[i].y = 1; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } cur_trmno.pos[3].x = WIDTH / 2; cur_trmno.pos[3].y = 0; grid[cur_trmno.pos[3].x][cur_trmno.pos[3].y] = cur_trmno.colour; break; case 5: // S-tetromino cur_trmno.colour = GREEN; for (i = 0; i < 4; i++) { cur_trmno.pos[i].x = WIDTH / 2 + (i < 2 ? i - 1 : i - 2); cur_trmno.pos[i].y = i < 2 ? 1 : 0; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } break; case 6: // Z-tetromino cur_trmno.colour = RED; for (i = 0; i < 4; i++) { cur_trmno.pos[i].x = WIDTH / 2 + (i < 2 ? i : 2 - i); cur_trmno.pos[i].y = i < 2 ? 1 : 0; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } break; } gen_trmno = false; } if (count >= (IsKeyDown(KEY_DOWN) ? FPS/30 : interval)) { count = 0; for (i = 0; i < 4; i++) grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = WHITE; for (i = 0; i < 4; i++) { cur_trmno.pos[i].y++; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } } if (IsKeyDown(KEY_RIGHT)) { for (i = 0; i < 4; i++) grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = WHITE; for (i = 0; i < 4; i++) { cur_trmno.pos[i].x++; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } } else if (IsKeyDown(KEY_LEFT)) { for (i = 0; i < 4; i++) grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = WHITE; for (i = 0; i < 4; i++) { cur_trmno.pos[i].x--; grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour; } } if (IsKeyPressed(KEY_G)) gen_trmno = true; BeginDrawing(); Draw2DGrid(grid); #ifdef DEBUG char *str1, *str2; asprintf(&str1, "block0: x: %d y: %d", cur_trmno.pos[0].x, cur_trmno.pos[0].y); for (i = 1; i < 4; i++) { asprintf(&str2, "%s\nblock%d: x: %d y: %d", str1, i, cur_trmno.pos[i].x, cur_trmno.pos[i].y); free(str1); str1 = str2; } DrawText(str2, 0, 20, 16, BLACK); free(str2); #endif EndDrawing(); } CloseWindow(); return 0; } void Draw2DGrid(Color grid[WIDTH][HEIGHT]){ int i, j; for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { DrawRectangle(i*FACT, j*FACT, FACT, FACT, grid[i][j]); } } for (i = 0; i <= WIDTH; i++) DrawLine(i*FACT, 0, i*FACT, HEIGHT*FACT, LIGHTGRAY); for (i = 0; i <= HEIGHT; i++) DrawLine(0, i*FACT, WIDTH*FACT, i*FACT, LIGHTGRAY); }