1画面だけで完結するゲーム:画面遷移をゼロにする
遊びをつくる執筆にClaudeを使用しています。

小さなゲームを作り終えて、タイトル画面、プレイ画面、結果画面の3枚をつなぐ場面を考えてみます。画面ごとにボタンを置き、「はじめる」で切り替え、終わったら「結果へ」で切り替え、「もう一度」でタイトルに戻す。ここまでで、遊びの中身より先に、画面をつなぐ配線が一番の作業になっていることがあります。 そこで「1画面だけで完結させたら、何が減り、何が壊れるか」という問いを立てます。タイトル、プレイ、結果を同じ場所に置き、状態に応じて中身だけを入れ替えます。この記事は、その設計を試す実験の設計書です。結果は書きません。読者が同じミニゲームを2通りに作り、自分で数字を取り、判断できる形にします。
問いと比べ方を決める
最初に、この実験で確かめたいことを一文にします。
タイトル・プレイ・結果を同じ画面に置くと、「遊び始めるまで」と「やり直すまで」は短くなるか。短くなる代わりに、誤操作は増えないか。
比べるのは次の2版です。ゲームのルールは同じにします。
- A版(3画面版):タイトル、プレイ、結果が別々の画面です。
- B版(1画面版):画面は1つで、ボタンの文言と周りの表示だけが状態で変わります。
ルールまで変えると、差が遷移の有無によるものか、遊びの違いによるものか区別できなくなります。ミニゲームは「5秒だと思うところで止める」ものを使います。ルールが一言で言え、1回が短く、結果が数字で出るので、記録が楽です。
見たい指標は次の4つです。
- 開始までの操作数:ページを開いてから、プレイが始まるまでのタップや click の回数
- 開始までの秒数:ページを開いてから、最初のプレイが始まるまでの時間
- 再挑戦までの秒数:結果を見てから、次のプレイが始まるまでの時間
- 誤操作の回数:意図しない開始や、結果を読む前に押してしまった回数
1と2は「軽さ」、3は「続けやすさ」、4は「1画面にしたことの代償」を見る指標です。代償の指標を最初から入れておくと、短くなった数字だけで「成功」と判断せずに済みます。
準備するものと、1画面版の最小実装
準備するものは次のとおりです。
- ブラウザで開けるHTMLファイルを2つ(A版とB版)
- 遊んでもらう人。人数は集められる範囲で決め、少人数でも続けて遊べる人を選びます
- 時間を測る手段。画面録画か、ストップウォッチ機能のある端末
- スマートフォンとパソコンのどちらか、できれば両方
B版の核は、状態を1つの変数で持つことです。idle(待機)、playing(プレイ中)、done(結果)の3つだけにして、同じボタン、同じ時間表示を使い回します。以下は単独で動く最小の例です。
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>5秒ぴったり</title>
<style>
body{font-family:sans-serif;display:grid;place-items:center;min-height:100vh;margin:0}
main{width:min(90vw,320px);text-align:center}
#time{font-size:3rem;font-variant-numeric:tabular-nums;margin:.5em 0}
#msg{min-height:3em}
#best{min-height:1.5em;font-size:.9rem}
button{width:100%;padding:1em;font-size:1.2rem}
</style>
<main>
<h1>5秒ぴったり</h1>
<p id="msg" aria-live="polite"></p>
<div id="time">0.00</div>
<button id="btn"></button>
<p id="best"></p>
</main>
<script>
let state="idle",t0=0,raf=0,lock=0,best=null;
const $=id=>document.getElementById(id);
const label={idle:["はじめる","5秒だと思うところで止めます。"],
playing:["止める","いま何秒でしょう。"],done:["もう一度",""]};
function set(s){state=s;$("btn").textContent=label[s][0];$("msg").textContent=label[s][1];}
function tick(){$("time").textContent=((performance.now()-t0)/1000).toFixed(2);raf=requestAnimationFrame(tick);}
$("btn").onclick=()=>{
const now=performance.now();
if(now<lock)return;
if(state==="playing"){
cancelAnimationFrame(raf);
const sec=(now-t0)/1000,d=Math.abs(sec-5);
$("time").textContent=sec.toFixed(2);
best=best===null?d:Math.min(best,d);
set("done");
$("msg").textContent="5秒との差は"+d.toFixed(2)+"秒です。";
$("best").textContent="ここまでの最小の差:"+best.toFixed(2)+"秒";
lock=now+400;
}else{t0=now;tick();set("playing");}
};
set("idle");
</script>このコードのポイントは2つあります。
1つ目は、ボタンの位置が状態によって動かないことです。「はじめる」「止める」「もう一度」が同じ場所にあるので、指を動かさずに続けて遊べます。ただしこれは、次に書く誤操作の原因にもなります。
2つ目は、lock です。結果が出た直後の400ミリ秒だけ押しを無効にしています。「止める」を連打した指が、そのまま「もう一度」を押してしまうことを防ぐためです。400という値は目安にすぎません。実験で調整する対象として扱ってください。
A版は、この3つの状態をそれぞれ別のHTML要素(またはページ)に分け、状態が変わるたびに表示と非表示を切り替えます。遊びの計算部分は共通にして、画面の構成だけを変えてください。
手順と記録の取り方
遊んでもらう手順は次のとおりです。
- 遊ぶ人に、ルールの説明は「5秒だと思うところで止めます」の一言だけ伝えます。
- A版かB版のどちらかを開いてもらい、端末の録画を始めます。
- 1版につき、最初の開始から数えて5回連続で遊んでもらいます。
- もう一方の版でも同じことを繰り返します。
- 順番は人ごとに入れ替えます。1人目はA→B、2人目はB→Aのようにします。
順番を入れ替えるのは、2つ目に遊ぶ版のほうが慣れて有利になるからです。入れ替えなければ、版の差と慣れの差を分けられません。
記録は録画を見返して取ります。次のような表を、人ごと、版ごとに1枚用意します。
- 開始までの操作数、単位:回、取り方:開いてから1回目のプレイ開始まで
- 開始までの秒数、単位:秒、取り方:開いてから1回目のプレイ開始まで
- 再挑戦までの秒数、単位:秒、取り方:結果表示から次のプレイ開始まで、各回
- 誤操作、単位:回、取り方:意図しない開始、読む前の押下など
- ひとこと、単位:文、取り方:迷った場所、戸惑った瞬間
「誤操作」は、遊んだ本人に聞くだけでは取りこぼします。録画で、結果が出てから1秒未満に次のプレイが始まった場合を候補として拾い、本人に「今のは意図して押しましたか」と尋ねて確かめてください。「ひとこと」は数字では見えない引っかかりを残すための欄です。
結果の読み方
数字が出たら、一つの指標だけで勝ち負けを決めず、組み合わせて読みます。次は判断の目安です。
- 開始までの秒数と操作数がB版で小さい:画面遷移を挟まない効果が出ている可能性があります。ただし、A版のタイトル画面に説明文が多い場合は、遷移の有無ではなく文章量の差かもしれません。A版の説明文をB版と揃えて、もう一度測ってください。
- 再挑戦までの秒数がB版で小さく、誤操作が増えていない:1画面にしたことの利点が素直に出ている状態です。
- 再挑戦までの秒数が小さいのに、誤操作が増えている:結果を読む前に次が始まっています。短さは「結果を読まない」ことで得た短さかもしれません。lock を延ばす、結果の帯を残して開始を別のボタンにする、といった対処を試し、同じ表で再測定します。
- 差がほとんどない:このミニゲームでは遷移の有無が効いていないという答えです。これも有用な結果です。画面が増えても迷わない規模のゲームなら、わざわざ1画面にしなくてよい、という判断ができます。
- 「ひとこと」に「今どの状態かわからない」が並ぶ:数字に出なくても、状態の見分けに問題があります。ボタンの文言だけでなく、背景色や見出しの変化など、手がかりを足す余地があります。
人数が少ないときは、平均よりも一人ひとりの動きを見るほうが信頼できます。誰か一人でも「結果を読めなかった」と言ったなら、数字が良くてもその点は直す価値があります。
起こりやすい誤り
1画面版で特に起きやすいつまずきを、実装と実験の両面でまとめます。
- 同じ場所のボタンが複数の意味を持つ:誤操作の最大の原因です。lock の時間、または開始ボタンを押すまでの小さな間を設けて試してください。
- 状態の見分けを文言だけに頼る:色が見分けにくい人や、画面を一瞬しか見ない人には届きません。結果の帯の出現、見出しの変化など、複数の手がかりを使います。
- 結果の情報が盤面を隠す:結果を重ねて表示すると、直前の盤面や数字が見えなくなります。置く場所を、盤面の下や横に決めておきます。
- A版とB版でルールや見た目が揃っていない:差が遷移によるものか判断できなくなります。比べる前に、2つの版を見比べて確認してください。
- 動きが多すぎる:状態が変わるたびに大きく動かすと、画面遷移をなくした意味が薄れます。動きを使うなら prefers-reduced-motion で弱められるようにしておくと、動きが苦手な人にも配慮できます。
- 状態更新の漏れ:playing から done へ移る際に、アニメーションの停止(上の例の cancelAnimationFrame)を忘れると、時間が動き続けます。状態を変える場所を一つの関数にまとめると、漏れを防げます。
アソバースに投稿する場合は、直下に index.html を置いた単独のHTMLでも公開できます。1画面で完結する設計は、1ファイルで作りやすい構成です。アップロード容量やZIPの条件などは、投稿画面の案内で最新の内容を確認してください。
次の行動
まず上のコードを自分のファイルに写し、A版として画面を3つに分けた版を作ってみてください。次に、2〜3人に両方を5回ずつ遊んでもらい、表の4項目だけ記録します。数字より先に「ひとこと」を読み返すと、直す場所が見えやすくなります。

