9
\$\begingroup\$

So, given a sun sprite set at the horizon (x = 0, y = worldheight/2) I'm trying to devise a function to make the sun rise, then fall.

The best way to do this would be the sin function, but I have no idea how to use it.

if using y = sin(x), then x would have to range between 0 and pi for a full curve, while having a constant velocity for X.

Any thoughts or suggestions?

Edit: Thanks guys!

Sun working!

\$\endgroup\$

2 Answers 2

6
\$\begingroup\$

Regarding the 0 to pi issue, in general all you have to do is scale the X by a multiplier. Example:

y = sin(x * pi / worldWidth)

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

However, this doesn't get quite the curve you're probably looking for. You should use the parametric form:

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

This combination of sin for Y and cos for X will trace out an ellipse.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks, this is awesome. I'm not very math-centric. My skills in Math are pretty much just rudimentary calculus. \$\endgroup\$
    – Ross
    Commented Jan 5, 2012 at 2:09
12
\$\begingroup\$

Like Jimmy said an ellipse is probably a better fit for this motion. Here's some ideas on how to actually implement it with a bit more detail for those interested.

Taking Time

For starters, you need a variable to keep track of time in the game world. You can implement it any way you like, but here's an example. I'll use a variable called hours that varies from 0 to 24 (although when it reaches 24 it wraps back to 0).

Unlike real life though, I'll just consider that day starts at 0 hours, and night starts at 12 hours. This will make some of the calculations easier.

I'll also define the rate at which game time changes in relation to real time. In this example, every two minutes of real time will correspond to one hour in game.

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
}

Configuration

Now before setting our sun's movement we need to specify a few of its parameters. In particular, at what X value does it raise from the horizon, and at what X value does it fall into the horizon. Also, what Y corresponds to the horizon, and how high is he supposed to rise above that line.

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

Calculating the Sun's Coordinates

Now it's time to calculate the position of our sun for a given time of the day. I'll use the same parametric function used by Jimmy but with the domain ranging from [0..2PI] instead (in order to bring the sun back to its original position by daybreak):

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

y = sin(t)

This is a good function because the X value varies from 0 to 1 and then back to 0 again (which we'll be mapping to our sun's start and end X values) and the Y value starts at 0 and moves up to 1 and back to 0 again (which would be our day portion) and then repeats the exact same thing on the negative side before coming back to the original position (which would be our night although the sun will not be drawn at this point).

The first step is scaling the hours from the [0..24) range to the range of our function which is [0..2PI):

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

Next we apply the functions to get back the values between 0 and 1 I talked above:

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

And finally we scale those values using the sun's parameters:

float sunX = startX + (endX - startX) * horizontal;    // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical;         // Up and down around horizonY
\$\endgroup\$
2
  • \$\begingroup\$ +1 for amazingness, my only regret is that I can't mark two answers! \$\endgroup\$
    – Ross
    Commented Jan 5, 2012 at 2:45
  • \$\begingroup\$ No problem, I used the same base formulas as Jimmy anyway. :) \$\endgroup\$ Commented Jan 5, 2012 at 2:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .