# 機能設計書 19-プレイヤー切替

## 概要

本ドキュメントは、K-Shoot MANIA の選曲画面における「プレイヤー切替」機能の設計を記述する。BT1+BT2+方向キーで現在のプレイヤーを切り替え、プレイヤー別のスコアデータを再読み込みする機能である。

### 本機能の処理概要

本機能は、選曲画面でBTキー1番と2番を同時押ししながら方向キーを操作することで、登録済みプレイヤー間を切り替える機能を提供する。プレイヤー切替後は、切替先プレイヤーのスコアデータを自動的に再読み込みし、選曲画面上のスコア・メダル・グレード表示を更新する。

**業務上の目的・背景**：同一PCを複数人で共有してプレイする場合に、プレイヤーごとにスコアデータを分離管理できるようにする。プレイヤー切替により、各自のプレイ履歴やハイスコアを個別に管理・参照可能。

**機能の利用シーン**：選曲画面でBT1+BT2を同時押ししながら上方向キーで前のプレイヤーへ、下方向キーで次のプレイヤーへ切り替える。画面下部にプレイヤー名が表示される。

**主要な処理内容**：
1. BT1+BT2の同時押し状態検出(`btkey.1 + btkey.2 = 2`)
2. 方向キー(上/下)入力によるcplayer変数の増減
3. プレイヤー名(`players.cplayer`)の更新
4. `*reloadscore`によるスコアデータの再読み込み
5. `*refreshscore`/`*refreshsonginfo`による表示の更新
6. 連続切替防止のためのタイムスタンプ制御(160ms間隔)

**関連システム・外部連携**：ファイルシステム(score/ディレクトリ)。

**権限による制御**：プレイヤーリストは`players`配列で管理。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | BT1+BT2+方向キーによるcplayer変数切替とスコア・楽曲情報のリロード |

## 機能種別

設定切替 / データ再読み込み

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| btkey.1 | int | Yes | BT-Bボタン状態(0:未押下, 1:押下) | 0 or 1 |
| btkey.2 | int | Yes | BT-Cボタン状態(0:未押下, 1:押下) | 0 or 1 |
| 方向キー | int | Yes | 上(stat1=1)または下(stat1=1)の入力 | - |
| cplayer | int | Yes | 現在のプレイヤーインデックス | 0 <= cplayer < playersnum |
| playersnum | int | Yes | 登録プレイヤー数 | 1以上 |
| playerminustp / playerplustp | int | Yes | 前回切替時刻(連続切替防止) | - |

### 入力データソース

- キーボード/ジョイスティック入力(BT1+BT2同時押し+方向キー)
- config.ini: プレイヤー名リスト(`players`配列)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cplayer | int | 切替後のプレイヤーインデックス |
| players.cplayer | string | 切替後のプレイヤー名 |

### 出力先

- 画面表示: 画面下部のプレイヤー名表示
- メモリ: *reloadscoreによるmscore配列の更新

## 処理フロー

### 処理シーケンス

```
1. BT1+BT2の同時押し検出(btkey.1 + btkey.2 = 2)
2. 方向キー上入力 かつ 160ms経過(timenow - playerminustp > 160)
   └─ cplayer-- (0未満ならplayersnum-1にラップ)
   └─ *reloadscore / *refreshscore / *refreshsonginfo 実行
   └─ playerminustp = timenow
3. 方向キー下入力 かつ 160ms経過(timenow - playerplustp > 160)
   └─ cplayer++ (playersnum以上なら0にラップ)
   └─ *reloadscore / *refreshscore / *refreshsonginfo 実行
   └─ playerplustp = timenow
4. プレイヤー名表示更新
   └─ IR接続時: players.cplayer + "[IR]"
   └─ 通常時: players.cplayer
```

### フローチャート

