【问题标题】:Trouble using the same image for multiple objects对多个对象使用同一图像时遇到问题
【发布时间】:2013-01-04 20:29:05
【问题描述】:

我正在使用 Pygame 制作游戏,并尝试为被子弹击中的小行星制作动画。如果屏幕上只有一种小行星类型,则动画效果很好。当屏幕上有两个相同的小行星时,我遇到了麻烦。似乎第一个是唯一使用我的动画的。

例如,假设游戏生成了两个小行星,它们完全相同,我使用 glob.glob 来获取 4 个动画图像,然后我将使用这些图像通过循环创建一个小动画他们。这适用于其中一颗小行星,另一颗不会播放动画。我想这一定是因为任何时候只有一个对象可以使用特定的图像?

对于糟糕的解释,我深表歉意。

这是我拥有的小行星类和创建动画的调用:

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()

【问题讨论】:

  • 您在代码中的何处创建新的 Asteroid 对象?
  • 抱歉,我现在已经添加了。
  • 我不确定这是否是问题,但你应该在游戏开始时加载所有图片,并在创建时相应地使用它们,而不是在游戏期间从硬盘加载它们
  • 您使用的是sprite sheet 吗?您可以加载一次动画,为所有小行星实例重新使用表面。

标签: python animation python-3.x pygame glob


【解决方案1】:

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

asteroids.update()

for asteroid in asteroids:
    asteroid.update()

以上两个代码假设您有某种小行星分组,称为小行星。

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

【讨论】:

    猜你喜欢
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多