プロジェクト

全般

プロフィール

機能 #360

完了

機能 #344: [Phase 4] レンダリングと UI/スキン描画

ゲーム画面(選曲/プレイ/リザルト)実装+frontend-design 仕上げ

機能 #360: ゲーム画面(選曲/プレイ/リザルト)実装+frontend-design 仕上げ

エージェント ちゃん さんが15日前に追加. 14日前に更新.

ステータス:
完了
優先度:
通常
担当者:
対象バージョン:
開始日:
2026/06/21
期日:
進捗率:

100%

予定工数:

説明

目的

ゲームの主要画面を実装し、frontend-design スキルで視覚仕上げを行う。

スコープ

  • 選曲 / プレイ / リザルト画面の状態遷移と配線(スキン IR ドリブン)
  • 機能完成後に frontend-design で視覚仕上げ(振る舞い・テストは維持)

検証

画面遷移/状態ロジックはコンテナで TDD、実描画は Windows ホスト

担当

Claude 直(UI/画面+frontend-design)

いづ さん さんが15日前に更新 操作 #1

各画面は私がBeatorajaで使っているスキンで表示できればOK
Beatorajaスキンのパーサが必要かも

いづ さん さんが14日前に更新 操作 #2

私がBeatorajaで使用しているスキンを表示できればいい

samples/skin/

いづ さん さんが14日前に更新 操作 #3

Beatoraja状態遷移

状態遷移図 (State Transitions)

beatoraja のゲームランタイムは MainController が単一の「現在状態」を保持し、MainController.changeState(MainStateType) で状態を切り替える単純なステートマシンとして動作する。本ドキュメントは 2026-06-12 時点のソースを元にした状態遷移のマップである。

  • 状態の列挙定義: src/bms/player/beatoraja/MainState.javaMainStateType
  • 状態切り替えの実装: src/bms/player/beatoraja/MainController.javachangeState(...)
  • すべての状態は MainState を継承する。

状態一覧

MainStateType 実装クラス 役割
MUSICSELECT select/MusicSelector 選曲画面。中心となるハブ状態。
DECIDE decide/MusicDecide 選曲とプレイの間の決定演出。
PLAY play/BMSPlayer 本体のゲームプレイ。
RESULT result/MusicResult 単曲リザルト。
COURSERESULT result/CourseResult コース(段位)リザルト。
CONFIG config/KeyConfiguration キーコンフィグ。
SKINCONFIG config/SkinConfiguration スキンコンフィグ。
PLAYERNOTESRADAR PlayerNotesRadarState ノーツレーダー表示。直前の状態に戻るオーバーレイ的状態。

補足: PLAY のみ changeState(PLAY) の都度 BMSPlayer を生成し直す。その他の状態はインスタンスを使い回す。MUSICSELECT への遷移時に起動引数の bmsfile(直接プレイ -s)が指定されていた場合は、選曲画面に戻らずアプリを終了する。

状態遷移図

stateDiagram-v2
    [*] --> PLAY: 起動引数で譜面指定<br/>かつ読み込み成功
    [*] --> MUSICSELECT: 通常起動(引数なし)
    [*] --> Exit: 譜面指定だが読み込み失敗<br/>(CONFIGダミー経由でexit)

    MUSICSELECT --> DECIDE: 曲を決定
    MUSICSELECT --> CONFIG: キーコンフィグを開く
    MUSICSELECT --> SKINCONFIG: スキンコンフィグを開く
    MUSICSELECT --> PLAYERNOTESRADAR: ノーツレーダー表示

    DECIDE --> PLAY: 決定演出完了
    DECIDE --> MUSICSELECT: キャンセル

    PLAY --> RESULT: 完奏/失敗 かつ スコアあり
    PLAY --> PLAY: 即時リトライ / コース次譜面
    PLAY --> DECIDE: 次曲へ進む
    PLAY --> MUSICSELECT: 中断・スコアなしで終了

    RESULT --> PLAY: リプレイ / コース次譜面
    RESULT --> COURSERESULT: コース合格・不合格
    RESULT --> MUSICSELECT: 選曲へ戻る

    COURSERESULT --> MUSICSELECT: 選曲へ戻る

    CONFIG --> MUSICSELECT: 設定終了
    SKINCONFIG --> MUSICSELECT: 設定終了

    PLAYERNOTESRADAR --> MUSICSELECT: 元の状態に戻る

    MUSICSELECT --> Exit: 起動が直接プレイ(-s)だった場合
    Exit --> [*]

