Skip to content

About

C++ OpenGL/GLUT arcade snake engine with state-machine loop, collision math, and file I/O persistence.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

🐍 cpp-glut-snake-engine

A real-time Snake arcade game written in modern-ish C++ and rendered with OpenGL 1.x / GLUT (FreeGLUT). The engine is a single-binary, zero-asset game featuring a persistent menu system, three difficulty tiers with escalating frame rates and obstacle density, super-food spawns, procedural obstacle generation (5 shapes), screen-edge wrap-around, and on-disk high-score + recent-score persistence — all drawn from primitive 2D primitives (squares, circles, rounded rectangles, lines, text) with a hand-rolled 2.5D shadow pass.


✨ Features

Area Detail
Rendering 1024×800 window, 16 px grid cells, double-buffered GLUT, 16 px shadow offset for a subtle 2.5D look
Snake model 3-plane body array snakeBody[3][maxLength][1] → [active][x][y], head = index 0; body follows head with one-step lag; wraps around all four edges
Food system 5 food slots with per-slot respawn timers (15·FPS frames); super-food appears on an independent 60·FPS-frame timer and is worth ×4 points (20 vs 5). Spawn validation rejects cells occupied by other foods (row / column / diagonal sweeps) and the snake's own body
Obstacles Up to 3 procedural obstacles (one per difficulty tier) in 5 shapes: vertical line, horizontal line, U, L, and ∠. Each has a 30·FPS-frame lifetime, is validated against food, the snake body, and sibling obstacles (AABB corner/containment tests), then rasterized into a per-cell kill map
Difficulty tiers Easy 5 FPS · 1 obstacle · Hard 15 FPS · 2 obstacles · Insane 30 FPS · 3 obstacles
Menu 6-entry menu (Start / Resume / Change Level / High Scores / Game History / Exit) with arrow-key cursor, decorative crawling menu snake, and a resume-confirmation dialog that prevents clobbering an active game
Persistence highscore.txt (single int, beaten-record message on game-over) and scores.txt (rolling last-3 session scores, shown in Game History)
Input GLUT special-key + keyboard callbacks; direction changes reject 180° reversals; P pauses (returns to menu), Esc exits or navigates back

📐 Architecture

game-release.cpp   ──  Engine: GLUT callbacks, state machine, all game logic
│
├── Display()                per-frame renderer: clears the buffer, then branches
│                            on gameState to compose the visible scene
├── NonPrintableKeys()       arrow keys: steer in play, move menu cursor
├── PrintableKeys()          Enter / Esc / P: state transitions
└── Timer()                  glutTimerFunc tick @ 1000/FPS ms → re-posts Display

util.cpp / util.h  ──  Drawing toolkit + palette
│
├── DrawSquare / DrawCircle / DrawRoundRect / DrawLine / DrawTriangle / Torus2d
├── DrawString()             text blitting
├── GetRandInRange()         range-constrained RNG (seeded via InitRandomizer())
└── colors[160][3]           named palette indices (RED = 5, WHITE = 149,
                             custom game colors 140–154 for snake, food, UI)

Makefile / CMakeLists.txt ──  Build (Linux X11/FreeImage link, or Windows GLUT)
install-libraries.sh        ──  One-shot apt installer (Debian/Ubuntu)
highscore.txt / scores.txt  ──  Runtime persistence (recreated on demand)

Frame pipeline (per Display() tick, in play state)

  1. glClear the 1024×800 canvas
  2. DrawBackground() — static 16 px checker of olive-green cells (cached after first draw)
  3. InitSnake() — first-frame bootstrap of the body array (length 3, center of field)
  4. BodySnake() — shift every body segment to its predecessor
  5. Direction() — advance the head by 16 px along direction (0 = right, 1 = down, 2 = left, 3 = up), wrap at edges
  6. DisplayFood() — tick per-food respawn timers, spawn validated food / super-food
  7. DrawSnake() — head as layered circles (body, head, eyes, pupil), body as shaded squares
  8. Obstacles() — respawn timers, shape generation, collision validation, kill-map rasterization
  9. Collision() — head-vs-body, head-vs-obstacle → gameOver; head-vs-food → grow, score, history
  10. DisplayScore() — digit-reversal string builder for the HUD
  11. glutSwapBuffers()

