¿Convertir la hora del día en una variable suave de día / noche?

Estoy tratando de hacer un ciclo suave día / noche para un proyecto de juego en el que he estado trabajando. Ya he configurado un reloj que agrega deltaTime a segundos, ajusta segundos a gameMinutes, etc. El problema que estoy teniendo es que quiero que un float normalizado y firmado represente el día (+1) y la noche (-1), y no estoy exactamente seguro de cuál es la forma más efectiva de hacerlo.

Aquí está mi class de time en pseudocódigo:

class GameTime { float snDayNight; //signed normalized float seconds; int gameMinutes; int gameHours; int gameDays; int gameMonths; //Omitted consts used for wrapping (SEC_PER_MIN, HR_PER_DAY, etc.).. //Per-frame update.. public void Update(){ seconds += Timer.GetDeltaTime(); WrapTimeValues (); //Wraps sec to min, min to hr, etc. UpdateDayNightCycle (); } private void UpdateDayNightCycle(){ //????? } //...// } 

Por lo tanto, mi GameTime ha sido probado y parece estar funcionando bien; cuando el valor en segundos es> = el valor de SEC_PER_MIN agrega otro minuto y almacena la fracción restante de un segundo. Luego pasa a verificar minutos, horas, días, etc.

Sin embargo, he estado un poco atrapado en UpdateDayNightCycle (). Quiero poder convertir mi time en un valor decimal uniforme donde -1 representa la noche absoluta y 1 representa el día absoluto. He normalizado valores entre 0 ~ 1 y -1 ~ 1 antes, pero nunca he tratado de usar un valor normalizado para representar un valor periódico / periódico como night ~ day before ..

Intenté dibujar un gráfico simple donde la hora del día está en el eje xy el valor de la noche en el eje y. Lo que obtengo es esencialmente un gráfico de una onda triangular . Desafortunadamente mis habilidades matemáticas están un poco subdesarrolladas e incluso después de search fórmulas para ondas triangulares, he tenido problemas para implementarlo en mi código.

Entonces, ¿estoy incluso en el path correcto? ¿Cómo puedo convertir sin problemas el time de mi juego en un valor decimal único entre -1 y 1?

tl; dr

Func 1 en Wolfram Alpha :

1 - 2 * |(x mod 2) - 1|

O en tu caso específico:

 1 - 2 * |((time % entireDay) - halfDay) / halfDay| 

Incluso puedes usar una onda sinusal (mucho más bonita).

sin(x - pi/2)

Sin Wave en Wolfram Alpha

O en tu caso específico:

 sin (- pi / 2 + 2 * pi * time / entireDay); 

Larga y tediosa explicación en finos detalles:

Si en time militar: 00:00 (medianoche) es -1, 12:00 (mediodía) es 1 y 23:59 es de nuevo ~ -1, entonces estamos midiendo la distancia desde el mediodía (cuánto time hace mediodía o cuánto time hasta que es mediodía otra vez?). Luego negando el valor y restando uno.

Para medir la distancia en 1d usamos el operador abs: |7 - 5| = |3 - 5| = 2 |7 - 5| = |3 - 5| = 2 |7 - 5| = |3 - 5| = 2 (porque siete y tres son la distancia de guardado desde 5.

 float hours = gameHours + gameMinutes / 60.0 + seconds / 3600.0;//<time in hours with fracation> distanceFromNoon = |hours - 12.0|; // Equals 12 at most (so we"ll divide by 6) ""normalized distance"" = distanceFromNoon / 6.0; result = 1 - ""normalized distance""; or ""normalized time"" = -2 * |hours - 12| + 1; 

donde | | | | significa el valor absoluto de … Esto normalmente se logra con Math.abs();

Entonces obtienes:

 result = -2 * Math.abs(gameHours * 3600 + gameMinutes * 60 + seconds - 12 * 3600) / (3600) + 1;