# 機能設計書 73-タイマー

## 概要

本ドキュメントは、Godotエンジンにおけるタイマー機能の設計を記述する。時間経過後にイベントを発火させるシンプルで汎用的なタイマーノードを提供する。

### 本機能の処理概要

タイマー機能は、指定時間経過後にシグナル（timeout）を発火させる基本的なタイミング機構を提供する。ワンショット/リピート、一時停止、タイムスケール無視など柔軟な動作モードをサポートする。

**業務上の目的・背景**：ゲーム開発において、敵のリスポーン間隔、スキルのクールダウン、アニメーションの遅延開始など、時間に基づくイベント制御が頻繁に必要となる。タイマー機能は、こうした時間制御をコードの複雑さなく実現する標準的な仕組みを提供する。

**機能の利用シーン**：
- 敵キャラクターのリスポーン間隔制御
- プレイヤースキルのクールダウン管理
- 画面遷移時のフェード効果タイミング
- ゲーム内イベントのスケジュール実行
- UIアニメーションの遅延表示

**主要な処理内容**：
1. wait_time設定による待機時間の指定
2. start()によるタイマー開始
3. process/physics_processでの時間カウントダウン
4. time_leftが0以下になったらtimeoutシグナル発火
5. ワンショット時は自動停止、リピート時は再スタート
6. pause/resume機能による一時停止制御

**関連システム・外部連携**：シーンツリー、Engine（タイムスケール）、シグナル機構

**権限による制御**：特になし（すべてのスクリプトから利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当画面なし | - | タイマーは特定画面に限定されない汎用ノード |

## 機能種別

ユーティリティ / ノード

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| wait_time | double | Yes | 待機時間（秒） | 0より大きい値 |
| one_shot | bool | No | ワンショットモード（デフォルト: false） | - |
| autostart | bool | No | 自動開始（デフォルト: false） | - |
| process_callback | TimerProcessCallback | No | 処理タイミング（Physics/Idle） | enum値チェック |
| ignore_time_scale | bool | No | タイムスケール無視（デフォルト: false） | - |

### 入力データソース

- ノードプロパティ設定
- start()メソッド引数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| time_left | double | 残り時間 |
| is_stopped | bool | 停止状態 |
| is_paused | bool | 一時停止状態 |

### 出力先

- timeoutシグナル（時間経過時）
- プロパティ値の返却

## 処理フロー

### 処理シーケンス

```
1. ノードがシーンツリーに追加
   └─ NOTIFICATION_READYで自動開始チェック
2. start()呼び出し
   └─ time_leftにwait_timeをセット
   └─ 内部処理を有効化
3. フレームごとの更新
   └─ INTERNAL_PROCESS/INTERNAL_PHYSICS_PROCESSで時間減算
4. 時間経過チェック
   └─ time_left < 0 でtimeoutシグナル発火
5. リピート/停止判定
   └─ one_shotならstop()、そうでなければ再スタート
```

### フローチャート

```mermaid
flowchart TD
    A[start] --> B[time_left = wait_time]
    B --> C[処理有効化]
    C --> D{フレーム更新}
    D --> E{ignore_time_scale?}
    E -->|Yes| F[time_left -= process_step]
    E -->|No| G[time_left -= delta_time]
    F --> H{time_left < 0?}
    G --> H
    H -->|No| D
    H -->|Yes| I[timeout発火]
    I --> J{one_shot?}
    J -->|Yes| K[stop]
    J -->|No| L[time_left += wait_time]
    L --> D
    K --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-73-01 | 待機時間検証 | wait_timeは0より大きい値のみ許可 | set_wait_time呼び出し時 |
| BR-73-02 | シーンツリー必須 | start()はシーンツリー内でのみ実行可能 | start()呼び出し時 |
| BR-73-03 | ワンショット動作 | one_shot=trueなら1回のみ発火して停止 | timeout発火時 |
| BR-73-04 | リピート動作 | one_shot=falseなら繰り返し発火 | timeout発火時 |
| BR-73-05 | 低待機時間警告 | 0.05秒未満の待機時間は警告を表示 | エディタ表示時 |

### 計算ロジック

- **残り時間減算（通常）**: `time_left -= get_process_delta_time()`
- **残り時間減算（タイムスケール無視）**: `time_left -= Engine::get_singleton()->get_process_step()`
- **リピート時の再設定**: `time_left += wait_time`

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

本機能はデータベース操作を行わない（インメモリ処理）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_FAIL_COND_MSG | パラメータエラー | wait_time <= 0 | 0より大きい値を指定 |
| ERR_FAIL_COND_MSG | 状態エラー | シーンツリー外でstart() | シーンツリーに追加後にstart()を呼ぶ |

### リトライ仕様

タイマー処理にリトライ機構はない。

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

該当なし（インメモリ処理）

## パフォーマンス要件

- 軽量なノードとして設計されているため、多数のタイマーを使用可能
- ただし大量のタイマーよりはスクリプト内でのカウンター管理を推奨
- 0.05秒未満の待機時間は非推奨（フレームレート依存の挙動となる）

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

特になし

## 備考

- Physics ProcessモードはPhysics処理と同期して更新
- Idle ProcessモードはFrame処理と同期して更新
- ignore_time_scale=trueでEngine.time_scaleの影響を受けない
- エディタ内では自動開始しない（is_part_of_edited_scene()でチェック）

---

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

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

### 推奨読解順序

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

Timerクラスのプロパティと状態を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | timer.h | `scene/main/timer.h` | Timerクラス定義、プロパティ |
| 1-2 | timer.cpp | `scene/main/timer.cpp` | メソッド実装 |

**読解のコツ**: Timerはシンプルなノードで、主要な状態はtime_left, processing, pausedの3つ。

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

タイマーの開始・停止処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | timer.cpp | `scene/main/timer.cpp` | start(), stop()の実装 |

**主要処理フロー**:
1. **118-126行目**: start()でタイマー開始
2. **128-132行目**: stop()でタイマー停止
3. **134-145行目**: set_paused()で一時停止制御

#### Step 3: 通知処理を理解する

フレームごとのタイムカウントダウン処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | timer.cpp | `scene/main/timer.cpp` | _notification()の実装 |

**主要処理フロー**:
1. **35-47行目**: NOTIFICATION_READYで自動開始処理
2. **49-68行目**: NOTIFICATION_INTERNAL_PROCESSでアイドル処理
3. **70-88行目**: NOTIFICATION_INTERNAL_PHYSICS_PROCESSで物理処理

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

```
Timer::start()
    │
    └─ Timer::_set_process(true)
           │
           ├─ set_process_internal() [IDLE mode]
           │
           └─ set_physics_process_internal() [PHYSICS mode]

Timer::_notification(NOTIFICATION_INTERNAL_PROCESS)
    │
    ├─ time_left -= delta_time
    │
    └─ if (time_left < 0)
           │
           ├─ emit_signal("timeout")
           │
           └─ one_shot ? stop() : time_left += wait_time
```

### データフロー図

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

wait_time ─────────▶ time_left初期化
     │                    │
delta_time ─────────▶ 時間減算 ────────────▶ time_left
     │                    │
time_left < 0 ──────▶ timeout判定 ─────────▶ timeoutシグナル
     │                    │
one_shot ───────────▶ 継続/停止判定 ────────▶ 処理状態
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| timer.cpp | `scene/main/timer.cpp` | ソース | Timer実装 |
| timer.h | `scene/main/timer.h` | ヘッダー | Timer定義 |
| engine.h | `core/config/engine.h` | ヘッダー | タイムスケール参照 |
| node.cpp | `scene/main/node.cpp` | ソース | 親クラスNode |
