【问题标题】:How to move an object along a line given two points?如何在给定两点的情况下沿直线移动对象?
【发布时间】:2018-03-08 12:27:21
【问题描述】:

在我正在开发的游戏中,我有一座可以向敌人射击的塔。当敌人进入射程时,我试图让我的塔向敌人射击。我的火球出现了,但是我无法将火球移动到敌人身上。我最近的尝试只是让球在屏幕上跳舞。

球有一个 x 和 y 位置(类似于球开始的位置。 球还有一个 newX 和 newY 位置,即敌人所在的位置。我正在考虑做毕达哥拉斯定理,但这只能让我得到我想要旅行的线路长度。然后我在网上搜索并发现了有关 sin、cos 和 atan 的信息。我使用 atan 来获得我计算出的斜率角度,然后将角度代入 sin 和 cos。

我的 Ball::Update 函数如下所示:

int dx = newX - x;
int dy = newY - y;

int ang = atan(dy, dx);

x += cos(ang);
y += sin(ang);

那里的代码使球在屏幕上看起来“跳舞”。它根本不动。我用这些行测试了我的代码:

x += cos(45); y += sin(45);

球以 45 度角移动(向东南方向移动),这是意料之中的。所以我猜我的错误是在计算角度时。有没有数学专家可以帮忙?

【问题讨论】:

  • ang 应该是浮点单元并使用atan2。 x 和 y 如果还不是浮点单位,也应该是浮点单位。
  • 我真的怀疑你使用例如sin(45) 用于计算窦,因为 std::sin(和其他三角函数)期望其参数以 弧度 为单位。
  • 为什么这么复杂?请搜索线性插值。 x(t) = (1 - t) * x0 + t * x1。从 x0 到 x1 以任意步骤从 0 ... 1 迭代 t。 (对 y 应用相同的公式来成对计算 x 和 y。)
  • 通常计算不是基于角度,而是基于方向向量
  • cos(45) 不会给出你想的结果。三角函数的参数是弧度,而不是度数。

标签: c++ line angle trigonometry


【解决方案1】:

这是一个小示例,用于演示对 (x, y) 的 linear interpolation

#include <iostream>

int main()
{
  double x0 = 2.0, y0 = 3.5;
  double x1 = 7.0, y1 = 2.0;
  // do linear interpolation in n steps
  enum { n = 10 };
  for (int i = 0; i <= n; ++i) {
    double t = (double)i / n;
    double xT = (1.0 - t) * x0 + t * x1;
    double yT = (1.0 - t) * y0 + t * y1;
    std::cout << i << ":\tt: " << t << ",\tx: " << xT << ",\ty: " << yT << '\n';
  }
  // your code goes here
  return 0;
}

输出:

0:  t: 0,   x: 2,   y: 3.5
1:  t: 0.1, x: 2.5, y: 3.35
2:  t: 0.2, x: 3,   y: 3.2
3:  t: 0.3, x: 3.5, y: 3.05
4:  t: 0.4, x: 4,   y: 2.9
5:  t: 0.5, x: 4.5, y: 2.75
6:  t: 0.6, x: 5,   y: 2.6
7:  t: 0.7, x: 5.5, y: 2.45
8:  t: 0.8, x: 6,   y: 2.3
9:  t: 0.9, x: 6.5, y: 2.15
10: t: 1,   x: 7,   y: 2

Life demo on ideone

【讨论】:

  • 请注意,在带有弹丸的游戏中,如果t 随时间线性增长,那么无论距离多远,所有弹丸都将花费相同的时间到达目标(可能有也可能没有是可取的)。相反,如果您希望速度保持恒定,您可以预先计算归一化方向矢量v,并在每一步将弹丸移动speed*v(快速示例:ideone.com/YNELkN)。不过,它背后的(相当简单的)数学是一样的。
  • 另一种使速度保持不变的解决方案是预先计算每个射弹在生成时到达其目标的预期时间T(并将其存储在某处),然后让t以@的步长增加987654332@(而不是固定的硬编码步骤)。
  • @Caninonos 好点。要管理此步骤数,应考虑 (x0, y0) 和 (x1, y1) 之间的Euclidean distance。现在,我们又看到了毕达哥拉斯(OP 已经提到过)。我有另一个想法:让 t = sin²(Pi * i / n),你有加速和减速。因此,示例显示了原理,任何增强都可能被认为是 OP...
  • t = sin²(Pi * i / n) 是错误的。更好的是 t = 0.5 - cos(Pi * i / n) / 2。(只是在 Excel 中摆弄了一下。)前者是相关的,但在此示例中不正确。
猜你喜欢
  • 1970-01-01
  • 2016-06-26
  • 2015-08-13
  • 2016-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 2017-04-22
相关资源
最近更新 更多