🦊

rotateとnoiseで簡単な弾幕を作る

2023/02/11に公開

弾幕みたいなアニメーションを作る。

コード

function setup() {
  createCanvas(400, 400);
  noStroke();
  fill(255);
}
function draw() {
  background(0);
  translate(200, 200);
  let r = 400;
  while(r--){
    const x = (frameCount*2 + noise(r)*600)%300;
    rect(x-4, -2, 8, 4);
    rotate(TAU/400);
  }
}


 こんな感じの見た目になる。座標の中心をキャンバスの中心に合わせたうえで、x軸の正方向のある場所に長方形を描き、rotateで400回等間隔でずらしながらそれを行う。その際の距離がxで、これはframeCountでずらしている。その際のオフセット(初期位置)をノイズでずらしている。
 ノイズは固定されたランダム値のように用いることができる。引数が1つの場合、相当大きい数でない限りバラバラな0~1の値を返してくれる。これを300で割った余りを取る。半径300の円はこの正方形をすっぽり覆う(200のルート2倍がおおよそ282なので)。それで繰り返しのアニメーションにすると弾幕のようになるというわけ。

noise(r)に掛ける値が300ではなく600である理由

noise(r)の値は0~1なので、300を掛ければ0~300でばらけそうに思えるが、実際は違う。あそこを600から300に変えると、次のように途中に弾の飛んでこない時間ができてしまう。

これを調べるため、次のようにしてノイズの値の散らばり方を調べてみる。

function setup() {
  createCanvas(600, 600);
  fill(128);
  noStroke();
  background(0);
  
  let r=[];
  for(i=0;i<300;i++){
    r.push(noise(i)*300);
    //r.push((noise(i)*600)%300);
  }
  r.sort((a, b) => (a-b));
  
  for(i=0;i<300;i++){
    const y = r[i];
    rect(i*2, 600-y*2, 2, y*2);
  }
}


ご覧の通り、ノイズの値は0.5付近に集中しているので、単純に300倍だと150の近くに密集しすぎてしまう。なので、600倍して300で割った余りを取る。こうすることで値がばらけている範囲が分散していい感じになる:

これはいろいろと応用が利くのでつぶやきProcessingなどでよく使っていた。

バリエーション

background(0)をbackground(0, 40)にするだけでだいぶ違った見た目になる。

他、色を付けるなど、いろいろ応用できる。長方形の代わりに線とか円とかにしたり、色々。

Discussion