那些熟悉三角函数但不熟悉 Robocode 的人需要注意: Robocode 的角度值是非负的并且顺时针增加,而不是像三角约定那样以零为中心并逆时针增加。
天哪,那是个毛球。痛苦的风格也是,分配一个变量,然后在同一个表达式中使用它,并static
为不同的目的随机重用变量。(编辑:我已经离开机器人代码太久了;看起来很混乱的混乱可能是手动优化代码大小的结果。)让我们试着从这里开始解开那一条凌乱的线:
setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
看起来var
被用来保存子表达式的结果e.getBearingRadians() + getHeadingRadians()
。由于e.getBearingRadians()
返回目标相对于您的航向的方位角,var
是绝对 目标的方位角。重构:
double targetBearing = e.getBearingRadians() + getHeadingRadians();
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));
呃,还是一团糟。我们也有vel
下落不明的变量,但根据其余代码,它似乎是上次扫描时目标的速度(并且在仅进行一对一比赛的轻率假设下);它与当前速度组合成一个加权平均值,以给出粗略的预测速度,因此这里可能存在一些目标领先的逻辑。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));
由于机器人代码似乎忽略了航向和航向之间的差异,所以最里面的正弦Math.sin(e.getHeadingRadians() - targetBearing)
给出了一个带符号的系数,指示目标速度的哪个分量垂直于它的方位,因此需要调整发射角。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient)));
反正弦表达式似乎旨在将目标运动的垂直分量重新转换为角度调整。这一点数学是完全错误的,因为反正弦不是这样工作的:它将区间 [-1, 1] 中的系数转换回区间 [-pi/2, pi/2] 中的角度,并且将预测速度除以 14 可能只是试图将arc-sine 的参数限制在其域内。再说一次,到目标的距离和弹丸速度都没有进入计算,所以我能说的关于这个调整的最好的说法是它模糊地朝着正确的方向。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + firingAngleAdjustment));
最后一个正弦对我来说毫无意义。参数已经是枪需要移动的弧度角:目标的绝对方位减去当前枪的航向(枪需要转向多远才能准确指向目标),加上射击角度调整目标的运动。我将完全删除那里的正弦函数。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(targetBearing - getGunHeadingRadians() + firingAngleAdjustment);
当然,这也取决于将枪设置为转动超过半圈(pi 弧度)是否会被自动理解为将其转向另一个方向不到半圈......你最终可能会做很多毫无意义的事情否则枪旋。