jag

snake_c

public

Small snake game in C

Star0
Watch0
9357e6aedfb433987568f86b8ff19611c93ee1a9
2
ssh://git@git.jaglekon.de:30/jag/snake_c.git
drawing.cC461 lines11.7 KB
1
#include "snake.h"
2
3
bool start_animation() {  
4
5
  struct winsize current_size;
6
  ioctl(STDOUT_FILENO, TIOCGWINSZ, &current_size);
7
8
  struct timespec mili10 = {0, 1000000 * 10};
9
10
  char *snake[3][7] = {
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
  uint8_t width_snake[3] = {};
41
42
  {
43
    uint8_t i;
44
45
    for (i = 0; i < 3; i++)
46
      width_snake[i] = (uint8_t) strlen(snake[i][0]);
47
  }
48
49
  uint8_t middle;
50
51
  uint8_t height = 7;
52
  uint8_t width = width_snake[0] + width_snake[1] + width_snake[2];
53
54
  for (middle = 1; width < current_size.ws_col; middle++)
55
    width += width_snake[1];
56
57
  int32_t end = current_size.ws_col + width;
58
59
60
61
  while (end >= 0) {
62
63
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &current_size);
64
65
    int32_t start = end - width; 
66
67
    int32_t i, j;
68
 
69
    char string[1000] = {};
70
    ssize_t length_string = read(STDIN_FILENO, string, sizeof(string) - 1);
71
72
     if (length_string > 0) {
73
    
74
      string[length_string] = '\0';
75
76
77
    if (toupper(string[0]) == 'Q')
78
      return false;
79
80
    if (string[0] == '\n')
81
      break;
82
    }
83
84
    printf("\033[2J\033[H");
85
86
    for (j = 0; j < ((height > current_size.ws_row) ? current_size.ws_row : height) ; j++) {
87
88
    for (i = 0; i < current_size.ws_col; i++) {
89
      int32_t index = i - start;
90
91
      if (index >= 0 && index < width) {
92
        if (index < width_snake[0]) {
93
          printf("%c", snake[0][j][index]);
94
        } else if (index < width_snake[0] + width_snake[1] * middle) {
95
          printf("%c", snake[1][j][(index - width_snake[0]) % width_snake[1]]);
96
        } else {
97
          printf("%c", snake[2][j][index - (width_snake[0] + width_snake[1] * middle)]);
98
        }
99
      } else {
100
        printf(" ");
101
      }
102
    }      
103
    
104
      printf("\n");
105
106
    }
107
    fflush(stdout);
108
    
109
    end--;
110
111
    nanosleep(&mili10, NULL);
112
  }
113
  return true;
114
}
115
116
bool draw_menu(main_menu menu, struct winsize window_size) {
117
118
  char *menu_string[] = {"NEW GAME", "SETTINGS", "EXIT"};
119
120
  const uint8_t width_small = 8;
121
  const uint8_t height_small = 5;
122
123
  char *menu_string_big[][6] = {
124
      {"███╗   ██╗███████╗██╗    ██╗     ██████╗  █████╗ ███╗   ███╗███████╗",
125
       "████╗  ██║██╔════╝██║    ██║    ██╔════╝ ██╔══██╗████╗ ████║██╔════╝",
126
       "██╔██╗ ██║█████╗  ██║ █╗ ██║    ██║  ███╗███████║██╔████╔██║█████╗  ",
127
       "██║╚██╗██║██╔══╝  ██║███╗██║    ██║   ██║██╔══██║██║╚██╔╝██║██╔══╝  ",
128
       "██║ ╚████║███████╗╚███╔███╔╝    ╚██████╔╝██║  ██║██║ ╚═╝ ██║███████╗",
129
       "╚═╝  ╚═══╝╚══════╝ ╚══╝╚══╝      ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝"},
130
      {"███████╗███████╗████████╗████████╗██╗███╗   ██╗ ██████╗ ███████╗",
131
       "██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗  ██║██╔════╝ ██╔════╝",
132
       "███████╗█████╗     ██║      ██║   ██║██╔██╗ ██║██║  ███╗███████╗",
133
       "╚════██║██╔══╝     ██║      ██║   ██║██║╚██╗██║██║   ██║╚════██║",
134
       "███████║███████╗   ██║      ██║   ██║██║ ╚████║╚██████╔╝███████║",
135
       "╚══════╝╚══════╝   ╚═╝      ╚═╝   ╚═╝╚═╝  ╚═══╝ ╚═════╝ ╚══════╝"},
136
      {"███████╗██╗  ██╗██╗████████╗", "██╔════╝╚██╗██╔╝██║╚══██╔══╝",
137
       "█████╗   ╚███╔╝ ██║   ██║   ", "██╔══╝   ██╔██╗ ██║   ██║   ",
138
       "███████╗██╔╝ ██╗██║   ██║   ", "╚══════╝╚═╝  ╚═╝╚═╝   ╚═╝   "}};
139
140
  const uint8_t height_line = 6;
141
  const uint8_t height_space = 2;
142
143
  const uint8_t width_text[] = {68, 64, 28};
144
145
  const uint8_t width_big = width_text[0] /*strlen(menu_string_big[0][0])*/;
146
  const uint8_t height_big =
147
      height_line * MAIN_MENU + height_space * (MAIN_MENU - 1);
148
149
  printf("\033[2J\033[H");
150
151
  if (window_size.ws_row < height_small || window_size.ws_col < width_small) {
152
    printf("Too small\n");
153
    return true;
154
  }
155
156
  uint8_t i, j, k;
157
158
  if (window_size.ws_row >= height_big && window_size.ws_col >= width_big) {
159
160
    uint8_t vertical_buffer = (window_size.ws_row - height_big) >> 1;
161
162
    for (i = 0; i < vertical_buffer; i++)
163
      printf("\n");
164
165
    for (i = 0; i < MAIN_MENU; i++) {
166
167
      if (i == menu)
168
        printf("\033[32m");
169
170
      uint8_t horizontal_buffer = (window_size.ws_col - width_text[i]) >> 1;
171
172
      for (j = 0; j < height_line; j++) {
173
174
        for (k = 0; k < horizontal_buffer; k++)
175
          printf(" ");
176
177
        printf("%s", menu_string_big[i][j]);
178
179
        if (j != height_line - 1)
180
          printf("\n");
181
      }
182
183
      printf("\033[0m");
184
185
      if (i != MAIN_MENU - 1)
186
        printf("\n\n");
187
    }
188
189
  } else {
190
191
    uint8_t vertical_buffer = (window_size.ws_row - height_small) >> 1;
192
193
    for (i = 0; i < vertical_buffer; i++)
194
      printf("\n");
195
196
    for (i = 0; i < MAIN_MENU; i++) {
197
      if (i == menu)
198
        printf("\033[32m");
199
200
      uint8_t horizontal_buffer =
201
          (window_size.ws_col - strlen(menu_string[i])) >> 1;
202
203
      for (j = 0; j < horizontal_buffer; j++)
204
        printf(" ");
205
206
      printf("%s\033[0m", menu_string[i]);
207
208
      if (i != MAIN_MENU - 1)
209
        printf("\n\n");
210
    }
211
  }
212
213
  fflush(stdout);
214
  return false;
215
}
216
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
314
bool draw_board(
315
  selected game_size,
316
  board_state **board,
317
  struct winsize window_size, 
318
  bool redraw, bool paused
319
) {
320
321
  uint8_t i, j;
322
323
  uint8_t actual_height = game_size.y + 2;
324
  uint8_t actual_width = game_size.x * 2 + 1 + 2;
325
326
  if (actual_width > window_size.ws_col || actual_height > window_size.ws_row) {
327
328
    printf("\033[2J\033[HToo small\n");
329
    printf("Min width: %i & Min height: %i\n", actual_height, actual_width);
330
331
    return true;
332
  }
333
334
  uint8_t vertical_buffer = (window_size.ws_row - actual_height) >> 1;
335
  uint8_t horizontal_buffer = (window_size.ws_col - actual_width) >> 1;
336
337
  if (redraw) {
338
    printf("\033[2J\033[H");
339
    for (i = 0; i < vertical_buffer; i++)
340
      printf("\n");
341
  } else {
342
    for (i = 0; i < actual_height - 1; i++)
343
      printf("\033[%c", UP_CODE);
344
    printf("\r");
345
  }
346
347
  for (i = 0; i < horizontal_buffer; i++)
348
    printf(" ");
349
  printf("╭");
350
  for (i = 0; i < game_size.x; i++)
351
    printf("──");
352
  printf("─╮\n");
353
354
  for (i = 0; i < game_size.y; i++) {
355
356
    for (j = 0; j < horizontal_buffer; j++)
357
      printf(" ");
358
359
    printf("│");
360
361
    for (j = 0; j < game_size.x; j++)
362
      printf("%s", give_state(board[i][j]));
363
364
    printf("%s", give_state(board[i][0]));
365
366
    printf("\033[%c│\n", LEFT_CODE);
367
  }
368
369
  for (i = 0; i < horizontal_buffer; i++)
370
    printf(" ");
371
  printf("╰");
372
  for (i = 0; i < game_size.x; i++)
373
    printf("──");
374
  printf("─╯");
375
376
  if (paused)
377
    draw_pause(window_size, actual_width, actual_height);
378
379
  fflush(stdout);
380
381
  return false;
382
}
383
384
void draw_pause(struct winsize window_size, uint8_t field_width,
385
                uint8_t field_height) {
386
387
  const uint8_t height = 5;
388
  const uint8_t width = 14;
389
390
  const char *pause_menu[] = {
391
    "+------------+", 
392
    "|            |",
393
    "|   PAUSED   |",
394
    "|            |",
395
    "+------------+"
396
  };
397
398
  const uint8_t going_up = (field_height + height) >> 1;
399
  const uint8_t going_right = (field_width - width) >> 1;
400
401
  const uint8_t horizontal_buffer = (window_size.ws_col - field_width) >> 1;
402
403
  uint8_t i, j;
404
405
  for (i = 0; i < going_up; i++)
406
    printf("\033[%c", UP_CODE);
407
  printf("\r");
408
409
  for (i = 0; i < height; i++) {
410
    for (j = 0; j < horizontal_buffer; j++)
411
      printf("\033[%c", RIGHT_CODE);
412
    for (j = 0; j < going_right; j++)
413
      printf("\033[%c", RIGHT_CODE);
414
415
    printf("\033[37m%s\033[0m\033[%c\r", pause_menu[i], DOWN_CODE);
416
  }
417
418
  for (i = 0; i < going_up - height; i++)
419
    printf("\033[%c", DOWN_CODE);
420
  printf("\r");
421
422
  fflush(stdout);
423
}
424
425
char *give_state(board_state square) {
426
427
  switch (square) {
428
    case FRUIT:
429
      return "\033[32m O\033[0m";
430
      break;
431
    case HEAD_1:
432
      return "\033[33m═\033[31mX\033[0m";
433
      break;
434
    case HEAD_2:
435
      return "\033[31m\33[CX\033[0m";
436
      break;    
437
    case VERTICAL:
438
      return "\033[33m ║\033[0m";
439
      break;
440
    case HORIZONTAL:
441
      return "\033[33m══\033[0m";
442
      break;
443
    case TOP_RIGHT:
444
      return "\033[33m ╚\033[0m";
445
      break;
446
    case TOP_LEFT:
447
      return "\033[33m═╝\033[0m";
448
      break;
449
    case BOTTOM_RIGHT:
450
      return "\033[33m ╔\033[0m";
451
      break;
452
    case BOTTOM_LEFT:
453
      return "\033[33m═╗\033[0m";
454
      break;
455
    default:
456
      return " ·";
457
      break;
458
  }
459
}
460
461