マガジン

上下左右の4方向だけで遊ぶゲームを3本作る

遊びをつくる

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

大きな操作ボタンと横向きの砂時計、複数の操作道具が並ぶ紙と木のゲーム風景
記事のテーマをもとに制作したAI生成イラスト。

ゲームのジャンルは、入力の種類で決まるのでしょうか。それとも、同じ入力でもルールの置き方しだいで、まったく別の遊びになるのでしょうか。この記事は、入力を「上・下・左・右」の4つだけに固定し、そのうえで3本のゲームを作って、ジャンルが本当に分かれるかを確かめる実験の設計書です。結果は書きません。読者が自分の手で作り、自分の記録で判断するための手順だけを示します。 たとえば、矢印キーしか使えないと決めた場面を考えてみます。最初に思いつくのは、キャラクターを動かす迷路やパズルでしょう。しかし4方向は「移動」以外にも読めます。「流れてくる矢印に合わせる」「命令を並べる」といった読み方をすれば、同じ4つの入力から別の遊びが立ち上がるはずです。その仮説が本当に成り立つのか、成り立たないならどこで崩れるのかが、この実験の中心です。

この記事の目次
  1. 問いと仮説をどう立てるか
  2. 準備するもの
  3. 手順
  4. 記録の取り方
  5. 結果の読み方
  6. 誤りやすい点
  7. 次の行動

問いと仮説をどう立てるか

実験では、固定するものと変えるものを分けます。

  • 固定するもの:入力は上・下・左・右の4種類だけです。キー、スワイプ、画面上のボタンのどれから来ても、ゲーム側には同じ4つの出来事として届けます。決定ボタン、スペース、ポーズ用のキーは使いません。
  • 変えるもの:4つの入力に与える意味です。位置の移動、タイミングの一致、命令の記録など、入力の「読み方」を変えます。

問いは次の一文にまとめます。「入力を4方向に固定しても、遊び手が別のジャンルとして受け取るゲームを3本作れるか」。仮説は、「入力の意味づけを変えれば、操作の数が同じでも遊びの中心は変わる」とします。仮説が外れる可能性も、最初から想定に入れておきます。

3本の設計案

ジャンルが重ならないよう、遊びの中心になる動詞を変えた3案を用意します。

  • A、仮の名前:滑る床、4方向の意味:押した向きに壁まで滑る、遊びの中心:止まる場所を先読みする
  • B、仮の名前:流れる矢印、4方向の意味:判定ラインに来た矢印と同じ向きを押す、遊びの中心:押す瞬間を合わせる
  • C、仮の名前:命令の列、4方向の意味:8手ぶんの歩き方を入力し、並べ終えると自動で実行される、遊びの中心:手順を組み立てる

Aは、障害物の置かれた盤面で、ゴールの手前に止まれる位置をたどるパズルです。Bは、一定の速さで降りてくる矢印を受け止める反応型です。Cは、入力そのものが「プログラム」になる型で、決定ボタンがないため「いつ実行するか」を設計で解く必要があります。ここが制限の効きどころです。たとえば「8手入力した時点で自動実行する」ことにすれば、誤入力を直せない緊張感が生まれます。逆に「一定時間入力がなければ実行する」と決めれば、時間の圧力が加わってジャンルが反応型に寄るかもしれません。どちらを選んでも構いませんが、選んだ理由は記録に残します。

案が気に入らなければ、読者が自分で3案を作り替えて構いません。守るべき条件は、3本の「遊びの中心の動詞」が互いに異なることと、入力が4方向だけであることの2点です。

準備するもの

必要なのは、ブラウザとテキストエディタ、そして3本で共有する入力層です。入力層を共通化しておくと、「入力は本当に同じだった」と後から言えます。次のコードは、キー入力とスワイプを同じ4つの出来事(U・D・L・R)にそろえ、押した時刻の記録も取る最小構成です。

html
<canvas id="c" width="320" height="320" style="touch-action:none;background:#222"></canvas>
<script>
const Input = (() => {
  const handlers = [];
  const emit = d => handlers.forEach(h => h(d));
  const keyMap = {ArrowUp:'U',ArrowDown:'D',ArrowLeft:'L',ArrowRight:'R'};
  addEventListener('keydown', e => {
    const d = keyMap[e.key];
    if (!d) return;
    e.preventDefault();
    if (e.repeat) return;
    emit(d);
  });
  let sx, sy;
  const el = document.getElementById('c');
  el.addEventListener('pointerdown', e => { sx = e.clientX; sy = e.clientY; });
  el.addEventListener('pointerup', e => {
    if (sx == null) return;
    const dx = e.clientX - sx, dy = e.clientY - sy;
    sx = null;
    if (Math.max(Math.abs(dx), Math.abs(dy)) < 24) return;
    emit(Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? 'R' : 'L') : (dy > 0 ? 'D' : 'U'));
  });
  return { on: h => handlers.push(h) };
})();
let log = [];
Input.on(d => { log.push([Math.round(performance.now()), d]); console.log(d, log.length); });
</script>

ファイルを開いて矢印キーを押すか、キャンバス上をスワイプすると、開発者ツールのコンソールに方向と通算回数が出ます。e.repeat を無視しているのは、キーを押しっぱなしにしたときの連続入力を1回として数えるためです。Aの滑る床では妥当ですが、Bの流れる矢印では押しっぱなしを許すかどうかで難しさが大きく変わります。変えるときは、変えた事実を記録します。

あわせて、試遊してもらう相手を3人以上、読者が自分で集めます。人数に決まりはありません。多いほど判断はぶれにくくなりますが、少なくても記録の形さえ守れば比較はできます。

手順

