Por que usamos o teorema de Pitágoras na física dos jogos?

38

Recentemente, aprendi que usamos muito o teorema de Pitágoras em nossos cálculos de física e receio que não entendi direito.

Aqui está um exemplo de um livro para garantir que um objeto não viaje mais rápido que uma MAXIMUM_VELOCITYconstante no 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;
    }
}

Vamos tentar isso com alguns números:

Um objeto está tentando mover 5 unidades em xe 5 unidades em z. Só deve poder mover 5 unidades horizontalmente no 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
    }
}

Agora isso funciona bem, mas podemos fazer a mesma coisa sem 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
    }
}

Benefícios de fazer isso sem Pitágoras:

  1. Menos linhas
  2. Dentro dessas linhas, é mais fácil ler o que está acontecendo
  3. ... e leva menos tempo para calcular, pois há menos multiplicações

Parece-me que computadores e humanos conseguem um acordo melhor sem o teorema de Pitágoras! No entanto, tenho certeza que estou errado, pois já vi o teorema de Pitágoras em vários lugares respeitáveis, então gostaria que alguém me explicasse o benefício de usar o teorema de Pitágoras para um novato em matemática .

Isso tem algo a ver com vetores unitários? Para mim, um vetor unitário é quando normalizamos um vetor e o transformamos em uma fração. Fazemos isso dividindo o vetor por uma constante maior. Não tenho certeza do quão constante é. O tamanho total do gráfico? De qualquer forma, por ser uma fração, um vetor unitário é basicamente um gráfico que pode caber dentro de uma grade 3D com o eixo x rodando de -1 a 1, o eixo z rodando de -1 a 1 ey - eixo varia de -1 a 1. Isso é literalmente tudo o que sei sobre vetores unitários ... não muito: P E não vejo a utilidade deles.

Além disso, não estamos realmente criando um vetor de unidade nos exemplos acima. Devo determinar o escalar como este:

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

Novamente, não consigo entender por que isso é melhor, mas é mais "vetor-unidade-y" porque o multiplicative_scalar é um vetor de unidade? Como você pode ver, eu uso palavras como "unit-vector-y", então não sou realmente um gênio da matemática! Também ciente de que os vetores unitários podem não ter nada a ver com o teorema de Pitágoras, então ignore tudo isso se eu estiver latindo na árvore errada.

Eu sou uma pessoa muito visual (modelador 3D e artista conceitual por profissão!) E acho que diagramas e gráficos são realmente muito úteis para tantos humanamente quanto possível, por favor!

Starkers
fonte
2
Na verdade, nenhum dos algoritmos escritos limita corretamente a velocidade. O vector (2.5, 2.5)tem uma magnitude de aproximadamente 3,54, não 5.
bcrist
1
sqrt(2.5*2.5 + 2.5*2.5)
Bcrist 25/05
1
Não, o filósofo morreu há 2.500 anos e o teorema que leva seu nome foi entendido por outras civilizações milênios antes mesmo de ele nascer. É um pouco como dizer que usamos Einstein nos submarinos da Neuclear, um pensamento engraçado com certeza (todos os submarinos têm um Einstein na tripulação), mas o que fazemos é aplicar parte da teoria que ele publicou. No caso de Einstein, ele é famoso por muitas teorias da física, de modo que você pode nomear a teoria da qual a equivalência energia-massa é derivada usando apenas parte de seu nome (por exemplo, "relatividade" em vez de "relatividade especial") sem confundi-la por um pessoa.
Andon M. Coleman
3
O problema com sua posição é a afirmação de que "podemos fazer a mesma coisa sem Pitágoras". Mas a distância de Manhattan não é a mesma que a distância euclidiana, então você está comparando maçãs e laranjas. Se você deseja a distância euclidiana de um par X / Y, é necessário fazer as contas.
Jerry B
3
relacionados: "por que usamos matemática em física" e "por que usamos matemática em jogos?"
vaxquis

Respostas:

104

Seu código sem Pitágoras não calcula um comprimento como normalmente pensamos nele.

Normalmente, em jogos 3D, modelamos o mundo como um espaço euclidiano e usamos uma métrica de distância euclidiana ( também conhecida como Teorema de Pitágoras ) para calcular o comprimento total de um vetor v com os componentes vx e vy.

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

(Observe que essa raiz quadrada está ausente no código de exemplo acima, e é por isso que as duas abordagens parecem dar a mesma resposta. Mais sobre isso em breve ...)

O código que você descreveu usa a métrica de distância de Manhattan :

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

(Embora você não tenha incluído os valores absolutos, o que pode fazer com que ele se comporte inesperadamente em números negativos)

É fácil ver que essas duas funções de distância se combinam quando vx ou vy é zero, e estamos apenas nos movendo ao longo de um eixo. Como eles se comparam quando nos movemos na diagonal?

Digamos que vx = vy = 1. Quanto tempo dura esse vetor (equivalentemente, qual a velocidade que ele descreve)?

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

Você pode ver que essas métricas não concordam com as linhas diagonais.

Vamos traçar em um gráfico o conjunto de pontos que cada métrica diz que estão a uma distância de 1 da origem:

Métricas de distância

Nossa métrica euclidiana familiar é o círculo vermelho. Este é o conjunto de todos os pontos x, y, de modo que x ^ 2 + y ^ 2 = 1. Você pode ver que é simétrica rotacionalmente, e é por isso que gostamos: representa perfeitamente a ideia de que a distância não muda com direção.

A métrica de Manhattan é o diamante azul. Não é uma ótima combinação para nossa idéia intuitiva de distância - mas isso não a torna ruim. Em muitos jogos baseados em blocos em que você se move em etapas discretas nas quatro direções principais, a métrica de Manhattan fornece a distância correta entre os pontos (em termos de "quantos movimentos serão necessários para chegar lá?")

Por fim, joguei a métrica Chebyshev por diversão - é o quadrado verde:

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

Também é bom para jogos baseados em blocos, nos quais você pode seguir as diagonais. Um rei no xadrez se move de acordo com a métrica Chebyshev.

Espero que esclareça qual é a diferença entre o código típico do estilo pitagórico e o exemplo que você forneceu acima.

DMGregory
fonte
11

Sem Pitágoras, você está vinculado a uma velocidade fixa em cada eixo. Você tem uma velocidade x, uma velocidade y e (em um mundo 3d) uma velocidade z, todas independentes uma da outra. Qualquer movimento será alinhado a esses eixos perpendiculares.

No entanto, com Pitágoras, você tem uma velocidade que pode ser constante em qualquer ângulo. Isso permite que você desapareça a grade e faça com que os objetos se movam a uma velocidade constante em qualquer direção possível.

A área em que um objeto viaja em um segundo parece sem Pitágoras (métrica de Chebyshev):

insira a descrição da imagem aqui

E isso com Pitágoras:

insira a descrição da imagem aqui

O último geralmente parece muito mais natural em muitos casos.

Philipp
fonte