先日のランダムウォークを改良しました。
gotutiyan.hatenablog.com
方向ベクトルを斜めにして、軌跡を点線に。さらに円の内部を動く色付きのものと、円の外を動く白色のものに分けてみました。
白いものは画面外に出たとき、もしくは円の中に入ったときに、強制的に引き戻す方向に変えさせます。
色付きのものは、円を出ようとしたときに、強制的に引き戻す方向に変えさせます。
引き戻す方向は案外簡単に設定できて、引き戻す条件に合致した瞬間のx,y座標をX,Yとおけば、「出て行く」動きを引き戻すなら、X,Yそれぞれの反対の符号を持つdir[ ]を、「入りこむ」動きを引き戻すなら、X,Yそれぞれと同じ符号を持つ dir[ ]を足せば良いです。
また、軌跡を表す線を点線にしましたが、これは軌跡を格納している配列において、「5で割った余りが0,1,2となるような添字の時だけline()を引く」ということをしています。
つまり、3ピクセル描いて2ピクセル描かない、をひたすら繰り返します。
コードはprocessingで、以下の通りです。
RandomWalk2 random10_color[]=new RandomWalk2[100];
RandomWalk2 random10_white[]=new RandomWalk2[200];
void setup() {
size(600,600,P2D);
for (int i=0; i<random10_color.length; i++)random10_color[i]=new RandomWalk2(0);
for (int i=0; i<random10_white.length; i++)random10_white[i]=new RandomWalk2(1);
}
void draw() {
background(0);
translate(width/2, height/2);
noFill();
ellipse(0, 0, 500, 500);
for (int i=0; i<random10_color.length; i++)random10_color[i].move();
for (int i=0; i<random10_white.length; i++)random10_white[i].move();
}
class RandomWalk2 {
PVector now;
PVector dir[]=new PVector[4];
PVector diff;
ArrayList<PVector> prev=new ArrayList<PVector>();
int changeDir;
float c;
float radius=250;
int mode=0;
RandomWalk2(int emode) {
mode=emode;
if (mode==0)now=new PVector(0, 0);
else now=new PVector(random(width)-width/2, random(height)-height/2);
dir[0]=new PVector(1, 1);
dir[1]=new PVector(-1, -1);
dir[2]=new PVector(1, -1);
dir[3]=new PVector(-1, 1);
diff=new PVector(1, 1);
changeDir=(int)random(30, 50);
c=random(360);
}
void move() {
if (mode==0) {
if (dist(0, 0, now.x, now.y)>radius) {
if (now.x<0&&now.y<0)diff=dir[0];
if (now.x>0&&now.y>0)diff=dir[1];
if (now.x<0&&now.y>0)diff=dir[2];
if (now.x>0&&now.y<0)diff=dir[3];
}
} else {
if (dist(0, 0, now.x, now.y)<radius) {
if (now.x>0&&now.y>0)diff=dir[0];
if (now.x<0&&now.y<0)diff=dir[1];
if (now.x>0&&now.y<0)diff=dir[2];
if (now.x<0&&now.y>0)diff=dir[3];
}
if (now.x<-width/2)diff=dir[0];
if (now.x>width/2)diff=dir[1];
if (now.y<-height/2)diff=dir[3];
if (now.y>height/2)diff=dir[2];
}
if (frameCount%changeDir==0) {
int x=(int)random(0, 4);
diff=dir[x];
}
prev.add(new PVector(now.x, now.y));
while (prev.size()>100)prev.remove(0);
now.add(diff);
if (mode==0) {
colorMode(HSB,360,100,100,100);
fill(c, 100, 100,100);
} else {
colorMode(RGB);
fill(255);
}
noStroke();
ellipse(now.x, now.y, 10, 10);
colorMode(HSB);
if (mode==0) {
colorMode(HSB);
stroke(c, 100, 100, 100);
} else {
colorMode(RGB);
stroke(255);
}
for (int i=1; i<prev.size(); i++) {
if (i%5==0||i%5==1||i%5==2)line(prev.get(i).x, prev.get(i).y, prev.get(i-1).x, prev.get(i-1).y);
}
}
};