2d 游戏 : fire at a moving target by predicting intersection of projectile and unit

标签 2d intersection predict

好吧,这一切都发生在一个美好而简单的 2D 世界中......:)

假设我有一个位于 Apos 的静态物体 A,一个位于 Bpos 且速度为 bVelocity 的线性移动物体 B,以及一个速度为 Avelocity 的弹药...

考虑到 B 的线速度和 A 弹药的速度,我如何找出 A 必须射击、击中 B 的角度?

现在的目标是物体的当前位置,这意味着当我的射弹到达那里时,单位已经移动到更安全的位置:)

最佳答案

我为 xtank 编写了一个瞄准子程序一会儿回来。我将尝试阐述我是如何做到的。

免责声明:我可能在此处犯了一个或多个愚蠢的错误;我只是想用我生锈的数学技能来重建推理。不过,我先切入正题,因为这是编程问答而不是数学课:-)

如何做

归结为求解以下形式的二次方程:

a * sqr(x) + b * x + c == 0

请注意,sqr 是指平方,而不是平方根。使用以下值:

a := sqr(target.velocityX) + sqr(target.velocityY) - sqr(projectile_speed)
b := 2 * (target.velocityX * (target.startX - cannon.X)
          + target.velocityY * (target.startY - cannon.Y))
c := sqr(target.startX - cannon.X) + sqr(target.startY - cannon.Y)

现在我们可以查看判别式来确定是否有可能的解决方案。

disc := sqr(b) - 4 * a * c

如果判别式小于 0,就别想击中目标了——你的射弹永远无法及时到达目标。否则,请查看两个候选解决方案:

t1 := (-b + sqrt(disc)) / (2 * a)
t2 := (-b - sqrt(disc)) / (2 * a)

请注意,如果 disc == 0t1t2 相等。

如果没有其他考虑因素,例如干扰障碍物,则只需选择较小的正值。 (负t值需要及时向后射击才能使用!)

将所选的 t 值代入目标的位置方程,以获得您应该瞄准的引导点的坐标:

aim.X := t * target.velocityX + target.startX
aim.Y := t * target.velocityY + target.startY

推导

在时间 T 时,弹丸与大炮的(欧几里德)距离必须等于耗时乘以弹丸速度。这给出了一个圆的方程,以耗时为参数。

sqr(projectile.X - cannon.X) + sqr(projectile.Y - cannon.Y)
  == sqr(t * projectile_speed)

类似地,在时间 T 处,目标沿其矢量移动时间乘以其速度:

target.X == t * target.velocityX + target.startX
target.Y == t * target.velocityY + target.startY

当炮弹与炮弹的距离与炮弹的距离一致时,炮弹就能击中目标。

sqr(projectile.X - cannon.X) + sqr(projectile.Y - cannon.Y)
  == sqr(target.X - cannon.X) + sqr(target.Y - cannon.Y)

太棒了!将表达式替换为 target.X 和 target.Y 得出

sqr(projectile.X - cannon.X) + sqr(projectile.Y - cannon.Y)
  == sqr((t * target.velocityX + target.startX) - cannon.X)
   + sqr((t * target.velocityY + target.startY) - cannon.Y)

代入等式另一边可得出:

sqr(t * projectile_speed)
  == sqr((t * target.velocityX + target.startX) - cannon.X)
   + sqr((t * target.velocityY + target.startY) - cannon.Y)

...从两边减去sqr(t *projectile_speed)并翻转它:

sqr((t * target.velocityX) + (target.startX - cannon.X))
  + sqr((t * target.velocityY) + (target.startY - cannon.Y))
  - sqr(t * projectile_speed)
  == 0

...现在解析子表达式的平方结果...

sqr(target.velocityX) * sqr(t)
    + 2 * t * target.velocityX * (target.startX - cannon.X)
    + sqr(target.startX - cannon.X)
+ sqr(target.velocityY) * sqr(t)
    + 2 * t * target.velocityY * (target.startY - cannon.Y)
    + sqr(target.startY - cannon.Y)
- sqr(projectile_speed) * sqr(t)
  == 0

...并将相似术语分组...

sqr(target.velocityX) * sqr(t)
    + sqr(target.velocityY) * sqr(t)
    - sqr(projectile_speed) * sqr(t)
+ 2 * t * target.velocityX * (target.startX - cannon.X)
    + 2 * t * target.velocityY * (target.startY - cannon.Y)
+ sqr(target.startX - cannon.X)
    + sqr(target.startY - cannon.Y)
  == 0

...然后将它们合并...

(sqr(target.velocityX) + sqr(target.velocityY) - sqr(projectile_speed)) * sqr(t)
  + 2 * (target.velocityX * (target.startX - cannon.X)
       + target.velocityY * (target.startY - cannon.Y)) * t
  + sqr(target.startX - cannon.X) + sqr(target.startY - cannon.Y)
  == 0

...给出t中的标准二次方程。找到该方程的正实零点给出(零、一个或两个)可能的命​​中位置,这可以使用二次公式来完成:

a * sqr(x) + b * x + c == 0
x == (-b ± sqrt(sqr(b) - 4 * a * c)) / (2 * a)

关于2d 游戏 : fire at a moving target by predicting intersection of projectile and unit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2248876/

相关文章:

python - Numpy reshape 2D 到 3D : moving columns to "depth"

php - 相交(内连接)两个具有不同键名称的数组

r - mgcv:如何在 predict.gam 中使用 'exclude' 参数?

R:使用 dynlm 包进行动态线性回归,如何预测()?

r - 如何使用存储在 data.table 或 tibble 中的线性模型添加预测列?

Java 绘制的对象未正确更新

Python:对二维数组(列表列表)中的元素执行操作的单行代码?

c++ - 从 SDL_Surface 读取像素并转换为颜色值

python - 使用相似的列合并 2 个数据框

graph - 如何优化graphviz中的布局以删除不必要的边缘交叉点(交叉点)?