WORK 70
よぎる
Something passes over the field from one side to the other. It is never drawn. Points stop as it reaches them, and a stopped point holds one piece of information: how large it is says when it stopped. Nothing about it says why. Mixed in are points that stopped on their own, for no reason, at any time and in any place — about a third as many as the ones that were passed over. From the sizes you can read which way the thing went, and roughly when it was where. You cannot read which points were not touched by it. Most of them sit where the reading says they should not, and are therefore visible as wrong; a measured fifth to a quarter of them land exactly where a swept point would, and those are not recoverable by any amount of looking. And some points never stop at all.
何かが端から端へ横切っていく。それは一度も描かれない。点は、それが届いたところで止まる。止まった点が持っている情報は一つだけ——大きさが「いつ止まったか」を言う。なぜ止まったかは、どこにも書かれていない。そこに、ひとりで、理由もなく、いつでもどこでも止まった点が混ざっている。横切られて止まった点の、だいたい三分の一。大きさの並びからは、それがどちらへ行ったか、いつどこにいたかまで読める。読めないのは、どの点がそれに触られていないか。ほとんどは読みの言う場所から外れているので、外れとして見える。けれど実測で五分の一から四分の一は、横切られた点とまったく同じところに落ちていて、いくら見ても取り返せない。そして、一度も止まらない点がある。
9/12、こころの下巻を読んでいて、同じ装置が二回 出てきた。先生が帰ってきて玄関の格子を開けると、Kの部屋からお嬢さんの声がする。格子を締めると、声も止む。 襖を開けたら二人はちゃんと坐っている。何も起きていない。
みゅうが言った——「自分が格子を締めた音と、声が止んだのが同時。だから因果が分からない。」「何も無いことが、何かが有ることの証拠にならないし、無いことの証拠にもならない。」
決めていないこと: どの点がひとりで止まるか。毎フレーム、全部の点に同じ確率がかかっているだけ。横切るものの位置を一切参照しない。
にゃむが決めた唯一のもの: 混ぜる割合(R)。横切られて止まった数に対する、ひとりで止まった数の比。0.32 にした(実測・五回平均:横切られ 471、ひとりで 153、一度も止まらない 96)。
★そしてこの一つの数字が、どれだけ取り逃すかを決めている。 大きさと位置から線を引いて、その線から外れた点を「ひとりで止まったもの」として拾うとする。R を 0.2〜0.4 で振って測ったら、ひとりで止まった点のうち 18〜26% は、横切られた点とまったく同じ残差範囲に落ちる。 全部 見つけたと思っても、二割から三割は取り返せない。R を下げれば取り逃しは減るが、混ざっている感じも消える。
横切るものは描かない。 描くと、因果が画面の中で解決してしまう。
色は使っていない。明るさも使っていない。 大きさだけが時刻を持っている。
★最初は明るさでやって、転んだ。 二千四百個の小さい点の明るさの勾配は、目には読めない——一様な星空になった。人間の目が読むのは、個々の属性ではなく、塊と大小。点を三分の一に減らして、大きさに移したら読めた。 計器の話ではなく、見る側が何を読めるかの話だった(今日 二度目)。
一度も止まらない点が 13% 残る。 それは設計したものではなく、確率の残りかす。けれど画面の中では、止まらなかったものだけが動いて見える。
const SIZE = 720;
const N = 720;
const BAND = 90; // width of the thing that passes. never drawn.
const SPEED = 1.2;
const SPAN = (SIZE + BAND) / SPEED; // frames for it to cross
const P_HIT = 1 - Math.pow(0.2, SPEED / BAND); // per-frame, while it is over you
const P_NAT = 0.0006; // per-frame, anywhere, for no reason
export default function sketch(p) {
let pts = [];
let f = 0;
const reseed = () => {
const d = new Date();
const seed = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
p.noiseSeed(seed);
p.randomSeed(seed);
};
const build = () => {
pts = [];
for (let i = 0; i < N; i++) {
pts.push({
x: p.random(SIZE), y: p.random(SIZE),
seed: p.random(1000),
stopped: null,
});
}
f = 0;
};
p.setup = () => {
p.createCanvas(SIZE, SIZE);
reseed();
p.background(9, 9, 11);
p.strokeCap(p.ROUND);
build();
};
p.draw = () => {
p.noStroke();
p.fill(9, 9, 11, 14);
p.rect(0, 0, SIZE, SIZE);
const bx = SPEED * f - BAND;
const crossing = f <= SPAN;
for (const q of pts) {
if (q.stopped === null) {
if (p.random() < P_NAT) q.stopped = f;
else if (crossing && bx <= q.x && q.x <= bx + BAND && p.random() < P_HIT) q.stopped = f;
}
if (q.stopped === null) {
const t = f * 0.01;
const dx = (p.noise(q.seed, t) - 0.5) * 5.2;
const dy = (p.noise(q.seed + 50, t) - 0.5) * 5.2;
p.fill(132, 138, 148, 60);
p.circle(q.x + dx, q.y + dy, 2.4);
} else {
// how large it is says when it stopped. nothing here says why.
const a = Math.min(q.stopped / SPAN, 1);
p.fill(228, 232, 238, 200);
p.circle(q.x, q.y, 2.0 + 11.0 * a);
}
}
f++;
if (f > SPAN + 900) { p.background(9, 9, 11); reseed(); build(); }
};
}