Beginning Game Programming for Teens with Python

This is a post by Tutorial Team Member Julian Meyer, a 13-year-old python developer. You can find him on Google+ and Twitter. Have you ever wondered how video games are created? It’s not as complicated as you might think! In this tutorial, you’ll create a simple game called Bunnies and Badgers, where the hero, the […] By .

4 (17) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 4 of 5 of this article. Click here to view the first page.

Step 7: Collisions with Badgers and Arrows

The badgers are attacking your castle but your arrows have no effect on them! How's a bunny supposed to defend his home?

Time to set the arrows to kill the badgers so you can safeguard your castle and win the game! Basically, you have to loop through all of the bad guys and inside each of those loops, you have to loop through all of the arrows and check if they collide. If they do, then delete the badger, delete the arrow, and add one to your accuracy ratio.

Right after section #6.3.1, add this:

        #6.3.2 - Check for collisions
        index1=0
        for bullet in arrows:
            bullrect=pygame.Rect(arrow.get_rect())
            bullrect.left=bullet[1]
            bullrect.top=bullet[2]
            if badrect.colliderect(bullrect):
                acc[0]+=1
                badguys.pop(index)
                arrows.pop(index1)
            index1+=1

There's only one important thing to note in this code. The if statement is a built-in PyGame function that checks if two rectangles intersect. The other couple of lines just do what I explained above.

If you run the program, you should finally be able to shoot and kill the badgers.

Step 8: Add a HUD with Health Meter and Clock

The game's progressing pretty well. You have your attackers, and you have your defender. Now all you need is a way to keep score and to show how well the bunny is doing.

The easiest way to do this is to add a HUD (Heads Up Display) that shows the current health level of the castle. You can also add a clock to show how long the castle has survived.

First add the clock. Add the following code right before the beginning of section #7:

    # 6.4 - Draw clock
    font = pygame.font.Font(None, 24)
    survivedtext = font.render(str((90000-pygame.time.get_ticks())/60000)+":"+str((90000-pygame.time.get_ticks())/1000%60).zfill(2), True, (0,0,0))
    textRect = survivedtext.get_rect()
    textRect.topright=[635,5]
    screen.blit(survivedtext, textRect)

The above code simply creates a new font using the default PyGame font set to size 24. Then that font is used to render the text of the time onto a surface. After that, the text is positioned and drawn onscreen.

Next add the health bar. But before drawing the health bar, you need to load the images for the bar. Add the following code to the end of section #3:

healthbar = pygame.image.load("resources/images/healthbar.png")
health = pygame.image.load("resources/images/health.png")

The first is the red image used for the full health bar. The second is the green image used to show the current health level.

Now add the following code right after section #6.4 (which you just added) to draw the health bar on screen:

    # 6.5 - Draw health bar
    screen.blit(healthbar, (5,5))
    for health1 in range(healthvalue):
        screen.blit(health, (health1+8,8))

The code first draws the all-red health bar. Then it draws a certain amount of green over the bar, according to how much life the castle has remaining.

If you build and run the program, you should have a timer and a health bar.

Step 9: Win or Lose

But what's this? If you play for long enough, even if your health goes down to zero, the game still continues! Not just that, you can continue to shoot at the badgers, too. That isn't going to work, now is it? You need some sort of a win/lose scenario to make the game worth playing.

So let's add the win and lose condition as well as the win or lose screen. :] You do this by exiting out of the main loop and going into a win/lose loop. In the win/lose loop, you have to figure out if the user won or lost and display the screen accordingly.

Here is a basic outline of the win/lose scenarios:

If time is up (90000 ms or 90 seconds) then:

  • Stop running the game
  • Set outcome of game to 1 or win

If the castle is destroyed then:

  • Stop running game
  • Set outcome of game to 1 or win

Calculate the accuracy either way.

Note: The acc[0]*1.0 is just converting acc[0] to a float. If you do not do this, the division operand will return an integer like 1 or 2 instead of a float like 1.5

Note: The acc[0]*1.0 is just converting acc[0] to a float. If you do not do this, the division operand will return an integer like 1 or 2 instead of a float like 1.5

Add these lines to the end of game.py:

    #10 - Win/Lose check
    if pygame.time.get_ticks()>=90000:
        running=0
        exitcode=1
    if healthvalue<=0:
        running=0
        exitcode=0
    if acc[1]!=0:
        accuracy=acc[0]*1.0/acc[1]*100
    else:
        accuracy=0
# 11 - Win/lose display        
if exitcode==0:
    pygame.font.init()
    font = pygame.font.Font(None, 24)
    text = font.render("Accuracy: "+str(accuracy)+"%", True, (255,0,0))
    textRect = text.get_rect()
    textRect.centerx = screen.get_rect().centerx
    textRect.centery = screen.get_rect().centery+24
    screen.blit(gameover, (0,0))
    screen.blit(text, textRect)
else:
    pygame.font.init()
    font = pygame.font.Font(None, 24)
    text = font.render("Accuracy: "+str(accuracy)+"%", True, (0,255,0))
    textRect = text.get_rect()
    textRect.centerx = screen.get_rect().centerx
    textRect.centery = screen.get_rect().centery+24
    screen.blit(youwin, (0,0))
    screen.blit(text, textRect)
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit(0)
    pygame.display.flip()

This is the longest bit of code yet! But it’s not that complicated.

The first if statement checks if the time is up. The second one checks if the castle is destroyed. The third one calculates your accuracy ratio. After that, a quick if statement checks if you won or lost and displays the correct image.

Of course, if you want to display images for the win and lose screens, then those images have to be loaded first. So add the following code to the end of section #3:

gameover = pygame.image.load("resources/images/gameover.png")
youwin = pygame.image.load("resources/images/youwin.png")

One more quick thing. Change section #4 from:

# 4 - keep looping through
while 1:
    badtimer-=1

To:

# 4 - keep looping through
running = 1
exitcode = 0
while running:
    badtimer-=1

The running variable keeps track of if the game is over and the exit code variable keeps track of whether the player won or lost.

Run the game again and now you can either triumph or die trying! Cool. :]

Step 10: Gratuitous Music and Sound Effects!

The game's looking pretty good but how does it sound? It's a bit quiet, isn't it? Adding some sound effects can change the whole feel of a game.

PyGame makes loading and playing sounds super simple. First, you have to initialize the mixer by adding this at the end of section #2:

pygame.mixer.init()

Then load the sounds and set the volume level at the end of section #3:

# 3.1 - Load audio
hit = pygame.mixer.Sound("resources/audio/explode.wav")
enemy = pygame.mixer.Sound("resources/audio/enemy.wav")
shoot = pygame.mixer.Sound("resources/audio/shoot.wav")
hit.set_volume(0.05)
enemy.set_volume(0.05)
shoot.set_volume(0.05)
pygame.mixer.music.load('resources/audio/moonlight.wav')
pygame.mixer.music.play(-1, 0.0)
pygame.mixer.music.set_volume(0.25)

Most of the above code is simply loading the audio files and configuring the audio volume levels. But pay attention to the pygame.mixer.music.load line – that line loads the background music for the game and the next line sets the background music to repeat forever.

That takes care of the audio configuration. :] Now all you need to do is to play the various sound effects as needed. Do that as per the directions in the comments for the code below:

# section 6.3.1 after if badrect.left<64:
hit.play()
# section 6.3.2 after if badrect.colliderect(bullrect):
enemy.play()
# section 8, after if event.type==pygame.MOUSEBUTTONDOWN:
shoot.play()

Run the game one more time and you'll notice that you now have background music and sound effects for collisions and shooting. The game feels that much more alive! :]