ワンボタンゲームを面白くする:押す・離す・待つの組み合わせ
遊びをつくる執筆にClaudeを使用しています。

「ボタンを一つにしたら、選択肢がなくなってしまった」——そう感じたことがあるなら、設計の視点を変えるタイミングだ。ワンボタンゲームの制約は操作の数ではなく、時間の使い方を設計することに本質がある。押す・離す・待つという三つの入力の組み合わせで、一つのキーやタップが複数の意味を持てる。この記事では、入力を時間軸で設計する考え方と、キーボードとタッチの両方に対応させる最小の実装パターンを整理する。
制約をゲームの軸にする
「ボタン数を減らす」と「操作を簡単にする」は別の話だ。十字キーとボタン六つのゲームでも、操作そのものが難しくないものはある。一方、スペースキー一つで時間を計りながら判断を迫られると、操作は単純なのに緊張感が生まれる。
ワンボタンの設計では、入力の数ではなく入力の形を変数にする。キーを押した瞬間、離した瞬間、何も押さずに時間が経った瞬間——この三つの状態を区別するだけで、一つの入力から最低三つの「事象」を作れる。さらに長押しの長さを読めば連続的な値が得られる。ボタン一つで「いつ・どのくらい」という二次元の情報を扱えるのだ。
この構造には、プレイヤーに覚えてもらう操作説明を最小化できる利点もある。「押す」だけ伝えれば始められる。「長押し」「タイミングよく離す」「連打」は、ゲームの中で体験させれば説明なしに伝わりやすい。
押す・離す・待つ——三つの入力を読む
ブラウザゲームでは、キーボードの keydown と keyup イベント、タッチ画面の touchstart と touchend イベントを使う。それぞれの意味を整理すると次のようになる。
- 押す(keydown / touchstart):入力が始まる瞬間。ジャンプの踏み切り、チャージの開始、マーカーを置くタイミングとして使う。
- 離す(keyup / touchend):入力が終わる瞬間。押してから離すまでの時間を計測すれば「長さ」が取れる。矢の飛距離や反動の強さに変換できる。
- 待つ(入力がない時間):前回の入力からの経過時間を読む。一定時間入力がなければオートセーブ、あるいはキャラクターが別の行動に移るといった「無操作への反応」を作れる。
keydown イベントはキーを押し続けると repeat プロパティが true になり繰り返し発火する(MDN: KeyboardEvent.repeat)。長押し判定を自分で作る場合は、最初の keydown だけ受け取り、keyup が来るまでフラグを立てる方法が確実だ。
三つを組み合わせると、入力のパターンは一気に増える。「素早く押して離す(タップ)」「長押し後に離す」「連続して素早く二回押す(ダブルタップ)」「しばらく間を置いてから押す」など、一つのボタンから六種類以上の意図を読み取れる。ゲームデザインの課題は、この中からプレイヤーが迷わず使える数だけ選ぶことだ。
時間で「選択肢」を作る設計パターン
時間を軸にした入力設計には、大きく三つのパターンがある。どれを使うかはゲームの緊張感の作り方によって変わる。
パターン1:チャージ型
押している間、パラメータが増える。離した瞬間にそのパラメータを使って行動する。砲台の発射角度や弾の強さを長押しの長さで決める設計がこれにあたる。プレイヤーは「どこまで溜めるか」を毎回判断することになり、簡単な操作に意思決定が重なる。溜めすぎると不利になるリスクを加えると、緊張感がさらに増す。
パターン2:タイミング型
画面上の何かが動いていて、特定の瞬間に入力すると成功になる。リズムゲームの基本構造だが、ワンボタンに限定するとプレイヤーは「いつ押すか」だけに集中できる。視線の誘導と音のフィードバックを丁寧に設計すれば、難易度調整は判定の幅を変えるだけで対応できる。
パターン3:間隔型
押す間隔そのものが入力値になる。短打と長打の二種類を読み取るだけでも、組み合わせによって豊かな表現が生まれる。ただし「何が正解か」をプレイヤーに伝える手段が必要で、視覚・聴覚フィードバックの設計に時間をかける価値がある。
三パターンを同じゲームに混在させると、プレイヤーが混乱しやすい。試作の段階では一つに絞り、遊べることを確かめてから拡張するのが効率的だ。
キーボードとタッチを共通の入力として扱う
ブラウザゲームをPCとスマートフォンの両方に対応させるとき、入力イベントを一か所にまとめると管理しやすい。以下は説明用の最小パターンであり、実際のゲームに合わせて調整が必要だ。
// 押した瞬間の時刻を記録する
let pressStart = null;
function onPressStart() {
pressStart = performance.now();
}
function onPressEnd() {
if (pressStart === null) return;
const duration = performance.now() - pressStart;
pressStart = null;
handleInput(duration); // 長さを使って行動を決める
}
// キーボード
document.addEventListener('keydown', (e) => {
if (e.code === 'Space' && !e.repeat) onPressStart();
});
document.addEventListener('keyup', (e) => {
if (e.code === 'Space') onPressEnd();
});
// タッチ
document.addEventListener('touchstart', (e) => {
e.preventDefault();
onPressStart();
}, { passive: false });
document.addEventListener('touchend', () => onPressEnd());onPressStart と onPressEnd という二つの関数に処理をまとめることで、キーボードとタッチのどちらから来た入力かをゲームロジック側で意識せずに済む。e.repeat チェックによって長押し中の keydown 繰り返しを除外している。
touchstart に { passive: false } を指定しているのは、Window・Document などのターゲットに登録した touchstart と touchmove について、ブラウザがスクロール性能のためにデフォルトで passive: true を適用するためだ(MDN: EventTarget.addEventListener #passive)。passive のままでは preventDefault() が無効になるため、スクロール抑制が必要な場面では明示的に false を指定する。touchend はこのデフォルト変更の対象外なので、通常の addEventListener で問題ない。
スペースキーをメイン入力にするとスクリーンリーダーのボタン操作と干渉することがある。Enter や任意のキーを追加の選択肢として用意するか、canvas 要素にフォーカスを当てる設計にすると衝突を避けやすい。
試作の最小手順とアソバースへの投稿
ワンボタンゲームの試作では、「何が起きているかをプレイヤーが理解できるか」を最初に確かめることが目的だ。次の手順で最初の動くものを作ると、設計のずれを早期に発見できる。
- 入力の種類を一つ決める:「タップ」「長押し+離す」「間隔」のどれか一つから始める。
- フィードバックを先に作る:押した瞬間と離した瞬間に色や音が変わる状態を用意する。ゲームルールより先にフィードバックがあると、入力が伝わっているかの確認が早い。
- 成功と失敗の判定を一つ加える:チャージ型なら「閾値を超えたか否か」、タイミング型なら「判定ウィンドウ内か否か」。まず二択から試す。
- PCとスマートフォンで動かして確認する:ブラウザのデベロッパーツールのデバイスエミュレーターで確認できる。タッチでのスクロール抑制と、画面サイズによるUI崩れを見る。
- アソバースに投稿する:単一HTMLファイルまたはZIPファイルとして直接アップロードするか、すでに公開済みのURLを登録する方法が使える。
試作を人に遊んでもらうとき、「次に何を押せばいいかわかった?」という一問が最も多くの情報を返してくれる。操作が一つであっても、それをいつ使うかの手がかりが画面にないと、プレイヤーは止まってしまう。動くオブジェクト、点滅するゲージ、音の変化といった視覚・聴覚の「誘い」を入力設計と並行して磨くと、ワンボタンの面白さが伝わりやすくなる。
操作が少ないほど、フィードバックの精度が問われる。これがワンボタンゲームを設計するときの核心だ。ボタン数を増やせばプレイヤーに選ばせられるが、一つに絞るなら何が起きているかを画面と音が常に正直に伝えていなければならない。その精度を高める作業こそが、ワンボタンゲームの独自性を生む。




