Python,Pygame和碰撞检测效率

时间:2014-01-03 02:07:45

标签: python vector pygame

我正在使用自定义精灵类(不是pygame.Sprite )制作一个自上而下的侧滚动拼图游戏。

sprite collide()函数导致帧率下降(我使用cProfile)。

请帮我确定问题。

该功能以这种一般方式运作:

def collide(self):
        for tile in tiles:
            if tile.type == 'wall':
                if self.getDist(tile.rect.center) < 250:
                    if self.rect.colliderect(tile.rect):
                        return True
  1. 找到精灵和所有墙砖之间的距离矢量非常耗时
  2. 我认为只运行250像素的瓷砖会rect.colliderect()运行更快;但显然不是。
  3. 我没有包含源代码,因为我正在寻找更多关于碰撞检测效率低下问题的概念性答案。
  4. 一种可能的解决方案是为不同的tile组(即wallList,groundList)创建单独的列表,但是,我真的相信我在如何搜索tile对象列表时存在一个基本问题。

    我是StackOverflow的新手,所以,抱歉,如果我的问题结构/缺少源代码会冒犯你。

1 个答案:

答案 0 :(得分:2)

我没有检查地图中的每个图块以进行碰撞检测,而是创建了一个识别精灵当前图块的函数,然后返回其八个相邻图块。 平铺扫描方法:

def scanTiles(self):
    m = curMap.map # this is a 2d matrix filled with tile-objects 
    x = int(self.trueX) # trueX & trueY allow me to implement
    y = int(self.trueY) # a 'camera system'
    curTile = m[y // T_SIZE[1]][x // T_SIZE[0]] 
    i = curTile.index # (x, y) coordinate of tile on map

    nw = None # northwest
    n = None # north
    ne = None # northeast
    e = None # east
    se = None # southeast
    s = None # south
    sw = None # southwest
    w = None # west

    # Each if-statement uses map indices
    # to identify adjacent tiles. Ex:
    # NW  N  NE
    # W  CUR  E
    # SW  S  SE

    if i[0] > 0 and i[1] > 0:
        nw = m[i[1]-1][i[0]-1]
    if i[1] > 0:
        n = m[i[1]-1][i[0]]
    if i[0] < len(m[0])-1 and i[1] > 0:
        ne = m[i[1]-1][i[0]+1]
    if i[0] < len(m[0])-1:
        e = m[i[1]][i[0]+1]
    if i[0] < len(m[0])-1 and i[1] < len(m)-1:
        se = m[i[1]+1][i[0]+1]
    if i[1] < len(m)-1:
        s = m[i[1]+1][i[0]]
    if i[1] < len(m)-1 and i[0] > 0:
        sw = m[i[1]+1][i[0]-1]
    if i[0] > 0:
        w = m[i[1]][i[0]-1]
    return [nw, n, ne, e, se, s, sw, w]

最后,在返回相邻tile列表后,碰撞函数会检查每个tile与pygame.Rect.colliderects()的冲突。 碰撞检测方法:

def collide(self, adjTiles): # adjTiles was returned from scanTiles()
    for tile in adjTiles:
        if tile:             # if a tile actually exists, it continues
            if tile.type == 'wall': # tile type can either be 'ground' or 'wall'
                if self.rect.colliderect(tile.rect1):
                    return True # if there is a collision, it returns 'True'

这种新方法已经证明效率更高,现在已经解决了我的问题。