假設敵人以恆定半徑 r、角速度 ω 繞圓周運動。子彈飛行時間 t 內,敵人方向改變 Δθ = ωt。相對於初始位置的位移向量為:
Δx = cos(θ₀)·r - cos(θ₀+Δθ)·r Δy = sin(θ₀+Δθ)·r - sin(θ₀)·r
headingChangePerTurn = (heading₂ - heading₁) / time(需正規化至 (-π, π])bulletTime = getTime() + range / (20 - 3×firepower)radius = velocity / headingChangePerTurnpublic Point2D.Double guessPosition(long when) {
double diff = when - scanTime; // 掃描時間到預測時間的差值
double newX, newY;
if (Math.abs(headingChange) > 0.00001) { // 顯著轉向:圓周預測
double radius = velocity / headingChange;
double totalTurn = diff * headingChange;
newY = y + Math.sin(heading + totalTurn) * radius - Math.sin(heading) * radius;
newX = x + Math.cos(heading) * radius - Math.cos(heading + totalTurn) * radius;
} else { // 微小轉向:線性預測
newY = y + Math.cos(heading) * velocity * diff;
newX = x + Math.sin(heading) * velocity * diff;
}
return new Point2D.Double(newX, newY);
}
子彈飛行時間取決於擊中位置,擊中位置又取決於飛行時間。透過固定點迭代快速收斂:
void doGun() {
Point2D.Double p = new Point2D.Double(target.x, target.y);
for (int i = 0; i < 10; i++) { // 10 次迭代通常已足夠
int nextTime = (int) Math.round(getRange(getX(), getY(), p.x, p.y) / (20 - 3 * firePower));
long time = getTime() + nextTime;
p = target.guessPosition(time);
}
double gunOffset = getGunHeadingRadians() - (Math.PI/2 - Math.atan2(p.y - getY(), p.x - getX()));
setTurnGunLeftRadians(normalizeBearing(gunOffset));
}
double normalizeBearing(double ang) {
while (ang > Math.PI) ang -= 2*Math.PI;
while (ang < -Math.PI) ang += 2*Math.PI;
return ang;
}
double getRange(double x1, double y1, double x2, double y2) {
return Math.hypot(x2 - x1, y2 - y1);
}

圓周瞄準是對付 SpinBot 類機器人的利器,配合迭代修正可達到極高命中率。掌握其數學本質,您將能舉一反三,開發出更強大的瞄準系統。