AI(Claude)でスマホ1台の2人対戦ゲームを2時間で作って売るまで:画面を上下に分け、2本の指を別々に受け、子どもが勝てるハンデを3種類に絞る

AI(Claude)に頼んで、スマホ1台を2人のあいだに置いて向かい合って遊ぶ対戦ゲームを約2時間で作り、note で売るところまで進めました。HTMLファイル1枚で、音もコードで鳴らしています。画面を上下に分ける作り、2本の指の同時タッチ、子どもが勝てるハンデの決め方と、別のAIの点検で見つかった不具合を書きます。

※この記事には広告(PR)を含みます。

作ったもの

『タッチうんどうかい』という、スマホのブラウザで遊ぶ2人対戦ゲームです。

タッチうんどうかいの体験版の3つの種目(よーいドン・つなひき・マークでタッチ)の画面
体験版の3つの種目。画面の上半分は、向こうの人から読めるように、さかさまに出る
  • スマホを2人のまんなかに置くと、画面が上と下に分かれる。手前が「あかぐみ」、向こうが「しろぐみ」
  • あとは自分の側をタッチするだけ。運動会の種目のような勝負を順番にして、先に3点とったほうが勝ち
  • 1回の勝負は数秒から十数秒。優勝すると紙ふぶきが舞う
  • 子ども向けの画面の文は、漢字を使わず、ことばの区切りに空白を入れている

体験版(よーいドン・つなひき・マークでタッチの3種目)は無料で、完全版(たまいれ・だるまさんがころんだ・ぴったりストップ・いくつかな・パンくいきょうそうを足した8種目、ハンデ、名前、対戦の記録)は note で300円で売っています。

どちらも HTML ファイル1枚です(体験版 約46KB・完全版 約85KB)。画像ファイルも音声ファイルも、外部のライブラリもありません。外から読むのは Google Fonts の書体だけです。

体験版をブラウザで開く(無料)

かかった時間と、人がやったこと

最初の一言から note での公開まで、約2時間でした(2026年10月16日の23時ごろ〜17日の1時ごろ)。

人がやったのは、次のことだけです。

  • 「次のアプリを、下書きまで」と頼む
  • 試作を見て、「スマホ1台で、いますぐ子どもと向かい合って遊べる」を売りの一言に決める
  • GitHub と note の公開を了承する

設計・コード・音・テスト・点検の直し・記事の原稿・公開の作業は、AI(Claude)がやりました。コードは1行も手で書いていません。

設計の要点

