なぜか動きが”自然”になる魔法。クリエイティブコーディングで生命感を吹き込む法則

無数の光の粒子が、暗い背景の中を風に流れるように優雅に舞い落ちる様子。クリエイティブコーディングによる生命感の表現。
No.136 Breath of Life(生命の息吹)
  • URLをコピーしました!
上記画像のコードを見る(1/4)
(ここをクリックすると以下が開く)

このコードをp5.js Web Editorで試す

/**
 * @title   Breath of Life(生命の息吹)
 * @author  Takuya Watari (Watataku) 
 * @date    2025-08-12
 *
 * @desc
 * 目に見えない風と重力に導かれ、無数の光の粒子が生命感をもって舞い落ちる様子。
 * 一つ一つの粒子が持つ独自の「ゆらぎ」が、全体として有機的な流れを生み出す。
 *
 * @license
 * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 */

// --- 設定 ---
const PARTICLE_COUNT = 300; // 粒子の数
const particles = [];
let colorPalette;

// --- p5.jsのセットアップ関数 ---
function setup() {
  createCanvas(1600, 900);
  colorMode(HSB, 360, 100, 100, 100); // 色モードをHSBに設定
  noStroke(); // 粒子の枠線は描画しない
  

  // 使用する色のパレットを定義(暖色系+アクセントの水色)
  colorPalette = [
    color(30, 80, 100, 80), // オレンジ
    color(50, 90, 100, 80), // 黄色
    color(0, 70, 100, 80),  // 赤
    color(180, 70, 100, 80) // シアン
  ];

  // 設定した数だけ粒子を生成
  for (let i = 0; i < PARTICLE_COUNT; i++) {
    particles.push(new Particle());
  }
}

// --- p5.jsの描画関数 ---
function draw() {
  // 背景を深みのある紺色で塗りつぶす
  background(220, 70, 20);

  // 全ての粒子を更新し、描画する
  for (const particle of particles) {
    particle.update();
    particle.display();
  }
}

// --- 粒子を管理するクラス ---
class Particle {
  constructor() {
    // 粒子の初期位置を画面内にランダムに設定
    this.pos = createVector(random(width), random(height));
    // 粒子の初期速度(y方向の落下速度)をランダムに設定
    this.vel = createVector(0, random(0.5, 2));
    // 粒子の大きさをランダムに設定
    this.size = random(5, 12
                      );
    // パーリンノイズのオフセットをランダムに設定(これで各粒子が違う動きになる)
    this.noiseOffset = random(1000);
    // パレットからランダムに色を選択
    this.color = random(colorPalette);
  }

  // 粒子の位置を更新する
  update() {
    // パーリンノイズを使って、左右に揺れる「風」の力を計算
    let windX = map(noise(this.noiseOffset), 0, 1, -0.2, 0.2);
    let wind = createVector(windX, 0);

    // 粒子に風の力を加える
    this.vel.add(wind);
    // 粒子の位置を速度に応じて更新
    this.pos.add(this.vel);

    // ノイズのオフセットを少しずつずらして、動きに変化をつける
    this.noiseOffset += 0.005;

    // 画面外に出たらリセットする
    this.checkEdges();
  }

  // 粒子を描画する
  display() {
    // 粒子に色を設定
    fill(this.color);
    
    // 光っているような効果を追加
    drawingContext.shadowBlur = 50;
    drawingContext.shadowColor = this.color;
    
    // 粒子(少し縦長の円)を描画
    ellipse(this.pos.x, this.pos.y, this.size, this.size * 1.2);
  }

  // 画面の端に行ったかをチェックする
  checkEdges() {
    // 画面の下端より下に行ったら
    if (this.pos.y > height + this.size) {
      // 画面の一番上に、x座標はランダムな位置で再配置
      this.pos.x = random(width);
      this.pos.y = -this.size;
      
    }
  } 
}

ワタタク

「クリエイティブコーディングを始めたけど、なんだか動きがカクカクして機械っぽい…」

