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.
Related
I'd like to add clouds in my game to my game was more realistic, but I don't know, how to realize right. What's wrong?
from pygame.locals import *
import pygame
import os
import random
WIDTH = 1200
HEIGHT = 700
FPS = 60
usr_y = HEIGHT - 120
usr_x = WIDTH - 1120
BLUE = (0, 255, 255)
GREEN = (34, 89, 76)
NOTGREEN = (0, 128, 128)
WHITE = (255, 255, 255)
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Mini-games")
clock = pygame.time.Clock()
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
player_img = pygame.image.load('Sonic.actionp1.png').convert()
pygame.mixer.music.load('Фоновая музыка.mp3')
pygame.mixer.music.play(-1)
clouds_jpg = pygame.image.load('Clouds.jpg').convert()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = player_img
self.image.set_colorkey(NOTGREEN)
self.rect = self.image.get_rect()
self.rect.centerx = usr_x
self.rect.centery = usr_y
self.y = self.rect.y
def update(self):
self.rect.y = round(self.y)
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -8
if keystate[pygame.K_RIGHT]:
self.speedx = 8
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
class Clouds(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = clouds_jpg
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = random.randint(0, WIDTH)
self.rect.centery = random.randint(HEIGHT - 550, HEIGHT)
def update(self):
self.rect.x(-5, 0)
ADDCLOUD = pygame.USEREVENT + 1
pygame.time.set_timer(ADDCLOUD, 1000)
all_sprites = pygame.sprite.Group()
player = Player()
clouds = Clouds()
all_sprites.add(player, clouds)
jump = False
counter = -20
def make():
global usr_y, counter, jump
if counter >= -20:
player.y -= counter
counter -= 1
else:
counter = 20
jump = False
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_SPACE:
jump = True
elif event.type == pygame.QUIT:
running = False
if jump:
make()
all_sprites.update()
screen.fill(BLUE)
all_sprites.draw(screen)
pygame.display.flip()
clouds.update()
pygame.quit()
The instruction self.rect.x(-5, 0) doesn't make any sense. You can move a sorite respectively rectangle with the pygame.Rect.move_ip instruction:
self.rect.x(-5, 0)
self.rect.move_ip(-5, 0)
Change the clouds position to the right as it goes out of the Window:
class Clouds(pygame.sprite.Sprite):
# [...]
def update(self):
self.rect.move_ip(-5, 0)
if self.rect.right <= 0:
self.rect.left = screen.get_width()
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.
My game is almost complete! Unfortunately, there are some little details I need to fix. The main one is that after you play for a bit, some of the sprites will get stuck on the front of the screen. Can anybody please help me out.
import pygame, random
from pygame.locals import (
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
KEYDOWN,
QUIT,
)
print('Use the window above to play')
pygame.init()
pygame.font.init()
clock = pygame.time.Clock()
score = 0
display_width = 800
display_height = 600
X = 400
Y = 400
SCREEN_WIDTH = display_width
SCREEN_HEIGHT = display_height
screen = pygame.display.set_mode((display_width,display_height))
def death():
global alive
print('You died')
myfont = pygame.font.SysFont('Comic Sans MS', 100)
textsurface = myfont.render('You Died.', False, (0, 0, 0))
screen.blit(textsurface,(0,0))
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super(Player, self).__init__()
self.surf = pygame.image.load("Plane.png").convert()
self.rect = self.surf.get_rect(topleft = (x, y))
def update(self, pressed_keys):
if pressed_keys[K_UP]:
self.rect.move_ip(0, -5)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0, 5)
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5, 0)
if self.rect.left < 0:
self.rect.left = 0
if self.rect.right > SCREEN_WIDTH:
self.rect.right = SCREEN_WIDTH
if self.rect.top <= 0:
self.rect.top = 0
if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super(Enemy, self).__init__()
self.surf = pygame.Surface((20, 10))
self.surf = pygame.image.load("Missile.png").convert()
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
self.speed = random.randint(5, 10)
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
global score
score += 1
self.kill()
class Bomb(pygame.sprite.Sprite):
def __init__(self):
super(Bomb, self).__init__()
self.surf = pygame.Surface((50, 25))
self.surf = pygame.image.load("Bomber.png").convert()
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
self.speed = random.randint(2, 5)
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
global score
score += 2
self.kill()
class Blimp(pygame.sprite.Sprite):
def __init__(self):
super(Blimp, self).__init__()
self.surf = pygame.Surface((75, 35))
self.surf = pygame.image.load("Blimp.png").convert()
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
self.speed = random.randint(1, 3)
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
global score
score += 3
self.kill()
ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, 950)
player = Player(display_width // 2, display_height // 2)
enemies = pygame.sprite.Group()
bomb = pygame.sprite.Group()
blimp = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
alive = True
while alive:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
alive = False
elif event.type == ADDENEMY:
new_enemy = Enemy()
new_bomb = Bomb()
new_blimp = Blimp()
spawn = random.randint(1,3)
if spawn == 1:
enemies.add(new_enemy)
if spawn == 2:
enemies.add(new_blimp)
if spawn == 3:
enemies.add(new_bomb)
all_sprites.add(new_enemy)
all_sprites.add(new_bomb)
all_sprites.add(new_blimp)
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
enemies.update()
screen.fill((50,50,160))
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
alive = False
death()
screen.blit(player.surf, player.rect)
pygame.display.flip()
pygame.display.update()
clock.tick(60)
Press the arrow keys to move. The text box (not in the new window) will tell you your score.
You update all the enemies which are on the Group enemies
enemies.update()
And you draw all the Sprites in the group all_sprites.
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
But not all enemies which are in the Group all_sprites are in the Group enemies, too:
new_enemy = Enemy()
new_bomb = Bomb()
new_blimp = Blimp()
spawn = random.randint(1,3)
if spawn == 1:
enemies.add(new_enemy)
if spawn == 2:
enemies.add(new_blimp)
if spawn == 3:
enemies.add(new_bomb)
all_sprites.add(new_enemy)
all_sprites.add(new_bomb)
all_sprites.add(new_blimp)
All the enemies which are in the Group all_sprites, but not in the Group enemies are drawn but don't move.
Create a random enemy type and add it to both Gourps:
alive = True
while alive:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
alive = False
elif event.type == ADDENEMY:
new_opponent = random.choice([Enemy(), Bomb(), Blimp()])
enemies.add(new_opponent)
all_sprites.add(new_opponent)
This question already has an answer here:
pygame.sprite.groupcollide() does not work when trying to implement collision in pygame [duplicate]
(1 answer)
Closed 2 years ago.
I made an enemy class and a player class for a pygame game and I'm trying to figure out how to detect collisions between them. I've tried a lot of different methods, and they don't work, because they need you to use a Rect object and I use a Surface object. Can you tell me what code to add to detect collisions between to Surface Objects? Here is my code:
import pygame
from pygame.locals import *
from sys import exit
import time
import random
pygame.init()
SCREEN_SIZE = (800, 600)
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
screen.blit(background, (0, 0))
class Box(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self._1 = random.randint(10, 50)
self.image = pygame.Surface((self._1, self._1))
self.image.fill((random.randint(1, 255), random.randint(1, 255), random.randint(1, 255)))
self.rect = self.image.get_rect()
self.dx = random.randint(5, 15)
self.dy = random.randint(5, 15)
self.direction = self.dx, self.dy
def update(self):
pass
class Player(Box):
def __init__(self):
Box.__init__(self)
self.x = 400
self.y = 300
self.image = pygame.Surface((30, 30))
self.image.fill((0, 255, 0))
screen.fill((255, 255, 255))
self.rect.centerx = 400
self.rect.centery = 300
def update(self):
self.rect.centerx = self.x
self.rect.centery = self.y
class Enemy(Box):
def __init__(self):
Box.__init__(self)
self.image = pygame.Surface((30, 30))
self.image.fill((0, 255, 0))
self.image.fill((255, 0, 0))
def update(self):
self.dx, self.dy = self.direction
self.rect.centerx += self.dx
self.rect.centery += self.dy
if self.rect[0] >= 800 or self.rect[0] + self._1 <= 0:
self.direction = -self.dx, self.dy
if self.rect[1] >= 600 or self._1 + self.rect[1] <= 0:
self.direction = self.dx, -self.dy
allSprites = pygame.sprite.Group()
player = Player()
enemy1 = Enemy()
enemy2 = Enemy()
enemy3 = Enemy()
allSprites.add(enemy1)
allSprites.add(enemy2)
allSprites.add(enemy3)
allSprites.add(player)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
player.x -= 10
if event.key == K_RIGHT:
player.x += 10
if event.key == K_UP:
player.y -= 10
if event.key == K_DOWN:
player.y += 10
screen.fill((255, 255, 255))
allSprites.clear(screen, background)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
time.sleep(50.0 / 1000.0)
Add the enemies to a pygame.sprite.Group (enemies) and detect if the Sprite player collides with an element from the Group enemies by pygame.sprite.spritecollide(). e.g.:
player = Player()
enemy1 = Enemy()
enemy2 = Enemy()
enemy3 = Enemy()
allSprites = pygame.sprite.Group()
allSprites.add([enemy1, enemy2, enemy3, player])
enemies = pygame.sprite.Group()
enemies.add([enemy1, enemy2, enemy3])
while True:
# [...]
allSprites.update()
if pygame.sprite.spritecollide(player, enemies, False):
print("collide")
# [...]
But note the .rect attributes of the objects Player and Enemy have just a size of 1x1. Ensure that the rectangles have the proper size:
class Player(Box):
def __init__(self):
Box.__init__(self)
self.x = 400
self.y = 300
self.image = pygame.Surface((30, 30))
self.image.fill((0, 255, 0))
screen.fill((255, 255, 255))
self.rect = self.image.get_rect(center=(400, 300)) # <---
class Enemy(Box):
def __init__(self):
Box.__init__(self)
self.image = pygame.Surface((30, 30))
self.rect = self.image.get_rect() # <---
self.image.fill((0, 255, 0))
self.image.fill((255, 0, 0))
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