リクエスト詳細
✨ 既存アプリの改善
対応完了
対象アプリ: RPGストーリーフォージ AI風ドット絵冒険
DQ3風「冒険の書」セーブ&ロード画面の追加(スロット3枠・ファイル選択UI)
## 1. 目的
現在のセーブはセッション単位(session_key)で自動保存されるのみで、ブラウザを閉じたり別端末でアクセスすると続きが消える。DQ3の「冒険の書」のように、プレイヤーが任意のタイミングで名前付きスロット(最大3枠)に手動セーブし、後から選んでロードできる仕組みを追加する。これにより長期プレイ・複数キャラクター管理が可能になり、ゲームとしての完成度が大幅に向上する。
## 2. 具体的な仕様
### 2-1. DBスキーマ変更(既存テーブルに列追加)
```sql
ALTER TABLE rpgsf_save_states
ADD COLUMN slot_no TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0=自動,1-3=手動スロット',
ADD COLUMN save_label VARCHAR(60) NOT NULL DEFAULT '' COMMENT '表示名(例: 勇者 Lv5 月影の砦)',
ADD KEY idx_slot (scenario_id, session_key, slot_no);
```
slot_no=0 は既存の自動保存スロット(後方互換維持)。slot_no=1〜3 が手動セーブスロット。
### 2-2. lib.php に追加する関数
- `rpgsf_save_slots(int $scenario_id, string $session_key): array` — 指定シナリオのスロット1〜3を取得。存在しないスロットは空データとして返す。
- `rpgsf_write_slot(int $scenario_id, string $session_key, int $slot_no, array $state, string $hero_name): bool` — 指定スロットにINSERT or UPDATE。save_label は「{hero_name} Lv{level} {map_name} {datetime}」形式で自動生成。
- `rpgsf_load_slot(int $scenario_id, string $session_key, int $slot_no): ?array` — 指定スロットのstate_jsonをデコードして返す。
### 2-3. play.php のUI変更
#### セーブボタン
- ゲーム画面のアクションボタン群(移動・戦闘以外のエリア)に「📖 冒険の書に記録」ボタンを追加。
- クリックするとページ内モーダル(DQ3風ウィンドウデザイン)を表示。3スロットをカード形式で並べる。
- 各スロットカードには「スロット番号」「save_label(空なら『-空白-』)」「最終更新日時」を表示。
- スロットを選択して「ここに記録する」ボタンを押すとPOSTで保存(action=save_slot&slot=N)。
#### ロード(冒険の書を開く)
- play.php の上部「再開ボタン」付近、またはシナリオ選択直後のparty.phpに「冒険の書を開く」ボタンを追加。
- モーダルで3スロットを表示し、スロットを選択して「ここから再開」を押すとPOSTでロード(action=load_slot&slot=N)。
- ロード後は自動保存スロット(slot_no=0)に複製してセッションを継続。
### 2-4. POSTアクション処理(play.php内 rpgsf_apply_action 相当の分岐)
```php
if ($action === 'save_slot') {
$slot = max(1, min(3, (int)($_POST['slot'] ?? 1)));
rpgsf_write_slot($scenario_row['id'], $session_key, $slot, $state, $state['hero']['name'] ?? '勇者');
flash('冒険の書 ' . $slot . ' に記録しました。');
}
if ($action === 'load_slot') {
$slot = max(1, min(3, (int)($_POST['slot'] ?? 1)));
$loaded = rpgsf_load_slot($scenario_row['id'], $session_key, $slot);
if ($loaded) {
$state = $loaded;
rpgsf_save_state($scenario_row, $state); // slot_no=0 に反映
flash('冒険の書 ' . $slot . ' から再開しました。');
}
}
```
### 2-5. デザイン仕様(DQ3風)
- モーダルは既存の `.narrator-modal` / `.narrator-window` スタイルを流用。
- スロットカードは縦並び3枚。背景 `#201a24`、ボーダー `#d0b071`。
- 空スロットは薄いグレーで「- 空白 -」と表示。
- 選択中スロットにはゴールドのアウトライン。
- スマホでもタップしやすいよう最小タップ領域44px確保。
## 3. 既存機能との整合
- slot_no=0 の自動保存ロジック(rpgsf_save_state / rpgsf_load_or_create_save)は一切変更しない。既存セーブデータは slot_no=0 として引き続き動作する。
- ALTER TABLE の ADD COLUMN はデフォルト値付きのため、既存レコードに影響なし。
- 共有URLでのプレイ(他人のセッション)では自分のsession_keyでスロットが独立するため、他プレイヤーのセーブと衝突しない。
- パーティ編成(party.php)のフローは変更しない。ロードはparty.php選択後のplay.phpでのみ行える。
現在のセーブはセッション単位(session_key)で自動保存されるのみで、ブラウザを閉じたり別端末でアクセスすると続きが消える。DQ3の「冒険の書」のように、プレイヤーが任意のタイミングで名前付きスロット(最大3枠)に手動セーブし、後から選んでロードできる仕組みを追加する。これにより長期プレイ・複数キャラクター管理が可能になり、ゲームとしての完成度が大幅に向上する。
## 2. 具体的な仕様
### 2-1. DBスキーマ変更(既存テーブルに列追加)
```sql
ALTER TABLE rpgsf_save_states
ADD COLUMN slot_no TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0=自動,1-3=手動スロット',
ADD COLUMN save_label VARCHAR(60) NOT NULL DEFAULT '' COMMENT '表示名(例: 勇者 Lv5 月影の砦)',
ADD KEY idx_slot (scenario_id, session_key, slot_no);
```
slot_no=0 は既存の自動保存スロット(後方互換維持)。slot_no=1〜3 が手動セーブスロット。
### 2-2. lib.php に追加する関数
- `rpgsf_save_slots(int $scenario_id, string $session_key): array` — 指定シナリオのスロット1〜3を取得。存在しないスロットは空データとして返す。
- `rpgsf_write_slot(int $scenario_id, string $session_key, int $slot_no, array $state, string $hero_name): bool` — 指定スロットにINSERT or UPDATE。save_label は「{hero_name} Lv{level} {map_name} {datetime}」形式で自動生成。
- `rpgsf_load_slot(int $scenario_id, string $session_key, int $slot_no): ?array` — 指定スロットのstate_jsonをデコードして返す。
### 2-3. play.php のUI変更
#### セーブボタン
- ゲーム画面のアクションボタン群(移動・戦闘以外のエリア)に「📖 冒険の書に記録」ボタンを追加。
- クリックするとページ内モーダル(DQ3風ウィンドウデザイン)を表示。3スロットをカード形式で並べる。
- 各スロットカードには「スロット番号」「save_label(空なら『-空白-』)」「最終更新日時」を表示。
- スロットを選択して「ここに記録する」ボタンを押すとPOSTで保存(action=save_slot&slot=N)。
#### ロード(冒険の書を開く)
- play.php の上部「再開ボタン」付近、またはシナリオ選択直後のparty.phpに「冒険の書を開く」ボタンを追加。
- モーダルで3スロットを表示し、スロットを選択して「ここから再開」を押すとPOSTでロード(action=load_slot&slot=N)。
- ロード後は自動保存スロット(slot_no=0)に複製してセッションを継続。
### 2-4. POSTアクション処理(play.php内 rpgsf_apply_action 相当の分岐)
```php
if ($action === 'save_slot') {
$slot = max(1, min(3, (int)($_POST['slot'] ?? 1)));
rpgsf_write_slot($scenario_row['id'], $session_key, $slot, $state, $state['hero']['name'] ?? '勇者');
flash('冒険の書 ' . $slot . ' に記録しました。');
}
if ($action === 'load_slot') {
$slot = max(1, min(3, (int)($_POST['slot'] ?? 1)));
$loaded = rpgsf_load_slot($scenario_row['id'], $session_key, $slot);
if ($loaded) {
$state = $loaded;
rpgsf_save_state($scenario_row, $state); // slot_no=0 に反映
flash('冒険の書 ' . $slot . ' から再開しました。');
}
}
```
### 2-5. デザイン仕様(DQ3風)
- モーダルは既存の `.narrator-modal` / `.narrator-window` スタイルを流用。
- スロットカードは縦並び3枚。背景 `#201a24`、ボーダー `#d0b071`。
- 空スロットは薄いグレーで「- 空白 -」と表示。
- 選択中スロットにはゴールドのアウトライン。
- スマホでもタップしやすいよう最小タップ領域44px確保。
## 3. 既存機能との整合
- slot_no=0 の自動保存ロジック(rpgsf_save_state / rpgsf_load_or_create_save)は一切変更しない。既存セーブデータは slot_no=0 として引き続き動作する。
- ALTER TABLE の ADD COLUMN はデフォルト値付きのため、既存レコードに影響なし。
- 共有URLでのプレイ(他人のセッション)では自分のsession_keyでスロットが独立するため、他プレイヤーのセーブと衝突しない。
- パーティ編成(party.php)のフローは変更しない。ロードはparty.php選択後のplay.phpでのみ行える。
💬 返信 (3)
🛠 開発を開始しました (機能追加 (rpg-story-forge))
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「RPGストーリーフォージ AI風ドット絵冒険」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rpg-story-forge
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rpg-story-forge/
ご利用ありがとうございます!
ご要望いただいた「RPGストーリーフォージ AI風ドット絵冒険」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rpg-story-forge
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rpg-story-forge/
ご利用ありがとうございます!
Echo
Iris