マガジン

キーを1つだけ使うゲームを3種類作る:押す・離す・長押し

遊びをつくる

執筆にClaudeを使用しています。

キーボードとタッチの二つの入力が、同じ駒のジャンプにつながる様子を描いたイラスト。
記事のテーマをもとに制作したAI生成イラスト。

スペースキー1つだけで遊ぶゲームを考える場面を思い浮かべてみます。操作が1つなら、遊びの種類も1つに絞られそうです。けれども、キーには「押した瞬間」「離した瞬間」「押している長さ」という3つの出来事があります。どれを判定に使うかで、プレイヤーが頭の中でやることが変わるはずです。 この記事で確かめるのは、同じキー・同じ緑のゾーン・同じ判定の幅でも、判定に使う出来事を替えるだけで、別の遊びとして感じられるのかという問いです。結果は書きません。小さな試作を1ファイル用意し、読者が自分で動かして記録をとり、読み取るための設計書として進めます。

この記事の目次
  1. 3つの遊びの仮説
  2. 準備するもの:1ファイルの試作
  3. 手順と記録の取り方
  4. 結果の読み方
  5. 起こりやすい誤り
  6. 次の行動

3つの遊びの仮説

実験の前に、何を比べるのかをはっきりさせます。以下は仮説であり、結果ではありません。

  • 押す、判定に使う出来事:押した瞬間、マーカー:常に往復、プレイヤーがやること(仮説):動くものを見て、一瞬を狙う
  • 離す、判定に使う出来事:離した瞬間、マーカー:押している間だけ動く、プレイヤーがやること(仮説):動きを見ながら、先を読んで手を止める
  • 長押し、判定に使う出来事:押していた長さ、マーカー:見えない、プレイヤーがやること(仮説):目を使わず、時間の長さを体で測る

「押す」は目で見て反応する遊びに近くなりそうです。「離す」は押している間ずっと画面を見られるので、準備と決断が分かれそうです。「長押し」は画面にヒントがないため、内的な時間感覚が頼りになりそうです。

この仮説が当たるかどうかは、読者の手元の記録で決まります。外れても実験としては成功です。「入力を替えても遊びが変わらなかった」という発見も、設計では価値のある情報になります。

準備するもの:1ファイルの試作

必要なのはブラウザとテキストエディタだけです。次のコードを index.html として保存し、ブラウザで開きます。外部ライブラリもサーバーも使いません。画面上の3つのボタンは、モードを切り替えるための実験用です。ゲームの入力はスペースキー1つだけです。

html
<!doctype html><meta charset="utf-8">
<p id="m"></p>
<div style="position:relative;width:300px;height:30px;background:#ddd">
<div style="position:absolute;left:120px;width:60px;height:30px;background:#9c9"></div>
<div id="k" style="position:absolute;width:6px;height:30px;background:#c33"></div></div>
<p id="r"></p>
<button onclick="set(0)">押す</button><button onclick="set(1)">離す</button><button onclick="set(2)">長押し</button>
<script>
let mode=0,x=0,d=3,held=false,t0=0;
const $=id=>document.getElementById(id);
function set(n){mode=n;x=0;held=false;document.activeElement.blur();
 $("k").style.display=n==2?"none":"block";
 $("m").textContent=["押す","離す","長押し"][n];$("r").textContent="スペースキーで遊びます";}
function judge(){const off=Math.abs(x+3-150);
 $("r").textContent=off<=30?"ゾーン内":"ずれ "+Math.round(off-30)+"px";}
addEventListener("keydown",e=>{if(e.code!="Space"||e.repeat)return;
 e.preventDefault();held=true;t0=performance.now();if(mode==0)judge();});
addEventListener("keyup",e=>{if(e.code!="Space")return;e.preventDefault();held=false;
 if(mode==1)judge();
 if(mode==2){const t=performance.now()-t0;
  $("r").textContent=Math.round(t)+"ms(目標1500ms、差 "+Math.round(t-1500)+"ms)";}});
(function loop(){if(mode==0||(mode==1&&held)){x+=d;if(x<0||x>294)d=-d;}
 $("k").style.left=x+"px";requestAnimationFrame(loop);})();
set(0);
</script>

3つのモードの違いは、コードの中で次のように表れています。

  • 押す:マーカーは常に往復します。keydown(キーを押した瞬間)で judge() を呼びます。
  • 離す:マーカーは held が真の間、つまり押している間だけ動きます。keyup(キーを離した瞬間)で judge() を呼びます。
  • 長押し:マーカーは非表示です。押した時刻 t0 と離した時刻の差を測り、目標の1500msとの差を表示します。

判定に使う幅(緑のゾーン±30px)は「押す」と「離す」で同一です。条件をそろえておくと、差が出たときに原因を入力の違いに絞れます。

手順と記録の取り方

1. 記録表を先に作る

遊ぶ前に、紙か表計算ソフトに次の列を用意します。

  • モード名
  • 試行番号(1〜20)
  • 表示されたずれ(pxまたはms)
  • ゾーン内なら「内」と記入
  • 一言メモ(任意)

