如何在Tkinter中实现两个小球的碰撞检测与相互反弹效果?
问题原因
你原有代码中两球碰撞的判定逻辑错误:仅判断x或y坐标完全相等,该条件触发概率极低,同时没有考虑小球的实际尺寸,不符合圆形物体的碰撞判定规则。
修复步骤
- 首先删除4个边界反弹判断中错误的碰撞触发条件,也就是所有
or x == x1、or y == y1、or x1 == x、or y1 == y的冗余逻辑 - 新增独立的两球碰撞判定:计算两个小球的圆心坐标,当圆心距离小于等于两球半径之和(即小球直径)时判定为碰撞
- 碰撞后直接交换两个小球的x、y方向速度即可实现弹性反弹(两球大小、质量一致时该逻辑成立,若要更精准的角度反弹可按碰撞法线计算速度分量)
修复后完整代码
from tkinter import * # dimensions of canvas WIDTH=300 HEIGHT=400 # Create window and canvas window = Tk() canvas = Canvas(window, width=WIDTH, height=HEIGHT, bg='#ADF6BE') canvas.pack() # starting position of ball x = 0 y = 10 # starting position of ball1 x1 = 100 y1 = 0 # distance moved each time step for ball 1 dx = 10 dy= 10 # distance moved each time step for ball 2 dx1 = 10 dy1 = 10 # diameter of ball ballsize = 30 while True: x = x + dx y = y + dy x1 = x1 + dx1 y1 = y1 + dy1 # 边界反弹判断,删除了错误的碰撞触发条件 if x >= WIDTH-ballsize or x <= 0: dx = -dx print("x=", x) print('y=', y) if y >= HEIGHT-ballsize or y <= 0: dy = -dy print("x=", x) print('y=', y) if x1 >= WIDTH-ballsize or x1 <= 0: dx1 = -dx1 print("x1=", x1) print('y1=', y1) if y1 >= HEIGHT-ballsize or y1 <= 0: dy1 = -dy1 print("x1=", x1) print('y1=', y1) # 新增两球碰撞判断 cx = x + ballsize / 2 cy = y + ballsize / 2 cx1 = x1 + ballsize / 2 cy1 = y1 + ballsize / 2 distance_sq = (cx - cx1)**2 + (cy - cy1)**2 if distance_sq <= ballsize ** 2: # 交换速度实现反弹 dx, dx1 = dx1, dx dy, dy1 = dy1, dy # 位置修正避免两球卡在一起 overlap = ballsize - (distance_sq ** 0.5) x += dx * overlap / 10 y += dy * overlap / 10 x1 += dx1 * overlap / 10 y1 += dy1 * overlap / 10 # Create balls ball=canvas.create_oval(x, y, x+ballsize, y+ballsize, fill="white", outline='white') ball1 = canvas.create_oval(x1, y1, x1 + ballsize, y1 + ballsize, fill="white", outline='white') # display ball canvas.update() canvas.after(50) #remove ball canvas.delete(ball) canvas.delete(ball1) window.mainloop()
内容的提问来源于stack exchange,提问作者Adam A.
相关产品推荐
相关产品推荐

