[PyGame]碰撞检测
PyGame 1.7在pygame.sprite里为碰撞检测提供了三个函数:
sprite - pygame.sprite.Sprite对象
group - pygame.sprite.Group对象(或其子类对象)
dokill - 是否杀死group中与sprite碰撞的sprite对象
返回包含所有group中与sprite相撞的sprite的列表(list)
groupa - pygame.sprite.Group对象(或其子类对象)
groupb - pygame.sprite.Group对象(或其子类对象)
dokilla - 是否杀死groupa中与groupb中碰撞的sprite对象
dokillb - 是否杀死groupb中与groupa中碰撞的sprite对象
返回包含所有groupa中与groupb相撞的sprite的字典(dict)
和spritecollide(sprite, group, dokill)相似,但只是返回group中最第一个与sprite相碰撞的sprite。
上面的工作原理是检测sprite.rect是否与group中的sprite.rect是否重叠。然而,有时候也许太死板了。sprite.rect是与绘制相关的,但不一定就是sprite的范围,难道就要重写一个吗?
在PyGame,我们终于可以自定碰撞了。
pygame.sprite.groupcollide(group1, group2, dokill1, dokill2, collided=None)
spritecollideany(sprite, group, collided = None)
我想大家已经注意到collided可选参数,这实际上是自定义碰撞处理函数的引用(注意,对Java开发者:python把函数也当作变量来处理,可以引用)。
我们可以编写一个函数来实现自定义碰撞功能,例如:(假设你真正的范围是sprite.base,这是一个pygame.Rect对象)
return spritea.base.colliderect(spriteb.base)
然后,可以调用:
来进行检测了。其他函数中的collided参数的函数形式是一样的,必须是有两个参数的函数,其中两个参数都是pyame.sprite.Sprite对象。
现在PyGame的官方网站还没有对此进行更新,如果在1.7中享用的话,附PyGame 1.8中的源码:
"""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