GhostFrag1
GhostFrag1

Reputation: 1037

Pygame: Game Over Screen

Hello I am making a game in pygame and I am wondering how and what the best way is to add a game over screen. Here is the code up to where the players health is smaller or equal to 0:

import pygame
import random
import pygame.mixer
import Funk
from player import *
from zombie import *
from level import *
from bullet import *
from constants import *
from time import *
import menu as dm

class Game():

    def __init__(self):
        pygame.init()
        pygame.mixer.init()

        #pygame.mixer.music.load('sounds/menugame.ogg')
        #pygame.mixer.music.play(-1)

        # A few variables
        self.gravity = .50
        self.ground = pygame.Rect(0, 640, 1280, 80)
        self.red = (255, 0, 0)
        self.darkred = (200, 0, 0)
        self.darkblue = (0, 0, 200)
        self.darkgreen = (0, 200, 0)
        self.clock = pygame.time.Clock() #to track FPS
        self.fps = 0

        # Bullets
        self.bullets = []

        # Screen
        size = (1280, 720)
        self.screen = pygame.display.set_mode(size)
        pygame.display.set_caption("Moon Survival")
        self.clock.tick(self.fps)

        # Moon / Background
        self.moon = Background()

        # Zombies
        self.zombies = []
        for i in range(10):
            self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )

        # Player
        self.player = Player(25, 320, self.gravity)

        # Font for text
        self.font = pygame.font.SysFont(None, 72)

        # Pause - center on screen
        self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
        self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)

    def run(self):

        clock = pygame.time.Clock()

        # "state machine" 
        RUNNING   = True
        PAUSED    = False 
        GAME_OVER = False

        # Game loop
        while RUNNING:

            # (all) Events

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                elif event.type == pygame.KEYDOWN:

                    if event.key == pygame.K_s:
                        self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.player.direction))

                    if event.key == pygame.K_ESCAPE:
                        RUNNING = False

                    elif event.key == pygame.K_p:
                        choose = dm.dumbmenu(self.screen, [
                        'Resume Game',

                        'Menu',

                        'Quit Game'], 200, 200,'orecrusherexpanded',100,0.75,self.darkred,self.red)

                        if choose == 0:
                            print "You choose 'Start Game'."
                            break
                        elif choose == 1:
                            execfile('run_game.py')
                            print "You choose 'Controls'."
                        if choose == 2:
                            print "You choose 'Quit Game'."
                            pygame.quit()
                            sys.exit()

                # Player/Zomies events  

                if not PAUSED and not GAME_OVER:
                    self.player.handle_events(event)

            # (all) Movements / Updates

            if not PAUSED and not GAME_OVER:
                self.player_move()
                self.player.update()

                for z in self.zombies:
                    self.zombie_move(z)
                    z.update(self.screen.get_rect())

                for b in self.bullets:
                    b.update()
                    for tile in self.moon.get_surrounding_blocks(b):
                        if tile is not None:
                            if pygame.sprite.collide_rect(b, tile):
                                # Destroy block
                                x = tile.rect.x / tile.rect.width
                                y = tile.rect.y / tile.rect.height
                                self.moon.levelStructure[x][y] = None
                                try:
                                    self.bullets.remove(b)
                                except:
                                    continue

            # (all) Display updating

            self.moon.render(self.screen)

            for z in self.zombies:
                z.render(self.screen)

            for b in self.bullets:
                b.render(self.screen)

            self.player.render(self.screen)

            if PAUSED:
                self.screen.blit(self.pause_text, self.pause_rect)

            Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
            Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
            Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
            Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)

            pygame.display.update()

            # FTP

            clock.tick(100)

        # --- the end ---
        pygame.quit()

    def player_move(self):
        # add gravity
        self.player.do_jump()

        # simulate gravity
        self.player.on_ground = False
        if not self.player.on_ground and not self.player.jumping:
            self.player.velY = 4

        # Health
        for zombie in self.zombies:
            if pygame.sprite.collide_rect(self.player, zombie):
                self.player.health -= 5
                if self.player.health <= 0:


        # move player and check for collision at the same time
        self.player.rect.x += self.player.velX
        self.check_collision(self.player, self.player.velX, 0)
        self.player.rect.y += self.player.velY
        self.check_collision(self.player, 0, self.player.velY)

    def zombie_move(self, zombie_sprite):
        # add gravity
        zombie_sprite.do_jump()

        # simualte gravity
        zombie_sprite.on_ground = False
        if not zombie_sprite.on_ground and not zombie_sprite.jumping:
            zombie_sprite.velY = 4

        # Zombie damage
        for zombie in self.zombies:
            for b in self.bullets:
                if pygame.sprite.collide_rect(b, zombie):
                    #The same bullet cannot be used to kill
                    #multiple zombies and as the bullet was 
                    #no longer in Bullet.List error was raised
                    zombie.health -= 10                
                    self.bullets.remove(b)
                    if zombie.health <= 0:
                        self.player.score += random.randint(10, 20)
                        self.zombies.remove(zombie)
                    break

        # move zombie and check for collision
        zombie_sprite.rect.x += zombie_sprite.velX
        self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
        zombie_sprite.rect.y += zombie_sprite.velY
        self.check_collision(zombie_sprite, 0, zombie_sprite.velY)

    def check_collision(self, sprite, x_vel, y_vel):
        # for every tile in Background.levelStructure, check for collision
        for block in self.moon.get_surrounding_blocks(sprite):
            if block is not None:
                if pygame.sprite.collide_rect(sprite, block):
                    # we've collided! now we must move the collided sprite a step back
                    if x_vel < 0:
                        sprite.rect.x = block.rect.x + block.rect.w

                        if sprite is Zombie:
                            print "wohoo"

                    if type(sprite) is Zombie:
                            # the sprite is a zombie, let's make it jump
                            if not sprite.jumping:
                                sprite.jumping = True
                                sprite.on_ground = False

                    if x_vel > 0:
                        sprite.rect.x = block.rect.x - sprite.rect.w

                    if y_vel < 0:
                        sprite.rect.y = block.rect.y + block.rect.h

                    if y_vel > 0 and not sprite.on_ground:
                        sprite.on_ground = True
                        sprite.rect.y = block.rect.y - sprite.rect.h

#---------------------------------------------------------------------

Game().run()

I am not exactly sure how to do it, because I tried to use another py call game over but the time of which the player died was then reset to 0 and went back up, so is it possible for anything to happen where the player dies?

Upvotes: 0

Views: 9203

Answers (3)

Bartlomiej Lewandowski
Bartlomiej Lewandowski

Reputation: 11180

You should use states as Marcus wrote. I will elaborate on this a bit. You should have a class that will be your Game class.

This will include all the screens. A draft would look like this:

class GameEngine:
    def __init__(self):
        #initialize pygame
        #load resources
        #etc...
        states = [PlayGameState(),OptionsState(),GameOverState()]
    def run(self):
        while(True):
            states[current_state].draw()
            states[current_state].update()
            for event in pygame.event.get():
                states[current_state].input(event)

Then you can have the logic for all the states separate, and adding a new screen is just a matter of adding to the states list.

Pausing the game in this example would be really easy, it would simply see if the event_key was ESC and state was PlayGame, it would change it to PauseState.

The GameEngine could also poll the state, to see if it ended so that yu could change to the GameOverState, and after that back to MainState.

Upvotes: 2

Marcus M&#248;ller
Marcus M&#248;ller

Reputation: 618

Use states in your engine.

Some pseudo code:

while game_running:
    if STATE == STATE_MENU:
        Menu_ProcessInput()
        Menu_Update()
        Menu_Draw()
    elif STATE == STATE_INGAME:
        INGAME_ProcessInput()
        INGAME_Update()
        INGAME_Draw()
    elif STATE == STATE_GAMEOVER:
        GAMEOVER_ProcessInput()
        GAMEOVER_Update()
        GAMEOVER_Draw()

This is an easy solution that does not require messing around with multiple loops for menus etc.

Upvotes: 3

leewz
leewz

Reputation: 3346

Raise an exception, and catch it at a point where you're outside the running of the game but with the data you need to handle a game over.

try:
    stuff()
except GameOver:
    game_over_screen()

Upvotes: -3

Related Questions