Step 1: Bounce a ball around the screen

In this step we’re going to put a square “ball” on the screen and then to make it move, bouncing off each of the walls when it hits them.

Step 1a: Put a ball on the screen

The Code

Note

Normally code which you should type is highlighted in yellow. Since this is the first code in the worksheet, you need to type it all in. I haven’t highlighted it all in yellow!

WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(WIDTH / 2, HEIGHT / 2, 30, 30)
ball.colour = "red"

def draw():
    #
    # Clear the screen and place the ball at its current position
    #
    screen.clear()
    screen.draw.filled_rect(ball, ball.colour)

What’s happening?

  • A Ball is a PyGame Zero rectangle object. Its position is centred on the size of the game window: if the window is made bigger, the ball will still be in the middle. When you create a PyGame rectangle object, you give it four numbers: x, y, w, h

    NB Although the first two numbers are using the WIDTH & HEIGHT constants, they represent the x, y position of the ball.

  • The draw function is a special function which PyGame Zero calls to show whatever needs to be there on the game screen. In this case, we just clear the screen every time and draw the ball.

Change it around

  • Change the colour of the ball.

    Hint: there’s a list of colours in the PyGame Zero section.

  • Change the size of the ball

    Hint: the last two numbers inside the ball = Ball(...) constructor are its initial size.

  • Change where the ball appears

    Hint: the first two numbers inside the ball = Ball(...) constructor are its initial position.

  • Have the ball appear somewhere different every time

    Hint: you can import the random module and use the function randint to select where the ball starts from

Step 1b: Make the ball move

The Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(WIDTH / 2, HEIGHT / 2, 30, 30)
ball.colour = "red"
#
# The ball moves one step right and one step down each tick
#
ball.direction = 1, 1
#
# The ball moves at a speed of 3 steps each tick
#
ball.speed = 3

def draw():
    #
    # Clear the screen and place the ball at its current position
    #
    screen.clear()
    screen.draw.filled_rect(ball, ball.colour)

def update():
    #
    # Move the ball along its current direction at its current speed
    #
    dx, dy = ball.direction
    ball.move_ip(ball.speed * dx, ball.speed * dy)

What’s happening?

  • We give the ball a direction and a speed (like a Vector, if you know what that is).
  • The update function is another special function which is called by PyGame Zero on every tick of its clock: it’s where we calculate how much our different objects have moved. You don’t put anything on the screen in the update function, only in the draw function.
  • ball.move_ip tells PyGame to change the position of the ball rectangle by the requested amount. The “ip” part of that stands for “in-place”: it moves the ball itself; there is an equivalent called just ball.move that returns a new ball object which has been moved by the requested amount.

Change it around

  • Make the ball move faster or slower

  • Change the angle at which the ball moves

    Hint: the angle is determined by the ball’s direction which combines an x and a y component.

Step 1c: Make the ball bounce off the walls

The Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(WIDTH / 2, HEIGHT / 2, 30, 30)
ball.colour = "red"
#
# The ball moves one step right and one step down each tick
#
ball.direction = 1, 1
#
# The ball moves at a speed of 3 steps each tick
#
ball.speed = 3

def draw():
    #
    # Clear the screen and place the ball at its current position
    #
    screen.clear()
    screen.draw.filled_rect(ball, ball.colour)

def update():
    #
    # Move the ball along its current direction at its current speed
    #
    dx, dy = ball.direction
    ball.move_ip(ball.speed * dx, ball.speed * dy)

    #
    # Bounce the ball off the left or right walls
    #
    if ball.right >= WIDTH or ball.left <= 0:
        ball.direction = -dx, dy

    #
    # Bounce the ball off the top or bottom walls
    # (We'll remove this later when the bat and the
    # bricks are in place)
    #
    if ball.bottom >= HEIGHT or ball.top <= 0:
        ball.direction = dx, -dy

What’s happening?

  • In our program WIDTH is the width of the window the game is running in and HEIGHT is its height. Although you can normally give variables like this whatever name you liked (such as W and H or x_extent and y_extent), when you’re using PyGame Zero, the names WIDTH and HEIGHT have a special meaning and must be spelt exactly that way.
  • When the edge of the ball reaches the left or right-hand edge of the screen, we change its horizontal direction only so it appears to bounce back off the wall.
  • When the edge of the ball reaches the top or bottom edge of the screen, we change its vertical direction only.

Change it around

  • Make the ball bounce differently on different walls, eg make the angle of reflection vary between the top/bottom and left/right walls.