How do I make my pygame levels more efficient? [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I've been redoing a lot of my game in order to make it more efficient, before I had functions for each level and it had about 300+ repeated lines of code for each level, I've taken it out however I'm trying to get level one to function properly now. Below is my code, any help as to how to get my code to play level1 when I run the game as right now it only displays the background screen and none of the enemies, platforms or the character.
import pygame
import time
import random
from pygame.math import Vector2 as vec
pygame.init()
# Set the screen size
screen = pygame.display.set_mode([700, 500])
# Define the colours for text
black = (0,0,0)
white = (255,255,255)
green = (0,51,0)
light_green = (51,102,0)
PLAYER_FRICTION = 0.0
PLAYER_ACC = 3
HEIGHT = 500
WIDTH = 700
FPS = 60
# Set Display
pygame.display.set_caption('Jungle Blast')
clock = pygame.time.Clock()
class Character(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("TheoHills.png")
self.rect = self.image.get_rect(topleft=(50, 300))
self.x = 50
self.y = 300
self.pos = vec(50, 300)
self.vel = vec(0,0)
self.acc = vec(0,0)
def characterJump(self,platforms):
self.rect.y += 1
hits = pygame.sprite.spritecollide(self, platforms, False)
self.rect.y -= 1
if hits:
self.vel.y = -18
def update(self):
self.acc = vec(0, 0.5)
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pygame.K_d]:
self.acc.x = PLAYER_ACC
# apply friction
self.vel.x *= PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel
self.rect.midbottom = self.pos
if self.pos.y == 500:
background_image = pygame.image.load("Lose Screen.png")
if self.pos.x > 699:
level2()
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("Bullet.png").convert()
self.image.set_colorkey(black)
self.rect = self.image.get_rect()
def update(self):
self.rect.x += 10
class levelInd(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("1 out of 5.png")
self.rect = self.image.get_rect(topleft=(20, 20))
self.pos = vec(20, 20)
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((100, 88))
self.image.fill(black)
self.image = pygame.image.load("Platform1.png")
self.rect = self.image.get_rect(topleft=(x, y))
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((100, 50))
self.image = pygame.image.load("RobberStanding.png")
self.rect = self.image.get_rect(topleft=(x,y))
def draw_text(surface, text, size, x, y,font_name):
font = pygame.font.SysFont(str(font_name), size)
text_surface = font.render(text, True, black)
text_rect = text_surface.get_rect()
text_rect.topleft = (x, y)
surface.blit(text_surface, text_rect)
class levels():
levelind = levelInd()
character = Character()
all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
background_image = pygame.image.load("JungleBackground.png")
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
character.characterJump(platforms)
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
bullet = Bullet()
bullet.rect.x = character.rect.x + 10
bullet.rect.y = character.rect.y + 50
bullet_list.add(bullet)
all_sprites.add(bullet)
for bullet in bullet_list:
# See if the enemy is hit
enemyHit = pygame.sprite.spritecollide(bullet,enemies,True)
if enemyHit:
enemies.remove(Enemy)
score1 += 10
if bullet.rect.x > 700:
bullet_list.remove(bullet)
if character.rect.y >= 500:
background_image = pygame.image.load("Lose Screen.png")
pygame.display.update()
all_sprites.empty()
death = pygame.sprite.spritecollide(character, enemies, True)
if len(death) > 0:
background_image = pygame.image.load("Lose Screen.png")
all_sprites.empty()
all_sprites.update()
hits = pygame.sprite.spritecollide(character, platforms, False)
for platform in hits:
if character.vel.y > 0:
character.rect.bottom = character.rect.bottom
character.vel.y = 0
elif character.vel.y < 0:
character.rect.top = character.rect.top
character.vel.y = 3
character.pos.y = character.rect.bottom
screen.blit(background_image,[0,0])
all_sprites.draw(screen)
pygame.display.flip()
def level1():
done = False
clock = pygame.time.Clock()
font_name = pygame.font.match_font("Arial")
black = ( 0, 0, 0)
white = ( 255, 255, 255)
x = 300
y = 88
e1 = Enemy(250, 125)
enemies.add(e1)
all_sprites.add(character)
all_sprites.add(levelind)
all_sprites.add(e1)
p1 = Platform(-80, 400, WIDTH - 400, HEIGHT - 10)
p2 = Platform(175, 210, WIDTH - 400, HEIGHT - 10)
p3 = Platform(500, 400, WIDTH - 400, HEIGHT - 10)
all_sprites.add(p1, p2, p3)
platforms.add(p1, p2, p3)
score1 = 0
level1()
This is the image that shows up whenever the game is run.

I Think you should take a look at your "levels" Class.
Give it a proper init method, for example.
I got the game running by modifing the class as follows:
class levels():
def __init__(self):
self.levelind = levelInd()
self.character = Character()
self.all_sprites = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
self.enemies = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
self.background_image = pygame.image.load("1LPqX.png")
self.score1 = 0
self.running = True
def run(self):
while self.running:
self.level1()
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
pygame.display.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
self.haracter.characterJump(self.platforms)
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
bullet = Bullet()
bullet.rect.x = self.character.rect.x + 10
bullet.rect.y = self.character.rect.y + 50
self.bullet_list.add(bullet)
self.all_sprites.add(bullet)
for bullet in self.bullet_list:
# See if the enemy is hit
enemyHit = pygame.sprite.spritecollide(bullet, self.enemies, True)
if enemyHit:
self.enemies.remove(Enemy)
self.score1 += 10
if bullet.rect.x > 700:
self.bullet_list.remove(bullet)
if self.character.rect.y >= 500:
self.background_image = pygame.image.load("1LPqX.png")
pygame.display.update()
self.all_sprites.empty()
death = pygame.sprite.spritecollide(self.character, self.enemies, True)
if len(death) > 0:
self.background_image = pygame.image.load("1LPqX.png")
self.all_sprites.empty()
self.all_sprites.update()
hits = pygame.sprite.spritecollide(self.character, self.platforms, False)
for platform in hits:
if self.character.vel.y > 0:
self.character.rect.bottom = self.character.rect.bottom
self.character.vel.y = 0
elif self.character.vel.y < 0:
self.character.rect.top = self.character.rect.top
self.character.vel.y = 3
self.character.pos.y = self.character.rect.bottom
screen.blit(self.background_image, [0, 0])
self.all_sprites.draw(screen)
pygame.display.flip()
def level1(self):
done = False
clock = pygame.time.Clock()
font_name = pygame.font.match_font("Arial")
black = (0, 0, 0)
white = (255, 255, 255)
x = 300
y = 88
e1 = Enemy(250, 125)
self.enemies.add(e1)
self.all_sprites.add(self.character)
self.all_sprites.add(self.levelind)
self.all_sprites.add(e1)
p1 = Platform(-80, 400, WIDTH - 400, HEIGHT - 10)
p2 = Platform(175, 210, WIDTH - 400, HEIGHT - 10)
p3 = Platform(500, 400, WIDTH - 400, HEIGHT - 10)
self.all_sprites.add(p1, p2, p3)
self.platforms.add(p1, p2, p3)
self.score1 = 0
# level1()
(seems like the indentation was not copied properly, everything below "class levels()" has to be indented 4 more spaces)
and adding
if __name__ == '__main__':
game = levels()
game.run()
at the bottom of the file.

Related

Pygame 2D Platformer Full Platform Collision [duplicate]

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
I have been trying to create a 2D platformer in pygame, and I have encountered a problem with the collision of the player sprite with the platform. I hope to implement full collision for the platforms, so that the player sprite will stop when it hits the platform from any direction. Currently, the sprite stops when it hits the top of the platforms, but if it collides with the bottom or sides of a platform it instantly jumps to the top of the platform. I have tried various things to solve this, but to no avail. Any help would be appreciated.
I have seperated my code into 3 files.
This is my main file:
import pygame
from settings import *
from sprites import *
#Game Class
class Game:
def __init__(self):
pygame.init()
pygame.mixer.init()
self.gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
self.clock = pygame.time.Clock()
self.gameRunning = True
#Stars the game
def new(self):
self.allSprites = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
self.player = Player(self)
self.allSprites.add(self.player)
floor = Platform(0, 680, displayWidth, 40)
plat2 = Platform( 500, 400, 100, 40)
self.allSprites.add(floor, plat2)
self.platforms.add(floor, plat2)
self.run()
#Game Loop
def run(self):
self.gameRunning = True
while self.gameRunning == True:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
#Updates the screen
def update(self):
self.allSprites.update()
hits = pygame.sprite.spritecollide(self.player, self.platforms, False)
if hits:
self.player.pos.y = hits[0].rect.top
self.player.spd.y = 0
self.player.rect.midbottom = self.player.pos
if self.player.rect.left >= displayHeight - 200:
self.player.pos.x -= abs(self.player.spd.x)
for plat in self.platforms:
plat.rect.x -= abs(self.player.spd.x)
if self.player.rect.right <= displayHeight / 4:
self.player.pos.x += abs(self.player.spd.x)
for plat in self.platforms:
plat.rect.x += abs(self.player.spd.x)
#Events loop
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.player.jump()
#Draws things to the screen
def draw(self):
self.gameDisplay.fill(LIGHT_BLUE)
self.allSprites.draw(self.gameDisplay)
pygame.display.update()
def runGame():
game = Game()
game.new()
runGame()
Sprites file:
import pygame
from settings import *
vec = pygame.math.Vector2
#Player Class
class Player(pygame.sprite.Sprite):
def __init__(self, game):
pygame.sprite.Sprite.__init__(self)
self.game = game
self.image = pygame.Surface([40, 40])
self.image.fill(DARK_BLUE)
self.rect = self.image.get_rect()
self.rect.center = (displayWidth / 2, displayHeight / 2)
self.pos = vec(displayWidth / 2, displayHeight / 2)
self.spd = vec(0,0)
self.acc = vec(0,0)
def update(self):
self.acc = vec(0, playerGrav)
keysPressed = pygame.key.get_pressed()
if keysPressed[pygame.K_LEFT]:
self.acc.x = - playerAcc
if keysPressed[pygame.K_RIGHT]:
self.acc.x = playerAcc
self.acc.x += self.spd.x * playerFric
self.spd += self.acc
self.pos += self.spd + 0.5 * self.acc
self.rect.midbottom = self.pos
def jump(self):
self.rect.y +=1
hits = pygame.sprite.spritecollide(self, self.game.platforms, False)
self.rect.y -= 1
if hits:
self.spd.y = -20
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((w, h))
self.image.fill((GREEN))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
Settings File:
import pygame
pygame.font.init()
#Setup
FPS = 60
displayWidth = 1280
displayHeight = 720
pygame.display.set_caption("2D Platformer")
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
clock = pygame.time.Clock()
#Player
playerAcc = 0.5
playerFric = -0.1
playerGrav = 0.5
#Colour Pallette
BLACK = (0, 0, 0 )
WHITE = (255, 255, 255)
RED = (200, 0, 0 )
GREEN = (0, 200, 0 )
BLUE = (0, 0, 200)
LIGHT_BLUE = (0, 191, 255)
DARK_BLUE = (0, 50, 150)
#Score
score = 0
This is the code that is responsible for collision:
hits = pygame.sprite.spritecollide(self.player, self.platforms, False)
if hits:
self.player.pos.y = hits[0].rect.top
self.player.spd.y = 0
self.player.rect.midbottom = self.player.pos
I understand that the reason why the sprite jumps to the top of the platform is due to these lines of code:
if hits:
self.player.pos.y = hits[0].rect.top
However, I don't know how to implement full collision.

Pygame Start scren

im trying to create a game for class. and i want to add a start screen to it but it doesnt seem to work.
the whole code:
# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.
import pygame
import random
from os import path
img_dir = path.join(path.dirname(__file__), 'Sprites')
snd_dir = path.join(path.dirname(__file__), 'sound')
WIDTH = 480
HEIGHT = 600
FPS = 30
car_img = pygame.image.load(path.join(img_dir, "copgreen20.bmp"))
mob_img = pygame.image.load(path.join(img_dir, "mob_zom.bmp"))
priv_img = pygame.image.load(path.join(img_dir, "copgreen20.bmp"))
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# initialize pygame and create window
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode([800, 600])
test = "space.ogg"
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=4096)
pygame.mixer.music.load(path.join(snd_dir, 'atari.ogg'))
pygame.mixer.music.play(-1)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()
font_name = pygame.font.match_font('Arial')
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, BLUE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((80, 50))
self.images = []
self.image = car_img
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 50
self.speedx = 0
self.image = pygame.transform.scale(car_img, (50, 80))
self.image.set_colorkey(GREEN)
def update(self):
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -8
if keystate[pygame.K_RIGHT]:
self.speedx = 8
if keystate[pygame.K_UP]:
self.speedy = -8
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 40))
self.image = mob_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 9)
self.speedx = random.randrange(-3, 3)
self.image.set_colorkey(WHITE)
self.image.set_colorkey(YELLOW)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange( -100, -40)
self.speedy = random.randrange(1, 8)
class Priv(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 40))
self.image = priv_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 9)
self.speedx = random.randrange(-3, 3)
self.image.set_colorkey(WHITE)
self.image.set_colorkey(YELLOW)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange( -100, -40)
self.speedy = random.randrange(1, 8)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((10, 20))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = 200
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
background = pygame.image.load(path.join(img_dir, "back_road.bmp")).convert()
background_rect = background.get_rect()
bullets = pygame.sprite.Group()
allspriteslist = pygame.sprite.Group()
#showstartscreen()
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
def game_intro():
display = pygame.display.set_mode((800,600))
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
display.fill(BLACK)
largeText = pygame.font.match_font('Arial',10)
textSurf, textRect = text_objects("this is a game", largeText)
textRect.centre = ((display_width/2), (display_height/2))
display.blit(textSurf, textRect)
pygame.display.update()
clock.tick(15)
pygame.display.update()
score = 000
# Game loop
game_intro()
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
#for i in range(5):
#m = Mob()
#all_sprites.add(m)
#mobs.add(m)
elif event.type == pygame.KEYDOWN:
if event.type == pygame.K_9:
running = False
if event.key == pygame.K_SPACE:
player.shoot()
if event.key == pygame.K_EQUALS:
for i in range(100):
m = Mob()
all_sprites.add(m)
mobs.add(m)
#if event.key == pygame.K_SPACE:
if clock == 0:
for i in range(100):
m = Mob()
all_sprites.add(m)
mobs.add(m)
if event.key == pygame.K_1:
for i in range(2):
p = Priv()
all_sprites.add(p)
Priv.add(p)
if event.key == pygame.K_2:
for i in range(10):
m = Mob()
all_sprites.add(m)
mobs.add(m)
# Update
all_sprites.update()
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
score += 1
m = Mob()
all_sprites.add(m)
mobs.add(m)
p = Priv()
all_sprites.add(m)
Priv.add(p)
hits = pygame.sprite.spritecollide(player, mobs, False)
#if hits:
#running = False
try:
for i in bullets:
i.rect.bottom += -5
except:
None
# Draw / render
screen.fill(BLACK)
screen.blit(background, background_rect)
draw_text(screen, str(score), 50, WIDTH / 10, 10)
#draw_text(screen, str(scores), 50, WIDTH / 10, 10)
all_sprites.draw(screen)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.QUIT
the code where the problem is:
def game_intro():
display = pygame.display.set_mode((800,600))
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
display.fill(BLACK)
largeText = pygame.font.match_font('Arial',10)
textSurf, textRect = text_objects("this is a game", largeText)
textRect.centre = ((display_width/2), (display_height/2))
display.blit(textSurf, textRect)
pygame.display.update()
clock.tick(15)
pygame.display.update()
score = 000
# Game loop
game_intro()
The error:
File "/Users/harrisonj11/NetBeansProjects/game_test_jakob/src/game_test_jakob.py", line 167, in
game_intro()
File
"/Users/harrisonj11/NetBeansProjects/game_test_jakob/src/game_test_jakob.py", line 159, in game_intro
textSurf, textRect = text_objects("this is a game", largeText)
NameError: name 'text_objects' is not defined
You haven't defined a text_objects function. It looks like you meant the draw_text function that you declared above, but it doesn't quite do what you want either.
I'm guessing that what you meant to do was something like:
Create a text surface and a rectangle that represents the bounds of that surface
Move the rectangle to the middle of the screen (the width / 2 code)
Draw the text surface using that rectangle
You can modify the draw_text function you already have to return that stuff, since it seems to already calculate a bounding rectangle for the text and make a surface for that text as well.

"pygame.error: video system not initialized" after calling "pygame.event.get()"

When I try to load my game everything works except for the fact that it crashes and python doesn't respond. I can't see what I have missed.
Here is the whole code:
# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.
import pygame
import random
from os import path
img_dir = path.join(path.dirname(__file__), 'Sprites')
snd_dir = path.join(path.dirname(__file__), 'sound')
WIDTH = 480
HEIGHT = 600
FPS = 60
car_img = pygame.image.load(path.join(img_dir, "copgreen20.bmp"))
mob_img = pygame.image.load(path.join(img_dir, "mob_zom.bmp"))
priv_img = pygame.image.load(path.join(img_dir, "copgreen20.bmp"))
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# initialize pygame and create window
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode([800, 600])
test = "space.ogg"
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=4096)
pygame.mixer.music.load(path.join(snd_dir, 'atari.ogg'))
pygame.mixer.music.play(-1)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()
clock.tick(FPS)
font_name = pygame.font.match_font('Arial')
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, BLUE)
text_rect = text_surface.get_rect()
text_rect.midtop = (y, x)
surf.blit(text_surface, text_rect)
font_name = pygame.font.match_font('Arial')
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, YELLOW)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((80, 50))
self.images = []
self.image = car_img
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 50
self.speedx = 0
self.image = pygame.transform.scale(car_img, (50, 80))
self.image.set_colorkey(GREEN)
def update(self):
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -8
if keystate[pygame.K_RIGHT]:
self.speedx = 8
if keystate[pygame.K_UP]:
self.speedy = -8
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 40))
self.image = mob_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 9)
self.speedx = random.randrange(-3, 3)
self.image.set_colorkey(WHITE)
self.image.set_colorkey(YELLOW)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange( -100, -40)
self.speedy = random.randrange(1, 8)
class Priv(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 40))
self.image = priv_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 9)
self.speedx = random.randrange(-3, 3)
self.image.set_colorkey(WHITE)
self.image.set_colorkey(YELLOW)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange( -100, -40)
self.speedy = random.randrange(1, 8)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((10, 20))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = 200
def show_go_screen():
screen.blit(background, background_rect)
draw_text(screen, "SHMUP!", 64, WIDTH / 2, HEIGHT / 4)
draw_text(screen, "Arrow keys move, Space to fire", 22,
WIDTH / 2, HEIGHT / 2)
draw_text(screen, "Press a key to begin", 18, WIDTH / 2, HEIGHT * 3 / 4)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.K_SPACE:
waiting = False
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
background = pygame.image.load(path.join(img_dir, "back_road_update.bmp")).convert()
background_rect = background.get_rect()
bullets = pygame.sprite.Group()
allspriteslist = pygame.sprite.Group()
#showstartscreen()
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
#def game_intro():
#display = pygame.display.set_mode((800,600))
#intro = True
#while intro:
#for event in pygame.event.get():
#if event.type == pygame.QUIT:
#pygame.quit()
#quit()
#display.fill(BLACK)
#largeText = pygame.font.match_font('Arial',10)
#textSurf, textRect = draw_text(text, size, x, y)
#textRect.centre = ((display_width/2), (display_height/2))
#display.blit(textSurf, textRect)
#pygame.display.update()
#clock.tick(15)
#pygame.display.update()
show_go_screen()
score = 000
score2 = 50
# Game loop
#game_intro()
game_over = True
running = True
while running:
if game_over:
game_over = False
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
#for i in range(5):
#m = Mob()
#all_sprites.add(m)
#mobs.add(m)
elif event.type == pygame.KEYDOWN:
if score2 == 0:
game_over = True
if event.type == pygame.K_9:
running = False
if event.key == pygame.K_SPACE:
player.shoot()
score2 -= 1
if event.key == pygame.K_EQUALS:
for i in range(100):
m = Mob()
all_sprites.add(m)
mobs.add(m)
#if event.key == pygame.K_SPACE:
if clock.tick == 10:
for i in range(100):
m = Mob()
all_sprites.add(m)
mobs.add(m)
if event.key == pygame.K_1:
for i in range(2):
p = Priv()
all_sprites.add(p)
Priv.add(p)
if event.key == pygame.K_2:
for i in range(10):
m = Mob()
all_sprites.add(m)
mobs.add(m)
# Update
all_sprites.update()
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
score += 1
m = Mob()
all_sprites.add(m)
mobs.add(m)
p = Priv()
all_sprites.add(m)
Priv.add(p)
hits = pygame.sprite.spritecollide(player, mobs, False)
#if hits:
#running = False
try:
for i in bullets:
i.rect.bottom += -5
except:
None
# Draw / render
screen.fill(BLACK)
screen.blit(background, background_rect)
draw_text(screen, str(score), 50, WIDTH / 10, 10)
draw_text(screen, str(score2), 50, HEIGHT / 13, 200)
#draw_text(screen, str(scores), 50, WIDTH / 10, 10)
all_sprites.draw(screen)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.QUIT
Here is the error that happens if I force quit the app:
Traceback (most recent call last):
File "/Users/harrisonj11/NetBeansProjects/game_test_jakob/src/game_test_jakob.py", line 187, in <module>
show_go_screen()
File "/Users/harrisonj11/NetBeansProjects/game_test_jakob/src/game_test_jakob.py", line 147, in show_go_screen
for event in pygame.event.get():
pygame.error: video system not initialized
pygame.quit doesn't quit the whole program, it just uninitializes the pygame modules. So the while loop in show_go_screen is still running and calls pygame.event.get(), but that doesn't work anymore after you've uninitialized everything and the pygame.error: video system not initialized is raised.
To quit the game call sys.exit() after pygame.quit(). Add import sys at the top of the file.
Also, to run the game I had to modify the event loop in show_go_screen and remove the first while running: loop:
def show_go_screen():
screen.blit(background, background_rect)
draw_text(screen, "SHMUP!", 64, WIDTH / 2, HEIGHT / 4)
draw_text(screen, "Arrow keys move, Space to fire", 22,
WIDTH / 2, HEIGHT / 2)
draw_text(screen, "Press a key to begin", 18, WIDTH / 2, HEIGHT * 3 / 4)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# First check if the event type is KEYDOWN.
if event.type == pygame.KEYDOWN:
# Then you need to check if the `event.key` not `event.type`
# equals `pygame.K_SPACE`.
if event.key == pygame.K_SPACE:
waiting = False

