I'm not sure if I can express this question correctly, but here it goes..
I want to code an example, where small dots have a velocity according to which they move - but also, there is a random motion superimposed to the "proper" motion. Using the Processing
code below, I get the following animation:
The right dot is supposed to be going towards the bottom right corner, and I'm OK with how it behaves. The problem is the left dot, which is supposed to be "static" - so it would only show the "random" motion "in place"; however, as the animated .gif shows, it tends to end up veering some distance away from its original location. The random velocity is calculated with:
this.randspeed.set(random(0,1)-0.5, random(0,1)-0.5);
I would have guessed that random(0,1)-0.5
doesn't give me a Gaussian-like "normal distribution" centered around (or converging? to) zero; but then again, even if it was a "proper" Gaussian, I still could have such "luck" so that say, positive values [0:0.5) are returned for a whole day, and then negative values [-0.5:0) are returned the next day, and in the end, it would still be a proper Gaussian.
So, I guess, I'm looking for a way to convert a (pseudo?)-random sequence (as the one generated by random(0,1)-0.5
) to a pseudo-random one, but in which the average sum of N samples (say, 10) is 0. I'm not sure how to call this - a random sequence periodically converging to zero, I guess??
Note that I've been trying below with both changing position
directly; and saving position
with changing finalpos
instead - changing the position seems more like a "natural", smoothed motion (especially with the modulo frame operation, so a new random velocity isn't assigned every frame); but then, it also allows that the random noise accumulates, and "pushes" the dot away from its central location. Also, note that it took me a few takes until I could reproduce this on the .gif, running the program "live" seems to cause the dot to diverge from the original location more quickly (I had read something about hardware events like hard-disk writes being used for changing entropy for /dev/random
on Linux, but I don't really know if it's related).
Also, I thought of setting some sort of a virtual border around the dot position, and having a collision detection for the random motion going out of the border - but that seems to me like too much work (and CPU cycles for vector operations) for this kind of thing; I would have hoped that the random function can somehow be "tempered" in an easier manner, instead.
So, would there be a recommended way to approach this kind of random motion around a central location in a limited area?
marbles.pde
:
import java.util.*; // added for Iterator;
ArrayList<Marble> marbles = new ArrayList<Marble>();
Iterator<Marble> imarb;
color mclr = #0000FF;
int RNDLIMIT = 2;
int framecount = 0;
void setup() {
size(600,400,P2D);
Marble m_moving = new Marble(width/2, height/2, 2, 2);
marbles.add(m_moving);
Marble m_stopped = new Marble(width/2-100, height/2, 0, 0);
marbles.add(m_stopped);
}
void draw() {
background(255);
strokeWeight(1);
stroke(mclr);
fill(mclr);
imarb = marbles.iterator();
while (imarb.hasNext()) {
Marble m = imarb.next();
m.update();
ellipse(m.finalpos.x, m.finalpos.y, m.radius*2, m.radius*2);
}
framecount++;
//~ saveFrame("marbles-######.png");
}
class Marble {
PVector position = new PVector(0,0);
PVector finalpos = new PVector(0,0);
PVector speed = new PVector(0,0);
PVector randspeed = new PVector(0,0);
float radius=4;
public Marble() {
}
public Marble(float inx, float iny, float invx, float invy) {
this.position.set(inx, iny);
this.speed.set(invx, invy);
}
public void update() {
this.position.add(this.speed);
if (framecount % 4 == 0) {
this.randspeed.set(random(0,1)-0.5, random(0,1)-0.5);
this.randspeed.setMag(RNDLIMIT);
}
int algoTry = 1; // 0
switch(algoTry) {
case 0:
this.finalpos.set(PVector.add(this.position, this.randspeed));
break;
case 1:
this.position.set(PVector.add(this.position, this.randspeed));
this.finalpos.set(this.position);
break;
}
}
}