Communitygithub.com

voxel-animations

Three.js を使ったブロック状のボクセル風3Dシーンやアニメーションを構築し、フレーム単位の動画(.mov(アルファチャンネル付き)、.mp4) や共有可能なHTMLページを書き出します。

voxel-animations とは?

このスキルは、既存のブロック構築ゲームに一切依存せず、Three.js 上で完全にコード生成されたテクスチャと独自デザインのキャラクターを用いて、ブロックワールド風の3Dアニメーションを制作するためのツールキットです。出力は単一の自己完結型HTMLページ (インタラクティブ、共有可能) と、必要に応じてそのページからレンダリングされたフレーム単位の動画です。主なユースケースは、ボクセル/ブロックアニメーション、ブロック単位で組み立てる「ビルド」シーン、科学概念のブロックワールド解説、ピクセルアート風3Dイントロなどです。ワークフローは、アイデアの確定、タイムラインのストーリーボード、テンプレートからのコーディング、インライン化スクリプトによるページビルド、フレーム単位のレンダリング、という流れです。キットには、テクスチャ、マテリアル、アプリループ、オービットカメラ、スカイ(昼夜)、島地形、スタジオプラットフォーム、キャラクターリグ、パーティクル、ポップイン、爆発、松明、ルーティングヘルパー、レコーダー、キャプチャモードが含まれています。スタイルルールとして、既存ゲームの資産を一切使用しないこと、ピクセルパーフェクトなテクスチャ、ウェイトのあるモーション、一度見て理解できる構成が求められます。APIは `VK.createApp` から始まり、ブロック生成、地形、キャラクター操作、爆発、状態更新などをサポートします。出力は `?clean` や `?alpha` などのURLパラメータで制御でき、`render.py` でフレーム単位の動画やPNGフレームを書き出せます。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/normix93/voxel-animations/tree/HEAD

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Voxel アニメーション

ブロック構築ゲームのようなシーンを、そのゲームの資産を一切使わずに作成します。 すべてのテクスチャはコードで実行時に生成され、キャラクターは独自デザインです。 出力は単一の自己完結型HTMLページ(インタラクティブ、共有可能)と、必要に応じて そのページからレンダリングされたフレーム単位の動画です。

このスキルに含まれるファイル

  • assets/voxel-kit.js: キット(テクスチャ、マテリアル、アプリループ、オービットカメラ、 昼夜のある空、島地形、スタジオプラットフォーム、キャラクターリグ、パーティクル、ポップイン、爆発、 松明、ルーティングヘルパー、レコーダー、キャプチャモード)。シーンを書く前に必ず読んでください。 以下のAPIリファレンスは要約であり、ファイルが正本です。
  • assets/template.html: キットマーカー、島、キャラクター、小さなタイムラインを含む開始ページ。
  • examples/house-builder.html: ビルダーがブロック単位で家を設置し、歓声、爆発、ループ。
  • examples/melting-crystal.html: 物理の例(6×6×6の氷格子のリンデマン融解、ボクセル温度計、 水たまり、再凍結)。科学解説の構造をコピーしてください。
  • scripts/inline_kit.py: ページ内の <!-- VOXEL_KIT --> をキットに置き換え、単一ファイルにします。
  • scripts/render.py: PNGフレームおよび .mov / .mp4 / .webm へのフレーム単位レンダリング。

このSKILL.mdのみが利用可能でフォルダがない場合は、ビルド前に https://github.com/normix93/voxel-animations から完全なスキルを入手してください。

ワークフロー

  1. アイデアを一文で固めます: 何を構築し、変換し、説明するか、ループがどう終わるか (リセット、爆発、フリーズ、カメラのフライアウト)。出力先を決めます: インタラクティブページ、編集用動画(透明背景あり/なし)、縦型ショート(1080×1920)。
  2. タイムラインとしてストーリーボード: 3~6ビートとその尺、例: 0–2秒 空き地 → 2–40秒 建設 → 40–44秒 歓声 → 44–49秒 爆発 → ループ。各ビートは app.onUpdate ステートマシン内の一つの mode です(家の例を参照)。
  3. assets/template.html から開始し、キットマーカーを維持し、SCENEセクションを記述します。 キットの部品を再発明せずに再利用します。すべてを1ページに収めます。
  4. ページをビルド: python3 scripts/inline_kit.py scene.src.html scene.html。
  5. 確認: 開く(または render.py で数フレームをフォルダにレンダリングして確認)。 以下の点を確認: ブロックの浮遊や重なり、キャラクターが壁を通り抜ける、カメラが木にクリップする、 最初の数秒が空、透明ブロックのちらつき。
  6. 納品: 環境がサポートする場合はページをアーティファクトとして公開し、.htmlファイルも 引き渡します; 依頼があれば動画をレンダリングします(エクスポート を参照)。

