弹性碰撞模拟



我正试图用一维牛顿方程模拟弹性碰撞(https://en.wikipedia.org/wiki/Elastic_collision)与pygame。问题是,即使我转录了求解的方程来改变两个物体的速度,它也不起作用(或者可能代码有问题(。这是代码:

import pygame
pygame.init()
clock = pygame.time.Clock()
screenx,screeny = 1000,800
screen = pygame.display.set_mode([screenx,screeny])
pygame.display.set_caption("Elastic collision")
# Rectangles
small= pygame.Rect(70,433,17,17)
big = pygame.Rect(220,400,50,50)
# Masses
m_small = 1
m_big = 1
# Velocity
small_vel = 0
big_vel = -1
count = 0
start = False
sumM = m_small+m_big
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
run = False
screen.fill((0,0,0))
big.x += big_vel
small.x+=small_vel
# If collision between small and big...
if big.x==small.x+17:
start=True
if start == True:
# ...change velocity of small and big,
# using the elastic collision equation at each collision
if small.x==0 or big.bottomleft<=small.bottomright:
small_vel = (m_small-m_big)/sumM*small_vel+2*m_big/sumM*big_vel
big_vel = (m_big-m_small)/sumM*big_vel+2*m_small/sumM*small_vel
count += 1
print("Small vel:", small_vel, " Big vel:", big_vel)
# Draw the rectangles
pygame.draw.rect(screen, (255,255,255), small)
pygame.draw.rect(screen, (255,255,255), big)
pygame.draw.line(screen, (255,0,0), (0,450), (1000,450),width=1)
pygame.display.flip()
clock.tick(60)
pygame.display.update()

由于两个质量相等,碰撞后,移动的一个应该停止,另一个应该开始移动。这并没有发生。我还试着在if状态下写small_vel=-1big_vel=0,其中速度应该由于碰撞而改变,它工作得很好。

在我看来,问题是由以下两行引起的:

small_vel = (m_small-m_big)/sumM*small_vel+2*m_big/sumM*big_vel
big_vel = (m_big-m_small)/sumM*big_vel+2*m_small/sumM*small_vel

这里big_vel是根据small_vel的新值更新的,这不是我们想要的。将small_vel的新值保存在临时变量中,并在分配给big_vel后将其恢复似乎可以解决问题:

tmp_small_vel = (m_small-m_big)/sumM*small_vel+2*m_big/sumM*big_vel
big_vel = (m_big-m_small)/sumM*big_vel+2*m_small/sumM*small_vel
small_vel = tmp_small_vel

老实说,我还没有看过数学方面的东西,我不确定这是否正是你想要的,但结果看起来至少像维基百科页面的视频。

顺便说一句,你应该看看这篇文章:我得到一个pygame.error:每次我运行程序来修复关闭窗口时出现的代码错误时,视频系统未初始化错误(引发的异常不相同,但问题的来源和解决方案相同(。

最新更新