Funkcja ruchu słonecznego?


9

Tak więc, biorąc pod uwagę sprite'a ustawionego na horyzoncie (x = 0, y = worldheight / 2) Staram się opracować funkcję, dzięki której słońce wzejdzie, a potem spadnie.

Najlepszym sposobem, aby to zrobić, byłaby funkcja grzechu, ale nie mam pojęcia, jak jej używać.

jeśli użyjemy y = sin (x), to x musiałby mieścić się w zakresie od 0 do pi dla pełnej krzywej, przy stałej prędkości dla X.

Wszelkie myśli lub sugestie?

Edycja: Dzięki chłopaki!

Słońce działa!

Odpowiedzi:


7

Jeśli chodzi o problem od 0 do pi, ogólnie wszystko, co musisz zrobić, to przeskalować X o mnożnik. Przykład:

y = sin(x * pi / worldWidth)

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

Jednak nie jest to krzywa, której prawdopodobnie szukasz. Powinieneś użyć formularza parametrycznego:

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

Ta kombinacja grzechu dla Y i cos dla X wykreśli elipsę.


Dzięki, to jest niesamowite. Nie jestem bardzo zorientowany na matematykę. Moje umiejętności matematyczne to w gruncie rzeczy rachunek podstawowy.
Ross

12

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, hoursktó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

+1 za zdumienie, żałuję tylko, że nie mogę zaznaczyć dwóch odpowiedzi!
Ross

Nie ma problemu, w każdym razie użyłem tych samych podstawowych formuł co Jimmy. :)
David Gouveia,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.