Eu estou olhando para criar movimento de carro realista usando vetores

12

Eu observei como fazer isso e achei isso http://www.helixsoft.nl/articles/circle/sincos.htm Eu já experimentei, mas a maioria das funções mostradas não funcionou, apenas obtive erros porque eles não existiam. Examinei as funções cos e sin, mas não entendo como usá-las ou como fazer o movimento do carro funcionar corretamente usando vetores. Não tenho código porque não tenho certeza do que fazer.

Qualquer ajuda é apreciada.

EDITAR:

Tenho restrições de que devo usar o mecanismo TL no meu jogo, não tenho permissão para adicionar nenhum tipo de mecanismo de física. Ele deve ser programado em c ++. Aqui está uma amostra do que recebi ao tentar seguir o que foi feito no link que forneci.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);
bobthemac
fonte
Confira este site em busca de comportamentos de direção: red3d.com/cwr/steer
MichaelHouse
Você precisa definir "movimento carro realista"
Maik Semder
1
Presumo que seu ângulo venha do volante, talvez. O comprimento deve ser a magnitude da sua velocidade. Assim, o último trecho de código poderia ser algo sobre as linhas de: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, para além de que, por favor, diga o que sua entrada é e como o carro deve se comportar. No momento, ele deve dirigir no plano de terra, mas, novamente, isso não é nada geral. Lá você acabou de nos feitos de um passo de integração Euler bruto ..
teodron

Respostas:

23

Não é tão difícil criar um movimento de carro bastante bom (mas este post será bastante longo). Você precisará "simular" algumas forças básicas para tornar o carro fisicamente plausível.

(Todos os exemplos de código são pseudocódigo.)

Aceleração

Primeiro, você obviamente precisará de aceleração. Algo tão simples quanto a seguinte linha faria:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Um vetor apontando na mesma direção que o carro.
  • acceleration_input - A entrada deve estar no intervalo [-1, 1].
  • acceleration_factor - O valor da aceleração (pixels / segundo ^ 2 ou quaisquer que sejam suas unidades).

Direção

A direção também é bastante simples. Em princípio, o que você fará é girar o vetor para frente do carro para apontá-lo em outra direção.

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

Você pode encontrar uma complicação aqui, no entanto. Se sua entrada for através de um teclado, seu valor será -1 ou 1, o que significa que seu carro giraria instantaneamente. Você pode corrigir isso usando uma interpolação linear muito simples (lerping):

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

A quantia deve depender do tempo, para que seu movimento não dependa da taxa de quadros. A quantidade deve estar entre [0, 1] e quanto menor, mais suave será a transição entre os vetores antigos e novos.

(Nesse ponto, você descobrirá que o carro dirigirá mesmo que esteja parado. Para evitar isso, multiplique steer_anglepor current_speed / max_speed, onde max_speedé uma constante definida por você.)

Movendo

Agora aplicaremos a aceleração e moveremos o carro com um certo número de pixels com base em sua velocidade, aceleração e direção. Também queremos limitar a velocidade do carro para que ele não se mova infinitamente rápido.

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Seu carro está deslizando agora

Se eu estiver certo, seu carro deve parecer deslizar sempre que você estiver virando como se estivesse no gelo. Isso ocorre porque não há atrito. Em um carro real, há um alto atrito lateral (devido às rodas não poderem girar para o lado: P).

Você precisará reduzir a velocidade lateral. Ao não reduzi-lo completamente, você também pode fazer o carro parecer estar à deriva.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

Como estamos falando de fricção, você também pode querer ter uma força (de fricção) que reduz sua velocidade, de modo que, quando você para de acelerar, seu carro acaba parando.

 backwards_friction = -velocity_vector * backwards_friction_factor

Seu código para mover o carro agora deve ficar assim:

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Notas finais

Mencionei como você deve aplicar o lerping à direção; Eu acho que você pode precisar fazer o mesmo para a aceleração e, possivelmente, também para o ângulo de direção (você terá que armazenar seus valores do quadro anterior e lerp a partir disso). Todos os vetores relativos ao carro (frente, direita, cima) também devem ter o comprimento 1.

Além disso, o atrito é um pouco mais complicado do que mostrei aqui. Você deve sempre garantir que seu comprimento nunca seja maior que o da aceleração necessária para fazer o carro parar (caso contrário, o atrito faria o carro se mover na direção oposta). Então você deve ter algo como:

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))
Paul Manta
fonte
Uau, esta é uma ótima resposta!
ezolotko
0

A julgar pela sua pergunta, vou assumir que você é relativamente novo em programação (o que é ótimo!). Eu sugeriria o uso de estruturas existentes, pois a simulação realista de carros é um dos aspectos mais difíceis da física para acertar.

Você não mencionou restrições em 2D / 3D, por isso vou sugerir que você faça o download do Havok SDK (gratuito para uso não comercial) e obtenha uma demonstração simples em funcionamento (na verdade, eles têm demos que ficam prontas para uso imediato [get compilado em seu sistema, todo o código existe], você não precisa fazer nada para compilá-lo ... basta abrir o projeto e clicar em build).

Depois de ter uma idéia dos aspectos dos bastidores da física do carro (embora você não veja a implementação real da física, que está oculta, você verá as interfaces), acredito que estará em uma posição melhor para acertar quando você começar por conta própria.

Também fiz uma pergunta semelhante há pouco tempo. Os links podem ajudar também. E aqui está outro link .


Depois de analisar a sua edição, parece que você está simplesmente alterando a velocidade do carro, dependendo dos ângulos calculados (que não são realistas, então você deve alterar a pergunta original para refletir isso). Se os ângulos fazem parte da pergunta (que você não pode mudar) e você precisa usá-los para calcular a nova velocidade, siga o que @teodron colocou nos comentários.

Outra maneira é usar apenas vetores. Existem várias abordagens usando vetores, vou apresentar uma.

Uma velocidade é direção * magnitude (onde magnitude é velocidade e direção é um vetor normalizado). Calcule a velocidade e direção atuais do carro. Pegue a direção e adicione um vetor (vamos chamá-lo D') a ele que é perpendicular a ele. Isso mudará a velocidade do carro. Sem ângulos para mexer (embora você possa usar ângulos para determinar o comprimento do vetor perpendicular, que pode ser o fator de virada [veja abaixo])

Como calcularD' : para encontrar o vetor perpendicular, tome a direção da velocidade original, atravesse-o com o vetor de direção vindo para a tela em que a ordem na qual você cruza os vetores determina a direção do vetor perpendicular. Então multiplique esse fator perpedicular com algum fator de virada que determina a rapidez com que o carro gira.

Samaursa
fonte
Eu usaria, mas não tenho permissão para usar um mecanismo de física, o jogo é 3D e tudo o que preciso mudar são os vetores X e Z; só preciso descobrir o que são.
precisa
@bobthemac: Esta é uma pergunta de lição de casa? Se sim, edite sua pergunta para apontar as restrições que você possui e, talvez, publique algum código relevante para que possamos desenvolver algo. Aliás, o último link pode ser o que você está procurando em termos de compreensão da funcionalidade.
Samaursa
Adicionei as informações solicitadas e verifiquei os links fornecidos, mas ainda não os entendemos.
bobthemac
@bobthemac: Veja minha edição
Samaursa