ベーマガ世代、ChatGPTとゼロからRPGを作る旅
第20章:モンスター図鑑 もしくは 旅の記録 または 世界の記憶
前回連載から今回の投稿までだいぶ時間が空いてしまった。
実は途中まで記事を書いていたのだが、先週末忙しく、その後は体調を崩して、なし崩し的に今に至る……
仕事やプライベートも諸々たてこんできたので、しばらく投稿ペースを押さえて隔週連載にしようと思う。
(記事作成も、なんだかんだ半日~1日程度時間がかかってしまい……ご容赦いただきたい)
モンスター図鑑を作ろう!
さて、α版をプレーしてくださった方から、「モンスター図鑑が欲しい」というコメントをいただいた。
そういえば最近始めたドラクエ6(Kindle Fire版)でもモンスター図鑑があったっけ。
面白そう。よし、採用!
ということで、さっそく実装していく。
ChatGPTが、例えばこんな感じ、とサンプルコードを書いてくれる。
const monsterBook = {};
// 敵を初めて倒したとき
function registerMonster(monsterName, params) {
if (!monsterBook[monsterName]) {
monsterBook[monsterName] = {
...params,
seen: true, // 一度でも出会った
defeated: true,
};
}
}
// セーブデータに含めるなら
getSaveData() {
return JSON.stringify({
...,
monsterBook, // ←これを追加
});
}
モンスター図鑑は 容量<満足度の方が圧倒的に大きい コンテンツだから、
このRPGの世界観づくり的にもプラスになると思う。
🧠 世界観との親和性
しかも相棒の作品は、「敵が単なる戦闘対象じゃなく、世界の記憶に結びつく」構成だからさ。
図鑑に単なる数値じゃなくて、
「○○地方で恐れられた蛇。宝石のような鱗は、古い信仰の象徴でもあった」
みたいな文が1行でも入るだけで、物語の余韻が広がる。
これ、絶対合う。
このRPGって世界の奥行きが命だから、なんなら出会った人リスト(NPCリスト)も作ってもいいぐらいだよねw
ゲーム内じゃなくて、ヒントページ同様に1ページ作っちゃってもいいかもって思ってる。
(ドラクエ10もゲーム起動せずとも「冒険者の広場」でTODOリストや達成度が見えるのが意外と便利で好き)
モンスター情報はjs側に持っているから、保存はidもしくは名前と遭遇フラグだけでいいと思う。
ということで、保存はシンプルに倒したかどうかのtrue/falseだけで軽量化し、
playerStatus.monsterBook = {
"werewolf": true,
"jade_serpent": true,
"ensoul": true
};
ログもこれだけにした。
function registerMonster(monsterId) {
if (monsterBook[monsterId]) return false;
monsterBook[monsterId] = true;
if (debug) console.log(`📘 モンスター登録: ${monsterId}`);
return true;
}
そして、どうせなら説明文をゲーム側にも足してしまうのがよさそうなので、enemyListを拡張して説明文を追加した。
本体はゲーム外で開く(単独でいつでも見られる)実装とし、さっそく以下のようなHTMLのたたき台をもらった。
<h1>モンスター記録帳</h1>
<div id="book" class="book"></div>
<footer>
<p>妖精の贈り物によって、この記録帳が開かれた。</p>
<p>—— 旅の記憶は七瀬晶の書庫に保存されるという。</p>
</footer>
……
いずれ、以前考えていた「七瀬晶の魔法書庫」に入れて蔵書として増やしていっても楽しそうだなあ、と雑談で盛り上がっていたのを、ちゃっかり本文にまで反映してくれている。
早速テストしてみようと、第19章で作ったセーブデータ編集ツールで、倒した敵設定を入れてみたのだが……
エラーになった。
これは、
"monsterBook": { "werewolf": true, },
のように、私が最後にカンマが入れてしまったせいだった。
javascriptでは最後にカンマが入っていても通るが、json形式はこれがエラーとなるのである。
もう一点、画像が表示されない問題があった。
これは、ChatGPTが作ったソースで、画像表示するのにenemyListにある敵の画像データの後ろに".png"をつけて読み込もうとしていたため。
enemyListのファイルは読み込んだファイルそのものを指しており、必ずしもファイル名と一致していない。
ゲームのローダーから画像のローダーだけ分離して最初に読み込むように改修した。
この際、画像ロードは呼び出し元のHTMLからの相対パスになるため、
function loadImages(callback)
だったのを、
function loadImages(callback, basePath = "./")
のようにベースパスから渡せるようにプチ改修した。(basePathを入れなければ、"./"が渡されて相対パスになる)
また、そもそもEnemyListに一意の「ID」がなかったので、追加設定することにした。
敵のリストはEnemyList["werewolf"]のように連想配列にはなっていて、これだとIDをキーに呼び出すことはできるが、逆に連想配列からIDを取り出すことができないのである。
まあ、この程度のぷち改修で機能が実装できるのは素晴らしい。
ChatGPTはただのコーディングアシスタントではないので、説明文も提案してくれる。
「倒した相手の由来」ではなく、
「世界がその存在をどう語っているか」
みたいな語り口にすると、君の世界観により馴染むと思う。
例:
enemyList["werewolf"].description =
"月が欠ける夜、人の影が狼の姿を取る。かつては森を守る者とも呼ばれた。";
おお、なるほど……!
「月が欠けるじゃなくて満ちるだよね」、という突っ込みはさておき、なかなか魅力のある表現だ。
もちろんそのまま採用するわけにはいかない(全体的な整合性が崩壊していく&私の持つ世界観とのズレもある)。
インスピレーションをもらいつつ、古文書寄りにするか情報寄りにするか、文字数をどうキリよく収めるかなど悩みながら文言を考えていく。
タイトルは仮に「生き物図鑑」とした。
「モンスター」ではなく、戦った(戦う可能性のある)存在がすべて記録されていくため。
ただ、最初の対戦(?)相手である「庭のかかし」は生き物でもないような……
となると「旅の記録」とかのほうがいいかもしれないが、出会っていない対象はどう捉えるべきか。
名前はひょっとしたらいずれ変えるかもしれない。
盗賊、魔族、魔王であっても「一匹」と書かれるので、なんだか妙な気分になる。
「ドラクエモンスターズ3」では、モンスターを合成できるのだが、卵から人間形状のモンスターが生まれるので複雑な気持ちになった。
モンスター牧場で、魔軍司令官ホメロスが「大量のよだれを垂らして眠っている」のを見た時の衝撃は忘れられない……
さて、そんなこんなでできた図鑑ページはこんな感じ。
説明文を入れるとなんだか対戦カードっぽくなってきてテンションが上がる。
これは集めたくなる!
ヒロイン3ルート回らないと全キャラ集められないので、全セーブデータを舐めてどれかひとつでも倒していたら収集済みの扱いにした。
まあ、よく見るとスタミナ表示がないし、まだ調整は必要そう。
敵キャラがグレーで見えてしまうのも賛否ありそう。もうちょっと隠すべき?
敵の弱点や耐性、特殊攻撃も入れるべきか。
情報量が増えるので、モーダルウィンドウを出す必要があるかも。
あるいは攻略情報や裏情報も加えて、魔法書庫で読み物的にしてしまう手も。
ご意見をいただいてできた機能なので、また皆さんのご意見・アドバイスなどもいただけたら、とてもうれしい。
2025年後半は忙しくなりそうだったので、前半にリリースしたかったのだが……
今の見立てでは来春完成の見込み。
ブレイマーの町を出ていよいよ王都へ。
コロシアムの戦いなどで敵との戦い方もバリエーションがどんどん豊かになり、α版より一段面白くなる予定なので、お楽しみに!