python - Collision not working for pygame Sprites -
i'm trying make spaceship game python programming class, , want use sprite.spritecollideany
check if player sprite spaceship
colliding of asteroid sprites in spritegroup
group, no matter do, doesn't seem work.
here's code:
import pygame import random pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("asteroids , spaceships") background = pygame.image.load("background.png") background = background.convert() white = 255,255,255 #first make asteroids class. class asteroids(pygame.sprite.sprite): def __init__(self, x, y): pygame.sprite.sprite.__init__(self) self.x = x self.y = y self.width = 30 self.height = 30 self.i1 = pygame.image.load("smallasteroid.png") self.i1 = self.i1.convert() self.i1.set_colorkey(white) self.rect = self.i1.get_rect() self.rect.left = x self.rect.top = y self.i2 = pygame.image.load("smallasteroid2.png") self.i2 = self.i2.convert() self.i2.set_colorkey(white) self.rect = self.i2.get_rect() self.rect.left = x self.rect.top = y self.i3 = pygame.image.load("mediumasteroid.png") self.i3 = self.i3.convert() self.i3.set_colorkey(white) self.rect = self.i3.get_rect() self.rect.left = x self.rect.top = y self.current = 0 def render(self, image_num): if image_num == 1: self.current = 1 if image_num == 2: self.current = 2 if image_num == 3: self.current = 3 def update(self): if self.current == 1: screen.blit(self.i1, (self.x,self.y)) self.y += random.randint(7,11) if self.y > screen.get_height(): self.y = 0 if self.current == 2: screen.blit(self.i2, (self.x,self.y)) self.y += random.randint(5,9) if self.y > screen.get_height(): self.y = 0 if self.current == 3: screen.blit(self.i3, (self.x,self.y)) self.y += random.randint(3,6) if self.y > screen.get_height(): self.y = 0 #and class spaceship class spaceship(pygame.sprite.sprite): def __init__(self, x, y): pygame.sprite.sprite.__init__(self) self.x = x self.y = y self.width = 40 self.height = 60 self.image = pygame.image.load("spaceship.png") self.image = self.image.convert() self.image.set_colorkey(white) self.rect = self.image.get_rect() self.rect.left = x self.rect.top = y def update(self): screen.blit(self.image,(self.x,self.y)) if self.y > screen.get_height(): self.y = 0 if self.y < screen.get_height()-610: self.y = screen.get_height() if self.x > screen.get_width(): self.x = 0 if self.x < screen.get_width()-610: self.x = screen.get_width() #main have game run def main(): x_ship, y_ship = 0,0 player = spaceship(300,550) spritegroup = pygame.sprite.group() #my asteroid sprites grouped here in range(25): image_num = random.randint(0,3) asteroid = asteroids(random.randint(0,500),random.randint(0, 200)) asteroid.render(image_num) spritegroup.add(asteroid) clock = pygame.time.clock() keepgoing = true while keepgoing: #this tried use check collisions. know it's not working don't know why. if pygame.sprite.spritecollideany(player,spritegroup): #the program quits on collision. pygame.quit() event in pygame.event.get(): if (event.type == pygame.quit): keepgoing = false elif event.type == pygame.keyup: if event.key == pygame.k_escape: keepgoing = false if (event.type == pygame.keydown): if (event.key == pygame.k_left): x_ship = -4 if (event.key == pygame.k_right): x_ship = 4 if (event.key == pygame.k_up): y_ship = -4 if (event.key == pygame.k_down): y_ship = 4 if (event.type==pygame.keyup): if (event.key==pygame.k_left): x_ship = 0 if (event.key==pygame.k_right): x_ship = 0 if (event.key==pygame.k_up): y_ship = 0 if (event.key==pygame.k_down): y_ship = 0 player.x += x_ship player.y += y_ship screen.blit(background, (0,0)) spritegroup.clear(screen, background) player.update() spritegroup.update() clock.tick(50) pygame.display.flip() pygame.quit() main()
i can't figure out why collision isn't working.
your problem neither spaceship
nor asteroids
classes revise own rect
s (their hitboxes) on update
, , x
, y
attributes have no direct or automatic connection location of rect. if add self.rect.topleft = self.x, self.y
end of update
function both classes, respective rects-- is, hitboxes-- move ought be, instead of remaining @ initialized locations, in case (300,550) player
and... semi-random offset each asteroid (i'm not sure where, exactly; did make sloppy reproduction of code, test bunch of hunches. apologize not finding exact origin of problem...)
in case, short answer that, although have running check x , y locations of each sprite, haven't told pygame apply location hitbox, , sprite.spritecollideany
falsey because hitbox rects were never touching.
putting self.rect.topleft = self.x, self.y
@ end of each of sprite class' update
functions fix it. (make sure line @ end of function , @ lowest indentation level within def update(self)
!)
edit
alternatively, instead of adding aforementioned code update
, replace player.x = x_ship
, player.y = y_ship
in main loop like:
while keepgoing: ... player.rect.move_ip(x_ship, y_ship) # move ship's rect player.x, player.y = player.rect.topleft # update it's x , y, if use these elsewhere item in spritegroup: # update rects asteroid objects item.rect.topleft = item.x, item.y
i use update
-altering solution, since there's chance solution cause grief when player approaches edges of play field. still, avenue consider.
as suggestion, redefine <sprite>.x
, <sprite>.y
property
s return self.rect.left
, return self.rect.top
, respectively, x , y values pinned topleft of hitbox. setter, too, even.
i'm not sure how may wish use parameters in future; it's possible eliminate them entirely, if like, , use rect
s' locators instead. food thought!
a note:
i'm assuming of sprite's x
, y
attributes refer top left point of rect
box. if point supposed somewhere else (the center, instance), may need make adjustments code, if decide use it.
Comments
Post a Comment