diff --git a/main.c b/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7c71bc22f68bf98c1fd602a2acc6234dac9b8927 --- /dev/null +++ b/main.c @@ -0,0 +1,171 @@ +#include "raylib.h" +#include "stdbool.h" +#include "stdio.h" + +#define SNAKE_LENGTH 256 +#define SQUARE_SIZE 20 + +typedef struct Snake { + Vector2 position; + Vector2 size; + Vector2 speed; + Color color; +} Snake; + +typedef struct Food { + Vector2 position; + Vector2 size; + Texture2D texture; // texture for the apple icon +} Food; + +typedef struct Barrier { + Vector2 position; + Vector2 size; + Texture2D texture; +} Barrier; + +void InitializeGame(Snake snake[], int *snakeLength, Food *food, Barrier barriers[], int *barrierCount, int screenWidth, int screenHeight); +void UpdateGame(Snake snake[], int *snakeLength, Food *food, Barrier barriers[], int *barrierCount, int *score, float *delay, int screenWidth, int screenHeight); +void DrawGame(Snake snake[], int snakeLength, Food food, Barrier barriers[], int barrierCount, int score); + +int main() { + const int screenWidth = 900; + const int screenHeight = 600; + + InitWindow(screenWidth, screenHeight, "Snake Game"); + + Snake snake[SNAKE_LENGTH]; + int snakeLength = 1; + Food food; + Barrier barriers[50]; // maximum of 50 barriers + int barrierCount = 0; + int score = 0; + float delay = 0.3f; // Initial delay in seconds + + InitializeGame(snake, &snakeLength, &food, barriers, &barrierCount, screenWidth, screenHeight); + + SetTargetFPS(60); + + while (!WindowShouldClose()) { + UpdateGame(snake, &snakeLength, &food, barriers, &barrierCount, &score, &delay, screenWidth, screenHeight); + + BeginDrawing(); + ClearBackground(RAYWHITE); + DrawGame(snake, snakeLength, food, barriers, barrierCount, score); + EndDrawing(); + } + + // Unload the apple texture + UnloadTexture(food.texture); + + // Unload the fence textures + for (int i = 0; i < barrierCount; i++) { + UnloadTexture(barriers[i].texture); + } + + CloseWindow(); + + return 0; +} + +void InitializeGame(Snake snake[], int *snakeLength, Food *food, Barrier barriers[], int *barrierCount, int screenWidth, int screenHeight) { + for (int i = 0; i < SNAKE_LENGTH; i++) { + snake[i].position = (Vector2){ screenWidth/2, screenHeight/2 }; + snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + snake[i].speed = (Vector2){ SQUARE_SIZE, 0 }; + snake[i].color = PINK; + } + + *snakeLength = 1; + + // Load the apple texture + food->texture = LoadTexture("resources/apple2.png"); + if (food->texture.id == 0) { + printf("Failed to load apple texture\n"); + } + food->size = (Vector2){ food->texture.width, food->texture.height }; + food->position = (Vector2){ GetRandomValue(0, screenWidth/SQUARE_SIZE - 1) * SQUARE_SIZE, + GetRandomValue(0, screenHeight/SQUARE_SIZE - 1) * SQUARE_SIZE }; + + // Load the fence texture for barriers + Texture2D fenceTexture = LoadTexture("resources/fence.png"); + if (fenceTexture.id == 0) { + printf("Failed to load fence texture\n"); + } + + *barrierCount = 0; // Initialize barrier count +} + +void UpdateGame(Snake snake[], int *snakeLength, Food *food, Barrier barriers[], int *barrierCount, int *score, float *delay, int screenWidth, int screenHeight) { + static float timer = 0.0f; + timer += GetFrameTime(); + + // Detect key presses and update snake direction + if (IsKeyDown(KEY_RIGHT) && snake[0].speed.x == 0) { + snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; + } else if (IsKeyDown(KEY_LEFT) && snake[0].speed.x == 0) { + snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 }; + } else if (IsKeyDown(KEY_UP) && snake[0].speed.y == 0) { + snake[0].speed = (Vector2){ 0, -SQUARE_SIZE }; + } else if (IsKeyDown(KEY_DOWN) && snake[0].speed.y == 0) { + snake[0].speed = (Vector2){ 0, SQUARE_SIZE }; + } + + if (timer >= *delay) { + // Move snake + for (int i = *snakeLength - 1; i > 0; i--) { + snake[i].position = snake[i - 1].position; + } + snake[0].position.x += snake[0].speed.x; + snake[0].position.y += snake[0].speed.y; + + // Wrap snake around screen + if (snake[0].position.x >= screenWidth) snake[0].position.x = 0; + else if (snake[0].position.x < 0) snake[0].position.x = screenWidth - SQUARE_SIZE; + if (snake[0].position.y >= screenHeight) snake[0].position.y = 0; + else if (snake[0].position.y < 0) snake[0].position.y = screenHeight - SQUARE_SIZE; + + // Check for collision with food + if (CheckCollisionRecs((Rectangle){ snake[0].position.x, snake[0].position.y, snake[0].size.x, snake[0].size.y }, + (Rectangle){ food->position.x, food->position.y, food->size.x, food->size.y })) { + (*snakeLength)++; + (*score)++; + food->position = (Vector2){ GetRandomValue(0, screenWidth/SQUARE_SIZE - 1) * SQUARE_SIZE, + GetRandomValue(0, screenHeight/SQUARE_SIZE - 1) * SQUARE_SIZE }; + + // Add a new barrier every 9 points + if (*score % 9 == 0) { + barriers[*barrierCount].texture = LoadTexture("resources/fence.png"); + barriers[*barrierCount].size = (Vector2){ barriers[*barrierCount].texture.width, barriers[*barrierCount].texture.height }; + barriers[*barrierCount].position = (Vector2){ GetRandomValue(0, screenWidth/SQUARE_SIZE - 1) * SQUARE_SIZE, + GetRandomValue(0, screenHeight/SQUARE_SIZE - 1) * SQUARE_SIZE }; + (*barrierCount)++; + } + + // Adjust delay based on score + if (*score % 5 == 0 && *score != 0) { + *delay -= 0.01f; // Decrease delay to increase speed + if (*delay < 0.05f) *delay = 0.05f; // Set a minimum delay + } + } + + // Check for collision with barriers + for (int i = 0; i < *barrierCount; i++) { + if (CheckCollisionRecs((Rectangle){ snake[0].position.x, snake[0].position.y, snake[0].size.x, snake[0].size.y }, + (Rectangle){ barriers[i].position.x, barriers[i].position.y, barriers[i].size.x, barriers[i].size.y })) { + // Deduct 3 points for collision with barrier + (*score) -= 3; + if (*score < 0) *score = 0; // Ensure score doesn't go below 0 + + // End game if score reaches 0 + if (*score == 0) { + printf("Game Over! You reached 0 points.\n"); + CloseWindow(); + return; + } + } + } + + timer = 0.0f; // Reset timer + } +}