SotK's Python Tutorials - Part 7: More Pygame

Started by Son of the King, May 13, 2014, 10:18:28 PM

Previous topic - Next topic

Son of the King

SotK's Python Tutorials
Part 7: More Pygame




Introduction:

Last time, we made a window open on the screen. Its not a lot, but its the basis of anything with pygame (obviously). By the end of this tutorial we will have made a box on the screen, and been able to move it around with WASD! This is clearly a basis upon which a simple game can be built.

Township started out similar to this, I had an assignment to create something with dynamic graphics using pygame, and was devoid of inspiration so made a bunch of spheres chase each other around the screen and got an idea from there.

Representing a box:

At the end of the last tutorial we had the following, which opened a window and coloured it black.


# import pygame modules
import pygame

# initialise pygame
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('Hello, world!')

# game loop
running = True
while running:
    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            # Terminate on window closure
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
            # Terminate on Esc keypress
            self.running = False

    # drawing code
    screen.fill((0, 0, 0))

    pygame.display.flip()


We want to have a box at a position on this window. Lets say [295, 295] as that will but the box in the centre of the window. This position is the top-left corner of the box. It will be a good idea to store this position in a variable, so that we can modify the position easily. Since in the future we will want to make this box move, it will be a good idea to have a variable to represent its speed too. We are working in 2D, so we'll make the speed a two-element list of the form (horizontal speed, vertical speed). For now this can be [0, 0]. Our box could also use a height and width, so we'll make those too, a square of edge length 10 pixels. We'll also want a colour for the box to be, in this case we'll choose white (or (255, 255, 255)).

Note we use lists for the position and the speed so that we can change them later on.

Finally, we will need to make a "Rect" object, which is pygame's representation of a rectangular shape.


# import pygame modules
import pygame

# initialise pygame
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('Hello, world!')

# set up box stuff
box_pos = [295, 295]
box_speed = [0, 0]
box_height = 10
box_width = 10
box_colour = (255, 255, 255)
box = pygame.Rect(box_pos, (box_width, box_height))

# game loop
running = True
while running:
    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            # Terminate on window closure
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
            # Terminate on Esc keypress
            self.running = False

    # drawing code
    screen.fill((0, 0, 0))

    pygame.display.flip()


That is all the data we need to draw the box, and potentially move it in the future, so on to drawing!

Drawing the box:

Clearly, the drawing code for our example is at the end of the loop. We want to draw the box after filling the screen in black (otherwise our box will be drawn "underneath" the black of the screen). Imagine you are painting a picture, so the things nearest the front need to be drawn last.

Drawing a rectangle in pygame is simple. We use the function pygame.draw.rect(), which takes a surface (the screen), the colour of the rectangle and the Rect object to draw.


# import pygame modules
import pygame

# initialise pygame
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('Hello, world!')

# set up box stuff
box_pos = [295, 295]
box_speed = [0, 0]
box_height = 10
box_width = 10
box_colour = (255, 255, 255)
box = pygame.Rect(box_pos, (box_width, box_height))

# game loop
running = True
while running:
    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            # Terminate on window closure
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
            # Terminate on Esc keypress
            self.running = False

    # drawing code
    screen.fill((0, 0, 0))

    pygame.draw.rect(screen, box_colour, box)

    pygame.display.flip()


Now, there is a box in the middle of the screen!

Moving the box:

Great, there is a box, but it doesn't do a lot. Lets make that box move around!

In the last tutorial I mentioned the pygame.KEYUP event. There is an opposite event, pygame.KEYDOWN. We will use these to make the WASD keys make the box move. When a key is pressed down, we need to check which one is pressed and change the speed of the box accordingly. When the key goes up again we need to put the speed back to 0 in the relevant direction. The vert_keys and hori_keys tuples store the vertical and horizontal keys to make the checking nicer for when the key goes up.


vert_keys = (pygame.K_w, pygame.K_s)
hori_keys = (pygame.K_a, pygame.K_s)
if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_w:
        box_speed[1] = -1
    if event.key == pygame.K_s:
        box_speed[1] = 1
    if event.key == pygame.K_a:
        box_speed[0] = -1
    if event.key == pygame.K_d:
        box_speed[0] = 1
elif event.type == pygame.KEYUP:
    if event.key in vert_keys:
        box_speed[1] = 0
    if event.key in hori_keys:
        box_speed[0] = 0


We now integrate this into the event loop of our main program. We should also make the position of the box change so that we can see an effect. We will need to move our definition of the Rect object into the loop since it takes the position as a parameter.


# import pygame modules
import pygame

# initialise pygame
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('Hello, world!')

# set up box stuff
box_pos = [295, 295]
box_speed = [0, 0]
box_height = 10
box_width = 10
box_colour = (255, 255, 255)

vert_keys = (pygame.K_w, pygame.K_s)
hori_keys = (pygame.K_a, pygame.K_d)

# game loop
running = True
while running:
    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                box_speed[1] = -1
            if event.key == pygame.K_s:
                box_speed[1] = 1
            if event.key == pygame.K_a:
                box_speed[0] = -1
            if event.key == pygame.K_d:
                box_speed[0] = 1
        elif event.type == pygame.KEYUP:
            if event.key in vert_keys:
                box_speed[1] = 0
            if event.key in hori_keys:
                box_speed[0] = 0
            if event.key == pygame.K_ESCAPE:
                running = False

    # update box
    box_pos[0] += box_speed[0]
    box_pos[1] += box_speed[1]

    # drawing code
    screen.fill((0, 0, 0))

    # draw box
    box = pygame.Rect(box_pos, (box_width, box_height))
    pygame.draw.rect(screen, box_colour, box)

    pygame.display.flip()


Now the box will move when you press the WASD keys! It moves fast, so be careful.

Next time I will talk about how we can use classes to make this code neater.