Skip to content

アセット・パレット規約 ​

スプライト・BG タイル制作の確定ルール。アート修正を AI エージェント(Codex 等)に委譲するときは、本ページの制約をプロンプトに毎回明記すること。

制作方式(確定) ​

自動画像変換は禁止

画像 → CHR の自動変換は減色ノイズで一度失敗済み。**「帯パレット先行設計 → ピクセルマップ手打ち → Python ジェネレータで CHR 化」**が正のワークフロー。

tools/gen_ai_sprite.py         # アイ: ピクセルマップ → ai_sprite_data.inc + .chr(26F + ゲームオーバー 2F)
tools/gen_instructor_sprite.py # お手本ガール(講師): 32F × 128B → instructor_sprite_data.inc + .chr
tools/gen_ai_stage_bg.py       # ステージ背景 + 観客 17 状態 × 4F → ai_stage_bg_data.inc
tools/gen_dialog_font.py       # 会話かなフォント → dialog_font_data.inc(54 タイル)
tools/gen_prologue_font.py     # プロローグ 4 ページ × 3 行のフォント → prologue_font_data.inc(要 MISAKI_BDF)
tools/gen_ending_font.py       # エンディング 12 ページ × 3 行のフォント → ending_font_data.inc(同上)
tools/export_bgm_inc.py        # BGM: assets/bgm/*.json → bgm_data.inc(BANK0)
tools/export_charts_inc.py     # 譜面: assets/charts/charts.json → charts_data.inc(BANK0)
  • 生成物は src/*.inc として engine.s に取り込み、リセット時に CHR-RAM へ転送
  • CHR ラウンドトリップ検証(エンコードのピクセル一致確認)をテストで担保(tools/test_*.py)

CHR-RAM レイアウト(8KB) ​

リセット時に progress_entry_request に応じて転送する(engine.s の CHR 転送部)。

PPU アドレス内容
$0000〜$026FUI フォント 39 タイル: 0 = 空白, 1〜26 = A〜Z, 27〜36 = 0〜9, 37 = :, 38 = -
$0270〜$049Fステージ BG 低位タイル($27〜$49: 床・スポットライト・電脳グリッド・観客)
$04A0〜$07FF会話かなフォント 54 タイル($4A〜$7F)。プロローグ / エンディング起動時はここを各フォントで差し替え
$0800〜$08AFステージ高位タイル($80〜$8A: 台座・振りアイコン・スタンド)
$08B0〜$0A0Fエンディング用オーバーフロー 22 タイル(ENTRY_ENDING 時のみ)
$0A00〜$0A5Fプロローグ用オーバーフロー 6 タイル(ENTRY_PROLOGUE 時のみ)
$1000〜$1CFFアイのダンススプライト v4(26 フレーム = タイル 0〜207)
tile 208〜213ノーツ用振りアイコン
tile 214判定マーカー(8×8 リング)
tile 215〜216紙吹雪(S ランク演出、CONFETTI_TILE_BASE)
$1E00〜$1EFFコーチ CHR ダブルバッファ(スロット A = タイル $E0〜$E7 / スロット B = $E8〜$EF、NMI でストリーミング)
$1F00〜$1FFFアイのゲームオーバー 2 フレーム(タイル $F0〜$FF)
  • ステージ CHR は $0270 から連続転送した後、会話フォントが中央($04A0〜$07FF)を上書きする構造
  • アサートで配置を強制(dialog CHR must follow stage CHR / lane tiles must start at tile 208 など)。レイアウトを変えるとビルドが落ちる設計

アイのスプライト(v4・承認済み) ​

項目内容
サイズ16×32 メタスプライト(8×8 × 8 枚)
フレーム数26(idle + 各振り 4 コマ + ホールド等)
アニメ4 コマ × 5 フレーム = 20 フレーム固定・接地固定(ジャンプのみ pose_dy)
アセットassets/sprites/ai-dance-sprite-nes-v4.chr(3,328 バイト固定・アサートあり)

帯パレット(スプライト・確定値) ​

キャラの縦 32px を 3 帯に分け、行ごとに使用色を固定する。

帯(行)色(NES パレット値)用途
行 0〜15$00, $36, $2C頭部・上半身
行 16〜23$00, $30, $36腰まわり
行 24〜31$36, $30, $2C脚部
  • スプライトパレットは gen_ai_sprite.py v4 が生成($3F10〜)

スプライトパレット 4 本目は予約済み

$3F1C〜 は観客・判定文字用に予約。キャラ用に使わないこと。

お手本ガール(講師)のスプライト ​

  • 専用スプライト v1(未来系ダンス講師・#26/#40、ピンクアクセント #49)を本編に組込み済み(#42)
  • アセット: assets/sprites/instructor-dance-sprite-nes-v1.chr(4,096B = 32 フレーム × 128B、ページ境界整列)/ src/instructor_sprite_data.inc
  • CHR-RAM 上には常駐させず、BANK2 から $1E00 / $1E80 のダブルバッファへ NMI が 64B ずつストリーミングする(詳細はエンジン設計)。CHR を差し替える場合は 32 フレーム × 128B の契約を維持すること(tools/test_sprite_assets.py で検証)
  • 歩行 4 相(オープニング入場)とゲームオーバーポーズ(30/31)を含む

テキストフォント(美咲フォント由来) ​

フォント生成用途
会話かな(54 タイル)gen_dialog_font.py会話 24 タイル × 4 行 × 3 ページ。セリフから使用文字だけを CHR 化
プロローグ(60 タイル)gen_prologue_font.py4 ページ × 3 行 × 24 タイル。ステージタイル $80〜$8A を避けて配置
エンディング(76 タイル)gen_ending_font.py12 ページ × 3 行。"THE END" センタリング
  • ライセンス: assets/fonts/LICENSE-misaki.txt。再生成には MISAKI_BDF(../misaki/misaki_gothic.bdf)が必要(make prologue-font / make ending-font)
  • フォントに未定義の文字を .byte 文字列に書くと化ける。全パレットの color1 = $30(白)共有がテキスト可読性の要

BG パレット ​

パレット用途
0UI テキスト(フォント)
1電脳ステージ背景
2ステージ床
3観客

(ai_stage_bg_data.inc で確定。属性テーブルは 16×16px = 2 タイル単位でしか塗り分けられない点に注意)

スプライト同時使用数の設計制約 ​

  • NES は 1 スキャンラインに 8 スプライトまで
  • ノーツレーンは同一 Y にノーツ 6 + マーカー 1 = 7 枚で制限内。アイ・お手本ガールはレーンと別の Y 帯に配置
  • OAM 割り当て: アイ $0200- / お手本 $0220- / レーン $0240-

一枚絵の減色パイプライン(nes-quantize、#73) ​

フルカラーの元絵から背景データを作る手順。スキル nes-quantize(Skills/nes-quantize、正はスキル側)と同じスクリプトが tools/ にある。

元絵(セル画調・無地背景・主役大きめ)
  → tools/nes_bg_quantize.py   減色: 4 サブパレット自動導出、--flatten-bg、--protect、タイル上限   → assets/<x>/nes-base/*-raw.*
  → tools/nes_bg_sheet.py      比較シート(--grid で編集座標)
  → tools/nes_bg_edit.py       画素単位の微修正(貼り込み・色置換・ミラー・輪郭復元)             → assets/<x>/nes/*.*
  → tools/export_prologue_pictures.py  .inc 化(タイル 0 を黒に固定、sprite 0 位置、文字色)      → src/prologue_pictures.inc
  • Makefile: make prologue-nes-raw(量子化)→ make prologue-nes(編集)→ src/prologue_pictures.inc は依存関係で自動再生成
  • 承認済みレシピは --merge-metric index でバイト再現。ユーザーが選んだ旧版(nes-base/p1-v8, p2-v9)は凍結
  • 症状別の対処(四角いマスク = セルのパレット不一致、モザイク = タイル削減)は SKILL.md の表を参照

(2026-09-02 時点)

アセット状況
アイ(主人公)26 フレーム 16×32 + ゲームオーバー 2 フレーム✅ v4 承認済み・歩行 v3 / うなだれ追加(#53)
お手本ガール専用スプライト 32 フレーム✅ 組込み済み(CHR ストリーミング、#42/#49)
ステージ背景(床・スポットライト・電脳グリッド・巨大ビジョン)✅ 組込み済み(#41)
観客(3 段 84 席・17 状態 × 4 フレーム・テンション Lv1〜4)✅ 組込み済み(#38/#41)
振りアイコン・判定マーカー・紙吹雪✅ 組込み済み
会話 / プロローグ / エンディングフォント✅ 組込み済み(#27/#60)
判定文字 PERFECT / GOOD / MISS✅ UI フォント(BG テキスト行 JUDGE:)で表示
タイトル画面✅ 仮タイトル(#60)。新ロゴ合成版は wip/ai-title-screen で未マージ
プロローグ画像(#55〜#58)📋 フルカラー構図 v1 のみ。ROM のプロローグはテキストのみ
BGM✅ ROM に 5 曲(DPCM 版)/ トラッカー原曲は assets/bgm/ に 15 曲
譜面✅ 曲 0〜3 に固有譜面(assets/charts/charts.json、譜面メーカー #45)
カートリッジ✅ ラベル・シール・パッケージ印刷データ・3D プリント用シェル STL(assets/cartridge/ / assets/package/)
ソケット換装基板用シェル(前面 flat/hump 2 案)✅ 生成済み(tools/export_socket_cartridge_shells.mjs、famicom-package 参照)