Ponto V!

Home Matemática e Física Movimento Retilíneo Uniforme Variado (MRUV) - XNA
Kléber de Oliveira Andrade
Movimento Retilíneo Uniforme Variado (MRUV) - XNAImprimir
Escrito por Kleber Andrade

Neste tutorial veremos que um movimento em que a velocidade não é mais constante. No Movimento Retilíneo Uniforme Variado (MRUV) passa a existir a aceleração, isso significa que a velocidade varia de uma forma uniforme. Como exemplo, poderíamos citara uma bola de sinuca logo após a tacada (e antes de chocar com as outras bolas ou com a mesa), uma maçã caindo de uma certa altura ou até mesmo um carro freando ao ver o sinal vermelho. O código deste tutorial foi criado e testado no XNA 4.0, ou seja, qualquer mudança de versão pode acarretar ou não em reajustes no código.

Nesse movimento a velocidade do objeto aumenta ou diminui a cada intervalo de tempo.

  • Movimento Acelerado

  • Movimento Retardado

Ao tratarmos este movimento, devemos atualizar a posição do objeto e também sua velocidade a cada atualização do jogo. Conforme a função velocidade, quando um objeto esta em MRUV a sua velocidade (v) na velocidade anterior (vo) somada a multiplicação da aceleração (a) pelo tempo (t).

v = vo + a * t

A atualização da posição do objeto deve considerar não apenas sua velocidade, como também sua aceleração. Segundo a função horária do MRUV, dada a posição anterior do objeto (So), sua velocidade anterior, sua aceleração e o tempo do intervalo, a posição atual de um objeto (S) pode ser definida pela seguinte fórmula.

S = So + vo * t + (a * t * t) / 2

No exemplo a seguir foram definidas aceleração de 500 pix/s² e velocidade igual a zero. Na rotina de Update são feitas as atualizações da posição e da velocidade do objeto conforme as funções horária e a velocidade do MRUV

Exemplo no XNA:

1º passo: Crie um novo projeto (Windows Game) e crie variáveis para armazenar a posição, velocidade, aceleração e textura do objeto.

// Informações do carro
 private Vector2 posicao;
 private float velocidade;
 private float aceleracao;
 private Texture2D imagem;

2º passo: Inicialize a posição do objeto e defina a sua velocidade inicial e aceleração que será constante, tudo isso dentro do método Initialize()

protected override void Initialize()
{
      // Posição inicial do carro
      posicao= new Vector2(0.0f, 300.0f);
      // Configura a velocidade inicial do carro
      velocidade = 0.0f;
      // Configura a aceleração
      aceleracao = 500.0f;
      base.Initialize();
}

3º passo: Copie a textura abaixo ou outra imagem de sua preferência para você carregar e aplicar o MRUV.

protected override void LoadContent()
{
     // Create a new SpriteBatch, which can be used to draw textures.
     spriteBatch = new SpriteBatch(GraphicsDevice);
     // Carrega a textura do carro
     imagem = Content.Load<Texture2D>(@"car");
}

4º passo: Vamos desenhar a imagem na tela

protected override void Draw(GameTime gameTime)
{
     GraphicsDevice.Clear(Color.CornflowerBlue);
     spriteBatch.Begin();
     // Desenha o carro
     spriteBatch.Draw(imagem, posicao, Color.White);
     spriteBatch.End();
     base.Draw(gameTime);
}

5º passo: Para concluir vamos aplicar a fórmula descrita no nosso objeto

protected override void Update(GameTime gameTime)
{
     // Tempo passado desde a ultima atualização
     float tempo = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0f);
     // Atualiza a posição do carro
     // S = So + vo * t + (a * t * t) / 2
     posicao.X += (velocidade * tempo) + ((aceleracao * (float)Math.Pow(tempo, 2)) / 2.0f);
     // Atualiza velocidade do objeto
     // v = vo + a * t
     velocidade += aceleracao * tempo;
     base.Update(gameTime);
}

Com esta rotina é chamada a cada laço do jogo, o que será exibido na tela é um objeto (carro) se deslocando no eixo X com aceleraação de 500 pix/s².