1本ごとに作る時間の上限を決めます。目安は1本あたり90分です。上限を超えて作り込むと、4方向の制限ではなく作者の工夫量で出来が決まってしまうためです。時間は読者の都合で変えて構いませんが、3本で同じにします。

  1. ルール文を先に書きます。 「プレイヤーは〜して、〜を目指す」という一文を、コードを書く前に決めます。この文の動詞が、後で比較する主な材料になります。
  2. 入力層を貼り付けます。 3本とも同じコードを使い、変更点があれば記録します。
  3. 画面を最小にします。 背景、効果音、演出は後回しにし、ルールが成立する最小の画面だけを作ります。
  4. 自分で3分遊びます。 遊びながら「ここにボタンがほしい」と思った回数を数えます。
  5. 試遊者に3分遊んでもらいます。 ルールの説明は一言だけにし、遊び終えたら「このゲームを一言で何と呼びますか」と聞きます。
  6. 次の1本に進みます。 前の作品の仕組みを流用せず、ルール文から新しく書きます。

3本目まで終えたら、記録を並べて見比べます。作る順番による慣れの影響が気になる場合は、別の機会に順番を入れ替えてもう一度行ってみます。

記録の取り方

記録の単位をそろえるほど、後で比較しやすくなります。1本につき次の項目を残します。

  • ルール文:一文で、動詞を含めて書きます。
  • 制作時間:実際にかかった分数です。
  • ボタンがほしくなった回数:自分の試遊中に数え、何がほしかったか(決定、取り消し、ポーズなど)を一言添えます。
  • 入力ログ:上の log から、3分間の入力回数と、入力間隔の最短・最長を取り出します。
  • 試遊者の呼び名:各人が付けた一言を、聞いたままの言葉で書きます。言い換えず、そのまま残します。
  • 最初に見た場所:試遊中、試遊者の視線が最初に向いた場所(自機、盤面全体、判定ライン、命令欄など)を観察して書きます。

回数は、自分の試遊が各3回、試遊者が各1回以上を目安にします。1回だけの結果で判断せず、ばらつきも見ます。

結果の読み方

記録がそろったら、3本を次の表のように並べて見ます。

  • 動詞、見るもの:ルール文の動詞、別ジャンルと言いやすい状態:3本で動詞が異なる
  • 失敗の原因、見るもの:負けや失点の理由、別ジャンルと言いやすい状態:「先読み不足」「タイミングのずれ」「手順の誤り」のように種類が違う
  • 時間の役割、見るもの:時間が果たす働き、別ジャンルと言いやすい状態:無い、判定の基準、圧力のように役割が違う
  • 最初に見る場所、見るもの:試遊者の視線、別ジャンルと言いやすい状態:盤面、判定ライン、命令欄のように場所が違う
  • 呼び名、見るもの:試遊者の一言、別ジャンルと言いやすい状態:「パズル」「リズム」など異なる語が出る

判断は次のように行います。

  • 5観点のうち4つ以上で3本が分かれていれば、「入力を固定してもジャンルは分かれた」と読めます。
  • 動詞と失敗の原因は分かれても、呼び名がすべて「パズル」に集まった場合は、作品としては近いと読めます。この場合は、Bの時間の使い方が弱い可能性があります。
  • 呼び名が分かれたのに入力ログが3本で似ているなら、ジャンルの差を作ったのは入力ではなく画面の見せ方だと読めます。それも一つの答えです。
  • ボタンがほしくなった回数が特定の1本に偏っているなら、その作品は4方向では足りない設計かもしれません。何を足したくなったかが、次の設計の材料になります。

答えが「分かれなかった」でも失敗ではありません。どの観点で重なったかが分かれば、制限つきの制作で何が個性になるのかを具体的に言えるようになります。

誤りやすい点

  • 作者の目で採点しないようにします。 自分が作ったゲームを自分でジャンル分けすると、違いを大きく見がちです。呼び名は試遊者の言葉を優先します。
  • 決定ボタンを足さないようにします。 「ここだけEnter」は、一度許すと3本すべてに広がります。足したくなったら、足さずに記録だけ残します。4方向以外の入力が必要になった作品を比べるなら、潮目のオセロ(矢印キーとEnterで操作)や紙ひこうき郵便(左右キー、ドラッグ、矢印ボタン)のように、複数の入力を併用する公式作品を開き、どの場面で何を使い分けているかを確かめる方法もあります。具体的な操作の細部は、作品を開いて確認してください。
  • スワイプの斜めを放置しないようにします。 上のコードは縦横のうち大きいほうを採ります。斜めを無効にしたほうが合う作品もあるので、判定は作品ごとに決めます。
  • スマートフォンの画面スクロールに注意します。 キャンバスに touch-action:none を付けないと、スワイプがページのスクロールに奪われます。
  • 押しっぱなしの扱いを決めます。 e.repeat を無視するかどうかで、Bの難しさがまるで変わります。変えたら記録します。
  • 工夫を足しすぎないようにします。 90分の枠を超えて演出を重ねると、ジャンルの差が演出の差に紛れます。

アソバースに投稿する場合

3本を公開したくなったら、アソバースの投稿条件に合わせます。HTMLを直接アップロードするか、ZIPなら直下に index.html を置き、素材は相対パスで参照します。サーバー用コードやサービスワーカーは使えません。今回のコードは外部通信もなく、条件を満たします。作品内で localStorage を使った記録は一時メモリーとして扱われるため、記録が残ることを前提にした設計にしないでください。投稿には上限があるので、公開内容は下書きの段階で確認してから進めます。

次の行動

まず入力層のコードを1つのHTMLに貼り、矢印キーとスワイプの両方でコンソールに方向が出ることを確かめます。そのうえで3案のうち1本のルール文を一文で書き、90分の枠で最小の画面を作ってください。3本そろったら、表の5観点で記録を並べて読みます。