Como Jimmy dijo, una elipse es probablemente una mejor opción para este movimiento. Aquí hay algunas ideas sobre cómo implementarlo realmente con un poco más de detalle para los interesados.
Tomando tiempo
Para empezar, necesitas una variable para hacer un seguimiento del tiempo en el mundo del juego. Puede implementarlo de la manera que desee, pero aquí hay un ejemplo. Usaré una variable llamada hours
que varía de 0 a 24 (aunque cuando llega a 24 vuelve a 0).
Sin embargo, a diferencia de la vida real, consideraré que el día comienza a las 0 horas y la noche comienza a las 12 horas. Esto facilitará algunos de los cálculos.
También definiré la velocidad a la que cambia el tiempo del juego en relación con el tiempo real. En este ejemplo, cada dos minutos de tiempo real corresponderá a una hora en el juego.
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
}
Configuración
Ahora, antes de configurar el movimiento de nuestro sol, necesitamos especificar algunos de sus parámetros. En particular, a qué valor X sube del horizonte, y a qué valor X cae en el horizonte. Además, lo que Y corresponde al horizonte, y qué tan alto se supone que debe elevarse por encima de esa línea.
float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;
Cálculo de las coordenadas del sol
Ahora es el momento de calcular la posición de nuestro sol para un momento determinado del día. Usaré la misma función paramétrica utilizada por Jimmy pero con el dominio que va desde [0..2PI] en su lugar (para que el sol vuelva a su posición original al amanecer):
x = (1-cos (t)) / 2
y = sin (t)
Esta es una buena función porque el valor X varía de 0 a 1 y luego nuevamente a 0 (que asignaremos a los valores X iniciales y finales de nuestro sol) y el valor Y comienza en 0 y sube a 1 y regresa a 0 nuevamente (que sería nuestra porción del día ) y luego repite exactamente lo mismo en el lado negativo antes de volver a la posición original (que sería nuestra noche, aunque el sol no se dibujará en este punto).
El primer paso es escalar las horas desde el rango [0..24) al rango de nuestra función que es [0..2PI):
float t = (hours / 24f) * MathHelper.TwoPi; // Scale: [0..24) to [0..2PI)
A continuación, aplicamos las funciones para recuperar los valores entre 0 y 1 que mencioné anteriormente:
float horizontal = (float)((1-Math.Cos(t)) / 2f); // Changes: 0 1 0
float vertical = (float)(Math.Sin(t)); // Changes: 0 1 0 -1 0
Y finalmente escalamos esos valores usando los parámetros del sol:
float sunX = startX + (endX - startX) * horizontal; // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical; // Up and down around horizonY