jag

snake_c

public

Small snake game in C

Star0
Watch0
b806cbd5647f1914277e5f38fd2a5992106df41c
2
ssh://git@git.jaglekon.de:30/jag/snake_c.git
drawing.cC475 lines12.2 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
  uint16_t score
320
) {
321
322
  uint8_t i, j;
323
324
  uint8_t actual_height = game_size.y + 2 + 2;
325
  uint8_t actual_width = game_size.x * 2 + 1 + 2;
326
327
  if (actual_width > window_size.ws_col || actual_height > window_size.ws_row) {
328
329
    printf("\033[2J\033[HToo small\n");
330
    printf("Min width: %i & Min height: %i\n", actual_height, actual_width);
331
332
    return true;
333
  }
334
335
  uint8_t vertical_buffer = (window_size.ws_row - actual_height) >> 1;
336
  uint8_t horizontal_buffer = (window_size.ws_col - actual_width) >> 1;
337
338
  if (redraw) {
339
    printf("\033[2J\033[H");
340
    for (i = 0; i < vertical_buffer; i++)
341
      printf("\n");
342
  } else {
343
    for (i = 0; i < actual_height - 1; i++)
344
      printf("\033[%c", UP_CODE);
345
    printf("\r");
346
  }
347
  
348
  for (i = 0; i < ((actual_width - 9) >> 1) + horizontal_buffer; i++)
349
    printf(" ");
350
  printf("╭───────╮\n");
351
    for (i = 0; i < ((actual_width - 9) >> 1) + horizontal_buffer; i++)
352
    printf(" ");
353
  printf("│ \033[32m%05d\033[0m │\n", score);
354
355
  for (i = 0; i < horizontal_buffer; i++)
356
    printf(" ");
357
  printf("╭");
358
  for (i = 0; i < game_size.x; i++)
359
    printf("──");
360
  printf("─╮");
361
  printf("\r");
362
  for (i = 0; i < ((actual_width - 9) >> 1) + horizontal_buffer; i++)
363
    printf("\033[%c", RIGHT_CODE);
364
  printf("┴───────┴\n");
365
366
367
368
  for (i = 0; i < game_size.y; i++) {
369
370
    for (j = 0; j < horizontal_buffer; j++)
371
      printf(" ");
372
373
    printf("│");
374
375
    for (j = 0; j < game_size.x; j++)
376
      printf("%s", give_state(board[i][j]));
377
378
    printf("%s", give_state(board[i][0]));
379
380
    printf("\033[%c│\n", LEFT_CODE);
381
  }
382
383
  for (i = 0; i < horizontal_buffer; i++)
384
    printf(" ");
385
  printf("╰");
386
  for (i = 0; i < game_size.x; i++)
387
    printf("──");
388
  printf("─╯");
389
390
  if (paused)
391
    draw_pause(window_size, actual_width, actual_height);
392
393
  fflush(stdout);
394
395
  return false;
396
}
397
398
void draw_pause(struct winsize window_size, uint8_t field_width,
399
                uint8_t field_height) {
400
401
  const uint8_t height = 5;
402
  const uint8_t width = 14;
403
404
  const char *pause_menu[] = {
405
    "+------------+", 
406
    "|            |",
407
    "|   PAUSED   |",
408
    "|            |",
409
    "+------------+"
410
  };
411
412
  const uint8_t going_up = (field_height + height) >> 1;
413
  const uint8_t going_right = (field_width - width) >> 1;
414
415
  const uint8_t horizontal_buffer = (window_size.ws_col - field_width) >> 1;
416
417
  uint8_t i, j;
418
419
  for (i = 0; i < going_up; i++)
420
    printf("\033[%c", UP_CODE);
421
  printf("\r");
422
423
  for (i = 0; i < height; i++) {
424
    for (j = 0; j < horizontal_buffer; j++)
425
      printf("\033[%c", RIGHT_CODE);
426
    for (j = 0; j < going_right; j++)
427
      printf("\033[%c", RIGHT_CODE);
428
429
    printf("\033[37m%s\033[0m\033[%c\r", pause_menu[i], DOWN_CODE);
430
  }
431
432
  for (i = 0; i < going_up - height; i++)
433
    printf("\033[%c", DOWN_CODE);
434
  printf("\r");
435
436
  fflush(stdout);
437
}
438
439
char *give_state(board_state square) {
440
441
  switch (square) {
442
    case FRUIT:
443
      return "\033[32m O\033[0m";
444
      break;
445
    case HEAD_1:
446
      return "\033[33m═\033[31mX\033[0m";
447
      break;
448
    case HEAD_2:
449
      return "\033[31m\33[CX\033[0m";
450
      break;    
451
    case VERTICAL:
452
      return "\033[33m ║\033[0m";
453
      break;
454
    case HORIZONTAL:
455
      return "\033[33m══\033[0m";
456
      break;
457
    case TOP_RIGHT:
458
      return "\033[33m ╚\033[0m";
459
      break;
460
    case TOP_LEFT:
461
      return "\033[33m═╝\033[0m";
462
      break;
463
    case BOTTOM_RIGHT:
464
      return "\033[33m ╔\033[0m";
465
      break;
466
    case BOTTOM_LEFT:
467
      return "\033[33m═╗\033[0m";
468
      break;
469
    default:
470
      return " ·";
471
      break;
472
  }
473
}
474
475