Scoring & End Screen
Subscribe to Tech with Tim
Pausing the Game
When the user falls or collides with an obstacle we are going to reset the game and pause until the user gives us some input that they’d like to play again.
The first step to pausing the game is to setup a few variables that we will need later on.
fallSpeed = 0 pause = 0
And inside our main loop we are going to add a few lines of code. These lines will allow us to show the falling animation for a few seconds before moving to and displaying the end screen.
while run: ... if pause > 0: # If we have fallen we will increment pause pause += 1 if pause > fallSpeed * 2: # once the pause variable hits a certain number we will call the endScreen endScreen() # We will create this function soon for obstacle in obstacles: if obstacle.collide(runner.hitbox): runner.falling = True if pause == 0: # This will check if we have fallen already or not fallSpeed = speed pause = 1 ...
Creating an End Screen
Once our user losses the game we want to display an end screen telling them their score. We are going to set up a new function called endScreen() to do this. Inside of this function we will add another game loop. This game loop will check if the user hits the mouse button, if they do it will bring them to a new game.
def endScreen(): global pause, score, speed, obstacles # We need to reset our variables pause = 0 speed = 30 obstacles = [] # another game loop run = True while run: pygame.time.delay(100) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() if event.type == pygame.MOUSEBUTTONDOWN: # if the user hits the mouse button run = False runner.falling = False runner.sliding = False runner.jumpin = False # This will draw text displaying the score to the screen. win.blit(bg, (0,0)) largeFont = pygame.font.SysFont('comicsans', 80) # creates a font object lastScore = largeFont.render('Best Score: ' + str(updateFile()),1,(255,255,255)) # We will create the function updateFile later currentScore = largeFont.render('Score: '+ str(score),1,(255,255,255)) win.blit(lastScore, (W/2 - lastScore.get_width()/2,150)) win.blit(currentScore, (W/2 - currentScore.get_width()/2, 240)) pygame.display.update() score = 0
Scoring
Some of you may have noticed that we reset a variable called score in the last function. This variable still needs to be created and incremented appropriately. We will increment the score by one each time the speed increases by five. To do this we add the following line to our game loop. ``´python score = speed//5 - 6
Goes inside the game loop
Now we are going to draw the score in the top right corner of the screen. We will add some code to the redrawWindow function to accomplish this. ```python def redrawWindow(): largeFont = pygame.font.SysFont('comicsans', 30) # Font object win.blit(bg, (bgX, 0)) win.blit(bg, (bgX2,0)) text = largeFont.render('Score: ' + str(score), 1, (255,255,255)) # create our text runner.draw(win) for obstacle in obstacles: obstacle.draw(win) win.blit(text, (700, 10)) # draw the text to the screen pygame.display.update()
Saving Score
Now for the last steps! We are going to be saving our highest score into a text file so that each time we run the game we know what we should try and beat.
IMPORTANT Please create a text file called “scores.txt” that is in the same directory as your python file! You must also ensure you type the number “0” on the first line of that file. MAKE SURE TO CLICK SAVE. To do this we are going to create a function called updateFile() which will not only update our file but return our highest score.
def updateFile(): f = open('scores.txt','r') # opens the file in read mode file = f.readlines() # reads all the lines in as a list last = int(file[0]) # gets the first line of the file if last < int(score): # sees if the current score is greater than the previous best f.close() # closes/saves the file file = open('scores.txt', 'w') # reopens it in write mode file.write(str(score)) # writes the best score file.close() # closes/saves the file return score return last
Full Code
import pygame from pygame.locals import * import os import sys import math import random pygame.init() W, H = 800, 437 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'))] fall = pygame.image.load(os.path.join('images','0.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.falling = False self.slideCount = 0 self.jumpCount = 0 self.runCount = 0 self.slideUp = False def draw(self, win): if self.falling: win.blit(self.fall, (self.x, self.y + 30)) elif self.jumping: self.y -= self.jumpList[self.jumpCount] * 1.3 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 self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) elif self.sliding or self.slideUp: if self.slideCount < 20: self.y += 1 self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) elif self.slideCount == 80: self.y -= 19 self.sliding = False self.slideUp = True elif self.slideCount > 20 and self.slideCount < 80: self.hitbox = (self.x,self.y+3,self.width-8,self.height-35) if self.slideCount >= 110: self.slideCount = 0 self.runCount = 0 self.slideUp = False self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) 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 self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-13) #pygame.draw.rect(win, (255,0,0),self.hitbox, 2) class saw(object): rotate = [pygame.image.load(os.path.join('images', 'SAW0.PNG')),pygame.image.load(os.path.join('images', 'SAW1.PNG')),pygame.image.load(os.path.join('images', 'SAW2.PNG')),pygame.image.load(os.path.join('images', 'SAW3.PNG'))] def __init__(self,x,y,width,height): self.x = x self.y = y self.width = width self.height = height self.rotateCount = 0 self.vel = 1.4 def draw(self,win): self.hitbox = (self.x + 10, self.y + 5, self.width - 20, self.height - 5) #pygame.draw.rect(win, (255,0,0), self.hitbox, 2) if self.rotateCount >= 8: self.rotateCount = 0 win.blit(pygame.transform.scale(self.rotate[self.rotateCount//2], (64,64)), (self.x,self.y)) self.rotateCount += 1 def collide(self, rect): if rect[0] + rect[2] > self.hitbox[0] and rect[0] < self.hitbox[0] + self.hitbox[2]: if rect[1] + rect[3] > self.hitbox[1]: return True return False class spike(saw): img = pygame.image.load(os.path.join('images', 'spike.png')) def draw(self,win): self.hitbox = (self.x + 10, self.y, 28,315) #pygame.draw.rect(win, (255,0,0), self.hitbox, 2) win.blit(self.img, (self.x,self.y)) def collide(self, rect): if rect[0] + rect[2] > self.hitbox[0] and rect[0] < self.hitbox[0] + self.hitbox[2]: if rect[1] < self.hitbox[3]: return True return False def updateFile(): f = open('scores.txt','r') file = f.readlines() last = int(file[0]) if last < int(score): f.close() file = open('scores.txt', 'w') file.write(str(score)) file.close() return score return last def endScreen(): global pause, score, speed, obstacles pause = 0 speed = 30 obstacles = [] run = True while run: pygame.time.delay(100) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() if event.type == pygame.MOUSEBUTTONDOWN: run = False runner.falling = False runner.sliding = False runner.jumpin = False win.blit(bg, (0,0)) largeFont = pygame.font.SysFont('comicsans', 80) lastScore = largeFont.render('Best Score: ' + str(updateFile()),1,(255,255,255)) currentScore = largeFont.render('Score: '+ str(score),1,(255,255,255)) win.blit(lastScore, (W/2 - lastScore.get_width()/2,150)) win.blit(currentScore, (W/2 - currentScore.get_width()/2, 240)) pygame.display.update() score = 0 def redrawWindow(): largeFont = pygame.font.SysFont('comicsans', 30) win.blit(bg, (bgX, 0)) win.blit(bg, (bgX2,0)) text = largeFont.render('Score: ' + str(score), 1, (255,255,255)) runner.draw(win) for obstacle in obstacles: obstacle.draw(win) win.blit(text, (700, 10)) pygame.display.update() pygame.time.set_timer(USEREVENT+1, 500) pygame.time.set_timer(USEREVENT+2, 3000) speed = 30 score = 0 run = True runner = player(200, 313, 64, 64) obstacles = [] pause = 0 fallSpeed = 0 while run: if pause > 0: pause += 1 if pause > fallSpeed * 2: endScreen() score = speed//10 - 3 for obstacle in obstacles: if obstacle.collide(runner.hitbox): runner.falling = True if pause == 0: pause = 1 fallSpeed = speed if obstacle.x < -64: obstacles.pop(obstacles.index(obstacle)) else: obstacle.x -= 1.4 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: pygame.quit() run = False if event.type == USEREVENT+1: speed += 1 if event.type == USEREVENT+2: r = random.randrange(0,2) if r == 0: obstacles.append(saw(810, 310, 64, 64)) elif r == 1: obstacles.append(spike(810, 0, 48, 310)) if runner.falling == False: keys = pygame.key.get_pressed() if keys[pygame.K_SPACE] or keys[pygame.K_UP]: if not(runner.jumping): runner.jumping = True if keys[pygame.K_DOWN]: if not(runner.sliding): runner.sliding = True clock.tick(speed) redrawWindow()
If this tutorial helped you please consider supporting the website by heading to the Support/Donate Page. Your donations are what keep the site running and any bit helps!