I am making a game at the moment and I am experiencing problems with collision detection. I am making an end of level block but it can not detect if the player is standing on it to change to level 2. The collision detection for the block is found in player.updater(). As well as this the block is a class and in a group called endPlatform to allow the collision detection to work. The game runs perfectly fine however it can not detect when the Player hits Endplatform. I get no errors which show up.
EndPlatform:
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
Player:
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
All the code:
import pygame
import random
pygame.font.init()
# Colours + Global constants
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RANDOM = (12, 211, 123)
WIDTH = 800
HEIGHT = 600
SIZE = (WIDTH, HEIGHT)
AGENT = pygame.font.SysFont("Agent Orange", 30)
# CLASSES
# Block is the common platform
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Coins(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("hud_coins.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Score:
def __init__(self):
self.score = 0
def msgs(self, msg, colour, display):
screen_text = AGENT.render(msg, True, colour)
display.blit(screen_text, [0, 0])
def add(self):
self.score += 1
class Monster(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = HEIGHT - 80
def jump(self):
self.rect.y = -10
class Block(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
# Making image
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = 468
class Platform(pygame.sprite.Sprite):
def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
super().__init__()
self.tiles = pygame.image.load("tiles_spritesheet.png")
self.image = self.tiles.subsurface(pygame.Rect(x_sheet, y_sheet, height, length))
self.rect = self.image.get_rect(x=x_screen, y=y_screen)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
def gravity(self):
self.sprite_y_change += 3
class Level:
def __init__(self):
# Creating groups
self.endPlatform = pygame.sprite.Group()
self.powerups = pygame.sprite.Group()
self.sprites = pygame.sprite.Group()
self.all_things = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
self.entities = pygame.sprite.Group()
self.shift_x = 0
self.shift_y = 0
def updater(self, display, score):
self.all_things.draw(display)
score.msgs("Score: " + str(score.score), RED, display)
def scroll_x(self, shift_x_change):
self.shift_x += shift_x_change
for platform in self.entities:
platform.rect.x += shift_x_change
def scroll_y(self, shift_y_change):
self.shift_y += shift_y_change
for platform in self.entities:
platform.rect.y += shift_y_change
class Level01(Level):
def __init__(self, player1, monster, display):
# Initialise level1
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
self.entities.add(block)
theLevel = []
level = [[600, 400, 648, 0, 70, 70],
[740, 320, 648, 0, 70, 70],
[380, 400, 648, 0, 70, 70],
[900, 280, 648, 0, 70, 70],
[1200, 530, 648, 0, 70, 70],
[1350, 450, 648, 0, 70, 70],
[1500, 550, 648, 0, 70, 70],
[1680, 500, 648, 0, 70, 70],
]
for platform in theLevel:
block = Block(platform[0], platform[1], RED)
block.rect.x = platform[2]
block.rect.y = platform[3]
self.platforms.add(block)
self.all_things.add(block)
self.entities.add(block)
for goodPlatform in level:
platform = Platform(display, goodPlatform[0], goodPlatform[1], goodPlatform[2], goodPlatform[3], goodPlatform[4], goodPlatform[5])
self.platforms.add(platform)
self.all_things.add(platform)
self.entities.add(platform)
for n in range(1):
coin = Coins(display)
coin.rect.x = random.randint(0, WIDTH*3)
coin.rect.y = 400
self.all_things.add(coin)
self.entities.add(coin)
self.powerups.add(coin)
platforms_hit = pygame.sprite.spritecollide(coin, self.entities, False)
for hit in platforms_hit:
coin.rect.x = random.randrange(0, WIDTH*3)
finalPlatform = EndPlatform(display)
finalPlatform.rect.x = 1900
finalPlatform.rect.y = 420
self.all_things.add(finalPlatform)
self.entities.add(finalPlatform)
self.platforms.add(finalPlatform)
self.endPlatform.add(finalPlatform)
class Level02(Level):
def __init__(self, player1, monster):
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
def main():
# Init pygame
pygame.init()
# Set screen
backgrounds = ["background2.jpg", "background.jpg"]
background = pygame.image.load(backgrounds[0])
backgroundRect = background.get_rect()
display = pygame.display.set_mode(background.get_size())
# Creating FPS thingy
clock = pygame.time.Clock()
# Making levels + Player
score = Score()
monster = Monster(30, 30, RANDOM)
player = Player()
level_1 = Level01(player, monster, display)
level_2 = Level02(player, monster)
# Choosing level
levelList = []
levelList.append(level_1)
levelList.append(level_2)
currentLevelNumber = 0
# Game loop
loop = True
while loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.move_right()
if event.key == pygame.K_LEFT:
player.move_left()
if event.key == pygame.K_UP:
player.move_up(currentLevel.platforms)
if event.key == pygame.KMOD_LSHIFT and event.key == pygame.K_RIGHT:
player.sprint()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
player.stop()
if event.key == pygame.KMOD_LSHIFT:
player.sprite_x_change -= 10
# Update things
#monster.jump()
if player.rect.x > 400:
player.rect.x = 400
currentLevel.scroll_x(-10)
if player.rect.x >= WIDTH:
player.rect.x = WIDTH
currentLevel.scroll(0)
if player.rect.y >= HEIGHT:
main()
if player.sprite_x_change < 0 and player.rect.x >= 120:
currentLevel.scroll_x(0)
if player.rect.left <= 120 and player.sprite_x_change < 0:
player.rect.x = 120
player.rect.left = 120
currentLevel.scroll_x(10)
'''
if player.rect.y <= 300:
if player.standing == False and player.sprite_y_change < 0:
currentLevel.scroll_y(10)
if currentLevel.shift_y > 0:
y_speed = -4
if player.standing == True and player.rect.y < 300:
y_speed = 4
print(currentLevel.shift_y)
currentLevel.scroll_y(y_speed)
'''
currentLevel = levelList[currentLevelNumber]
if currentLevel.shift_x > 0:
currentLevel.scroll_x(currentLevel.shift_x * -1)
display.blit(background, backgroundRect)
player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
currentLevel.updater(display, score)
# Refresh screen
clock.tick(30)
pygame.display.update()
pygame.quit()
loop = False
if __name__ == "__main__":
main()
It seems I found the problem, for some daft reason you can't use collision detection twice on the same object. I used it once so that the player could stand on the block and another time so that you could go on to the next level!
The reason why it doesn't switch to the next level is that you change the position of the rect when it collides with a platform, so the player.rect gets moved out of the blocks.rect and therefore can't collide again when you call spritecollide with the endPlatform group.
A quick and dirty fix would be to check in the for blocks in platforms_hit: loops if the block is in the endPlatform group and then return True:
for blocks in platforms_hit:
if blocks in endPlatform:
score.add()
return True
And then increase the currentLevelNumber in the main function if True is returned:
change_level = player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
if change_level:
currentLevelNumber += 1
Related
When I shoot at my cement block sprites I have it set so that self.score is self.score += 1 in my player collision function, but when I shoot my cement blocks and destroy them, either 1 or 2 points is added at random to my score. Why? How can I fix this? A clear example is, I shoot at and destroy 2 cement blocks in a row and 1 point is added for each one destroyed which means my score is 2, which is what I want cause I want to add 1 point to my score whenever I destroy a cement block, but then when I shoot and destroy the third cement block, 2 points are added instead of 1 bringing my score to 4 instead of being a score of 3 points.
Github: https://github.com/Enoc-Mena99/AutoPilot
My code:
import random
import pygame
import pygame.freetype
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
self.score = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#check collision
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1
#player stats
def stats(self):
myfont = pygame.font.SysFont('comicsans', 30)
scoretext = myfont.render("Score: " + str(self.score), 1, (0,0,0))
screen.blit(scoretext, (100,10))
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.centery < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self,scale,speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = random.randrange(100,800)
self.speed_y = 10
self.y = 15
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
self.velocity = random.randrange(1,2)
self.speed_x = random.randrange(-3,3)
self.moving_down = True
self.is_destroyed = False
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.rect.center = (self.x,self.y)
#load explosion
self.img_explosion_00 = pygame.image.load('explosion/0.png').convert_alpha()
self.img_explosion_00 = pygame.transform.scale(self.img_explosion_00, (self.img_explosion_00.get_width() * 2,
self.img_explosion_00.get_height() * 2))
self.img_explosion_01 = pygame.image.load('explosion/1.png').convert_alpha()
self.img_explosion_01 = pygame.transform.scale(self.img_explosion_01, (self.img_explosion_01.get_width() * 2,
self.img_explosion_01.get_height() * 2))
self.img_explosion_02 = pygame.image.load('explosion/2.png').convert_alpha()
self.img_explosion_02 = pygame.transform.scale(self.img_explosion_02, (self.img_explosion_02.get_width() * 2,
self.img_explosion_02.get_height() * 2))
self.img_explosion_03 = pygame.image.load('explosion/3.png').convert_alpha()
self.img_explosion_03 = pygame.transform.scale(self.img_explosion_03, (self.img_explosion_03.get_width() * 2,
self.img_explosion_03.get_height() * 2))
#explosion list
self.anim_explosion = [self.img_explosion_00,
self.img_explosion_01,
self.img_explosion_02,
self.img_explosion_03]
self.anim_index = 0
self.frame_len = 10
#spawn new debris
def spawn_new_debris(self):
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.velocity = random.randrange(1, 2)
self.speed_x = random.randrange(-3, 3)
#respawn debris when they go of the screen
def boundaries(self):
if self.rect.left > WIDTH + 10 or self.rect.right < -10 or self.rect.top > HEIGHT + 10:
self.spawn_new_debris()
#update image
def update(self):
self.rect.y += self.velocity
self.rect.x += self.speed_x
self.boundaries()
if self.health <= 0:
max_index = len(self.anim_explosion) - 1
if self.anim_index > max_index:
self.kill()
else:
if self.frame_len == 0:
self.image = self.anim_explosion[self.anim_index]
self.anim_index += 1
self.frame_len = 10
else:
self.frame_len -= 1
#make debris fall down
def falldown(self):
self.rect.centery += self.velocity
if self.moving_down and self.rect.y > 350:
self.kill()
######################CAR/DEBRIS##########################
player = Player(1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
for x in range(50):
d = Debris(1, 5)
debris_group.add(d)
all_sprites.add(d)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Do not count debris objects with healt <= 0:
class Player(pygame.sprite.Sprite):
# [...]
def collision(self, debris_group):
for debris in debris_group:
# if health > 0 and collision:
if debris.health > 0 and pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1
I want to delete a sprite permanently from the memory once an event occurs. Using self.kill() doesn't help as the image of the sprite is deleted, but the sprite is still there. What can I do to delete it from memory permanently?
import pygame
import time
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREY = (129, 129, 129)
frame = 0
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert()
def get_image(self, x, y, width, height, colour):
image = pygame.Surface([width, height]).convert()
image.set_colorkey(colour)
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
return image
class Bomb(pygame.sprite.Sprite):
change_x =0
change_y = 0
def __init__(self):
super().__init__()
sprite_sheet = SpriteSheet("Untitled.png")
self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE)
self.rect = self.image.get_rect()
def move(self):
self.change_y = 2
self.rect.y += self.change_y
if self.rect.y > 500:
self.kill()
class Soldier(pygame.sprite.Sprite):
def __init__(self):
self.change_x = 0
self.change_y = 0
self.direction = "R"
super().__init__()
self.walking_frames_l = []
self.walking_frames_r = []
sprite_sheet = SpriteSheet("Picture2.png")
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = self.walking_frames_r[0]
self.rect = self.image.get_rect()
self.rect.y = 297
self.rect.x = 100
self.frame = 0
self.moved = 0
def move(self):
self.rect.x += self.change_x
def walk(self):
self.moved += abs(self.change_x)
pixels_for_one_step = 60
if self.moved > pixels_for_one_step:
self.frame += 1
self.moved = 0
if self.frame >= len(self.walking_frames_r):
self.frame = 0
if self.direction =="R":
self.image = self.walking_frames_r[self.frame]
else:
self.image = self.walking_frames_l[self.frame]
if self.change_x == 0 and self.direction == "R":
self.image = self.walking_frames_r[2]
if self.change_x == 0 and self.direction == "L":
self.image = self.walking_frames_l[2]
def go_left(self):
self.change_x = -6
self.direction = "L"
def go_right(self):
self.direction = "R"
self.change_x = 6
def stop(self):
self.change_x = 0
self.image = self.walking_frames_r[2]
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.change_x =0
self.change_y = 0
self.direction = ""
sprite_sheet = SpriteSheet("Bullet_2.png")
self.image = sprite_sheet.get_image(0, 0, 27, 27, BLACK)
self.image = pygame.transform.rotate(self.image, 45)
self.rect = self.image.get_rect()
self.rect.y = 0
self.rect.x = 0
def moveright(self):
self.change_x =2
self.change_y = 2
self.rect.y -= self.change_y
self.rect.x -= self.change_x
if self.rect.y < -30:
self.kill()
def moveleft(self):
self.change_x =-2
self.change_y = 2
self.rect.y -= self.change_y
self.rect.x -= self.change_x
if self.rect.y < -30:
self.kill()
pygame.init()
screen_width = 1000
screen_height = 500
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
done = False
bomb = Bomb()
soldier = Soldier()
all_sprites = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
bomb_list = pygame.sprite.Group()
bomb_list.add(bomb)
all_sprites.add(bomb)
all_sprites.add(soldier)
screen_rect = screen.get_rect()
pygame.mouse.set_cursor(*pygame.cursors.broken_x)
bg = pygame.image.load ("3601933.jpg")
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
soldier.go_left()
if event.key == pygame.K_RIGHT:
soldier.go_right()
if event.key == pygame.K_SPACE:
bullet = Bullet()
if soldier.direction == "R":
bullet.direction = "R"
bullet.rect.x = soldier.rect.left -23
bullet.rect.y = soldier.rect.top - 23
else:
bullet.image = pygame.transform.flip(bullet.image, True, False)
bullet.rect.x = soldier.rect.left +110
bullet.rect.y = soldier.rect.top - 24
bullet.direction = "L"
all_sprites.add(bullet)
bullet_list.add(bullet)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and soldier.change_x < 0:
soldier.stop()
if event.key == pygame.K_RIGHT and soldier.change_x > 0:
soldier.stop()
soldier.rect.clamp_ip(screen_rect)
screen.blit(bg, [0, 0])
all_sprites.draw(screen)
bomb.move()
soldier.move()
soldier.walk()
for bullet in bullet_list:
if bullet.direction == "R":
bullet.moveright()
else:
bullet.moveleft()
bomb_hit_list = pygame.sprite.spritecollide(bomb, bullet_list, True)
for bullet in bomb_hit_list:
bomb_list.remove(bomb)
all_sprites.remove(bomb)
pygame.sprite.spritecollide(soldier, bomb_list, True)
clock.tick(60)
pygame.display.flip()
pygame.quit()
I want to delete the bomb. If the bomb touches the player, then its image disappears but it is still there. Now whenever a bullet touches the (invisible) bomb, it gets deleted as well.
You have to use bomb_list instead of bomb. Iterate through bomb_list to move the bombs:
for bomb in bomb_list:
bomb.move()
Use pygame.sprite.groupcollide instead of pygame.sprite.spritecollide() to finde the collisions between the Group bomb_list and the Group bullet_list:
bomb_hit_list = pygame.sprite.spritecollide(bomb, bullet_list, True)
bomb_hit_dict = pygame.sprite.groupcollide(bullet_list, bomb_list, True, True)
You don't need the loop for bullet in bomb_hit_list: at all, if the the arguments dokill1 and dokill2 are set True.
I am trying to make a simple platformer in pygame, with simulated gravity and collision. I can't make the collision working. On collision with a sprite, the player slowly falls through the sprite and continues falling at normal speed when reached through.
Main.py:
class Game:
def __init__(self):
# initialize pygame library
pg.init()
pg.mixer.init()
# initialize screen
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.font = pg.font.match_font(FONT_NAME)
self.running = True
self.playing = True
def new(self):
# initzialize sprite groups
self.sprites = pg.sprite.Group()
self.objects = pg.sprite.Group()
self.p = Player(self)
self.sprites.add(self.p)
self.g = Ground()
self.sprites.add(self.g)
self.objects.add(self.g)
self.o = Object(100, 350, 100, 20)
self.sprites.add(self.o)
self.objects.add(self.o)
self.collide = False
self.run()
# constant running functions
def run(self):
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
self.running = False
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.playing = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.p.jump()
def update(self):
self.sprites.update()
hits = pg.sprite.spritecollide(self.p, self.objects, False)
if hits:
self.collide = True
if self.p.vel.y >= 0.0:
self.p.x = hits[0].rect.top
print("Collide bottom")
elif self.p.vel.y < 0: self.p.top = hits[0].rect.bottom
elif self.p.vel.x > 0: self.p.rect.right = hits[0].rect.left
elif self.p.vel.x < 0: self.p.rect.left = hits[0].rect.right
self.p.vel.y = 0
#self.p.acc.y = 0
#print(f"Collision with {hits[0].name}")
else:
self.collide = False
def draw(self):
self.screen.fill(BLACK)
self.sprites.draw(self.screen)
self.drawtext(f"X Pos: = {int(self.p.pos.x)}", 15, WHITE, WIDTH - 5, 20, 3)
self.drawtext(f"Y Pos: = {int(self.p.pos.y)}", 15, WHITE, WIDTH - 5, 40, 3)
self.drawtext(f"Y Velocity = {self.p.vel.y}", 15, WHITE, 5, 50, 0)
self.drawtext(f"Y Accelleration = {self.p.acc.y}", 15, WHITE, 5, 70, 0)
self.drawtext(f"Collision: = {self.collide}", 15, WHITE, 5, 200, 0)
#print(self.p.vel.y)
pg.display.flip()
# other functions
def drawtext(self, text, size, color, x, y, align):
font = pg.font.Font(self.font, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
if align == 0:
text_rect.midleft = (x, y)
elif align == 1:
text_rect.midtop = (x, y)
elif align == 2:
text_rect.midbottom = (x, y)
elif align == 3:
text_rect.midright = (x, y)
else:
text_rect.center = (x, y)
self.screen.blit(text_surface, text_rect)
# def checkCollisionY(self):
# hits = pg.sprite.spritecollide(self.p, self.objects, False)
# if hits:
# self.collide = True
# return True
# else:
# self.collide = False
# return False
g = Game()
while g.running:
g.new()
pg.quit()
Sprites.py:
from settings import *
import pygame as pg
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.width = 30
self.height = 30
self.image = pg.Surface((self.width, self.height))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.center = vec(150, 100)
self.pos = vec(150, 100)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def update(self):
self.acc = vec(0, PLAYER_GRAV)
#input
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_RIGHT]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
print(f"{self.vel.y} + 0.5 * {self.acc.y} = {self.vel.y + 0.5 * self.acc.y}")
self.rect.topleft = self.pos
def jump(self):
hits = pg.sprite.spritecollide(self, self.game.objects, False)
if hits:
self.vel.y = -20
class Object(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill((255, 0, 144))
self.name = "Object"
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Ground(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.name = "Ground"
self.image = pg.image.load("ground.png")
self.rect = self.image.get_rect()
self.rect.x = -100
self.rect.y = 550
Settings.py:
# game settings
TITLE = "My Game"
WIDTH = 480
HEIGHT = 800
FPS = 60
FONT_NAME = 'impact'
#Player properties
PLAYER_ACC = 0.7
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.7
# 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)
CYAN = (0, 255, 255)
PURPLE = (255, 0, 255)
The important code here is the update() in main.py and update() in sprites.py. Help?
EDIT
hits = pg.sprite.spritecollide(self.p, self.objects, False)
for hit in hits:
self.collide = True
if self.p.vel.x > 0.0:
self.p.rect.right = hit.rect.left
self.p.pos.x = self.p.rect.centerx
self.p.vel.x = 0
elif self.p.vel.x < 0.0:
self.p.rect.left = hit.rect.right
self.p.pos.x = self.p.rect.centerx
self.p.vel.x = 0
self.p.pos.x = self.p.rect.x
else:
self.collide = False
hits = pg.sprite.spritecollide(self.p, self.objects, False)
for hit in hits:
self.collide = True
if self.p.vel.y >= 0.0:
self.p.rect.bottom = hit.rect.top
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
elif self.p.vel.y < 0.0:
self.p.rect.top = hit.rect.bottom
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
self.p.pos.y = self.p.rect.y
else:
self.collide = False
Your Player class doesn't have x and y attributes but a pos attribute which you need to change after a collision. The rect of the object needs to be updated as well and it's better to do that first and then set the pos.y coordinate to the rect.centery coordinate afterwards.
if self.p.vel.y >= 0.0:
self.p.rect.bottom = hits[0].rect.top
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
Do the same for the other directions.
Also, the horizontal and vertical movement should be handled separately, otherwise you'll see odd jumps for example from the side to the top of a platform. Take a look at the first part of this platformer example.
And in the jump method you need to move the rect down by 1 pixel so that it's able to collide with the platform sprites.
def jump(self):
self.rect.y += 1
# ...
Here's a complete, runnable example:
import pygame as pg
# game settings
TITLE = "My Game"
WIDTH = 480
HEIGHT = 800
FPS = 60
FONT_NAME = 'impact'
#Player properties
PLAYER_ACC = 0.7
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.7
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = pg.Surface((30, 30))
self.image.fill(YELLOW)
self.rect = self.image.get_rect(center=(150, 100))
self.pos = vec(150, 100)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
self.objects = game.objects
def update(self):
self.acc = vec(0, PLAYER_GRAV)
#input
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_RIGHT]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
# Move along the x-axis first.
self.pos.x += self.vel.x + 0.5 * self.acc.x
# print(f"{self.vel.y} + 0.5 * {self.acc.y} = {self.vel.y + 0.5 * self.acc.y}")
self.rect.centerx = self.pos.x
# Check if the sprite collides with a platform.
hits = pg.sprite.spritecollide(self, self.objects, False)
if hits:
# Reset the x position.
if self.vel.x > 0:
self.rect.right = hits[0].rect.left
self.pos.x = self.rect.centerx
self.vel.x = 0
elif self.vel.x < 0:
self.rect.left = hits[0].rect.right
self.pos.x = self.rect.centerx
self.vel.x = 0
# Move along the y-axis.
self.pos.y += self.vel.y + 0.5 * self.acc.y
self.rect.centery = self.pos.y
# Check if the sprite collides with a platform.
hits = pg.sprite.spritecollide(self, self.objects, False)
if hits:
# Reset the y position.
if self.vel.y >= 0.0:
self.rect.bottom = hits[0].rect.top
self.pos.y = self.rect.centery
self.vel.y = 0
elif self.vel.y < 0:
self.rect.top = hits[0].rect.bottom
self.pos.y = self.rect.centery
self.vel.y = 0
def jump(self):
self.rect.y += 1 # Move it down to check if it collides with a platform.
hits = pg.sprite.spritecollide(self, self.game.objects, False)
if hits:
self.vel.y = -20
self.rect.y -= 1 # Move it up again after the collision check.
class Object(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill((255, 0, 144))
self.name = "Object"
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Ground(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.name = "Ground"
self.image = pg.Surface((500, 300))
self.image.fill((90, 30, 30))
self.rect = self.image.get_rect()
self.rect.x = -100
self.rect.y = 550
class Game:
def __init__(self):
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.font = pg.font.match_font(FONT_NAME)
self.running = True
self.playing = True
def new(self):
self.sprites = pg.sprite.Group()
self.objects = pg.sprite.Group()
self.p = Player(self)
self.sprites.add(self.p)
self.g = Ground()
self.sprites.add(self.g)
self.objects.add(self.g)
rects = [(100, 350, 100, 20), (50, 380, 100, 20),
(200, 450, 100, 100)]
for x, y, w, h in rects:
obj = Object(x, y, w, h)
self.sprites.add(obj)
self.objects.add(obj)
self.collide = False
self.run()
def run(self):
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
self.running = False
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.playing = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.p.jump()
def update(self):
self.sprites.update()
def draw(self):
self.screen.fill(BLACK)
self.sprites.draw(self.screen)
pg.display.flip()
g = Game()
while g.running:
g.new()
pg.quit()
It is asking for 3 arguments and i have given it one. How do i give it 2 more and could you explain how to do that as well? Thanks
import pygame, random, collisionObjects
pygame.init()
screen = pygame.display.set_mode((640,480))
class Pirate(pygame.sprite.Sprite):
EAST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("king_pirate/running e0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (0, random.randrange(30,450))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx += self.dx
if self.rect.centerx > self.screen.get_width():
self.rect.centerx = 0
self.rect.centery = random.randrange(30,450)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "king_pirate/running e000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
class Pirate2(pygame.sprite.Sprite):
WEST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pirate/running w0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (640, random.randrange(20,460))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx -= self.dx
if self.rect.centerx < 0:
self.rect.centerx = self.screen.get_width()
self.rect.centery = random.randrange(20,460)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "pirate/running w000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
#set up class for gold object,
class Gold(pygame.sprite.Sprite):
def __init__(self, screen, imageFile):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imageFile)
self.image = self.image.convert()
self.rect = self.image.get_rect()
self.rect.centerx = random.randrange(0, screen.get_width())
self.rect.centery = random.randrange(0, screen.get_height())
#main character class
class Thief(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("thief2.gif")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-15, -10)
self.rect.center = (30, (screen.get_height()-40))
self.dx = 30
self.dy = 30
if not pygame.mixer:
print("problem with sound")
else:
pygame.mixer.init()
self.collectcoin = pygame.mixer.Sound("collectcoin.wav")
self.hit = pygame.mixer.Sound("hit.ogg")
def update(self):
if self.rect.bottom > screen.get_height():
self.rect.centery = (screen.get_height()-40)
elif self.rect.top < 0:
self.rect.centery = 40
elif self.rect.right > screen.get_width():
self.rect.centerx = (screen.get_width()-30)
elif self.rect.left < 0:
self.rect.centerx = 30
#define movements
def moveUp(self):
self.rect.centery -= self.dy
def moveDown(self):
self.rect.centery += self.dy
def moveLeft(self):
self.rect.centerx -= self.dx
def moveRight(self):
self.rect.centerx += self.dx
def reset(self):
self.rect.center = (30, (screen.get_height()-40))
#set up a scoreboard
class Scoreboard(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.lives = 0
self.score = 0
self.font = pygame.font.SysFont("None", 40)
self.number = 0
#with a self updating label
def update(self):
self.text = "Damage: %d %% Gold Taken: %d" % (self.lives, self.score)
self.image = self.font.render(self.text, 1, (199,237,241))
self.rect = self.image.get_rect()
#define the game function
def game():
#set up background
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
#initialize pirates & scoreboard sprites
pirate = Pirate()
scoreboard = Scoreboard()
#create two arrays for multiple gold object occurances
#two arrays are used for better distribution on screen
gold1 = []
numberofGold = 16
for i in range(numberofgolds):
oneGold = golds(screen,"gold1.png")
golds1.append(onegold)
for gold in golds1:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(20,240)
gold.rect.inflate_ip(-5, -5)
gold2 = []
for i in range(numberofgolds):
onegold = golds(screen,"gold1.png")
golds2.append(onegold)
for gold in golds2:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(250,460)
gold.rect.inflate_ip(-5, -5)
totalgolds = ((len(golds1)-1)+(len(golds2)-1))
#initialize gold sprites
goldSprites = pygame.sprite.Group(golds1,
#initialize pirate sprites & instances
pirate1 = pirate1(screen,13)
pirate2 = pirate2(screen,13)
pirate3 = pirate1(screen,11)
pirate4 = pirate2(screen,11)
pirate5 = pirate1(screen,13)
pirateSprites = pygame.sprite.Group(pirate1, pirate2, pirate3, pirate4, pirate5)
#use ordered updates to keep clean appearance
allSprites = pygame.sprite.OrderedUpdates(goldSprites, thief, pirateSprites, scoreboard)
#set up clock & loop
clock = pygame.time.Clock()
keepGoing = True
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
thief.moveUp()
elif event.key == pygame.K_DOWN:
thief.moveDown()
elif event.key == pygame.K_LEFT:
thief.moveLeft()
elif event.key == pygame.K_RIGHT:
thief.moveRight()
elif event.key == pygame.K_ESCAPE:
keepGoing = False
#check collisions here
hitpirates = pygame.sprite.spritecollide(thief, pirateSprites, False)
hitgold = pygame.sprite.spritecollide(thief, goldSprites, True)
if hitpirates:
thief.hit.play()
scoreboard.lives += 1
if scoreboard.lives >= 100:
keepGoing = False
number = 0
if hitgolds:
thief.collectcoin.play()
scoreboard.score += 1
totalgolds -= 1
if totalgolds <= 0:
keepGoing = False
number = 1
#draw sprites
allSprites.clear(screen, background)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
return scoreboard.score
return scoreboard.number
def instructions(score, number):
pygame.display.set_caption("Hunt for Gold!")
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
if number == 0:
message = "Sorry try again..."
elif number == 1:
message = "The theif escapes!"
else:
message = "Onto the hunt for gold!"
insFont = pygame.font.SysFont("Calibri", 25)
insLabels = []
instructions = (
"Last score: %d" % score ,
"%s" % message,
"",
"GOLD!",
"Get all the gold before you are "
"obliterated!",
"Use arrow keys to move the thief.",
"Space to start, Esc to quit."
)
for line in instructions:
tempLabel = insFont.render(line, 1 , (0,0,0))
insLabels.append(tempLabel)
#set up homescreen loop
keepGoing = True
clock = pygame.time.Clock()
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
donePlaying = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
keepGoing = False
donePlaying = False
if event.key == pygame.K_ESCAPE:
keepGoing = False
donePlaying = True
for i in range(len(insLabels)):
screen.blit(insLabels[i], (50, 30*i))
pygame.display.flip()
return donePlaying
#define main function
def main():
donePlaying = False
score = 0
message = ""
while not donePlaying:
donePlaying = instructions(score, message)
if not donePlaying:
score = game()
else:
pygame.quit()
if __name__ == "__main__":
main()
Glancing at your code, this line:
pirate = Pirate()
Your Pirate class expects self, screen, dx. You only implicitly provide self.
I can only guess at what you want, especially since I don't know off the bat what dx is supposed to mean in respect to your game, but this will probably at least avoid the error:
pirate = Pirate(pygame.display.get_surface(), 60)
I have created code to see whether my aliens are dead however it doesn't work, can anyone see the problem.
CODE:
enemies = pygame.sprite.Group(aliens)
if len(enemies) <= 0:
print("game over")
gameover()
Complete code:
#MathsVaders
import pygame, random, time
from pygame.locals import *
import Databaseconnector
import tkMessageBox
pygame.init()
# set up the graphics window
size = [800, 595]
screen = pygame.display.set_mode(size, 0)
screenrect = screen.get_rect()
pygame.display.set_caption("Mathsvaders")
# set some variables
done = False
life = 3
aliens = pygame.sprite.Group()
allsprites = pygame.sprite.Group()
bombs = pygame.sprite.Group()
green = [0, 255, 0]
white = [255, 255, 255]
# create a timer to control how often the screen updates
clock = pygame.time.Clock()
fps = 100
# loads images to use in the game which link in with my classes(further down)
cannon = pygame.image.load("spaceship.png").convert()
cannon.set_colorkey(white)
blast = pygame.image.load("blast.png").convert_alpha()
boom = pygame.image.load("expl.png").convert_alpha()
bomb = pygame.image.load("missile_player.png").convert_alpha()
back = pygame.image.load("rsz_space.png").convert()
enemy = pygame.image.load("sii.png").convert_alpha()
lives2 = pygame.image.load("alien2.png").convert()
lives2.set_colorkey(white)
lives3 = pygame.image.load("alien3.png").convert()
lives3.set_colorkey(white)
lives1 = pygame.image.load("alien1.png").convert()
lives1.set_colorkey(white)
# (Classes)
# the explosion class
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = boom
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.count = 6
def update(self):
self.count -= 1
if self.count < 1:
self.kill()
class scoreClass:
def __init__(self):
self.value = 0
# set a font, default font size 28
self.font = pygame.font.Font(None, 28)
def update(self):
text = self.font.render("Score: %s" % self.value, True, (green))
textRect = text.get_rect()
textRect.centerx = screenrect.centerx
screen.blit(text, textRect)
class Msg:
def __init__(self, words):
# set a font, default font size 28
self.font = pygame.font.Font(None, 28)
self.text = self.font.render(words, True, (green))
self.textRect = self.text.get_rect()
def update(self):
self.textRect.centerx = screenrect.centerx
self.textRect.centery = screenrect.centery
screen.blit(self.text, self.textRect)
# the invader class
class Pi(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
aliens.add(self)
self.image = enemy
self.rect = self.image.get_rect()
self.rect.left = x
self.rect.top = y
self.speed = 1
def update(self):
self.rect.right += self.speed
if self.rect.right >= (screenrect.right -5):
self.speed = -1
self.rect.top += self.rect.height
if self.rect.left <= (screenrect.left +5):
self.speed = 1
self.rect.top += self.rect.height
if self.rect.top > screenrect.bottom:
self.kill()
i = random.randrange(1000)
j = self.rect.centerx
if i == 1:
laser_bomb = Bomb(j, self.rect.bottom)
allsprites.add(laser_bomb)
aliens.add(laser_bomb)
class Gun(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = cannon
self.rect = self.image.get_rect()
self.rect.bottom = screenrect.bottom
self.rect.centerx = screenrect.centerx
self.speed=0
def update(self):
self.rect.centerx += self.speed
if self.rect.right >= screenrect.right:
self.rect.centerx = 0
if self.rect.right <= 0:
self.rect.right = screenrect.right
# bomb class
class Bomb(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = bomb
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
bombs.add(self)
def update(self):
self.rect.centery +=1
# the laser blast class
class Blast(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = blast
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.top = (player.rect.top + 5)
self.rect.centerx = player.rect.centerx
self.speed = 0
def update(self):
if self.speed == 0:
self.rect.centerx = player.rect.centerx
self.rect.top -= self.speed
# function to make a sheet of invaders
def invade():
for j in range(10, 200, 120):
for i in range(10):
aliens.add(Pi((i*70)+10, j))
def gameover():
message = Msg("Game Over")
message.update()
player.kill()
shot.kill()
SQL = 'INSERT INTO TblScore(Score, StudentID) VALUES (' + str(score.value) + ', ' + str(8) + ')'
Databaseconnector.INSERT(SQL)
#pygame.quit()
##def gameover():
## message = Msg("Game Over")
## message.update()
## player.kill()
## shot.kill()
## SQL = 'INSERT INTO TblScore(Score, StudentID) VALUES (' + str(score.value) + ', ' + str(8) + ')'
## Databaseconnector.INSERT(SQL)
##
## #pygame.quit()
def gamewon():
# sprites(aliens) == 0
#sprites.aliens == 0
message = Msg("YOU WON, YOUR SCORE WAS " + score + " WELL DONE")
message.update
aliens.kill()
shot.kill()
pygame.quit()
# pre-game window
invade()
message = Msg("Press a key to play.")
allsprites.add(aliens)
key = True
while key:
screen.blit(back, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
for item in (aliens):
item.kill()
key = False
allsprites.update()
allsprites.draw(screen)
message.update()
# set the loop to 40 cycles per second
clock.tick(fps)
# update the display
pygame.display.flip()
# Main Game Starts Here
score = scoreClass()
player = Gun()
shot = Blast()
invade()
allsprites.add(player, aliens, shot)
while done==False:
screen.blit(back, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
done=True
if life <= 0:
gamewon()
## elif allsprites == 0:
## gamewon()
else:
# shoots laser missile
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if shot.speed == 0:
shot.speed = 7
#laser.play()
if event.key == pygame.K_LEFT:
player.speed = -3
if event.key == pygame.K_RIGHT:
player.speed = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.speed = 0
if event.key == pygame.K_RIGHT:
player.speed = 0
hit = pygame.sprite.spritecollide(shot, aliens, 1)
if len(hit) > 0:
explosion1 = Explosion(shot.rect.centerx, shot.rect.top)
score.value += 1500
shot.kill()
#explode.play()
shot = Blast()
allsprites.add(shot, explosion1)
hit2 = pygame.sprite.spritecollide(player, aliens, 1)
if len(hit2) > 0:
life -= 1
#explode.play()
explosion2 = Explosion(player.rect.centerx, player.rect.centery)
allsprites.add(explosion2)
player.kill()
shot.kill()
if life > 0:
ready = Msg("Push Harder !!.")
ready.update()
allsprites.update()
allsprites.draw(screen)
score.update()
pygame.display.flip()
for item in bombs:
item.kill()
while 1:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
break
player = Gun()
shot = Blast()
allsprites.add(player, shot)
if shot.rect.top <= screenrect.top:
shot.kill()
shot = Blast()
allsprites.add(shot)
if life == 2:
men = lives2
if life == 1:
men = lives1
if life == 3:
men = lives3
if life > 0:
screen.blit(men, (0,0))
allsprites.update()
allsprites.draw(screen)
score.update()
# set the loop to "fps" cycles per second
clock.tick(fps)
# update the display
pygame.display.flip()
# close pygame
pygame.quit()
This is the "pythonic" way since an empty list is False:
if not enemies:
print("game over")
gameover()
Where is the part of code that kills your aliens?