How do I fix my pause function in pygame?

Viewed 54

I'm just recently finished watching a tutorial / introduction to pygame and I'm trying to add some changes to it, one of them being a pause function which I've gotten to work apart from some problems e.g when I jump it sets the score to zero and while I'm in the pause screen it still increases the score, I've tried fixing the two problems and looking other things similar but can't seem to fix it.

here's the code:

import pygame
from sys import exit
from random import randint, choice


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        player_walk_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/player_walk_1.png').convert_alpha()
        player_walk_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/player_walk_2.png').convert_alpha()
        self.player_walk = [player_walk_1, player_walk_2]
        self.player_index = 0
        self.player_jump = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/jump.png').convert_alpha()

        self.image = self.player_walk[self.player_index]
        self.rect = self.image.get_rect(midbottom=(80, 300))
        self.gravity = 0

        self.jump_sound = pygame.mixer.Sound('C:/Users/user/Documents/Dragon_Runner/audio/jump.mp3')
        self.jump_sound.set_volume(0.5)

    def player_input(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
            self.gravity = -22
            self.jump_sound.play()

    def apply_gravity(self):
        self.gravity += 1
        self.rect.y += self.gravity
        if self.rect.bottom >= 300:
            self.rect.bottom = 300

    def animation(self):
        if self.rect.bottom < 300:
            self.image = self.player_jump
        else:
            self.player_index += 0.060
            if self.player_index >= len(self.player_walk): self.player_index = 0
            self.image = self.player_walk[int(self.player_index)]

    def update(self):
        self.player_input()
        self.apply_gravity()
        self.animation()


class Obstacle(pygame.sprite.Sprite):
    def __init__(self, type):
        super().__init__()

        if type == 'snail':
            snail_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/snail/snail1.png').convert_alpha()
            snail_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/snail/snail2.png').convert_alpha()
            self.frames = [snail_1, snail_2]
            y_pos = 300

        else:
            dragon_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon1.png').convert_alpha()
            dragon_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon2.png').convert_alpha()
            dragon_3 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon3.png').convert_alpha()
            self.frames = [dragon_1, dragon_2, dragon_3]
            y_pos = 190

        self.animation_index = 0
        self.image = self.frames[self.animation_index]
        self.rect = self.image.get_rect(midbottom=(randint(900, 1100), y_pos))

    def animation(self):
        self.animation_index += 0.1
        if self.animation_index >= len(self.frames):
            self.animation_index = 0
        self.image = self.frames[int(self.animation_index)]

    def update(self):
        self.animation()
        self.rect.x -= 7
        self.destroy()

    def destroy(self):
        if self.rect.x <= -100:
            self.kill()


def display_score():
    current_time = int(pygame.time.get_ticks() / 1000) - start_time
    score_surf = font1.render(f'Score: {current_time}', False, 'black')
    score_rect = score_surf.get_rect(center=(400, 50))
    screen.blit(score_surf, score_rect)
    return current_time


def collision_sprite():
    if pygame.sprite.spritecollide(player.sprite, obstacle_group, False):
        obstacle_group.empty()
        return False
    else:
        return True


pygame.init()
screen = pygame.display.set_mode((800, 400))
pygame.display.set_caption('Dragon Runner')
clock = pygame.time.Clock()
font1 = pygame.font.Font('C:/Users/user/Documents/Dragon_Runner/font/Pixeltype.ttf', 50)
game_active = False
paused = False
start_time = 0
score = 0
bg_music = pygame.mixer.Sound('C:/Users/user/Documents/Dragon_Runner/audio/music.wav')
bg_music.set_volume(0.2)
bg_music.play(loops=-1)

player = pygame.sprite.GroupSingle()
player.add(Player())

obstacle_group = pygame.sprite.Group()

sky_surface = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Sky.png').convert()
ground_surface = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/ground.png').convert()

player_stand = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/player/player_stand.png').convert_alpha()
player_stand = pygame.transform.rotozoom(player_stand, 0, 2)
player_stand_rect = player_stand.get_rect(center=(400, 200))

game_name = font1.render('Dragon Runner', False, (11, 196, 169))
game_name_rect = game_name.get_rect(center=(400, 80))

game_message = font1.render('Press space to run', False, (11, 196, 169))
game_message_rect = game_message.get_rect(center=(400, 330))

obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, 1500)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()

        else:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                game_active = True
                start_time = int(pygame.time.get_ticks() / 1000)

        if game_active and not paused:
            if event.type == obstacle_timer:
                obstacle_group.add(Obstacle(choice(['fly', 'snail', 'snail', 'snail'])))

            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                paused = True

        if paused:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
                paused = False

    if game_active and not paused:
        screen.blit(sky_surface, (0, 0))
        screen.blit(ground_surface, (0, 300))
        score = display_score()

        player.draw(screen)
        player.update()

        obstacle_group.draw(screen)
        obstacle_group.update()

        game_active = collision_sprite()

    if not game_active:
        screen.fill((94, 129, 162))
        screen.blit(player_stand, player_stand_rect)

        score_message = font1.render(f'Your score: {score}', False, (11, 196, 169))
        score_message_rect = score_message.get_rect(center = (400, 330))
        screen.blit(game_name, game_name_rect)

        if score == 0:
            screen.blit(game_message, game_message_rect)
        else:
            screen.blit(score_message, score_message_rect)

    if paused:
        screen.fill((94, 129, 162))
        screen.blit(player_stand, player_stand_rect)

        pause_message = font1.render('GAME PAUSED', False, (11, 196, 169))
        pause_message_rect = pause_message.get_rect(center = (400, 80))

        unpause_message = font1.render("Press 'c' to continue", False, (11, 196, 169))
        unpause_message_rect = unpause_message.get_rect(center = (400, 330))

        screen.blit(pause_message, pause_message_rect)
        screen.blit(unpause_message, unpause_message_rect)

    pygame.display.update()
    clock.tick(60)
1 Answers

You need to minus paused time from the score, which you can create a variable to store the accumulated paused time, as follows:

Define a new variable paused_total_time:

start_time = 0
paused_total_time = 0
score = 0

When game paused, you start the pause timer:

            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                paused = True
                pause_start_time = int(pygame.time.get_ticks() / 1000)

When game continue, you add paused time to paused_total_time:

        if paused:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
                paused = False
                paused_total_time = paused_total_time + (int(pygame.time.get_ticks() / 1000) - pause_start_time)

Finally in display_score(), you can minus current_time by paused time.

def display_score():
    current_time = int(pygame.time.get_ticks() / 1000) - start_time - paused_total_time
    score_surf = font1.render(f'Score: {current_time}', False, 'black')
    score_rect = score_surf.get_rect(center=(400, 50))
    screen.blit(score_surf, score_rect)
    return current_time

Edit: There is a bug that the score reduces when character jumps, it is because start_time is reset when jump is triggered, you can add a statement to check if the game is started before resetting start_time and other variables for game start

            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                # check whether game is active before start game
                if game_active == False:
                    game_active = True
                    start_time = int(pygame.time.get_ticks() / 1000)
                    paused_total_time = 0
                    score = 0
Related