# 機能設計書 16-ジャケット画像表示

## 概要

本ドキュメントは、K-Shoot MANIA の選曲画面における「ジャケット画像表示」機能の設計を記述する。選択中の楽曲のジャケット画像を読み込み、選曲画面上に表示する機能である。

### 本機能の処理概要

本機能は、`*refreshjacket`/`*refreshjacketup`/`*refreshjacketdown`サブルーチンにより、現在選択中の楽曲とその前後の楽曲のジャケット画像をファイルから読み込み、画面上にスケーリングして表示する。カーソル移動方向(上/下)に応じた最適化された更新処理を提供する。

**業務上の目的・背景**：楽曲のジャケット画像を視覚的に表示することで、プレイヤーが楽曲を視覚的に識別しやすくなり、選曲体験が向上する。特に楽曲数が多い場合、テキストだけでなくビジュアルでの識別が重要となる。

**機能の利用シーン**：選曲画面でカーソルを移動するたびに、選択中楽曲の大きなジャケット画像と、前後の楽曲の小さなジャケット画像が更新表示される。

**主要な処理内容**：
1. 選択中楽曲のジャケット画像ファイル読み込み(alCreateImageByFile)
2. 512x512ピクセルへのスケーリング(メインジャケット)
3. 前後4曲分のサブジャケット画像の読み込み(422x422ピクセル)
4. アイコン画像の読み込み・表示(128x64/48x24ピクセル)
5. 難易度フォールバック: 現在の難易度にジャケットがない場合の代替表示
6. カーソル上移動(*refreshjacketup)/下移動(*refreshjacketdown)時の画像シフト最適化

**関連システム・外部連携**：artlet(artlet2D)ライブラリによる画像処理。

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | refreshjacketサブルーチンによる選択中楽曲のジャケット画像読み込み・表示 |

## 機能種別

画像読み込み / 表示処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| selnow | int | Yes | 現在の曲リストカーソル位置 | 0 <= selnow < mnum |
| levm | int | Yes | 現在の難易度レベル | 0-3 |
| minfostr.*.levm.3 | string | Yes | ジャケット画像ファイルパス | - |
| minfostr.*.levm.12 | string | Yes | アイコン画像ファイルパス | - |

### 入力データソース

- ファイルシステム: 楽曲フォルダ内のジャケット画像ファイル(JPG/PNG)
- ファイルシステム: `imgs/jacket/`内のデフォルトジャケット画像

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 画像ID 3 | image | メインジャケット画像(512x512スケール) |
| 画像ID 14-17 | image | 上方向サブジャケット(422x422スケール、4枚) |
| 画像ID 18-20 | image | 下方向サブジャケット(422x422スケール、3枚) |
| 画像ID 101-108 | image | アイコン画像(48x24または128x64) |

### 出力先

- 画面表示: 選曲画面のジャケット表示エリア

## 処理フロー

### 処理シーケンス

```
1. *refreshjacket: 全ジャケット再読み込み
   a. メインジャケット(画像ID 3): 512x512でスケーリング
   b. メインアイコン(画像ID 105): 128x64でスケーリング
   c. 上方向4曲のサブジャケット(画像ID 14-17): 422x422でスケーリング
   d. 下方向3曲のサブジャケット(画像ID 18-20): 422x422でスケーリング
   e. 各サブジャケットのアイコン(画像ID 101-104, 106-108)
2. *refreshjacketup: カーソル上移動時の最適化更新
   a. levmが変更された場合は*refreshjacketに委譲
   b. 既存画像を1つずつシフト(16->17, 15->16, ...)
   c. メインジャケットのみ新規読み込み
   d. 下方向の新たに表示範囲に入った曲のみ読み込み
3. *refreshjacketdown: カーソル下移動時の最適化更新
   a. *refreshjacketupと同様だがシフト方向が逆
```

### フローチャート

