为什么我们在游戏物理学中使用勾股定理?


38

我最近了解到,我们在物理计算中经常使用勾股定理,恐怕我并没有真正理解这一点。

这是一本书的示例,以确保对象MAXIMUM_VELOCITY在水平面中的移动速度不会快于常量:

MAXIMUM_VELOCITY = <any number>;
SQUARED_MAXIMUM_VELOCITY = MAXIMUM_VELOCITY * MAXIMUM_VELOCITY; 

function animate(){
    var squared_horizontal_velocity = (x_velocity * x_velocity) + (z_velocity * z_velocity);

    if( squared_horizontal_velocity <= SQUARED_MAXIMUM_VELOCITY ){

        scalar = squared_horizontal_velocity / SQUARED_MAXIMUM_VELOCITY;

        x_velocity = x_velocity / scalar;
        z_velocity = x_velocity / scalar;
    }
}

让我们用一些数字尝试一下:

对象试图在x中移动5个单位,在z中移动5个单位。总共只能水平移动5个单位!

MAXIMUM_VELOCITY = 5;
SQUARED_MAXIMUM_VELOCITY = 5 * 5;
SQUARED_MAXIMUM_VELOCITY = 25;

function animate(){
    var x_velocity = 5;
    var z_velocity = 5;

    var squared_horizontal_velocity = (x_velocity * x_velocity) + (z_velocity * z_velocity);
    var squared_horizontal_velocity = 5 * 5 + 5 * 5;
    var squared_horizontal_velocity = 25 + 25;
    var squared_horizontal_velocity = 50;

//  if( squared_horizontal_velocity <= SQUARED_MAXIMUM_VELOCITY ){
    if( 50 <= 25 ){
        scalar = squared_horizontal_velocity / SQUARED_MAXIMUM_VELOCITY;
        scalar = 50 / 25;
        scalar = 2.0;

        x_velocity = x_velocity / scalar;
        x_velocity = 5 / 2.0;
        x_velocity = 2.5;

        z_velocity = z_velocity / scalar;
        z_velocity = 5 / 2.0;
        z_velocity = 2.5;

        // new_horizontal_velocity = x_velocity + z_velocity
        // new_horizontal_velocity = 2.5 + 2.5
        // new_horizontal_velocity = 5
    }
}

现在这很好用,但是没有毕达哥拉斯,我们可以做同样的事情:

MAXIMUM_VELOCITY = 5;

function animate(){
    var x_velocity = 5;
    var z_velocity = 5;

    var horizontal_velocity = x_velocity + z_velocity;
    var horizontal_velocity = 5 + 5;
    var horizontal_velocity = 10;

//  if( horizontal_velocity >= MAXIMUM_VELOCITY ){
    if( 10 >= 5 ){
        scalar = horizontal_velocity / MAXIMUM_VELOCITY;
        scalar = 10 / 5;
        scalar = 2.0;

        x_velocity = x_velocity / scalar;
        x_velocity = 5 / 2.0;
        x_velocity = 2.5;

        z_velocity = z_velocity / scalar;
        z_velocity = 5 / 2.0;
        z_velocity = 2.5;

        // new_horizontal_velocity = x_velocity + z_velocity
        // new_horizontal_velocity = 2.5 + 2.5
        // new_horizontal_velocity = 5
    }
}

没有毕达哥拉斯的好处:

  1. 行数少
  2. 在这些行中,更容易阅读正在发生的事情
  3. ...由于乘法较少,因此计算时间较少

在我看来,没有毕达哥拉斯定理,计算机和人类将获得更好的收益!但是,我确定我错了,因为我已经在许多著名的地方看到了毕达哥拉斯定理,所以我想向我解释一下将毕达哥拉斯定理用于数学新手的好处。

这和单位向量有关系吗?对我而言,单位矢量是当我们将矢量标准化并将其转化为分数时。我们通过将向量除以更大的常数来完成此操作。我不确定它是什么常数。图的总大小?无论如何,因为它是分数,所以我认为单位矢量基本上是一个图形,它可以适合3D网格,其中x轴从-1到1,z轴从-1到1,y轴从-1到1。这实际上是我所知道的关于单位矢量的所有信息...:P太少了,我看不到它们的用处。

另外,在上面的示例中,我们并没有真正创建单位矢量。我应该像这样确定标量吗:

// a mathematical work-around of my own invention. There may be a cleverer way to do this! I've also made up my own terms such as 'divisive_scalar' so don't bother googling
var divisive_scalar = (squared_horizontal_velocity / SQUARED_MAXIMUM_VELOCITY);
var divisive_scalar = ( 50 / 25 );
var divisive_scalar = 2;

var multiplicative_scalar = (divisive_scalar / (2*divisive_scalar));
var multiplicative_scalar = (2 / (2*2));
var multiplicative_scalar = (2 / 4);
var multiplicative_scalar = 0.5;

