Come Jimmy ha detto che un'ellisse è probabilmente una misura migliore per questo movimento. Ecco alcune idee su come implementarlo effettivamente con un po 'più di dettaglio per gli interessati.
Prendere tempo
Per cominciare, hai bisogno di una variabile per tenere traccia del tempo nel mondo di gioco. Puoi implementarlo come preferisci, ma ecco un esempio. Userò una variabile chiamata hours
che varia da 0 a 24 (anche se quando raggiunge i 24 torna a 0).
A differenza della vita reale, però, prenderò in considerazione quel giorno che inizia a 0 ore e la notte inizia a 12 ore. Ciò renderà alcuni dei calcoli più facili.
Definirò anche la velocità con cui il tempo di gioco cambia rispetto al tempo reale. In questo esempio, ogni due minuti di tempo reale corrisponderanno a un'ora di gioco.
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
}
Configurazione
Ora, prima di impostare il movimento del nostro sole, dobbiamo specificare alcuni dei suoi parametri. In particolare, a quale valore X si alza dall'orizzonte ea quale valore X cade nell'orizzonte. Inoltre, ciò che Y corrisponde all'orizzonte e quanto in alto dovrebbe salire sopra quella linea.
float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;
Calcolo delle coordinate del sole
Ora è il momento di calcolare la posizione del nostro sole per un determinato momento della giornata. Userò invece la stessa funzione parametrica usata da Jimmy ma con un dominio che va da [0..2PI] (per riportare il sole nella sua posizione originale all'alba):
x = (1-cos (t)) / 2
y = sin (t)
Questa è una buona funzione perché il valore X varia da 0 a 1 e poi di nuovo a 0 (che mapperemo ai valori X di inizio e fine del nostro sole) e il valore Y inizia da 0 e si sposta da 1 a indietro a 0 di nuovo (che sarebbe la nostra porzione del giorno ) e quindi ripete la stessa identica cosa sul lato negativo prima di tornare alla posizione originale (che sarebbe la nostra notte anche se il sole non sarà disegnato a questo punto).
Il primo passo è ridimensionare le ore dall'intervallo [0..24) all'intervallo della nostra funzione che è [0..2PI):
float t = (hours / 24f) * MathHelper.TwoPi; // Scale: [0..24) to [0..2PI)
Quindi applichiamo le funzioni per recuperare i valori tra 0 e 1 di cui ho parlato sopra:
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 infine scaliamo quei valori usando i parametri del sole:
float sunX = startX + (endX - startX) * horizontal; // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical; // Up and down around horizonY