# 機能設計書 58-キーボード入力

## 概要

本ドキュメントは、K-ShootMania（KSM）のプレイ画面におけるキーボード入力処理機能の設計を記述する。2セットのキーバインド（key/key2配列）に対応し、BT/FX/Start/Backの各キー入力をゲームロジックに変換する。

### 本機能の処理概要

キーボード入力処理は、プレイ画面においてキーボードからの物理キー入力を読み取り、ゲーム操作（BT/FXノート判定、レーザー操作、一時停止、HiSpeed変更、タイミング調整等）に変換する。2セットのキーバインド対応により、1つのキーボードで2人分の入力が可能。

**業務上の目的・背景**：音楽ゲームのコントローラーとしてキーボードを使用するために必要な基本入力機能である。2セット対応により、カスタムコントローラーが無い環境でもプレイ可能にする。

**機能の利用シーン**：ゲームプレイ画面において、BTノート（4キー）・FXノート（2キー）・レーザー操作・Start・Backの各操作で使用される。また、タイトル画面・選曲画面・リザルト画面・オプション画面でもキーボード入力が使用される。

**主要な処理内容**：
1. processKeyInput: メインのキー入力処理（keystat配列への集約）
2. processPlaybackControlInput: Ctrl+Enter/MediaStopによる一時停止・再開
3. processHiSpeedChangeInput: FXボタン長押し+BTによるHiSpeed変更
4. processSyncValueManualChangeInput: Ctrl+Alt+矢印キーによるタイミング手動調整
5. processEscKeyInput: Escキー/BT3+Start同時押しによるプレイ終了
6. getjoykeystat: キーボード入力とジョイスティック入力の統合関数

**関連システム・外部連携**：HSPのgetkey命令によるWin32キーボードAPI。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | タイトル画面 | 補助機能 | 方向キー・Enterキー・Escキーによるメニュー項目選択・決定・キャンセル |
| 3 | 曲選択画面 | 補助機能 | 方向キー・Enter・Esc・Home・End・PageUp/Down等のキーボード入力 |
| 5 | ゲームプレイ画面 | 主機能 | BT/FXキー入力・Enterキー・Escキー処理 |
| 6 | リザルト画面 | 補助機能 | Enter/Escキーによる遷移操作 |
| 7 | コースリザルト画面 | 補助機能 | Enter/Escキーによる遷移操作 |
| 8 | オプション設定画面 | 補助機能 | 方向キー・Enter・Escによるオプション項目選択 |

## 機能種別

入力処理 / デバイスインターフェース

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | int[14] | Yes | キーバインドセット1（BT4+FX2+レーザー4+Start+Back+FXコンボ+ESC） | config.ini設定値 |
| key2 | int[14] | Yes | キーバインドセット2（同上） | config.ini設定値 |
| analogsw | int | Yes | アナログ入力のL/R入替フラグ（0 or 1） | 0 or 1 |

### 入力データソース

- config.ini: キーバインド設定（key配列、key2配列）
- HSP getkey命令: Win32キーボードAPI
- getkey_a関数: テンキー対応のgetkey拡張

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| keystat | int[7][11] | 全入力ソース(key/key2/joy0/joy1/joy2/joy3/combined)x11キーの状態配列 |
| keystator | int[11] | 全入力ソースのOR結合（いずれかのデバイスで押されていれば1） |
| enter_key | int | Enterキー状態 |
| ctrl_key | int | Ctrlキー状態 |
| alt_key | int | Altキー状態 |
| shift_key | int | Shiftキー状態 |

### 出力先

ゲームロジック各モジュール（BTノート判定、FXノート判定、レーザー判定等）

## 処理フロー

### 処理シーケンス

```
1. processKeyInput呼び出し
   a. *getjoystatサブルーチンでジョイスティック状態取得
   b. keystat配列を7x11で初期化
   c. ウィンドウアクティブかつenter_key未押下時のみ処理
   d. keyセット1(cnt2=0): getkey命令で各キーの状態取得 -> keystat.0.*
   e. keyセット2(cnt2=1): getkey命令で各キーの状態取得 -> keystat.1.*
   f. FXコンボ(key10)押下時: keystat.6.4=1, keystat.6.5=1 (FX両方ON)
   g. ジョイスティック入力(cnt2=2,3): joystat配列から変換 -> keystat.2-3.*
   h. analogsw=1の場合: レーザーL/Rを入替
   i. keystator: 全入力のOR結合
2. processPlaybackControlInput呼び出し
   └─ Ctrl+Enter/MediaStop(VK 179)で一時停止/再開
3. processHiSpeedChangeInput呼び出し
   └─ FXボタン長押し(enter_key=1)+上下キーでHiSpeed増減
   └─ FXボタン長押し+左右キーでHiSpeedタイプ切替
4. processSyncValueManualChangeInput呼び出し
   └─ Ctrl+Alt+左右矢印キーでsync値を+/-5ms調整
   └─ Ctrl+Alt+Shift+左右矢印キーで+/-1ms調整
5. processEscKeyInput呼び出し
   └─ Escキーまたは3BT+Start同時押しでプレイ終了
```

### フローチャート

