summaryrefslogtreecommitdiff
path: root/snake/snek.c
diff options
context:
space:
mode:
Diffstat (limited to 'snake/snek.c')
-rw-r--r--snake/snek.c228
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;
+}