Skip to content

A browser-based TypeScript implementation of the classic retro game, Snake

Notifications You must be signed in to change notification settings

FrankRay78/Snake

Repository files navigation

Snake

A browser-based TypeScript implementation of the classic retro game, Snake (Wikipedia)

Click here to play the game

Game features implemented so far are:

  1. Mobile responsive layout
  2. Keyboard / mouse / touch controls
  3. Persistent high scores

Technical Design

A non-UML class diagram for the Snake game is as follows:

Class diagram for Snake game

Class Description
Apple Is given a location on the board and remains static until the snake eats it by running into the same square. The user's score is incremented and another apple placed on the board for the snake to eat.
Snake Moves around the board 'eating' apples. Each apple eaten results in the snake growing in length, making it harder to remain in the game because the snake cannot run across itself or hit the edge of the board.
Game A container for holding the Apple and Snake objects. Also responsible for handling user events (keyboard / mouse / touch), snake events (snake has eaten an apple, snake has run into itself, snake has fallen off the board) and game events (Game Over).
GameRenderer Responsible for rendering the game state at point of redraw. Converts the relative locations of Snake and Apple into pixel coordinates for rendering to an Html canvas element it contains a reference to.
HighScoresProvider An interface defining the high scores functionality required by the Game class, primarily concerned with getting and saving game scores.

The game was implemented in HTML, CSS and TypeScript using Visual Studio 2019 as the development IDE.

High Scores

The HighScoresProvider interface has been implemented twice, namely an in-memory (non-persistent) provider and also a (persistent) webservice provider.

The in-memory provider has been configured as the default provider in the checked-in codebase. This allows the Snake game to be standalone and work 'out of the box' should you build and run a forked / cloned repo.

You will need to implement your own webservice implementation (or similar) should you want persistent high scores between games and between users.

The specific provider to use is defined in code through a poor man's DI located in the app.ts file, namely:

    //Load the correct high scores provider here:
    const highScoresProvider: HighScoresProviderInterface = new HighScoresMemoryProvider(
        [
            new HighScore("FDR", 10),
            new HighScore("HGR", 7),
            new HighScore("SRR", 2)
        ]
        );
        
    //const highScoresProvider: HighScoresProviderInterface = new HighScoresWebServiceProvider(
    //    'http://localhost/SnakeWebAPI/api/Snake/GetHighScores',
    //    'http://localhost/SnakeWebAPI/api/Snake/SaveHighScore'
    //);

Unit Testing

A comprehensive suite of unit tests have been written against the materially important classes to validate a lot of the game logic. Classes have been split out into separate TS files and loaded when needed through the RequireJS framework. The use of separate type files have allowed unit tests to be easily written against individual classes. Jest unit test framework was selected and remains a good choice due to ease of use and breadth of functionality. Both RequireJS and Jest were installed with NPM (Node Package Manager).

Development Backlog

  1. Make the Snake's length grow upon eating each apple [Done - 21 January 2021]
  2. Collision detection of the snake upon itself [Done - 21 January 2021]
  3. Unit testing (of TypeScript classes) [Done - 20 January 2021]
  4. GitHub post commit hook to execute unit tests
  5. Persist high scores in a database with the help of a ASP.Net Web API service [Done - 22 February 2021]
  6. Give the snake a timer and make it autonomous; redraw the Html canvas on browser screen refresh event
  7. Implement a proper config file option (example)

Resources

The following resources came in handy when implementing the game:

Getting started
Interacting with HTML elements
JavaScript file and module loading
Unit testing
TypeScript language & development environment

Credits

Royalty free Snake logo courtesy of CLEANPNG