From 4bd960f53da852ea5f06be72b83cda693413cfae Mon Sep 17 00:00:00 2001 From: Travis Avey Date: Fri, 15 May 2026 15:54:49 -0400 Subject: [PATCH] source code migrating from gitlab --- 001SnakeClone/CMakeLists.txt | 34 +++++ 001SnakeClone/README.md | 11 ++ 001SnakeClone/src/main.c | 266 +++++++++++++++++++++++++++++++++++ README.md | 10 ++ 4 files changed, 321 insertions(+) create mode 100644 001SnakeClone/CMakeLists.txt create mode 100644 001SnakeClone/README.md create mode 100644 001SnakeClone/src/main.c create mode 100644 README.md diff --git a/001SnakeClone/CMakeLists.txt b/001SnakeClone/CMakeLists.txt new file mode 100644 index 0000000..39f7f60 --- /dev/null +++ b/001SnakeClone/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 4.0) +project(SnakeClone C) +set(CMAKE_C_STANDARD 99) + +# Adding Raylib +# include(FetchContent) +# set(FETCHCONTENT_QUIET FALSE) +# set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples +# set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games +# +# FetchContent_Declare( +# raylib +# GIT_REPOSITORY "https://github.com/raysan5/raylib.git" +# GIT_TAG "master" +# GIT_PROGRESS TRUE +# ) +# +# FetchContent_MakeAvailable(raylib) + +# Adding our source files +file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/*.c") # Define PROJECT_SOURCES as a list of all source files +set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/src/") # Define PROJECT_INCLUDE to be the path to the include directory of the project + +find_package(raylib REQUIRED) + +# Declaring our executable +add_executable(${PROJECT_NAME}) +target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES}) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE}) +target_link_libraries(${PROJECT_NAME} PRIVATE raylib) + +# Setting ASSETS_PATH +target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets/") # Set the asset path macro to the absolute path on the dev machine +#target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable diff --git a/001SnakeClone/README.md b/001SnakeClone/README.md new file mode 100644 index 0000000..9f69694 --- /dev/null +++ b/001SnakeClone/README.md @@ -0,0 +1,11 @@ +# SNAKE CLONE + +The first game we write should be relatively easy. There is always a lot of things to do with game development, such as writing the code, designing the levels, making the artwork and/or models for the game. So it's a really good idea to start small and build into making your Science Based Dragon MMO + +## Watch Here +[YouTube](https://youtu.be/lEFoKvBfqHk) + + +## What Next? + +I'd look at trying to clone another easy game, maybe easier than snake. Asteroids? Pong? Brick Breaker? Pacman? etc.. there's a ton of old school games that were made with far less resources than we have today. diff --git a/001SnakeClone/src/main.c b/001SnakeClone/src/main.c new file mode 100644 index 0000000..1056faf --- /dev/null +++ b/001SnakeClone/src/main.c @@ -0,0 +1,266 @@ +#include +#include +#include +#include + +#define GRID_SIZE 25 +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 600 +#define MAX_SCORE 256 + +int widthByGrid = SCREEN_WIDTH / GRID_SIZE; +int heightByGrid = SCREEN_HEIGHT / GRID_SIZE; + +Vector2 head; +Vector2 dir; +Vector2 food; +Vector2 segments[MAX_SCORE - 1]; + +int score = 0; +char scoreStr[32]; +bool isRunning = true; +bool gameStart = false; + +const Color bg = {236, 239, 244, 255}; +const Color snakeRed = {191, 97, 106, 255}; +const Color snakeBlack = {46, 52, 64, 255}; +const Color foodColor = {163, 190, 140, 255}; +const Color textDark = {76, 85, 106, 255}; +const Color textOrange = {208, 135, 112, 255}; +const Color textGreen = {143, 188, 187, 255}; +const Color textBlue = {90, 129, 172, 255}; + +void initGame(); +void quitGame(); +void draw(); +Vector2 spawnFood(); +bool collide(Vector2 a, Vector2 b); +bool collideSelf(Vector2 self); +void processInput(); +void update(); +void gameOver(); +void restartGame(); +void startScreen(); + +int main(int argc, char *argv[]) { + initGame(); + + while (!WindowShouldClose()) { + + processInput(); + if (!gameStart) { + startScreen(); + } else if (isRunning) { + update(); + } + if (gameStart) { + draw(); + } + } + + quitGame(); + + return 0; +} + +void initGame() { + time_t t; + srand(time(&t)); + InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Snake Clone"); + + SetTargetFPS(10); + + sprintf(scoreStr, "SCORE: %d", score); + + head.x = 0; + head.y = 0; + dir.x = 1; + dir.y = 0; + + food = spawnFood(); +} + +Vector2 spawnFood() { + + Vector2 snack = {1 + rand() % (GRID_SIZE - 2), 1 + rand() % (GRID_SIZE - 2)}; + + while (collide(head, snack) || collideSelf(snack)) { + snack.x = 1 + rand() % (GRID_SIZE - 2); + snack.y = 1 + rand() % (GRID_SIZE - 2); + } + + return snack; +} + +bool collide(Vector2 a, Vector2 b) { return (a.x == b.x && a.y == b.y); } + +bool collideSelf(Vector2 self) { + for (int i = 0; i < score; i++) { + if (collide(self, segments[i])) { + return true; + } + } + return false; +} + +void processInput() { + + if (IsKeyPressed(KEY_W) || IsKeyPressed(KEY_UP)) { + if (dir.y == 1) + return; + dir.x = 0; + dir.y = -1; + } + + if (IsKeyPressed(KEY_A) || IsKeyPressed(KEY_LEFT)) { + if (dir.x == 1) + return; + dir.y = 0; + dir.x = -1; + } + + if (IsKeyPressed(KEY_D) || IsKeyPressed(KEY_RIGHT)) { + if (dir.x == -1) + return; + dir.y = 0; + dir.x = 1; + } + + if (IsKeyPressed(KEY_S) || IsKeyPressed(KEY_DOWN)) { + if (dir.y == -1) + return; + dir.y = 1; + dir.x = 0; + } + + if (IsKeyPressed(KEY_SPACE) && !isRunning) { + restartGame(); + } + + if (IsKeyPressed(KEY_ESCAPE)) { + isRunning = false; + quitGame(); + } + + if (IsKeyPressed(KEY_ENTER)) { + gameStart = true; + } +} + +void update() { + + for (int i = score; i > 0; i--) { + segments[i] = segments[i - 1]; + } + + segments[0] = head; + + head.x += dir.x; + head.y += dir.y; + + if (collideSelf(head) || head.x < 0 || head.y < 0 || head.x >= GRID_SIZE || + head.y >= GRID_SIZE) { + isRunning = false; + } + + if (collide(head, food)) { + if (score < MAX_SCORE) { + score += 1; + sprintf(scoreStr, "SCORE: %d", score); + } else { + sprintf(scoreStr, "YOU WIN"); + } + food = spawnFood(); + } +} + +void quitGame() { + printf("quitGame called\n"); + CloseWindow(); +} + +void draw() { + BeginDrawing(); + + ClearBackground(bg); + + DrawRectangle(food.x * widthByGrid, food.y * heightByGrid, widthByGrid, + heightByGrid, foodColor); + + DrawRectangle(head.x * widthByGrid, head.y * heightByGrid, widthByGrid, + heightByGrid, snakeRed); + + for (int i = 0; i < score; i++) { + if (i % 2 == 0) { + DrawRectangle(segments[i].x * widthByGrid, segments[i].y * heightByGrid, + widthByGrid, heightByGrid, snakeBlack); + } else { + DrawRectangle(segments[i].x * widthByGrid, segments[i].y * heightByGrid, + widthByGrid, heightByGrid, snakeRed); + } + } + + DrawText(scoreStr, 10, 10, 30, textBlue); + + if (!isRunning) { + gameOver(); + } + + EndDrawing(); +} + +void gameOver() { + DrawText("GAME OVER", 30, 120, 120, textOrange); + + char *restartText = "Try Again? Press Space"; + int resWidth = MeasureText(restartText, 28); + int resMid = (SCREEN_WIDTH - resWidth) / 2; + DrawText(restartText, resMid, SCREEN_HEIGHT / 2, 28, textGreen); + + char *quitText = "Press Escape to Quit."; + int quitWidth = MeasureText(quitText, 28); + int quitMid = (SCREEN_WIDTH - quitWidth) / 2; + DrawText(quitText, quitMid, SCREEN_HEIGHT / 2 + 40, 28, textDark); +} + +void restartGame() { + + head.x = 0; + head.y = 0; + + dir.x = 1; + dir.y = 0; + + score = 0; + sprintf(scoreStr, "SCORE %d", score); + isRunning = true; + food = spawnFood(); +} + +void startScreen() { + BeginDrawing(); + + ClearBackground(bg); + + DrawText("Snake Clone", 30, 120, 120, textGreen); + + char *startText = "Press Enter to Start"; + int restart = MeasureText(startText, 28); + int resX = (SCREEN_WIDTH - restart) / 2; + int resY = (SCREEN_HEIGHT / 2); + DrawText(startText, resX, restart, 28, textOrange); + + char *quitText = "Press Escape to Quit"; + int quit = MeasureText(quitText, 28); + int quitX = (SCREEN_WIDTH - quit) / 2; + int quitY = (SCREEN_HEIGHT / 2) + 40; + DrawText(quitText, quitX, quitY, 28, textDark); + + char *helpText = "Use WASD or arrows to move"; + int help = MeasureText(helpText, 24); + int helpX = (SCREEN_WIDTH - help) / 2; + int helpY = (SCREEN_HEIGHT / 2) + 80; + DrawText(helpText, helpX + 40, helpY, 24, textBlue); + + EndDrawing(); +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..de6ab90 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Game Dev Tutorials + +These are tutorials mostly written in C and using RayLib + +### 1. Snake Clone + +If you want to do game dev, you should start off simple. In the first tutorial we will walk through cloning the very basic snake game. + + +