Resultado

Após compilar (F5) seu código sem erro, você vai obter o seguinte resultado.

Download

Para fazer download do código criado neste tutorial, clique no ícone de download abaixo.

image


Comentários (15)
  • Jarbes
    avatar

    Bacana, mas acho que poderia ter detalhado melhor a física, menos técnico.

    Mas ajudou, Parabéns !

  • Kleber Andrade
    avatar

    Olá realmente poderia ter detalhado bem melhor esta física, mas não era muito o foco do tutorial. Era mais mostrar o que o pessoal viu na escola e conseguir aplicar na programação. Porém irei pensar em fazer depois alguma coisa mais detalhada conforme sugestão. Obrigado.

  • Lucas Lugão Guimarães  - Errom comum
    avatar

    Li o artigo e percebi que calculando a diferença ente a posição do carro nos 20 primeiro segundos podemos perceber uma diferença de cerca de 167 pixels para a posição ideal, calculada usando as equações providas aqui no artigo (500*20²/2 = 100000)

    Como não quero apenas apontar o erro nesse metodo, sugiro uma outra forma de abordar o MRUV:
    posicao.X += velocidade * tempo;
    velocidade += aceleracao * tempo;

    Dessa maneira teremos um carro se movendo em um MRUV melhor aproximado.
    Calculando a diferença entre a posição ideal e a posição desse segundo metodo podemos perceber uma diferença de cerca de 83 pixels, o que é 50% da diferença observada no metodo do artigo.

    Espero ter ajudado, um abraço!

  • Vinícius Godoy de Mendonça
    avatar

    Ótima observação.

    O objetivo dessa série de artigos é demonstrar a física da escola. Se você quiser ler artigos sobre a física de maneira mais iterativa, como é feita em games, veja nossa série sobre vetores:
    http://www.pontov.com.br/site/arquitetura/54-matematica-e-fisica/132-o -uso-de-vetores-nos-jogos

    Por enquanto, ainda não coloquei lá um artigo sobre física, pois estava focando mais no uso de vetores para CG. Mas sua sugestão, além de mais precisa computacionalmente, é também mais leve, pois exige cálculos bem mais simples a cada ciclo do gameloop.

    A fórmula vetorial precisa é:
    position += (momentum + acellSecs/2) * secs;
    momentum += accelSecs;

    Onde momentum refere-se a velocidade instantânea do corpo, acellSecs é a taxa de aceleração por segundo, e position a posição. Todos na forma de vetores.

  • Kleber Andrade
    avatar

    Olá Lucas, obrigado pela sugestão e observação. Obrigado também Vinicius pela resposta rápida uma vez que na parte da manhã eu não estava presente.

    Porém Lucas, devo lhe apontar que a solução programada condiz com a fórmula apresentada. Primeira coisa, verifique se a posição que você calculou é a posição da traseira do veículo ou a posição da dianteira, pois a posição nos jogos é sempre a superior esquerda (posição de desenho, e a figura do carro tem exatamente 164 pixels, então se você calcular pela dianteira você terá 164 pixels mais uma pequena diferença no tempo que não será 20 segundos redondos).

    Provando ainda o que eu falei, eu montei um sistema de log e gravei o tempo, velocidade e posição do veículo respectivamente. Segue abaixo o log gravado (o log gravou a cada instante de tempo, porém estou colocando somente os segundos):

    0 | 0 | 0
    1,000002 | 250,0009 | 500,0007
    2,000001 | 1000,004 | 1000,003
    3 | 2250,011 | 1500,005
    4 | 4000,021 | 2000,008
    5,000013 | 6250,032 | 2500,004
    6,000026 | 9000,039 | 2999,999
    7,00004 | 12250,04 | 3499,994
    8,000052 | 16000,04 | 3999,989
    9,000037 | 20250,04 | 4499,996
    10,00002 | 25000,05 | 5000,006
    11,00001 | 30250,07 | 5500,016
    12,01666 | 36100,17 | 6008,359
    13,01664 | 42358,55 | 6508,369
    14,01663 | 49116,94 | 7008,378
    15,01661 | 56375,33 | 7508,388
    16,0166 | 64133,74 | 8008,398
    17,01658 | 72392,16 | 8508,39
    18,01657 | 81150,54 | 9008,37
    19,01655 | 90408,93 | 9508,351
    19,99987 | 100000,6 | 9999,998
    20,01654 | 100167,3 | 10008,33

    Percebemos pelo log armazenado que a posição após os 20 segundos (seja tanto 9999,998 ou 10008,33 dado a diferença de tempo) condiz com o calculado pela fórmula (500*20²/2 = 100000).

    Foi legal demonstrar isso, pois realmente eu não tinha feito um teste de funcionamento e sua observação me alertou para fazer isso e provar que esta ok para quem for estudar esse material.

    Obrigado pela sugestão e Vinicius por complementar a resposta.

  • Vinícius Godoy de Mendonça
    avatar

    É interessante apontar que, as soluções iterativas (como a que eu e o Lucas apontamos) tendem a ter perda de precisão com o tempo, enquanto a solução do Kleber tem a taxa de imprecisão constante.

    A imprecisão da nossa solução também oscila com a taxa de quadros por segundo muito mais que a do Kleber.

    A vantagem das soluções iterativas são apenas 2:
    - Baixo custo computacional;
    - A solução vetorial é facilmente adaptável para incluir várias forças no sistema (aceleração, vento, gravidade, atrito, etc).

    Se precisar de física mais avançada, o ideal é mesmo recorrer a uma engine. Não só ela encapsulará os cálculos, como possui algorítmos específicos para evitar erros. Algumas engines tem inclusive diferentes classes para resolução de fórmulas, focadas em performance ou precisão.

  • Lucas Lugão Guimarães
    avatar

    E ai Kleber! Obrigado pela rápida resposta. Logo após postar aqui, li mais sobre métodos de iteração em sistemas computacionais e descobri que o que eu propus é o método de Euler que resolve a equação diferencia d²x/dt² = a. Indo mais a fundo no assunto encontrei sobre o método Runge–Kutta que possui uma precisão de quarta ordem, ou seja, muito mais preciso que o de Euler.
    Se possível, poderia fazer um tutorial de como implementá-la na plataforma XNA? Vi que as engines de física usam desse método como o padrão.

    Vinícius, sobre a sua implementação usando o momento, você estaria falando sobre a 2ª lei de newton reduzida? F = dP/dt sendo P o momento linear, se sim você acha que é possível utilizar da mesma ideia para o cálculo angular T = dL/dt onde T é o torque e L o momento angular?

    Desde já agradeço.
    Abraço1

  • Vinícius Godoy de Mendonça
    avatar

    Sim, a formulação que passei é baseada na primeira e segunda leis de Newton. A idéia é justamente representar a força de momento, e usar outras forças (representadas por vetores) do sistema de força para atuar sobre ela.

    Na prática, a formulação final fica parecida com a da física de segundo grau, justamente pela abstração promovida pelos vetores.


    Eu já pensei em montar um artigo sobre o método de Runge-Kutta, e outros métodos numéricos interessantes para computação. É bom ver que tem gente de fora do site pedindo, vou pensar com mais carinho nisso. :)


    Quanto ao método de Euler, acho que você vai gostar de ler esse artigo: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html

  • Vinícius Godoy de Mendonça
    avatar

    Sim, a formulação que passei é baseada na primeira e segunda leis de Newton. A idéia é justamente representar a força de momento, e usar outras forças (representadas por vetores) do sistema de força para atuar sobre ela.

    Na prática, a formulação final fica parecida com a da física de segundo grau, justamente pela abstração promovida pelos vetores.


    Eu já pensei em montar um artigo sobre o método de Runge-Kutta, e outros métodos numéricos interessantes para computação. É bom ver que tem gente de fora do site pedindo, vou pensar com mais carinho nisso. :)


    Quanto ao método de Euler, acho que você vai gostar de ler esse artigo: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html


    EDIT: Quase esqueço de responder sua outra pergunta. Creio que seja possível usar algo parecido para o momento angular, pelo menos em 2D. Mas nunca parei para implementar algo muito elaborado nesse sentido, pois esse é justamente o ponto onde opto por usar uma engine de física.

    Afinal, se representar o momento angular for muito relevante, passa também a ser necessário falar de local de ponto de impacto, direção da força de impacto, eixo de rotação, etc. Em jogos mais simples, basta usarmos uma velocidade angular, e alterarmos "no feeling", como se o corpo limitasse ou pudesse controlar essa velocidade.

    Novamente, recai na questão do que queremos simular.

  • Lucas Lugão Guimarães
    avatar

    Vinícius obrigado pelas respostas! Se puder me deixar a par de seus artigos ficarei grato, estou estudando mecânica e vi na programação uma forte chave pra simular movimentos mais complexos. Porém, como havia dito, isso recai em métodos mais complexos de integração numérica que é o caso do RK4, se puder me ajudar com a implementação do mesmo em um simulador de orbitas ficarei muito grato.

  • Vinícius Godoy de Mendonça
    avatar

    Legal. Você já seque nosso twitter, ou tem nossos artigos em seu reader?

    Se quiser assinar nossos feeds:
    http://www.pontov.com.br/site/component/bca-rss-syndicator/?feed_id=13

    E nosso twitter é @pontov.


    Infelizmente, a simulação para jogos é bem diferente do que você precisará para mecânica. Aqui, estamos mais preocupados com velocidade do que precisão.

    Mas certamente poderemos trocar algumas figurinhas. Hoje em dia, estou me focando mais em computação gráfica (que é outra área extremamente matemática), mas procuro não me desligar da física de maneira geral. :)

  • Jarbes
    avatar

    Muito bacana os artigos MRU, MRUV ainda mais baseado em tempo.
    tentei aplicar a um lançamento de projétil, mas tive dificuldade devido a necessidade de captar o angulo do lançamento.

    Minha alternativa foi a usada abaixo, mas nesse caso não consegui fazer baseado em tempo.

    vetor.Y= velocidade.Y * cos(angulo);
    vetor.X= velocidade.X * - sin(angulo);

    a cada chamada ao update:
    {
    posição.Y + = vetor.Y;
    posição.X + = vetor.X;
    //Não atualizo o vetor.X por ser MRU, já o vetor.Y somo a gravidade.
    vetor.Y + =gravidade;
    }
    Alguma ideia de como fazer esse update baseado em tempo, se tiver tudo errado é só falar, minha física é péssima (por enquanto)

    Abraço

  • Kleber Andrade
    avatar

    Ola amigo, entendi o que você quis fazer. Sua lógica não esta errada não, porém isso será em partes respondido no próximo tutorial sobre lançamento Oblíquo.

    Onde justamente é lançado uma bola. Vou até colocar um exemplo extra neste artigo sobre lançar conforme um ângulo.

    Abraços.

  • Jarbes
    avatar

    Obrigado, aguardo o artigo.

  • Vitor Almeida da Silva  - Excelente.
    avatar

    Excelente esses artigos com um conceito por vez, muito didáticos.

    Tomei a liberdade de fazer o mesmo exemplo em Unity (e fiz um projeto rápido aqui comparando o movimento retilíneo uniforme com o uniforme variado, serve bem para ver o efeito da aceleração no tempo).

    --------------------
    1 - crie uma cena simples com um cubo
    2 - insira um script chamado "MovimentoRetilineoUniformeVariado.js" no cubo
    3 - insira o código abaixo:


    var velocidade : float = 4.0f;
    var aceleracao : float = 2.0f;

    function Update() {
    // tempo passado desde a ultima atualizacao
    var tempo : float = Time.deltaTime;

    // S = So + vo * t + (a * t * t) / 2
    transform.position.x += (velocidade * tempo) + ((aceleracao * Mathf.Pow(tempo, 2)) / 2.0f);

    // atualiza a velocidade do objeto
    // v = vo + a * t
    velocidade += aceleracao * tempo;
    }

    --------------------

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter