高尔夫球正负X/Y方向运动表现异常问题排查求助
高尔夫球运动方向表现不一致问题排查
我实现的update运动处理方法中,正负速度的运动逻辑完全一致,但高尔夫球向北、向东移动时的表现和向南、向西移动时存在明显差异。我已经多次重写运动处理代码、检查deltaX/Y等相关数值,始终无法定位问题根源。
现有update方法代码
public void update() { double deceleration = 0.9; // Deceleration factor // Check if the ball is moving if (vx != 0 || vy != 0) { isMoving = true; updateCount++; // Increment the counter } // Apply deceleration to both components vx *= deceleration; vy *= deceleration; // Update position using the decelerated velocity components x += vx; y += vy; // System.out.println("vX: "+vx+" vY: "+vy); // Set velocity to zero when vx or vy is too small to matter if (Math.abs(vx) < 0.000001) { vx = 0; } if (Math.abs(vy) < 0.000001) { vy = 0; } // Border coordinates and dimensions int borderX = 100; // Update these values to match the actual border coordinates and dimensions int borderY = 100; int borderWidth = 800; int borderHeight = 600; // Bounce off the borders if (x + RADIUS >= borderX + borderWidth || x - RADIUS <= borderX) { vx *= -1; // Reverse horizontal velocity x = Math.min(x, borderX + borderWidth - RADIUS); x = Math.max(x, borderX + RADIUS); } if (y + RADIUS >= borderY + borderHeight || y - RADIUS <= borderY) { vy *= -1; // Reverse vertical velocity y = Math.min(y, borderY + borderHeight - RADIUS); y = Math.max(y, borderY + RADIUS); } // If the ball has stopped moving and was previously moving, log the update count if (vx == 0 && vy == 0 && isMoving) { System.out.println("Ball stopped moving after "+updateCount+" updates. "); isMoving = false; // Reset the moving state updateCount = 0; // Reset the counter } }
可能的问题根源及修正方案
1. 碰撞处理与位置更新的顺序问题
当前代码先应用减速、更新位置,再处理碰撞修正。这种顺序会导致碰撞后的位置调整与速度方向产生不对称的浮点数累积误差:
- 当球向负方向(西/南)移动触碰边界时,位置修正的
Math.max/Math.min会将位置拉回边界内,但结合已更新的位置,可能导致后续速度计算的偏差; - 正方向(东/北)的碰撞修正逻辑看似对称,但浮点数精度的累积会放大差异。
修正方案:调整顺序,先判断碰撞并反转速度,再应用减速和更新位置:
public void update() { double deceleration = 0.9; boolean xBounce = false; boolean yBounce = false; int borderX = 100; int borderY = 100; int borderWidth = 800; int borderHeight = 600; // 先检查碰撞,标记需要反弹的方向 if (x + RADIUS >= borderX + borderWidth || x - RADIUS <= borderX) { vx *= -1; xBounce = true; } if (y + RADIUS >= borderY + borderHeight || y - RADIUS <= borderY) { vy *= -1; yBounce = true; } // 应用减速 vx *= deceleration; vy *= deceleration; // 修正碰撞后的位置,避免球卡入边界 if (xBounce) { x = Math.min(Math.max(x, borderX + RADIUS), borderX + borderWidth - RADIUS); } if (yBounce) { y = Math.min(Math.max(y, borderY + RADIUS), borderY + borderHeight - RADIUS); } // 更新位置 x += vx; y += vy; // 速度归零判断 final double VELOCITY_EPSILON = 1e-4; if (Math.abs(vx) < VELOCITY_EPSILON) vx = 0; if (Math.abs(vy) < VELOCITY_EPSILON) vy = 0; // 运动状态与计数处理 if (vx != 0 || vy != 0) { isMoving = true; updateCount++; } else if (isMoving) { System.out.println("Ball stopped moving after "+updateCount+" updates. "); isMoving = false; updateCount = 0; } }
2. 浮点数精度的不对称截断
原代码使用1e-6作为速度归零阈值,正负方向的浮点数在多次乘法后,精度丢失的程度可能不一致,导致某一方向的速度提前归零,另一方向仍持续运动。
修正方案:将阈值调整为更合理的1e-4,或采用相对阈值(比如基于初始速度的比例),减少精度差异带来的影响。
3. 坐标系统方向不匹配
如果渲染时的Y轴方向与物理逻辑中的Y轴方向相反(比如渲染时Y向下为正,物理逻辑中Y向上为正),会导致南北方向的运动表现出现视觉上的“差异”,看似逻辑对称但实际渲染结果不符。
验证方案:检查渲染代码中Y坐标的使用方式,确保物理运动的Y轴方向与渲染的Y轴方向一致。
内容的提问来源于stack exchange,提问作者Robert Romani
相关产品推荐
相关产品推荐

