¿Por qué usamos el teorema de Pitágoras en la física del juego?

38

Recientemente aprendí que usamos mucho el teorema de Pitágoras en nuestros cálculos de física y me temo que realmente no entiendo el punto.

Aquí hay un ejemplo de un libro para asegurarse de que un objeto no viaje más rápido que una MAXIMUM_VELOCITYconstante en el plano horizontal:

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;
    }
}

Probemos esto con algunos números:

Un objeto está intentando mover 5 unidades en xy 5 unidades en z. ¡Solo debería poder mover 5 unidades horizontalmente en total!

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
    }
}

Ahora esto funciona bien, pero podemos hacer lo mismo sin Pitágoras:

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
    }
}

Beneficios de hacerlo sin Pitágoras:

  1. Menos líneas
  2. Dentro de esas líneas, es más fácil leer lo que está sucediendo.
  3. ... y toma menos tiempo calcular, ya que hay menos multiplicaciones

¡Me parece que las computadoras y los humanos obtienen un mejor trato sin el teorema de Pitágoras! Sin embargo, estoy seguro de que estoy equivocado, ya que he visto el teorema de Pitágoras en varios lugares de buena reputación, así que me gustaría que alguien me explique el beneficio de usar el teorema de Pitágoras a un novato en matemáticas .

¿Tiene esto algo que ver con los vectores unitarios? Para mí, un vector unitario es cuando normalizamos un vector y lo convertimos en una fracción. Hacemos esto dividiendo el vector por una constante más grande. No estoy seguro de qué constante es. El tamaño total de la gráfica? De todos modos, como es una fracción, supongo que un vector unitario es básicamente un gráfico que puede caber dentro de una cuadrícula 3D con el eje x que va de -1 a 1, el eje z que va de -1 a 1 y la y -eje que va de -1 a 1. Eso es literalmente todo lo que sé sobre los vectores unitarios ... no mucho: P Y no veo su utilidad.

Además, en realidad no estamos creando un vector unitario en los ejemplos anteriores. ¿Debo determinar el escalar así?

// 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

Una vez más, no puedo ver por qué esto es mejor, pero es más "unit-vector-y" porque multiplicative_scalar es unit_vector. Como puede ver, uso palabras como "unit-vector-y", ¡así que realmente no soy un genio de las matemáticas! También consciente de que los vectores unitarios podrían no tener nada que ver con el teorema de Pitágoras, así que ignore todo esto si estoy ladrando el árbol equivocado.

Soy una persona muy visual (¡modelista 3D y artista conceptual por profesión!) Y encuentro diagramas y gráficos realmente, muy útiles, ¡por favor, tantos como sea humanamente posible!

Starkers
fuente
2
En realidad, ninguno de los algoritmos escritos correctamente limita la velocidad. El vector (2.5, 2.5)tiene una magnitud de aproximadamente 3.54, no 5.
bcrist
1
sqrt(2.5*2.5 + 2.5*2.5)
bcrist
1
Nosotros no, el filósofo murió hace 2.500 años y el teorema que lleva su nombre fue entendido por otras civilizaciones milenios antes de que él naciera. Eso es un poco como decir que usamos Einstein en submarinos Neucleares, un pensamiento curioso seguro (cada submarino tiene un Einstein en la tripulación), pero lo que hacemos es aplicar parte de una teoría que publicó. En el caso de Einstein, es famoso por muchas teorías en física, por lo que puede nombrar la teoría de la que se deriva la equivalencia de masa-energía utilizando solo una parte de su nombre (por ejemplo, "relatividad" en lugar de "relatividad especial") sin confundirla con persona.
Andon M. Coleman
3
El problema con su posición es la afirmación de que "podemos hacer lo mismo sin Pitágoras". Pero la distancia de Manhattan no es lo mismo que la distancia euclidiana, así que estás comparando manzanas y naranjas. Si desea distancia euclidiana de un par X / Y, tiene que hacer los cálculos.
Jerry B
3
relacionado: "¿por qué usamos las matemáticas en física" y "por qué usamos las matemáticas en los juegos?"
vaxquis

Respuestas:

104

Su código libre de Pitágoras no calcula una longitud como normalmente pensamos en él.

Normalmente en los juegos 3D modelamos el mundo como un espacio euclidiano, y utilizamos una métrica de distancia euclidiana ( también conocida como Teorema de Pitágoras) ) para calcular la longitud total de un vector v con componentes vx y vy A saber:

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

(Tenga en cuenta que esta raíz cuadrada falta en su código de muestra anterior, por lo que los dos enfoques parecen dar la misma respuesta. Más sobre eso en breve ...)

El código que ha descrito utiliza la métrica de distancia de Manhattan :

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

(Aunque no incluyó los valores absolutos, lo que puede hacer que se comporte inesperadamente para números negativos)

Es fácil ver que estas dos funciones de distancia coinciden cuando vx o vy es cero, y solo nos movemos a lo largo de un eje. ¿Cómo se comparan cuando nos movemos en diagonal?

Digamos vx = vy = 1. ¿Cuánto mide este vector (equivalentemente, qué tan rápida es la velocidad que describe)?

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

Puede ver que estas métricas en realidad no están de acuerdo con las líneas diagonales.

Tracemos en un gráfico el conjunto de puntos que cada métrica dice que están a una distancia de 1 del origen:

Distance metrics

Nuestra métrica euclidiana familiar es el círculo rojo. Este es el conjunto de todos los puntos x, y tal que x ^ 2 + y ^ 2 = 1. Puede ver que es simétrico rotacionalmente, y por eso nos gusta: representa claramente la idea de que la distancia no cambia con dirección.

La métrica de Manhattan es el diamante azul. No es una gran combinación para nuestra idea intuitiva de distancia, pero eso no lo hace malo. En muchos juegos basados ​​en fichas donde te mueves en pasos discretos en las cuatro direcciones cardinales, la métrica de Manhattan proporciona la distancia correcta entre puntos (en términos de "¿cuántos movimientos se necesitarán para llegar allí?")

Finalmente, agregué la métrica de Chebyshev por diversión: es el cuadrado verde:

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

También es bueno para juegos basados ​​en fichas, donde puedes moverte en diagonales. Un rey en ajedrez se mueve según la métrica de Chebyshev.

Espero que eso aclare cuál es la diferencia entre el código típico de estilo pitagórico y el ejemplo que proporcionó anteriormente.

DMGregory
fuente
11

Sin Pitágoras, estás obligado a una velocidad fija en cada eje. Tienes una velocidad x, una velocidad y y (en un mundo 3d) una velocidad z que son independientes entre sí. Cualquier movimiento se alineará con estos ejes perpendiculares.

Sin embargo, con Pitágoras, tienes una velocidad que puede ser constante en cualquier ángulo. Eso le permite hacer desaparecer la cuadrícula y hacer que los objetos se muevan con una velocidad constante en cualquier dirección posible.

El área que viaja un objeto en un segundo se ve sin Pitágoras (métrica de Fe Chebyshev):

enter image description here

Y esto con Pitágoras:

enter image description here

Este último generalmente parece mucho más natural en muchos casos.

Philipp
fuente