7_6:円運動 p5.js JavaScript

三角関数のサインとコサインは連続する滑らかなモーションに利用できます。

サインとコサインと円

サイン(sin)とコサイン(cos)は、角度θに対する半径1の円周上の点が座標(cosθ, sinθ)にあることを言います。したがって点Pが(cosθ, sinθ)にあるとき、cosθはX軸上の0からcosθまでの長さに、sinθはY軸上の0からsinθまでの長さに当たります。

この円は半径が1なので、もっと大きくしたい場合はその半径を掛けます。また円の中心は原点(0, 0)なので、中心を移動したい場合には、それを足します。

// (centerX, centerY)を中心とする半径がradiusの円
// 円周上のx座標値
const x = centerX + cosValue * radius;
// 円周上のy座標値
const y = centerY + sinValue * radius;

この計算により、角度θのときの(x, y)が分かるので、draw()関数内でθを増減させ、位置(cosθ, sinθ)にシェイプを描くと、円運動になります。

let angle = 0;
let centerX;
let centerY;
// 大きな円の半径
const radius = 80;
const speed = 0.01;

function setup() {
  createCanvas(200, 200);
  // キャンバスのセンターをメモ
  centerX = width / 2;
  centerY = height / 2;
}

function draw() {
  // angleのサイン値とコサイン値
  const sinValue = sin(angle);
  const cosValue = cos(angle);

  background(204);
  fill(255);
  ellipse(centerX, centerY, 160, 160);
  // 円周上のx座標値
  const x = centerX + cosValue * radius;
  // 円周上のy座標値
  const y = centerY + sinValue * radius;
  fill(100, 255, 255);
  triangle(centerX, centerY, x, y, x, centerY)

  fill(255, 0, 0);
  // 円周上を移動する赤い円を描画
  ellipse(x, y, 10, 10);
  // 角度を少しずつ大きくする
  angle += speed;
}

サイン波とコサイン波

p5.jsのsin()とcos()関数が返す値を、次のコードでグラフにプロットすると、サイン波とコサイン波が描画できます(plotly.jsを使用)。

let angle = 0;
const speed = 0.01;

function draw() {
    // angleのサイン値とコサイン値
    const sinValue = sin(angle);
    const cosValue = cos(angle);

    plot(frameCount, sinValue);
    plot(frameCount, cosValue);
    angle += speed;
}

サイン波もコサイン波も、波のてっぺんと底近くで変化の度合いが緩くなり、その後向きを変えます。この曲がり具合が面白いモーションを生み出す元です。サイン波は0から始まるので、0から始めたいモーションに適していると言えます。

サイン波の動き

次の例は、sin(angle)が返すサイン値を動きに変換するうまい方法を示しています。

let angle = 0.0;
const offset = 60;
const scalar = 40;
const speed = 0.05;

function setup() {
    createCanvas(240, 120);
    strokeWeight(2);
    stroke(255);
}

function draw() {
    background(0);
    const y1 = offset + sin(angle) * scalar;
    const y2 = offset + sin(angle + 0.4) * scalar;
    const y3 = offset + sin(angle + 0.8) * scalar;
    fill(255, 0, 0);
    ellipse(80, y1, 40, 40);

    fill(0, 255, 0);
    ellipse(120, y2, 40, 40);

    fill(0, 0, 255);
    ellipse(160, y3, 40, 40);
    angle += speed;
}

うずまき

円の半径に当たるscalar値をフレームごとに大きくすると、うずまきになります。

let angle = 0.0;
const offset = 60;
let scalar = 2;
const speed = 0.05;

function setup() {
    createCanvas(120, 120);
    fill(0);
    background(204);
}

function draw() {
    const x = offset + cos(angle) * scalar;
    const y = offset + sin(angle) * scalar;
    ellipse(x, y, 2, 2);
    angle += speed;
    scalar += speed;
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA