Snake - Part 6: What a classy snake

Subclassing

You might have noticed, that in the last part, we created three blank functions:

  • on_init()
  • on_event(event)
  • draw()

These are called at specific points during the game loop.

We can use these to expand on the Game-class in a so called subclass.
Subclasses work just like normal classes, with the exeption of inheriting all functions and methods of another class.

So when writing the snake for our game, we can start with the following:

class Snake(Game):
    def on_init(self, event):
        pass
    def on_event(self, event):
        pass
    def draw(self):
        pass

Now we have functions that are run

  1. When starting the game
  2. Every time an event is called
  3. Every tick of the game

Food

The food in snake is pretty simple.

  1. We need to store its position during the game
  2. We need to be able to generate new random positions

The things we need to achieve this are:

  1. A new food-class for storing the coordinates and food-specific functions
  2. random.randint()
  3. The size of the board, to generate coordinates ON the board

I have solved this the following way:

class Food():
    def __init__(self, _playing_field_size):
        self._playing_field_size = _playing_field_size
        self.reset()
    def genCoord(self,boundary:int) -> int():
        return random.randint(0,boundary-1)
    def genCoords(self, boundary:int) -> tuple:
            return (self.genCoord(boundary),self.genCoord(boundary))
    def get(self):
        if self.coordFood == None:
            self.coordFood = self.genCoords(self._playing_field_size)
        return self.coordFood
    def reset(self): self.coordFood = None
    coords = property(get)

To implement this into our Game, we will need to do the following:

  1. Generate a food on startup
  2. Draw the food
  3. Generate a new food

Number 1 we achieve by creating a new food-Instance.
For Number 2, we can simply call draw_cell() with the coords of the food and a colour of our choice.
The key to Number 3 is calling Food().reset().

To test the generation of new food, I chose to reset it when I press the Return key.
Of course, once we have the player, it will get triggered on collision.

class Snake(Game):
    def on_init(self):
        self.food = Food(self._playing_field_size)
    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN:
                self.food.reset()
    def draw(self):
        self.drawFood()
    # #### FOOD ####
    def drawFood(self):
        self.draw_cell(*self.food.coords,(200,0,0))