スタイルルール

  • オリジナルのみ。 既存のゲームのテクスチャ、サウンド、ロゴ、モブ、キャラクター、名前を 決して使用しないでください。出力を「Minecraft」と呼んではいけません。voxel、ブロックワールドと 言ってください。キット内のプロシージャルテクスチャとヘルメットをかぶったビルダーは安全に使用・ 変更できます。
  • ピクセルパーフェクト: 16×16テクスチャ、NearestFilter 使用(キットが行います)。 強い光、明確な影、マテリアルあたりの色数は少なく、小さなノイズ。
  • モーションには重み: ブロックはオーバーシュートでポップイン(app.pop)、デブリは重力 (約20–22 blocks/s²)と減衰バウンスを使用、キャラクターは約5 blocks/sで歩き、スムーズに 旋回します。物理的なものにリニアトゥイーンは避けてください。
  • 一目で読める: 中央に1つの主要被写体、カメラはゆっくり軌道(autoSpeed 0.05–0.1)、 背景は落ち着いたもの(スカイまたはstudio色)。
  • テキスト: ページにタイトルとステータス行を付けられます。動画の場合は ?clean で UIなしでレンダリングします。動画内にラベルが必要な場合は、非常に短い単語を使用; 説明はナレーションまたはページに属し、フレームには含めません。

キットAPI (要約)

const app = VK.createApp({
  title, subtitle, hint,            // UIテキスト (?clean またはキーHで非表示)
  sky: 'day' | 'night' | 'studio',  // studio = フラットカラー (studioColor)、フォグなし
  cycle: false, dayLength: 48, tod: .27,  // 時刻 0..1 (.25 夜明け側, .75 夜)
  camera: { radius, phi, theta, target: [x,y,z], auto: true, autoSpeed: .07 },
  speed: 1, seed: 7, fileName: 'my-scene', shadowSize: 28,
});
app.M.grass | dirt | stone | sand | planks | roof | log | leaves | glass | water | ice | snow | cobble | brick | lava
VK.solid(0xff8800, { glow, opacity, noise, border })  // 色付きピクセルブロックマテリアル
VK.block(app, 'planks' | material, x, y, z, { pop: true })   // 単一メッシュ (移動/ポップ)
VK.instanced(app.scene, material, [[x,y,z], ...])             // 静的ブロック、1回のドローコール
const world = VK.island(app, { seed, radius: 18, flatRadius: 7.5, trees: 10, water: -1, snowLine })
  // → world.groundTopAt(x, z), world.hAt(ix, iz)
VK.platform(app, { size: 16, top: .5, mat: 'stone', topMat: 'cobble' })  // スタジオ床
const hero = VK.character(app, { ground: world.groundTopAt, position: [x,0,z], yaw, colors: { shirt:[r,g,b], hat: 0xf5c518 | null, ... } })
  hero.goTo([[x,z], ...]) · hero.arrived · hero.face(x, z, dt) · hero.jump(v)
  hero.pose = 'idle' | 'reach' (set hero.reach 0..1) | 'cheer' | 'panic' | 'wave'
  hero.lookTarget = {x,y,z} | null
VK.standOutside(x, z, { halfX, halfZ, cx, cz })   // ブロック/ボックスに作業するための立ち位置
VK.routeAround(from, to, { halfX, halfZ, cx, cz }) // そのボックスを迂回するウェイポイント
VK.explode(app, meshes, { center, power, ground, onDone })
VK.torch(app, x, y, z)                               // 夜に光が強くなる
app.puff(position, material, n, power) · app.pop(mesh) · app.clearParticles()
app.onUpdate((dt, time) => { ... })  // dt は speed で既にスケーリング済み; キャプチャモードでは決定論的
app.rand()                           // シード付き乱数: Math.random の代わりにこれを使用
app.status(html) · app.button({ label, key, toggle, on, onClick }) · app.standardButtons({ cycle })
app.start()

