#本人原创,费了不少功夫计算推导公式,通过验证非常完美
#两球的位置和速度,R为半径,这里设质量一样,容易加上不同的质量和半径
def collide(loc1,loc2,sp1,sp2):
x,y=loc1
x2,y2 = loc2
dlx,dly = x-x2,y-y2
dx,dy = sp1
dx2,dy2 = sp2
dvx,dvy = dx-dx2,dy-dy2
#假如当前“碰撞过度”则回到之前的位置再求相切时的位置
if dlx**2+dly**2<R**2:
x,y = x-dx , y-dy
x2, y2 = x2-dx2, y2-dy2
dlx, dly = x-x2, y-y2
b = R**2*(dvx**2+dvy**2)-(dlx*dvy - dly*dvx)**2
#计算碰撞的时间
p = -dlx*dvx -dly*dvy+ math.sqrt(b)
p2 =-dlx*dvx -dly*dvy - math.sqrt(b)
if dvx**2 + dvy**2==0:
t=1
#因为会相切两次所以有两个解,取较小一个
else:
temp = min((abs(p),abs(p2)))
t = (temp)/(dvx**2 + dvy**2)
#碰撞时的位置
loc1 = x + t*dx , y +t*dy
loc2 = x2 + t*dx2, y2 + t*dy2
## print(math.sqrt((loc1[1]-loc2[1])**2+(loc1[0]-loc2[0])**2))
#碰撞后的速度改变,求动量交换
if dly==0:
ey=0
ex=dvx
else:
k = dlx/dly
ey=(dvy+k*dvx)/(1+k*k)
ex=k*ey
sp1 = dx -ex, dy-ey
sp2 = dx2+ex, dy2 + ey
return [loc1,loc2 ,sp1, sp2]