Java 2D射击游戏:计算圆沿Y轴至线段的最大投影碰撞距离
2D射击游戏中子弹沿Y轴移动的碰撞距离计算函数
以下是满足需求的Java实现,核心逻辑是先判断子弹与墙体线段的X轴范围是否重叠(无重叠则不会碰撞),再计算Y轴方向的碰撞距离:
核心函数实现
public class BulletCollisionCalculator { /** * 计算子弹沿Y轴移动的最大距离 * @param bulletX 子弹中心X坐标 * @param bulletY 子弹中心Y坐标 * @param bulletRadius 子弹半径 * @param lineX1 墙体线段端点1的X坐标 * @param lineY1 墙体线段端点1的Y坐标 * @param lineX2 墙体线段端点2的X坐标 * @param lineY2 墙体线段端点2的Y坐标 * @return 可移动的Y轴距离:线段在圆上方返回负值,下方返回正值,无碰撞返回POSITIVE_INFINITY,已碰撞返回0 */ public static float calculateMaxYDistance(float bulletX, float bulletY, float bulletRadius, float lineX1, float lineY1, float lineX2, float lineY2) { // 计算子弹和线段的X轴范围 float xBulletMin = bulletX - bulletRadius; float xBulletMax = bulletX + bulletRadius; float xLineMin = Math.min(lineX1, lineX2); float xLineMax = Math.max(lineX1, lineX2); // X轴无交集,不会碰撞 if (xBulletMax < xLineMin || xBulletMin > xLineMax) { return Float.POSITIVE_INFINITY; } // 计算线段在X重叠区域内的Y值范围 float yLineMin, yLineMax; if (lineX1 == lineX2) { // 垂直线段 yLineMin = Math.min(lineY1, lineY2); yLineMax = Math.max(lineY1, lineY2); } else { // 斜线/水平线段,用参数方程计算重叠区域的Y范围 float slope = (lineY2 - lineY1) / (lineX2 - lineX1); float intercept = lineY1 - slope * lineX1; float overlapXMin = Math.max(xBulletMin, xLineMin); float overlapXMax = Math.min(xBulletMax, xLineMax); float yAtMinX = slope * overlapXMin + intercept; float yAtMaxX = slope * overlapXMax + intercept; yLineMin = Math.min(yAtMinX, yAtMaxX); yLineMax = Math.max(yAtMinX, yAtMaxX); } return calculateDistanceFromYRange(bulletY, bulletRadius, yLineMin, yLineMax); } /** * 根据线段的Y范围计算子弹可移动的距离 */ private static float calculateDistanceFromYRange(float bulletY, float bulletRadius, float yLineMin, float yLineMax) { float circleYMin = bulletY - bulletRadius; float circleYMax = bulletY + bulletRadius; // 子弹已与线段碰撞 if (!(circleYMax < yLineMin || circleYMin > yLineMax)) { return 0.0f; } // 线段在圆上方(所有线段点的Y小于圆的最低Y) if (yLineMax < circleYMin) { return (yLineMax + bulletRadius) - bulletY; } // 线段在圆下方(所有线段点的Y大于圆的最高Y) if (yLineMin > circleYMax) { return (yLineMin - bulletRadius) - bulletY; } // 理论上不会执行到此处 return Float.POSITIVE_INFINITY; } }
逻辑说明
- X轴范围判断:只有子弹的X范围与线段的X范围有重叠时,子弹沿Y轴移动才可能碰撞墙体,否则直接返回
Float.POSITIVE_INFINITY。 - Y范围计算:针对垂直线段、斜线/水平线段分别处理,计算出线段在X重叠区域内的Y值区间。
- 距离计算:
- 若子弹已与线段重叠,返回
0; - 线段在圆上方时,返回负距离(对应子弹向上移动的碰撞位置);
- 线段在圆下方时,返回正距离(对应子弹向下移动的碰撞位置)。
- 若子弹已与线段重叠,返回
内容的提问来源于stack exchange,提问作者Reiss Gomez
相关产品推荐
相关产品推荐

