Pygame from scratch – chapter 1

If you want to start making games with pygame, you need to learn as first thing how to move an object on the screen. I tried to make as less lines of code for this so that you do not take too much time to get how it works. Here is a screen that shows you the result:

And here is the code, I think it is very clear what it does.

import pygame
import sys

# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
rectx, recty = 100, 100
rectangle = pygame.Surface((10,10))
rectangle.fill((255,0,0)) # color red for it
# direction controller
go = 0
while True:
    # use the event.key id to move
    if go == 1073741903: rectx += 1  
    if go == 1073741904: rectx -= 1    # left
    if go == 1073741905: recty += 1
    if go == 1073741906: recty -= 1    # top
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            go = event.key

    screen.blit(rectangle, (rectx, recty))
    pygame.display.flip()
    clock.tick(60)

The event.key returns a number for each key pressed, so I used this number to change directions. These are the numbers for the arrow keys. The rectangle is made using a Surface, that is a part of the memory that contains images in a rectangular size. I could create a rectangle instead, you can do it, but I found that this way was simpler and also more usable, in case you want to make changes to the Surface. So, in just 23 lines of code we made something happen. In another post we will see how to make an actual game going further with our code.

import pygame
import sys

# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
rectx, recty = 100, 100
rectangle = pygame.Surface((10,10))
rectangle.fill((255,0,0)) # color red for it
# direction controller
go = 0
while True:
    # use the event.key id to move
    match go:
        case 3: rectx += 1 
        case 4: rectx -= 1 
        case 5: recty += 1 
        case 6: recty -= 1

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            go = event.key % 10

    screen.blit(rectangle, (rectx, recty))
    pygame.display.flip()
    clock.tick(60)

We could also use match case instead of if, taking only the last digit of the event.key (but we could have other keys that return that last digit, I dunno if it’s a good idea, maybe it’s better to use the whole number).

If you don’t want to make a trace of the square, you just fill the screen every frame with the color of the background.

import pygame
import sys

# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
rectx, recty = 100, 100
rectangle = pygame.Surface((10,10))
rectangle.fill((255,0,0)) # color red for it
# direction controller
go = 0
while True:
    screen.fill((0,0,0))
    # use the event.key id to move
    match go:
        case 1073741903: rectx += 1 
        case 1073741904: rectx -= 1 
        case 1073741905: recty += 1 
        case 1073741906: recty -= 1

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            go = event.key

    screen.blit(rectangle, (rectx, recty))
    pygame.display.flip()
    clock.tick(60)

If you want you could also use a class to make the rectangle.

import pygame
import sys

# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
class Shape:
    def __init__(self, x, y):
        self.rectx, self.recty = x, y
        self.surface = pygame.Surface((10,10))
        self.surface.fill((255,0,0)) # color red for it

# direction controller
rectangle = Shape(100,100)
go = 0
while True:
    screen.fill((0,0,0))
    # use the event.key id to move
    match go:
        case 1073741903: rectangle.rectx += 1 
        case 1073741904: rectangle.rectx -= 1 
        case 1073741905: rectangle.recty += 1 
        case 1073741906: rectangle.recty -= 1

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            go = event.key

    screen.blit(rectangle.surface, (rectangle.rectx, rectangle.recty))
    pygame.display.flip()
    clock.tick(60)

You could ask, what is it for?

In case you wanted to create a more complex figure with 5 rectangles (that are sqares, indeed). You could do so:

import pygame
import sys

# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
class Shape(pygame.sprite.Sprite):
    def __init__(self, x, y, color):
        super().__init__()
        self.rectx, self.recty = x, y
        self.surface = pygame.Surface((10,10))
        self.surface.fill(color) # color red for it
        self.speed = 4
        group.add(self)
    def update(self, go):
        match go:
            case 1073741903: self.rectx += self.speed
            case 1073741904: self.rectx -= self.speed
            case 1073741905: self.recty += self.speed
            case 1073741906: self.recty -= self.speed
        screen.blit(self.surface, (self.rectx, self.recty))


# direction controller
group = pygame.sprite.Group()
rec1 = Shape(100,100,(255,0,0))
rec2 = Shape(100,90,(255,255,0))
rec3 = Shape(90,100,(255,255,255))
rec4 = Shape(110,100,(0,255,0))
rec5 = Shape(100,110,(0,255,255))
go = 0

def check_keys():
    global go
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()
            go = event.key
        else:
            go = 0
    return go


while True:
    screen.fill((0,0,0))
    # use the event.key id to move
    group.update(go)
    go = check_keys()
    pygame.display.flip()
    clock.tick(60)

Why I should do this and not just load an image like that instead? We will discover it in the next post, maybe. As you can see I user the super class Sprite of pygame.pygame. So I can use some methods in that class. I used the pygame.sprite.Group object called group (?) to update all the object just updating the object group. Otherwise I should have used 5 lines of code, and we do not want that, right?

I also added the attribute speed to the class Shape, so that it is easier to change speed of the square in case I want. In fact I changed it to 4, but I can imagine that the speed could change in the game for various reasons, so… it’s better to have it stored in a variable instead of having an absolute number.

But, why wait the next post when we can do something new now? Ok, we will use these 5 objects to do something like this:

So, that was an example of why we should use classes to make funcy stuffs. Here is the code modified to do what you saw in the video, with some math… if I knew that math could be used to make funny games I should have appreciate it more at school.

import pygame
import sys
import math
# Initialize Pygame
pygame.init()

# Create a window with a clock for frame rate speed
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
# coordinates of the rectangle and surface of it
class Shape(pygame.sprite.Sprite):
    def __init__(self, x, y, color, pos=""):
        super().__init__()
        self.rectx, self.recty = x, y
        self.surface = pygame.Surface((10,10))
        self.surface.fill(color) # color red for it
        self.speed = 4
        self.pos = pos
        group.add(self)
    def update(self, go):
        match go:
            case 1073741903: self.rectx += self.speed
            case 1073741904: self.rectx -= self.speed
            case 1073741905: self.recty += self.speed
            case 1073741906: self.recty -= self.speed
        self.pulsar()

    def pulsar(self):
        if self.pos == "right":
            self.rectx += math.cos(timer / 4)
        if self.pos == "left":
            self.rectx -= math.cos(timer / 4)
        if self.pos == "top":
            self.recty -= math.cos(timer / 4)
        if self.pos == "bottom":
            self.recty += math.cos(timer / 4)
        screen.blit(self.surface, (self.rectx, self.recty))


# direction controller
group = pygame.sprite.Group()
rec1 = Shape(100,100,(255,0,0), "center")
rec2 = Shape(100,86,(255,255,0), "top")
rec3 = Shape(86,100,(255,255,255), "left")
rec4 = Shape(114,100,(0,255,0), "right")
rec5 = Shape(100,114,(0,255,255), "bottom")
go = 0

def check_keys():
    global go
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # If the user presses the left arrow key, move the rectangle to the left
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()
            go = event.key
        else:
            go = 0
    return go

timer = 0
while True:
    screen.fill((0,0,0))
    # use the event.key id to move
    group.update(go)
    go = check_keys()
    pygame.display.flip()
    timer +=1
    clock.tick(60)

I have used a timer that goes up for every frame, so 60 times for second. maybe it’s too much? We will see it in the next post. This time it’s true, we continue in another post. Bye.

A preview of the next post

As the code is becoming complex, I will put it into github at this address:

https://github.com/formazione/pygamezero


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.