[PyGame]碰撞检测

Plux posted @ 2008年7月25日 21:43 in Design with tags pygame python , 6952 阅读

PyGame 1.7在pygame.sprite里为碰撞检测提供了三个函数:

 

spritecollide(sprite, group, dokill)

sprite - pygame.sprite.Sprite对象

group - pygame.sprite.Group对象(或其子类对象)

dokill - 是否杀死group中与sprite碰撞的sprite对象

返回包含所有group中与sprite相撞的sprite的列表(list)

 

groupcollide(groupa, groupb, dokilla, dokillb)

groupa - pygame.sprite.Group对象(或其子类对象)

groupb - pygame.sprite.Group对象(或其子类对象)

dokilla - 是否杀死groupa中与groupb中碰撞的sprite对象

dokillb - 是否杀死groupb中与groupa中碰撞的sprite对象

返回包含所有groupa中与groupb相撞的sprite的字典(dict)

 

spritecollideany(sprite, group)

和spritecollide(sprite, group, dokill)相似,但只是返回group中最第一个与sprite相碰撞的sprite。

上面的工作原理是检测sprite.rect是否与group中的sprite.rect是否重叠。然而,有时候也许太死板了。sprite.rect是与绘制相关的,但不一定就是sprite的范围,难道就要重写一个吗?

在PyGame,我们终于可以自定碰撞了。

pygame.sprite.spritecollide(sprite, group, dokill, collided=None)
pygame.sprite.groupcollide(group1, group2, dokill1, dokill2, collided=None)
spritecollideany(sprite, group, collided =
None)

我想大家已经注意到collided可选参数,这实际上是自定义碰撞处理函数的引用(注意,对Java开发者:python把函数也当作变量来处理,可以引用)。

我们可以编写一个函数来实现自定义碰撞功能,例如:(假设你真正的范围是sprite.base,这是一个pygame.Rect对象)

 

def myspritecollide(spritea, spriteb):
    return spritea.base.colliderect(spriteb.base)

然后,可以调用:

 

spritecollide(sprite, group, myspritecollide)

来进行检测了。其他函数中的collided参数的函数形式是一样的,必须是有两个参数的函数,其中两个参数都是pyame.sprite.Sprite对象。

现在PyGame的官方网站还没有对此进行更新,如果在1.7中享用的话,附PyGame 1.8中的源码:

 

以下内容来自PyGame 1.8的源码
def spritecollide(sprite, group, dokill, collided = None):
    """pygame.sprite.spritecollide(sprite, group, dokill) -> list
       collision detection between sprite and group

       given a sprite and a group of sprites, this will
       return a list of all the sprites that intersect
       the given sprite.
       all sprites must have a "
rect" value, which is a
       rectangle of the sprite area. if the dokill argument
       is true, the sprites that do collide will be
       automatically removed from all groups."
""
    crashed = []
    acollide = collided


    if not collided:
        # special case
        spritecollide = sprite.rect.colliderect
        if dokill:
            for s in group.sprites():
                if spritecollide(s.rect):
                    s.kill()
                    crashed.append(s)
        else:
            for s in group:
                if spritecollide(s.rect):
                    crashed.append(s)
    else:
        if dokill:
            for s in group.sprites():
                if acollide( sprite, s ):
                    s.kill()
                    crashed.append(s)
        else:
            for s in group:
                if acollide( sprite, s ):
                    crashed.append(s)
    return crashed

def groupcollide(groupa, groupb, dokilla, dokillb, collided = None):
    """pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb) -> dict
       collision detection between group and group

       given two groups, this will find the intersections
       between all sprites in each group. it returns a
       dictionary of all sprites in the first group that
       collide. the value for each item in the dictionary
       is a list of the sprites in the second group it
       collides with. the two dokill arguments control if
       the sprites from either group will be automatically
       removed from all groups."
""
    crashed = {}
    SC = spritecollide
    if not collided:
        collided = collide_rect

    if dokilla:
        for s in groupa.sprites():
            c = SC(s, groupb, dokillb, collided)
            if c:
                crashed[s] = c
                s.kill()
    else:
        for s in groupa:
            c = SC(s, groupb, dokillb, collided)
            if c:
                crashed[s] = c
    return crashed

def spritecollideany(sprite, group, collided = None):
    """pygame.sprite.spritecollideany(sprite, group) -> sprite
       finds any sprites that collide

       given a sprite and a group of sprites, this will
       return return any single sprite that collides with
       with the given sprite. If there are no collisions
       this returns None.

       if you don't need all the features of the
       spritecollide function, this function will be a
       bit quicker.

       all sprites must have a "
rect" value, which is a
       rectangle of the sprite area."
""

    if collided:
        for s in group:
            if collided( sprite, s ):
                return s
    else:
        spritecollide = sprite.rect.colliderect
        for s in group:
            if spritecollide(s.rect):
                return s

    return None

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter