Documentation
README
Snake Game
A classic Snake game built with HTML5 Canvas 2D. Control a snake that moves around a 20×20 grid, eat food to grow and score points, and try to achieve the highest score before colliding with walls or yourself.
Quick Start
src/game.html in a modern web browser (Chrome, Firefox, Safari, Edge)Installation
No installation required! The game runs entirely in your browser with zero dependencies.
Verify Tests (Optional)
To run the test suite:
npm testOr directly:
node --test tests/game-logic.test.js
Usage
Playing the Game
File: src/game.html
Simply open the HTML file in any modern web browser. The game starts immediately.
Keyboard Controls:
- Arrow Up (↑): Move snake up
- Arrow Down (↓): Move snake down
- Arrow Left (←): Move snake left
- Arrow Right (→): Move snake right
- Space: Restart after game over
Running Tests
npm testThis runs 47 unit tests covering:
- Snake initialization and movement
- Direction control and blocking
- Food spawning and consumption
- Collision detection (walls and self)
- Speed progression
- Game over and restart
- Edge cases and boundary conditions
Examples
Example 1: Basic Gameplay
game.htmlExample 2: Speed Progression
The game gets progressively harder:
| Food Eaten | Game Speed | Difficulty |
|---|---|---|
| 0 | 8 ticks/sec | Easy learning phase |
| 5 | 8.5 ticks/sec | Slight speedup |
| 10 | 9 ticks/sec | Early challenge |
| 20 | 10 ticks/sec | Noticeable difficulty |
| 50 | 13 ticks/sec | Frantic gameplay |
| 100+ | 15 ticks/sec (capped) | Maximum speed |
Example 3: High Score Persistence
Game Mechanics
Snake Movement
- Snake moves one grid cell per tick
- Direction changes are queued and applied on the next tick
- 180° turns (reversing into yourself) are blocked to prevent instant death
Food Spawning
- Red square appears at random unoccupied position
- Never spawns on snake's body
- New food spawns immediately after eating
- Always at least one food present during gameplay
Scoring and Growth
- Eating food increases score by 1 point
- Snake grows by 1 segment when eating food
- Growth is permanent until game over
- Score resets when starting a new game
Collision Detection
Game ends immediately on:
- Wall collision: Head reaches boundary (x < 0 or x > 19 or y < 0 or y > 19)
- Self-collision: Head occupies same cell as any body segment
Speed Progression
Speed formula: ticks_per_second = min(8 + (food_eaten / 5) * 0.5, 15)
- Baseline: 8 ticks/sec (125ms per tick)
- Speed increase: +0.5 ticks/sec for every 5 food eaten
- Cap: 15 ticks/sec maximum (66.67ms per tick)
- Speed changes smoothly without stuttering
Visual Feedback
When eating food:
- Snake briefly flashes cyan (#00ffff) instead of green (#00ff00)
- Flash lasts 100-150ms
- Simultaneous with growth and score update
High Score Persistence
- High score stored in browser's localStorage
- Automatically loaded on page refresh
- Updated only if current score exceeds stored high score
- Gracefully handles localStorage unavailable (defaults to 0)
Architecture
Files
- src/game-logic.js - Pure function module (testable)
- src/game.html - HTML5 Canvas game (browser)
- tests/game-logic.test.js - Test suite
Code Metrics
- Inline HTML JavaScript: 305 lines
- Pure logic module: 132 lines
- Test suite: 508 lines
- Total dependencies: 0 (zero npm packages)
- Lint status: PASS (0 errors, 0 warnings)
Error Handling
localStorage Not Available
If browser has localStorage disabled:
- High score defaults to 0
- Game continues normally
- Updates not persisted (no error thrown)
Food Spawn Edge Case
If snake occupies 350+ cells (nearly full grid):
- Food spawn algorithm finds free cell within reasonable time (<10ms)
- Spawn completes successfully every time
- Maximum safe snake length: ~350 cells (not recommended for gameplay)
Out-of-Bounds Movement
Snake cannot move diagonally or move more than one cell per tick:
- Enforced by movement logic
- Invalid directions are silently ignored
- 180° turns explicitly blocked
Browser Compatibility
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
- Any browser supporting:
Performance
- Rendering: 60 FPS (requestAnimationFrame)
- Game loop: Decoupled rendering from logic updates
- Tick accuracy: Within ±10ms of target interval
- Frame budget: <16.67ms per frame maintained
- No jank or stutter: Even at maximum speed (15 ticks/sec)
Testing
Test Execution
node --test tests/game-logic.test.js
Test Suites (9 total)
Test Coverage
- Programmatic tests: 47/47 pass
- Scenario coverage: TS-1 through TS-28, EC-1 through EC-12
- Requirements coverage: FR-1 through FR-8, NFR-1 through NFR-4
Known Limitations
Development Notes
Dual-File Pattern
This project uses the dual-file testing pattern for browser games:
- game-logic.js: Pure functions with no browser dependencies (tested)
- game.html: HTML with inline Canvas rendering (manual browser testing)
Next Steps
Potential enhancements (not implemented):
- Different game modes (timed, endless, obstacles)
- Sound effects
- Mobile touch controls
- Difficulty settings
- Leaderboard server integration
- Visual themes/skins
License
MIT