```mermaid
flowchart TD
    A{BT1+BT2同時押し?} -->|No| Z[何もしない]
    A -->|Yes| B{方向キー上?}
    B -->|Yes| C{160ms経過?}
    C -->|Yes| D[cplayer-- ラップアラウンド]
    C -->|No| Z
    B -->|No| E{方向キー下?}
    E -->|Yes| F{160ms経過?}
    F -->|Yes| G[cplayer++ ラップアラウンド]
    F -->|No| Z
    E -->|No| Z
    D --> H[*reloadscore / *refreshscore / *refreshsonginfo]
    G --> H
    H --> I[プレイヤー名表示更新]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-1 | 同時押し条件 | btkey.1 + btkey.2 = 2(BT-BとBT-Cの同時押し)が必須 | 常時 |
| BR-19-2 | 連続切替防止 | 前回切替から160ms以上経過していること | 常時 |
| BR-19-3 | ラップアラウンド | cplayerが範囲外になった場合、反対端にラップ | cplayer < 0 or cplayer >= playersnum |
| BR-19-4 | ダイアログ非表示 | dialognow=0(ダイアログ非表示)時のみ切替可能 | 常時 |
| BR-19-5 | IR表示 | IR接続中(ksm_id有)の場合はプレイヤー名に"[IR]"を付加 | プレイヤー名表示時 |

### 計算ロジック

なし。

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

本機能ではデータベース操作は行わない。*reloadscoreを通じてスコアファイルの再読み込みが発生する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | プレイヤー1人 | playersnum=1の場合 | 切替操作しても同じプレイヤーに戻る(ラップアラウンド) |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

- プレイヤー切替時に*reloadscoreが実行されるため、楽曲数が多い場合は一時的な遅延が発生する可能性がある

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

特になし。

## 備考

- cplayer変数はstart_select開始時に初期化されず、前回の値を保持する
- playerminustp/playerplustp変数はstart_select開始時に0で初期化される(57-58行目)
- プレイヤー名は画面下部のフッター領域に常時表示される(2294-2299行目)

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.hsp | `src/scene/select.hsp` | cplayer(プレイヤーインデックス)、playersnum(プレイヤー数)、players配列(プレイヤー名リスト)の変数を理解 |
| 1-2 | select.hsp | `src/scene/select.hsp` | playerminustp/playerplustp(連続切替防止タイムスタンプ)の役割を理解 |

**読解のコツ**: btkey配列はBTボタン0-3の状態を保持する。btkey.1=BT-B、btkey.2=BT-C。同時押しはbtkey.1+btkey.2=2で判定。

#### Step 2: プレイヤー切替処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | 227-242行目のプレイヤー切替処理 |

**主要処理フロー**:
1. **57-58行目**: playerminustp/playerplustp初期化(start_select内)
2. **227-234行目**: 上方向切替(cplayer--)
3. **236-242行目**: 下方向切替(cplayer++)
4. **229行目**: cplayer < 0 の場合 playersnum-1 にラップ
5. **238行目**: cplayer >= playersnum の場合 0 にラップ
6. **230-232行目**: *reloadscore -> *refreshscore -> *refreshsonginfo 呼び出し

#### Step 3: プレイヤー名表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.hsp | `src/scene/select.hsp` | 2294-2299行目のプレイヤー名表示処理 |

**主要処理フロー**:
- **2295-2296行目**: IR接続時の表示(`players.cplayer+"[IR]"`)
- **2297-2298行目**: 通常時の表示(`players.cplayer`)

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

```
選曲画面メインループ
    |
    +-- [BT1+BT2同時押し検出] (227行目)
    |       |
    |       +-- [方向キー上] (227-234行目)
    |       |       +-- cplayer-- (ラップアラウンド)
    |       |       +-- *reloadscore (4841行目)
    |       |       +-- *refreshscore (4958行目)
    |       |       +-- *refreshsonginfo (4057行目)
    |       |       +-- playerminustp = timenow
    |       |
    |       +-- [方向キー下] (236-242行目)
    |               +-- cplayer++ (ラップアラウンド)
    |               +-- *reloadscore
    |               +-- *refreshscore
    |               +-- *refreshsonginfo
    |               +-- playerplustp = timenow
    |
    +-- [プレイヤー名表示] (2294-2299行目)
            +-- _drawtxt players.cplayer
```

### データフロー図

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

BT1+BT2+方向キー ----------> cplayer増減 ----------------> cplayer(インデックス)
                                  |
players配列 -----------------> players.cplayer取得 ---------> プレイヤー名表示
                                  |
                              *reloadscore -----------------> mscore配列更新
                                  |
score/[プレイヤー]/ ---------> スコアファイル読み込み ------> sc/gr/md/pc更新
                                  |
                              *refreshsonginfo ------------> 画面再描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | プレイヤー切替処理(227-242行目)、プレイヤー名表示(2294-2299行目) |
| kshootmania.hsp | `kshootmania.hsp` | ソース | players配列・playersnum・cplayerの定義・config.iniからの読み込み |
