1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#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;
// zero init so that prev_trmno can be set later
Tetromino cur_trmno = {.pos = {0}}, prev_trmno;
bool gen_trmno = true;
srand(time(NULL));
// clear screen
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;
}
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;
cur_trmno.pos[i+1].x = WIDTH / 2 + 1;
cur_trmno.pos[i+1].y = 1 - i / 2;
}
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;
}
cur_trmno.pos[3].x = WIDTH / 2 + 1;
cur_trmno.pos[3].y = 2;
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;
}
cur_trmno.pos[3].x = WIDTH / 2 - 1;
cur_trmno.pos[3].y = 2;
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;
}
cur_trmno.pos[3].x = WIDTH / 2;
cur_trmno.pos[3].y = 0;
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;
}
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;
}
break;
}
gen_trmno = false;
}
prev_trmno = cur_trmno;
// KEY CHECKING
if (count >= (IsKeyDown(KEY_DOWN) ? FPS/30 : interval)) {
count = 0;
for (i = 0; i < 4; i++)
cur_trmno.pos[i].y++;
}
if (IsKeyDown(KEY_RIGHT))
for (i = 0; i < 4; i++)
cur_trmno.pos[i].x++;
else if (IsKeyDown(KEY_LEFT))
for (i = 0; i < 4; i++)
cur_trmno.pos[i].x--;
// for debug purposes only
if (IsKeyPressed(KEY_G))
gen_trmno = true;
// redraw current tetromino position
for (i = 0; i < 4; i++)
grid[prev_trmno.pos[i].x][prev_trmno.pos[i].y] = WHITE;
for (i = 0; i < 4; i++)
grid[cur_trmno.pos[i].x][cur_trmno.pos[i].y] = cur_trmno.colour;
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);
}
|