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 rects (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 propertys 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 rects' 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

Popular posts from this blog

java - Plugin org.apache.maven.plugins:maven-install-plugin:2.4 or one of its dependencies could not be resolved -

Round ImageView Android -

How can I utilize Yahoo Weather API in android -