「図鑑」を作り込む:発見・未発見・ヒントの三状態
遊びをつくる執筆にClaudeを使用しています。

生きものや道具を集めるゲームで、図鑑画面を開く場面を考えてみます。並んでいるのは、見つけたものの名前と絵だけです。見つけていないものは、そもそも載っていません。これでも図鑑として動きますが、「あと何があるのか」「どうすれば出会えるのか」が見えないので、プレイヤーは集める手がかりを失います。 逆に、未発見の欄がすべて黒いシルエットで、「?」だけが並ぶ図鑑も考えてみます。総数は分かりますが、次に何をすればよいかは分かりません。探索の導線が弱くなり、行き詰まった人は手探りで同じ行動を繰り返すことになります。 この記事で確かめるのは、「発見」「未発見」「ヒント」の三状態を持たせると、図鑑が記録帳から次の行動を示す道具に変わるのか、という問いです。方法は、状態の決め方、保存するデータ、ヒントの出し方に分けて組み立てます。最後にHTML1ファイルの最小コードを使い、自分のゲームに移すときの確認項目まで進みます。
この記事の目次
三状態に何を担当させるか
まず、三つの状態がプレイヤーに何を伝えるのかを整理します。
- 未発見、プレイヤーに見せるもの:枠、「?」、番号など、伝えたいこと:まだ何かがある
- ヒント、プレイヤーに見せるもの:枠に加えて、出会い方の手がかり、伝えたいこと:どの方向に動けばよいか
- 発見、プレイヤーに見せるもの:名前、絵、説明文、伝えたいこと:確かに手に入れた
ポイントは、ヒントを「未発見の延長」として独立の状態にすることです。未発見の欄に毎回ヒントを出すと、探す楽しみが薄れます。反対に、ヒントがまったくないと、手詰まりの人を助けられません。「条件を満たしたときだけ未発見がヒントに変わる」という中間の段階が、探索の緩急を作ります。
公式作品の「潮だまり」は、この設計を考える材料になります。確認済みの範囲では、引き潮の浅瀬に海藻を3つ、砂地に小石を2つ置き、潮を切り替えて観察します。上下左右の隣接条件によって、イソギンチャクからタツノオトシゴまで8種の生きものが現れます。絵付きの図鑑と観察ノートも備えています。
ここから読み取れるのは、発見の条件が「盤面の配置」という、プレイヤーの手で作れるものに置かれていることです。こうした作りでは、図鑑が「何を置けば何が現れるか」を考える手がかりの置き場にもなります。図鑑が未発見やヒントをどう見せているか、観察ノートとどう役割を分けているかは、作品を開いて確かめてください。
手順1:エントリーのデータを決める
最初に、一つの項目に持たせる情報を決めます。必要最小限は次の四つです。
- id:保存と照合に使う固定の文字列です。表示名を変えても変わらないものにします。
- name:発見後に表示する名前です。
- hint:ヒント状態で見せる手がかりの一文です。
- need:ヒントを解放するのに必要な発見数です。
ここでの判断は、「ヒントの解放条件を、保存データとは別に導けるようにしておく」ことです。「発見済みの数がneed以上ならヒント」という形にすれば、保存するのは「どれを発見したか」だけで足ります。ヒントの解放済みフラグを別に保存すると、フラグと発見状況がずれるバグの原因になります。
手順2:状態は保存せず、毎回導く
次に、三状態を決める関数を一つだけ作ります。
- 発見済みの一覧にそのIDがあれば「発見」にします。
- なければ、発見済みの総数を数えます。
- 総数がneed以上なら「ヒント」、そうでなければ「未発見」にします。
保存するものと導くものを分けると、後から条件を変えやすくなります。たとえば「発見数」ではなく「特定の別エントリを発見したら」という条件に差し替えたくなったとき、保存データの形を変えずに済みます。
以下が、この二つの手順をまとめた最小構成です。ファイル1つで動き、外部通信もありません。
<!doctype html>
<meta charset="utf-8">
<title>ミニ図鑑</title>
<ul id="list"></ul>
<p id="count"></p>
<button id="find">ランダムに1つ見つける</button>
<script>
const ENTRIES = [
{id:"moss", name:"ほたる苔", hint:"暗い場所で淡く光る", need:1},
{id:"drop", name:"しずく石", hint:"雨のあとに現れる", need:1},
{id:"fox", name:"霧狐", hint:"霧の朝に尾が見える", need:2},
{id:"moon", name:"月見草", hint:"夜だけ咲く", need:3}
];
let save = {version:1, found:{}};
try { save = JSON.parse(localStorage.getItem("zukan")) || save; } catch(e) {}
function count(){ return Object.keys(save.found).length; }
function stateOf(e){
if (save.found[e.id]) return "found";
return count() >= e.need ? "hint" : "unknown";
}
function render(){
const li = ENTRIES.map(e => {
const s = stateOf(e);
const text = s === "found" ? e.name
: s === "hint" ? "?(手がかり:" + e.hint + ")"
: "?";
return "<li data-state='" + s + "'>" + text + "</li>";
});
document.getElementById("list").innerHTML = li.join("");
document.getElementById("count").textContent = count() + " / " + ENTRIES.length;
}
document.getElementById("find").onclick = () => {
const rest = ENTRIES.filter(e => !save.found[e.id]);
if (!rest.length) return;
save.found[rest[Math.floor(Math.random() * rest.length)].id] = true;
try { localStorage.setItem("zukan", JSON.stringify(save)); } catch(e) {}
render();
};
render();
</script>保存データにversionを入れているのは、将来形式を変えるときに古い保存を新しい形へ移すためです。公式作品でも、古い保存(version1)を新しい形式(version2)へ移行する仕組みが確認されています。
このコードの「ランダムに見つける」ボタンは、動作確認用の仮の発見手段です。実際のゲームでは、ここを「条件を満たしたらsave.found[id] = trueにする」処理に置き換えます。
手順3:ヒントの文面と解放条件を設計する
状態の仕組みができたら、ヒントの中身を作ります。ここが図鑑の手触りを決めます。ヒントの文面は、次の三つを基準に書きます。
- 行動に結びつけます。 「珍しい生きもの」では何をすればよいか分かりません。「雨のあとに」「暗い場所で」のように、プレイヤーが操作や時間で再現できる条件を含めます。
- 答えを言い切りません。 手がかりは条件の一部だけを示し、残りは試行で埋めさせます。全部書くと未発見との差がなくなります。
- 一文にします。 図鑑の一覧で読める長さにします。長い説明は発見後の説明文に回します。
解放条件は、最初は「発見数」で十分です。慣れてきたら、次のような条件に広げられます。
- 別のエントリーを発見したら:関連する二つを順に導く遊びに向きます。
- 同じ場所に一定回数訪れたら:行き詰まった人を救う条件になります。
- 一定時間、発見がなかったら:詰まりを検知して助け舟を出せます。
どれを選ぶかは、「ヒントを探索の報酬にしたいのか、救済にしたいのか」で決めます。報酬なら1、救済なら2か3が向きます。ただし2と3は、回数や時間を保存する必要が出てきます。保存項目が増えるぶん、手順2の「導く」原則から外れます。保存する値を増やすときは、versionを上げて古い保存を読めるようにしておきます。
手順4:総数を見せるかどうかを決める
「3 / 8」のような完成率を表示するかは、設計上の分かれ目です。
- 総数を見せる場合:ゴールが明確になり、コンプリート志向の人が動きやすくなります。反面、「あと何個」が見えるため、発見が作業的になりやすくなります。
- 総数を隠す場合:未知の余地が残ります。反面、どこまで探せばよいか分からず、途中で離れる人が出る可能性があります。
中間案として、「今の章の総数だけ見せる」方法があります。ゲームの規模と、プレイヤーに期待する遊び方で選んでください。判断に迷うときは、まず総数を見せる形で作り、遊んだ人が「物足りない」と言うか「作業的」と言うかを見て調整するのが現実的です。
手順5:自分で行える確認項目
三状態は、組み込んだ後に崩れやすい部分です。次の手順で、自分のゲームを確認してください。
- 初回起動の確認:保存データを消した状態で開き、全項目が「未発見」になっていることを確かめます。ヒントが最初から出ていないかも見ます。
- 一つ発見した直後の確認:needが1の項目が「ヒント」に変わり、それ以外は変わらないことを確かめます。
- 全発見の確認:すべて発見した状態で、ヒント表示が残っていないことを確かめます。
- 再読み込みの確認:途中まで進めて再読み込みし、状態が同じに戻ることを確かめます。
- 順序違いの確認:発見の順番を変えて数回繰り返し、どの順でも矛盾したヒントが出ないことを確かめます。ヒントが「Aを見つけた人向け」の文面なのに、Aを見つける前に出ていないかが要点です。
記録のとり方は簡単で足ります。確認ごとに「操作」「期待した状態」「実際の状態」の三列をメモし、ずれた箇所だけ直します。
起こりやすい誤りは、次のとおりです。
- 表示名をIDに使う:名前を直した途端、保存済みの発見が消えたように見えます。IDは固定にします。
- ヒントの解放済みを別に保存する:発見状況とずれて、見つけたのにヒントが残る不具合の元になります。
- 全項目を同じneedにする:ヒントが一斉に出て、段階の意味がなくなります。
- 保存失敗を想定しない:コードのtryは、保存が使えない環境で落ちないための備えです。
保存先に関する注意
投稿作品として公開する場合は、保存先の扱いに注意してください。アソバースでは、アップロードした作品内のlocalStorage/sessionStorageは一時メモリーの互換処理として扱われます。そのため、図鑑の進行を長く残したいなら、永続する前提で作らないでください。
ログインしたプレイヤーには、作品ごとにJSONで128KiBまでのクラウドセーブが使える仕組みがあります。アップロードしたゲームにはSDKが自動で追加され、URL投稿の場合は作者がSDKを読み込むと使えます。呼び出し方の詳細はここでは書きません。投稿画面の案内で確認してください。
ここで手順2の考え方が効いてきます。保存するのが「発見済みIDの一覧」とversionだけなら、図鑑の保存データは小さく収まり、上限に近づく心配もほとんどありません。
次の行動
まず自分のゲームの収集物を5〜8個に絞り、id、name、hint、needの四つを表にしてみてください。次に、上のコードのENTRIESをその表に置き換え、ボタンの代わりに実際の発見処理をつなぎます。最後に、手順5の確認項目を一つずつ実行し、ずれた箇所を直してください。「潮だまり」を開き、図鑑と観察ノートが何を見せているかを見比べると、自分の図鑑に足りない情報も見つけやすくなります。

