jag

tetoris_c

public

Small block game in C

Star0
Watch0

Commit 1f869eaffc8c

tarball

Jaglekon <58274093+Jaglekon@users.noreply.github.com>2026-07-20 13:29 UTC

3 files changed+115-58
polling
Modified file: draw.c+2 additions
@@ -34,6 +34,8 @@ void draw_color (tetromino current_square) {
3434 case Z_PIECE:
3535 printf("%s", PURPLE);
3636 break;
37+ default:
38+ break;
3739 }
3840 }
3941
Modified file: main.c+107 additions−58 deletions
@@ -32,63 +32,127 @@ int main () {
3232 printf("\033[?25l\033[?1049h");
3333
3434
35+ /* Polling */
36+
37+ struct pollfd polling[1];
38+
39+ polling[0].fd = 0;
40+ polling[0].events = POLLIN;
41+
42+
3543 /* Init */
3644
3745 init_field();
3846
47+ bool blink[FIELD_HEIGHT] = {};
48+
3949 bool is_piece = false;
4050
4151 piece current_piece = {};
4252
4353
44- uint16_t i;
54+ /* Game Loop */
55+
56+ struct timespec start, current;
57+ clock_gettime(CLOCK_MONOTONIC_RAW, &start);
58+
59+
60+ uint8_t i;
61+ bool is_tetris = false;
4562
46- for (i = 0;; i++) {
63+ while (true) {
4764
4865 int8_t move = 0;
4966 bool down = false;
5067 bool draw = false;
5168 bool rotate = false;
5269
53- int8_t j, k;
70+ clock_gettime(CLOCK_MONOTONIC_RAW, &current);
5471
55- if (!is_piece) {
56- current_piece = init_piece((rand() % Z_PIECE) + 1);
57- is_piece = true;
58- draw = true;
59- i = 0;
60- }
72+ uint64_t time_diff = (current.tv_sec - start.tv_sec) * 1000000000ULL + (current.tv_nsec - start.tv_nsec);
6173
6274
6375 /* Take care of the input */
6476
77+ int is_poll = poll(polling, 1, 17);
78+
79+ if (is_poll > 0 && polling[0].revents & POLLIN) {
80+
81+ char buf[10] = {};
6582
66- char buf[10] = {};
83+ if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
84+ if (buf[0] == 'q') {
85+ break;
86+ }
6787
68- if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
69- if (buf[0] == 'q') {
70- break;
88+ if (buf[0] == '\033' && buf[1] == '[') {
89+
90+ switch (buf[2]) {
91+ case 'A':
92+ rotate = true;
93+ break;
94+ case 'B':
95+ down = true;
96+ break;
97+ case 'C':
98+ move = 1;
99+ break;
100+ case 'D':
101+ move = -1;
102+ break;
103+ default:
104+ break;
105+ }
106+ }
71107 }
108+ }
72109
73- if (buf[0] == '\033' && buf[1] == '[') {
74-
75- switch (buf[2]) {
76- case 'A':
77- rotate = true;
78- break;
79- case 'B':
80- down = true;
81- break;
82- case 'C':
83- move = 1;
84- break;
85- case 'D':
86- move = -1;
87- break;
88- default:
89- break;
110+
111+ if (is_tetris) {
112+
113+ if (time_diff >= FRAME * BLINK && i < 4) {
114+
115+ time_diff -= time_diff % (FRAME * BLINK);
116+ start.tv_sec += time_diff / 1000000000ULL;
117+ start.tv_nsec += time_diff % 1000000000ULL;
118+
119+ draw_board(current_piece, (i % 2 == 0) ? NULL : blink, is_piece);
120+ i++;
121+ }
122+
123+ if (i == 4) {
124+
125+ int8_t j, k;
126+
127+ for (j = 0; j < FIELD_HEIGHT; j++) {
128+ if (blink[j]) {
129+
130+ for (k = j; k > 0; k--) {
131+ int8_t l;
132+
133+ for (l = 0; l < FIELD_WIDTH; l++) {
134+ playfield[k][l + BORDER_WIDTH] = playfield[k - 1][l + BORDER_WIDTH];
135+ }
136+ }
137+ }
90138 }
139+
140+ i = 0;
141+ is_tetris = false;
91142 }
143+
144+ continue;
145+ }
146+
147+
148+
149+ /* Creates new piece */
150+
151+
152+ if (!is_piece) {
153+ current_piece = init_piece((rand() % Z_PIECE) + 1);
154+ is_piece = true;
155+ draw = true;
92156 }
93157
94158
@@ -100,8 +164,6 @@ int main () {
100164 current_piece.x + move + current_piece.size <= FULL_WIDTH
101165 ) {
102166
103- bool is_valid = true;
104-
105167 piece moved_piece = current_piece;
106168 moved_piece.x += move;
107169
@@ -125,14 +187,19 @@ int main () {
125187 current_piece = rotated;
126188 draw = true;
127189 }
128- }
190+ }
129191
130192
131193 /* Piece falls */
132194
133- if (i >= 100 || down) {
195+ if (time_diff >= (FRAME * FALL) || down) {
134196 current_piece.y++;
135- i = 0;
197+
198+ time_diff -= time_diff % (FRAME * FALL);
199+ start.tv_sec += time_diff / 1000000000ULL;
200+ start.tv_nsec += time_diff % 1000000000ULL;
201+
202+
136203 draw = true;
137204 }
138205
@@ -141,6 +208,8 @@ int main () {
141208
142209 if (!valid_position(current_piece)) {
143210
211+ int8_t j, k;
212+
144213 for (j = 0; j < current_piece.size; j++) {
145214 for (k = 0; k < current_piece.size; k++) {
146215
@@ -159,8 +228,7 @@ int main () {
159228
160229 /* Looks if there is a tetris */
161230
162- bool blink[FIELD_HEIGHT] = {};
163- bool is_tetris = false;
231+ int8_t j, k;
164232
165233 for (j = FIELD_HEIGHT - 1; j >= 0; j--) {
166234
@@ -175,26 +243,8 @@ int main () {
175243
176244 blink[j] = true;
177245 is_tetris = true;
178- }
179- }
180-
181- if (is_tetris) {
182- for (j = 0; j < 4; j++) {
183- draw_board(current_piece, (j % 2 == 0) ? NULL : blink, is_piece);
184- usleep(200000);
185- }
186-
187- for (j = 0; j < FIELD_HEIGHT; j++) {
188- if (blink[j]) {
189-
190- for (k = j; k > 0; k--) {
191- int8_t l;
192-
193- for (l = 0; l < FIELD_WIDTH; l++) {
194- playfield[k][l + BORDER_WIDTH] = playfield[k - 1][l + BORDER_WIDTH];
195- }
196- }
197- }
246+ } else {
247+ blink[j] = false;
198248 }
199249 }
200250
@@ -215,7 +265,6 @@ int main () {
215265
216266 if (draw)
217267 draw_board(current_piece, NULL, is_piece);
218- usleep(10000);
219268 }
220269
221270 end:
Modified file: main.h+6 additions
@@ -13,6 +13,7 @@
1313
1414 #include <time.h>
1515 #include <unistd.h>
16+#include <poll.h>
1617
1718 #include <errno.h>
1819
@@ -26,6 +27,11 @@
2627 #define FULL_WIDTH (FIELD_WIDTH + BORDER_WIDTH * 2)
2728 #define FULL_HEIGHT (FIELD_HEIGHT + BORDER_WIDTH)
2829
30+#define FRAME 17000000
31+
32+#define FALL 58
33+#define BLINK 12
34+
2935 typedef enum {
3036 EMPTY, I_PIECE, J_PIECE, L_PIECE, O_PIECE, S_PIECE, T_PIECE, Z_PIECE, TETRIS
3137 } tetromino;