Sense HAT Introduction
Introduction to Sense HAT projects
A couple of months ago I wrote two posts about RaspberryPi and Python (Docker and Oh My ZSH). At the same time I bought Sense HAT to play a little bit with it. The first thing, besides modification to my RasPi case, was coding tutorial which took me trough basic concepts of the hardware while I was creating classic Slug game (probably known under different name).
Once I’ve managed to complete it I decided to write another classic myself. Here you can find my “Sense Racing” tutorial.
This tutorial requires basic Python or generic programming knowledge
Getting started with Sense HAT
In any Sense HAT project (or tutorial) you woul need either:
- Raspberry Pi
- Sense HAT
- Preferably lates version of Raspbian
- Python3
- Sense HAT for Python3
sudo apt-get install sense-hat
Or
Code
Every project needs to be started with either sense_hat
or sense_emu
library import. In my code I’m doing it like that:
from sense_hat import SenseHat
# from sense_emu import SenseHat
Where one of them needs to be always commented out and by default sense_hat
is the active one. It allows an easy switch between the production environment (actual Sense HAT) and the development environment (Sense emulator).
Game Concept
Before we will step into further implementation lets define how the game should look like. So here is our project definition.
- We will have a car (single pixel) driving on the stright track whith some obstacles appearing on the road as we move forward.
- Car will be able to move left and right in the bottom row, by pressing left and right keys.
- Hitting any obstacle will end game.
- Points are based on distance we make.
- We can accellerate speed for a short time by pressing up key.
- Base speed will increase beased on game time.
Drawing Track
As everything on Sense HAT 8x8 display our graphic will be simplified to the maximum. Objects will be represented by different colour pixes, lets first define all colours that we need:
blank
for backgroundborder_colour
for track borders that will create illusion of movementcar_colour
so we know where we areobstacle_colour
and of course things we don’t want to hit
All colours are defined as (R,G,B) in range 0 - 255
here are mine:
blank = (0, 0, 0)
border_colour = (0, 0, 200)
car_colour = (100, 200, 0)
obstacle_colour = (100, 0, 0)
Race is completely different concept to Slug, our car will be moving by not moving at all. Actualy background has to move downwards. In such case we have to “remember” state of each point on screen and move it one row down and then create new row of track at the top. As shown on the image below, in the next step first row is becoming second, second is becoming third and so one. Only the car stays always at the bottom.
In order to achieve that we have to always redraw whole screen (like in classic CRT screen), so we have to create a matrix which will keep value of each pixel and at the beginning we will fill it with our background colour. As well as we have to define distance
and startup SenseHat()
.
track = [[blank for x in range(8)] for y in range(8)]
distance = 0
sense = SenseHat()
Now any movement will be achieved by simple operations on track
matrix.
It’s time to create actual drawing function, as an argument we will take our track
matrix.
def draw(matrix):
matrix.reverse()
flat_list = [item for sublist in matrix for item in sublist]
sense.set_pixels(flat_list)
To refresh state of pixels we will use built in sense.set_pixels()
which argument is a vector of rows from one the eight put one ofter another. So we have to convert our 8x8
matrix into 64
elements vector:
flat_list = [item for sublist in matrix for item in sublist]
And what is most important here, as we want our car to move forward by actually moving background backwards we have to reverse the matrix
.
Generating Track
As we already have a function which will draw a frame based on a given matrix of values. It’s time to generate some track:
def gen_track():
line = [blank for x in range(8)]
if distance % 4 > 1:
line[0] = border_colour
line[7] = border_colour
return line
This function is generating single line, which later on will be put ath the end (so after reverse at the beginning) of the matrix
. At the moment its just empty line generated in the same way as initial matrix [blank for x in range(8)]
.
And then it generates track borders in two of four cycles distance % 4 > 1
this can be change later if you desire different pattern of track border.
Filnally we have to use all created functions:
if __name__ == '__main__':
while True:
track.append(gen_track())
draw(track[distance:distance + 8])
distance += 1
sleep(0.5)
Game needs to happen in the infinit loop, eveytime frame wi will append track with a new line generated by gen_trac()
and we will draw last 8 rows of it. Then we have to increment distance
which tells program how far we moved on the track and to slow down cycles a little bit we will use sleep(0.5)
the actual value can be adjusted to your needs. Dont forget to add import:
from time import sleep
If you run this and you have everything setup corectly you shoudl see in your emulator track moving forward. Now you can try commenting out matrix.reverse()
reverse line and see the effect.
This will be contiuned in the next post.
Everything together:
- Category:
- Raspi