Funktion für Sonnenbewegung?

9

Angesichts eines am Horizont untergehenden Sonnensprites (x = 0, y = Welthöhe / 2) versuche ich, eine Funktion zu entwickeln, mit der die Sonne auf- und abfällt.

Der beste Weg, dies zu tun, wäre die Sündenfunktion, aber ich habe keine Ahnung, wie ich sie verwenden soll.

Wenn y = sin (x) verwendet wird, müsste x für eine vollständige Kurve zwischen 0 und pi liegen, während für X eine konstante Geschwindigkeit vorliegt.

Irgendwelche Gedanken oder Vorschläge?

Edit: Danke Jungs!

Sonne arbeitet!

Ross
quelle

Antworten:

7

In Bezug auf das Problem von 0 bis pi müssen Sie das X im Allgemeinen nur mit einem Multiplikator skalieren. Beispiel:

y = sin(x * pi / worldWidth)

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

Dies entspricht jedoch nicht ganz der Kurve, nach der Sie wahrscheinlich suchen. Sie sollten das parametrische Formular verwenden:

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

Diese Kombination von sin für Y und cos für X zeichnet eine Ellipse auf.

Jimmy
quelle
Danke, das ist großartig. Ich bin nicht sehr mathematisch. Meine Fähigkeiten in Mathematik sind so ziemlich nur rudimentäre Berechnungen.
Ross
12

Wie Jimmy sagte, passt eine Ellipse wahrscheinlich besser zu dieser Bewegung. Hier sind einige Ideen, wie Sie es tatsächlich mit etwas mehr Details für Interessierte implementieren können.

Zeit nehmen

Für den Anfang benötigen Sie eine Variable, um die Zeit in der Spielwelt zu verfolgen. Sie können es beliebig implementieren, aber hier ist ein Beispiel. Ich werde eine Variable namens verwenden hours, die von 0 bis 24 variiert (obwohl sie bei Erreichen von 24 wieder auf 0 zurückgesetzt wird).

Im Gegensatz zum wirklichen Leben werde ich nur bedenken, dass der Tag um 0 Uhr und die Nacht um 12 Uhr beginnt. Dies erleichtert einige Berechnungen.

Ich werde auch die Geschwindigkeit definieren, mit der sich die Spielzeit im Verhältnis zur Echtzeit ändert. In diesem Beispiel entspricht alle zwei Minuten Echtzeit einer Stunde im Spiel.

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
}

Aufbau

Bevor wir die Bewegung unserer Sonne untergehen, müssen wir einige ihrer Parameter angeben. Insbesondere bei welchem ​​X-Wert steigt es vom Horizont an und bei welchem ​​X-Wert fällt es in den Horizont. Außerdem, was Y dem Horizont entspricht und wie hoch er sich über diese Linie erheben soll.

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

Berechnung der Sonnenkoordinaten

Jetzt ist es Zeit, den Sonnenstand für eine bestimmte Tageszeit zu berechnen. Ich werde dieselbe parametrische Funktion verwenden, die auch von Jimmy verwendet wird, jedoch mit einer Domäne zwischen [0..2PI] (um die Sonne bei Tagesanbruch wieder in ihre ursprüngliche Position zu bringen):

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

y = sin (t)

Dies ist eine gute Funktion, da der X-Wert von 0 bis 1 und dann wieder zurück auf 0 variiert (was wir den X- und End-X-Werten unserer Sonne zuordnen werden) und der Y-Wert bei 0 beginnt und sich auf 1 und zurück bewegt wieder auf 0 (die unsere sein würde Tag Teil) und wiederholt dann die genau die gleiche Sache auf der negativen Seite , bevor sie wieder in die ursprüngliche Position kommt (was unser wäre Nacht , obwohl die Sonne an diesem Punkt nicht gezogen wird).

Der erste Schritt besteht darin, die Stunden vom Bereich [0..24) auf den Bereich unserer Funktion zu skalieren, der [0..2PI) ist:

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

Als nächstes wenden wir die Funktionen an, um die Werte zwischen 0 und 1 zurückzugewinnen, die ich oben erwähnt habe:

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

Und schließlich skalieren wir diese Werte anhand der Parameter der Sonne:

float sunX = startX + (endX - startX) * horizontal;    // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical;         // Up and down around horizonY
David Gouveia
quelle
+1 für Erstaunlichkeit, mein einziges Bedauern ist, dass ich nicht zwei Antworten markieren kann!
Ross
Kein Problem, ich habe sowieso die gleichen Basisformeln wie Jimmy verwendet. :)
David Gouveia