why collide_mask is significantly slower than collide_rect in pygame?

huangapple go评论57阅读模式
英文:

why collide_mask is significantly slower than collide_rect in pygame?

问题

I have this piece of code here to add collision to my pygame game:

        collidable_sprites = self.tiles["ground"].sprites.Sprites() + self.tiles["fg_machines"].sprites.sprites()
        for sprite in collidable_sprites:
            if sprite.rect.colliderect(player.rect):

And this is working smoothly at 60 fps (my fps for clock.tick).

But, of course, that collision detection is very rough unless your game is just rectangles - which is not true in my case.

So, I switched to mask collision:

        collidable_sprites = self.tiles["ground"].sprites.sprites() + self.tiles["fg_machines"].sprites.sprites()
        for sprite in collidable_sprites:
            if pygame.sprite.collide_mask(player, sprite):

Which works better, but drops my fps to 20.

I understand that this is far harder to calculate, but is this a good alternative to do it with a 3x frame drop?

英文:

i have this piece of code here to add collision to my pygame game:

        collidable_sprites = self.tiles["ground"].sprites. Sprites() + self.tiles["fg_machines"].sprites.sprites()
        for sprite in collidable_sprites:
            if sprite.rect.colliderect(player.rect):

and this is working smooth at 60 fps (my fps for clock.tick)
but, of course, that collision detection is very rough unless your game is just rectangles - which is not true in my case.
so, i switched to mask collision:

        collidable_sprites = self.tiles["ground"].sprites.sprites() + self.tiles["fg_machines"].sprites.sprites()
        for sprite in collidable_sprites:
            if pygame.sprite.collide_mask(player, sprite):

which works better, but drops my fps to 20.
i understanding that this far harder to calculate,
but is this a good alternative to do it with 3x frame drop?

答案1

得分: 3

pygame.Rect.colliderect 执行一个边界框测试,pygame.sprite.collide_rect 基于 pygame.sprite.Sprite.rect 属性执行一个碰撞测试。

pygame.sprite.collide_mask 基于 pygame.sprite.Sprite.rect.mask 属性执行一个碰撞测试。如果精灵没有 .mask 属性,那么必须即时创建掩码。

collide_maskcollide_rect 慢,因为它执行一个基于重叠像素的碰撞测试,而 collide_rect 只执行一个轴对齐的边界框测试。边界框测试可以通过单个条件执行。另一方面,掩码测试必须首先找到矩形的重叠区域,然后找到重叠的像素,因此取决于两个区域或掩码的重叠区域的大小。

基本上,collide_mask 在找到矩形的交集后执行的操作与 collide_rect 相同,但之后它必须迭代掩码位以检测是否设置了重叠位。

要改善代码性能的第一件事是预先使用 pygame.mask.from_surface 创建掩码,示例如下:

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.Rect.colliderect performs a bounding box test and pygame.sprite.collide_rect performs a collision test based on the .rect attributes of the pygame.sprite.Sprite.

pygame.sprite.collide_mask performs a collision test based on the .rect and .mask attributes of the pygame.sprite.Sprite. If the sprites does not have a .mask attribute, the masks must even be created on the fly.

collide_mask is slower than collide_rect because it performs a collision test based on overlapping pixels, while collide_rect only performs an axis-aligned bounding box test. A bounding box test can be performed with a single condition. The mask test, on the other hand, must first find the overlapping area of the rectangles and then the overlapping pixels, and therefore depends on the size of the overlapping area of the two areas respectively masks.
Basically collide_mask does what collide_rect does to find the intersection of the rectangles, but after that it has to iterate through the mask bits to detect if overlapping bits are set.

The first thing you should try to do to improve the performance of your code is to create the masks in advance with pygame.mask.from_surface. e.g.:

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)

huangapple
  • 本文由 发表于 2023年5月7日 22:22:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194506.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定