From 19b8ce813a0e3adc8bf09a637a2ca37f32b6cf2d Mon Sep 17 00:00:00 2001 From: "DESKTOP-3SJQ2V2\\PC" Date: Mon, 17 Apr 2023 01:38:13 +0700 Subject: [PATCH] Snake sample --- MyGame/example-raylib/example-raylib.vcxproj | 2 + .../example-raylib.vcxproj.filters | 6 + MyGame/example-raylib/snake.c | 286 ++++++++++++++++++ MyGame/example-raylib/snake_remake.c | 259 ++++++++++++++++ examples/shaders/shaders_basic_lighting.c | 2 +- 5 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 MyGame/example-raylib/snake.c create mode 100644 MyGame/example-raylib/snake_remake.c diff --git a/MyGame/example-raylib/example-raylib.vcxproj b/MyGame/example-raylib/example-raylib.vcxproj index 1a6a68172..bccbd7c44 100644 --- a/MyGame/example-raylib/example-raylib.vcxproj +++ b/MyGame/example-raylib/example-raylib.vcxproj @@ -156,6 +156,8 @@ + + diff --git a/MyGame/example-raylib/example-raylib.vcxproj.filters b/MyGame/example-raylib/example-raylib.vcxproj.filters index 37470e20b..19f66b859 100644 --- a/MyGame/example-raylib/example-raylib.vcxproj.filters +++ b/MyGame/example-raylib/example-raylib.vcxproj.filters @@ -18,5 +18,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/MyGame/example-raylib/snake.c b/MyGame/example-raylib/snake.c new file mode 100644 index 000000000..119276f48 --- /dev/null +++ b/MyGame/example-raylib/snake.c @@ -0,0 +1,286 @@ +/******************************************************************************************* +* +* raylib - classic game: snake +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) +#include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define SNAKE_LENGTH 256 +#define SQUARE_SIZE 40 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Snake { + Vector2 position; + Vector2 size; + Vector2 speed; + Color color; +} Snake; + +typedef struct Food { + Vector2 position; + Vector2 size; + bool active; + Color color; +} Food; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static const int screenWidth = 800; +static const int screenHeight = 450; + +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; + +static Food fruit = { 0 }; +static Snake snake[SNAKE_LENGTH] = { 0 }; +static Vector2 snakePosition[SNAKE_LENGTH] = { 0 }; +static bool allowMove = false; +static Vector2 offset = { 0 }; +static int counterTail = 0; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main_old2(void) +{ + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "classic game: snake"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 60, 1); +#else + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update and Draw + //---------------------------------------------------------------------------------- + UpdateDrawFrame(); + //---------------------------------------------------------------------------------- + } +#endif + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + framesCounter = 0; + gameOver = false; + pause = false; + + counterTail = 1; + allowMove = false; + + offset.x = screenWidth % SQUARE_SIZE; + offset.y = screenHeight % SQUARE_SIZE; + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snake[i].position = (Vector2){ offset.x / 2, offset.y / 2 }; // initial position middle of the window ? + snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + snake[i].speed = (Vector2){ SQUARE_SIZE, 0 }; + + if (i == 0) snake[i].color = DARKBLUE; + else snake[i].color = BLUE; + } + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snakePosition[i] = (Vector2){ 0.0f, 0.0f }; + } + + fruit.size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + fruit.color = SKYBLUE; + fruit.active = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player control + if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_LEFT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_UP) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, -SQUARE_SIZE }; + allowMove = false; + } + if (IsKeyPressed(KEY_DOWN) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, SQUARE_SIZE }; + allowMove = false; + } + + // Snake movement + for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position; + + if ((framesCounter % 5) == 0) + { + for (int i = 0; i < counterTail; i++) + { + if (i == 0) + { + snake[0].position.x += snake[0].speed.x; + snake[0].position.y += snake[0].speed.y; + allowMove = true; + } + else snake[i].position = snakePosition[i - 1]; + } + } + + // Wall behaviour + if (((snake[0].position.x) > (screenWidth - offset.x)) || + ((snake[0].position.y) > (screenHeight - offset.y)) || + (snake[0].position.x < 0) || (snake[0].position.y < 0)) + { + gameOver = true; + } + + // Collision with yourself + for (int i = 1; i < counterTail; i++) + { + if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true; + } + + // Fruit position calculation + if (!fruit.active) + { + fruit.active = true; + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x / 2, GetRandomValue(0, (screenHeight / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.y / 2 }; + + for (int i = 0; i < counterTail; i++) + { + while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y)) + { + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x / 2, GetRandomValue(0, (screenHeight / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.y / 2 }; + i = 0; + } + } + } + + // Collision + if ((snake[0].position.x < (fruit.position.x + fruit.size.x) && (snake[0].position.x + snake[0].size.x) > fruit.position.x) && + (snake[0].position.y < (fruit.position.y + fruit.size.y) && (snake[0].position.y + snake[0].size.y) > fruit.position.y)) + { + snake[counterTail].position = snakePosition[counterTail - 1]; + counterTail += 1; + fruit.active = false; + } + + framesCounter++; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw grid lines + for (int i = 0; i < screenWidth / SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2) { SQUARE_SIZE* i + offset.x / 2, offset.y / 2 }, (Vector2) { SQUARE_SIZE* i + offset.x / 2, screenHeight - offset.y / 2 }, LIGHTGRAY); + } + + for (int i = 0; i < screenHeight / SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2) { offset.x / 2, SQUARE_SIZE* i + offset.y / 2 }, (Vector2) { screenWidth - offset.x / 2, SQUARE_SIZE* i + offset.y / 2 }, LIGHTGRAY); + } + + // Draw snake + for (int i = 0; i < counterTail; i++) DrawRectangleV(snake[i].position, snake[i].size, snake[i].color); + + // Draw fruit to pick + DrawRectangleV(fruit.position, fruit.size, fruit.color); + + if (pause) DrawText("GAME PAUSED", screenWidth / 2 - MeasureText("GAME PAUSED", 40) / 2, screenHeight / 2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth() / 2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20) / 2, GetScreenHeight() / 2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/MyGame/example-raylib/snake_remake.c b/MyGame/example-raylib/snake_remake.c new file mode 100644 index 000000000..e0eaccb28 --- /dev/null +++ b/MyGame/example-raylib/snake_remake.c @@ -0,0 +1,259 @@ +#include "raylib.h" + +// Some defines +#define SNAKE_LENGTH 24 +#define BOX_SIZE 50 + +// Types and structure definition +typedef struct Snake +{ + Vector2 position; + Color color; +} Snake; + +typedef struct Food +{ + Vector2 position; + Color color; +} Food; + +typedef struct Offset +{ + int x, y; +} Offset; + +// Global variable declaration +static const int screenWidth = 1030; +static Snake snake[SNAKE_LENGTH] = {0}; +static const int screenHeight = 780; +static Food fruit = { 0 }; +static bool gameOver = false; +static bool pause = false; +static Offset offset = { 0 }; +static int tailCount = 0; +static bool isFruitAvailable = false; +static bool shouldFruitSpawn = false; +static Vector2 snakeSpeed = { 0 }; +static int frameCounter = 0; +static int allowInput = false; + +// Modules declaration (local) +static void InitGame(void); +static void UpdateGame(void); +static void DrawGame(void); +static void UnloadGame(void); +static void UpdateDrawFrame(void); + +int main(void) +{ + InitWindow(screenWidth, screenHeight, "The Snake Game"); + InitGame(); + // Main game loop + SetTargetFPS(60); + while (!WindowShouldClose()) + { + UpdateDrawFrame(); + } + UnloadGame(); + CloseWindow(); + + + return 0; +} + +static void InitGame(void) +{ + // Init some vars + gameOver = false; + pause = false; + offset.x = screenWidth % BOX_SIZE; + offset.y = screenHeight % BOX_SIZE; + tailCount = 0; + snakeSpeed = (Vector2){ BOX_SIZE, 0 }; + // snake initial position + for (int i = 0; i < SNAKE_LENGTH; i++) + { + if (i == 0) + { + snake[i].color = BLUE; + snake[i].position = (Vector2){ offset.x / 2, offset.y / 2 }; + } + else { + snake[i].color = LIGHTGRAY; + snake[i].position = (Vector2){ -100, -100 }; + } + } + fruit.color = RED; + shouldFruitSpawn = true; + allowInput = true; + + +} + +static void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +static void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P') )pause = !pause; + if (!pause) + { + // handle snake + // Player input + if (IsKeyPressed(KEY_RIGHT) && allowInput && snakeSpeed.x == 0) + { + snakeSpeed = (Vector2){ BOX_SIZE, 0 }; + allowInput = false; + } + if (IsKeyPressed(KEY_DOWN) && allowInput && snakeSpeed.y == 0) + { + snakeSpeed = (Vector2){ 0, BOX_SIZE }; + allowInput = false; + } + if (IsKeyPressed(KEY_LEFT) && allowInput && snakeSpeed.x == 0) + { + snakeSpeed = (Vector2){ - BOX_SIZE, 0 }; + allowInput = false; + } + if (IsKeyPressed(KEY_UP) && allowInput && snakeSpeed.y == 0) + { + snakeSpeed = (Vector2){ 0, - BOX_SIZE }; + allowInput = false; + } + + // Snake movement + if (frameCounter % 5 == 0) + { + // tail positions + for (int i = tailCount; i > 0; i--) + { + //printf("%d", tailCount); + snake[i].position.x = snake[i - 1].position.x; + snake[i].position.y = snake[i - 1].position.y; + } + // head position + //printf("%f", snake[0].position.x); + snake[0].position.x += snakeSpeed.x; + snake[0].position.y += snakeSpeed.y; + allowInput = true; + } + + + + + // handle fruit + // check if fruit should be spawn + if (shouldFruitSpawn) + { + while (!isFruitAvailable) + { + isFruitAvailable = true; + fruit.position.x = offset.x /2 + GetRandomValue(0 , screenWidth / BOX_SIZE - 1) * BOX_SIZE; + fruit.position.y = offset.y/2 + GetRandomValue(0, screenHeight / BOX_SIZE - 1) * BOX_SIZE; + + for (int i = 0; i < tailCount ; i++) + { + // Check if fruit spawn is overlap with any of the snake body + if ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y)) + { + isFruitAvailable = false; + shouldFruitSpawn = false; + } + } + } + } + + // handle collision + // collision with fruit + if (snake[0].position.x == fruit.position.x && snake[0].position.y == fruit.position.y) + { + tailCount++; + shouldFruitSpawn = true; + isFruitAvailable = false; + } + // collision with wall + /*if ((snake[0].position.x > screenWidth - offset.x || snake[0].position.x < 0) || + (snake[0].position.y > screenHeight - offset.y || snake[0].position.y < 0)) + gameOver = true;*/ + if (((snake[0].position.x) > (screenWidth - offset.x)) || + ((snake[0].position.y) > (screenHeight - offset.y)) || + (snake[0].position.x < 0) || (snake[0].position.y < 0)) + { + gameOver = true; + } + + // collision with self + for (int i = 1; i <= tailCount; i++) + { + gameOver = (snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y); + if (gameOver) + { + break; + } + } + frameCounter++; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + } + } +} + + +static void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw grid vertical + for (int i = 0; i < screenWidth / BOX_SIZE + 1; i++) + { + DrawLine( offset.x /2 + i * BOX_SIZE, offset.y / 2, offset.x /2 + i * BOX_SIZE, screenHeight - offset.y / 2, GRAY); + + } + // Draw grid horizontal + for (int i = 0; i < screenHeight / BOX_SIZE + 1; i++) + { + DrawLine( offset.x / 2, offset.y /2 + i * BOX_SIZE, screenWidth - offset.x /2 , offset.y /2 + i * BOX_SIZE, GRAY); + } + // Draw snake head + DrawRectangle(snake[0].position.x, snake[0].position.y, BOX_SIZE, BOX_SIZE, snake[0].color); + // Draw snake tail + for (int i = tailCount; i > 0; i--) + { + DrawRectangle(snake[i].position.x, snake[i].position.y, BOX_SIZE, BOX_SIZE, snake[i].color); + } + // Draw fruit + + DrawRectangle(fruit.position.x, fruit.position.y, BOX_SIZE, BOX_SIZE, fruit.color); + if (pause) + { + DrawText("Game paused", screenWidth / 2 - MeasureText("Game paused", 40) / 2, screenHeight/2 - 40, 40, GRAY); + } + + } + else + { + DrawText("Press [Enter] to player again!", screenWidth / 2 - MeasureText(("Press [Enter] to player again!"), 40) / 2, screenHeight / 2 - 40, 40, GRAY); + } + + EndDrawing(); +} + +static void UnloadGame(void) +{ + +} + diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c index 68bd72cd7..ca56f316e 100644 --- a/examples/shaders/shaders_basic_lighting.c +++ b/examples/shaders/shaders_basic_lighting.c @@ -34,7 +34,7 @@ //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -int main(void) +int main_old(void) { // Initialization //--------------------------------------------------------------------------------------