【问题标题】:Python, Pygame, and collision detection efficiencyPython、Pygame 和碰撞检测效率
【发布时间】:2014-01-03 02:07:44
【问题描述】:

我正在制作一个带有自定义精灵类(不是 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. 我没有包含源代码,因为我正在寻找更多关于我的碰撞检测效率低下问题的概念性答案。

一种可能的解决方案是为不同的图块组(即wallList、groundList)创建单独的列表,但是,我真的认为我在图块对象列表中搜索的方式存在根本问题。

我是 StackOverflow 的新手,所以,如果我的问题结构/缺少源代码冒犯了您,请见谅。

【问题讨论】:

  • 哇。代码格式确实发生了最坏的转变。对不起!
  • 在代码前添加 4 个空格以使其格式正确
  • @user3155622 我编辑了,你可以点击edit查看源代码,看看如何正确格式化。
  • @Nabla 我检查过了。这很有帮助,谢谢。
  • 我不会将此作为答案发布,因为我对游戏开发一无所知,但瓷砖地图的想法不会是,整个地图被分成固定的瓷砖坐标,所以您只需要检查目标图块(及其邻居)是否可访问,消除所有循环?

标签: python vector pygame


【解决方案1】:

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

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]

最后,在返回相邻瓦片列表后,碰撞函数会检查每个瓦片是否与 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'

事实证明,这种新方法效率更高,目前已经解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多