Função para o movimento do sol?

9

Então, dado um sprite do sol no horizonte (x = 0, y = altura do mundo / 2), estou tentando criar uma função para fazer o sol nascer e depois cair.

A melhor maneira de fazer isso seria a função sin, mas não tenho idéia de como usá-lo.

se usando y = sin (x), x teria que variar entre 0 e pi para uma curva completa, mantendo uma velocidade constante para X.

Quaisquer pensamentos ou sugestões?

Edit: Obrigado pessoal!

Sun trabalhando!

Ross
fonte

Respostas:

7

Em relação à questão de 0 a pi, em geral, tudo o que você precisa fazer é escalar o X por um multiplicador. Exemplo:

y = sin(x * pi / worldWidth)

http://www.wolframalpha.com/input/?i=Plot%5BSin%5Bx%5D%2C+%7Bx%2C+0%2C+Pi%7D%5D

No entanto, isso não corresponde à curva que você provavelmente está procurando. Você deve usar o formulário paramétrico:

t = 0 -> pi over the course of a day
y = sin(t)   -> goes from 0 up to 1 at noon, then down to 0 again
x = (1-cos(t))/2 -> starts at 0 goes up to 1 by sundown.

http://www.wolframalpha.com/input/?i=ParametricPlot%5B%7B1+-+Cos%5Bt%5D%2C+Sin%5Bt%5D%7D%2C+%7Bt%2C+0%2C+Pi% 7D% 5D

Essa combinação de pecado para Y e cos para X traçará uma elipse.

Jimmy
fonte
Obrigado, isso é incrível. Eu não sou muito centrada em matemática. Minhas habilidades em matemática são basicamente cálculos rudimentares.
Ross
12

Como Jimmy disse, uma elipse é provavelmente a melhor opção para esse movimento. Aqui estão algumas idéias sobre como realmente implementá-lo com um pouco mais de detalhes para os interessados.

Tomando tempo

Para iniciantes, você precisa de uma variável para acompanhar o tempo no mundo do jogo. Você pode implementá-lo como quiser, mas aqui está um exemplo. Vou usar uma variável chamadahours que varia de 0 a 24 (embora, quando chegue a 24, volte a 0).

Ao contrário da vida real, considerarei que o dia começa às 0 horas e a noite às 12 horas. Isso facilitará alguns dos cálculos.

Também vou definir a taxa em que o tempo do jogo muda em relação ao tempo real. Neste exemplo, a cada dois minutos em tempo real corresponderá a uma hora no jogo.

float hours = 0.0f;                       // From 0 to 24 wrapping around
const float HoursPerSecond = 1f / 120f;   // E.g. 2 minutes = 1 hour ingame

public void Update(float elapsed)
{
    hours += elapsed * HoursPerSecond;    // Advance clock
    if(hours >= 24f) hours -= 24f;        // Wrap around 24 hours
}

Configuração

Agora, antes de definir o movimento do sol, precisamos especificar alguns de seus parâmetros. Em particular, em qual valor X ele eleva do horizonte e em qual valor X ele cai no horizonte. Além disso, o que Y corresponde ao horizonte, e quão alto ele deveria subir acima dessa linha.

float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;

Cálculo das coordenadas do sol

Agora é hora de calcular a posição do nosso sol para uma determinada hora do dia. Usarei a mesma função paramétrica usada por Jimmy, mas com o domínio variando entre [0..2PI] (para trazer o sol de volta à sua posição original ao amanhecer):

x = (1-cos (t)) / 2

y = pecado (t)

Essa é uma boa função porque o valor X varia de 0 a 1 e depois volta a 0 novamente (que mapearemos para os valores X de início e fim do sol) e o valor Y começa em 0 e move-se até 1 e vice-versa. para 0 novamente (que seria a nossa parte do dia ) e depois repete exatamente a mesma coisa no lado negativo antes de voltar à posição original (que seria a nossa noite, embora o sol não seja atraído neste momento).

O primeiro passo é escalar as horas do intervalo [0..24) para o intervalo da nossa função que é [0..2PI):

float t = (hours / 24f) * MathHelper.TwoPi;          // Scale: [0..24) to [0..2PI)

Em seguida, aplicamos as funções para recuperar os valores entre 0 e 1, como falei acima:

float horizontal = (float)((1-Math.Cos(t)) / 2f);    // Changes: 0 1 0
float vertical = (float)(Math.Sin(t));               // Changes: 0 1 0 -1 0

E finalmente escalamos esses valores usando os parâmetros do sol:

float sunX = startX + (endX - startX) * horizontal;    // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical;         // Up and down around horizonY
David Gouveia
fonte
+1 por surpresa, meu único arrependimento é não poder marcar duas respostas!
Ross
Não tem problema, usei as mesmas fórmulas básicas que Jimmy de qualquer maneira. :)
David Gouveia