# 機能設計書 62-プレイ中HiSpeed変更

## 概要

本ドキュメントは、K-Shoot MANIA のプレイ画面においてプレイ中にHiSpeed（譜面のスクロール速度）をリアルタイムで変更する機能の設計を記述する。FXボタン長押し（Enter キー）+BT ボタンまたは方向キーの操作で、5種類のHiSpeed方式（x倍速/C値/m値/a値/オフセット値）に対応した速度変更が可能である。

### 本機能の処理概要

**業務上の目的・背景**：リズムゲームでは譜面のスクロール速度が視認性に大きく影響する。BPM変化のある楽曲や初見プレイ時に、プレイヤーがリアルタイムでスクロール速度を調整できることで、プレイの快適性と成績向上を支援する。

**機能の利用シーン**：ゲームプレイ画面（SCENE_PLAY）において、FXボタン（Start/Enter キー）を押したまま、BT ボタンや方向キーで上下操作する。HiSpeed方式の切替は左右操作で行う。通常ゲージモードまたはゲージ残量がある状態でのみ操作可能である。

**主要な処理内容**：
1. FXボタン長押し状態の検出（enter_key=1）
2. 上下入力によるHiSpeed値の増減（方式に応じた刻み幅で変更）
3. 左右入力によるHiSpeed方式の切替（x倍速 ↔ C値 ↔ m値 ↔ a値 ↔ オフセット値）
4. 変更後のhs値（実際のスクロール速度）の再計算
5. 楽曲情報表示のリフレッシュフラグ設定

**関連システム・外部連携**：config.ini への保存（プレイ終了時に processEscKeyInput 内で行われる）。

**権限による制御**：通常ゲージモード（effratetype<=0 かつ iscourse=0）、またはHARDゲージで残量がある場合（gauge/1000>0）のみ操作可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | FXボタン長押し+BTによるプレイ中HiSpeed変更処理 |

## 機能種別

入力制御 / パラメータ変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| enter_key | int | Yes | Enter(FX)キー状態（0/1） | 1でHiSpeed変更モード有効 |
| 上方向入力 | int | Yes | 上矢印キー/BTキー/ジョイスティック上 | ts2>60 の入力間隔制限 |
| 下方向入力 | int | Yes | 下矢印キー/BTキー/ジョイスティック下 | ts2>60 の入力間隔制限 |
| 左方向入力 | int | Yes | 左矢印キー/FXキー | ts>120 の入力間隔制限 |
| 右方向入力 | int | Yes | 右矢印キー/FXキー | ts>120 の入力間隔制限 |
| ctrl_key | int | Yes | Ctrlキー状態（0/1） | 0 であること（Ctrl押下中は無効） |
| hstypenow | int | Yes | 現在のHiSpeed方式（0-4） | 0=x倍速, 1=オフセット, 2=C値, 3=m値, 4=a値 |

### 入力データソース

キーボード入力（getkey / getkey_a 関数）、ジョイスティック入力（getjoykeystat 関数）、アナログスティック入力（stickstat 配列）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| hsr | int | x倍速の値（5-99、実効BPM = bpm * hsr / 10） |
| hso | int | オフセット値（25-2000、25刻み） |
| hsc | int | C値（25-2000、25刻み） |
| hsm | int | m値（25-2000、25刻み） |
| hsa | int | a値（25-2000、25刻み） |
| hstypenow | int | 現在のHiSpeed方式 |
| hs | int | 計算後のスクロール速度値 |
| minforefresh | int | 楽曲情報表示のリフレッシュフラグ（1=要更新） |

### 出力先

内部変数への書き込み。プレイ終了時にconfig.iniへ保存。

## 処理フロー

### 処理シーケンス