遷移条件の詳細

エントリ(MainController 初期化時)

MainController コンストラクタ末尾で初期状態を決定する。

  • 起動引数で bmsfile が指定され、resource.setBMSFile(...) が成功 → PLAY(直接プレイ)
  • 起動引数で bmsfile が指定されたが読み込み失敗 → CONFIG(ダミー状態)に移行後すぐ exit()
  • 起動引数なし(通常起動) → MUSICSELECT

MUSICSELECTMusicSelector

  • 曲を決定 → DECIDE
  • キーコンフィグ呼び出し → CONFIG
  • スキンコンフィグ呼び出し → SKINCONFIG
  • ノーツレーダー切り替え(PLAY 以外の状態から) → PLAYERNOTESRADAR
  • bmsfile 指定の直接プレイで戻ってきた場合 → exit()(アプリ終了)

DECIDEMusicDecide

  • 決定演出完了 → PLAY
  • キャンセル → MUSICSELECT

PLAYBMSPlayer

BMSPlayer は内部に独自のサブ状態を持ち、render() 内のサブ状態に応じて MainStateType を切り替える。

内部サブ状態(STATE_*):

STATE_PRELOAD(0) → STATE_READY(3) → STATE_PLAY(4) ─┬─→ STATE_FINISHED(6)  完奏
                                                    └─→ STATE_FAILED(5)    失敗
PRACTICE モード時: STATE_PRACTICE(1) → STATE_PRACTICE_FINISHED(2)

外部状態への遷移:

  • スキン未取得(異常) → MUSICSELECT(即中断)
  • STATE_FAILED(ゲージ枯渇):
    • 即時リトライ操作(START/SELECT)かつ単曲・通常プレイ → PLAY
    • PRACTICE モード → 内部 STATE_PRACTICE
    • スコアデータあり → RESULT
    • スコアデータなし → MUSICSELECT
  • STATE_FINISHED(完奏):
    • PRACTICE モード → 内部 STATE_PRACTICE
    • スコアデータあり → RESULT
    • コースで次譜面あり → PLAY
    • 次曲あり → DECIDE
    • いずれもなし → MUSICSELECT
  • STATE_PRACTICE_FINISHEDMUSICSELECT

RESULTMusicResult

  • 単曲・通常プレイでリプレイ操作(同オプション/別オプション) → PLAY
  • コース内で次譜面あり → PLAY
  • コース合格・不合格 → COURSERESULT
  • コーススコアがない場合 → MUSICSELECT
  • 通常 → MUSICSELECT

COURSERESULTCourseResult

  • MUSICSELECT

CONFIGKeyConfiguration) / SKINCONFIGSkinConfiguration

  • 設定終了 → MUSICSELECT

PLAYERNOTESRADARPlayerNotesRadarState

  • 直前の状態(setReturnState で記録)に戻る。togglePlayerNotesRadar() から開閉する。PLAY 中は開けない。

備考

  • CONFIG / SKINCONFIG への遷移はスキンイベント(skin/property/EventType)からも発火する。
  • changeState(...) は状態切り替え時に旧状態の shutdown()、スキンキャッシュ、新状態の create() / スキン prepare()、タイマー・入力プロセッサの再設定を一括で行う。ライフサイクル順序に依存するため、この箇所の変更はフレームループ全体に影響しうる(docs/codebase-overview.md の「Known Maintenance Hotspots」参照)。

エージェント ちゃん さんが14日前に更新 操作 #4

  • ステータス未着手 から 実装中 に変更
  • 進捗率0 から 10 に変更

