初学者的2D碰撞检测问题

时间:2010-07-29 23:06:07

标签: python pygame

我参加了计算机科学的入门课程,但不久之后我决定尝试制作游戏。我遇到了碰撞检测问题。我的想法是移动一个物体,如果发生碰撞,将其移回原来的状态,直到不再发生碰撞。这是我的代码:

class Player(object):  
    ...  
    def move(self):
        #at this point, velocity = some linear combination of (5, 0)and (0, 5)
        #gPos and velocity are types Vector2    
        self.hitBox = Rect(self.gPos.x, self.gPos.y, 40, 40)
        self.gPos += self.velocity  
        while CheckCollisions(self):  
            self.gPos -= self.velocity/n #see footnote  
            self.hitBox = Rect(self.gPos.x, self.gPos.y, 40, 40)
    ...
def CheckCollisions(obj):
    #archList holds all 'architecture' objects, solid == True means you can't walk        
    #through it. colliderect checks to see if the rectangles are overlapping
    for i in archList:
        if i.solid:
            if i.hitBox.colliderect(obj.hitBox):
                return True
    return False

*我为n(整数和浮点数)替换了几个不同的值,以更改玩家向后移动的增量。我想通过尝试一个大浮点数,它一次只能移动一个像素

当我运行程序时,每当我碰到一堵墙时,玩家的精灵会在大约5个像素的范围内快速振动。如果我放开箭头键,精灵将永久卡在墙上。我想知道为什么sprite首先在墙内,因为当我将精灵blit到屏幕时,它应该被移到墙外。

我的方法有问题,还是我的执行中存在问题?

1 个答案:

答案 0 :(得分:1)

看起来你在更新位置之前设置了hitbox。修复似乎很简单。

查找

    self.hitBox = Rect(self.gPos.x, self.gPos.y, 40, 40)
    self.gPos += self.velocity  

替换:

    self.gPos += self.velocity  
    self.hitBox = Rect(self.gPos.x, self.gPos.y, 40, 40)

其他建议:您应该做的是在移动之前检查位置,如果它被占用,请不要移动。这是未经测试的,所以请使用它作为psuedocode旨在说明要点:

class Player(object):  
    ...  
    def move(self):
        #at this point, velocity = some linear combination of (5, 0)and (5, 5)
        #gPos and velocity are types Vector2    
        selfCopy = self
        selfCopy.gPos += self.velocity
        selfCopy.hitBox = Rect(selfCopy.gPos.x, selfCopy.gPos.y, 40, 40)
        if not CheckCollisions(selfCopy)    
            self.gPos += self.velocity
    ...
def CheckCollisions(obj):
    #archList holds all 'architecture' objects, solid == True means you can't walk        
    #through it. colliderect checks to see if the rectangles are overlapping
    for i in archList:
        if i.solid:
            if i.hitBox.colliderect(obj.hitBox):
                return True
    return False