Movimento curvo entre dois pontos


15

Qual é uma boa técnica para permitir que um objeto se mova entre pontos em um bom movimento curvo?

A posição final também pode estar em movimento, como a trajetória de um míssil local.

Respostas:


11

Supondo que você queira que isso seja algo quadro a quadro (para onde o alvo possa estar se movendo) e não uma trajetória pré-computada, isso é realmente incrivelmente simples:

Em cada quadro, compare o vetor de velocidade do míssil com o vetor (posição alvo - posição míssil ) ; isto é, o vetor apontando do míssil para o alvo. Todo quadro, se os dois vetores não tiverem a mesma direção, gire o vetor de velocidade um pouco em direção ao outro vetor, para que todo quadro o míssil fique um pouco mais perto de olhar para o alvo.

Você pode determinar se deseja girar no sentido horário ou anti-horário, observando o sinal do produto cruzado entre os dois vetores.


[Editar] Código XNA-ish (não tenho XNA para testar isso):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Observe que, como rotationAnglepossui apenas três valores possíveis, todos os valores possíveis de Matrix.CreateRotationZ(rotationAngle)podem ser armazenados em cache, para que você não precise chamá-lo de todos os quadros.


Você poderia fornecer algum pseudo-código, pois sou novo em tudo isso. Atualmente, estou trabalhando apenas na 2ª dimensão, o que elimina algumas complicações.
Anonymouse

@anonymouse: com certeza, tente isso #
BlueRaja # Danny Pflughoeft 7/11

15

Existem duas técnicas possíveis:

A primeira técnica é fazer um frame-based simulação . Isso é bom se você estiver fazendo algo como um míssil local na jogabilidade, que não precisa atingir seu alvo exatamente.

Nesse caso, você deseja acompanhar a posição e a velocidade do objeto. Cada quadro observa a direção do alvo e a direção atual do movimento e ajusta a velocidade adequadamente.

Se você acertar a velocidade instantaneamente, seu míssil sempre atingirá o alvo. Mas se você ajustar a velocidade em uma pequena quantidade a cada quadro, seu míssil se curvará em direção ao alvo - e se ele se curvar lentamente o suficiente, o alvo poderá desviá-lo.

A segunda técnica é usar um método paramétrico . Isso é útil para animar coisas nas quais você deseja atingir seu alvo com precisão e previsibilidade. Nesse caso, você normalmente toma o "tempo" como parâmetro e o coloca em uma função de algum tipo.

Um conjunto de funções particularmente útil são as Equações de Movimento que você aprendeu na física do ensino médio. Aplicando-os aos dois eixos, você pode obter trajetórias balísticas. Com um pouco de matemática, você pode determinar os parâmetros iniciais para atingir um alvo - mesmo um em movimento, se ele se mover de forma previsível.

O XNA também fornece várias funções de interpolação e movimento curvo. Dê uma olhada na documentação para Vector2 e paraMathHelper . Eles fornecem algumas funções de interpolação que você pode usar e até combinar para fazer coisas interessantes. Por exemplo, disparando um míssil: Lerp(interpole linear) a posição do seu míssil desde o ponto inicial até a posição alvo e também leia essa posição do alvo de algum alvo inicial para a posição real (de mudança) do objeto alvo. Isso lhe dará um bom efeito de "travamento".

(Existem também algumas funções para a produção de curvas, por exemplo: CatmulRom, Hermite. Essas são provavelmente mais difíceis de usar com sucesso com um alvo em movimento.)

Se você procurar "flexibilização" (no contexto da animação), poderá obter algumas funções de interpolação mais interessantes que podem fornecer efeitos interessantes, como a aceleração.

Agora - você pode dizer que esta técnica fornece alguns resultados estranhos à medida que seu alvo se move. No entanto, na prática, desde que o seu projétil esteja se movendo mais rápido do que o seu alvo, geralmente parece bom. Se for um problema, você provavelmente deve estar usando uma técnica baseada em quadros de qualquer maneira.


3

Você pode procurar ondas senoidais ou possivelmente curvas de Bezier . Não sei se a abordagem da onda senoidal é normal, mas não vejo por que seria tão ruim.


O uso de curvas de Bezier com B-Splines permite uma representação bastante precisa de qualquer curva. Se você precisar de precisão, os splines do Cubic Hermit são um pouco mais precisos. Lembre-se de que, às vezes, a imprecisão fornece um toque bem-vindo de organicidade.
Doppelgreener

+1 para curvas de Bezier. Para o uso descrito, é provavelmente o mais fácil e o mais controlável.
Ggambett #

1

Você pode dar uma olhada em Steering Behaviors, conforme definido por Craig Reynolds: http://red3d.com/cwr/steer/

Isso geralmente é usado na IA para fazer com que os NPCs se movam em direção ao seu alvo.

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.