#include #include // malloc, rand #include // time #include // sprintf int screen_width = 800; int screen_heigth = 700; int cell_size = 22; typedef struct snake_body { float x, y; struct snake_body *next; } snake_body; struct snake { snake_body *head; } snake; bool dead = false; float speed = 10.0f; enum { UP, DOWN, LEFT, RIGHT, NONE } direction; int score; void input(void); void update(void); void prepare_game(void); Vector2 fruit; int main(){ // Round up screen size to be multiple of cell_size screen_width += screen_width % cell_size; screen_heigth += screen_heigth % cell_size; InitWindow(screen_width, screen_heigth, "Snake"); SetTargetFPS(144); srand(time(0)); snake.head = malloc(sizeof(snake_body)); prepare_game(); while (!WindowShouldClose()){ input(); if (!dead && direction != NONE) update(); BeginDrawing(); ClearBackground(BLACK); DrawCircle((int)fruit.x * cell_size + cell_size / 2, // It's a circle, so the center is the middle of the cell (int)fruit.y * cell_size + cell_size / 2, cell_size / 2, RED); snake_body *body = snake.head->next; while (body){ DrawRectangle((int)body->x * cell_size, (int)body->y * cell_size, cell_size, cell_size, GREEN); body = body->next; } // Draw the head in a darker shade of green DrawRectangle((int)snake.head->x * cell_size, (int)snake.head->y * cell_size, cell_size, cell_size, DARKGREEN); if (dead){ DrawText("GAME OVER", (screen_width / 2) - 100, (screen_heigth / 2) - 40, 30, WHITE); DrawText("Press [Space] to restart", (screen_width / 2) - 100, (screen_heigth / 2) - 10, 15, WHITE); char buf[100]; sprintf(buf, "Score: %d", score); DrawText(buf, 5,5, 25, WHITE); direction = NONE; } EndDrawing(); } CloseWindow(); return 0; } void input(void){ if ((IsKeyPressed(KEY_A) || IsKeyPressed(KEY_LEFT)) && direction != RIGHT) direction = LEFT; else if ((IsKeyPressed(KEY_W) || IsKeyPressed(KEY_UP)) && direction != DOWN) direction = UP; else if ((IsKeyPressed(KEY_D) || IsKeyPressed(KEY_RIGHT)) && direction != LEFT) direction = RIGHT; else if ((IsKeyPressed(KEY_S) || IsKeyPressed(KEY_DOWN)) && direction != UP) direction = DOWN; if (dead && IsKeyPressed(KEY_SPACE)){ dead = false; snake_body *body = snake.head->next; while (body){ snake_body *ptr = body; body = body->next; free(ptr); } prepare_game(); } } bool collision_fruit_snake(){ snake_body *body = snake.head; while (body){ if ((int)fruit.x == (int)body->x && (int)fruit.y == (int)body->y) return true; body = body->next; } return false; } void update(void){ Vector2 prev = {snake.head->x, snake.head->y}; switch (direction){ case UP: snake.head->y -= speed * GetFrameTime(); break; case DOWN: snake.head->y += speed * GetFrameTime(); break; case LEFT: snake.head->x -= speed * GetFrameTime(); break; case RIGHT: snake.head->x += speed * GetFrameTime(); break; default: break; } if ((int)snake.head->x == (int)prev.x && (int)snake.head->y == (int)prev.y) return; if (snake.head->x < 0 || (snake.head->x * cell_size) >= screen_width || snake.head->y < 0 || (snake.head->y * cell_size) >= screen_heigth){ dead = true; snake.head->x = prev.x; snake.head->y = prev.y; return; } snake_body *body = snake.head; while (body->next){ if ((int)body->next->x == (int)snake.head->x && (int)body->next->y == (int)snake.head->y) dead = true; Vector2 tmp = {body->next->x, body->next->y}; body->next->x = prev.x; body->next->y = prev.y; prev = tmp; body = body->next; } if (collision_fruit_snake()){ body->next = malloc(sizeof(snake_body)); body->next->x = prev.x; body->next->y = prev.y; body->next->next = NULL; speed += 0.1; score += 20; do{ fruit.x = rand() % (screen_width / cell_size); fruit.y = rand() % (screen_heigth / cell_size); }while (collision_fruit_snake()); } } void prepare_game(void){ snake.head->x = screen_width / cell_size / 2; snake.head->y = screen_heigth / cell_size / 2; snake.head->next = NULL; do{ fruit.x = rand() % (screen_width / cell_size); fruit.y = rand() % (screen_heigth / cell_size); }while (collision_fruit_snake()); direction = NONE; score = 0; }