Por que meu objeto se move mais rápido a 45 graus do que a 90 graus?


32

Eu tenho objetos no meu jogo que se movem mais rápido a 45 graus do que a 90 graus.

Cada objeto tem

  • Posição do ponto (x, y)
  • Direção Vector2D (x, y)
  • Int velocidade

E o que faço durante uma atualização é que a nova posição é calculada como:

position.x += direction.x * speed
position.y += direction.y * speed

Como faço para corrigir isso? Quero que ele se mova com a mesma velocidade em qualquer ângulo.


8
Normalize seu vetor de direção antes de usar; problema resolvido.
Deceleratedcaviar

1
Tive que google normalização :) encontrei este site útil fundza.com/vectors/normalize/index.html
Jason94

E se você estiver usando a entrada do usuário para controlar esse objeto, esteja ciente de bloquear as instruções 12,3,6,9, conforme explicado aqui para os desenvolvedores do XNA: xona.com/2010/05/03.html . Pode ser algo que você deseja (como em um jogo de RPG) ou não (como em um jogo no estilo Geometry Wars).
Xonatron

no antigo jogo Descent , esse era um recurso .
1911 J. Holmes

@ 32bitkid Sim, ver também o Doom straferunning
bobobobo

Respostas:


55

Isso pode ser explicado pelo teorema de Pitágoras , que é a seguinte fórmula:

a² + b² = c²

No seu caso, ao mover para a direita, você está usando (x: 1, y: 0), o que nos fornece

c² = 1 + 0 = 1
c = sqrt(1) = 1.00

Ao mover para cima e para a direita, você está usando (x: 1, y: 1), o que nos fornece

c² = 1 + 1 = 2
c = sqrt(2) = 1.41

Como você pode ver, o comprimento na diagonal é maior que o comprimento nos eixos cardinais.

Como outros já mencionaram, você deve simplesmente normalizar seu vetor de direção. Se você usa o XNA, é feito assim:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed

Estou lhe dando +1 por sua ajuda na minha pergunta :)
Martin.

12

Normalize seu vetor de direção antes de usar.

Conforme explicado pelo MindWorX, isso pode ser entendido simplesmente, se você está preocupado com os vetores de direção que possivelmente causam sofrimento, verifique se eles são vetores unitários (magnitude / comprimento de 1).

Length(Vector2(1, 1)) == 1.4142135623730951 // first hint of grief
Length(Vector2(1, 0)) == 1

Vector2(1, 1) * 2 == Vector2(2, 2)
Vector2(1, 0) * 2 == Vector2(2, 0)

Length(Vector2(2, 2)) = 2.8284271247461903 // second hint
Length(Vector2(2, 0)) = 2

Se normalizado:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect

14
Não é uma resposta útil. Se o questionador soubesse o que significa "normalize seu vetor de direção", ele não teria feito a pergunta.
Kristopher Johnson

@KristopherJohnson não ficou claro que o questionador não sabia como normalizar um vetor. Embora o interlocutor pareça engenhoso o suficiente para não ter importância.
Deceleratedcaviar

2
@KristopherJohnson: se o interlocutor não sabia o que significa "normalizar seu vetor de direção", ele só precisava digitar isso no google, anexar o nome de seu idioma e obter um código com explicações.
Lie Ryan

6

Como você está calculando sua direção? Se 45 graus é (1,1), certamente será mais rápido que 90 graus (1,0).

Eu sugiro que você use algo como isto:

direction.x = Math.Cos(angleInRadians);
direction.y = Math.Sin(angleInRadians);

Para obter o ângulo em radianos, você precisará multiplicar seus graus com PI / 180ou, melhor ainda, com o uso MathHelper. Por exemplo.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method

6

Jason,

Em vez de ter três atributos de objeto,

  • Posição do ponto (x, y)
  • Direção Vector2D (x, y)
  • Int velocidade

geralmente é muito mais fácil combinar a direção e a velocidade em um vetor de velocidade. Então você tem apenas dois atributos,

  • Posição do ponto (x, y)
  • Velocidade do vetor 2D (x, y)

Atualizando posição

Quando você precisa atualizar a posição do objeto, é tão simples quanto:

position.x += velocity.x * Δt;
position.y += velocity.y * Δt;

onde Δtestá seu delta de tempo - ou diferença de tempo - ou intervalo de tempo.

Atualizando posição e velocidade

Também é muito fácil lidar com a aceleração (como na gravidade). Se você tiver um vetor de aceleração, poderá atualizar a velocidade e a posição juntas assim:

position.x += (velocity.x * Δt) + (0.5 * acceleration.x * Δt * Δt);
position.y += (velocity.y * Δt) + (0.5 * acceleration.y * Δt * Δt);

velocity.x += acceleration.x * Δt;
velocity.y += acceleration.y * Δt;

(Esta é basicamente a fórmula s = vt + ½at² da Física 101.)

Aplicando uma velocidade

Se você deseja aplicar uma determinada velocidade em alguma direção normalizada, pode definir a velocidade da seguinte forma:

velocity.x = normalizedDirection.x * speed;
velocity.y = normalizedDirection.y * speed;

Derivando uma velocidade

E se você precisar fazer o inverso - derivando a velocidade e a direção de um determinado vetor de velocidade - você pode simplesmente usar o teorema de Pitágoras ou o .Length()método:

speed = velocity.Length();

E uma vez que a velocidade é conhecida, a direção normalizada pode ser calculada dividindo a velocidade pela velocidade (tomando cuidado para evitar a divisão por zero):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.