Thursday, 26 November 2015

Snake on MicroBit using MicroPython

I got my hands on one of the BBC's Microbit's as part of ntoll's Micro World Tour.

I used ntoll's upyed website to create my code and download the .hex file which I uploaded to the Microbit.

After a few tests to see if everything was working I decided to see if I could port the code I wrote to make Snake for Minecraft and Raspberry Pi Sense Hat.


I was pretty pleased. If you want to have a go yourself you will find the code here.

The code
import microbit

import random

class SnakeBit():
    UP = 0
    DOWN = 1
    RIGHT = 2
    LEFT = 3
    
    SNAKEBRIGHTNESS = 9
    APPLEBRIGHTNESS = 5
    SAMPLETIME = 50
    SAMPLESPERMOVE = 10
    
    def __init__(self):
        pass
    
    def startGame(self):
        microbit.display.clear()
        self.direction = self.UP
        self.length = 2
        self.tail = []
        self.tail.insert(0, [2, 4])
        self.createApple()
        self.score = 0
        
        playing = True
        
        samples = 0
        while(playing):
            #keep looping around, if the button is pressed, move the snake immediately, 
            #otherwise move it when the sample time is reached
            microbit.sleep(self.SAMPLETIME)
            buttonPressed = self._handle_buttons()
            samples = samples + 1
            if buttonPressed or samples == self.SAMPLESPERMOVE:
                playing = self.move()
                samples = 0
                
        microbit.display.scroll("Score = " + str(self.score), 100)
        microbit.display.clear()

    def _handle_buttons(self):
        buttonPressed = False
        
        #has a button been pressed
        if microbit.button_a.is_pressed():
            #wait for the button to be released
            while microbit.button_a.is_pressed():
                microbit.sleep(self.SAMPLETIME)
            self.left()
            buttonPressed = True
        
        if microbit.button_b.is_pressed():
            while microbit.button_b.is_pressed():
                microbit.sleep(self.SAMPLETIME)
            self.right()
            buttonPressed = True
            
        return buttonPressed

    def createApple(self):
        badApple = True
        #try and fnd a location for the apple
        while(badApple):
            x = random.randint(0,4)
            y = random.randint(0,4)
            badApple = self.checkCollision(x, y)
        self.apple = [x, y]
        microbit.display.set_pixel(x, y, self.APPLEBRIGHTNESS)

    def checkCollision(self, x, y):
        #is this outside the screen
        if x > 4 or x < 0 or y > 4 or y < 0:
            return True
        else:
            #or in the snakes tail
            for segment in self.tail:
                if segment[0] == x and segment[1] == y:
                    return True
            else:
                return False

    def addSegment(self, x, y):
        #create the new segment of the snake
        microbit.display.set_pixel(x, y, self.SNAKEBRIGHTNESS)
        self.tail.insert(0, [x, y])
        
        #do I need to clear a segment
        if len(self.tail) > self.length:
            lastSegment = self.tail[-1]
            microbit.display.set_pixel(lastSegment[0], lastSegment[1], 0)
            self.tail.pop()

    def move(self):
        #work out where the new segment of the snake will be
        newSegment = [self.tail[0][0], self.tail[0][1]]
        if self.direction == self.UP:
            newSegment[1] -= 1
        elif self.direction == self.DOWN:
            newSegment[1] += 1
        elif self.direction == self.LEFT:
            newSegment[0] -= 1
        elif self.direction == self.RIGHT:
            newSegment[0] += 1

        if self.checkCollision(newSegment[0], newSegment[1]):
            #game over
            snakehead = self.tail[0]
            for flashHead in range(0,5):
                microbit.display.set_pixel(snakehead[0], snakehead[1], self.SNAKEBRIGHTNESS)
                microbit.sleep(200)
                microbit.display.set_pixel(snakehead[0], snakehead[1], 0)
                microbit.sleep(200)
            
            return False
            
        else:
            self.addSegment(newSegment[0], newSegment[1])

            #has the snake eaten the apple?
            if newSegment[0] == self.apple[0] and newSegment[1] == self.apple[1]:
                self.length += 1
                self.score += 10
                self.createApple()

            return True

    def left(self):
        if self.direction == self.RIGHT:
            self.direction = self.UP
        elif self.direction == self.UP:
            self.direction = self.LEFT
        elif self.direction == self.LEFT:
            self.direction = self.DOWN
        elif self.direction == self.DOWN:
            self.direction = self.RIGHT

    def right(self):
        if self.direction == self.RIGHT:
            self.direction = self.DOWN
        elif self.direction == self.DOWN:
            self.direction = self.LEFT
        elif self.direction == self.LEFT:
            self.direction = self.UP
        elif self.direction == self.UP:
            self.direction = self.RIGHT

snake = SnakeBit()
snake.startGame()

2 comments:

  1. Cool, here's my version, uses the tilt sensor. I decided to wrap the screen as it's so small. More points if you choose a faster game.

    https://gist.github.com/mavhc

    ReplyDelete
  2. This is great fun! Thanks for sharing.

    I've made a microbit python simulator that lets you test code in your browser to speed up development and for people who haven't yet got their microbits. Here's your game of snake that you can test in a browser:

    https://create.withcode.uk/python/5D

    ReplyDelete