Appearance
アセット・パレット規約
スプライト・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〜$026F | UI フォント 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.pyv4 が生成($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.py | 4 ページ × 3 行 × 24 タイル。ステージタイル $80〜$8A を避けて配置 |
| エンディング(76 タイル) | gen_ending_font.py | 12 ページ × 3 行。"THE END" センタリング |
- ライセンス:
assets/fonts/LICENSE-misaki.txt。再生成にはMISAKI_BDF(../misaki/misaki_gothic.bdf)が必要(make prologue-font/make ending-font) - フォントに未定義の文字を
.byte文字列に書くと化ける。全パレットの color1 = $30(白)共有がテキスト可読性の要
BG パレット
| パレット | 用途 |
|---|---|
| 0 | UI テキスト(フォント) |
| 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 参照) |