So a couple of days ago I posted a screen recording of a feature I worked in the weekend for Autumn: dynamic rain effects. Somehow, plenty of people got interested in it and asked me how I did it and if I could share the code.
I don’t share the code, not because it’s top-secret or I am afraid of someone stealing my game(it will be free, btw) but because it is very tightly integrated in other parts of the game, and so might be a bit messy to understand. Instead, I decided to write this short blog post to explain how I did it.
But first, the video: (something have already changed since this recording was made, but anyway…)
So the whole thing is quite simple, actually. But let’s go step by step.
The first thing is to decide when the rain starts and ends, its duration and intensity. So I have a function that makes this decisions, that is called on the start of the game, and every time the rain finishes. In Autumn, the game time follows a year cycle, mapped from 0 to 100. So the beginning of winter is 0, and the end of autumn is 100, then the whole thing repeats in cycles.
So I can assign the rain to start and end at specific times. To do that, I have a few important variables:
The first two should be self-evident. The climax time defines when the rain intensity should reach the climax_strength (ranges from 0.3 to 1). Having this four variables allows me to create more realistic rain effects, as they will be different every time.
The last one, rainctl, is the main variable, that holds how much rain there is at any given moment (ranges from 0 to 1). Its value is normalized according to the current game time position relatively to the rain start, end and climax times and the climax strength
So, for example, I can have rain that has the climax_time very close to the start_time, which will make it start very fast and then slowly wane away. The graphic below shows two different scenarios, that illustrate this
Now we have to put all this into something the player can see (and hear!). The value of rainctl directly affects three different aspects of the rain:
- amount of droplets on the screen glass
- amount of rain (lines)
- volume of the rain sound
Having just one variable (rainctl), makes things really easy!
The droplets on the screen are very simple “objects” that have a few properties which make them feel a bit more real:
- size (random)
- falling speed (random, depends on size)
- initial color alpha
On every update call, I reduce the alpha of each drop, until it becomes 0 and gets removed. The rainctl value indicates the maximum number of drops that can be on the screen. The falling speed depends on the size so that bigger drops seem to fall faster and smaller ones.
The rain lines are just randomly drawn grey semi-transparent lines. I also use the rainctl value to set up a maximum number of lines that get drawn.
And finally, the volume of the rain sound is directly set by rainctl, as it also ranges from 0 to 1.
So there it is, quite simple! It took me a whole day to do it, because I had to come up with the idea, try different ways of doing it and finally settling down with this one and tuning it up.
Besides this I also do a bunch of sanity checks that are more closely related with Autumn (like, few chance of rains in summer, or only light showers, etc).
Hope you enjoyed it