2022-06-05
わずか数kbの小さいプログラムですごい映像を実現するプログラム「メガデモ」、MSX-FANでの1画面プログラムなどの文化を継いだ、Twitterのツイート内に収まるプログラムが熱い!
たった256文字のJavaScriptコードで描かれた街の風景アニメがスゴ過ぎて訳がわからない - やじうまの杜 - 窓の杜


このツイート内の256文字のコードをindex.htmlとして保存して、ブラウザで開き、クリックすると実際に動き出します!

改行もなく詰め込んだプログラムを解いて、解析してみます。

まずは、インデントを付けて、読みやすく <canvas style=width:99% id=c> <script type="module"> let t, w, i, a, b, s, X, d, Z, Y; const f = () => { for ( c.width = w = 99, ++t, i = 6e3; i--; c.getContext`2d`.fillRect(i % w, i / w | 0, 1 - d * Z / w + s, 1) ) { for ( a = i % w / 50 - 1, s = b = 1 - i / 4e3, X = t, Y = Z = d = 1; ++Z < w & ( Y < 6 - (32 < Z & 27 < X % w && X / 9 ^ Z / 8) * 8 % 46 || d | ( s = (X & Y & Z) % 3 / Z, a = b = 1, d = Z / w ) ); Y -= b ) { X += a } } }; setInterval(f, t = 99); </script> 次にfor文内に詰め込まれたプログラム。実行順序を確認。(src on GitHub) let i = 0; for (alert(1), alert(2); alert(3), alert(4), i < 3; alert(5), i++) { alert("loop") } これに準じて(正確にはちょっと違うけど)展開して、コメントを入れてみました。 let t; // フレーム数 const f = () => { let w; c.width = w = 99; ++t; let s; // 背景 let d; let Z; // X座標 for (let i = w * 60 + 1; i--;) { const color = 1 - d * Z / w + s; // オリジナル //const color = s; // s のみでもそれなりに //const color = 1 - d * Z / w; // 背景なし //const color = d * Z / w; // 背景なし、反転 //const color = d * Z / w + s; // 背景あり、反転 //const color = d * Z / w; // 背景なし、反転 c.getContext("2d").fillRect(i % w, i / w | 0, color, 1) let a = i % w / 50 - 1; // ビルの横幅 50 を小さくすると細くなる let b; s = b = 1 - i / 4000; // 背景 let X = t; // フレーム数tに連動する、描画初期位置 let Y; Y = Z = d = 1; for (; ++Z < w; Y -= b) { X += a; //if (Y < 6 - (32 < Z & 27 < X % w && X / 9 ^ Z / 8) * 8 % 46) { //if (Y < 6 - (((32 < Z) & (27 < X % w)) && (X / 9) ^ (Z / 8)) * 8 % 30) { //const xo = (X / 9) ^ (Z / 8); //const xo = Z / 3; // 奥行き方向の形 三角 //const xo = X / 3; // 横方向の形 三角 const xo = 3 & (Z / 5); const n = 32 < Z && 10 < X % 20 && xo; // 横座標20の内10だけ表示 //const n = (32 < Z) & (27 < X % w) && xo; //const n = (80 < Z) && xo; // 表示距離 80より遠方 //const n = (80 < Z) & (27 < X % w) && xo; // 表示距離 80より遠方、横幅wの内27までを表示 if (Y < 6 - n * 8) { // if (Y < 6) { // 地平線のみ continue; } //s = (X & Y & Z) % 3 / Z; // オリジナル 格子 //s = (Y & Z) % 3 / Z, // 横線 //s = (X & Z) % 3 / Z, // 縦線 //s = (X & Y) % 3 / Z, // ぐちゃぐちゃ s = 1 / Z; // グラデーションのみ a = b = 1; d = Z / w; break; } } }; setInterval(f, t = 1000 / 60); 6e3 は、6000 と等価で1文字短くなります
(一番下の行が中途半端なのは6000がキャンバス幅99で割り切れないため)
c.getContext("2d") を c.getContext`2d` と書くことで2文字短縮。
| 0 とビット演算を使うことで、Math.floor の代わりに。
fillRectで、少数を使って塗ることで、白から黒へのグラデーションを実現。
(X / 9) ^ (Z / 8) この数式が、ビルを表現。
(X & Y & Z) % 3 / Z この数式で、窓を表現。

シンプルにしてみたものがこちら。

「city」
src on GitHub
コンピューターが非力なMSX時代によく見た、簡易3D表現、いまでもなかなかオシャレです。

Tweet
クリエイティブ・コモンズ・ライセンス
本ブログの記事や写真は「Creative Commons — CC BY 4.0」の下に提供します。記事内で紹介するプログラムや作品は、それぞれに記載されたライセンスを参照ください。
CC BY / @taisukef / アイコン画像 / プロフィール画像 / 「一日一創」画像 / RSS