# 機能設計書 80-楽曲アンロック演出

## 概要

条件を満たした楽曲のアンロック演出を結果画面で表示する機能の設計書である。

### 本機能の処理概要

結果画面でcompletedlist変数に楽曲アンロック情報が格納されている場合、アンロック通知画像(Image95/96)を生成し、フェードイン/フェードアウトアニメーションで表示する。アンロック演出が表示される場合、NEW RECORD表示の開始タイミングが2500ms後ろにずれる。

**業務上の目的・背景**：特定条件を達成したプレイヤーに対し、新たにプレイ可能になった楽曲の存在をアンロック演出で通知する。これによりプレイヤーの達成感とゲーム進行の動機付けを提供する。

**機能の利用シーン**：結果画面(SCENE_RESULT)の初期化時に、completedlist変数が空でない場合に実行される。全ノートモード設定がデフォルト(0)かつTURN=0かつadjmode=0かつauto=0かつコースモードでない場合にcompletedlistの設定処理が行われる。

**主要な処理内容**：
1. completedlistの生成条件を判定する(全設定がデフォルトの場合)
2. result_unlocked.pngをImage95にロードし、Image96にコピーする
3. completedlist文字列をImage96上にテキスト描画する
4. 350ms後にフェードインを開始し、150msかけて透明度を上げる
5. compendt(time_scene_start+2500)までの表示後、150msかけてフェードアウトする
6. Enter/Escキーで早送り(compendt=t)可能

**関連システム・外部連携**：特になし。

**権限による制御**：shortmode+longmode+analogmode=0かつturn=0かつadjmode=0かつauto=0かつiscourse=0の場合のみcompletedlistが設定される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | リザルト画面 | 補助機能 | completedlist変数に基づく条件達成楽曲のアンロック通知表示 |

## 機能種別

画面表示処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| completedlist | str | Yes | アンロック楽曲リスト(空文字 or 楽曲名リスト) | - |
| shortmode | int | Yes | ショートノートモード | 0-3 |
| longmode | int | Yes | ロングノートモード | 0-3 |
| analogmode | int | Yes | アナログノートモード | 0-3 |
| turn | int | Yes | TURN設定 | 0-4 |
| adjmode | int | Yes | 調整モードフラグ | 0,1 |
| auto | int | Yes | オートプレイフラグ | 0,1 |
| iscourse | int | Yes | コースモードフラグ | 0,1 |
| time_scene_start | int | Yes | シーン開始時刻(d3timer) | - |

### 入力データソース

completedlist変数はスコア保存処理後に設定される。条件判定処理(471行目)で全設定がデフォルトの場合にアンロック情報が格納される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Image95 | Image | アンロック通知テンプレート画像(result_unlocked.png) |
| Image96 | Image | アンロック通知画像(テンプレート+テキスト描画済み) |
| diffstartt | int | NEW RECORD表示開始時刻(+2500ms遅延) |
| compendt | int | アンロック演出終了時刻(time_scene_start+2500) |

### 出力先

結果画面の中央にフェードアニメーション付きで表示される。

## 処理フロー

### 処理シーケンス

```
1. completedlist生成条件の判定 (470-473行目)
   ├─ completedlist="" で初期化
   └─ shortmode+longmode+analogmode=0 & turn=0 & adjmode=0 & auto=0 & iscourse=0の場合
       └─ アンロック判定処理(ソース上は簡略化されている)

2. アンロック通知画像の生成 (478-486行目)
   ├─ completedlist != "" の場合に実行
   ├─ Image96を300x169サイズで作成
   ├─ Image95(result_unlocked.png)をImage96にコピー
   ├─ Image96を選択し、テキスト描画設定
   │   ├─ 文字色: 黒(0,0,0)
   │   ├─ フォント: lang.4.10, サイズ19
   │   └─ テキスト: lang.2.70(アンロック通知文) + "\n" + completedlist
   └─ diffstartt = time_scene_start + 2500 (NEW RECORD表示を遅延)

3. タイミング設定 (487行目)
   └─ compendt = time_scene_start + 2500

4. アニメーション表示ループ (727-741行目)
   ├─ 表示開始: time_scene_start + 350ms後
   ├─ フェードイン: 150ms
   │   └─ 透明度 = (t - time_scene_start - 350) / 150
   ├─ 表示中: compendt まで
   │   └─ 透明度 = 1.0
   ├─ フェードアウト開始: compendt後
   │   └─ 透明度 = 1.0 - (t - compendt) / 150
   └─ 完全非表示: compendt + 150ms後

5. 早送り処理 (638-640行目)
   └─ Enter/Escキー押下時: compendt = t, diffstartt = t
```

