Python 球体物理问题
我正在尝试让一个球在一个盒子里正确地反弹,特别是处理特定角度的角落和正面碰到角落的情况。不过我遇到了问题,因为我的球总是会跑出盒子。我有一个函数可以判断我的球是否出盒子,并且它能处理角落和墙壁。代码如下:
if ((self._x > self._Grid.getWidth()) or (self._x < 0)):
print("RandomNode:outside paramaters: x! self._x = %s , self._velx = %s" % (self._x , self._velx))
if ((self._y > self._Grid.getLength()) or (self._y < 0)):
print("RandomNode:outside paramaters: y!")
if ((self._velx + self._x) > self._Grid.getWidth()):
diff = self._Grid.getWidth()-self._x
self._velx *= -1
if (diff == 0):
self._x -= self._velx
else:
self._x+= diff
tampered = True
#print("eqn1: self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if (self._velx + self._x < 0):
diff = self._x
self._velx *= -1
if (diff == 0):
self._x += self._velx
else:
self._x-= diff
tampered = True
#print("eqn2: self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if ((self._vely + self._y) > self._Grid.getLength()):
diff = self._Grid.getLength()-self._y
self._vely *= -1
if (diff == 0):
self._y -= self._vely
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn31:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx - diff)
self._y += self._vely
#print("eqn32:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn33:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._y+= diff
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn31:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx - diff)
self._y += self._vely
#print("eqn32:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn33:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if (self._vely + self._y < 0):
diff = self._y
self._vely *= -1
if (diff == 0):
self._y += self._vely
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn41:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx + diff)
self._y += self._vely
#print("eqn42:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn43:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._y-= diff
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn41:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx + diff)
self._y += self._vely
#print("eqn42:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn43:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
return tampered
我不知道为什么它不工作。x 和 y 显然是球的坐标。Velx 和 Vely 是它在 x 轴和 y 轴上的速度。Tampered 是一个布尔值,用来防止球正常移动,只能在检查的范围内移动。
我的问题是,这段代码有什么问题?或者……网上有没有用 Python 写的模板,或者你用过的代码,能做到我想要处理的事情?请随意修改代码,只要告诉我一声就行。任何已经解决的链接也非常欢迎。谢谢。
2 个回答
1
你不需要自己去重新发明这个轮子,因为pymunk已经帮你做得很好了。;)
7
重写这段代码吧。它对你想解决的简单问题来说,实在是太复杂了。
首先,一个球的二维运动其实可以看作是两个一维的问题。你可以把X轴和Y轴完全分开来处理。比如,球撞到一个角落,其实就等于先撞到X轴的墙,再撞到Y轴的墙。撞到X轴的墙只需要把X方向的速度反向(如果你想模拟能量损失,也可以考虑这一点)。撞到Y轴的墙则是反向Y方向的速度。
其次,因为处理X和Y的方式非常相似,可以把这部分代码提取成一个方法。
def handle_axis_movement(location, velocity):
"returns updated location and velocity"
...
self.x, self.vel_x = handle_axis_movement(self.x, self.vel_x)
self.y, self.vel_y = handle_axis_movement(self.y, self.vel_y)
这样可以把代码量(和可能出现的错误)减少一半。
第三,你不需要把diff==0和diff<0这两种情况分开处理。这两种情况都意味着球撞到了墙,应该反向速度。然后你还需要调整位置,以确保球没有穿过墙。
location += velocity
if location > max_bound:
location = max_bound - (location - max_bound)
velocity *= -1
if location < min_bound:
location = min_bound - (location - min_bound)
velocity *= -1