How to delete rects/sprites with python and pygame

I am working on a game and I wanted to add an ammo box that randomly spawns. so far the box spawns as expected and if you move over it, it is removed and gives you 200+ ammo. However, it is only supposed to give 50 ammo. Then later in the game when the player goes back to that spot they continue to get more ammo. If I just sit there I end up getting 1000+ ammo.
Here is my ammo class:
class Ammo(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
pass
and here is the game loop:
class Game():
def __init__(self):
pygame.init()
screen_width = 850
screen_height = 640
place_ammo = False
self.screen = pygame.display.set_mode( (screen_width,screen_height) )
pygame.mouse.set_visible(False)
#-----
self.all_sprites_list = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
self.blitwave = 1
# --- create sprites ---
self.background = Background()
self.player = Player(self.screen.get_rect(), 0, 370)
self.all_sprites_list.add(self.player)
self.ammo = Ammo(self.screen.get_rect(),random.randrange(10,screen_width),random.randint(10,screen_height - 10))
self.all_sprites_list.add(self.ammo)
self.ammo_amount = 10
self.on_screen = 1
self.score = 0
self.crosshair = Crosshair()
def bullet_create(self, start_pos, mouse_pos):
bullet = Bullet(start_pos, mouse_pos)
self.all_sprites_list.add(bullet)
self.bullet_list.add(bullet)
def bullets_update(self):
for bullet in self.bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, self.block_list, True)
screen_width = 850
screen_height = 640
for block in block_hit_list:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
self.score += 1
self.on_screen -= 1
self.ammo_chance = self.ammo_amount * 5
if self.ammo_chance > 0:
self.drop = random.randint(1, self.ammo_chance)
print(self.drop)
if self.drop > 0 and self.drop < 2:
print('ammo drop')
self.ammo = Ammo(self.screen.get_rect(),random.randrange(10,screen_width),random.randint(10,screen_height - 10))
self.all_sprites_list.add(self.ammo)
if bullet.rect.y < -10:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
# -------- Main Program Loop -----------
def run(self):
screen_width = 850
screen_height = 640
#wave
self.wave = 1
self.wave_no = 2
self.wave_running = True
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
clock = pygame.time.Clock()
self.cash = 1
self.health = 100
self.ammo_amount = 10
RUNNING = True
PAUSED = False
while RUNNING:
# --- events ---
if self.player.health <= 0:
RUNNING = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = PAUSED
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
PAUSED = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
PAUSED = not PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN and self.ammo_amount > 0:
self.bullet_create(self.player, event.pos)
self.ammo_amount -= 1
self.cash = self.score * 5
if self.on_screen == 0:
for i in range(self.wave_no):
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
self.on_screen += 1
self.wave_div = int(self.wave_no / 2)
self.wave_no += self.wave_div
self.wave += 1
#wave font
font = pygame.font.SysFont("", 34)
self.text_pause = font.render("WAVE " + str(self.wave) * self.blitwave, -1, RED)
self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text
#health font
self.text_health = font.render("|" * self.player.health, -1, RED)
#score font
self.text_score = font.render("SCORE " + str(self.score), -1, BLACK)
#cash font
self.text_cash = font.render("CASH " + str(self.cash), -1, GREEN)
#ammo font
self.text_ammo = font.render("AMMO " + str(self.ammo_amount), -1, RED)
# send event to player
self.player.event_handler(event)
if not PAUSED:
self.all_sprites_list.update()
self.bullets_update()
player_rect = pygame.Rect(self.player.rect.x, self.player.rect.y, 20, 20)
block_rect = pygame.Rect(block.rect.x, block.rect.y, 20, 20)
if player_rect.colliderect(block_rect):
self.player.health = self.player.health - 3
if player_rect.colliderect(self.ammo.rect):
self.ammo_amount += 50
self.all_sprites_list.remove(self.ammo)
self.crosshair.update()
# --- draws ---
self.background.draw(self.screen)
self.all_sprites_list.draw(self.screen)
#must be last
self.screen.blit(self.text_pause, (10, 610))
self.screen.blit(self.text_score, (700, 585))
self.screen.blit(self.text_cash, (700, 560))
self.screen.blit(self.text_ammo, (700, 610))
self.screen.blit(self.text_health, (10, 10))
self.crosshair.draw(self.screen)
pygame.display.update() # use flip() OR update()
# --- FPS ---
clock.tick(70)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
The sprite is indeed removed but self.ammo which is called to check for collision is still working even after the sprite is removed. Here's what I'd do:
if self.ammo and player_rect.colliderect(self.ammo.rect):
self.ammo_amount += 50
self.all_sprites_list.remove(self.ammo)
self.ammo = None

