Reflection on Snake Game

You can find this project here

During the snake game project, I have used a few programming techniques introduced in the bouncing ball animation as well as some new ones. Here is a list of the new techniques shown during this project:

  • Methods of objects
  • helper vs control functions
  • taking key press inputs
  • taking touchscreen inputs

When creating an object, it can have properties and methods. Properties are values and methods are functions of the object. These can be called using ObjectName.Property or ObjectName.Method() and are useful for encapsulating values.

function create_snake() {
    var new_snek = {
        colour: generate_hex(),
        x: grid * 2,
        y: grid * 2,
        dx: grid,
        dy: 0,
        cells: [],
        max_cells: 4,
        move_left: function () {
            if (this.dx === 0) {
                this.dx = - grid;
                this.dy = 0;
            }
        },
        move_right: function () {
            if (this.dx === 0) {
                snake.dx = grid;
                snake.dy = 0;
            }
        },
        move_up: function () {
            if (this.dy === 0) {
                snake.dy = -grid;
                snake.dx = 0;
            }
        },
        move_down: function () {
            if (this.dy === 0) {
                snake.dy = grid;
                snake.dx = 0;
            }
        }

    }
    return new_snek
}

In this function, I create and return an object called new_snek. It has the properties:

  • colour – stores the randomly generated colour of the snake. This is used to draw the snake in the same colour every time the position of the snake is updated on-screen.
  • x – stores the current x co-ordinate of the snake’s head.
  • y – stores the current y co-ordinate of the snake’s head.
  • dx – stores if the snake is moving along the x axis and if it is moving in a positive or negative direction.
  • dy – stores if the snake is moving along the y axis¬†and if it is moving in a positive or negative direction.
  • cells – is an array that holds information about each segment of the snake’s body. Each time the snake consumes an apple, a new cell is added to the array.
  • max_cells – stores the maximum number of cells the snake can have. When the snake reaches this point, each time it eats an apple it loses a cell to keep it’s size consistent.

To allow my snakes and apples to have random colours, I directly copied my generate_hex function from the bouncing ball animation. I chose to have random snake colours as I felt it would be easier for players to determined that they died and are starting over once more with a new snake. I made the apples random colours to keep things visually interesting.

The object new_snek also has the following methods:

  • move_left
  • move_right
  • move_up
  • move_down

These methods allow you to directly move the snake object in 4 different directions as long as you weren’t previously moving along the same axis. These are called by event listeners that are detecting arrow/WASD key presses or touch inputs.

function add_listeners() {
    var start_x, start_y, distance_x, distance_y;

    document.addEventListener("keydown", function (e) {
        //left (A) 65 | right (D) 68 | up (W) 87 | down (S) 83
        if (e.keyCode == 65 || e.keyCode == 37) {
            snake.move_left();
        } else if (e.keyCode == 68 || e.keyCode == 39) {
            snake.move_right();
        } else if (e.keyCode == 87 || e.keyCode == 38) {
            snake.move_up();
        } else if (e.keyCode == 83 || e.keyCode == 40) {
            snake.move_down();
        }
    })
    document.addEventListener("touchstart", function (e) {
        var touch = e.changedTouches[0];
        start_x = Math.round(touch.clientX);
        start_y = Math.round(touch.clientY);
        e.preventDefault();
    }, { passive: false });
    document.addEventListener("touchmove", function (e) {

        e.preventDefault();
    }, { passive: false });
    document.addEventListener("touchend", function (e) {
        var touch = e.changedTouches[0];
        distance_x = Math.round(touch.clientX) - start_x;
        distance_y = Math.round(touch.clientY) - start_y;
        if (Math.abs(distance_x) > Math.abs(distance_y)) {
            if (distance_x > 0) {
                snake.move_right();
            } else if (distance_x < 0) {
                snake.move_left();
            }
        } else {
            if (distance_y > 0) {
                snake.move_down();
            } else if (distance_y < 0) {
                snake.move_up();
            }
        }
        e.preventDefault();
    }, { passive: false });
}

I use the OR || operator to allow the user to control the snake using WASD or the arrow keys at any time depending on their personal preference. This gave my game additional flexibility as some players would default to WASD while others find the arrow keys easier to use.

By calculating the distance between the beginning and end of a touch event, I can determine which direction the player swiped in. This allows me to then call the appropriate move property of the snake using nested if statements.

The key techniques that I learnt during this project were how to detect key presses and touch input. I can use these in future web-based game projects to ensure that the game is playable across multiple platforms. I found creating objects without using a class an unusual experience, as the way I learnt OOP was using a stricter language where to create an object you had to have created a class.