diff options
Diffstat (limited to 'snake/snek.c')
-rw-r--r-- | snake/snek.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/snake/snek.c b/snake/snek.c new file mode 100644 index 0000000..1021015 --- /dev/null +++ b/snake/snek.c @@ -0,0 +1,228 @@ +#include <raylib.h> +#include <stdlib.h> +#include <stdio.h> + +/* typedef struct map_t { */ + +/* } Map; */ + +const int screenHeight = 800; +const int screenWidth = 800; +int fps = 60; +int rows = 10; +int cols = 10; +int size; +int food_x; +int food_y; +int score = 0; +char score_text[16] = "0"; + +typedef enum directions { + UP, + DOWN, + LEFT, + RIGHT +} Direction; + +typedef struct snake_body { + int x; + int y; +} SnakeBody; + +typedef struct snake_t { + SnakeBody *body; + int max_length; + int length; + int direction; + int frame_duration; + bool alive; +} Snake; + +Snake make_snake(int max_len, int speed){ + Snake snek; + if (max_len < 3){ + snek.alive = false; + snek.length = 0; + return snek; + } + + snek.body = (SnakeBody*) calloc(max_len, sizeof(SnakeBody)); + snek.max_length = max_len; + snek.length = 3; + snek.body[0].x = GetRandomValue(0, cols - 1); + snek.body[0].y = GetRandomValue(0, rows - 1); + snek.frame_duration = fps / speed; + snek.direction = snek.body[0].x < cols / 2 ? RIGHT : LEFT; + snek.alive = true; + snek.body[1] = snek.body[2] = snek.body[0]; + snek.body[1].x += snek.direction == LEFT ? 1 : -1; + snek.body[2].x += snek.direction == LEFT ? 2 : -2; + return snek; +} + +void free_snake(Snake* s){ + free(s->body); +} + +void grow_snake(Snake* s){ + int i = s->length; + if (i < s->max_length){ + s->body[i] = (SnakeBody) { + 2 * s->body[i - 1].x - s->body[i - 2].x, + 2 * s->body[i - 1].y - s->body[i - 2].y + }; + + s->length++; + } +} + +void draw_snake(Snake* s){ + for (int i = 0; i < s->length; i++){ + DrawRectangle(size * s->body[i].x, size * s->body[i].y, size, size, BLACK); + } + return ; +} + +bool collides_with_snake(Snake* s, int x, int y){ + for (int i = 0; i < s->length; i++){ + if (s->body[i].x == x && s->body[i].y == y){ + return true; + } + } + return false; +} + +void place_food(Snake* s){ + do { + food_x = GetRandomValue(0, cols - 1); + food_y = GetRandomValue(0, rows - 1); + } while (collides_with_snake(s, food_x, food_y)); +} + +void move_snake(Snake* s){ + SnakeBody temp1 = s->body[0]; + SnakeBody temp2; + switch (s->direction){ + case LEFT: + s->body[0].x--; + if (s->body[0].x < 0 || s->body[0].x >= cols){ + s->alive = false; + } + break; + case RIGHT: + s->body[0].x++; + if (s->body[0].x < 0 || s->body[0].x >= cols){ + s->alive = false; + } + break; + case UP: + s->body[0].y--; + if (s->body[0].y < 0 || s->body[0].y >= rows){ + s->alive = false; + } + break; + case DOWN: + s->body[0].y++; + if (s->body[0].x < 0 || s->body[0].y >= rows){ + s->alive = false; + } + break; + } + for (int i = 1; i < s->length; i++){ + if (s->body[0].x == s->body[i].x && + s->body[0].y == s->body[i].y){ + s->alive = false; + break; + } + temp2 = s->body[i]; + s->body[i] = temp1; + temp1 = temp2; + } +} + + +/* int frame = 0; */ +void update_snake(Snake* s){ + static int frame = 0; + if (frame++ > s->frame_duration){ + move_snake(s); + frame = 0; + } + int key; + while ((key = GetKeyPressed()) != 0){ + switch (key){ + case KEY_W: + s->direction = UP; + break; + case KEY_A: + s->direction = LEFT; + break; + case KEY_S: + s->direction = DOWN; + break; + case KEY_D: + s->direction = RIGHT; + break; + case KEY_G: + grow_snake(s); + } + } + if (collides_with_snake(s, food_x, food_y)){ + food_x = food_y = -1; + score++; + snprintf(score_text, 16, "%d", score); + grow_snake(s); + place_food(s); + } +} + +void draw_grid(int size){ + /* DrawGrid(10, screenWidth / 10); */ + + for (int i = 0; i < rows; i++){ + DrawLine(0, i * size, screenWidth, i * size, BLACK); + } + for (int j = 0; j < cols; j++){ + DrawLine(j * size, 0, j * size, screenHeight, BLACK); + } +} + +void init_game(){ + InitWindow(screenHeight, screenHeight, "Snek"); + SetTargetFPS(fps); + + int width = screenWidth / cols; + int height = screenHeight / rows; + size = height > width ? width : height; +} + +int main(void){ + + init_game(); + Snake snek = make_snake(100, 5); + + while (!WindowShouldClose()){ + BeginDrawing(); + + ClearBackground(WHITE); + draw_grid(size); + if (snek.alive){ + update_snake(&snek); + } else { + DrawText("Died!", screenWidth / 2, screenHeight / 2, 20, BLACK); + } + if (food_x >= 0){ + DrawRectangle(size * food_x, size * food_y, size, size, RED); + } + draw_snake(&snek); + DrawText(score_text, 0, 0, 20, BLACK); + + EndDrawing(); + } + + free_snake(&snek); + + CloseWindow(); + + return 0; +} |