Scrolling Background & Character Movement
Subscribe to Tech with Tim
In this tutorial series we will be working to create a side scrolling game with pygame. This game will involve objects randomly appearing on the screen that our character must avoid by jumping our sliding.
Game Assets
We are going to be using a series of different images to animate our game. Please download all of the game assets from one of the below links.
GitHub: Click Here
Note: The folder named "images" must be in the same directory as your python file.
Starter File
To save us a bit of time I have created a starter file for us to work off of. This file simply contains the code to load all of the images and animate the character. If you would like a detailed explanation of the starter file please watch the video.
import pygame from pygame.locals import * import os import sys import math pygame.init() W, H = 800, 447 win = pygame.display.set_mode((W,H)) pygame.display.set_caption('Side Scroller') bg = pygame.image.load(os.path.join('images','bg.png')).convert() bgX = 0 bgX2 = bg.get_width() clock = pygame.time.Clock() class player(object): run = [pygame.image.load(os.path.join('images', str(x) + '.png')) for x in range(8,16)] jump = [pygame.image.load(os.path.join('images', str(x) + '.png')) for x in range(1,8)] slide = [pygame.image.load(os.path.join('images', 'S1.png')),pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S3.png')), pygame.image.load(os.path.join('images', 'S4.png')), pygame.image.load(os.path.join('images', 'S5.png'))] jumpList = [1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4] def __init__(self, x, y, width, height): self.x = x self.y = y self.width = width self.height = height self.jumping = False self.sliding = False self.slideCount = 0 self.jumpCount = 0 self.runCount = 0 self.slideUp = False def draw(self, win): if self.jumping: self.y -= self.jumpList[self.jumpCount] * 1.2 win.blit(self.jump[self.jumpCount//18], (self.x,self.y)) self.jumpCount += 1 if self.jumpCount > 108: self.jumpCount = 0 self.jumping = False self.runCount = 0 elif self.sliding or self.slideUp: if self.slideCount < 20: self.y += 1 elif self.slideCount == 80: self.y -= 19 self.sliding = False self.slideUp = True if self.slideCount >= 110: self.slideCount = 0 self.slideUp = False self.runCount = 0 win.blit(self.slide[self.slideCount//10], (self.x,self.y)) self.slideCount += 1 else: if self.runCount > 42: self.runCount = 0 win.blit(self.run[self.runCount//6], (self.x,self.y)) self.runCount += 1
Game Loop
In every game there is something called a main loop or a game loop. This loop runs until the game is exited and is what is responsible for checking for events from the user. In our program we will use a while loop to represent the game loop.
run = True while run: for event in pygame.event.get(): # Loop through a list of events if event.type == pygame.QUIT: # See if the user clicks the red x run = False # End the loop pygame.quit() # Quit the game quit()
Scrolling Background
To make it appear as our character is moving forward we will actually just scroll the background backwards. We will use two background images and move them to the left each frame. Once one of the background images reaches the end of the screen we will reset its position back to the right. This will allow us to continually scroll the background.
run = True speed = 30 # NEW while run: clock.tick(speed) # NEW bgX -= 1.4 # Move both background images back bgX2 -= 1.4 if bgX < bg.get_width() * -1: # If our bg is at the -width then reset its position bgX = bg.get_width() if bgX2 < bg.get_width() * -1: bgX2 = bg.get_width() for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() quit()
Now that we are moving our background we need to draw it to the screen. To do this we will setup a function and call it from our game loop. This function will be called redrawWindow() and will be responsible for drawing all of our objects to the screen.
def redrawWindow(): win.blit(bg, (bgX, 0)) # draws our first bg image win.blit(bg, (bgX2, 0)) # draws the seconf bg image pygame.display.update() # updates the screen # Call this from the game loop!
Changing the Background Speed
Now that we have our background moving we want to increase its speed at a regular interval. To do this we will use a timer event. Every time the timer goes off we will increase the speed and reset the timer.
pygame.time.set_timer(USEREVENT+1, 500) # Sets the timer for 0.5 seconds # This should go above the game loop
To check if this timer is triggered we will add some code the game loop.
while run: redrawWindow() bgX -= 1.4 bgX2 -= 1.4 if bgX < bg.get_width() * -1: bgX = bg.get_width() if bgX2 < bg.get_width() * -1: bgX2 = bg.get_width() for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() quit() if event.type == USEREVENT+1: # Checks if timer goes off speed += 1 # Increases speed clock.tick(speed)
Now our background increases in speed!
Drawing our Character
Since we already have our player class setup this is not very difficult. We just need to create an instance of our player and then call its draw method from the redrawWindow function.
runner = player(200, 313, 64, 64) # This should go above our game loop
Now we need to draw this player.
def redrawWindow(): win.blit(bg, (bgX, 0)) win.blit(bg, (bgX2, 0)) runner.draw(win) # NEW pygame.display.update()
Moving Our Character
To move our character we need to check for some specific key press events. We will do this inside the game loop.
# Should go inside the game loop keys = pygame.key.get_pressed() if keys[pygame.K_SPACE] or keys[pygame.K_UP]: # If user hits space or up arrow key if not(runner.jumping): # If we are not already jumping runner.jumping = True if keys[pygame.K_DOWN]: # If user hits down arrow key if not(runner.sliding): # If we are not already sliding runner.sliding = True # Because we have a starter file this is all we have to do to move our character. # The physics and math behind the movement has been coded for you.
And now our character can slide and jump!