Estou tão sem matemática que dói, mas para alguns de vocês isso deve ser um pedaço de bolo. Quero mover um objeto em torno de outro ao longo de suas idades ou circunferências em um caminho circular simples. No momento, meu algoritmo de jogo sabe como mover e posicionar um sprite na beira de um obstáculo e agora aguarda o próximo ponto se mover, dependendo de várias condições.
Portanto, o problema matemático aqui é como obter as posições (aX, aY) e (bX, bY) , quando conheço o centro (cX, cY), a posição do objeto (oX, oY) e a distância necessária para mover (d)
java
mathematics
Lumis
fonte
fonte
d
uma distância linear ou é um arco?Respostas:
( CAVEAT: Estou usando duas aproximações aqui: a primeira leva d como comprimento do arco e a segunda leva como comprimento ortogonal. Ambas as aproximações devem ser boas para valores relativamente pequenos de d, mas não cumprem a pergunta precisa, conforme esclarecido nos comentários.)
A matemática sobre isso, felizmente, é relativamente direta. Primeiro de tudo, podemos encontrar o vetor relativo da nossa posição central para a nossa posição atual:
E uma vez que tenhamos esse vetor relativo, podemos saber o raio do círculo em que estamos trabalhando, encontrando o comprimento dele:
Além disso, do nosso vetor relativo, podemos encontrar o ângulo preciso em que a linha de cX a oX está:
Agora as coisas ficam um pouco mais complicadas. Antes de tudo, entenda que a circunferência de um círculo - ou seja, o 'comprimento do arco' de um arco com uma medida angular de 2π - é 2πr. Em geral, o comprimento do arco com uma medida angular de θ ao longo de um círculo de raio r é apenas θr. Se usarmos d no seu diagrama como o comprimento do arco, e como conhecemos o raio, podemos encontrar a mudança no teta para nos levar à nova posição apenas dividindo:
Para o caso em que d precisa ser uma distância linear, as coisas são um pouco mais complicadas, mas felizmente não muito. Lá, d é um lado de um triângulo de isoceles cujos outros dois lados são o raio do círculo (de cX / cY a oX / oY e aX / aY, respectivamente), e dividir esse triângulo de isoceles nos dá dois triângulos retângulos, cada um dos quais tem d / 2 como um lado e raio como hipotenusa; isso significa que o seno da metade do nosso ângulo é (d / 2) / raio e, portanto, o ângulo completo é apenas o dobro disso:
Observe como se você tirasse o asin desta fórmula e cancelasse os 2s, isso seria o mesmo que a última fórmula; é o mesmo que dizer que sin (x) é aproximadamente x para pequenos valores de x, o que é uma aproximação útil para se conhecer.
Agora podemos encontrar o novo ângulo apenas adicionando ou subtraindo:
Depois de termos o novo ângulo, podemos usar alguns triggers básicos para encontrar nosso vetor relativo atualizado:
e da nossa posição central e do nosso vetor relativo, podemos (finalmente) encontrar o ponto alvo:
Agora, com tudo isso, existem algumas advertências importantes a serem observadas. Por um lado, você notará que essa matemática é principalmente de ponto flutuante e, na verdade, quase precisa ser; tentar usar esse método para atualizar em um loop e arredondar de volta para valores inteiros a cada etapa pode fazer de tudo, desde fazer o seu círculo não fechar (espiralando para dentro ou para fora toda vez que você percorre o loop) até não iniciar no primeiro Lugar, colocar! (Se seu d é muito pequeno, você pode descobrir que as versões arredondadas de aX / aY ou bX / bY estão exatamente onde estava a sua posição inicial oX / oY.) Por outro lado, isso é muito caro, especialmente pelo que está tentando Faz; em geral, se você sabe que seu personagem se moverá em um arco circular, planeje todo o arco com antecedência e nãomarque-o de quadro em quadro como este, pois muitos dos cálculos mais caros aqui podem ser carregados com antecedência para reduzir custos. Outra boa maneira de reduzir os custos, se você realmente deseja atualizar de forma incremental como essa, é não usar trigonometria em primeiro lugar; se d for pequeno e você não precisar que seja exato, mas apenas muito próximo, poderá fazer um 'truque' adicionando um vetor de comprimento d a oX / oY, ortogonal ao vetor em direção ao seu centro (observe que um o vetor ortogonal a (dX, dY) é dado por (-dY, dX)) e depois reduza-o para o comprimento certo. Não vou explicar esse código passo a passo, mas espero que faça sentido, considerando o que você viu até agora. Observe que "reduzimos" o novo vetor delta implicitamente na última etapa,
fonte
Forme um triângulo usando os dois lados que você já possui (um lado é de 'c' a 'o', o outro de 'o' a 'a') e o terceiro lado vai de 'a' a 'c'. Você ainda não sabe onde 'a' está, apenas imagine que há um ponto lá por enquanto. Você precisará da trigonometria para calcular o ângulo do ângulo oposto ao lado 'd'. Você tem o comprimento dos lados c <-> o e c <-> a, porque ambos são o raio do círculo.
Agora que você tem o comprimento dos três lados deste triângulo que ainda não pode ver, é possível determinar o ângulo oposto ao lado 'd' do triângulo. Aqui está a fórmula do SSS (lado a lado) se você precisar: http://www.teacherschoice.com.au/maths_library/trigonometry/solve_trig_sss.htm
Usando a fórmula SSS, você tem o ângulo (que chamaremos de 'j') oposto ao lado 'd'. Então, agora podemos calcular (aX, aY).
Verifique se os ângulos calculados estão sempre em radianos.
Se você precisar calcular o raio do círculo, poderá usar a subtração vetorial, subtrair o ponto 'c' do ponto 'o' e obter o comprimento do vetor resultante.
Algo assim deve fazer, acredito. Como não conheço Java, adivinhei a sintaxe exata.
Aqui está a imagem fornecida pelo usuário
Byte56
para ilustrar a aparência desse triângulo:fonte
Para fazer obj2 girar em torno de obj1, talvez tente:
fonte