Reputation: 1037
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
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
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
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