Two enemy movement glitches

So this is my game I've bean working on and so have things are going very well, the player can move around and shoot down the boxes which are ment to be moving but theres these small glitches, but before I go on heres the code:
import pygame, math, random, sys
from pygame import *
import random, math, cmath
pygame.init()
#variables end----------------------------------------------------------------
#imagers
grass = "grass_shit.png" #grass image
player_img = "shithead.png" #player name
ali_img = "shit_head2.png" #alien image
dead_screen = "dead_shit.png"
cross_hair = "crosshair.png"
playButton = "playbutton.png"
#screen
screen = pygame.display.set_mode((850, 640),0,32) #set screen
background = pygame.image.load(grass).convert() #load image to screen
health = 100
#mouse things
crosshair = pygame.image.load(cross_hair).convert_alpha()
#variables end----------------------------------------------------------------
pygame.mouse.set_visible(False)
black = ( 0, 0, 0)
white = ( 255, 255, 255)
red = ( 255, 0, 0)
blue = ( 0, 0, 255)
player_x, player_y = 0, 0
move_player_x, move_player_y = 0, 0
move_ali_x, move_ali_y = 0, 0
class Block(pygame.sprite.Sprite):
def __init__(self, color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
def update(self):
global move_ali_x
global move_ali_y
if block.rect.x < player_x:
move_ali_x =+ 0.05
elif block.rect.x > player_x:
move_ali_x =- 0.05
if block.rect.y < player_y:
move_ali_y =+ 0.05
elif block.rect.y > player_y:
move_ali_y =- 0.05
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(red)
self.rect = self.image.get_rect()
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x = player_x
self.rect.y = player_y
class Bullet(pygame.sprite.Sprite):
def __init__(self, mouse, player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([4, 10])
self.image.fill(black)
self.mouse_x, self.mouse_y = mouse[0], mouse[1]
self.player = player
self.rect = self.image.get_rect()
def update(self):
speed = 10
range = 50000
distance = [self.mouse_x - self.player[0], self.mouse_y - self.player[1]]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1] / norm]
bullet_vector = [direction[0] * speed, direction[1] * speed]
self.rect.x += bullet_vector[0]
self.rect.y += bullet_vector[1]
pygame.init()
screen_width = 850
screen_height = 640
screen = pygame.display.set_mode([screen_width,screen_height])
all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
for i in range(5):
block = Block(blue)
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(350)
block_list.add(block)
all_sprites_list.add(block)
player = Player()
all_sprites_list.add(player)
done = False
clock = pygame.time.Clock()
score = 0
player.rect.y = 370
# -------- Main Program Loop -----------
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet(event.pos, [player.rect.x, player.rect.y])
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
if event.type== pygame.KEYDOWN:
if event.key==K_a:
move_player_x=-4
elif event.key==K_d:
move_player_x=+4
elif event.key==K_w:
move_player_y=-4
elif event.key==K_s:
move_player_y=+4
if event.type== pygame.KEYUP:
if event.key==K_a:
move_player_x=0
elif event.key==K_d:
move_player_x=0
elif event.key==K_w:
move_player_y=0
elif event.key==K_s:
move_player_y=0
# --- Game logic
all_sprites_list.update()
player_x += move_player_x
player_y += move_player_y
block.rect.y += move_ali_y
block.rect.x += move_ali_x
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print( score )
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if player.rect.colliderect(block.rect):
health =- 35
mouse_x, mouse_y = pygame.mouse.get_pos()
mouse_x -= crosshair.get_width() / 2
mouse_y -= crosshair.get_height() / 2
screen.blit(background,(0,0))
all_sprites_list.draw(screen)
screen.blit(crosshair,(mouse_x, mouse_y))
pygame.display.flip()
pygame.display.update()
clock.tick(20)
pygame.quit()
So glitch number one:
only one of the boxers moves, I cant figure out why it only one of them is moving towards the player, all the boxers are meant to move towards the player as this is hoping to become a zombie shooter.
Glitch two:
At a random point the box that does move does stops moving in all directions but one, so lets say this happens when the box in in the center of the screen, if the player goes to the left of the box, nothing, but when the player moves to thr right of the player it moves right, but only right not up or down, and this seams to happen at soem point everytime.
Well thats it, hope you can help thanks heaps stackoverflow
Your code should looks like this:
import pygame
from pygame import *
import sys
import math
import random
import cmath
#----------------------------------------------------------------------
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
#imagers
IMAGE_GRASS = "grass_shit.png" #grass image
IMAGE_PLAYER = "shithead.png" #player name
IMAGE_ALI = "shit_head2.png" #alien image
IMAGE_DEAD_SCREEN = "dead_shit.png"
IMAGE_CROSSHAIR = "crosshair.png"
IMAGE_PLAYBUTTON = "playbutton.png"
#~ IMAGE_GRASS = "ball3.png" #grass image
#~ IMAGE_PLAYER = "ball2.png" #player name
#~ IMAGE_ALI = "ball3.png" #alien image
#~ IMAGE_DEAD_SCREEN = "ball3.png"
#~ IMAGE_CROSSHAIR = "ball1.png"
#~ IMAGE_PLAYBUTTON = "ball3.png"
#----------------------------------------------------------------------
class Block(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.player = player
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_x = self.move_y = 0
def update(self):
if self.player:
player_x, player_y = self.player.rect.center
if self.rect.x < player_x:
self.rect.x += 1
elif self.rect.x > player_x:
self.rect.x -= 1
if self.rect.y < player_y:
self.rect.y += 1
elif self.rect.y > player_y:
self.rect.y -= 1
#----------------------------------------------------------------------
class Player(pygame.sprite.Sprite):
def __init__(self, screen_rect, x=0, y=0):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.min_x = screen_rect.left
self.min_y = screen_rect.top
self.max_x = screen_rect.right
self.max_y = screen_rect.bottom
self.move_x = self.move_y = 0
self.health = 100
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x += self.move_x
self.rect.y += self.move_y
if self.rect.top < self.min_x:
self.rect.top = self.min_x
elif self.rect.bottom > self.max_y:
self.rect.bottom = self.max_y
if self.rect.left < self.min_x:
self.rect.left = self.min_x
elif self.rect.right > self.max_x:
self.rect.right = self.max_x
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
self.move_x = -4
elif event.key == pygame.K_d:
self.move_x = +4
elif event.key == pygame.K_w:
self.move_y = -4
elif event.key == pygame.K_s:
self.move_y = +4
if event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.move_x = 0
elif event.key in (pygame.K_w, pygame.K_s):
self.move_y = 0
#----------------------------------------------------------------------
class Bullet(pygame.sprite.Sprite):
def __init__(self, start_pos, mouse_pos):
pygame.sprite.Sprite.__init__(self)
self.start_rect = start_pos.rect.copy()
self.mouse_x, self.mouse_y = mouse_pos # mouse[0], mouse[1]
self.image = pygame.Surface([5, 5])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = self.start_rect.centerx
self.rect.centery = self.start_rect.centery
self.speed = 10
self.max_range = 50
self.current_range = 0
distance_x = self.mouse_x - self.start_rect.centerx
distance_y = self.mouse_y - self.start_rect.centery
norm = math.sqrt(distance_x ** 2 + distance_y ** 2)
direction_x = distance_x / norm
direction_y = distance_y / norm
self.bullet_vector_x = direction_x * self.speed
self.bullet_vector_y = direction_y * self.speed
def update(self):
self.current_range += 1
if self.current_range < self.max_range:
print self.start_rect.centerx + (self.bullet_vector_x*self.current_range),
print self.rect.centerx + self.bullet_vector_x,
#self.rect.centerx += self.bullet_vector_x
self.rect.centerx = self.start_rect.centerx + (self.bullet_vector_x*self.current_range)
print self.rect.centerx
#self.rect.centery += self.bullet_vector_y
self.rect.centery = self.start_rect.centery + (self.bullet_vector_y*self.current_range)
else:
self.kill()
#----------------------------------------------------------------------
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_CROSSHAIR).convert_alpha()
self.rect = self.image.get_rect()
def update(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
self.rect.centerx = mouse_x
self.rect.centery = mouse_y
def draw(self, screen):
screen.blit(self.image,self.rect.topleft)
#----------------------------------------------------------------------
class Background(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_GRASS).convert_alpha()
self.rect = self.image.get_rect()
def draw(self, screen):
screen.fill((128,128,128))
screen.blit(self.image,(0,0))
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
screen_width = 850
screen_height = 640
self.screen = pygame.display.set_mode( (screen_width,screen_height) )
pygame.mouse.set_visible(False)
#-----
self.all_sprites_list = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
# --- create sprites ---
self.background = Background()
self.player = Player(self.screen.get_rect(), 0, 370)
self.all_sprites_list.add(self.player)
for i in range(5):
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
self.crosshair = Crosshair()
#-----
font = pygame.font.SysFont("", 72)
self.text_pause = font.render("PAUSE", -1, RED)
self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text
#-----
self.score = 0
def bullet_create(self, start_pos, mouse_pos):
bullet = Bullet(start_pos, mouse_pos)
self.all_sprites_list.add(bullet)
self.bullet_list.add(bullet)
def bullets_update(self):
for bullet in self.bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, self.block_list, True)
for block in block_hit_list:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
self.score += 1
print self.score
if bullet.rect.y < -10:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
if pygame.sprite.collide_rect(self.player, block):
self.player.health =- 35
# -------- Main Program Loop -----------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
PAUSED = False
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = false
elif event.key == pygame.K_SPACE:
PAUSED = not PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN:
self.bullet_create(self.player, event.pos)
# send event to player
self.player.event_handler(event)
# send event to crosshair for mousebuttondown
#if not PAUSED:
# self.crosshair.event_handler(event)
# --- updates ---
if not PAUSED:
self.all_sprites_list.update()
self.bullets_update()
self.crosshair.update()
# --- draws ---
self.background.draw(self.screen)
self.all_sprites_list.draw(self.screen)
self.crosshair.draw(self.screen)
if PAUSED:
self.screen.blit(self.text_pause, self.text_pause_rect.topleft)
pygame.display.update() # use flip() OR update()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
Changes:
player can move but can leave screen
press space to pause game - but you can still move cursor and fire :)
bullet has max range - than it is removed
i change bullet vetor calculations because value was rounded to integer every frame and bullet trajectory was incorrect
bullet never change trajectory when player is moving
all code is in classes except some constant values. I add class Crosshair and Background
you can see how class (Player) handle events in event_handle
I use pygame.Rect() (screen.get_rect(), image.get_rect()) to get rect.top, rect.left, rect.center, rect.centerx, rect.topleft, etc.
There is still many things to do.
ps. if someone needs images 'ball1.png', 'ball2.png', 'ball3.png' to run this example you can find it in answer to
Space invaders project
Pygame- window and sprite class - python

Categories