使用python模拟二维弹性碰撞
Using python to simulate 2D elastic collisions
我在Python3中写了一个脚本来模拟二维弹性碰撞。
我不知道我做错了什么,因为当我 运行 它时,球似乎相互粘在一起,有时会出现故障成为一个球。另外,当一个球碰到屏幕的任何边缘时,它会弹开,但是当另一个球粘在它上面时,它会导致其中一个球脱离屏幕。
Eqautions that I used
代码片段:
class Particle(Sprite):
def __init__(self, image):
super(Particle, self).__init__(image)
self.Vxi, self.Vyi = random.randint(-3, 3), random.randint(-3, 3)
self.mass = random.randint(1, 100) / 1000
self.schedule_interval(self.update, 1/60)
def update(self, dt):
self.xpos, self.ypos = self.position
if self.xpos <= self.width/2 or self.xpos >= scr_width - self.width/2:
self.Vxi *= -1
if self.ypos <= self.width/2 or self.ypos >= scr_height - self.height/2:
self.Vyi *= -1
for particle in director.scene.children[0][1].particles:
particle_xpos, particle_ypos = particle.position
if abs(self.xpos - particle_xpos) <= self.width/2 + particle.width/2:
if abs(self.ypos - particle_ypos) <= self.height/2 + particle.height/2:
xmomentum = (particle.mass * particle.Vxi) + (self.mass * self.Vxi)
ymomentum = (particle.mass * particle.Vyi) + (self.mass * self.Vyi)
Vxf = (xmomentum - particle.mass * (self.Vxi - particle.Vxi)) / (particle.mass + self.mass)
Vyf = (ymomentum - particle.mass * (self.Vyi - particle.Vyi)) / (particle.mass + self.mass)
self.Vxi = Vxf
self.Vyi = Vyf
self.xpos += self.Vxi
self.ypos += self.Vyi
self.position = self.xpos, self.ypos
我想你忘了更新碰撞时另一个粒子的速度。
之前
self.Vxi = Vxf
self.Vyi = Vyf
应该还有
particle.Vxi = Vxf + (self.Vxi - particle.Vxi)
particle.Vyi = Vyf + (self.Vyi - particle.Vyi)
风格方面,我认为变量可以命名得更好。粒子对象不应具有名为 Vxi
或 Vxf
的属性。就物理粒子而言,它只有一种速度。 initial/final 速度的概念与数值模拟有关,粒子 class 的属性不应对其进行建模。在您当前的代码中,self
的 "final" 速度更新为其初始速度,这可能会造成混淆。
初速度(Vxi
,Vyi
)应该取自self.Vx
和self.Vy
开头的update
。最后,Vfx
和Vfy
应该更新为self.Vx
和self.Vy
。
此外,最好在局部变量中指明它是哪个粒子,例如V1_x_initial
、V2_x_initial
等
我在Python3中写了一个脚本来模拟二维弹性碰撞。 我不知道我做错了什么,因为当我 运行 它时,球似乎相互粘在一起,有时会出现故障成为一个球。另外,当一个球碰到屏幕的任何边缘时,它会弹开,但是当另一个球粘在它上面时,它会导致其中一个球脱离屏幕。
Eqautions that I used
代码片段:
class Particle(Sprite):
def __init__(self, image):
super(Particle, self).__init__(image)
self.Vxi, self.Vyi = random.randint(-3, 3), random.randint(-3, 3)
self.mass = random.randint(1, 100) / 1000
self.schedule_interval(self.update, 1/60)
def update(self, dt):
self.xpos, self.ypos = self.position
if self.xpos <= self.width/2 or self.xpos >= scr_width - self.width/2:
self.Vxi *= -1
if self.ypos <= self.width/2 or self.ypos >= scr_height - self.height/2:
self.Vyi *= -1
for particle in director.scene.children[0][1].particles:
particle_xpos, particle_ypos = particle.position
if abs(self.xpos - particle_xpos) <= self.width/2 + particle.width/2:
if abs(self.ypos - particle_ypos) <= self.height/2 + particle.height/2:
xmomentum = (particle.mass * particle.Vxi) + (self.mass * self.Vxi)
ymomentum = (particle.mass * particle.Vyi) + (self.mass * self.Vyi)
Vxf = (xmomentum - particle.mass * (self.Vxi - particle.Vxi)) / (particle.mass + self.mass)
Vyf = (ymomentum - particle.mass * (self.Vyi - particle.Vyi)) / (particle.mass + self.mass)
self.Vxi = Vxf
self.Vyi = Vyf
self.xpos += self.Vxi
self.ypos += self.Vyi
self.position = self.xpos, self.ypos
我想你忘了更新碰撞时另一个粒子的速度。
之前
self.Vxi = Vxf
self.Vyi = Vyf
应该还有
particle.Vxi = Vxf + (self.Vxi - particle.Vxi)
particle.Vyi = Vyf + (self.Vyi - particle.Vyi)
风格方面,我认为变量可以命名得更好。粒子对象不应具有名为 Vxi
或 Vxf
的属性。就物理粒子而言,它只有一种速度。 initial/final 速度的概念与数值模拟有关,粒子 class 的属性不应对其进行建模。在您当前的代码中,self
的 "final" 速度更新为其初始速度,这可能会造成混淆。
初速度(Vxi
,Vyi
)应该取自self.Vx
和self.Vy
开头的update
。最后,Vfx
和Vfy
应该更新为self.Vx
和self.Vy
。
此外,最好在局部变量中指明它是哪个粒子,例如V1_x_initial
、V2_x_initial
等