jag

snake_c

public

Small snake game in C

Star0
Watch0

Commit 9357e6aedfb4

tarball

Jaglekon <58274093+Jaglekon@users.noreply.github.com>2026-03-29 21:17 UTC

5 files changed+340-328
made it more streamlined
Modified file: Makefile+1 additions−1 deletions
@@ -1,2 +1,2 @@
11 snake: snake.c
2- gcc -std=c99 -Wall -Wextra -o snake snake.c drawing.c
2+ gcc -std=c99 -Wall -Wextra -o snake snake.c drawing.c logic.c
Modified file: drawing.c+97 additions
@@ -214,6 +214,103 @@ bool draw_menu(main_menu menu, struct winsize window_size) {
214214 return false;
215215 }
216216
217+
218+void draw_settings(settings selected_setting, speed game_speed, selected game_size) {
219+
220+ char *setting_string[] = {
221+ " HEIGHT ",
222+ " WIDTH ",
223+ " SPEED ",
224+ " BACK "
225+ };
226+
227+ char *speed_char[] = {
228+ " VERY FAST ",
229+ " FAST ",
230+ " AVERAGE ",
231+ " SLOW ",
232+ " VERY SLOW "
233+ };
234+
235+ uint8_t width = (uint8_t) strlen(setting_string[0]);
236+ uint8_t width_setting = (uint8_t) strlen(speed_char[0]);
237+
238+ uint8_t i, j;
239+
240+ printf("\033[2J\033[H");
241+
242+
243+ for (i = 0; i < SETTINGS_MENU; i++) {
244+
245+ printf("+");
246+ for (j = 0; j < width; j++)
247+ printf("-");
248+ printf("+");
249+
250+ if (i != BACK_S) {
251+ printf (" +");
252+
253+ for (j = 0; j < width_setting; j++)
254+ printf("-");
255+ printf("+");
256+ }
257+
258+ printf("\n|");
259+
260+ if (i == selected_setting)
261+ printf("\033[32m");
262+
263+ printf("%s\033[0m", setting_string[i]);
264+
265+ printf("|");
266+
267+ if (i != BACK_S) {
268+ printf(" |");
269+ if (selected_setting == i)
270+ printf("\033[32m");
271+
272+ switch (i) {
273+ case SPEED_S:
274+ printf("%s", speed_char[game_speed]);
275+ break;
276+
277+ case WIDTH_S:
278+ case HEIGHT_S:
279+ for (j = 0; j < (width_setting - 3) >> 1; j++)
280+ printf(" ");
281+ printf("%3d", (i == WIDTH_S) ? game_size.x : game_size.y);
282+ for (j = 0; j < width_setting - ((width_setting - 3) >> 1) - 3; j++)
283+ printf(" ");
284+
285+ }
286+ printf("\033[0m");
287+ printf("|");
288+ }
289+
290+ printf("\n");
291+
292+ if (i != HEIGHT_S) {
293+
294+ printf("+");
295+ for (j = 0; j < width; j++)
296+ printf("-");
297+ printf("+");
298+
299+ if (i != BACK_S) {
300+ printf (" +");
301+
302+ for (j = 0; j < width_setting; j++)
303+ printf("-");
304+ printf("+");
305+ }
306+
307+ if (i < SETTINGS_MENU - 1)
308+ printf("\n");
309+ }
310+ }
311+ fflush(stdout);
312+}
313+
217314 bool draw_board(
218315 selected game_size,
219316 board_state **board,
Added file: logic.c+199 additions
@@ -0,0 +1,199 @@
1+#include "snake.h"
2+
3+
4+
5+uint8_t update_snake (selected game_size, snake *my_snake, direction shift) {
6+
7+ my_snake->position[0].directions[1] = my_snake->position[0].directions[0];
8+ my_snake->position[0].directions[0] = shift;
9+
10+ uint16_t i;
11+ for (i = my_snake->length; i > 0; i--)
12+ my_snake->position[i] = my_snake->position[i - 1];
13+
14+ switch (shift) {
15+ case UP:
16+ my_snake->position[0].coords.y =
17+ ((my_snake->position[0].coords.y + game_size.y - 1) % game_size.y);
18+ break;
19+ case DOWN:
20+ my_snake->position[0].coords.y = ((my_snake->position[0].coords.y + 1) % game_size.y);
21+ break;
22+ case LEFT:
23+ my_snake->position[0].coords.x =((my_snake->position[0].coords.x + game_size.x - 1) % game_size.x);
24+ break;
25+ case RIGHT:
26+ my_snake->position[0].coords.x = ((my_snake->position[0].coords.x + 1) % game_size.x);
27+ break;
28+ default:
29+ return 0;
30+ break;
31+ }
32+
33+ uint8_t head_y = my_snake->position[0].coords.y;
34+ uint8_t head_x = my_snake->position[0].coords.x;
35+
36+ for (i = 1; i < my_snake->length; i++) {
37+ int16_t x = my_snake->position[i].coords.x;
38+ int16_t y = my_snake->position[i].coords.y;
39+
40+ if (x == head_x && y == head_y)
41+ return 2;
42+ }
43+
44+
45+ return 1;
46+}
47+
48+void update_field(snake my_snake, selected game_size, board_state **board, bool init) {
49+
50+ uint8_t i, j;
51+
52+ board_state snake_bit[DIRECTIONS][DIRECTIONS] = {
53+ [UP][UP] = VERTICAL,
54+ [DOWN][DOWN] = VERTICAL,
55+
56+ [RIGHT][RIGHT] = HORIZONTAL,
57+ [LEFT][LEFT] = HORIZONTAL,
58+
59+ [DOWN][RIGHT] = BOTTOM_LEFT,
60+ [LEFT][UP] = BOTTOM_LEFT,
61+
62+ [UP][RIGHT] = TOP_LEFT,
63+ [LEFT][DOWN] = TOP_LEFT,
64+
65+ [DOWN][LEFT] = BOTTOM_RIGHT,
66+ [RIGHT][UP] = BOTTOM_RIGHT,
67+
68+ [UP][LEFT] = TOP_RIGHT,
69+ [RIGHT][DOWN] = TOP_RIGHT
70+ };
71+
72+
73+ if (init) {
74+ for (i = 0; i < game_size.y; i++) {
75+ for (j = 0; j < game_size.x; j++) {
76+ board[i][j] = AIR;
77+ }
78+ }
79+
80+ for (i = 1; i < my_snake.length; i++) {
81+ int16_t x = my_snake.position[i].coords.x;
82+ int16_t y = my_snake.position[i].coords.y;
83+
84+ if (x >= 0 && y >= 0) {
85+
86+ direction first = my_snake.position[i].directions[0];
87+ direction second = my_snake.position[i].directions[1];
88+
89+ board[y][x] = snake_bit[first][second];
90+ }
91+ }
92+ } else {
93+
94+ int16_t x = my_snake.position[my_snake.length].coords.x;
95+ int16_t y = my_snake.position[my_snake.length].coords.y;
96+
97+ if (x != -1 && y != -1)
98+ board[y][x] = AIR;
99+
100+
101+ x = my_snake.position[1].coords.x;
102+ y = my_snake.position[1].coords.y;
103+
104+ direction first = my_snake.position[1].directions[0];
105+ direction second = my_snake.position[1].directions[1];
106+
107+ if (x != -1 && y != -1)
108+ board[y][x] = snake_bit[first][second];
109+ }
110+
111+
112+ int16_t x = my_snake.position[0].coords.x;
113+ int16_t y = my_snake.position[0].coords.y;
114+
115+ if (my_snake.position[0].directions[0] == RIGHT) {
116+ board[y][x] = HEAD_1;
117+ } else {
118+ board[y][x] = HEAD_2;
119+ }
120+
121+ for (i = 0; i < game_size.y; i++) {
122+ for (j = 0; j < game_size.x; j++) {
123+ if (board[i][j] == FRUIT)
124+ return;
125+ }
126+ }
127+
128+ while (true) {
129+ x = rand() % game_size.x;
130+ y = rand() % game_size.y;
131+
132+ if (board[y][x] == AIR) {
133+ board[y][x] = FRUIT;
134+ return;
135+ }
136+ }
137+}
138+
139+direction read_direction(char *string, bool wasd_enabled) {
140+
141+ if (string[0] == '\033') {
142+
143+ if (strlen(string) == 1)
144+ return ESCAPE;
145+
146+ if (strlen(string) >= 3) {
147+
148+ if (string[1] == '[') {
149+
150+ switch (string[2]) {
151+ case RIGHT_CODE:
152+ return RIGHT;
153+ break;
154+ case LEFT_CODE:
155+ return LEFT;
156+ break;
157+ case UP_CODE:
158+ return UP;
159+ break;
160+ case DOWN_CODE:
161+ return DOWN;
162+ break;
163+ }
164+ }
165+ }
166+ }
167+
168+ if (wasd_enabled) {
169+ switch (toupper(string[0])) {
170+ case 'A':
171+ return LEFT;
172+ break;
173+ case 'D':
174+ return RIGHT;
175+ break;
176+ case 'W':
177+ return UP;
178+ break;
179+ case 'S':
180+ return DOWN;
181+ break;
182+ }
183+ }
184+
185+ switch (toupper(string[0])) {
186+ case 'Q':
187+ return Q_KEY;
188+ break;
189+ case 'P':
190+ return P_KEY;
191+ break;
192+ case '\n':
193+ return ENTER;
194+ break;
195+ default:
196+ return DIRECTIONS;
197+ break;
198+ }
199+}
Modified file: snake.c+37 additions−321 deletions
@@ -1,5 +1,6 @@
11 #include "snake.h"
22
3+
34 int main(int argc, char *args[]) {
45
56 /* command argument handling */
@@ -14,7 +15,7 @@ int main(int argc, char *args[]) {
1415
1516 printf("This is a small TUI snake game.\n\n");
1617 printf("Controls: Arrow keys/WASD to control the snake.\n");
17- printf(" P to pause.\n");
18+ printf(" P/Enter to pause.\n");
1819 printf(" Q to quit.\n");
1920
2021 return 0;
@@ -58,6 +59,11 @@ int main(int argc, char *args[]) {
5859 if (!start_animation())
5960 goto end_of_program;
6061
62+ /* game settings */
63+
64+ speed game_speed = AVERAGE;
65+ selected game_size = {WIDTH, HEIGHT};
66+
6167 /* Menu */
6268
6369 bool menu = true;
@@ -67,16 +73,9 @@ int main(int argc, char *args[]) {
6773 main_menu selected_menu = NEW_GAME;
6874 settings selected_setting = HEIGHT_S;
6975
70- speed game_speed = AVERAGE;
71-
72- selected game_size = {WIDTH, HEIGHT};
73-
7476 while (menu) {
7577
76- bool pressed_enter = false;
77- bool changed_selected = false;
78-
79- direction arrow = NO_DIRECTION;
78+ direction pressed_key = DIRECTIONS;
8079
8180 char string[STRING_LEN] = {};
8281 ssize_t length_string = read(STDIN_FILENO, string, sizeof(string) - 1);
@@ -87,45 +86,43 @@ int main(int argc, char *args[]) {
8786 if (current_size.ws_col != init_size.ws_col ||
8887 current_size.ws_row != init_size.ws_row) {
8988 init_size = current_size;
90- changed_selected = true;
89+ change_menu = true;
9190 }
9291
9392
9493 if (length_string > 0) {
9594 string[length_string] = '\0';
9695
97- arrow = read_direction(string, false);
98-
99- if (string[0] == '\n')
100- pressed_enter = true;
101-
102- if (toupper(string[0]) == 'Q')
103- goto end_of_program;
96+ pressed_key = read_direction(string, false);
10497 }
10598
99+ if (pressed_key == Q_KEY)
100+ goto end_of_program;
101+
102+
106103 if (!setting) {
107104
108105 if (!too_small) {
109- switch (arrow) {
106+ switch (pressed_key) {
110107 case UP:
111108 selected_menu = (selected_menu + (MAIN_MENU - 1)) % MAIN_MENU;
112- changed_selected = true;
109+ change_menu = true;
113110 break;
114111 case DOWN:
115112 selected_menu = (selected_menu + 1) % MAIN_MENU;
116- changed_selected = true;
113+ change_menu = true;
117114 break;
118115 default:
119116 break;
120117 }
121118 }
122119
123- if (changed_selected || change_menu) {
120+ if (change_menu) {
124121 too_small = draw_menu(selected_menu, init_size);
125122 change_menu = false;
126123 }
127124
128- if (pressed_enter && !too_small) {
125+ if (pressed_key == ENTER && !too_small) {
129126 switch (selected_menu) {
130127 case NEW_GAME:
131128 menu = false;
@@ -135,120 +132,24 @@ int main(int argc, char *args[]) {
135132 change_menu = true;
136133 break;
137134 default:
138- tcsetattr(STDIN_FILENO, TCSANOW, &old);
139- printf("\033[?25h\n\n");
140-
141-
142- printf("\033[32m");
143- return 0;
135+ goto end_of_program;
144136 break;
145137 }
146138 }
147- } else {
148-
149- char *setting_string[] = {
150- " HEIGHT ",
151- " WIDTH ",
152- " SPEED ",
153- " BACK "
154- };
155-
156- char *speed_char[] = {
157- " VERY FAST ",
158- " FAST ",
159- " AVERAGE ",
160- " SLOW ",
161- " VERY SLOW "
162- };
163-
164- uint8_t width = (uint8_t) strlen(setting_string[0]);
165- uint8_t width_setting = (uint8_t) strlen(speed_char[0]);
166-
167-
168- if (changed_selected || change_menu) {
169-
170- uint8_t i, j;
171-
172- printf("\033[2J\033[H");
173-
174-
175- for (i = 0; i < SETTINGS_MENU; i++) {
176-
177- printf("+");
178- for (j = 0; j < width; j++)
179- printf("-");
180- printf("+");
181-
182- if (i != BACK_S) {
183- printf (" +");
184-
185- for (j = 0; j < width_setting; j++)
186- printf("-");
187- printf("+");
188- }
189-
190- printf("\n|");
191-
192- if (i == selected_setting)
193- printf("\033[32m");
194-
195- printf("%s\033[0m", setting_string[i]);
196139
197- printf("|");
198-
199- if (i != BACK_S) {
200- printf(" |");
201- if (selected_setting == i)
202- printf("\033[32m");
203-
204- switch (i) {
205- case SPEED_S:
206- printf("%s", speed_char[game_speed]);
207- break;
208-
209- case WIDTH_S:
210- case HEIGHT_S:
211- for (j = 0; j < (width_setting - 3) >> 1; j++)
212- printf(" ");
213- printf("%3d", (i == WIDTH_S) ? game_size.x : game_size.y);
214- for (j = 0; j < width_setting - ((width_setting - 3) >> 1) - 3; j++)
215- printf(" ");
216-
217- }
218- printf("\033[0m");
219- printf("|");
220- }
221-
222- printf("\n");
223-
224- if (i != HEIGHT_S) {
225-
226- printf("+");
227- for (j = 0; j < width; j++)
228- printf("-");
229- printf("+");
230-
231- if (i != BACK_S) {
232- printf (" +");
233-
234- for (j = 0; j < width_setting; j++)
235- printf("-");
236- printf("+");
237- }
140+ } else {
238141
239- if (i < SETTINGS_MENU - 1)
240- printf("\n");
241- }
242- }
243- fflush(stdout);
142+ if (change_menu) {
143+
144+ draw_settings(selected_setting, game_speed, game_size);
244145
245146 change_menu = false;
246147 }
247148
248149
249- if (arrow != NO_DIRECTION) {
150+ if (pressed_key < DIRECTIONS) {
250151
251- switch (arrow) {
152+ switch (pressed_key) {
252153 case UP:
253154 selected_setting = (selected_setting + (SETTINGS_MENU - 1)) % SETTINGS_MENU;
254155 break;
@@ -298,7 +199,7 @@ int main(int argc, char *args[]) {
298199
299200 }
300201
301- if (pressed_enter) {
202+ if (pressed_key == ENTER) {
302203 switch (selected_setting) {
303204 case BACK_S:
304205 setting = false;
@@ -308,12 +209,12 @@ int main(int argc, char *args[]) {
308209 }
309210 change_menu = true;
310211 }
311- pressed_enter = false;
312212 }
313213
314214 nanosleep(&mili100, NULL);
315215 }
316216
217+
317218 /* initialisation of the game */
318219
319220 snake my_snake;
@@ -352,18 +253,16 @@ int main(int argc, char *args[]) {
352253
353254 update_field(my_snake, game_size, board, true);
354255
355- selected fruit = new_fruit(game_size, board);
356-
357256 bool paused = false;
358257
359258 if ((too_small = draw_board(game_size, board, current_size, true, false)))
360259 paused = true;
361260
362261
363- bool run = true;
364-
365262 struct timespec milispeed = {0, 1000000 * (SPEED + game_speed * 25)};
366263
264+ bool run = true;
265+
367266 /* start of the actual game loop */
368267
369268 while (run) {
@@ -413,7 +312,7 @@ int main(int argc, char *args[]) {
413312
414313 if (!paused) {
415314
416- if (tmp_direction != NO_DIRECTION &&
315+ if (tmp_direction < DIRECTIONS &&
417316 ((shift + (DIRECTIONS >> 1)) % DIRECTIONS) != tmp_direction) {
418317 shift = tmp_direction;
419318 }
@@ -423,18 +322,19 @@ int main(int argc, char *args[]) {
423322 uint8_t head_y = my_snake.position[0].coords.y;
424323 uint8_t head_x = my_snake.position[0].coords.x;
425324
426-
427- update_field(my_snake, game_size, board, false);
428-
429- if (head_y == fruit.y && head_x == fruit.x) {
325+ if (board[head_y][head_x] == FRUIT) {
430326 my_snake.length++;
431327 snake_part *tmp = realloc(my_snake.position, (my_snake.length + 1) * sizeof(snake_part));
432328 if (tmp == NULL)
433329 goto end_free;
434330 my_snake.position = tmp;
435- fruit = new_fruit(game_size, board);
331+
332+ my_snake.position[my_snake.length].coords.y = -1;
333+ my_snake.position[my_snake.length].coords.x = -1;
436334 }
437335
336+ update_field(my_snake, game_size, board, false);
337+
438338 draw_board(game_size, board, current_size, false, false);
439339
440340 switch (update) {
@@ -470,187 +370,3 @@ end_of_program:
470370 printf("\033[32m");
471371 return 0;
472372 }
473-
474-
475-uint8_t update_snake (selected game_size, snake *my_snake, direction shift) {
476-
477- my_snake->position[0].directions[1] = my_snake->position[0].directions[0];
478- my_snake->position[0].directions[0] = shift;
479-
480- uint16_t i;
481- for (i = my_snake->length; i > 0; i--)
482- my_snake->position[i] = my_snake->position[i - 1];
483-
484- switch (shift) {
485- case UP:
486- my_snake->position[0].coords.y =
487- ((my_snake->position[0].coords.y + game_size.y - 1) % game_size.y);
488- break;
489- case DOWN:
490- my_snake->position[0].coords.y = ((my_snake->position[0].coords.y + 1) % game_size.y);
491- break;
492- case LEFT:
493- my_snake->position[0].coords.x =((my_snake->position[0].coords.x + game_size.x - 1) % game_size.x);
494- break;
495- case RIGHT:
496- my_snake->position[0].coords.x = ((my_snake->position[0].coords.x + 1) % game_size.x);
497- break;
498- default:
499- return 0;
500- break;
501- }
502-
503- uint8_t head_y = my_snake->position[0].coords.y;
504- uint8_t head_x = my_snake->position[0].coords.x;
505-
506- for (i = 1; i < my_snake->length; i++) {
507- int16_t x = my_snake->position[i].coords.x;
508- int16_t y = my_snake->position[i].coords.y;
509-
510- if (x == head_x && y == head_y)
511- return 2;
512- }
513-
514-
515- return 1;
516-}
517-
518-void update_field(snake my_snake, selected game_size, board_state **board, bool init) {
519-
520- uint8_t i, j;
521-
522- board_state snake_bit[DIRECTIONS][DIRECTIONS] = {
523- [UP][UP] = VERTICAL,
524- [DOWN][DOWN] = VERTICAL,
525-
526- [RIGHT][RIGHT] = HORIZONTAL,
527- [LEFT][LEFT] = HORIZONTAL,
528-
529- [DOWN][RIGHT] = BOTTOM_LEFT,
530- [LEFT][UP] = BOTTOM_LEFT,
531-
532- [UP][RIGHT] = TOP_LEFT,
533- [LEFT][DOWN] = TOP_LEFT,
534-
535- [DOWN][LEFT] = BOTTOM_RIGHT,
536- [RIGHT][UP] = BOTTOM_RIGHT,
537-
538- [UP][LEFT] = TOP_RIGHT,
539- [RIGHT][DOWN] = TOP_RIGHT
540- };
541-
542-
543- if (init) {
544- for (i = 0; i < game_size.y; i++) {
545- for (j = 0; j < game_size.x; j++) {
546- board[i][j] = AIR;
547- }
548- }
549-
550- for (i = 1; i < my_snake.length; i++) {
551- int16_t x = my_snake.position[i].coords.x;
552- int16_t y = my_snake.position[i].coords.y;
553-
554- if (x >= 0 && y >= 0) {
555-
556- direction first = my_snake.position[i].directions[0];
557- direction second = my_snake.position[i].directions[1];
558-
559- board[y][x] = snake_bit[first][second];
560- }
561- }
562- } else {
563-
564- int16_t x = my_snake.position[my_snake.length].coords.x;
565- int16_t y = my_snake.position[my_snake.length].coords.y;
566-
567- if (x != -1 && y != -1)
568- board[y][x] = AIR;
569-
570-
571- x = my_snake.position[1].coords.x;
572- y = my_snake.position[1].coords.y;
573-
574- direction first = my_snake.position[1].directions[0];
575- direction second = my_snake.position[1].directions[1];
576-
577- if (x != -1 && y != -1)
578- board[y][x] = snake_bit[first][second];
579- }
580-
581-
582- int16_t x = my_snake.position[0].coords.x;
583- int16_t y = my_snake.position[0].coords.y;
584-
585- if (my_snake.position[0].directions[0] == RIGHT) {
586- board[y][x] = HEAD_1;
587- } else {
588- board[y][x] = HEAD_2;
589- }
590-}
591-
592-selected new_fruit(selected game_size, board_state **board) {
593- bool found_space = false;
594-
595- uint8_t x;
596- uint8_t y;
597-
598- while (!found_space) {
599- x = rand() % game_size.x;
600- y = rand() % game_size.y;
601-
602- if (board[y][x] == AIR)
603- found_space = true;
604- }
605-
606- selected fruit = {x, y};
607-
608- board[fruit.y][fruit.x] = FRUIT;
609-
610- return fruit;
611-}
612-
613-
614-direction read_direction(char *string, bool wasd_enabled) {
615-
616- if (strlen(string) >= 3) {
617- if (string[0] == '\033') {
618- if (string[1] == '[') {
619-
620- switch (string[2]) {
621- case RIGHT_CODE:
622- return RIGHT;
623- break;
624- case LEFT_CODE:
625- return LEFT;
626- break;
627- case UP_CODE:
628- return UP;
629- break;
630- case DOWN_CODE:
631- return DOWN;
632- break;
633- }
634- }
635- }
636- }
637-
638- if (wasd_enabled) {
639- switch (toupper(string[0])) {
640- case 'A':
641- return LEFT;
642- break;
643- case 'D':
644- return RIGHT;
645- break;
646- case 'W':
647- return UP;
648- break;
649- case 'S':
650- return DOWN;
651- break;
652- }
653- }
654-
655- return NO_DIRECTION;
656-}
Modified file: snake.h+6 additions−6 deletions
@@ -44,12 +44,8 @@ typedef enum {HEIGHT_S, WIDTH_S, SPEED_S, BACK_S, SETTINGS_MENU} settings;
4444 typedef enum {V_FAST, FAST, AVERAGE, SLOW, V_SLOW, SPEED_L} speed;
4545
4646 typedef enum {
47- NO_DIRECTION = -1,
48- UP = 0,
49- LEFT = 1,
50- DOWN = 2,
51- RIGHT = 3,
52- DIRECTIONS = 4
47+ UP, LEFT, DOWN, RIGHT, DIRECTIONS,
48+ ENTER, P_KEY, Q_KEY, ESCAPE
5349 } direction;
5450
5551 typedef enum {
@@ -79,9 +75,13 @@ void update_field(snake my_snake, selected game_size,
7975 selected new_fruit(selected game_size, board_state **board);
8076
8177 bool start_animation();
78+
8279 bool draw_menu(main_menu menu, struct winsize window_size);
80+void draw_settings(settings selected_setting, speed game_speed, selected game_size);
81+
8382 bool draw_board(selected game_size, board_state **board,
8483 struct winsize window_size, bool redraw, bool paused);
84+
8585 void draw_pause(struct winsize window_size,
8686 uint8_t field_width,uint8_t field_height);