「お手本みたいに、”ゆらぎ”のあるオシャレな表現ができない…」

コードを書き始めたばかりの頃、僕も同じ壁にぶつかりました。画面に図形を動かすことはできても、そこに「生命感」を宿すことが、とてつもなく難しく感じられたのです。

まるで、魂の入っていない人形を動かしているような、もどかしい感覚。

でも、あることに気づいたとき、僕のコードから生み出される世界は一変しました。それは、僕たちが毎日目にしている「自然現象」の中に、すべての答えが隠されていたということです。

この記事では、あなたが作る作品に「生命感」という魔法をかけるための、自然現象の捉え方とその法則について、僕の旅の経験も交えながら、分かりやすく解説していきます。

この記事を書いた人
ワタタク
  • クリエイティブコーディングで制作した作品と、上達のためにやったこと・学習過程を発信
  • コンセプトは「クリエイティブコーディング1万時間の歩き方」
  • 2024年にProcessingの構文のアウトプットを終え、2025年から作品制作開始(クリエイティブコーディングで作成した作品集

目次

世界の設計図をコードで真似てみる

僕たちが「自然だ」と感じる動きのほとんどは、物理法則という世界のルールに従っています。クリエイティブコーディングで自然現象を表現する第一歩は、この「世界の設計図」をこっそり覗き見て、コードで真似てみることです。

パーリンノイズによって生成されたベクトル場の可視化アート。無数の短い線が、水の流れのような滑らかなパターンを描いている。
No.137 World’s Blueprint(世界の設計図)
上記画像のコードを見る(2/4)
(ここをクリックすると以下が開く)

このコードをp5.js Web Editorで試す

/**
 * @title   World's Blueprint(世界の設計図)
 * @author  Takuya Watari (Watataku) 
 * @date    2025-08-12
 *
 * @desc
 * パーリンノイズを利用して生成したベクトル場(Flow Field)の可視化。
 * 目に見えない自然界の力の流れ、その「設計図」をアートとして表現する。
 *
 * @license
 * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 */

// --- 設定 ---
let particles = [];
const PARTICLE_NUM = 1500; // 粒子の数

const NOISE_SCALE = 0.005; // ノイズの細かさ(小さいほど滑らかな流れになる)
const GRID_SCALE = 20;    // 流れの地図(ベクトル場)を計算する格子の解像度

let flowfield; // 流れの地図を保存する配列

// --- p5.jsのセットアップ関数 ---
function setup() {
  createCanvas(1600, 900);
  colorMode(HSB, 360, 100, 100, 100); // HSBカラーモード

  // 流れの地図(Flow Field)を計算する
  flowfield = new Array(floor(width / GRID_SCALE) * floor(height / GRID_SCALE));
  calculateFlowField();
  
  // 粒子を初期化
  for (let i = 0; i < PARTICLE_NUM; i++) {
    particles[i] = new Particle();
  }
  
  // 背景を一度だけ描画
  background(220, 80, 15); // 深い青色
}

// --- p5.jsの描画関数 ---
function draw() {
  // 全ての粒子を動かして描画
  for (let p of particles) {
    p.follow(flowfield); // 流れの地図に従って動く
    p.update();
    p.show();
    p.edges();
  }
}

// --- 流れの地図(Flow Field)を計算する関数 ---
function calculateFlowField() {
  let yoff = 0;
  // 格子状に画面を分割し、各格子点での流れの角度を計算する
  for (let y = 0; y < height; y += GRID_SCALE) {
    let xoff = 0;
    for (let x = 0; x < width; x += GRID_SCALE) {
      // パーリンノイズを使って角度を生成
      let angle = noise(xoff, yoff) * TWO_PI * 2; // 0から4πの間の角度
      // 角度からベクトル(力の方向)を計算
      let v = p5.Vector.fromAngle(angle);
      v.setMag(1); // 力の大きさは常に1に正規化
      
      // 計算したベクトルを配列に保存
      let index = floor(x / GRID_SCALE) + floor(y / GRID_SCALE) * floor(width / GRID_SCALE);
      flowfield[index] = v;
      
      xoff += 0.1; // x方向のノイズオフセットをずらす
    }
    yoff += 0.1; // y方向のノイズオフセットをずらす
  }
}

// --- 粒子クラス ---
class Particle {
  constructor() {
    this.pos = createVector(random(width), random(height)); // 初期位置
    this.vel = createVector(0, 0); // 初速度
    this.acc = createVector(0, 0); // 加速度
    this.maxSpeed = 2; // 最高速度
    this.colorHue = random(160, 200); // 色相(水色〜青緑の範囲)
  }

  // 位置の更新
  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed); // 速度が速くなりすぎないように制限
    this.pos.add(this.vel);
    this.acc.mult(0); // 加速後は加速度をリセット
  }

  // 描画
  show() {
    stroke(this.colorHue, 80, 90, 2); // 色と透明度を設定
    strokeWeight(1.5);
    line(this.pos.x, this.pos.y, this.pos.x - this.vel.x * 2, this.pos.y - this.vel.y * 2);
  }

  // 画面外に出た時の処理
  edges() {
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.y > height) this.pos.y = 0;
    if (this.pos.y < 0) this.pos.y = height;
  }

  // 流れの地図に従う力を適用する
  follow(vectors) {
    let x = floor(this.pos.x / GRID_SCALE);
    let y = floor(this.pos.y / GRID_SCALE);
    let index = x + y * floor(width / GRID_SCALE);
    let force = vectors[index];
    if (force) {
      this.applyForce(force);
    }
  }

  // 力を加速度に適用する
  applyForce(force) {
    this.acc.add(force);
  }
}