試行を20回とするのは目安です。5回では偶然の影響が大きく、50回では疲れて操作が変わります。自分の集中が続く回数に変えても構いません。ただし3モードで同じ回数にしてください。

2. 順番を入れ替えて遊ぶ

「押す→離す→長押し」の順で毎回遊ぶと、後のモードほど慣れや疲れの影響を受けます。次のように並べ替えます。

  1. 1日目:押す→離す→長押し
  2. 2日目:長押し→押す→離す
  3. 3日目:離す→長押し→押す

日を分けられない場合は、モードの間に数分の休憩を挟みます。

3. 最初の数回は練習として分ける

初回は操作の確認で終わります。各モードの最初の3回は「練習」と記録し、集計から外します。外す回数は先に決めておきます。結果を見てから決めると、都合のよい数字だけを選ぶことになりやすいためです。

4. 感覚のメモを同時にとる

数値だけでは「別の遊びに感じたか」は分かりません。各モードの20回が終わった直後に、次の3点を一言ずつ書きます。

  • 失敗したとき、原因は「見るのが遅れた」「手が早かった」「長さが分からなかった」のどれに近かったか
  • 画面のどこを見ていたか(マーカー、ゾーン、画面の外など)
  • もう1回やりたくなったか

5. 他の人に遊んでもらう場合

別の人に遊んでもらうなら、仮説や見てほしい点は先に伝えず、まず遊んでもらいます。先に伝えると、その見方で遊んでしまいます。人数が少ないときは傾向の確認にとどめ、「みんなそう感じる」とは言わないでください。

結果の読み方

数値は「どれだけ正確だったか」より、ずれの出方に注目します。判断の目安を挙げます。

ずれの大きさがモードで大きく違うとき難しさが違うだけかもしれません。ゲームの種類が違うとは限らないので、メモの内容と合わせて読みます。難しさを調整したうえで、もう一度比べるのが確実です。

「押す」でずれがマーカーの位置に関係しているときたとえば、マーカーが右へ動いている最中は遅れ、左へ動いている最中は早すぎる、という偏りです。見てから反応するまでの遅れが出ている可能性があります。この場合、反応速度の遊びとして成立していると読めます。

「離す」で後半に急に上達するときマーカーの速さを体で覚え、先を読んで離せるようになった可能性があります。「押す」よりも学習の手応えが出る設計かもしれません。

「長押し」でずれが毎回同じ方向(長すぎる、または短すぎる)に偏るとき内的な時間感覚が一定の癖を持っているということです。目標秒数の選び方がゲームの手触りを左右する、と読めます。

どのモードも、メモの「失敗の理由」が同じ言葉になるとき入力を替えても、プレイヤーの体験は変わっていないということです。判定の幅や速さの影響のほうが大きい可能性があります。判定の幅と速さを動かして、もう一度比べます。

最終的に確かめたいのは次の3点です。

  1. 失敗の理由を、プレイヤー自身が言葉にできるか
  2. もう一度やりたくなる理由がモードごとに違うか
  3. 画面を見る場所がモードごとに違うか

この3点が揃って違えば、同じ入力から別の遊びが生まれていると言えます。

起こりやすい誤り

ボタンにフォーカスが残るモード切替のボタンをクリックした直後、そのボタンにフォーカスが残ります。この状態でスペースキーを押すと、ボタンが押されたことになる場合があります。試作では set() の中で blur() を呼んで避けています。コードを書き換えるときも残してください。

押しっぱなしの自動リピートを数えてしまうキーを押し続けると、keydown が繰り返し発生します。e.repeat を確認しないと、「押した時刻」が上書きされ続け、長押しの測定が狂います。

画面のリフレッシュ率で速さが変わるrequestAnimationFrame は、画面の更新ごとに呼ばれます。試作ではマーカーを1回の更新につき3px動かすため、高リフレッシュレートの画面では速く動きます。比べる回の間は、同じ端末と同じ画面設定を使ってください。ゲームとして公開するなら、経過時間から位置を計算する方法に直すと安定します。

ずれの単位をそろえて比べてしまう「押す」と「離す」はpx、「長押し」はmsです。数値同士を並べて大小を決めると、意味のない比較になります。モードの中での変化(前半と後半、日ごとの差)を見るか、それぞれを「ゾーン内に入った割合」に直して比べてください。

マーカーが見えるかどうかを難しさと取り違える「長押し」はマーカーがないため、他のモードと見え方が違います。ここでの差は入力の違いだけでなく、視覚情報の有無も含みます。これを分けたいなら、「長押し」にも薄いタイマー表示を足したモードを追加して4つ目として比べます。

結果を見てから仮説を直すデータを見たあとで「実はこう予想していた」と書き換えると、実験の意味が薄れます。仮説の表は、遊ぶ前に保存しておきます。

次の行動

まず index.html を保存し、3つのモードを日を分けて20回ずつ遊び、記録表とメモを残してください。その記録から、いちばん「もう一度やりたい」と感じたモードを選び、判定の幅や速さを変えて、小さなゲームに育てます。形になったら、index.html を直下に置いたHTMLファイルとして、アソバースに投稿できます(アップロードは20MiB以内)。