8. More advanced games
These games demonstrate some essential building blocks you will need to make more advanced games of your own.
8.1. Lists
We introduced lists in Program 2.12. In this
game, we create an empty list []
and use a loop to fill it with
alien Actors.
We again use loops to draw all the aliens and move all the aliens in the list. When the mouse is clicked we add a new alien to the list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
WIDTH = 500
HEIGHT = 500
aliens = []
for i in range(0,10):
aliens.append(Actor('alien', (i*30, i*30)))
def draw():
screen.clear()
for alien in aliens:
alien.draw()
def update():
for alien in aliens:
alien.x += 2
if alien.x > WIDTH:
alien.x = 0
def on_mouse_down(pos, button):
aliens.append(Actor('alien', pos))
|
Advanced
Go back to a previous game (e.g. Program 5.1) and add a list of bullets that move up the screen. When the player presses the spacebar to shoot, add a new bullet to the list.
8.2. Animation
Animation is another use for functions. (See Program 2.17) We define our own function and then ask Pygame to call it back every 0.2 seconds. Most of this code is from Program 5.1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
alien = Actor("alien")
alien.pos = (200, 200)
def draw():
screen.clear()
alien.draw()
def update():
if keyboard.right:
alien.x = alien.x + 2
elif keyboard.left:
alien.x = alien.x - 2
images = ["alien_hurt", "alien"]
image_counter = 0
def animateAlien():
global image_counter
alien.image = images[image_counter % len(images)]
image_counter += 1
clock.schedule_interval(animateAlien, 0.2)
|
Exercise
Make the alien animate more quickly.
Advanced
Add another image to the list of images.
Advanced
Draw your own animation, e.g. a man walking left which plays when the left key is pressed
8.3. Simple physics
Here we draw a ball and move it, like we did in
Program 4.2. But instead of moving it
by a fixed number of pixels, we store the number of pixels to move in
variables, vx
and vy
. These are velocities, i.e. speed in a
fixed direction. vx
is the speed in the horizontal direction and
vy
is the speed in the vertical direction. This allow us to change
the velocity. Here we reverse the velocity when the ball hits the edge
of the screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | WIDTH = 500
HEIGHT = 500
ball = Rect((200, 400), (20, 20))
vx = 1
vy = 1
def draw():
screen.clear()
screen.draw.filled_rect(ball, "red")
def update():
global vx, vy
ball.x += vx
ball.y += vy
if ball.right > WIDTH or ball.left < 0:
vx = -vx
if ball.bottom > HEIGHT or ball.top < 0:
vy = -vy
|
Advanced
Make the ball move faster by increasing its velocity each time it hits the sides.
8.4. Bat and ball game
Pong is the classic bat and ball game.
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 | WIDTH = 500
HEIGHT = 500
ball = Rect((150, 400), (20, 20))
bat = Rect((200, 480), (60, 20))
vx = 4
vy = 4
def draw():
screen.clear()
screen.draw.filled_rect(ball, "red")
screen.draw.filled_rect(bat, "white")
def update():
global vx, vy
ball.x += vx
ball.y += vy
if ball.right > WIDTH or ball.left < 0:
vx = -vx
if ball.colliderect(bat) or ball.top < 0:
vy = -vy
if ball.bottom > HEIGHT:
exit()
if(keyboard.right):
bat.x += 2
elif(keyboard.left):
bat.x -= 2
|
Exercise
Make the ball move more quickly.
Advanced
Add another bat at the top of the screen for player 2.
Advanced
Add bricks (Rects) that disappear when the ball hits them.
8.5. Timer
The update()
and draw()
functions are called by Pygame many
times every second. Each time draw()
is called we say it draws one
frame. The exact number of frames per second is called the framerate
and it will vary from one computer to another. Therefore counting frames
is not the most reliable way of keeping time.
Fortunately Pygame can tell us exactly how much many seconds have passed since the last frame in a parameter to our update function. We use this delta time to keep a timer.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
timer = 0
def update(dt):
global timer
timer += dt
def draw():
screen.clear()
screen.draw.text(f"Time passed: {timer}", (0, 0))
if timer > 5:
screen.draw.textbox("Time's up!", Rect(50, 50, 200, 200))
|
Exercise
Make the timer count down, not up.
Advanced
Add a timer to one of your other games.
Advanced
Add a timer to Program 2.12 that deletes one of the aliens when the timer runs out, then starts the timer again.
8.6. Callbacks: another kind of timer
Pygame has its own clock which we can use by asking it to callback one of our functions at a certain time, or regularly over and over at an interval.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import random
aliens = []
def add_alien():
aliens.append(
Actor("alien", (random.randint(0,500), random.randint(0,500)))
)
# call add_alien once, 0.5 seconds from now
clock.schedule(add_alien, 0.5)
# call add_alien over and over again, ever 2 seconds
clock.schedule_interval(add_alien, 2.0)
def draw():
screen.clear()
for alien in aliens:
alien.draw()
|
Exercise
Make the aliens appear more often.
Advanced
Use len(aliens)
to print how many aliens there are
Advanced
When there are too many aliens, stop adding them using this code:
clock.unschedule(add_alien)