Sepphod / CppND-Capstone-Snake-Game

A 2D Snake game using C++ and SDL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CPP nanodegree: Capstone - Snake extended

This is a clone from the starter repo for the (Capstone project)[https://github.com/udacity/CppND-Capstone-Snake-Game] in the Udacity C++ Nanodegree Program.

The starter repo was refactored and extended with the following new features:

  • a configuration file (e.g. change size of food, snake and the size of the game area)
  • a demonstration mode (automatically play of the computer without any interaction of a human player)
  • one-to-n battle (human vs computer, computer can control more than one snake)
  • every snake controlled by the computer gets randomly a different colour

The objective of the game

It is quite simple. Control your snake by your keyboard to reach the food. Once you eat the food you will grow and move faster. Don't eat yourself...
The game stops if any snakes bites itself. In that case the head of the snake will change its colour to red.
The winner in a multiplayer mode is the biggest snake.

Dependencies for Running Locally

Basic Build Instructions

  1. Clone this repo.
  2. Make a build directory in the top level directory: mkdir build && cd build
  3. Compile: cmake .. && make
  4. Adapt the deployed (configuration file)[https://github.com/Sepphod/CppND-Capstone-Snake-Game/blob/master/src/snake.cfg] according your wishes.
  5. Run it: ./SnakeGame../src/snake.cfg. If no config file is provided default values will be used. The default values can be found in (settings.h)[https://github.com/Sepphod/CppND-Capstone-Snake-Game/blob/master/src/settings.h]

Configuration

Via the configuration file snake.cfg it is possible to modify:

  • the size of the play area on the screen
    • ScreenWidth and ScreenHeight
  • the resolution of the play area by changing the grid size (it affects the size of the food and the snake)
    • GridWidth and GridHeight
  • the refresh rate with which the play is displayed
    • FramesPerSecond
  • the number of snakes which try to reach the food (currently limited to one human player)
    • NumOfSnakes for more than one snake AND DemoMode is 0 the first player will be the human player and the rest will be controlled by the computer
  • Automatic playing by a virtual player
    • DemoMode (1 - on and 0 - off)

Hints

For more snakes a bigger battlefield area is recommended. Otherwise a probable winner emerges quickly.

Next steps

The game is in a stable state. It covers almost all of the rubic required C++ features. Though an interesting developer can even extend more features like:

  • snakes should not touch other snakes
  • more salt in the smartness of the computer controlled snakes.

SW design

Static SW design

Below the class diagram. Almost all SW modules are implemented as CPP classes or structs. Only the parsing of the configuration file is implemented as free functions. Those free functions base on a template function.
The main class is Game. It owns the food and the players. If any of the snakes has eaten the food it will be placed on a new location by Game. The players are a vector of smart pointers to the class Player.
Every object of Player owns one object of class Snake and one object of ControllerBase. The class Player controls the moving of its Snake. It checks if the Snake has eaten the food. In that case the snake increases its size. Further it checks if the snake has not accidentally eaten itself. In that case the game would be over.

The class Snake is the representation of a snake with its head and its body. At the start of the game the body has a size of 0. With every food eaten by the snake the body increases by one. The body is a vector of smart pointers of SDL_Point. If the body increases std::make_unique<SDL_Point> is called.

The snake can be controlled by a real entrys via the keyboard or by calculating the best direction the snake shall head in order to reach the food. The class Controller is responsible for the input via keyboard and VirtualController is responsible for the calculation of the next step during the Demomode. As the player should not care about the kind of controller both were abstracted with a base class ControllerBase which specify by virtual function the common API. That API is used by the Player.

The VirtualController outsources the calculation of the next step to RoutePlanner. Which calculates the manhattan-distance of the current head to the food. It checks the possible neighbour positions and decides the best next neighbour. This leads to the direction whiches the VirtualController will use during the current game cycle to control the snake. Either the snake changes its direction or it keeps going in the same direction.

class design

The implementation follows the rule of 5. Behaviour is encapsulated in dedicated classes or structs as it fits most. There is no usage of raw pointers. Only smart pointers regarding their ownership are used.

Dynamic SW design

The game is started via the commandline. The main function verifies the provided parameters. Afterwards the one object of the type _Renderer and one object of the type Game are instantiated.
Within the constructor the configured number of Player are instantiated. Depending on a input parameter the constructor of Player instantiates either a VirtualController or a Controller. At last action in the constructor of Game the food is placed randomly somewhere in the game area.

After all initialization the main function calls Game.run(). Which is a classic while-loop. It will be executed as long as you terminate the application (typically by pressing CMD or CTRL - C). A Player dies if it touches itself. Then the game ends and the player with the highest scores wins.

To fulfill the requirement to implement threads the calculation of the new position for every player is handled in a thread. At first within the while-loop one thread for every player is created. The threads are waiting for the keyboard input which is verified by the main loop. The main loop packs the control information in a message and informs all threads to start their working.
The human player will move the snake to a new position according to the keyboard input. The virtual players will calculate their new position. If the message sent by the main loop contains the terminating command both players will stop.
Every threads is getting destroyed after the calculation of the new position. The main loop waits until all threads are finished.

The main loop verifies if any snake will eaten itself. Than the food and the Snake of every Player are rendered. At the end of any game cycle the game statistics are updated and the display delay are calculated.

threads

Details activity diagram

dynamic

Route planning

The VirtualController controls the snake without any interaction of any human player. In every game cycle the possible neighbours of the head of the snake in all 4 directions (UP, DOWN, LEFT, RIGHT) are evaluated. The criterias are

  • distance to the food
  • already not occupied by any part of any snake
  • neighbour is not in the opposite direction

The distance is calculated as Manhattan-Distance. The list of neighbours is sorted with the shortest distance as sorting criteria.

route planner

Capstone rubric points

The following rubric points are addressed within this project:

  • Compilation and execution without any error
  • usage of loops, control structures and functions
  • Techniques of object-oriented programming (abstract classes and their child classes)
  • Usage of templates
  • File access
  • Memory Management (usage of smart pointer - strict avoidance of raw pointers, rule-of-5)
  • threads, mutex and conditions are used in the communication of the main loop with the threads of the players
  • Futures and promises are not used.

CC Attribution-ShareAlike 4.0 International

Shield: CC BY-SA 4.0

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

CC BY-SA 4.0

About

A 2D Snake game using C++ and SDL

License:Creative Commons Attribution Share Alike 4.0 International


Languages

Language:C++ 88.1%Language:CMake 11.9%