I understand that math.random's seed in based on the os.clock. I am having a small problem with many random numbers declared many times in a row. Here is an example:
for a=1, #objectsToMove do
local rand = math.random(-5,5)
objectsToMove[a].x = objectsToMove[a].x + rand * dt
end
This is an example of what I am talking about, in this instance all of the objects will move randomly, but in the same pattern. I want all the objects to move independently based on their own random number.
Alright, the long answer is that math.random doesn't actually provide random numbers, it provides pseudorandom numbers. The distinction is that regular random numbers are generated from sources like you moving your mouse, or cosmic radiation, where as pseudorandom numbers start with a number, (like the current time) and keep adding and multiplying to them in some algorithm. HOWEVER, the "period" for PRNGs, or how many times it can generate a number before it loops back and starts over is immensely huge.
Anyway, a good tip, use math.random without any parameters. When you give it numbers, it returns integers. Without, it returns a real number between [0 and 1). That can increase the amount of diversity in their movement.
Another tip, you're moving them randomly every frame, which means you're going to get wiggling at best. Instead, pick a direction, speed, and time randomly, and try moving them in a straight line for that period before picking a new way to go.
Yes, the real problem here is statistics: over a long period of time, on average all these enemies just keep bouncing back to the middle. Like Inny said: pick a direction/speed for them at the beginning and use that:
(Also, I use ipairs here instead of a numeric for.)
-- in love.load
for i, obj in ipairs(objectsToMove) do
obj.speed = math.random(-5,5)
end
-- in love.update
for i, obj in ipairs(objectsToMove) do
obj.x = obj.x + obj.speed * dt
end
Thank you very much for the replies, I still a little stumped though.
While I do (now) understand how random numbers are generated, I still don't know the best way to get different random numbers at the same os.time. How would I implement something like mouse movement or cosmic radiation to my random number?
Thank you very much again, Love2d has an awesome community!
In other words: How can I get a random number that is NOT based on os.time, because I generate multiple random numbers at the EXACT SAME TIME which causes them to all be the same.
First of all, sorry about the double post. It will not happen again.
The computer I am on isn't working properly for making .love files (not admin on this comp). I will upload the .love file later when I get access to my home computer.
For now here is all the code I am using for the random:
rand = { }
function rand:init()
math.randomseed (os.time())
end
function rand:seed()
math.randomseed (os.time())
end
function rand:newInteger(low,high)
local randomNum
randomNum = math.random(low,high)
randomNum = math.random(low,high)
randomNum = math.random(low,high)
randomNum = math.random(low,high)
return randomNum
end
function npc:update(dt)
for i,v in ipairs(self.currentNPCs) do
local direction = rand:newInteger(-5,5)
v["x"] = v["x"] - direction * dt * 100
end
end
end
I know the NPC code is bad right now, I plan on making NPCs move more smoothly after I get this random thing worked out.
Thank you again, I do appreciate you taking the time to help me out.
Ok, here is how random number generation on a computer works:
The code for generation random numbers has an internal state. Depending on that and on some complicated calculations, the next number is generated and then the state is updated. So next time you call the math.random function, you get a new random number.
These numbers are not truly random in the sense that in a certain state the algorithm will always generate the same random number. However the state is not visible to the user and the sequence that comes out of the generator looks random (unless you understand all the details of the algorithm, which I dont).
When you start your program, the state of the generator cannot be random, because the computer is deterministic. So if you set the state (seed) to a fixed number, then every time you start your program, you get the same sequence of random number. You don't want that. So in most implementations the random seed is set according to the system time. This has only to be done once. After that the sequence you get is as random as it can.
Now in löve, the setting of the random seed is done anyway at start up (guys correct me, when I'm wrong here). So you don't even need to ever call the randomseed function yourself. Never.
The only application I see, where you need to set the randomseed, is when you do scientific applications and want reproducible results. In that case you can set the seed to a number you know and get the same random sequence every time.
Edit: Also, if you need one random number, there is no point in calling the math.random function multiple times. There is no visible correlation between to consecutive function calls.
micha wrote:
When you start your program, the state of the generator cannot be random, because the computer is deterministic. So if you set the state (seed) to a fixed number, then every time you start your program, you get the same sequence of random number. You don't want that. So in most implementations the random seed is set according to the system time. This has only to be done once. After that the sequence you get is as random as it can.
micha wrote:
Now in löve, the setting of the random seed is done anyway at start up (guys correct me, when I'm wrong here). So you don't even need to ever call the randomseed function yourself. Never.
You're quite right, Micha. Well, it seems that this was introduced in love 0.8.0. See love.run default implementation.