Monday, February 6, 2017

mathematics - Converting time of day into a smooth day/night variable?


I'm trying to make a smooth day/night cycle for a game project that I've been working on. I've already set up a clock that adds deltaTime to seconds, wraps seconds to gameMinutes, etc. The issue that I'm having is that I want a signed normalized float to represent day (+1) and night (-1), and I'm not exactly sure what the most effective way of doing that is.


Here's my time class in pseudocode:


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(){
//?????
}

//...//
}


So, my GameTime has been tested and seems to be working fine; when the value in seconds is >= the value of SEC_PER_MIN it adds another minute and stores the leftover fraction of a second. It then goes on to check minutes, hours, days, etc.


I've been a little bit stuck at UpdateDayNightCycle() though. I want to be able to convert my time into a smooth decimal value where -1 represents absolute night and 1 represents absolute day. I've normalized values between 0~1 and -1~1 before, but I've never tried to use a normalized value to represent a repeating/periodic value like night~day before..


I tried drawing a simple graph where time of day is on the x-axis and daynight value is on the y-axis. What I get is essentially a graph of a triangle wave. Sadly my math skills are a little bit underdeveloped and even after looking into formulas for triangle waves, I've been having trouble implementing it in my code..


So, am I even on the right track? How can I smoothly convert my game world's time into a single decimal value between -1 and 1?



Answer



tl;dr


Func 1 on Wolfram Alpha:


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


Or in your specific case:



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



You can even use a sinus wave instead (much more pretty).


sin(x - pi/2)


Sin Wave on Wolfram Alpha


Or in your specific case:


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




Long tedious explaination in fine detail:


If in military time: 00:00 (midnight) is -1, 12:00 (noon) is 1 and 23:59 is again ~-1 then we are measuring distance from noon (how long ago was noon or how long until it's noon again?). Then negating the value and subtracting one.


To measure distance in 1d we use the abs operator: |7 - 5| = |3 - 5| = 2(because seven and three are the save distance from 5.


float hours = gameHours + gameMinutes / 60.0 + seconds / 3600.0;//

where | | means the absolute value of... This is normally accomplished with Math.abs();


So you get:


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

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...