Reputation: 8941
Could anyone give me a hint on how to generate "smooth" random numbers? Here's what I mean by smooth:
The random numbers shall be used in a game, e.g. for wind direction and strength (does anyone remember goood old "Worms"?). Of course setting random numbers for those values every second or so would look awfully choppy. I would rather have some kind of smooth oscillation in a given value range. Sort of like a sine wave but much more random.
Does anyone get what I'm after? ;-) Any ideas on how to achieve this kind of behavior would be appreciated.
Upvotes: 12
Views: 7116
Reputation: 606
I created a new version of a smooth random number. The idea is that our random number is going to be within limits = [average - oscillation, average + oscillation], and will change everytime [-varianciance, +variance].
But, if it reaches the limits, our variance is going to be reduce.
E.g. numbers from [0, 100], with variance of 10. If the current value = 8, then the variance will be [0, 18]
python code:
def calculate_smooth_random(current_value, average, oscillation, variance):
max_value = average + oscillation
min_value = average - oscillation
max_limit = min(max_value, current_value + variance)
min_limit = max(min_value, current_value - variance)
total_variance = max_limit - min_limit
current_value = min_limit + random.random() * total_variance
print("current_value: {}".format(current_value))
return current_value
Image for distribution with values: average: 20 oscillation: 10 variance: 5
Upvotes: 0
Reputation: 881703
If you want the delta (change) to be small, just generate a small random number for the delta.
For example, instead of:
windspeed = random (100) # 0 thru 99 inclusive
use something like:
windspeed = windspeed - 4 + random (9) # -4 + 0..8 gives -4..4
if windspeed > 99: windspeed = 99
elif windspeed < 0: windspeed = 0
That way, your wind speed is still kept within the required bounds and it only ever changes gradually.
This will work for absolute values like speed, and also for direction if the thing you're changing gradually is the angle from a fixed direction.
It can pretty well be used for any measurement.
Alternatively, if you want to ensure that the windspeed changes with a possibly large delta, but slowly, you can generate your target windspeed as you currently do but move gradually toward it:
windspeed = 50
target = windspeed
while true:
# Only set new target if previous target reached.
if target == windspeed:
target = random (100)
# Move gradually toward target.
if target > windspeed:
windspeed = windspeed + max (random (4) + 1, target - windspeed)
else:
windspeed = windspeed - max (random (4) + 1, target - windspeed)
sleep (1)
Upvotes: 9
Reputation: 6595
Perlin (or better simplex) noise would be the first method that comes to mind when generating smoothed noise. It returns a number between 1 and -1, which will add or subtract from the current value. You can multiple that to make it seem less subtle or better yet... make the lowest wind value -1 and highest wind value 1.
Then simply have a seeder as a counter (1,2,3... etc) as the perlin/simplex input keep the values 'smooth'.
Upvotes: 4