jag

snake_c

public

Small snake game in C

Star0
Watch0
e118234aa39babbcab57ae071a03988539e0844c
2
ssh://git@git.jaglekon.de:30/jag/snake_c.git
drawing.cC364 lines9.9 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
bool draw_board(
218
  selected game_size,
219
  board_state **board,
220
  struct winsize window_size, 
221
  bool redraw, bool paused
222
) {
223
224
  uint8_t i, j;
225
226
  uint8_t actual_height = game_size.y + 2;
227
  uint8_t actual_width = game_size.x * 2 + 1 + 2;
228
229
  if (actual_width > window_size.ws_col || actual_height > window_size.ws_row) {
230
231
    printf("\033[2J\033[HToo small\n");
232
    printf("Min width: %i & Min height: %i\n", actual_height, actual_width);
233
234
    return true;
235
  }
236
237
  uint8_t vertical_buffer = (window_size.ws_row - actual_height) >> 1;
238
  uint8_t horizontal_buffer = (window_size.ws_col - actual_width) >> 1;
239
240
  if (redraw) {
241
    printf("\033[2J\033[H");
242
    for (i = 0; i < vertical_buffer; i++)
243
      printf("\n");
244
  } else {
245
    for (i = 0; i < actual_height - 1; i++)
246
      printf("\033[%c", UP_CODE);
247
    printf("\r");
248
  }
249
250
  for (i = 0; i < horizontal_buffer; i++)
251
    printf(" ");
252
  printf("╭");
253
  for (i = 0; i < game_size.x; i++)
254
    printf("──");
255
  printf("─╮\n");
256
257
  for (i = 0; i < game_size.y; i++) {
258
259
    for (j = 0; j < horizontal_buffer; j++)
260
      printf(" ");
261
262
    printf("│");
263
264
    for (j = 0; j < game_size.x; j++)
265
      printf("%s", give_state(board[i][j]));
266
267
    printf("%s", give_state(board[i][0]));
268
269
    printf("\033[%c│\n", LEFT_CODE);
270
  }
271
272
  for (i = 0; i < horizontal_buffer; i++)
273
    printf(" ");
274
  printf("╰");
275
  for (i = 0; i < game_size.x; i++)
276
    printf("──");
277
  printf("─╯");
278
279
  if (paused)
280
    draw_pause(window_size, actual_width, actual_height);
281
282
  fflush(stdout);
283
284
  return false;
285
}
286
287
void draw_pause(struct winsize window_size, uint8_t field_width,
288
                uint8_t field_height) {
289
290
  const uint8_t height = 5;
291
  const uint8_t width = 14;
292
293
  const char *pause_menu[] = {
294
    "+------------+", 
295
    "|            |",
296
    "|   PAUSED   |",
297
    "|            |",
298
    "+------------+"
299
  };
300
301
  const uint8_t going_up = (field_height + height) >> 1;
302
  const uint8_t going_right = (field_width - width) >> 1;
303
304
  const uint8_t horizontal_buffer = (window_size.ws_col - field_width) >> 1;
305
306
  uint8_t i, j;
307
308
  for (i = 0; i < going_up; i++)
309
    printf("\033[%c", UP_CODE);
310
  printf("\r");
311
312
  for (i = 0; i < height; i++) {
313
    for (j = 0; j < horizontal_buffer; j++)
314
      printf("\033[%c", RIGHT_CODE);
315
    for (j = 0; j < going_right; j++)
316
      printf("\033[%c", RIGHT_CODE);
317
318
    printf("\033[37m%s\033[0m\033[%c\r", pause_menu[i], DOWN_CODE);
319
  }
320
321
  for (i = 0; i < going_up - height; i++)
322
    printf("\033[%c", DOWN_CODE);
323
  printf("\r");
324
325
  fflush(stdout);
326
}
327
328
char *give_state(board_state square) {
329
330
  switch (square) {
331
    case FRUIT:
332
      return "\033[32m O\033[0m";
333
      break;
334
    case HEAD_1:
335
      return "\033[33m═\033[31mX\033[0m";
336
      break;
337
    case HEAD_2:
338
      return "\033[31m\33[CX\033[0m";
339
      break;    
340
    case VERTICAL:
341
      return "\033[33m ║\033[0m";
342
      break;
343
    case HORIZONTAL:
344
      return "\033[33m══\033[0m";
345
      break;
346
    case TOP_RIGHT:
347
      return "\033[33m ╚\033[0m";
348
      break;
349
    case TOP_LEFT:
350
      return "\033[33m═╝\033[0m";
351
      break;
352
    case BOTTOM_RIGHT:
353
      return "\033[33m ╔\033[0m";
354
      break;
355
    case BOTTOM_LEFT:
356
      return "\033[33m═╗\033[0m";
357
      break;
358
    default:
359
      return " ·";
360
      break;
361
  }
362
}
363
364