Step 2: Make the ball bounce off the bat

In this step we’re going to put an oblong “bat” along the bottom of the screen. It will move left and right when the player moves the mouse. When the ball hits the bat it will bounce off it.

Finally, now that we have a bat in place, the player will die if the ball reaches the bottom edge of the screen.

Step 2a: Put a bat on the screen

At the end of Step 2a you will see: a green bat along the bottom of the screen. It won’t move yet, and it won’t stop the ball.

../_images/step-s2a.gif

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
46
47
48
49
50
51
52
53
54
55
56
57
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(0, 0, 30, 30)
ball.center = WIDTH / 2, HEIGHT / 2
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

class Bat(ZRect): pass
#
# The bat is a green oblong which starts just along the bottom
# of the screen and halfway across.
#
BAT_W = 150
BAT_H = 15
bat = Bat(WIDTH / 2, HEIGHT - BAT_H, BAT_W, BAT_H)
bat.colour = "green"

def draw():
    #
    # Clear the screen and place the ball at its current position
    #
    screen.clear()
    screen.draw.filled_rect(ball, ball.colour)
    screen.draw.filled_rect(bat, bat.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?

  • We make the bat in the same way as the ball: a coloured rectangle, only with a different shape and a different colour.
  • We draw it in the same way as well, inside the draw function.

Change it around

  • Change the colour of the bat
  • Change the size of the bat
  • Change where the bat starts

Step 2b: Control the bat with the mouse

At the end of Step 2b you will see: the bat being moved by the mouse. It still won’t stop the ball which will bounce off the floor

../_images/step-s2b.gif

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(0, 0, 30, 30)
ball.center = WIDTH / 2, HEIGHT / 2
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

class Bat(ZRect): pass
#
# The bat is a green oblong which starts just along the bottom
# of the screen and halfway across.
#
BAT_W = 150
BAT_H = 15
bat = Bat(WIDTH / 2, HEIGHT - BAT_H, BAT_W, BAT_H)
bat.colour = "green"

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

def on_mouse_move(pos):
    #
    # Make the bat follow the horizontal movement of the mouse.
    #
    x, y = pos
    bat.centerx = x

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?

  • When the mouse is moved, PyGame Zero automatically calls a function called on_mouse_move and passes in the current position of the mouse. We’re only interested in the horizontal movement, so we pick out the x-coordinate.
  • By setting the bat’s x-centre to the same as the mouse’s x-coordinate whenever the mouse moves, we make the bat move horizontally with the mouse.

Change it around

  • Make the bat move left & right according to the up and down movement of the mouse

    Hint: The mouse position has two components: x & y – guess which one you want to use?

  • Make the bat move up and down as well as left and right

    Hint: The bat – like any PyGame rectangle – has a centerx and a centery attribute

  • Make the bat move only when one of the buttons is pressed

    Hint: As well as an on_mouse_move() event, PyGame Zero has on_mouse_down() and on_mouse_up() events, which pass in the mouse position and which button was pressed.

Step 2c: Make the ball bounce off the bat

At the end of Step 2c you will see: the ball bouncing off the bat. The ball can still bounce off the floor

../_images/step-s2c.gif

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(0, 0, 30, 30)
ball.center = WIDTH / 2, HEIGHT / 2
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

class Bat(ZRect): pass
#
# The bat is a green oblong which starts just along the bottom
# of the screen and halfway across.
#
BAT_W = 150
BAT_H = 15
bat = Bat(WIDTH / 2, HEIGHT - BAT_H, BAT_W, BAT_H)
bat.colour = "green"

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

def on_mouse_move(pos):
    #
    # Make the bat follow the horizontal movement of the mouse.
    #
    x, y = pos
    bat.centerx = x

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 bat
    #
    if ball.colliderect(bat):
        ball.direction = dx, -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?

  • The colliderect function detects when one rectangle (the ball) has collided with another rectangle (the bat). As soon as this happens, we reverse the vertical direction of the ball (its y-direction) and it appears to “bounce” off the bat.

Change it around

  • Make the ball go backwards when it hits the bat

    Hint: At the moment, we only change the ball’s y-direction when we detect a collision with the bat.

  • Make the ball go randomly faster or slower when it hits the bat

Step 2d: The player dies if the ball hits the bottom of the screen

At the end of Step 2d you will see: the game end if the ball hits the floor instead of bouncing off the bat

../_images/step-s2d.gif

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
WIDTH = 640
HEIGHT = 480

class Ball(ZRect): pass
#
# The ball is a red square halfway across the game screen
#
ball = Ball(0, 0, 30, 30)
ball.center = WIDTH / 2, HEIGHT / 2
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

class Bat(ZRect): pass
#
# The bat is a green oblong which starts just along the bottom
# of the screen and halfway across.
#
BAT_W = 150
BAT_H = 15
bat = Bat(WIDTH / 2, HEIGHT - BAT_H, BAT_W, BAT_H)
bat.colour = "green"

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

def on_mouse_move(pos):
    #
    # Make the bat follow the horizontal movement of the mouse.
    #
    x, y = pos
    bat.centerx = x

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 bat
    #
    if ball.colliderect(bat):
        ball.direction = dx, -dy

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

    #
    # If the ball hits the bottom of the screen, you lose
    #
    ## DELETE --> if ball.bottom >= HEIGHT or ball.top <= 0:
    if ball.bottom >= HEIGHT:
        exit()

    #
    # Bounce the ball off the top wall
    #
    if ball.top <= 0:
        ball.direction = dx, -dy