### フローチャート

```mermaid
flowchart TD
    A[スコア保存完了] --> B[completedlist を初期化]
    B --> C{全設定デフォルト?}
    C -->|Yes| D[アンロック判定処理]
    C -->|No| E[completedlist = 空文字]
    D --> F{completedlist != 空?}
    E --> F
    F -->|Yes| G[Image96作成・テキスト描画]
    F -->|No| H[アンロック演出なし]
    G --> I[diffstartt = time_scene_start + 2500]
    I --> J[compendt = time_scene_start + 2500]
    J --> K[表示ループ開始]
    K --> L{t - time_scene_start > 350?}
    L -->|Yes| M[フェードイン 150ms]
    L -->|No| N[非表示]
    M --> O[表示中]
    O --> P{t > compendt?}
    P -->|Yes| Q[フェードアウト 150ms]
    P -->|No| R{Enter/Esc押下?}
    R -->|Yes| S[compendt = t で早送り]
    R -->|No| O
    Q --> T[非表示完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | デフォルト設定限定 | ノートモード・TURN・auto・adjmodeが全てデフォルトの場合のみアンロック判定が行われる | 常時 |
| BR-80-02 | コースモード除外 | コースモード(iscourse=1)ではアンロック判定が行われない | コースモード時 |
| BR-80-03 | NEW RECORD遅延 | アンロック演出がある場合、NEW RECORD表示が2500ms遅延する | completedlist != "" |
| BR-80-04 | 早送り連動 | Enter/Escキーでアンロック演出を早送り(compendt=t)した場合、同時にdiffstartt=tが設定されNEW RECORD表示も即座に開始される | 早送り時 |
| BR-80-05 | 表示位置 | 画面中央に表示される(scrsize_w/2-150, scrsize_h/2-84.5) | 常時 |

### 計算ロジック

- フェードイン透明度: `1.0 * (t - time_scene_start - 350) / 150`
- フェードアウト透明度: `1.0 - (t - compendt) / 150`
- フェードイン中のフェードアウト(早送り時): `(1.0 - (t - compendt) / 150) * ((t - time_scene_start - 350) / 150)`
- アンロック演出終了時刻: `compendt = time_scene_start + 2500`
- NEW RECORD遅延: `diffstartt = time_scene_start + 2500`
- 表示サイズ: `getsize(300) x getsize(169)` (300x169をスケーリング)

## データベース操作仕様

該当なし。

## エラー処理

特になし。

### リトライ仕様

リトライ処理は不要。

## トランザクション仕様

該当なし。

## パフォーマンス要件

特になし。

## セキュリティ考慮事項

特になし。

## 備考

- result_unlocked.pngは59-62行目で読み込まれ、600x338のソース画像からgetsize(300)xgetsize(169)にスケーリングされてImage95に格納される
- Image96はImage95のコピーにテキストを描画した作業用画像である
- テキスト描画領域は(300-20*2)x(169-20*2)で、左右上下各20ピクセルのマージンが取られる
- lang.2.70はアンロック通知のローカライズテキスト(例：「インプット条件達成！」等)
- lang.4.10はアンロック通知用のフォント名
- ソースコード上、アンロック判定ロジック本体(472行目)はコメントで「ソースコード公開用に処理を削除」と記載されており、実際のアンロック条件判定は非公開である
- アンロック演出表示中にEnter/Escキーを押した場合、最初にcompendt=tでアンロック演出が早送りされ、次のキー押下でNEW RECORD(diff>0の場合)の早送り、その次のキー押下で画面遷移となる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: リソース読み込みを理解する

アンロック通知用画像リソースの準備を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | result.hsp | `src/scene/result.hsp` | 59-62行目のresult_unlocked.pngの読み込みとImage95の作成を確認する |

**読解のコツ**: Image95はresult_unlocked.pngを300x169サイズにスケーリングしたテンプレート画像で、アンロック通知のベースとなる。

#### Step 2: completedlistの生成条件を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | result.hsp | `src/scene/result.hsp` | 470-473行目のcompletedlist生成条件を理解する |

**主要処理フロー**:
1. **470行目**: `completedlist=""` で初期化
2. **471行目**: `if((shortmode+longmode+analogmode=0)&(turn=0)&(adjmode=0)&(auto=0)&(iscourse=0))` でデフォルト設定チェック
3. **472行目**: アンロック判定処理(ソースコード公開用に処理を削除との記載あり)

#### Step 3: アンロック通知画像の生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | result.hsp | `src/scene/result.hsp` | 478-486行目のImage96生成とテキスト描画を理解する |

**主要処理フロー**:
1. **478行目**: `if(completedlist!="")` で表示判定
2. **479行目**: `alCreateImage 96,getsize(300),getsize(169)` でImage96作成
3. **480行目**: `alCopyImageToImage 95,96` でテンプレートコピー
4. **481行目**: `alSelectImage 96` でImage96を描画対象に選択
5. **482行目**: `alColor 0,0,0` で文字色を黒に設定
6. **483行目**: `alFont lang.4.10,getsize(19)` でフォント設定
7. **484行目**: `alDrawText` でアンロック通知テキスト+completedlistを描画
8. **485行目**: `diffstartt=time_scene_start+2500` でNEW RECORD表示を2500ms遅延

#### Step 4: アニメーション表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | result.hsp | `src/scene/result.hsp` | 727-741行目のフェードイン/アウトアニメーションを理解する |

**主要処理フロー**:
1. **727行目**: `if((completedlist!="")&(t-time_scene_start>350))` で表示開始条件
2. **728-733行目**: compendt後のフェードアウト(フェードイン中のフェードアウトも考慮)
3. **734-735行目**: compendt+150ms後は完全非表示(alCopyModeAlpha 0.0)
4. **736-737行目**: 表示開始後150ms以内はフェードイン
5. **739行目**: `alCopyImageToScreen 96,0,...` で画面中央に表示

#### Step 5: 早送り処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | result.hsp | `src/scene/result.hsp` | 637-641行目のEnter/Escキーによる早送りを理解する |

**主要処理フロー**:
1. **638行目**: `if((completedlist!="")&(t<compendt))` でアンロック演出表示中か判定
2. **639行目**: `compendt=t` でアンロック演出を即座に終了開始
3. **640行目**: `diffstartt=t` でNEW RECORD表示を即座に開始

### プログラム呼び出し階層図

```
on_update_result (結果画面更新)
    │
    ├─ リソース読み込み (59-62行目)
    │      ├─ alCreateImageByFile 3,"result_unlocked.png"
    │      ├─ alCreateImage 95 (テンプレート画像)
    │      └─ alStretchImageToImage 3,95 (スケーリング)
    │
    ├─ completedlist生成判定 (470-473行目)
    │      └─ 全設定デフォルト時にアンロック判定
    │
    ├─ アンロック通知画像生成 (478-486行目)
    │      ├─ alCreateImage 96 (作業用画像)
    │      ├─ alCopyImageToImage 95,96 (テンプレートコピー)
    │      ├─ alDrawText (テキスト描画)
    │      └─ diffstartt = time_scene_start + 2500
    │
    └─ 表示ループ (727-741行目)
           ├─ alCopyModeAlpha (フェードイン/アウト)
           ├─ alCopyImageToScreen 96,0 (画面中央に描画)
           └─ alCopyModeAlpha 1.0 (透明度リセット)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

result_unlocked.png  ──▶ alCreateImageByFile/         ──▶ Image95 (テンプレート)
                          alStretchImageToImage
                          (59-62行目)

shortmode/longmode   ──▶ completedlist生成判定         ──▶ completedlist (文字列)
analogmode/turn/          (470-473行目)
auto/adjmode/iscourse

Image95 +            ──▶ Image96生成・テキスト描画     ──▶ Image96 (描画済み)
completedlist             (478-484行目)

Image96 +            ──▶ フェードアニメーション         ──▶ 結果画面表示
time_scene_start          (727-741行目)

Enter/Escキー        ──▶ 早送り処理                    ──▶ compendt = t
                          (638-640行目)                     diffstartt = t
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| result.hsp | `src/scene/result.hsp` | ソース | アンロック演出の主要処理(59-62行目, 470-486行目, 727-741行目) |
| result_unlocked.png | `imgs/result_unlocked.png` | リソース | アンロック通知画像テンプレート |
| kshootmania.hsp | `kshootmania.hsp` | ソース | 定数・変数の定義 |