```
1. 操作可能判定
   └─ ginfo2()=0 AND (通常ゲージモード OR ゲージ残量>0)
2. *refreshhs サブルーチンで現在のHiSpeed方式を確認
3. 上方向入力の検出
   └─ 上矢印 OR (BT上キー AND enter_key=1) OR (ジョイスティック上 AND enter_key=1)
   └─ ts2>60 AND ctrl_key=0 の場合:
       - hstypenow=0: hsr++ (上限99)
       - hstypenow=1: hso+=25 (上限2000)
       - hstypenow=2: hsc+=25 (上限2000)
       - hstypenow=3: hsm+=25 (上限2000)
       - hstypenow=4: hsa+=25 (上限2000)
       - minforefresh=1
4. 下方向入力の検出（同様の構造で値を減少）
   └─ hstypenow=0: hsr-- (下限5)
   └─ その他: 値-=25 (下限25)
5. 左方向入力の検出（HiSpeed方式の切替: 前の方式へ）
   └─ ts>120 AND ctrl_key=0
   └─ 現在のスクロール速度を保持したまま方式を変換
   └─ vhstype配列で有効な方式のみ巡回
6. 右方向入力の検出（HiSpeed方式の切替: 次の方式へ）
   └─ 同上
7. *refreshhs で最終的なhstypenow を確認
8. hs値の再計算
   └─ hstypenow=0: hs = 108*hsr/10/2
   └─ hstypenow=1: hs = 108*hso*1000/oftbpm/2
   └─ hstypenow=2: hs = 108/2 (C値はBPM連動)
   └─ hstypenow=3: hs = 108*hsm*1000/maxbpm/2
   └─ hstypenow=4: hs = 108*hsa*1000/avebpm/2
   └─ hs < 1 の場合: hs = 1
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作可能?}
    B -->|No| Z[return]
    B -->|Yes| C[refreshhs で現在方式確認]
    C --> D{上方向入力?}
    D -->|Yes| E[方式に応じてHiSpeed値を増加]
    D -->|No| F{下方向入力?}
    F -->|Yes| G[方式に応じてHiSpeed値を減少]
    F -->|No| H{左方向入力?}
    H -->|Yes| I[HiSpeed方式を前へ切替]
    H -->|No| J{右方向入力?}
    J -->|Yes| K[HiSpeed方式を次へ切替]
    J -->|No| L[hs値を再計算]
    E --> L
    G --> L
    I --> L
    K --> L
    L --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-62-1 | ゲージ制限 | HARDゲージ/コースモード時はゲージ残量がある場合のみ変更可能 | effratetype>0 OR iscourse=1 |
| BR-62-2 | x倍速の範囲 | hsr は 5 以上 99 以下（x0.5 ~ x9.9） | hstypenow=0 |
| BR-62-3 | C/m/a/オフセット値の範囲 | 25 以上 2000 以下、25 刻み | hstypenow=1,2,3,4 |
| BR-62-4 | Ctrl キー無効化 | Ctrl キーが押されている間は HiSpeed 変更を無効化 | ctrl_key=0 |
| BR-62-5 | 方式切替時の速度保持 | 方式切替時には現在のスクロール速度（BPM換算値）を保持して新方式の値に変換する | 左右入力時 |
| BR-62-6 | 有効方式のみ巡回 | vhstype 配列で有効（=1）な方式のみ切替対象とする | 方式切替時 |

### 計算ロジック

**HiSpeed方式ごとのhs値計算**:
- x倍速 (hstypenow=0): `hs = 108 * hsr / 10 / 2`
- オフセット値 (hstypenow=1): `hs = 108 * hso * 1000 / oftbpm / 2`
- C値 (hstypenow=2): `hs = 108 / 2` (BPM変化に追従)
- m値 (hstypenow=3): `hs = 108 * hsm * 1000 / maxbpm / 2`
- a値 (hstypenow=4): `hs = 108 * hsa * 1000 / avebpm / 2`

**方式間の変換（左右切替時）**:
1. 現在の方式でのスクロール速度を BPM換算値(stat2) に統一
2. 新方式での値を逆算（ran関数で範囲制限: min=25, max=2000）

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

### 操作別データベース影響一覧

本機能にデータベース操作はない。プレイ終了時に config.ini へ HiSpeed 設定値が保存される（processEscKeyInput 内）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 範囲外値 | hsr, hso, hsc, hsm, hsa が範囲外 | min/max による範囲クリップ |
| - | hs=0 | 計算結果が0以下 | hs=1 に強制設定（441行目） |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

毎フレーム呼ばれる processHiSpeedChangeInput 関数内で処理されるが、条件分岐による早期リターンがあるため、通常操作時以外の負荷は極小。

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

該当なし。

## 備考

- C値方式（hstypenow=2）は BPM 変化に追従するため、hs 値自体は固定値（108/2）だが、BPM 変化時にスクロール速度が自動調整される
- no_hstype_c 変数は C値方式使用時に 0 に設定され、IR（インターネットランキング）のスコア送信条件に影響する（434行目）
- スプラッシュ画面でも同一のHiSpeed変更ロジックが複製されている（play_splash_screen.hsp）

---

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

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

### 推奨読解順序

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

HiSpeed 制御に関わる変数群を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | hsr/hso/hsc/hsm/hsa の5変数がそれぞれのHiSpeed方式の値を保持。-1は無効を示す |
| 1-2 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | hstypenow: 現在アクティブなHiSpeed方式（0-4） |
| 1-3 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | vhstype: 各方式の有効/無効フラグ配列 |

**読解のコツ**: HiSpeed の5方式はそれぞれ独立した変数で管理されるが、アクティブな方式は1つだけ。他の方式の値は -1 に設定される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | `processHiSpeedChangeInput` 関数（288行目から定義）がエントリーポイント |

**主要処理フロー**:
1. **289行目**: 操作可能条件の判定（ウィンドウアクティブ AND ゲージ条件）
2. **290行目**: `*refreshhs` サブルーチンで現在のHiSpeed方式を取得
3. **291-301行目**: 現在の方式に応じたBPM換算値の計算
4. **302-323行目**: 上方向入力の処理（値の増加）
5. **324-344行目**: 下方向入力の処理（値の減少）
6. **345-385行目**: 左方向入力の処理（方式の前方切替）
7. **386-426行目**: 右方向入力の処理（方式の後方切替）
8. **428-441行目**: hs値の最終計算

#### Step 3: hs値の計算ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | **429-440行目**: 方式ごとのhs値計算。108はベースとなるスクロール速度定数 |
| 3-2 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | **434行目**: C値方式時に `no_hstype_c=0` を設定（IR条件に影響） |

#### Step 4: スプラッシュ画面での重複実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_splash_screen.hsp | `src/scene/play/play_splash_screen.hsp` | **125-267行目**: スプラッシュ画面でも同一のHiSpeed変更ロジックが実装されている |

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

```
play_update (メインループ)
    |
    +-- processHiSpeedChangeInput
    |       |
    |       +-- *refreshhs (現在のHiSpeed方式確認)
    |       +-- getkey / getkey_a (キーボード入力)
    |       +-- getjoykeystat (ジョイスティック入力)
    |       +-- stickstat (アナログスティック入力)
    |       +-- ran() (範囲制限関数)
    |
    +-- (hs値がノート描画・カメラ制御で参照される)

