无法弄清楚如何检查两个精灵之间的掩码碰撞

Can't figure out how to check mask collision between two sprites

我在同一组中有两个不同的精灵,变量 'player' 和 'ground'。它们都是独立的 类,表面有遮罩。这条线在他们的类.

self.mask = pygame.mask.from_surface(self.surface)

它们表面使用的图像上使用了 'convert_alpha()',因此它们的一部分是透明的,蒙版应该对它们有效。地面是几个平台,我想检查碰撞,这样我就可以让玩家保持在地面上,当他们不在非透明部分时让他们掉下来。

if pygame.sprite.collide_mask(player,ground):
        print("collision")
else:
        print("nope")

这会打印出“不”,即使玩家精灵正在掉落到彩色地面精灵像素所在的位置。所以 'collide_mask()' 的文档说它 returns 在没有碰撞时是“NoneType”。所以我尝试了这个。

if pygame.sprite.collide_mask(player,ground)!= NoneType:
        print("collision")

无论玩家身在何处,都会打印“碰撞”(我为玩家设置了跳跃、左右移动)。我昨天问了一个关于碰撞的问题,但没有得到任何帮助。我被告知要压缩我在问题中提交的代码,所以希望我在没有发布所有 90 行的情况下解释得足够好。我在这里检查了很多其他问题,它们似乎都有些不同,所以我很困惑(而且相当新)。 强调两个精灵在同一组中,因此我无法让 spritecollide() 工作。

精灵不仅需要mask属性,还需要rect属性。 mask 定义位掩码,rect 指定精灵在屏幕上的位置。见 pygame.sprite.collide_mask:

Tests for collision between two sprites, by testing if their bitmasks overla. If the sprites have a mask attribute, it is used as the mask, otherwise a mask is created from the sprite's image. Sprites must have a rect attribute; the mask attribute is optional.

如果在 pygame.sprite.Group 中使用精灵,则每个精灵都应具有 imagerect 属性。 pygame.sprite.Group.draw() and pygame.sprite.Group.update()pygame.sprite.Group.

提供的方法

后者委托给包含pygame.sprite.Sprites — you have to implement the method. See pygame.sprite.Group.update()update方法:

Calls the update() method on all Sprites in the Group. [...]

前者使用包含的 pygame.sprite.Spriteimagerect 属性来绘制对象 - 你必须确保 pygame.sprite.Sprite 具有所需的属性。见 pygame.sprite.Group.draw():

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]


最小示例

import os, pygame
os.chdir(os.path.dirname(os.path.abspath(__file__)))

class SpriteObject(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.mask = pygame.mask.from_surface(self.image)

pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((400, 400))
size = window.get_size()

object_surf = pygame.image.load('AirPlane.png').convert_alpha()
obstacle_surf = pygame.image.load('Rocket').convert_alpha()

moving_object = SpriteObject(0, 0, object_surf)
obstacle = SpriteObject(size[0] // 2, size[1] // 2, obstacle_surf)
all_sprites = pygame.sprite.Group([moving_object, obstacle])

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    moving_object.rect.center = pygame.mouse.get_pos()
    collide = pygame.sprite.collide_mask(moving_object, obstacle)
    
    window.fill((255, 0, 0) if collide else (0, 0, 64))
    all_sprites.draw(window)
    pygame.display.update()

pygame.quit()
exit()