One of the most important skills any coder can have is the ability to learn from other coders, sometimes borrowing from those who have solved a problem, so that we can build on their work.
... Well, not really. Sometimes copying others work is cheating, like when you're taking a test in school. In many situations, though, using others' work to do something is really the easiest and best way to go about things.
Just make sure you have permission from the person you're copying!
For this project, we are going to try to emulate rotating our space ship, using our Raspberry Pi Sense HAT joystick. The led matrix will be used to show how the stars will appear out of the window of our ship.
We will first need to find out how we can read the joystick input. Often, we can just do a quick internet search for documentation. We have been controlling our Pi with the sense_hat library. (that's what we have been importing with the import statement at the top of our code)
This library is an example of an "Application Programming Interface" or "API"
Wow! there sure is a lot of stuff on this page? ALL commands for the Raspberry Pi are here to see, with examples of how they can be used! And it looks like there is an example for how to use the joystick at the very bottom of the page.
Okay. It looks like there is a single lit LED on the Sense HAT's LED matrix, and we can use the joystick to change which LED is lit up. Cool!
It looks like a lot of the things we would want to do are already being done here. That is going to save us a lot of time. All we have to do now is figure out which parts we want to keep, and which parts we are going to have to change. To do that, we have to read through the code very carefully, and figure out what it is doing, so that we can know how to change it.
Wow, I can see once you cheat the first time, it only gets easier and easier.
Let's take a look at this code together and see if we can figure out what is going on...
from sense_hat import SenseHat, ACTION_PRESSED, ACTION_HELD, ACTION_RELEASED
from signal import pause
# okay, so instead of just 'import sense_hat, it looks like we are only importing parts of it.
# this way, we aren't loading as much, and we don't have to type in 'sense_hat.' before anything.
# I don't know what this pause function from this signal library is for.
# to tell you the truth, I don't even know what the signal library is for.
# I won't really worry about any of that now.
# If you don't know what something in someone else's code does,
# then it's better to leave it alone until you learn more about it.
# We'll just ignore it for now.
x = 3
y = 3
sense = SenseHat()
# it looks like we are declaring some x and y coordinates, and instantiating a SenseHat()
# so far so good...
def clamp(value, min_value=0, max_value=7):
return min(max_value, max(min_value, value))
# okay, it looks like clamp takes a value, aparently a number,
# and makes sure anything below zero becomes zero, and anything over seven becomes seven.
# FINALLY. It looks like we are getting into the joystick...
# These functions are being defined to handle the event of the joystick being pressed.
# When the joystick is pressed in a direction,
# Then the code in the body of the function assigned to that event gets run.
def pushed_up(event):
global y
if event.action != ACTION_RELEASED:
y = clamp(y - 1)
def pushed_down(event):
global y
if event.action != ACTION_RELEASED:
y = clamp(y + 1)
def pushed_left(event):
global x
if event.action != ACTION_RELEASED:
x = clamp(x - 1)
def pushed_right(event):
global x
if event.action != ACTION_RELEASED:
x = clamp(x + 1)
# it looks like these functions allow us to use the joystick to change the x and y values.
# moving the joystick right adds to the x value,
# moving the joystick down adds to the y value. Makes sense...
def refresh():
sense.clear()
sense.set_pixel(x, y, 255, 255, 255)
# it looks like the refresh() function updates the image on the LED matrix.
sense.stick.direction_up = pushed_up
sense.stick.direction_down = pushed_down
sense.stick.direction_left = pushed_left
sense.stick.direction_right = pushed_right
sense.stick.direction_any = refresh
# Okay now that the event handling functions have been defined,
# these lines are used to bind the functions to the events themselves.
# Finally, we call refresh when the run button is pressed, and then pause is used.
# CHALLENGE: what does pause() do?
refresh()
pause()
There are three things we will need to change in this code, to simulate our star field.
Go ahead and delete the clamp function.
In each of the joystick event-handling functions, remove the clamp function, but keep the argument. Just replace the pluses with minuses, and replace the minuses with pluses.
Next, insert the following code into the body of the refresh() function, between sense.clear() and sense.set_pixel().
star_coords = ((x%8, (y - 1)%8),
((x + 5)%8, y%8),
((x - 1)%8, (y + 4)%8),
((x + 4)%8, (y + 5)%8))
for star in star_coords:
i, j = star
Now, all we have to do is put the cursor at the beginning of the sense.set_pixel() line, and hit the 'Tab' key. This will put the set_pixel() function inside the for loop. After that, just change the functions 'x' argument to refer to 'i', and change the 'y' argument to be 'j'.
The final version of your code should look like this:
from sense_hat import SenseHat, ACTION_PRESSED, ACTION_HELD, ACTION_RELEASED
from signal import pause
x = 3
y = 3
sense = SenseHat()
def pushed_up(event):
global y
if event.action != ACTION_RELEASED:
y = y + 1
def pushed_down(event):
global y
if event.action != ACTION_RELEASED:
y = y - 1
def pushed_left(event):
global x
if event.action != ACTION_RELEASED:
x = x + 1
def pushed_right(event):
global x
if event.action != ACTION_RELEASED:
x = x - 1
def refresh():
sense.clear()
star_coords = ((x%8, (y - 1)%8),
((x + 5)%8, y%8),
((x - 1)%8, (y + 4)%8),
((x + 4)%8, (y + 5)%8))
for star in star_coords:
i, j = star
sense.set_pixel(i, j, 255, 255, 255)
sense.stick.direction_up = pushed_up
sense.stick.direction_down = pushed_down
sense.stick.direction_left = pushed_left
sense.stick.direction_right = pushed_right
sense.stick.direction_any = refresh
refresh()
pause()