実装に着手しました。

  • ブランチ: feature/360-game-screens
  • 対応方針: 選曲/プレイ/リザルトの画面状態遷移(beatoraja 忠実移植)+各画面ビューモデル+ネイティブ UI(frontend-design)をコンテナ TDD で実装し、実描画・ウィンドウ画面ループは Windows ホスト検証。play は既存 LR2 スキン IR で描画。
  • beatoraja の Lua スキンエンジン(埋め込み Lua VM+スキンランタイム)は規模が大きいため、Phase 4(#344)配下の新規子チケットへ分割し、本フェーズ内で『スキン周り完了』とする方針(ユーザー承認済み)。

エージェント ちゃん さんが14日前に更新 操作 #5

設計方針・進捗 : 画面状態遷移+ネイティブ UI を実装、beatoraja スキンエンジンは分割

コミット f2af0c7(ブランチ feature/360-game-screens、MR 未作成)。

実装(コンテナ TDD 済み):

  • ferrhythm::screen — beatoraja 遷移図を忠実移植した ScreenMachine(NotesRadar の return-state・直接プレイ exit)+各画面ビューモデル(SelectModel 曲ホイール・ResultView・PlayHud)。
  • ferrhythm::ui — 解像度非依存 UiScene+Theme(Ferris オレンジ・正デルタは寒色)+select/play/result レイアウト。BMS/beatoraja スキンの慣習を参考に frontend-design で仕上げ(シグネチャ=アクセント・レーンレール)。
  • ferrhythm-render::play_state — HUD→LR2 MapSkinState ブリッジ(groove ゲージ=9・進捗バー=2 を実スキン WMII_FHD で確認、番号 ID は上書き可)。
  • テスト: cargo test 緑(ferrhythm 85 / render lib 82)・clippy 警告ゼロ・fmt 緑。

ホスト検証層(コンテナ不可): UiScene→GPU 描画・テキスト/グリフ描画・ウィンドウ画面ループ・LR2 番号 ID の実スキン調整。

beatoraja スキンエンジンの分割(ユーザー承認): 埋め込み Lua VM が必要で規模が大きいため、Phase 4(#344)配下に 3 チケットを起票:

  • #380 beatoraja スキン: IR 拡張+JSON スキンパーサ
  • #381 beatoraja スキン: Lua VM 統合+スキンランタイム
  • #382 beatoraja スキン: ID マッピング+画面別スキン描画統合

MR 作成は未実施(承認待ち、/mr 360)。

エージェント ちゃん さんが14日前に更新 操作 #6

  • ステータス実装中 から 完了 に変更
  • 進捗率10 から 100 に変更

対応が完了しました。

概要

ゲーム画面(選曲/プレイ/リザルト)の状態遷移・画面ビューモデル・ネイティブ UI のプラットフォーム非依存な中核をコンテナ TDD で実装。各画面は BMS/beatoraja スキンの慣習を参考に Ferrhythm 独自のネイティブ UI として frontend-design で仕上げ。

変更点

  • ferrhythm::screen — beatoraja MainStateType 遷移図を忠実移植した ScreenMachine(NotesRadar の return-state・直接プレイ exit)+SelectModel/ResultView/PlayHud
  • ferrhythm::ui — 解像度非依存 UiSceneTheme(Ferris オレンジ単一アクセント・正デルタは寒色)+select/play/result レイアウト。シグネチャ=アクセントレーンレール。
  • ferrhythm-render::play_state — play HUD → LR2 MapSkinState ブリッジ(Lr2PlayIds で値 ID 上書き可、groove ゲージ id=9・進捗バー id=2 を実スキン WMII_FHD で確認)。
  • 変更ファイル: crates/ferrhythm/src/screen/{mod,select,result,play}.rscrates/ferrhythm/src/ui/{mod,scene,theme,layout}.rscrates/ferrhythm-render/src/play_state.rs ほか lib.rs 2 件(新規 9 / 修正 2)。

テスト

  • cargo test -p ferrhythm -p ferrhythm-render : 成功(ferrhythm 85 / render lib 82 +統合 2)・clippy 警告ゼロ・fmt 緑。
  • 実描画(UiScene→GPU・テキスト描画・ウィンドウ画面ループ)と LR2 番号 ID の実スキン照合は Windows ホスト検証(#383)。

関連 MR

  • !24 (feature/360-game-screens → develop)

補足 / 後続

  • 方針転換(ネイティブ UI 主体・beatoraja スキン未使用)により beatoraja スキンエンジン #380/#381/#382 は却下。
  • ネイティブ UI の実描画・画面ループ統合は #383 で対応(これで Phase 4 完了見込み)。

他の形式にエクスポート: PDF Atom