Python Cheat Sheet - Week 2

Back again? Good. In Week 2 we made an entire game. Admittedly not one you'd want to play for long, but pretty good for an hour's work. Code is in blue, outputs are green.

P5

Last week we were printing words and emojis to the console. But that's not much fun. What if you want some graphics? There are a number of libraries that extend Python in this way, allowing you to make not just games, but apps, with buttons and crazy stuff like that. Pygame, PyOpenGL, Pyglet, Tkinter Kivy... the hardest part is deciding which to choose. Luckily, the Raspberry Pi Foundation has chosen for you, and P5 it is.

The Window

You're working in a code editor embedded in a browser, but if you were making something for the real world then your code would run in its own window. In the setup() function, you defined this to be 400 x 400 pixels. The first number is how wide it is (the x axis), the second is how high (the y axis). X runs left to right, and y runs top to bottom, so (0, 0) is the top left corner, (400, 400) is bottom right.

Drawing

Shapes are drawn using functions, and you pass numbers in the brackets to define the size and position:

rect(0, 0, 400, 250)

draws a rectangle with the top corner at (0, 0) and the bottom corner at (400, 250). It's worth saying, at this point, that if you don't know how x and y coordinates work, it may be an idea to ask someone for an explanation.

Rectangles, triangles and circles work like this:

rect(x1, y1, x2, y2)
where (x1, y1) is the first corner, (x2, y2) is the opposite corner

triangle(x1, y1, x2, y2, x3, y3)
where (x1, y1), (x2, y2) and (x3, y3) are 3 points of a triangle

circle(x1, y1, d)
where (x1, y1) is the circle's centre, and d is its width (diameter). Why do you define the width of the circle rather than its radius? I've no idea.

Stroke, fill and colour

When you draw a shape, stroke refers to the line around it. This can be any colour or thickness. Fill, on the other hand, refers to, well, the fill. So:

fill('cyan') stroke_weight(10) stroke('purple') circle(200, 200, 60)
=

How do you know what colours you can use? Purple is a safe bet. Cyan might be a mystery to you, unless you were programming ZX Spectrums in the 1980s. But what if you want something more specific? Pistacio, Arsenic or Dead Salmon? Well then you define your own colours, and I've explained all about that here.

The Game Loop

If you think about how a game works, it's always running, checking whether a key has been pressed, a mouse clicked, a collision detected. Unlike last weeks programs, it doesn't just run through and come to an end. It goes on forever, at least until something determines it should stop. The way that this is done is by running in an eternal loop - the game loop.

Everything that has to happen in the game is done or checked for in this loop, and when it gets to the end, it goes back to the beginning and does it all again. The game loop here is the draw() function, which draws the arrow on the screen, checks for a mouse click and outputs the score. Each of these is called a frame, and how quickly these happen is defined by the frame rate variable, which says how many times per second to run the loop.

run(frame_rate=2)

It also draws the entire scene every time. Why does it do that? Because if it didn't, every time it drew an arrow it would stay on the screen, and eventually every pixel would be covered by brown circles. By re-drawing everything from scratch, we effectively delete the previous arrow before drawing the new one.

Events

To know when the the user clicks a mouse or hits a key, the program listens for events. Here we want it to listen for a mouse click, and P5 has a function for that:

def mouse_pressed(): do_something()

Conditions - if, elif, else

Programs have to make decisions all the time. Just like in English, these are called conditionals, because they say "If a condition is met, do this." They also let you say "else if [a different condition is met]" (shortened to elif in Python), and "else...", letting you define an action if none of the conditions are met.

In my game, an aardvark eats cakes. The Custard Tart is disgraceful, and gets 1 point for the sugar alone. The Belgian Bun, Donut and Muffin all score 5, and the king of treats, the Chocolate Eclair, scores 10. We could write that like this:

def eat_cake(): if (cake == 'eclair'): score = score + 10 aarvark_burp() elif (cake == custard_tart) score = score + 1 else score = score + 5

Let's look at this more closely. The condition that's being tested goes after the if/elif keyword. Then there's a block of code to be executed if the condition is met. To be part of this block, each line has to be indented by 4 spaces from the condition line, exactly like we used indents to define the functions. Then the else keyword catches everything we haven't tested for.

Note that I put these conditions inside a function. That means the whole thing is already indented 4 spaces, so the code to be executed must be indented again, to a total of 8 spaces. You can nest multiple blocks of code in this way, requiring multiple levels of indentation, so you have to be quite careful with it.

Note also the double equals. This means "is equivalent to". You can read more about that here.