Snake sample

This commit is contained in:
DESKTOP-3SJQ2V2\PC 2023-04-17 01:38:13 +07:00
parent 3f6e12ee04
commit 19b8ce813a
5 changed files with 554 additions and 1 deletions

View File

@ -156,6 +156,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\examples\shaders\shaders_basic_lighting.c" />
<ClCompile Include="snake.c" />
<ClCompile Include="snake_remake.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -18,5 +18,11 @@
<ClCompile Include="..\..\examples\shaders\shaders_basic_lighting.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="snake.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="snake_remake.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -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 <emscripten/emscripten.h>
#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();
}

View File

@ -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)
{
}

View File

@ -34,7 +34,7 @@
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
int main_old(void)
{
// Initialization
//--------------------------------------------------------------------------------------