初学者的2D碰撞检测问题
我之前上过一门计算机科学的入门课程,最近决定尝试制作一个游戏。不过,我在碰撞检测方面遇到了问题。我的想法是移动一个物体,如果发生碰撞,就把它往回移动,直到不再发生碰撞。以下是我的代码:
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
*我尝试了几种不同的值来改变玩家后退的步幅,包括整数和浮点数。我以为如果用一个比较大的浮点数,物体每次只会移动一个像素。
但是当我运行程序时,玩家的角色在碰到墙壁时会在大约5个像素的范围内快速抖动。如果我松开方向键,角色就会永久卡在墙里。我在想,角色为什么一开始会在墙里,因为在我把角色显示到屏幕上之前,它应该已经移动到墙外了。
我想知道,是我的方法有问题,还是在执行过程中出现了问题?
1 个回答
1
看起来你是在更新位置之前就设置了碰撞盒。这个问题的解决办法似乎很简单。
找到:
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)
其他建议:你应该在移动之前检查一下目标位置,如果那里已经被占据了,就不要移动。这部分代码没有经过测试,所以请把它当作示例代码来理解:
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