最初に決めた条件は、次の7つです。

  1. 1枚のHTMLで完結させる。解析タグ・外部への送信は入れない
  2. 画面を上下に分け、上半分は transform: rotate(180deg) で向こうの人向きにする
  3. タッチは pointer イベントを指ごと(pointerId)に受け、どちらの側かは座標で決める。2人が同時に触っても、それぞれの側で反応する
  4. ハンデは「相手の反応を遅らせる」「必要な数を減らす」「まちがえたときの罰をゆるくする」の3種類だけにして、種目ごとに数字で決める
  5. 横向き(高さ500px以下の横長)になったら「スマホを たてに してね」を出して止める。ほかのアプリに切り替えたときも止める。遊んでいるあいだは画面が暗くならないようにする(Wake Lock)
  6. 記録(名前・設定・勝ち負け)は完全版だけ、ブラウザの localStorage に残す。体験版と完全版は同じドメイン(GitHub Pages)に置く
  7. 元ファイルは1枚(src/app.html)で、完全版だけの部分を行の印(#full 〜 #end)で囲み、小さな Python のスクリプトで体験版と完全版に分ける。体験版のファイルを読んでも、完全版の種目のコードは入っていない

2本の指を、別々に受ける

上下のパネルそれぞれに pointerdown を付け、ボタンの上でなければそのパネルの側のタッチとして処理します(実際のコードを短くしたもの)。

panels[t].el.addEventListener('pointerdown', e => {
  if (e.target.closest('button')) return;
  e.preventDefault();
  lastInput = performance.now();
  if (!wake && playing) keepAwake();   // 画面を暗くしない
  ripple(t, e);                          // 触った所に波紋
  ensureAudio();                         // 最初のタッチで音を起こす
  onTap(t, e);                           // t は 'aka' か 'shiro'
});

touch イベントではなく pointer イベントにしたのは、指ごとに pointerId が付き、2本の指が同時でも別々の pointerdown として届くからです。長押しのメニューが出ないように contextmenu も止めています。

種目のルールは、この onTap に「どちらの側が、どの局面で触ったか」を渡して決めています。たとえば「よーいドン」は、「よーい…」のあいだに触ればフライング(相手に1点)、「ドン!」のあとは先に触ったほうに1点、という具合です。

ハンデは、3種類だけ

大人が本気を出すと子どもは勝てず、わざと負けると子どもはすぐ気づきます。そこで、大人は本気のまま、子どもに勝つ目が残る形にしました。

  • 相手の反応を遅らせる:よーいドンは「ドン!」のあと 0.15秒→0.3秒、マークでタッチは 0.25秒→0.5秒のあいだ、相手が触っても反応しない
  • 必要な数を減らす:たまいれは10こ→8こ→6こ、だるまさんがころんだは22歩→16歩→12歩
  • 罰をゆるくする:「たくさん」のときは、フライングやおてつきをしても相手に点が入らず、1秒の「おやすみ」になるだけ

種目ごとの数字は、記事の有料部分に全部書きました。「どれくらい有利なのか」が分からないと、親は選べないからです。

音もコードで鳴らす

「ドン!」の合図、タッチの音、紙ふぶき、ぴったりストップの秒の「ピッ」などは、Web Audio のオシレーターとエンベロープで、その場で作っています。音声ファイルはありません。最初のタッチで AudioContext を起こすのは、iPhone が「ユーザーの操作のあと」でないと音を出さないためです。

テストは、ボットに遊ばせる

2人で同時に触るゲームを手で確かめるのは難しいので、遊ぶボットを作りました。

  • Playwright(Python)で、手元の http サーバーから体験版と完全版を開く。Google Fonts は手元の書体に差し替える(クラウドの作業場所からは Google Fonts に届かないため)
  • 時計を Playwright の偽の時計にして、「よーい…」の待ち時間や「つなひき」の10秒を一瞬で進める。Math.random は seed で固定する
  • ボットは画面(DOM)だけを見て遊ぶ。「ドン!」が出たら触る、マークが合ったら触る、という具合に
  • 2本の指の同時タッチは、ブラウザの開発者用の口(CDP)から2点のタッチを送って確かめる。偽の時計では通らないので、ここだけ本物の時計で

テストの項目は、決まり・ハンデ・記録・画面の大きさ(幅320〜タブレット)・同時タッチ・裏に回る・横向き・音なし・保存できないブラウザ・壊れた記録、です。

つまずいた点(別のAIの点検で見つかったもの)

自分のテストが全部通ったあとで、別のAIに「壊す気で点検して」と渡しました。出たのは26件(重い3・中4・軽い16、ほか未確認3)。代表的なものです。

  • 完全版の置き場所(リポジトリ)が、検索から見つかる:有料のものを GitHub Pages に置く以上、URLを知れば誰でも開けます。noindex にして、URLは記事の有料部分にだけ書くことにしました(静的なファイルでは、これ以上は止められません)
  • マークでタッチで、手前の側の説明と「さがす マーク」が見えない:色の指定が重なって、文字が背景と同じ色になっていた
  • 「いくつかな」で、小さめのスマホだと絵が重なって数えられない:絵の大きさを、画面の幅でなく、絵を置く箱の実寸から決めるようにした
  • 「裏に回る → 戻る → 0.5秒以内にまた裏」で、ゲームが裏で進んで点を失う:裏に回ったら、どの局面でも再開のタイマーを消すようにした
  • 試合が終わっても、画面が消えない:優勝の画面で Wake Lock を手放していなかった
  • ぴったりストップで、5.00より前に止めると表示と判定が合わない:先に百分の一秒に丸めてから、表示にも判定にも同じ値を使うようにした

記事の原稿も、ゲームの画面の文字と1文ずつ突き合わせる校閲を別のAIにさせました。出たのは36件で、多くは「」で引いた画面の文言のずれ(「もういちど おすと やめる」のような空白の位置まで)でした。子ども向けに空白で区切った文は、記事に写すときにずれやすいです。

同じものを作るときの手順

  1. 1枚HTML・元ファイルの印の付け方・完全版の部分を抜く方法を、最初に決める
  2. 画面の上下分けと、pointer イベントの同時タッチを、いちばん最初に動かす(これが成り立たないとゲームにならない)
  3. ハンデの種類を先に3つに絞り、種目ごとの数字は表にして記事にも書く
  4. 偽の時計で速く回るボットのテストを作り、同時タッチだけは本物の時計で確かめる
  5. 別のAIに壊させて直す。記事の文言はゲームの画面と突き合わせる
  6. 体験版と完全版を同じドメインの GitHub Pages に置き、完全版は noindex にしてURLは有料部分にだけ書く

体験版と完全版

体験版は、ブラウザで開くだけで遊べます(スマホは縦向きにして、2人のあいだに置きます)。

体験版をブラウザで開く(無料)

完全版(8種目・ハンデ・名前・対戦の記録)は、note「余白の実験室」の記事で案内しています(有料・買い切り)。

note の記事を見る(PR)

※この記事は、AI(Claude)でブラウザのゲームを作って売るまでの記録です。動きは、パソコンの Chrome でスマホの画面の大きさにして確かめています。実際のスマホでは確かめきれていないので、お使いの端末で動くかは体験版で確かめてください。同じ作り方の記録に、ブラウザのシミュレーションRPGとふたりの休み合わせカレンダーがあります。

この記事が参考になったら、ランキングの応援をお願いします。

にほんブログ村 小遣いブログ 副業・副収入へ にほんブログ村 小遣いブログ 在宅ワークへ
おすすめの記事