Not all games require a day night cycle system and plenty would not benefit from having one, but it is a staple requirement of adventure and role playing games. It seems like a complex thing at first consideration but at least for a basic system it is not really that hard. When you start with a basic system like this, it becomes easier then to customise and add features to make your game stand out.
My aim in this tutorial is to look at the code required, but in order to do so I will also need to touch on the setup of the elements in the game engine to make this happen. I will assume you have at least some knowledge of coding and the engine you plan to use so I am going to use pseudo-code here. I will leave it to you to adapt it to the language and engine of your choice.
Setting up the sun
Before we get into the code, the very simple day night cycle here will require a little setup in your game engine. Some (but not all) of the game engines I have experimented with seem to allow you to simply rotate a directional light, and they handle the billboarding of the sun moving through the sky. In some others, or if coding one from scratch, you may need to consider a setup such as this.
Create an invisible scene node as the sunController and position it at approx the center of your map.
Create a sceneNode as a child of the sunController and position it a good distance away from the sunController, attach the sun directional light to this node and set its direction to be facing the sunController. I will leave you to work out billboards, etc.
Now, as you rotate the sunController around the desired axis, the sun light will move around as well. You should be able to preview the effect and fine tune it by manually setting the rotation of the sunController and viewing what it does with the light.
Code the sun
Now, lets get to the bit you're really interested in. Psuedo-code. Well, actually, you'd probably prefer real code, but then you would just copy and not really learn much.
Lets say we want our data about the time to be available to other parts of our game (such as when saving a game). We will want to create a class that can be accessed to gather that information. This could be useful not just for saving a players game but to provide other dynamic features such as moving clocks or events that are triggered at certain times.
class GameTime {
.....
}
Now, we will need to have some variables to store the time information we want.
public float currentHour; // The current hour of the game day public int currentDay; // The current day of the week public int currentWeek; // The current week of the month public int currentMonth; // The current month of the year public int currentYear; // The current yearNow for some basic variables that will help control our sun. This includes how long 1 game day will last and uses that to calculate some other required data.
// 1 in game day will take 30 real minutes (30m * 60s = 1800s) private int dayLengthInSeconds = 1800; // Calculate how many degrees the sun needs to move through the sky per second private float sunRotationDegPerSecond = 360f / dayLengthInSeconds; // How many degrees of sun rotation per game hour (assuming 24 hour days) float degreesPerHour = 360f / 24; // current rotation of the sun private float sunRot = 0; // GameObject for our sunController (or Sun as required) public GameObject sunController; // Constructor public function GameTime() { // Set the GameObject sunController = EngineSpecificGetEntityFunctionCallHere(); // calculate starting position based on time sunRot = currentHour * degreesPerHour; // Set the initial rotation around specified axis (z) // How this is done will vary based on the engine.
// Again, this is psuedo-code not to be copied verbatim sunController.rotation.z = sunRot; } // The update function will be called every frame public function Update(float frameDelta) { // Check if the sun object exists if(sunController != null) { // Reset to 0 if require if(sunRot > 360f) { sunRot = 0; currentDay++; } // Calculate rest of time if(currentDay > 7) { //assuming 7 day weeks currentWeek++; currentDay = 1; } if(currentWeek > 4) { // assuming 4 weeks to a month currentMonth++; currentWeek = 1; } if(currentMonth > 12) { // assuming 12 months in a year currentYear++; currentMonth = 1; } // Update the suns rotation by taking the degreesPerSecond and
// multiplying by the frameDelta to calculate the degrees for
// that part of that second. sunRot += degreesPerSecond * frameDelta; // Set the rotation around specified axis (z) // How this is done will vary based on the engine.
// Again, this is psuedo-code not to be copied verbatim
sunController.rotation.z = sunRot; // Recalculate currentHour currentHour = sunRot / degreesPerHour; } }Basically what we are doing here is determining how long we want an in game day to last in real time and then calculating how much to move the sun so that it does a full 360 degree rotation within that time period.
30 minutes might be too short or too long for your game, it is completely configurable. You could set it to quite a short period in order to test the functionality quickly. However, if you intent to lower the number of seconds a day lasts below 360 you will likely need to make some adjustments in the code to compensate for that.
By taking the number of degrees we need to rotate per second and multiplying that by our frameDelta we get the correct degrees of rotation for that frame which is generally a fraction of a second.
In the constructor we set the initial rotation based on the currentHours, so this could be preset to 6 to have the sun start at sunrise, 18 for sundown, 12 for midday, etc.
It may take some tweaking to get correct, but with a bit of experimentation you should have a sun tracking through the sky and giving you 12 hours of sunlight and 12 hours of darkness.
Good work.
This is only part 1 of the overall day/night cycle solution however. In part 2 we will look at the blending of a skybox or skydome to allow our map to have a black sky at night, a bright orange glow at sunrise/sunset and a sky blue during the day.
No comments:
Post a Comment