篮球投篮碰撞检测问题:Brick与Swish输出功能故障排查
篮球投篮碰撞检测修复方案
问题根源
你当前的碰撞判断逻辑完全错误:直接用球心到篮筐中心的距离和球半径比较,但篮筐是环形结构,不是一个点。只有当篮球刚好砸在篮筐中心时才会触发判断,完全不符合实际碰撞场景。
修复后的完整代码
import math as m from vpython import * ground = box(pos=vector(0,0,0), size=vector(10,0.2,1),color=color.green) ball = sphere(pos=vector(-4.8,2,0), radius=.25, color=color.orange) rim = ring(pos=vector(0,3,0), axis=vector(0,.1,0), radius=.45, thickness=.01, color=color.white) g = vector(0,-9.8,0) v0 = 6.0 theta = 60*m.pi/180 ball.m = .625 # kg ball.v = vector(v0*m.cos(theta),v0*m.sin(theta),0) t = 0 dt = 0.01 collided = False # 标记是否已触发碰撞 above_rim = ball.pos.y > rim.pos.y # 标记球是否在篮筐上方 attach_trail(ball) while ball.pos.y >= 0: rate(100) F = ball.m * g ball.v = ball.v + (F/ball.m)*dt ball.pos = ball.pos + ball.v * dt # 修正原代码错误的位移计算 t = t + dt # 检测空刷(Swish):球从篮筐上方穿过到下方且未碰撞 current_above = ball.pos.y > rim.pos.y if above_rim and not current_above and not collided: print("Swish") above_rim = current_above # 篮筐碰撞检测逻辑 if not collided: # 球心到篮筐平面的垂直距离(篮筐平面近似为y=3的平面) y_dist = abs(ball.pos.y - rim.pos.y) # 球心在水平面上的投影到篮筐中心的距离 horizontal_dist = m.sqrt(ball.pos.x**2 + ball.pos.z**2) # 篮筐的有效碰撞范围:水平距离落在[环半径-球半径, 环半径+球半径],垂直距离不超过球半径+篮筐厚度的一半 rim_inner = rim.radius - ball.radius rim_outer = rim.radius + ball.radius max_y_dist = ball.radius + rim.thickness/2 if (rim_inner <= horizontal_dist <= rim_outer) and (y_dist <= max_y_dist): print("Brick") collided = True # 避免重复打印碰撞信息
关键改动说明
- 修正运动公式:原代码中
ball.pos = ball.pos + ball.v*dt/ball.m是错误的,位移更新应为位置 += 速度*dt,无需除以质量。 - 环形碰撞判断:
- 先判断球心到篮筐平面的垂直距离,确保球处于篮筐的高度范围内
- 再判断球心的水平投影到篮筐中心的距离,是否落在篮筐环的碰撞区间(结合球半径和篮筐厚度)
- 空刷触发逻辑:通过跟踪球在篮筐上下方的状态,当球从上方穿过到下方且未触发碰撞时,打印“Swish”
- 防重复触发:用
collided标记避免多次打印同一结果
内容的提问来源于stack exchange,提问作者Sutter Donegan
相关产品推荐
相关产品推荐

