jag

tetoris_c

public

Small block game in C

Star0
Watch0

Commit b7c05d8620b0

tarball

Jaglekon <58274093+Jaglekon@users.noreply.github.com>2026-07-30 22:19 UTC

8 files changed+184-42
input buffer
Modified file: source/main.c+52 additions−41 deletions
@@ -1,4 +1,5 @@
11 #include "main.h"
2+#include "parser.h"
23
34
45 tetromino playfield[FULL_HEIGHT][FULL_WIDTH] = {};
@@ -76,6 +77,7 @@ int main () {
7677 uint16_t tick_blink = 0;
7778 uint16_t tick_spin = 0;
7879 uint16_t tick_fall_prot = 0;
80+ uint16_t tick_wait_key = 0;
7981
8082 uint8_t i;
8183 bool is_tetris = false;
@@ -88,6 +90,7 @@ int main () {
8890 bool down = false;
8991 bool draw = false;
9092 bool rotate = false;
93+ bool key_lock = false;
9194
9295
9396 /* Polling for input */
@@ -126,63 +129,75 @@ int main () {
126129
127130 if (is_poll > 0 && polling[0].revents & POLLIN) {
128131
129- char buf[10] = {};
132+ uint8_t buf[256] = {};
130133
131- if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
132-
133- if (tolower(buf[0]) == 'q') {
134- break;
135- }
134+ int read_len;
136135
137- if (tolower(buf[0]) == 'p') {
138- if (paused) {
136+ if ((read_len = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
139137
138+ if (add_to_buf(buf, read_len)) {
140139
141- paused = false;
142- } else {
140+ keypress input = UNKNOWN;
143141
142+ while (input != NO_KEY) {
144143
145- draw_pause();
146-
147- paused = true;
148- }
149- }
144+ input = parse_input();
145+
146+ if (input == INCOMPLETE) {
147+ if(tick_wait_key >= KEY_PROTECTION) {
148+ break_unfinished();
149+ } else {
150+ key_lock = true;
151+ break;
152+ }
150153
154+ } else {
155+
156+ switch (input) {
157+ case PAUSE:
158+ paused = !paused;
159+ break;
160+ case QUIT:
161+ goto end;
162+ break;
163+ case UP_ARROW:
164+ rotate = true;
165+ break;
166+ case DOWN_ARROW:
167+ down = true;
168+ break;
169+ case RIGHT_ARROW:
170+ move = 1;
171+ break;
172+ case LEFT_ARROW:
173+ move = -1;
174+ break;
175+ default:
176+ break;
177+ }
151178
152- if (buf[0] == '\033' && buf[1] == '[') {
153-
154- switch (buf[2]) {
155- case 'A':
156- rotate = true;
157- break;
158- case 'B':
159- down = true;
160- break;
161- case 'C':
162- move = 1;
163- break;
164- case 'D':
165- move = -1;
166- break;
167- default:
168- break;
179+ tick_wait_key = 0;
180+ }
169181 }
182+ } else {
183+ break; /* TODO error */
170184 }
171185 }
172186 }
173187
188+ if (key_lock)
189+ tick_wait_key++;
174190
175- if (paused)
191+ if (paused) {
192+ draw_pause();
176193 continue;
177-
194+ }
178195
179196
180197 /* Dealing with cleared Lines */
181198
182199 if (is_tetris) {
183200
184- uint8_t lines_cleared = 0;
185-
186201 tick_blink += ticks;
187202
188203 while (tick_blink >= BLINK && i < 4) {
@@ -209,12 +224,8 @@ int main () {
209224 }
210225 }
211226
212- lines_cleared++;
227+ all_cleared_lines++;
213228 }
214-
215- all_cleared_lines += lines_cleared;
216-
217- pot_score_lines = line_points_add(lines_cleared, level);
218229 }
219230
220231 i = 0;
Modified file: source/main.d+2 additions−1 deletions
@@ -1,2 +1,3 @@
1-source/main.o: source/main.c source/main.h
1+source/main.o: source/main.c source/main.h source/parser.h
22 source/main.h:
3+source/parser.h:
Modified file: source/main.h+1 additions
@@ -35,6 +35,7 @@
3535 #define BLINK 12
3636 #define SPIN 8
3737 #define FALL_PROTECTION 50
38+#define KEY_PROTECTION 2
3839
3940 #define LINES_LEVEL 10
4041 #define MAX_LEVEL 20
Binary file: source/main.obinary

Binary file not shown.

Added file: source/parser.c+106 additions
@@ -0,0 +1,106 @@
1+#include "parser.h"
2+
3+uint8_t main_buffer[BUF_LEN];
4+
5+uint16_t start = 0;
6+uint16_t end = 0;
7+
8+uint16_t length = 0;
9+
10+
11+int add_to_buf(uint8_t *input, uint16_t input_length) {
12+
13+ if (BUF_LEN - length < input_length)
14+ return 0;
15+
16+ uint16_t space_end = BUF_LEN - end;
17+
18+ if (input_length <= space_end) {
19+ memcpy(main_buffer + end, input, input_length);
20+ } else {
21+ memcpy(main_buffer + end, input, space_end);
22+ memcpy(main_buffer, input + space_end, input_length - space_end);
23+ }
24+
25+ end = (end + input_length) % BUF_LEN;
26+ length += input_length;
27+
28+ return 1;
29+}
30+
31+
32+uint16_t next_pos(uint16_t starting_position) {
33+ return (starting_position + 1) % BUF_LEN;
34+}
35+
36+
37+keypress parse_input() {
38+
39+ if(length == 0)
40+ return NO_KEY;
41+
42+ keypress output = UNKNOWN;
43+
44+ uint8_t next_char = tolower(main_buffer[start]);
45+ uint16_t next_position = next_pos(start);
46+
47+
48+ if (next_char == '\033') {
49+
50+ if (length < ARROW_LEN) {
51+ output = INCOMPLETE;
52+ next_position = start;
53+ } else {
54+
55+ length--;
56+
57+ if (main_buffer[next_position] == '[') {
58+ next_position = next_pos(next_position);
59+
60+ length--;
61+
62+ uint8_t escape_code = main_buffer[next_position];
63+
64+ switch(escape_code) {
65+ case 'A':
66+ output = UP_ARROW;
67+ break;
68+ case 'B':
69+ output = DOWN_ARROW;
70+ break;
71+ case 'C':
72+ output = RIGHT_ARROW;
73+ break;
74+ case 'D':
75+ output = LEFT_ARROW;
76+ break;
77+ default:
78+ break;
79+ }
80+
81+ length--;
82+
83+ next_position = next_pos(next_position);
84+ }
85+ }
86+
87+ } else {
88+
89+ length--;
90+
91+ if (next_char == 'p') {
92+ output = PAUSE;
93+ } else if(next_char == 'q') {
94+ output = QUIT;
95+ }
96+ }
97+
98+ start = next_position;
99+
100+ return output;
101+}
102+
103+void break_unfinished() {
104+ length--;
105+ start = next_pos(start);
106+}
Added file: source/parser.d+2 additions
@@ -0,0 +1,2 @@
1+source/parser.o: source/parser.c source/parser.h
2+source/parser.h:
Added file: source/parser.h+21 additions
@@ -0,0 +1,21 @@
1+#ifndef PARSER_H
2+#define PARSER_H
3+
4+#include <string.h>
5+#include <ctype.h>
6+#include <stdint.h>
7+
8+#define BUF_LEN 4096
9+#define ARROW_LEN 3
10+
11+typedef enum {
12+ NO_KEY, PAUSE, QUIT, LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, INCOMPLETE, UNKNOWN
13+} keypress;
14+
15+int add_to_buf(uint8_t *input, uint16_t input_length);
16+
17+keypress parse_input();
18+
19+void break_unfinished();
20+
21+#endif
Binary file: source/parser.obinary

Binary file not shown.