Score points
Step 5
Snake's tail extension management.
Score management and display.
When the snake stretches...
We will now look at the progression of the game and the increase in difficulty, which is correlated with the lengthening of the snake's tail. This happens every time the snake swallows an apple.
Let's start by writing a extendSnakeTail()
function that will handle queue lengthening:
# ----------------------------------------------------------
# Snake management
# ----------------------------------------------------------
def extendSnakeTail():
i = snake['head']
n = snake['len']
i = (i + 1) % n
x = snake['x'][i]
y = snake['y'][i]
for _ in range(SNAKE_EXTENT):
snake['x'].insert(i, x)
snake['y'].insert(i, y)
snake['len'] += SNAKE_EXTENT
This function is based on a new global variable that determines the additional tail length, i.e. the number of sections that will be added to the snake:
# ----------------------------------------------------------
# Global variables
# ----------------------------------------------------------
SNAKE_EXTENT = 2
The extendSnakeTail()
function is relatively simple:
We start by positioning ourselves on the end of the snake's tail (which happens to be the box that immediately follows the head) at the level of the snake['x']
and snake['y']
lists:
i = snake['head']
n = snake['len']
i = (i + 1) % n
We then pick the position (x,y)
of the end of the tail:
x = snake['x'][i]
y = snake['y'][i]
Then we will insert, still at the end of the tail, copies of x
and y
(SNAKE_EXTENT
copies more precisely):
for _ in range(SNAKE_EXTENT):
snake['x'].insert(i, x)
snake['y'].insert(i, y)
Finally, we update the snake['len']
property that characterizes the length of the lists:
snake['len'] += SNAKE_EXTENT
Here is a diagram that summarizes the sequence of operations performed:
Therefore, the 2
additional sections initially occupy the same position as the end of the tail (since they are copies). They will gradually "unfold" as the snake moves forward on the grid.
All that remains is to integrate this routine into the scheduler:
# ----------------------------------------------------------
# Game management
# ----------------------------------------------------------
def tick():
if game['mode'] == MODE_START:
resetSnake()
spawnApple()
game['mode'] = MODE_READY
elif game['mode'] == MODE_READY:
handleButtons()
moveSnake()
if snakeHasMoved():
game['mode'] = MODE_PLAY
elif game['mode'] == MODE_PLAY:
handleButtons()
moveSnake()
if didSnakeEatApple():
extendSnakeTail()
spawnApple()
if didSnakeBiteItsTail() or didSnakeHitTheWall():
game['mode'] = MODE_START
draw()
The extension of the tail is done during the MODE_PLAY
phase when the snake swallows an apple:
if didSnakeEatApple():
extendSnakeTail()
spawnApple()
There you go! Demonstration:
Perfect! Perfect! Now we can take care of the player's score...
Score management
To memorize the score as the game progresses, we will store it in the game
engine:
# ----------------------------------------------------------
# Initialization
# ----------------------------------------------------------
game = {
'mode': MODE_START,
'score': 0
}
Then we'll increment it every time the snake swallows an apple. And don't forget to reset it every time the game goes into the MODE_START
phase:
# ----------------------------------------------------------
# Game management
# ----------------------------------------------------------
def tick():
if game['mode'] == MODE_START:
resetSnake()
spawnApple()
game['mode'] = MODE_READY
game['score'] = 0
elif game['mode'] == MODE_READY:
handleButtons()
moveSnake()
if snakeHasMoved():
game['mode'] = MODE_PLAY
elif game['mode'] == MODE_PLAY:
handleButtons()
moveSnake()
if didSnakeEatApple():
game['score'] += 1
extendSnakeTail()
spawnApple()
if didSnakeBiteItsTail() or didSnakeHitTheWall():
game['mode'] = MODE_START
draw()
Resetting the score at the beginning of the game:
if game['mode'] == MODE_START:
resetSnake()
spawnApple()
game['mode'] = MODE_READY
game['score'] = 0
Increase the score each time the snake swallows an apple:
if didSnakeEatApple():
game['score'] += 1
extendSnakeTail()
spawnApple()
All that's left is to display the score! To do this, we will define a new global variable to determine its display color:
# ----------------------------------------------------------
# Global variables
# ----------------------------------------------------------
COLOR_SCORE = 0xffff
Then we will add a drawScore()
function that will be responsible for displaying it on the screen, which we will call from the main method draw()
, responsible for the global display of the game scene :
# ----------------------------------------------------------
# Graphic display
# ----------------------------------------------------------
def draw():
clearScreen()
drawWalls()
drawSnake()
drawScore()
drawApple()
def drawScore():
display.setColor(COLOR_SCORE)
display.print(2, 2, game['score'])
The score is displayed at the coordinates (2,2)
.
Come on!... We save the script and can now admire the result:
We're almost done with our Snake!
We still have to optimize things a little and add a few finishing touches to finish the game in style.
To the next step!