Scratch Snake Tutorial – Section 04 – Snake with a Segmented Body

This page is part of the Snake in MIT Scratch Tutorial.

Snake with a Segmented Body

The snake is composed of a number of sprites that each occupy one space on the grid.

As the snake moves and grows the pieces must be re-arranged to reflect the snake’s current state.

When designing a complex object like the snake there are two important areas to consider:

  1. Data Structures: All the variables that describe the object.
  2. Operations: The actions that the object can make.

The data structure describes the current state of the snake and the operations allow the snake to alter its state.

Data Structure of the Snake

The snake is described by the following data:

  1. Body Parts List: Contains the location of every piece of the snake.
  2. Head: The head is the body part at the front of the snake.
  3. Tail: The tail is the body part at the end of the snake.
  4. Direction: This is the direction that the snake is currently traveling.

The following diagram shows the data that describes the snake:

Snake Data

The data that is used to describe the state of the snake.

The body parts list contains the coordinates of every square that the snake occupies on screen.

The first element in the list is the head and the last element in the list is the tail.

In the example above the body parts list would contain the following data:

{ (8,4), (7,4), (7,3), (7,2), (6,2), (5,2) }

Finally the direction variable stores the direction that the snake is currently traveling.

The possible directions are: Up, Right, Down or Left.

Operations on the Snake Data Structure

The following operations are used to manipulate the snake’s body during gameplay.

  1. Move Snake: Advances the snake one square in the direction it is facing.
  2. Grow Snake: Increases the length of the snake by adding an extra body part in the direction the snake is facing.
  3. Create Snake: Builds the snake at the start of a game.
  4. Change Direction: Sets the direction that the snake is currently traveling.

These operations are performed on the data structure as follows.

Move Snake

The process of moving the snake can be thought of as chopping off the tail of the snake and moving it to where the head should go next.

It wouldn’t be nice to do this to a real snake but it’s an effective way of moving the snake with the data structure described previously.

The method is as follows:

  1. Calculate the next position the snake’s head will move to.
  2. Remove the tail from the snake.
  3. Add a new body part at the next position
  4. Update the head and tail values.

The following animation shows the process:

Move Snake Operation

Moving the snake can be visualized as chopping off its tail and moving it to the next position the head should go.

Grow Snake

The snake increases in length when it eats an apple. The process is similar to how the move operation is carried out:

  1. Calculate the next position the snake’s head will move to.
  2. Add a new body part at the next position
  3. Update the head and tail values.

The following animation shows the snake growing:

How the Snake Grows when Eating an Apple

When the snake eats an apple the growth occurs at its front end. The tail pauses for a moment while the head grows.

The process is the same except the tail is not deleted at the start so the total number of body parts grows by one.

Create Snake

Creating a snake can be thought of as placing an empty snake (a snake with zero body parts) at a location and then repeating the grow snake operation until the snake is the desired length:

  1. Using the desired starting position decide upon the next position a body part should be placed.
  2. Use the Grow Snake operation to add a body part at the next position.
  3. If the snake’s body has reached the desired length then stop. Otherwise go back and repeat step 2.
Snake Create Operation

The snake is created by repeatedly using the grow operation.

Reusing the grow snake operation when creating a snake is helpful because when it becomes time to implement the operation in Scratch the code for making the snake longer only has to be written once.

Change Direction

The snake’s direction value can be Up, Down, Left or Right. These are the movement directions allowed by the grid of squares.

The snake is allowed to turn at right angles to its current direction:

Snake Turning Directions

The direction that the snake can turn changes according to the direction it is facing.

When its direction is Up or Down it is only allowed to turn Left or Right and when the direction is Left or Right it is only allowed to turn Up or Down.

Scratch Implementation of the Snake Data Structure

The data structure must be re-created using the tools available in Scratch.

This diagram shows the data that describes the snake:

Snake Data

The data that is used to describe the state of the snake.

This data structure is implemented in Scratch as follows:

Body Parts List

The body parts list contains the coordinates of every piece of the snake’s body. Coordinates have 2 components – an X and Y value that represents a horizontal and vertical position.

In the Snake project the list of coordinates is created using 2 lists called snake parts X and snake parts Y. These lists contain all of the X and Y values that make up the body parts list.

The Body Parts List for the snake in the picture above would be as follows:

(8,4), (7,4), (7,3), (7,2), (6,2), (5,2)

This would be represented in Scratch with the two lists:

snake parts X: 8, 7, 7, 7, 6, 5

snake parts Y: 4, 4, 3, 2, 2, 2

The abstract body parts list that had two values for each body part has been replaced with 2 lists that each hold one value of each coordinate.

The lists appear in the Scratch data panel as follows:

Scratch Body Parts Lists

The body parts lists have been made available to all sprites.

They have been defined globally – that is to say they are available in all sprite scripts.

The head is the first value in the lists and the tail is the last value in the lists. In scratch they are accessed within list blocks as follows:

Accessing Head and Tail

The head and tail values are accessed in list blocks using the first and last index values.

Snake Part

Each part of the snake’s body is represented on screen by a clone of the Snake Part sprite.

Cloning allows multiple copies of a sprite to exist in the game. More information on cloning can be found in the Scratch Documentation.

At the start of the game the original Snake Part sprite is hidden.

When pieces of the snake are created a clone of the sprite is made and that is what appears on screen.

When the game ends all the clones are deleted.