startSplashScreen (スプラッシュ画面)
    |
    +-- *refreshhs + 同一のHiSpeed変更ロジック
```

### データフロー図

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

キーボード/            processHiSpeedChangeInput
ジョイスティック  ───>  ┌───────────────────────────┐
  FX長押し+BT          |  方式判定                  |
  方向キー              |  ├─ 上下: 値の増減        |      hsr/hso/hsc/hsm/hsa
                        |  └─ 左右: 方式の切替      |  ──> hs (スクロール速度)
BPM情報         ───>   |  hs値の再計算              |      minforefresh=1
  bpm/maxbpm/          |  値の変換(方式間)          |
  avebpm/oftbpm         └───────────────────────────┘
                                                        ──> config.ini (終了時保存)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_key_input.hsp | `src/scene/play/play_key_input.hsp` | ソース | processHiSpeedChangeInput 関数（288-442行目） |
| play_splash_screen.hsp | `src/scene/play/play_splash_screen.hsp` | ソース | スプラッシュ画面での HiSpeed 変更処理（重複実装） |
| play_draw_frame.hsp | `src/scene/play/play_draw_frame.hsp` | ソース | hs値を使用したノート描画・HiSpeed表示 |
| play_game_logic.hsp | `src/scene/play/play_game_logic.hsp` | ソース | hs変数の初期値設定 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | config.ini への HiSpeed 設定保存 |