難しく考える必要はなく、ほんの少し、ルールを意識するだけ。

  • 重力(物体が落ちる):全てのものは下に落ちますよね。これはプログラムで「Y座標の値を少しずつプラスしていく」ことで表現できます。さらに「だんだん速くなる」という加速度のルールを加えるだけで、動きは格段にリアルになります。

簡単な重力のサンプルコード↓
p5.js web editorで試す

// 簡単な重力のサンプルコード
let y = 0;
function draw() {
  background(240);
  y = y + 1; // 毎フレームy座標を1増やす
  ellipse(width/2, y, 30);
}
  • 風(木々のゆらめき):風は、目に見えない力の流れです。これを表現するには「パーリンノイズ(Perlin Noise)」という魔法の道具が役立ちます。ただのrandom()関数が作るバラバラな動きと違い、パーリンノイズは滑らかにつながりのあるランダムな値を生み出してくれます。これにより、そよ風に吹かれる木々や、立ち上る湯気のような、有機的な「ゆらぎ」が生まれるのです。
  • 流れ(川の流れ):川の流れは、無数の水の粒子(パーティクル)が、大きな流れの地図(ベクトル場)に沿って動いている状態です。一つ一つの粒子に「こっちの方向に進んでね」と教えてあげることで、画面全体に雄大な流れを描き出すことができます。

これらの根底にあるのは、物理的な法則の模倣です。上記のような世界のルールを、ほんの少しコードで再現してあげる。それだけで、あなたの作品は「それっぽく」見え始めるはずです。

「心地よい揺らぎ」の正体

なぜ私たちは「自然な動き」に心地よさや生命感を感じるのでしょうか?その答えは、人間の脳と心の仕組みに隠されています。

心理学の世界では「1/fゆらぎ(エフぶんのいちゆらぎ)」という言葉があります。これは、ろうそくの炎の揺れ、小川のせせらぎ、人の心拍のリズムなど、自然界に溢れている特別なリズムのこと。

暗闇の中で温かいオレンジ色に揺らめく、ろうそくの炎のイラスト。心地よい「1/fゆらぎ」を表現している。
No138 Candle Flame(ろうそくの炎)
上記画像のコードを見る(3/4)
(ここをクリックすると以下が開く)

