【问题标题】:pygame/sprites: mob collisionpygame/sprites:暴民碰撞
【发布时间】:2020-06-30 11:38:31
【问题描述】:

您好,我最近开始接触 pygame 库并制作一些小项目。我正在制作一个非常简单的游戏,你作为玩家必须躲避敌人。但是,我想在它们相互碰撞时删除它们。我想到了下面的代码,但是,它只删除了其中一个小怪。生物在 all_sprites 和 mob_sprites 中。我是 sprites 和 pygame 的新手,所以这里可能有一个愚蠢的错误,希望有人可以帮助我。

# check mob collision
for mob in mobs:
    temp_sprites.add(mob)
    mobs.remove(mob)
    collision = pg.sprite.groupcollide(temp_sprites, mobs, True, True)
    for col in collision:
        # score is just for the game
        score += col.size
    else:
        mobs.add(mob)
        all_sprites.add(mob)

    temp_sprites.remove(mob)

【问题讨论】:

    标签: python pygame sprite


    【解决方案1】:

    您的第一个问题是您使用了for...else 循环;如果你不break for 循环以防发生冲突,else 部分将被执行,从而重新添加精灵。

    您的代码的第二个问题是,虽然 groupcollide 将正确地从它们的组中删除精灵,但它们将被读取,因为它们仍然存储在您使用 for 循环迭代的列表中(迭代一个精灵组每次都会创建一个新列表)。

    因此,您可以使用以下方式修复您的代码:

        for mob in mobs.sprites():
            
            if not mob.groups():
                # mob was already removed by a previous iteration of this loop
                continue
    
            temp_sprites.add(mob)
            mobs.remove(mob)
            collision = pygame.sprite.groupcollide(temp_sprites, mobs, True, True)
            for col in collision:
                # score is just for the game
                score += col.size
                break
            else:
                mobs.add(mob)
                all_sprites.add(mob)
    
            temp_sprites.remove(mob)
    

    但我建议改为在精灵的update 方法中处理冲突。

    def update(self):
        # whatever
        if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
            self.kill()
    

    其中self.mobs 是对mobs 组的引用,collide_rect_not_selfpygame.sprite.collide_rect 的简单包装器:

    def collide_rect_not_self(a, b):
        if a != b:
            return pygame.sprite.collide_rect(a, b)
    

    这是一个完整的例子:

    import random
    import pygame
    
    def collide_rect_not_self(a, b):
        if a != b:
            return pygame.sprite.collide_rect(a, b)
    
    class Actor(pygame.sprite.Sprite):
        def __init__(self, pos, mobs, static, *grps):
            super().__init__(mobs, *grps)
            self.image = pygame.Surface((40, 40))
            self.rect = self.image.get_rect(center=pos)
            self.pos = pygame.Vector2(*pos)
            self.vel = pygame.Vector2(random.randint(0, 10), random.randint(0, 10)) if not static else pygame.Vector2(0, 0)
            self.mobs = mobs
    
        def update(self):
            self.pos += self.vel
            if not pygame.display.get_surface().get_rect().contains(self.rect):
                self.vel *= -1
                self.rect.clamp_ip(pygame.display.get_surface().get_rect())
                self.pos = self.rect.center
            self.rect.center = self.pos
            if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
                self.kill()
    
    def main():
        pygame.init()
        clock = pygame.time.Clock()
        screen = pygame.display.set_mode((800, 600))
        mobs = pygame.sprite.Group()
        all_sprites = pygame.sprite.Group()
        while True:
    
            for event in pygame.event.get():
                pos = pygame.mouse.get_pos()
                if event.type == pygame.QUIT:
                    return
    
                if event.type == pygame.MOUSEBUTTONDOWN:
                    Actor(event.pos, mobs, event.button == 1, all_sprites)
                        
            screen.fill((255, 255, 255))
            all_sprites.update()
            all_sprites.draw(screen)
            clock.tick(30)
            
                   
            pygame.display.flip()
    main()
    

    使用鼠标左键放置静态矩形,使用鼠标左键放置移动矩形。

    【讨论】:

      【解决方案2】:

      如果你想销毁一个精灵,那么调用pygame.sprite.Sprite.kill()就足够了:

      mob.kill()
      

      kill 将 Sprite 从包含它的所有组中删除。

      如果你想检测一个精灵是否与循环中的任何其他精灵发生碰撞,那么我建议使用 2 个嵌套循环和pygame.sprite.collide_rect()

      例如:

      for mob1 in mobs:
          for mob2 in mobs:
              
              if mob1 != mob2 and pg.sprite.collide_rect(mob1, mob2):
                  mob1.kill()
                  mob2.kill()
      
                  # score is just for the game
                  score += col.size
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-22
        • 2020-05-21
        • 1970-01-01
        相关资源
        最近更新 更多