2

I'm making a game with Pygame and I'm trying to animate asteroids that get hit with a bullet. The animation works fine if there's just one asteroid type on the screen. I run into trouble when there's two identical asteroids on the screen. It seems that the first one on is the only one that uses my animation.

For example, say the game spawns two small asteroids, these are the exact same and I'm using glob.glob to get the 4 animation images, then I'll just use those images to create a little animation by looping over them. This works with one of the asteroids, the other will not play the animation. I'm thinking it must be because only one object can use specific images at any one time?

I'm sorry for the terrible explaination.

Here's the asteroid class I have and the call to create the animation:

class Asteroid(pygame.sprite.Sprite):
    def __init__(self, screen, size):
        pygame.sprite.Sprite.__init__(self)
        self.screen = screen
        self.size = size
        self.pos_x = random.randint(100,900)
        pos_y= random.randint(100, 700)
        self.pos_y = -pos_y
        self.vel_y = 3
        self.update_main = True
        self.animation_path = ""

        #load the image then put it above the screen, ready to drop
        if self.size == "small":
            self.asteroid_image = pygame.image.load("asteroid_small.tga")
            self.animation_path = "C:/Programming/Stupid Games/Alien Invasion/animations/asteroid_small/*.tga"
        elif self.size == "medium":
            self.asteroid_image = pygame.image.load("asteroid_medium.tga")
            self.animation_path = "C:/Programming/Stupid Games/Alien Invasion/animations/asteroid_medium/*.tga"
        elif self.size == "med_large":
            self.asteroid_image = pygame.image.load("asteroid_med_large.tga")
            self.animation_path = "C:/Programming/Stupid Games/Alien Invasion/animations/asteroid_med_large/*.tga"
        elif self.size == "small_med":
            self.asteroid_image = pygame.image.load("asteroid_small_med.png")
        elif self.size == "small_1":
            self.asteroid_image = pygame.image.load("small1.tga")
            self.animation_path = "C:/Programming/Stupid Games/Alien Invasion/animations/small/*.tga"
        else:
            self.asteroid_image = pygame.image.load("asteroid_large.tga")
            self.animation_path = "C:/Programming/Stupid Games/Alien Invasion/animations/asteroid_large/*.tga"

        #make the asteroid transparent
        corner = self.asteroid_image.get_at((0,0))
        self.asteroid_image.set_colorkey(corner, RLEACCEL)

        #randomly rotate the image
        self.new_asteroid_image = pygame.transform.rotate(self.asteroid_image, random.randint(0,340))

        self.rect = self.new_asteroid_image.get_rect()
        self.rect.x, self.rect.y = ((self.pos_x, self.pos_y))
        self.start_animate = False
        self.times = 0

        #load the asteroid animation
        self.animation = glob.glob(self.animation_path)
        self.animation.sort()
        self.animation_pos = 0
        self.animation_max = len(self.animation)-1
        self.animation_speed_init = 50
        self.animation_speed = self.animation_speed_init

    def update(self):
        #if asteroid has left the screen, place it back to the top
        if self.rect.y > 900:
            pos_y = random.randint(100,500)
            self.rect.y = -pos_y
            self.rect.x = random.randint(100,900)

        self.rect.y += self.vel_y
        self.position = self.rect.x, self.rect.y
        self.screen.blit(self.new_asteroid_image.convert(), self.position)

        if self.start_animate == True:
            self.animation_speed += 25
            if self.animation_speed > 60:
                self.update_main = False
                self.new_asteroid = pygame.image.load(self.animation[self.times])
                corner = self.new_asteroid.get_at((0,0))
                self.new_asteroid.set_colorkey(corner, RLEACCEL)
                self.new_asteroid_image = self.new_asteroid
                self.animation_speed = 0
                self.animation_pos += 1
                self.times += 1

            if self.times > self.animation_max:
                self.kill()

    def start_animation(self):
        self.start_animate = True



#create asteroids at the start of the game
if keys[K_SPACE]:
    game_over = False
    player = Space_Ship("space_ship.tga", screen)
    asteroid_small = Asteroid(screen, "small")
    asteroid_large = Asteroid(screen, "large")
    asteroid_medium = Asteroid(screen, "medium")
    asteroid_med_large = Asteroid(screen, "med_large")
    asteroid_group.add(asteroid_small, asteroid_large, asteroid_medium, asteroid_med_large)
    player_group.add(player)
    score = 0



#add asteroids after the game has started
if len(asteroid_group) < difficulty:
    random_asteroid_number = random.randint(0,5)
    if random_asteroid_number == 0:
        #large asteroid
        asteroid_large = Asteroid(screen, "large")
        asteroid_group.add(asteroid_large)
    elif random_asteroid_number == 1:
        #medium asteroid
        asteroid_medium = Asteroid(screen, "medium")
        asteroid_group.add(asteroid_medium)
    elif random_asteroid_number == 2:
        #medium large asteroid
        asteroid_med_large = Asteroid(screen, "med_large")
        asteroid_group.add(asteroid_med_large)
    elif random_asteroid_number == 3:
        #small medium asteroid
        asteroid_small_med = Asteroid(screen, "small_med")
        asteroid_group.add(asteroid_small_med)
    elif random_asteroid_number == 4:
        #small_1 asteroid
        asteroid_small_1 = Asteroid(screen, "small_1")
        asteroid_group.add(asteroid_small_1)
    else:
        #small asteroid
        asteroid_small = Asteroid(screen, "small")
        asteroid_group.add(asteroid_small)



#bullet - asteroid collision
collisions = pygame.sprite.groupcollide(bullet_group, asteroid_group, True, False)
if collisions != None:
    for i in collisions.values():
            for sprite in i:
                channel2.play(asteroid_audio)
                if sprite == asteroid_large:
                    score += 3
                    sprite.start_animation()
                elif sprite == asteroid_small_1 or sprite == asteroid_med_large or sprite == asteroid_medium or sprite == asteroid_small:
                    score += 1
                    sprite.start_animation()
                else:
                    score += 1
                    sprite.kill()
4

1 回答 1

1

尽管我不能确定,因为您调用 update 的位置没有显示,但我对它为什么会这样做有一些想法。似乎没有调用第二颗小行星的更新。这可能有几个原因。第一个原因是如果您不实施群组来更新您的小行星。基本上,如果您只调用小行星的单个实例,第二个将不会做任何事情,甚至会出现在屏幕上。如果是这种情况,您将需要创建一个组,也许是一个渲染更新组,但即使是一个列表也可以。这意味着您可以执行以下操作:

asteroids.update()

或者

for asteroid in asteroids:
    asteroid.update()

上面的两个代码假设你有某种小行星分组,称为小行星。

如果您正在实施组,另一个可能的问题是,如果第二颗小行星没有被添加到该组中。如果您在init函数中告诉它将自己添加到组中,则不会出现此问题,但是,如果您在此函数之外调用它,则在创建第二个小行星时可能不会这样做。要解决这个问题,只需将添加小行星的部分移动到一个组中,该组将更新为小行星的init函数。

于 2013-11-24T03:31:41.947 回答