このコードをp5.js Web Editorで試す

/**
 * @title   Candle Flame(ろうそくの炎)
 * @author  Takuya Watari (Watataku)
 * @date    2025-08-12
 *
 * @desc
 * パーリンノイズを用いて「1/fゆらぎ」をシミュレートし、
 * ろうそくの炎の心地よい揺らぎを表現する。
 *
 * @license
 * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 */

// --- 設定 ---
let particles = [];
const PARTICLE_NUM = 80; // 炎を構成する粒子の数
let noiseOffset = 0; // ノイズを動かすためのオフセット

// --- p5.jsのセットアップ関数 ---
function setup() {
  createCanvas(1600, 900);
  colorMode(HSB, 360, 100, 100, 100);
  noStroke();

  // 炎の中心位置を定義
  const flameBaseX = width / 2;
  const flameBaseY = height * 0.75;

  // 粒子を生成
  for (let i = 0; i < PARTICLE_NUM; i++) {
    particles.push(new Particle(flameBaseX, flameBaseY));
  }
}

// --- p5.jsの描画関数 ---
function draw() {
  // 背景を黒で塗りつぶす
  background(0);

  // ノイズのオフセットを更新して、炎全体を揺らす
  noiseOffset += 0.01;

  // 全ての粒子を描画
  for (let p of particles) {
    p.update(noiseOffset);
    p.show();
  }
}

// --- 炎の粒子クラス ---
class Particle {
  constructor(x, y) {
    // 粒子の基準位置
    this.basePos = createVector(x, y);
    this.pos = this.basePos.copy();
    
    // 各粒子に固有のノイズオフセットを持たせる
    this.pNoiseOffset = createVector(random(1000), random(1000));
    
    // 炎の上部ほど粒子が小さくなるように設定
    this.maxSize = random(80, 150) * (1 - (random() * 0.5));
    this.size = this.maxSize;

    // 炎の色相(赤〜黄色)
    this.hue = random(15, 60);
    // 炎の上部ほど透明に近くなる
    this.alpha = random(5, 20);
  }

  update(globalOffset) {
    // 炎全体の揺らぎ(グローバルなノイズ)と、粒子固有の揺らぎ(ローカルなノイズ)を組み合わせる
    let noiseX = noise(this.pNoiseOffset.x + globalOffset);
    let noiseY = noise(this.pNoiseOffset.y + globalOffset);

    // ノイズを使い、基準位置からのずれを計算
    let offsetX = map(noiseX, 0, 1, -20, 20);
    let offsetY = map(noiseY, 0, 1, -250, 0); // Y方向は上向きに大きくずれる

    // 粒子の位置を更新
    this.pos.set(this.basePos.x + offsetX, this.basePos.y + offsetY);
    
    // 上にいくほどサイズを小さくする
    this.size = map(this.pos.y, this.basePos.y, this.basePos.y - 250, this.maxSize, 0);
  }

  show() {
    // 描画色を設定
    fill(this.hue, 90, 100, this.alpha);
    
    // 光っているような効果
    drawingContext.shadowBlur = 32;
    drawingContext.shadowColor = color(this.hue, 80, 100);

    // 粒子(円)を描画
    ellipse(this.pos.x, this.pos.y, this.size);
  }
}

完全に予測できる規則的な動きでもなく、全く予測できないカオスな動きでもない。「規則性」と「不規則性」が絶妙に混ざり合ったこの「ゆらぎ」を、人間の脳は最も心地よいと感じるようにできています。

僕がかつて音楽で人に感動してもらおうと必死だった頃、気づいたことがあります。音程を意識しすぎた演奏では、人の心は動きにくかったです。そこに、ほんの少しの「間」や「揺れ」、つまり僕自身の「感情のゆらぎ」が加わったとき、聴いている人の涙腺を刺激することができました。

クリエイティブコーディングも全く同じです。

random()だけで作ったバラバラな動きは、人に不安を与えることも。

sinやcosだけで作った完璧な円運動は、機械的で退屈に見えることもあります。

しかし、パーリンノイズなどを使い、予測できそうで、できない、「心地よい裏切り」を動きの中に生み出すことで、人はそこに生命の気配を感じ取り、無意識に惹きつけられるのです。

動きに物語を宿らせる

科学と心理学の視点で心地よさの正体を知ったなら、最後は芸術家の目線で、そこに「物語」を吹き込みましょう。

自然現象は、それ自体が豊かな物語を持っています。

  • ひらひらと舞い落ちる一枚の葉は、「儚さ」や「終わりと始まり」の物語を。
  • 激しく打ち付ける雨は、「悲しみ」や「浄化」の物語を。
  • 暗闇を切り裂く稲妻は、「恐怖」や「閃き」の物語を。

クリエイティブコーディングで自然現象を扱うということは、単に動きを真似るだけではありません。その現象が持つ「感情」や「物語」を、あなた自身のフィルターを通して再構築する作業でもあります。

僕は世界20カ国を旅する中で、様々な自然の表情に出会ってきました。アイスランドのオーロラが見せる静かな畏怖、台湾を襲うスコールの後の生命力に満ちた空気。10万枚以上撮り溜めた写真を見返すと、その時の感情が蘇ります。

アイスランドのオーロラを撮影した写真。左の方に1軒の家が写っている。
実際に旅していたときにアイスランドで撮影したオーロラ。当時の僕の知識では撮るのが難しかった。
星が輝く夜空と黒い山々のシルエットを背景に、緑色の雄大なオーロラがゆっくりと揺らめいている様子。
No.138 Aurora over Iceland(アイスランドのオーロラ)
上記画像のコードを見る(4/4)
(ここをクリックすると以下が開く)

このコードをp5.js Web Editorで試す

/**
 * @title   Aurora over Iceland(アイスランドのオーロラ)
 * @author  Takuya Watari (watataku) 
 * @date    2025-08-12
 *
 * @desc
 * パーリンノイズを用いて、アイスランドの夜空に揺らめくオーロラを描く。
 * 静かな畏怖と、自然が紡ぐ物語を表現する。
 *
 * @license
 * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 */

// --- 設定 ---
let stars = [];
const STAR_COUNT = 400;
let auroraBands = [];
const BAND_COUNT = 5; // オーロラの帯の数

// --- p5.jsのセットアップ関数 ---
function setup() {
  createCanvas(1600, 900);
  colorMode(HSB, 360, 100, 100, 100);

  // 星を生成
  for (let i = 0; i < STAR_COUNT; i++) {
    stars.push(createVector(random(width), random(height * 0.7)));
  }

  // オーロラの帯を生成
  for (let i = 0; i < BAND_COUNT; i++) {
    auroraBands.push(new AuroraBand());
  }
}

// --- p5.jsの描画関数 ---
function draw() {
  // 夜空のグラデーションを描画
  drawNightSky();

  // 星を描画
  drawStars();
  
  // 山並みをシルエットで描画
  drawMountains();

  // オーロラを描画
  for (let band of auroraBands) {
    band.update();
    band.display();
  }
}

// --- 夜空のグラデーションを描画 ---
function drawNightSky() {
  let topColor = color(240, 80, 15);    // 深い夜の青
  let bottomColor = color(240, 70, 40); // 少し明るい青
  for (let y = 0; y < height; y++) {
    let inter = map(y, 0, height, 0, 1);
    let c = lerpColor(topColor, bottomColor, inter);
    stroke(c);
    line(0, y, width, y);
  }
}

// --- 星を描画 ---
function drawStars() {
  noStroke();
  for (let star of stars) {
    let starSize = random(0.5, 2);
    let starAlpha = random(50, 100);
    fill(0, 0, 100, starAlpha);
    ellipse(star.x, star.y, starSize);
  }
}

// --- 山並みをシルエットで描画 ---
function drawMountains() {
  noStroke();
  fill(0, 0, 5); // ほぼ黒
  beginShape();
  vertex(0, height);
  let xoff = 0;
  for (let x = 0; x <= width; x += 10) {
    let y = map(noise(xoff), 0, 1, height * 0.6, height * 0.85);
    vertex(x, y);
    xoff += 0.02;
  }
  vertex(width, height);
  endShape(CLOSE);
}

// --- オーロラの帯クラス ---
class AuroraBand {
  constructor() {
    this.yoff = random(1000); // 各帯の縦方向のノイズオフセット
    this.xoff_start = random(1000); // 帯の横方向の動きを管理
    this.hue = random(120, 160); // オーロラの色(緑〜青緑)
    this.alpha = random(10, 30); // 帯の透明度
    this.bandHeight = random(100, 400); // 帯の高さ
  }

  update() {
    // 帯をゆっくりと横に動かす
    this.xoff_start += 0.001;
  }

  display() {
    noStroke();
    fill(this.hue, 70, 100, this.alpha);
    
    let xoff = this.xoff_start;
    beginShape();
    // 帯の下側の境界線を描く
    for (let x = 0; x <= width; x += 10) {
      let y = map(noise(xoff, this.yoff), 0, 1, height * 0.1, height * 0.7);
      vertex(x, y);
      xoff += 0.01;
    }
    // 帯の上側の境界線を描く
    for (let x = width; x >= 0; x -= 10) {
      let y = map(noise(xoff, this.yoff + 50), 0, 1, height * 0.1, height * 0.7) - this.bandHeight;
      vertex(x, y);
      xoff -= 0.01;
    }
    endShape(CLOSE);
  }
}

あなたの作品に、あなたが撮影した写真を使い、砂のようにサラサラと崩れ落ちる表現(ピクセルソーティング)を加えたらどうでしょう?それは単なるエフェクトではなく、「思い出の風化」や「時間の経過」という、あなただけの物語を語り始めるはずです。

動きのある作品はもちろん、静止画であっても自然現象の「見せ方」は可能です
M.C.エッシャーのだまし絵のように、ありえない重力が支配する世界を描けば、見る人の想像力を掻き立て、作品の中に思考の旅へと誘うことができるでしょう。

あなたのコードに「自然」という魂を

ここまで、クリエイティブコーディングで自然現象を表現するための3つの視点を探求してきました。

  1. 科学者の視点: 世界のルール(物理法則)を真似てみよう。
  2. 心理学者の視点: 人が心地よいと感じる「ゆらぎ」を創り出そう。
  3. 芸術家の視点: 動きにあなただけの「物語」を込めよう。

難しく考えず、まずは身の回りの自然をじっくり観察することから始めてみてください。雨粒はどんな風に窓を伝っていく?風に吹かれたビニール袋はどんな動きをする?

その「なぜ?」と感じる探究心が、あなたのコードに他の誰にも真似できない、ユニークな生命感を吹き込んでくれます。

さあ、まずは小さな一歩を踏み出してみましょう。

手始めに、画面の上からボールが落ちて、地面で一度だけ「ぽよん」と跳ねる。そんな簡単なプログラムからで構いません。そこに、ほんの少し「加速度」という自然のルールを加えてみてください。きっと、昨日までのあなたの作品とは違う、確かな「生命の息吹」を感じられるはずです。


【さらに探求したいあなたへ】

この記事では「自然現象」に焦点を当てましたが、クリエイティブコーディングの探求はまだまだ続きます。

ところで、多くの人が参考にする「The Nature of Code」という本があります。このタイトルにある“Nature”という言葉、実は「自然」以外にもっと深い意味が隠されているのを知っていますか?

その意味を知ることは、あなたの「本質」や「個性」そのものを作品に映し出す、強力なヒントになります。

その話は、また次回の記事で。

ワタタク

それでは今日もレッツワクワクコーディング。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次