Jak powiedział Jimmy, elipsa jest prawdopodobnie lepszym rozwiązaniem dla tego ruchu. Oto kilka pomysłów na to, jak go wdrożyć z nieco bardziej szczegółowymi informacjami dla zainteresowanych.
Poświęcać czas
Na początek potrzebujesz zmiennej, aby śledzić czas w świecie gry. Możesz to zaimplementować w dowolny sposób, ale oto przykład. Użyję zmiennej o nazwie, hours
która zmienia się od 0 do 24 (chociaż gdy osiągnie 24, zawija się z powrotem do 0).
Jednak w przeciwieństwie do prawdziwego życia, po prostu wezmę pod uwagę, że dzień zaczyna się o godzinie 0, a noc zaczyna się o godzinie 12. Ułatwi to niektóre obliczenia.
Zdefiniuję także szybkość zmian czasu gry w stosunku do czasu rzeczywistego. W tym przykładzie co dwie minuty czasu rzeczywistego odpowiadają jednej godzinie w grze.
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
}
Konfiguracja
Teraz przed ustawieniem ruchu Słońca musimy podać kilka jego parametrów. W szczególności przy jakiej wartości X podnosi się z horyzontu i przy jakiej wartości X spada do horyzontu. Ponadto, co Y odpowiada horyzontowi i jak wysoko ma on wznieść się powyżej tej linii.
float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;
Obliczanie współrzędnych Słońca
Teraz nadszedł czas, aby obliczyć położenie naszego słońca dla danej pory dnia. Zamiast tego użyję tej samej funkcji parametrycznej, której używał Jimmy, ale z domeną w zakresie od [0..2PI] (aby przywrócić słońce do pierwotnej pozycji przed świtem):
x = (1-cos (t)) / 2
y = sin (t)
Jest to dobra funkcja, ponieważ wartość X zmienia się od 0 do 1, a następnie z powrotem do 0 (co będziemy mapować do początkowych i końcowych wartości naszego Słońca), a wartość Y zaczyna się od 0 i przesuwa się do 1 i wstecz ponownie do 0 (co byłoby naszą porą dzienną ), a następnie powtarza dokładnie to samo po stronie negatywnej przed powrotem do pierwotnej pozycji (która byłaby naszą nocą, chociaż słońce nie zostanie w tym momencie wyciągnięte).
Pierwszym krokiem jest skalowanie godzin z zakresu [0..24) do zakresu naszej funkcji, którym jest [0..2PI):
float t = (hours / 24f) * MathHelper.TwoPi; // Scale: [0..24) to [0..2PI)
Następnie zastosujemy funkcje, aby odzyskać wartości od 0 do 1, o których mówiłem powyżej:
float horizontal = (float)((1-Math.Cos(t)) / 2f); // Changes: 0 1 0
float vertical = (float)(Math.Sin(t)); // Changes: 0 1 0 -1 0
Na koniec skalujemy te wartości przy użyciu parametrów słońca:
float sunX = startX + (endX - startX) * horizontal; // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical; // Up and down around horizonY