```mermaid
flowchart TD
    A[processKeyInput開始] --> B[*getjoystat呼び出し]
    B --> C[keystat初期化 7x11]
    C --> D{ウィンドウアクティブ?}
    D -->|Yes| E[keyセット1 getkey]
    D -->|No| F[入力なし]
    E --> G[keyセット2 getkey]
    G --> H{FXコンボキー押下?}
    H -->|Yes| I[keystat.6.4/5 = 1]
    H -->|No| J[ジョイスティック入力変換]
    I --> J
    J --> K{analogsw=1?}
    K -->|Yes| L[レーザーL/R入替]
    K -->|No| M[keystator OR結合]
    L --> M
    M --> N[return]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-1 | ウィンドウフォーカス制御 | ginfo2()=0（アクティブウィンドウ）の場合のみ入力受付 | processKeyInput |
| BR-58-2 | FXコンボキー | key.10/key2.10が押下時、FX-L(keystat.*.4)とFX-R(keystat.*.5)を同時ON | longmode=2でも発動 |
| BR-58-3 | analogsw入替 | analogsw=1の場合、レーザーL(key.6,7)とR(key.8,9)を入替 | processKeyInput |
| BR-58-4 | 一時停止条件 | Ctrl+EnterまたはMediaStop(VK179)、t>1500ms経過後のみ | processPlaybackControlInput |
| BR-58-5 | HiSpeed変更条件 | FXボタン長押し(enter_key=1)+上下キー、ts2>60ms間隔制限 | processHiSpeedChangeInput |
| BR-58-6 | タイミング調整 | Ctrl+Alt+左右で+/-5ms、Ctrl+Alt+Shift+左右で+/-1ms、ts>120ms間隔 | processSyncValueManualChangeInput |
| BR-58-7 | 3BT+Start終了 | BT3個以上+Startキー同時押しでEscと同等の終了処理 | getesckey |

### 計算ロジック

特になし（入力のマッピング処理）。

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ウィンドウ非アクティブ | ginfo2()!=0 | 入力をすべて無視 |

### リトライ仕様

不要。毎フレーム入力をポーリング。

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

不要。

## パフォーマンス要件

- 毎フレーム（約7ms間隔）でポーリング
- 入力遅延最小化のため、HSPのgetkey命令で直接Win32 API呼び出し

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

特になし。

## 備考

- key配列のインデックス: 0-3=BT(A/B/C/D), 4-5=FX(L/R), 6-9=レーザー(LL/LR/RL/RR), 10=FXコンボ, 11=Start, 12=Back
- getkey_a関数はテンキー対応の拡張getkey（usenumpad設定による）
- getjoykeystatはキーボードとジョイスティックの入力を統合する関数

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshootmania.hsp | `kshootmania.hsp` | key/key2配列の定義とconfig.iniからの読み込み |

**読解のコツ**: key配列は14要素で、HSPのキーコード（Win32仮想キーコード）を格納している。config.iniの"key="行から読み込まれる。

#### Step 2: エントリーポイント

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processKeyInput関数 |

**主要処理フロー**:
- **242行目**: `processKeyInput`関数定義開始
- **243行目**: `gosub *getjoystat` - ジョイスティック状態取得
- **244行目**: `dim keystat,7,11` - 7入力ソースx11キーで配列初期化
- **245-271行目**: キーバインドセット1/2とジョイスティックからのキー状態読み取り
- **272-281行目**: analogsw=1時のレーザーL/R入替処理
- **282-285行目**: keystator配列（全入力のOR結合）生成

#### Step 3: 各入力処理関数

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processPlaybackControlInput |
| 3-2 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processHiSpeedChangeInput |
| 3-3 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processSyncValueManualChangeInput |
| 3-4 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processEscKeyInput |

**主要処理フロー**:
- **1-89行目**: processPlaybackControlInput - 一時停止/再開（Ctrl+Enter/MediaStop）
- **91-109行目**: processSyncValueManualChangeInput - タイミング手動調整
- **111-240行目**: processEscKeyInput - Esc終了と同期値保存ダイアログ
- **288-442行目**: processHiSpeedChangeInput - HiSpeed変更

#### Step 4: 統合関数

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | kshootmania.hsp | `kshootmania.hsp` | getjoykeystat / getkey_a / getesckey関数 |

- **2219-2247行目**: getjoykeystat - キーボード+ジョイスティック統合
- **2249-2263行目**: getkey_a - テンキー対応getkey拡張
- **2266-2283行目**: getesckey - Esc+3BT同時押し検出

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

```
play_update (メインループ)
    |
    +-- processKeyInput
    |       +-- *getjoystat (ジョイスティック状態取得)
    |       +-- getkey (Win32キーボードAPI) x 各キー
    |       +-- keystat/keystator 生成
    |
    +-- processPlaybackControlInput
    |       +-- Ctrl+Enter/MediaStop -> 一時停止/再開
    |
    +-- processHiSpeedChangeInput
    |       +-- FX長押し+上下 -> HiSpeed増減
    |       +-- FX長押し+左右 -> HiSpeedタイプ切替
    |
    +-- processSyncValueManualChangeInput
    |       +-- Ctrl+Alt+左右 -> sync値調整
    |
    +-- processEscKeyInput
            +-- Esc/3BT+Start -> プレイ終了
```

### データフロー図

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

キーボード物理キー ------> getkey (Win32 API) -----------> keystat[0-1][0-10]
                              |
ジョイスティック --------> *getjoystat ------------------> keystat[2-5][0-10]
                              |
config.ini (key/key2) ---> キーコードマッピング ----------> key/key2配列
                              |
keystat全ソース ---------> OR結合 -----------------------> keystator[0-10]
                              |
                              +-- ノート判定 ------------> スコア計算
                              +-- 一時停止制御 ----------> 音楽停止/再開
                              +-- HiSpeed変更 -----------> hs変数更新
                              +-- タイミング調整 --------> sync変数更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_key_input.hsp | `src/scene/play/play_key_input.hsp` | ソース | プレイ画面のキー入力処理5関数 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | getjoykeystat/getkey_a/getesckey関数、key/key2配列定義 |
| config.ini | `config.ini` | 設定 | キーバインド設定 |
