python - 我如何检测pygame中的碰撞?

标签 python pygame collision-detection pygame-surface pygame2

我已经使用下面的类制作了一个子弹列表和一个 Sprite 列表。如何检测子弹是否与 sprite 发生碰撞,然后删除该 sprite 和子弹?

#Define the sprite class
class Sprite:

    def __init__(self,x,y, name):
        self.x=x

        self.y=y

        self.image = pygame.image.load(name)

        self.rect = self.image.get_rect()

    def render(self):
        window.blit(self.image, (self.x,self.y))


# Define the bullet class to create bullets          
class Bullet:

    def __init__(self,x,y):
        self.x = x + 23
        self.y = y
        self.bullet = pygame.image.load("user_bullet.BMP")
        self.rect = self.bullet.get_rect()

    def render(self):
        window.blit(self.bullet, (self.x, self.y))

最佳答案

在 PyGame 中,碰撞检测是使用 pygame.Rect 完成的对象。 Rect 对象提供了多种方法来检测对象之间的碰撞。即使是矩形和圆形物体(例如桨和球)之间的碰撞也可以通过两个矩形物体(桨和球的边界矩形)之间的碰撞来检测。

一些例子:

  • pygame.Rect.collidepoint :

    Test if a point is inside a rectangle

    repl.it/@Rabbid76/PyGame-collidepoint

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(100, 100)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        point = pygame.mouse.get_pos()
        collide = rect.collidepoint(point)
        color = (255, 0, 0) if collide else (255, 255, 255)
    
        window.fill(0)
        pygame.draw.rect(window, color, rect)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    
  • pygame.Rect.colliderect

    Test if two rectangles overlap

    另见 How to detect collisions between two rectangular objects or images in pygame

    repl.it/@Rabbid76/PyGame-colliderect

    colliderect

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    rect1 = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
    rect2 = pygame.Rect(0, 0, 75, 75)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        rect2.center = pygame.mouse.get_pos()
        collide = rect1.colliderect(rect2)
        color = (255, 0, 0) if collide else (255, 255, 255)
    
        window.fill(0)
        pygame.draw.rect(window, color, rect1)
        pygame.draw.rect(window, (0, 255, 0), rect2, 6, 1)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

此外,pygame.Rect.collidelistpygame.Rect.collidelistall可用于矩形与矩形列表之间的碰撞测试。 pygame.Rect.collidedictpygame.Rect.collidedictall可用于矩形与矩形字典的碰撞测试。

碰撞pygame.sprite.Spritepygame.sprite.Group对象,可以通过 pygame.sprite.spritecollide() 检测到, pygame.sprite.groupcollide()pygame.sprite.spritecollideany() .使用这些方法时,可以通过 collided 参数指定碰撞检测算法:

The collided argument is a callback function used to calculate if two sprites are colliding.

可能的碰撞 可调用项是 collide_rect , collide_rect_ratio , collide_circle , collide_circle_ratio , collide_mask

一些例子:

  • pygame.sprite.spritecollide()

    repl.it/@Rabbid76/PyGame-spritecollide

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    
    sprite1 = pygame.sprite.Sprite()
    sprite1.image = pygame.Surface((75, 75))
    sprite1.image.fill((255, 0, 0))
    sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
    sprite2 = pygame.sprite.Sprite()
    sprite2.image = pygame.Surface((75, 75))
    sprite2.image.fill((0, 255, 0))
    sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
    
    all_group = pygame.sprite.Group([sprite2, sprite1])
    test_group = pygame.sprite.Group(sprite2)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        sprite1.rect.center = pygame.mouse.get_pos()
        collide = pygame.sprite.spritecollide(sprite1, test_group, False)
    
        window.fill(0)
        all_group.draw(window)
        for s in collide:
            pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

有关与面具的碰撞,请参阅 How can I make a collision mask?Pygame mask collision

另见 Collision and Intersection

  • pygame.sprite.spritecollide()/collide_circle

    repl.it/@Rabbid76/PyGame-spritecollidecollidecircle

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    
    sprite1 = pygame.sprite.Sprite()
    sprite1.image = pygame.Surface((80, 80), pygame.SRCALPHA)
    pygame.draw.circle(sprite1.image, (255, 0, 0), (40, 40), 40)
    sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(40, 40)
    sprite2 = pygame.sprite.Sprite()
    sprite2.image = pygame.Surface((80, 89), pygame.SRCALPHA)
    pygame.draw.circle(sprite2.image, (0, 255, 0), (40, 40), 40)
    sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)
    
    all_group = pygame.sprite.Group([sprite2, sprite1])
    test_group = pygame.sprite.Group(sprite2)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        sprite1.rect.center = pygame.mouse.get_pos()
        collide = pygame.sprite.spritecollide(sprite1, test_group, False, pygame.sprite.collide_circle)
    
        window.fill(0)
        all_group.draw(window)
        for s in collide:
            pygame.draw.circle(window, (255, 255, 255), s.rect.center, s.rect.width // 2, 5)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

这对您的代码意味着什么?

pygame.Surface.get_rect.get_rect()返回一个具有 Surface 对象大小的矩形,该矩形始终从 (0, 0) 开始,因为 Surface 对象没有位置。矩形的位置可以由关键字参数指定。例如,矩形的中心可以用关键字参数 center 指定。这些关键字参数应用于 pygame.Rect 的属性在返回之前(参见 pygame.Rect 以获取关键字参数列表)。
参见 * Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?

您根本不需要SpriteBulletxy 属性。使用 rect 属性的位置代替:

#Define the sprite class
class Sprite:
    def __init__(self, x, y, name):
        self.image = pygame.image.load(name)
        self.rect = self.image.get_rect(topleft = (x, y))

    def render(self):
        window.blit(self.image, self.rect)

# Define the bullet class to create bullets          
class Bullet:
    def __init__(self, x, y):
        self.bullet = pygame.image.load("user_bullet.BMP")
        self.rect = self.bullet.get_rect(topleft = (x + 23, y))

    def render(self):
        window.blit(self.bullet, self.rect)

使用pygame.Rect.colliderect()检测 Sprite Bullet 实例之间的碰撞。
参见 How to detect collisions between two rectangular objects or images in pygame :

my_sprite = Sprite(sx, sy, name)
my_bullet = Bullet(by, by)
while True:
    # [...]

    if my_sprite.rect.colliderect(my_bullet.rect):
        printe("hit")

关于python - 我如何检测pygame中的碰撞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29640685/

相关文章:

python - 在 Python 中将字符串转换为列表

python - 在 Python 和 __init__.py 中导入模块

python - 如何放置这些船舶图像?

c++ - 如何在 SFML 中检查二维 map 上的碰撞?

javascript - 如何在矩形外最小化一个圆圈?

android - 使用 appium-python-client 在 android 中缩放 Action

python - 如何理解 Python 中 `None or False` 、 `False or None` 、 `None and False` 、 `False and None` 的结果?

python-3.x - 如何将一个矩形传递给 pygame.display.update() 以更新窗口的特定区域?

python - Pygame - 有没有办法只在掩码中进行 blit 或更新

python - Pygame 中蒙版和发射光束的重叠 [AI 汽车模型视觉]