python碰撞检测解析循环依赖

时间:2014-01-27 15:55:11

标签: python collision-detection game-engine circular-dependency

我正在使用pygame开发python中的一个简单游戏(我作为一种语言相当新),似乎python真的讨厌循环依赖(虽然我知道有办法解决这个问题)。

通常对于碰撞检测,我会有一个回调函数,一旦检测到碰撞,就会为碰撞中涉及的每个对象调用。问题是,在这样做时,碰撞中涉及的每个对象都需要知道另一个对象,以便以正确的方式解决冲突,从而产生循环依赖,我宁愿避免(见下文)。 / p>

这是Enemy.py模块:

from Player include * #dependency on player

class Enemy():
    def handle_collision(other_object):
        if isinstance(other_object,Player) #this check requires the Enemy class to know about Player

这是Player.py模块:

from enemy include * #dependency on enemy

class Player():
    def handle_collision(other_object):
        if isinstance(other_object,Wall): 
            #do what we need to do to resolve a wall collision
        elif isinstance(other_object,Enemy): #this check requires that we include the Enemy class
            #do what we need to do to resolve an enemy collision    

任何有关如何处理此事的建议或见解都会很棒。

2 个答案:

答案 0 :(得分:1)

像这样的循环依赖,其中模块player.py导入模块enemy.py,反之亦然,在Python中确实相当棘手。但是(至少)有两种解决方法:

首先,您不需要导入模块来使用该模块中的类。即使不导入enemy.py模块,您也可以使用Enemy类的实例,例如在它被某些其他模块作为参数传递给handle_collision方法之后。然后,您可以通过查看例如other_object.__class__.__name__ == 'Enemy'

这样可行,但效果不是很好,会导致问题,例如Enemy的子类。

其次,你必须将每个类放在它自己的模块/文件中,因为它在例如Java中很常见。在Python中,将许多相关类放在同一个模块中是完全正常和良好的做法。 (在Python中不鼓励模块之间的循环依赖性的原因之一是因为需要它们被认为是系统设计不良的标志。)

所以我的建议是将所有“实体”类放入同一个模块中,例如: entities.py

class Entity:
    def handle_collision(self, other_object):
        pass

class Player(Entity):
    def handle_collision(self, other_object):
        if isinstance(other_object, Enemy):
            # do stuff

class Enemy(Entity):
    def handle_collision(self, other_object):
        if isinstance(other_object, Player):
            # do other stuff

请注意,循环导入 实际上可以在Python中使用,但应谨慎使用。有关详情,请查看these two个相关帖子。

答案 1 :(得分:0)

通常可以通过将导入从模块级别移动到实际需要的函数或方法来消除循环依赖性错误。

在Player.py中,尝试将from enemy include *(应该是IMPORT,而不是INCLUDE)移动到handle_collision方法中:

def handle_collision(other_object):
    from enemy import Enemy
    if isinstance(other_object,Wall): 
        #do what we need to do to resolve a wall collision
        pass
    elif isinstance(other_object,Enemy): 
        #this check requires that we include the Enemy class
        pass
        #do what we need to do to resolve an enemy collision    

此外,您应该尽量避免导入*,因为它很难看到各种导入名称的来源。