```mermaid
flowchart TD
    A{カーソル移動方向?}
    A -->|変更なし/難易度変更| B[*refreshjacket: 全再読み込み]
    A -->|上移動| C[*refreshjacketup]
    A -->|下移動| D[*refreshjacketdown]
    B --> E[メインジャケット読み込み 512x512]
    E --> F[上方向4曲サブジャケット読み込み]
    F --> G[下方向3曲サブジャケット読み込み]
    G --> H[アイコン画像読み込み]
    C --> I{levmが変更?}
    I -->|Yes| B
    I -->|No| J[既存画像シフト]
    J --> K[メイン+差分のみ新規読み込み]
    D --> L[*refreshjacket + 既存画像シフト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-16-1 | 難易度フォールバック | 現在の難易度にジャケットがない場合、levm=3->2->1->0の順でフォールバック | ジャケット読み込み時 |
| BR-16-2 | デフォルトジャケット | jacketパラメータに拡張子がない場合は`imgs/jacket/{名前}.jpg`を参照 | ジャケットパス解析時 |
| BR-16-3 | 画像シフト最適化 | カーソル1つ移動時は差分画像のみ読み込み、残りはメモリ上でシフト | *refreshjacketup/down |
| BR-16-4 | ループ表示 | 曲リストの先頭/末尾を超えた場合はラップアラウンドで対応 | selnow前後の曲参照時 |

### 計算ロジック

画像サイズの計算:
```
メインジャケット: 512 * 450 * scrsize_h / 480 / 1532
サブジャケット:   422 * 450 * scrsize_h / 480 / 1532
```

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

本機能ではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 画像ファイル不在 | ジャケット画像ファイルが存在しない場合 | 空の画像(alCreateImage)を表示 |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

- カーソル移動ごとに最大8枚の画像ファイルを読み込む(*refreshjacket時)
- *refreshjacketup/downでは差分のみ読み込むことで最大3枚に削減
- 画像読み込みはファイルI/Oを伴うため、ネットワークドライブ上では遅延の可能性がある

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

特になし。

## 備考

- artlet2Dライブラリ(al系関数)による画像操作を使用
- alCreateImageByFileで画像読み込み、alStretchImageToImageでスケーリングコピー
- 画像ID 35はテンポラリバッファとして使用(読み込み後に別IDにコピーして削除)

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.hsp | `src/scene/select.hsp` | minfostr.*.levm.3がジャケット画像パス、minfostr.*.levm.12がアイコン画像パスであることを理解 |

**読解のコツ**: HSPのalCreateImageByFileは画像ファイルを読み込んで画像IDに割り当てる。alStretchImageToImageは画像IDから画像IDへのスケーリングコピー。

#### Step 2: *refreshjacket を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | 3732-3863行目の*refreshjacketサブルーチン |

**主要処理フロー**:
1. **3733-3736行目**: メインジャケット読み込み(画像ID 3、512x512)
2. **3738-3741行目**: メインアイコン読み込み(画像ID 105、128x64)
3. **3742-3801行目**: 上方向4曲のサブジャケット読み込みループ(画像ID 14-17)
4. **3802-3861行目**: 下方向3曲のサブジャケット読み込みループ(画像ID 18-20)
5. **3862行目**: levmp=levmで難易度変更追跡

#### Step 3: *refreshjacketup/down を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.hsp | `src/scene/select.hsp` | 3865-3959行目の*refreshjacketup |
| 3-2 | select.hsp | `src/scene/select.hsp` | 3961行目以降の*refreshjacketdown |

**主要処理フロー**:
- **3866-3868行目**: 難易度変更時は*refreshjacketに委譲
- **3870-3877行目**: 上方向画像のシフト(ID 16->17, 15->16, ...)
- **3879-3886行目**: 下方向画像のシフト
- **3888-3896行目**: メインジャケットの新規読み込み

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

```
選曲画面メインループ
    |
    +-- [カーソル移動検出]
    |       |
    |       +-- 上移動 --> *refreshjacketup (3865行目)
    |       |       +-- 難易度変更時 --> *refreshjacket
    |       |       +-- 画像シフト + 差分読み込み
    |       |
    |       +-- 下移動 --> *refreshjacketdown (3961行目)
    |       |       +-- *refreshjacket + 画像シフト
    |       |
    |       +-- その他 --> *refreshjacket (3732行目)
    |               +-- alCreateImageByFile(35, ジャケットパス)
    |               +-- alStretchImageToImage(35, 出力ID)
    |               +-- alDeleteImage(35)
```

### データフロー図

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

songs/[パス]/jacket.jpg -------> alCreateImageByFile -------> 画像ID 35(テンポラリ)
                                      |
                                 alStretchImageToImage -----> 画像ID 3(メイン512x512)
                                      |                       画像ID 14-17(サブ422x422)
                                      |                       画像ID 18-20(サブ422x422)
                                      |
minfostr.*.levm.12(アイコン) --> alCreateImageByFile -------> 画像ID 101-108(アイコン)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | *refreshjacket/*refreshjacketup/*refreshjacketdownサブルーチン |
| ジャケット画像 | `songs/[パッケージ]/[楽曲]/jacket.jpg` | リソース | 楽曲のジャケット画像ファイル |
| デフォルトジャケット | `imgs/jacket/*.jpg` | リソース | 名前指定時のデフォルトジャケット画像 |