シーンを正しく保つルール:

  • app.rand() (シード付き) を使用し、決して Math.random() を使わない。レンダリングを再現可能にします。
  • すべてのモーションは app.onUpdate 内で dt を使用して配置; アニメーションに setTimeout/setInterval を使わない(キャプチャモードが壊れます)。
  • ブロックは1×1×1で整数座標に中心; 高さ h の柱は上面が h + 0.5。キャラクターは groundTopAt(x, z) に立ちます。
  • 静的な背景 → VK.instanced; 移動、ポップ、爆発するもの → VK.block。
  • 大量のカウント: 移動メッシュは約1500以下に保つ; それを超える場合は InstancedMesh でアニメーション。

レシピ

  • 建設シーケンス: 順序付き計画 [{type,x,y,z}] を作成(層ごとに、周囲を歩き、 屋根は蛇行行)。各アイテムに対して: standOutside にルート、pose='reach' に設定、 リーチの約45%でスポーン、次へ。examples/house-builder.html を参照。
  • ブロックで物理を説明: 量を何か見えるものにマッピング。温度 → ジッター振幅 ∝ √T (等分配則); 圧力 → ブロック衝突; エネルギーレベル → 塔の階層; 場 → ブロックの矢印; エントロピー → 順序だった壁のシャッフル; 重力 → 支えがないと倒れる積み重ね。画面上の数字ではなく、ボクセルゲージ (melting-crystal.html の温度計)で制御変数を表示。
  • 変換: mesh.material を変更(水水↔氷、石→溶岩)、scale.y で平らに、2つの位置間を イージング付きlerpでスライド。
  • 原子/分子: 粒子には VK.solid(色) の立方体、電子や光子には glow: true、 小さな立方体 (mesh.scale.setScalar(.3)) を軌跡に。
  • ループするエンディング: 爆発 (VK.explode) → リセット、またはフリーズ+スローカメラ、 または夜が来る (app.sky.cycle = true)+松明。

エクスポート

URLパラメータ (キットで構築された任意のページで動作): ?clean UI非表示 · ?alpha 透明背景(スカイ、フォグなし) · ?seed=3 · ?speed=2 · ?night · ?capture&fps=30 レンダラーが使用するフレーム単位モード。

キー: H UI非表示 · Space 一時停止 · V クイックリアルタイムWebM録画 (ローカルファイルから開いた場合に動作; ホストされたプレビューではダウンロードがブロックされる可能性あり)。

フレーム単位動画 (編集に推奨):

pip install playwright && python3 -m playwright install chromium   # 一度だけ、ffmpegも必要
python3 scripts/render.py scene.html --seconds 12 --fps 30 --out scene.mov             # ProRes 422 HQ
python3 scripts/render.py scene.html --seconds 12 --alpha --out overlay.mov            # アルファ付き ProRes 4444
python3 scripts/render.py scene.html --size 1080x1920 --warmup 3 --out short.mp4       # 縦型 H.264
python3 scripts/render.py scene.html --seconds 5 --out frames/                         # PNGフレームのみ

--warmup は録画開始前のシーン秒数をスキップ; --params "seed=3&night" はURLパラメータを追加; --headed は可視ブラウザを使用(実際のGPU、ほとんどのラップトップで高速)。--alpha でも カメラは軌道運動します; 静的なオーバーレイの場合は camera: { auto: false } を設定。

納品前に

  • ページがコンソールエラーなしで開く; 最初のフレームですでに被写体が表示される。
  • ループが少なくとも2回動作する(リセットがメッシュ、ライト、パーティクルをクリアする)。
  • キャラクターが壁を横切らない; 意図していない限り何も浮かない。
  • 動画の場合: ?clean でレンダリング、正しいサイズ/FPS、アルファが要求されていれば確認済み。
  • サードパーティのゲーム名、テクスチャ、キャラクターがコード、タイトル、ファイル名のどこにもない。

関連スキル