The sprite uses the when backdrop switches block to know when the game has started or ended.

The Title backdrop is used at the start of the game and the GameOver backdrop is used at the end of the game.

Backdrop Switch Events

At the start and end of each game the original snake sprite is hidden and all existing clones are deleted.

The sprite’s script contains the Move To Grid Pos function that allows it to position itself using the logical grid defined in Section 03 – Dividing the Playing Area into a Grid.

Move To Grid Position Function

Function used to translate grid coordinates into Scratch screen positions.

The snake is composed of multiple Snake Part sprites. Each of these sprites moves itself to the proper X and Y grid position according to what is stored in the snake parts X and snake parts Y lists.

In order that each clone of the Snake Part sprite represents a single piece of the snake a unique identifier is assigned to each clone. This unique value links the cloned sprite to the snake parts data it is to represent.

The identifier is defined in the Snake Part sprite script as snake part ID. Its value is an index of the snake parts X and snake parts Y lists – a number that corresponds to the location of a body part.

snake part ID

The snake part ID is defined in the Snake Part sprite. It is used to uniquely identify clones of the sprite and associate them with the body part they are to represent on screen.

Each clone of the Snake Part sprite has its own snake part ID that holds the location of the coordinates from snake parts X and snake parts Y that are used to position the clone on screen.

Creating a new body part for the snake has the following steps:

  1. Add the position of the new part to snake parts X and snake parts Y.
  2. Create a clone of the Snake Part sprite.
  3. Assign the clone a snake part ID that points to the newly created position in snake parts X and snake parts Y.

The first step adds the position of the new body part to the body parts X and body parts Y lists.

The Snake Part sprite is cloned and its snake part ID is set to the index of the new body part’s position in the snake part lists.

The new position is added to the end of the list so the Snake Part sprite clone sets its value to the length of the body parts list as that will be the index of the last item in the list:

Assigning Snake Part I

When a Snake Part sprite is cloned it sets its ID to the index of the last value added to the Snake Parts X/Y position lists.

Moving the Snake

In the abstract definition the process of moving the snake was described as chopping off the snake’s tail and moving it to the front as the new head.

The process of moving the snake works as follows in the Scratch project:

  1. Calculate the position that the head will occupy after the move is complete and store this in two variables called Snake Next X and Snake Next Y.
  2. Add the new X and Y Next Position values at the front of the snake parts X and snake parts Y lists.
  3. Delete the last item in the snake parts X and snake parts Y lists.
  4. Broadcast the Snake Changed message.

A new head is added and the old tail is deleted.

The Move Snake function appears in the Game Controller sprite as follows:

Move Snake

The move snake functions adds a new head to the snake and deletes the old tail.

After moving the snake the system broadcasts a Snake Changed message. The Snake Part sprites that compose the snake’s body will move to the snake’s new position when they receive this message.

Note: The next position is calculated as part of the input handling code described in Section 6.

Growing the Snake

Growing the snake works by adding a new head position to the snake parts lists and creating a clone of the Snake Part sprite to represent it on screen.

The process has the following steps:

  1. Add the Snake Next X and Snake Next Y position values at the head of the body parts lists.
  2. Make a new clone of the Snake Part sprite.
  3. Broadcast the Snake Changed message.

The position of the new head is added to the snake parts lists and a clone of the Snake Part sprite is created.

When the Snake Part clone is created it will assign its snake part ID to the new length of the list so that the new body part has a corresponding Snake Part clone.

The operation appears in the Game Controller script as follows:

Grow Snake

The grow snake operation adds a new item to the body parts lists and then makes a clone of the Snake Part list to represent it.

Create Snake

The Create Snake operation makes use of the Grow Snake operation to create the snake’s body parts.

A starting location is decided and the grow operation is repeated until the snake is the desired length. The process has the following steps:

  1. Empty all of the body parts from the snake parts lists.
  2. Set Snake Next X and Snake Next Y to the location the tail should occupy.
  3. Repeat 3 times:
    1. Use grow snake to add a new body part.
    2. Move the Snake Next X to one space to the right.

The Create Snake operation appears in the Scratch project as follows:

Create Snake

This function is used to create the snake.

Updating the Snake Parts

When the snake’s state changes by moving or growing the snake parts must move on screen to reflect those changes.

The game controller lets all the clones know that the snake has changed by using a broadcast block to send a message saying ‘Snake Changed’.

More information on the broadcast block can be found in the Scratch documentation.

When the snake is changed the current tail becomes the new head.

The move and grow operations set the position of the head in the first item in the snake parts lists.

When the snake is changed the following script is executed:

The clone moves when the snake is updated.

When the Snake Updated message is received the clone uses its ID to look up the location it should move to from the body parts lists.

In order for a snake part clone to determine that it is the tail it checks its snake part ID against the length of the snake parts list. If the ID is equal to the length of the snake parts list then this snake part must be the final element and therefore the tail.

The snake part that is the tail sets its snake part ID to 1 so that it becomes the new head and uses the Move To Grid Pos block to move itself to the correct position on screen.

All of the other snake parts that weren’t the tail increase their snake part ID by one so eventually they will reach the end and become the tail.

Conclusion

The snake’s body is represented by a list of coordinates with its head being the first value in the list and its tail being the last.

Operations for creating, growing and moving the snake have been specified and their Scratch implementation has been described.

Next Section: Moving the Snake at Regular Intervals

Table of Contents