State machine

stateDiagram-v2
    [*] --> menu

    state menu {
        [*] --> Menu
    }

    menu --> confirmation : Enter «Start Game» while a game is running
    menu --> play : Enter «Start Game» (fresh) · or «Resume Game»
    menu --> difficulty : Enter «Change Level»
    menu --> highscore : Enter «High Scores»
    menu --> history : Enter «Game History»
    menu --> [*] : Enter «Exit» · or Esc

    confirmation --> play : Enter (abort previous game)
    confirmation --> menu : Esc

    difficulty --> difficulty : Enter (apply Easy 5fps/1 · Hard 15fps/2 · Insane 30fps/3)
    difficulty --> menu : Esc

    highscore --> menu : Enter / Esc
    history --> menu : Enter / Esc

    play --> menu : P or Esc (pause)
    play --> gameOver : head hits own body or obstacle
    gameOver --> menu : Enter / Esc
Loading

Controls

Key In play In menus
↑ / ↓ / ← / → Steer snake (180° reversal ignored) Move cursor (wrap-around)
Enter — Select highlighted item / confirm dialog
Esc Pause → menu Back · Exit from main menu
P Pause → menu —

Scoring

Event Points
Regular food +5
Super-food (gold, independent 60·FPS timer) +20

Every eaten food grows the snake by one segment and pushes the session score into scores.txt (last 3 games, oldest evicted). A higher session score than highscore.txt updates the record and the game-over panel announces You beat the previous high score.


🔨 Build

Dependencies

  • C++11 compiler (g++ or MSYS2/MinGW g++)
  • GLUT — FreeGLUT (or the system GLUT)
  • OpenGL / GLU dev headers
  • X11 dev headers (Linux) · FreeImage (optional, linked by the Makefile)

Debian/Ubuntu one-shot:

./install-libraries.sh
# or manually:
sudo apt-get install freeglut3-dev libglew-dev libgl1-mesa-dev libfreeimage-dev
MSYS2 (Windows)
pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-freeglut mingw-w64-ucrt-x86_64-glew

Option 1 — Make

make            # builds ./game-release  (CXXFLAGS: -g3 -Wall -fmessage-length=0)
make clean      # removes objects and the binary

The Makefile links GLUT, GLU, GL, X11, and FreeImage from standard system / SUSE-X (/sw/lib) paths.

Option 2 — CMake

cmake -S . -B build
cmake --build build
./build/game-release          # highscore.txt / scores.txt are copied beside the binary

Option 3 — raw g++

g++ -g3 -Wall -fmessage-length=0 -std=c++11 \
    game-release.cpp util.cpp \
    -o game-release \
    -lGLU -lGL -lglut -lX11 -lfreeimage

Run

./game-release        # opens the "Snake game" GLUT window

Requires an X server / desktop session (on Windows, run under WSLg or MSYS2).


🗂 Project layout

├── game-release.cpp      # engine: state machine, game loop, input, rendering
├── util.cpp / util.h     # drawing primitives, palette, RNG helpers
├── Makefile              # native make build (Linux/X11 toolchain)
├── CMakeLists.txt        # CMake build (cross-platform)
├── install-libraries.sh  # apt dependency installer
├── highscore.txt         # persisted record score
├── scores.txt            # last three session scores
└── .github/
    ├── copilot-instructions.md
    └── repo-metadata.json

📝 Notes

  • The game writes highscore.txt / scores.txt in the current working directory — run from the repo root.
  • No automated test suite; validate changes by building, playing a session, and toggling through the menu states.
  • The window is fixed at 1024×800; the playfield is 64×48 cells with a 2-cell HUD strip along the bottom.

About

C++ OpenGL/GLUT arcade snake engine with state-machine loop, collision math, and file I/O persistence.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages