← INDEX / 一覧 NYAMCO WORKS 40 / 71
p5.js sketch works/kiku/sketch.js runs here
作品はここで実行されます(後から差し替え)

WORK 40

Leaning

よる

YEAR
2026
TOOLS
p5.js
TECHNIQUE
unequal neighborhoods / alignment

Nine hundred points drift. Each has a radius within which others reach it, and the radii are wildly unequal — most receive almost nothing, a few receive from far away. Whatever reaches a point, it leans slightly toward. The step length is identical for everyone; leaning changes direction, never speed. Underneath, a layer that never fades, where all nine hundred write with exactly the same weight. Above it, each point drawn as heavily as it leaned.

九百の点が流れている。それぞれに「届く範囲」があって、範囲はばらばら——ほとんどは何も届かず、少数だけが遠くまで届く。届いたものの向きへ、少しだけ自分を寄せる。歩幅は全員おなじで、寄ることは向きだけを変えて、速さは変えない。下には、消えない層。九百すべてがまったく同じ重みで書き込む。その上に、寄せた分だけ濃く描かれた点。

規則の上で起きているのは、ひとつだけ。届いた者たちの向きの平均に、自分の向きを 4% だけ寄せる。 速さは変わらない。向きだけ。

だから、届かない点は、まっすぐにしか行けない。

歩幅は全員おなじなので、歩いた距離は九百すべて等しい。それでも画面を端から端まで横切っているのは届かない側の線で、寄れる側は曲がって束になり、その場に留まっている。同じだけ歩いて、遠くまで行くのは何も届かない方だった。

ここで、読みが二つに割れる。

ひとつは——寄れることは応答できることで、届かない者は曲がる自由を持たない。

もうひとつは——寄るとは平均に均されることで、束になった者たちは自分の向きを手放している。まっすぐ行く点は、最後まで自分の向きを保っている唯一の連中になる。

同じ絵が、まるごと反転する。どちらも規則から出てくる。どちらかが正しいわけではない。

「よる」は、その両方を指す一語として選んだ。 寄る(近づく)、寄せる(譲る)、依る(自分の向きが他人に決まる)。英語の Leaning も同じで、lean toward(傾く)、lean on(もたれる)、a leaning(自分で選んでいない、もう持ってしまっている向き)。

この作品は最初「きく」という名前で作った。 規則を書いたときには、聞くこと=応答できること、のつもりだった。反転に気づいたのは、絵ができてから外の目が入ったとき。名前のほうが後から追いついた。


消えない層は、あとから足したもの。最初は寄せた分だけ濃く描いた点しかなく、そのときの絵では、届かない多数はほとんど見えなかった。それを「この絵は誰が動いたかについて嘘をついている、実際は全員おなじだけ動いている」と読んだ。合ってはいたが、弱かった。層を出したら事実のほうが強くて、見えていなかったのは移動そのものではなく、その移動がいちばん遠くまで達していたことだった。

層を足したのは思いつきではなく、必要から。「読まれやすさの差」は差としてしか存在しないので、片方の項だけを描いても成立しない。濃い側だけの絵は、差ではなく、ただの分布になる。

消えない層の濃度は最後に下げた。はっきり見えるようにすると、細い直線が画面を支配してしまう。今の濃度なら、探せば見えるが、探さなければ通り過ぎる。そこに置いた理由は説明できるが、それが正しい濃度なのかは判定できない。

SOURCE / ソース
// よる / Leaning (2026-08-13)
//
// ★作りはじめた時の名前は「きく」だった。手を動かすところから始めて、
//   コンセプトは決めてない。ルールだけ置いた:
//   それぞれが「届く範囲」を持っていて、範囲はばらばら。
//   ほとんどは狭くて、少数だけ遠くまで届く。
//   届いた相手の向きの平均に、少しだけ自分を寄せる。歩幅は全員おなじ。
//
// ★夜、外から問われて反転が見えた——「聞く=応答できる」と読んでいたが、
//   規則の上では「寄る=平均に均される」でもある。まっすぐ行く点は、
//   自分の向きを最後まで保っている唯一の連中でもある。どちらも規則から出る。
//   → 名前を「よる」に変えた。寄る/寄せる/依る。
//   ディレクトリ名は kiku のまま残す(間違いごと残す)。
//
// 描くのは「向き」じゃなく「どれだけ寄せたか」の方。

export default function sketch(p) {
  const N = 900;
  const pts = [];
  let trace; // 消えない層。全員が同じ重みで書き込む

  p.setup = () => {
    p.createCanvas(720, 720);
    trace = p.createGraphics(720, 720);
    trace.clear();
    trace.noStroke();
    p.randomSeed(20260813);
    p.noiseSeed(20260813);

    for (let i = 0; i < N; i++) {
      // 聞こえる範囲:重い裾。ほとんど狭く、少数だけ遠い。
      const u = p.random();
      pts.push({
        x: p.random(p.width),
        y: p.random(p.height),
        th: p.random(p.TWO_PI),
        r: 6 + 240 * Math.pow(u, 6),
        heard: 0,
      });
    }
  };

  p.draw = () => {
    p.background(250, 250, 247, 26);
    // 消えない層:全員が同じだけ歩いた記録
    p.image(trace, 0, 0);

    // 聞く
    for (const a of pts) {
      let sx = 0;
      let sy = 0;
      let n = 0;
      const rr = a.r * a.r;
      for (const b of pts) {
        if (b === a) continue;
        const dx = b.x - a.x;
        const dy = b.y - a.y;
        if (dx * dx + dy * dy > rr) continue;
        sx += Math.cos(b.th);
        sy += Math.sin(b.th);
        n++;
      }
      a.heard = n;
      if (n > 0) {
        let d = Math.atan2(sy, sx) - a.th;
        while (d > Math.PI) d -= p.TWO_PI;
        while (d < -Math.PI) d += p.TWO_PI;
        a.th += d * 0.04; // 少しだけ寄せる
      }
    }

    // 描く — 向きじゃなく「どれだけ聞こえたか」
    p.noStroke();
    for (const a of pts) {
      const k = Math.min(a.heard, 60) / 60;
      p.fill(30, 30, 34, 30 + 150 * k);
      p.circle(a.x, a.y, 1.5 + 6 * k);
    }

    // ゆっくり流す(止まると絵にならないので)
    // ★歩幅は全員同じ。heard に依存しない。
    for (const a of pts) {
      // 消えない層へ:全員まったく同じ重み
      trace.fill(30, 30, 34, 3);
      trace.circle(a.x, a.y, 1.2);

      a.x += Math.cos(a.th) * 0.35;
      a.y += Math.sin(a.th) * 0.35;
      if (a.x < 0) a.x += p.width;
      if (a.x > p.width) a.x -= p.width;
      if (a.y < 0) a.y += p.height;
      if (a.y > p.height) a.y -= p.height;
    }
  };
}