Welcome to Part 3 of this PyGame platformer tutorial, which I’m writing for my eldest son. So far we’ve covered the basic game loop in Part 1, and drawn the player character in Part 2. We will now look at moving the player character with the left/right arrows keys on the keyboard.
First though here is the code so far!
# import the PyGame library
import pygame
# initialise PyGame
pygame.init()
pygame.display.set_caption("Platformer")
# settings
HEIGHT = 450
WIDTH = 400
FPS = 60
# the clock and display surface
FramePerSec = pygame.time.Clock()
displaysurface = pygame.display.set_mode((WIDTH, HEIGHT))
# the Player Sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 15,15 is the width and height
self.surf = pygame.Surface((15, 15))
self.surf.fill((128,255,40))
self.rect = self.surf.get_rect()
self.rect.midbottom = (200, 225)
# visible elements
P1 = Player()
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
# the game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
displaysurface.fill((0, 0, 0))
# draw all visible elements
for entity in all_sprites:
displaysurface.blit(entity.surf, entity.rect)
pygame.display.update()
FramePerSec.tick(FPS)
Handling keyboard presses – left/right arrows
To move the character we need to know when the player has pressed the left/right arrows on the keyboard.
It’s really easy in PyGame – you can call pygame.key.get_pressed() which returns a list of all the keys that the player is holding down right now.
Remember that the game loop runs 60 times per second, so what we can do in the game loop is this:
- check
pygame.key.get_pressed() - if the user is holding down the left arrow, move the player to the left by a few pixels
- if the user is holding down the right arrow, move the player to the right by a few pixels
Here is the new game code, with movement code inserted:
# import the PyGame library
import pygame
from pygame.locals import *
# initialise PyGame
pygame.init()
pygame.display.set_caption("Platformer")
# settings
HEIGHT = 450
WIDTH = 400
FPS = 60
LEFT_RIGHT_MOVE = 5
# the clock and display surface
FramePerSec = pygame.time.Clock()
displaysurface = pygame.display.set_mode((WIDTH, HEIGHT))
# the Player Sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 15,15 is the width and height
self.surf = pygame.Surface((15, 15))
self.surf.fill((128,255,40))
self.rect = self.surf.get_rect()
self.rect.midbottom = (200, 225)
# visible elements
P1 = Player()
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
# the game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
displaysurface.fill((0, 0, 0))
# move the player left/right
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
P1.rect.left -= LEFT_RIGHT_MOVE
if keys[K_RIGHT]:
P1.rect.right += LEFT_RIGHT_MOVE
# draw all visible elements
for entity in all_sprites:
displaysurface.blit(entity.surf, entity.rect)
pygame.display.update()
FramePerSec.tick(FPS)
Note this line: LEFT_RIGHT_MOVE = 5 – this sets by how many pixels the player moves left or right each time the game loop runs. Make this bigger to move faster, smaller to move more slowly. Have a go and choose a number that feels right to you.
Also note these two operators: -= and += – they might look a little strange. They are a shorter way of subtracting or adding a number. So:P1.rect.left -= LEFT_RIGHT_MOVE
subtracts LEFT_RIGHT_MOVE pixels (in our case 5 pixels) from the current left position of the player’s rectangle. This moves the player’s character to the left.
AndP1.rect.left += LEFT_RIGHT_MOVE
adds LEFT_RIGHT_MOVE (5 pixels, remember) to the current left position of the rectangle. This moves the player’s character to the right.
Type out the new code and run the game. See how the player moves left and right when you hit the arrow keys?
Using other keys
You might not want to use the arrows keys – after all many games use ASDW to move the player around. You can change the code really easily to use different keys instead.
To use A to go left, change:if keys[K_LEFT]: to if keys[K_a]:
To use D to go right, change:
if keys[K_RIGHT]: to if keys[K_d]:
PyGame has these constants built in for each key on the keyboard – just add the letter to K_ and you can check whether it’s pressed. Number keys for example are K_0 all the way to K_9 for example.
Have a go and change the keyboard triggers for moving the player around.
Dealing with the edge of the screen
When you play the game right now you’ll see that if you press the left arrow long enough the player disappears off the edge of the screen. You can bring it back by pressing the right arrow – it’s not really gone, it’s just moved too far left to be displayed by the game.
This isn’t great – let’s see what we can do about it.
One idea is that it could stop at the edge of the screen. Remember that the coordinate system starts at 0 and goes all the way to the width of the game, stored in the WIDTH variable. PyGame also gives us handy values on the rect property to check the left/right position of the rectangle.
Using this information we end up with a new movement code to replace the code we already have in the game loop:
# move the player left/right
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
P1.rect.left -= LEFT_RIGHT_MOVE
if keys[K_RIGHT]:
P1.rect.right += LEFT_RIGHT_MOVE
# stop at the edge
if P1.rect.left < 0:
P1.rect.left = 0
if P1.rect.right > WIDTH:
P1.rect.right = WIDTH
How does this work?
When the player’s rectangle has gone off the left-hand side of the screen, its left coordinate will be less than zero. In this case we reset the left position to 0, so it’s snug against the left-hand side.
On the right-hand side we check whether the right edge of the rectangle has gone off the screen. This happens when it’s gone further than the WIDTH of the game. When it happens we reset the position to be exactly the WIDTH, so that the player is snug against the right side of the screen.
Alternative: Looping around the screen
Instead of stopping at the edges we can also loop around the screen. See if you can write this code yourself using the left/right if-statements from before.
Once you’ve tried, compare it with this code example. (If the code isn’t exactly the same it doesn’t matter, you might have found a different way of doing it!)
# move the player left/right
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
P1.rect.left -= LEFT_RIGHT_MOVE
if keys[K_RIGHT]:
P1.rect.right += LEFT_RIGHT_MOVE
# loop around
if P1.rect.left < 0:
P1.rect.right = WIDTH
if P1.rect.right > WIDTH:
P1.rect.left = 0
How does this work? Well, when the left edge of the player has gone off the left-hand side of the screen (left < 0) we set the right edge to be the WIDTH of the screen – this pops the player round exactly to the right-hand side.
Also when the right edge has gone off the right-hand side (right > WIDTH) we set the left edge to be at 0 – this pops the player round exactly to the left-hand side.
See which version you like most and use that one in your game!
I like the ‘stop at the edges’ approach, and with that in place here is the final code for this part of the tutorial:
# import the PyGame library
import pygame
from pygame.locals import *
# initialise PyGame
pygame.init()
pygame.display.set_caption("Platformer")
# settings
HEIGHT = 450
WIDTH = 400
FPS = 60
LEFT_RIGHT_MOVE = 5
# the clock and display surface
FramePerSec = pygame.time.Clock()
displaysurface = pygame.display.set_mode((WIDTH, HEIGHT))
# the Player Sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 15,15 is the width and height
self.surf = pygame.Surface((15, 15))
self.surf.fill((128,255,40))
self.rect = self.surf.get_rect()
self.rect.midbottom = (200, 225)
# visible elements
P1 = Player()
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
# the game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
displaysurface.fill((0, 0, 0))
# move the player left/right
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
P1.rect.left -= LEFT_RIGHT_MOVE
if keys[K_RIGHT]:
P1.rect.right += LEFT_RIGHT_MOVE
# stop at the edge
if P1.rect.left < 0:
P1.rect.left = 0
if P1.rect.right > WIDTH:
P1.rect.right = WIDTH
# draw all visible elements
for entity in all_sprites:
displaysurface.blit(entity.surf, entity.rect)
pygame.display.update()
FramePerSec.tick(FPS)
Next Steps
In Part 4 we’re going to add gravity and make the player jump!
Leave a Reply