x_velocity = x_velocity * multiplicative_scalar
x_velocity = 5 * 0.5
x_velocity = 2.5

再说一次,我看不出为什么这样更好,但是它更多的是“ unit-vector-y”,因为multiplicative_scalar是unit_vector吗?如您所见,我使用诸如“ unit-vector-y”之类的词,因此我实际上不是数学家!还应注意,单位矢量可能与勾股定理无关,因此,如果我在错误的树上吠叫,则可以忽略所有这些。

我是一个非常有视觉素养的人(3D建模者和行业的概念艺术家!),我发现图表真的非常有用,所以请尽可能多地人道主义!


2
实际上,编写的两种算法均未正确限制速度。矢量(2.5, 2.5)了,不是5的约3.54的幅度
bcrist

1
sqrt(2.5*2.5 + 2.5*2.5)
bcrist

1
我们没有,这位哲学家在2500年前就去世了,而千禧一代甚至在出生之前就已经被其他文明千年所理解。这有点像说我们在Neuclear潜艇中使用爱因斯坦,这肯定是一个很有趣的想法(每个潜艇的船员中都有爱因斯坦),但是我们要做的就是运用他发表的理论。以爱因斯坦为例,他以物理学中的许多理论而闻名,因此您可以仅使用其名称的一部分(例如,“相对论”而不是“特殊相对论”)来命名推论质量能等效的理论。人。
安东·科尔曼

3
您的职位存在问题是声称“没有毕达哥拉斯就可以做同样的事情”。但是,曼哈顿距离与欧几里得距离并不相同,因此您正在比较苹果和橙子。如果要从X / Y对获得欧几里得距离,则必须进行数学运算。
杰里B

3
相关:“为什么在物理学中使用数学”和“为什么在游戏中使用数学?”
vaxquis

Answers:


104

您的无毕达哥拉斯代码并不像我们通常认为的那样计算长度。

通常,在3D游戏中,我们将世界建模为欧几里得空间,并使用欧几里得距离度量标准也称为毕达哥拉斯定理)来计算向量v的总长度,其中向量v的分量为vx和vy,即:

EuclideanLength(v) = sqrt(v.x * v.x + v.y * v.y)

(请注意,上面的示例代码中缺少平方根,这就是为什么两种方法似乎给出相同答案的原因。稍后将进一步介绍...)

您描述的代码使用曼哈顿距离度量标准

ManhattanLength(v) = abs(v.x) + abs(v.y)

(尽管您没有包括绝对值,这可能会使它对负数表现出意外的行为)

很容易看出,当vx或vy为零时,这两个距离函数会匹配,并且我们仅沿一个轴移动。当我们对角移动时,它们如何比较?

假设vx = vy =1。这个向量有多长时间(相当于,它描述的速度有多快)?

Euclidean                              Manhattan

sqrt(v.x*v.x + v.y * v.y)              abs(v.x) + abs(v.y)
sqrt(1 * 1 + 1 * 1)                    abs(1) + abs(1)
sqrt(2)                                1 + 1
1.414...                               2

您会看到这些指标实际上并不符合对角线。

让我们在图形上绘制每个度量标准所表示的点集与原点的距离为1:

距离指标

我们熟悉的欧几里得度量是红色圆圈。这是所有点x,y的集合,使得x ^ 2 + y ^ 2 =1。您可以看到它是旋转对称的,这就是我们喜欢它的原因:它整洁地表示距离不随距离变化的想法。方向。

曼哈顿度量标准是蓝色钻石。这与我们对距离的直观想法不是很好的匹配-但这并没有很糟糕。在许多基于图块的游戏中,您在四个基本方向上以不连续的步骤移动,因此,“曼哈顿”度量标准提供了点之间的正确距离(以“到达该位置需要多少步?”而言)。

最后,我出于娱乐目的投入了Chebyshev指标 -这是绿色方块:

ChebyshevLength(v) = max(abs(v.x), abs(v.y))

这对于允许在对角线上移动的基于图块的游戏也非常有用。国际象棋中的国王根据切比雪夫度量标准移动。

我希望可以弄清楚典型的勾股样式代码与您上面提供的示例之间的区别。


11

如果没有毕达哥拉斯,则您在每个轴上的固定速度都会受到限制。您有一个x速度,一个y速度和(在3d世界中)一个z速度,它们彼此独立。任何运动都将与这些垂直轴对齐。

但是,使用毕达哥拉斯,您可以在任何角度都保持恒定的速度。这使您可以使网格消失,并使对象在任何可能的方向上以恒定的速度移动。

一个物体在一秒钟内经过的区域看起来没有毕达哥拉斯(fe Chebyshev metric):

在此处输入图片说明

这与毕达哥拉斯:

在此处输入图片说明

在许多情况下,后者通常看起来更自然。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.