Small snake game in C
Commit 96e537edae6d
tarball8 files changed+265-171
@@ -26,6 +26,7 @@ add_executable(snake
2626
source/draw.c2727
source/parameters.c2828
source/settings_file/settings_file.c29
+ source/animation/animation.c2930
)3031
3132
target_link_libraries(snake PRIVATE @@ -33,6 +33,7 @@
3333
logic.c \3434
parameters.c \3535
settings_file/settings_file.c \36
+ animation/animation.c \3637
-I${jag-parse-lib}/include \3738
-L${jag-parse-lib}/lib \3839
-ljag_parse \@@ -0,0 +1,166 @@
1
+#include "../snake.h"2
+#include <jag_parse.h>3
+#include <poll.h>4
+5
+#define DELAY 106
+7
+#define KEY_PROTECTION 28
+9
+bool start_animation() { 10
+11
+ struct winsize current_size;12
+ if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, ¤t_size)) == -1)13
+ return false;14
+15
+16
+ char *snake[3][7] = {17
+ {18
+ " ________ ",19
+ " _/ _ \\_",20
+ "________/ (_) ",21
+ "\\ \\ ",22
+ "/_______/ _ ",23
+ " \\_ (_) _",24
+ " \\________/ "25
+ },26
+ {27
+ " ",28
+ "________",29
+ "\\ /",30
+ " \\ / ",31
+ " \\ / ",32
+ "___\\/___",33
+ " ",34
+ },35
+ {36
+ " ",37
+ "__ ",38
+ " \\_____ ",39
+ " \\",40
+ " _____/",41
+ "__/ ",42
+ " "43
+ }44
+ };45
+46
+ uint8_t width_snake[3] = {};47
+48
+ {49
+ uint8_t i;50
+51
+ for (i = 0; i < 3; i++)52
+ width_snake[i] = (uint8_t) strlen(snake[i][0]);53
+ }54
+55
+ uint8_t middle;56
+57
+ uint8_t height = 7;58
+ uint8_t width = width_snake[0] + width_snake[1] + width_snake[2];59
+60
+ for (middle = 1; width < current_size.ws_col; middle++)61
+ width += width_snake[1];62
+63
+ int32_t end = current_size.ws_col + width;64
+65
+66
+ struct pollfd polling[1];67
+68
+ polling[0].fd = STDIN_FILENO;69
+ polling[0].events = POLLIN;70
+71
+ uint8_t wait_incomplete = 0;72
+ bool key_lock = false;73
+74
+ while (end >= 0) {75
+76
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, ¤t_size);77
+78
+ int32_t start = end - width; 79
+80
+ int32_t i, j;81
+ 82
+ printf("\033[2J\033[H");83
+84
+ for (j = 0; j < ((height > current_size.ws_row) ? current_size.ws_row : height) ; j++) {85
+86
+ for (i = 0; i < current_size.ws_col; i++) {87
+ int32_t index = i - start;88
+89
+ if (index >= 0 && index < width) {90
+ if (index < width_snake[0]) {91
+ printf("%c", snake[0][j][index]);92
+ } else if (index < width_snake[0] + width_snake[1] * middle) {93
+ printf("%c", snake[1][j][(index - width_snake[0]) % width_snake[1]]);94
+ } else {95
+ printf("%c", snake[2][j][index - (width_snake[0] + width_snake[1] * middle)]);96
+ }97
+ } else {98
+ printf(" ");99
+ }100
+ } 101
+ 102
+ printf("\n");103
+104
+ }105
+ fflush(stdout);106
+ 107
+ end--;108
+109
+ keypress input[20] = {};110
+ size_t input_len = 0;111
+112
+ if (key_lock)113
+ wait_incomplete++;114
+115
+ if (wait_incomplete >= KEY_PROTECTION) {116
+ input[0] = ESCAPE_KEY;117
+ input_len++;118
+119
+ key_lock = false;120
+ wait_incomplete = 0;121
+122
+ break_unfinished();123
+ }124
+125
+ int is_poll = poll(polling, 1, DELAY);126
+127
+ char string[256] = {};128
+ ssize_t length_string = read(STDIN_FILENO, string, sizeof(string) - 1);129
+ 130
+ add_to_buf(string, length_string);131
+132
+ 133
+ size_t k = input_len;134
+135
+ input[k] = UNKNOWN;136
+137
+ while (input[k] != NO_KEY) {138
+139
+ input[k] = parse_input();140
+141
+ if (input[k] == INCOMPLETE) {142
+ key_lock = true;143
+ break;144
+ } 145
+146
+ k++;147
+ }148
+149
+ input_len = k;150
+151
+ for (k = 0; k < input_len; k++) {152
+ switch (input[k]) {153
+ case Q_KEY:154
+ case ESCAPE_KEY:155
+ return false;156
+ break;157
+ case ENTER_KEY:158
+ end = -1; 159
+ break;160
+ default:161
+ break;162
+ } 163
+ }164
+ }165
+ return true;166
+}@@ -1,118 +1,5 @@
11
#include "snake.h"22
3
-bool start_animation() { 4
-5
- struct winsize current_size;6
- ioctl(STDOUT_FILENO, TIOCGWINSZ, ¤t_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, ¤t_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
- direction pressed_key = read_direction(string, true);77
-78
- if (pressed_key == Q_BUTTON || pressed_key == ESCAPE)79
- return false;80
-81
- if (pressed_key == ENTER)82
- break;83
- }84
-85
- printf("\033[2J\033[H");86
-87
- for (j = 0; j < ((height > current_size.ws_row) ? current_size.ws_row : height) ; j++) {88
-89
- for (i = 0; i < current_size.ws_col; i++) {90
- int32_t index = i - start;91
-92
- if (index >= 0 && index < width) {93
- if (index < width_snake[0]) {94
- printf("%c", snake[0][j][index]);95
- } else if (index < width_snake[0] + width_snake[1] * middle) {96
- printf("%c", snake[1][j][(index - width_snake[0]) % width_snake[1]]);97
- } else {98
- printf("%c", snake[2][j][index - (width_snake[0] + width_snake[1] * middle)]);99
- }100
- } else {101
- printf(" ");102
- }103
- } 104
- 105
- printf("\n");106
-107
- }108
- fflush(stdout);109
- 110
- end--;111
-112
- nanosleep(&mili10, NULL);113
- }114
- return true;115
-}1163
1174
bool draw_menu(main_menu menu, struct winsize window_size) {1185
@@ -534,7 +421,7 @@ void draw_pause(struct winsize window_size, uint8_t field_width,
534421
fflush(stdout);535422
}536423
537
-void draw_highscore (int16_t new_score, score leader_board[SCORE_NUMBER], struct winsize window_size) {424
+void draw_highscore (int16_t new_score, highscore leader_board[SCORE_NUMBER], struct winsize window_size) {538425
539426
uint8_t i, j;540427
@@ -8,17 +8,7 @@ int main(int argc, char *args[]) {
88
if (!parse_parameters(argc, args))99
return 0;1010
11
- printf("\033[?1049h");1211
13
-14
- /* game settings */15
-16
- speed game_speed = AVERAGE;17
- selected game_size = {WIDTH, HEIGHT};18
-19
- score leader_board[SCORE_NUMBER] = {};20
-21
-2212
/* Handling Files to store settings & highscores */2313
2414
@@ -29,22 +19,33 @@ int main(int argc, char *args[]) {
2919
{3020
char xdg_path[PATH_MAX];3121
32
- if (!create_xdg_folder(xdg_path))22
+ if (!create_xdg_folder(xdg_path)) {23
+ printf("Failed to create folder\n");3324
return 1;25
+ }3426
35
- if(!create_folder(SETTINGS_FOLDER ,xdg_path, folder_path))27
+ if(!create_folder(SETTINGS_FOLDER ,xdg_path, folder_path)) {28
+ printf("Failed to create Folder\n");3629
return 1;30
+ }3731
}3832
3933
4034
/* Settings file */41
- 42
- char *settings_path = malloc(strlen(folder_path) + strlen(SETTINGS_FILE) + 2); 35
+36
+37
+ speed game_speed;38
+ selected game_size;39
+40
+41
+ char *settings_path;42
+ if (!(settings_path = malloc(strlen(folder_path) + strlen(SETTINGS_FILE) + 2))) {43
+ printf("alloc_issue");44
+ }4345
sprintf(settings_path, "%s/%s", folder_path, SETTINGS_FILE);4446
4547
4648
{47
-4849
setting_arr settings;4950
5051
if (!init_setting_arr(&settings, 3)) {@@ -52,12 +53,12 @@ int main(int argc, char *args[]) {
5253
return 1;5354
}5455
55
- settings.settings[0] = game_speed;56
- settings.settings[1] = game_size.x;57
- settings.settings[2] = game_size.y;56
+ settings.settings[0] = AVERAGE;57
+ settings.settings[1] = WIDTH;58
+ settings.settings[2] = HEIGHT;5859
5960
if (!read_settings(settings_path, settings)) {60
- printf("Issue reading files\n");61
+ printf("Issue reading settings file\n");6162
return 1;6263
}6364
@@ -71,38 +72,21 @@ int main(int argc, char *args[]) {
7172
7273
/* Highscore file */7374
74
- char *score_path = malloc(strlen(folder_path) + strlen(SCORE_FILE) + 2);75
- sprintf(score_path, "%s/%s", folder_path, SCORE_FILE);76
-77
- {78
- FILE* score_file = fopen(score_path, "r");79
-80
- if (score_file != NULL) {81
-82
- char score_input[STRING_LEN];75
+ highscore leader_board[SCORE_NUMBER] = {};8376
84
- uint8_t i;85
- for (i = 0; i < SCORE_NUMBER; i++) {86
- fgets(score_input, sizeof(score_input), score_file);87
- if (score_input[0] != '\0') {88
- uint8_t j;89
- for(j = 0; score_input[j] != '\0'; j++) {90
- if (score_input[j] == '\n' || score_input[j] == ' ' || score_input[j] == '\t') {91
- score_input[j] = '\0';92
- break;93
- }94
- }95
- score_input[SCORE_LEN - 1] = '\0';96
- strncpy(leader_board[i].name, score_input, SCORE_LEN);97
- }77
+ char *score_path;78
+ if (!(score_path = malloc(strlen(folder_path) + strlen(SCORE_FILE) + 2))) {79
+ printf("alloc issue");80
+ return 1;81
+ }82
+ sprintf(score_path, "%s/%s", folder_path, SCORE_FILE);9883
99
- fgets(score_input, sizeof(score_input), score_file);100
- leader_board[i].points = string_to_num(score_input, 0, UINT16_MAX, leader_board[i].points);101
- }102
- fclose(score_file);103
- }84
+ if (!get_highscore(score_path, leader_board, SCORE_NUMBER)){85
+ printf("Issue reading highscore file\n");86
+ return 1;10487
}10588
89
+10690
/* Setting up terminal with termios */10791
10892
struct termios old, new;@@ -119,8 +103,7 @@ int main(int argc, char *args[]) {
119103
120104
srand(time(NULL));121105
122
- printf("\033[?25l");123
-106
+ /* Get windowssize */124107
struct winsize init_size, current_size;125108
ioctl(STDOUT_FILENO, TIOCGWINSZ, &init_size);126109
current_size = init_size;@@ -128,6 +111,9 @@ int main(int argc, char *args[]) {
128111
129112
bool gameloop = true;130113
114
+ /* Termianl in alternate buffer and hide cursor */115
+ printf("\033[?1049h\033[?25l");116
+131117
/* Animation at the start */132118
if (!start_animation())133119
gameloop = false;@@ -4,8 +4,13 @@ uint8_t read_settings(char *settings_path, setting_arr set_arr) {
44
55
FILE* setting_file = fopen(settings_path, "r");66
7
- if (setting_file == NULL)7
+ if (setting_file == NULL) {8
+ if (errno == ENOENT) 9
+ return 1;10
+11
+ free(set_arr.settings);812
return 0;13
+ }914
1015
char setting_input[SET_LEN]; 1116
@@ -41,3 +46,43 @@ void free_setting_arr(setting_arr set_arr) {
4146
free(set_arr.settings);4247
}4348
49
+50
+51
+52
+uint8_t get_highscore(char *highscore_path, highscore *leader_board, size_t score_ammount) {53
+54
+ FILE* highscore_file = fopen(highscore_path, "r");55
+56
+ if(highscore_file == NULL) 57
+ return (errno == ENOENT) ? 1 : 0;58
+59
+ char score_name[SCORE_LEN];60
+ char score_value[SCORE_LEN];61
+62
+ uint8_t i;63
+ for (i = 0; i < score_ammount; i++) {64
+65
+ fgets(score_name, sizeof(score_name), highscore_file);66
+ 67
+ fgets(score_value, sizeof(score_value), highscore_file);68
+ leader_board[i].points = strtoll(score_value, NULL, 10);;69
+70
+ if (score_name[0] == '\0')71
+ continue;72
+ 73
+ uint8_t j;74
+ for(j = 0; score_name[j] != '\0'; j++) {75
+ if (score_name[j] == '\n' || score_name[j] == ' ' || score_name[j] == '\t') {76
+ score_name[j] = '\0';77
+ break;78
+ }79
+ }80
+ 81
+ score_name[SCORE_LEN - 1] = '\0';82
+ strncpy(leader_board[i].name, score_name, SCORE_LEN); 83
+ }84
+85
+ fclose(highscore_file);86
+87
+ return 1;88
+}@@ -4,20 +4,33 @@
44
#include <stdio.h>55
#include <stdint.h>66
#include <stdlib.h>7
+#include <string.h>8
+9
+#include <errno.h>710
811
#define SET_LEN 10912
13
+#define SCORE_LEN 1014
+15
+1016
typedef struct {1117
int64_t *settings;1218
size_t length;1319
} setting_arr;1420
21
+typedef struct score {22
+ char name[SCORE_LEN];23
+ uint16_t points;24
+} highscore;1525
16
-uint8_t read_settings(char *settings_file, setting_arr set_arr);1726
27
+uint8_t read_settings(char *settings_file, setting_arr set_arr);1828
1929
uint8_t init_setting_arr(setting_arr *set_arr, size_t length);2030
2131
void free_setting_arr(setting_arr set_arr);2232
33
+34
+uint8_t get_highscore(char *highscore_path, highscore *leader_board, size_t score_ammount);35
+2336
#endif@@ -42,7 +42,6 @@
4242
4343
#define STRING_LEN 204444
45
-#define SCORE_LEN 104645
#define SCORE_NUMBER 104746
4847
#define SPEED 50 /* in ms */@@ -85,10 +84,6 @@ typedef struct snake {
8584
uint16_t length;8685
} snake;8786
88
-typedef struct score {89
- char name[SCORE_LEN];90
- uint16_t points;91
-} score;9287
9388
uint8_t update_snake (selected game_size, snake *my_snake, direction shift);9489
void update_field(snake my_snake, selected game_size, @@ -106,7 +101,7 @@ bool draw_board(selected game_size, board_state **board,
106101
void draw_pause(struct winsize window_size, 107102
uint8_t field_width,uint8_t field_height, uint8_t game_over);108103
void draw_highscore (int16_t new_score, 109
- score leader_board[SCORE_NUMBER], struct winsize window_size);104
+ highscore leader_board[SCORE_NUMBER], struct winsize window_size);110105
111106
bool print_buffer(uint16_t width, char *string);