【ゲーム】JavaScript:54 反射神経テストゲーム

 「反射神経テストゲーム」は、画面の色が変わった瞬間をできるだけ早くクリックして、自分の反射速度をミリ秒単位で測定するシンプルなリアクションゲームです。背景には待機中を示すグレー、合図時には緑、早すぎるクリック時にはオレンジと色が変化し、視覚的に反射のタイミングを把握できます。自己ベストを更新しながら、最高の反射速度を目指しましょう。

遊び方・操作方法

  1. タイトル画面で「スタート」ボタンをクリックするとテストが始まります。
  2. 画面中央のテストエリアが「準備中…」のグレー状態からランダム時間(約1.5~3.5秒)経過後に緑色に変わります。
  3. 緑色に変わったら、できるだけ早くテストエリア(赤い枠)をクリック(タップ)してください。
  4. 合図前にクリックするとオレンジ色で注意メッセージが表示され、自動で再スタートします。
  5. 反射速度が計測され、結果画面でミリ秒単位の値が表示されます。何度でも挑戦でき、直近10回分の記録が表示されます。

ルール

  • 合図(緑色)後のクリック時間を計測し、その差分を「反射速度(ミリ秒)」として記録。
  • 合図前の早すぎるクリックは「早押し」とみなし、再チャレンジ。
  • 直近10回分の結果を保管し、上位3件をタイトル画面と結果画面に表示。
  • 何度でも挑戦可能。自己ベスト更新を目指す。

🎮ゲームプレイ

以下のリンク先から実際にプレイできます。

54 反射神経テストゲーム

素材のダウンロード

以下のリンクから使用する素材をダウンロードできます。

reflex_test_game_title.pngreflex_test_game_bg.png

ゲーム画面イメージ

プログラム全文(reflex_test_game.html)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>🔴 反射神経テストゲーム 🔴</title>
  <style>
    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
      font-family: 'Yu Gothic', 'Meiryo', sans-serif;
      background: url('reflex_test_game_bg.png') no-repeat center center fixed;
      background-size: cover;
    }
    body {
      width: 100vw;
      height: 100vh;
      overflow: auto;
    }
    .container {
      width: 800px;
      margin: 40px auto;
      background: rgba(255,255,255,0.93);
      border-radius: 24px;
      box-shadow: 0 4px 24px rgba(0,0,0,0.12);
      padding-bottom: 32px;
      min-height: 600px;
      position: relative;
    }
    .title-img {
      display: block;
      margin: 20px auto 16px auto;
      width: 400px;
      max-width: 80%;
      height: auto;
    }
    h1 {
      text-align: center;
      font-size: 2.2em;
      margin: 0.6em 0 0.2em 0;
      color: #B11D1D;
      text-shadow: 2px 2px 6px #fff;
      letter-spacing: 0.05em;
    }
    .rule-section {
      background: rgba(255,245,230,0.97);
      border-radius: 14px;
      margin: 30px 32px 14px 32px;
      padding: 16px 24px;
      box-shadow: 0 2px 8px rgba(128,64,0,0.09);
    }
    .rule-title {
      text-align: center;
      font-weight: bold;
      font-size: 1.4em;
      margin-bottom: 10px;
      color: #d50000;
    }
    .rule-text {
      text-align: left;
      font-size: 1.09em;
      line-height: 1.65;
      color: #7a3333;
      letter-spacing: 0.01em;
    }
    .btn {
      display: block;
      margin: 26px auto 0 auto;
      padding: 14px 54px;
      font-size: 1.24em;
      border: none;
      border-radius: 28px;
      background: linear-gradient(90deg, #ff6767, #e02b2b);
      color: #fff;
      font-weight: bold;
      box-shadow: 0 2px 8px #d1727290;
      cursor: pointer;
      transition: background 0.2s;
    }
    .btn:hover { background: linear-gradient(90deg, #ffaaaa, #b11d1d); }
    /* テストエリア */
    .reflex-area {
      width: 640px;
      height: 320px;
      margin: 40px auto 0 auto;
      border-radius: 20px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 2.6em;
      color: #fff;
      background: #d50000;
      cursor: pointer;
      box-shadow: 0 2px 16px #d1727290;
      user-select: none;
      position: relative;
      transition: background 0.18s;
    }
    .reflex-area.waiting {
      background: #888;
      color: #eee;
      cursor: not-allowed;
    }
    .reflex-area.ready {
      background: #17a81a;
      color: #fff;
      cursor: pointer;
    }
    .reflex-area.early {
      background: #ff9800;
      color: #fff;
      cursor: not-allowed;
    }
    .message-box {
      text-align: center;
      background: rgba(255,245,230,0.97);
      font-size: 2em;
      color: #b11d1d;
      font-weight: bold;
      border-radius: 16px;
      box-shadow: 0 4px 24px #ffb70033;
      width: 80%;
      max-width: 480px;
      margin: 40px auto 0 auto;
      padding: 38px 18px;
      position: relative;
      z-index: 2;
    }
    .center-btn { margin: 24px auto 0 auto; }
    .score-list {
      font-size: 1.06em;
      margin: 16px auto;
      text-align: center;
      color: #555;
      line-height: 1.7;
    }
    @media (max-width: 900px) {
      .container, .reflex-area { width: 98vw !important; min-width: 0; }
      .reflex-area { height: 28vw !important; font-size: 2em;}
    }
  </style>
</head>
<body>
  <div class="container" id="main-container"></div>
  <script>
    // --- 状態変数 ---
    let gameStarted = false;
    let startTime = 0;
    let timeoutId = null;
    let resultTime = null;
    let records = []; // 記録用

    // === タイトル画面描画 ===
    function showTitleScreen() {
      gameStarted = false;
      clearTimeout(timeoutId);
      document.getElementById('main-container').innerHTML = `
        <h1>🔴 反射神経テストゲーム 🔴</h1>
        <img src="reflex_test_game_title.png" class="title-img" alt="反射神経テストタイトル">
        <div class="rule-section">
          <div class="rule-title">🎲 遊び方・ルール 🎲</div>
          <div class="rule-text">
            ・スタートボタンを押すとテストが始まります。<br>
            ・「クリックして!」の合図が表示されたら、できるだけ早くクリック(タップ)してください。<br>
            ・クリックが早いほど、あなたの反射神経が良い証拠です!<br>
            ・合図が出る前に押してしまうと、やり直しになります。<br>
            ・何回でも挑戦できます。自己ベストを目指そう!
          </div>
        </div>
        <button class="btn" id="start-btn">スタート</button>
        <div class="score-list" id="record-list"></div>
      `;
      // 記録表示
      updateRecords();
      document.getElementById('start-btn').onclick = startReflexTest;
    }

    // === 記録リスト表示 ===
    function updateRecords() {
      const listEl = document.getElementById('record-list');
      if (!listEl) return;
      if (records.length === 0) {
        listEl.textContent = "";
        return;
      }
      // 上位3件
      let list = records.slice(-3).reverse().map((t,i)=>
        `#${records.length-i} ${t} ミリ秒`
      ).join('<br>');
      listEl.innerHTML = `<b>直近の記録</b><br>${list}`;
    }

    // === ゲーム画面(テスト開始) ===
    function startReflexTest() {
      gameStarted = true;
      resultTime = null;
      document.getElementById('main-container').innerHTML = `
        <h1>🔴 反射神経テストゲーム 🔴</h1>
        <div class="reflex-area waiting" id="reflex-area">
          準備中...<br>色が変わるまで待ってください
        </div>
      `;
      // 待ち時間ランダム(1.5~3.5秒)
      let waitTime = 1500 + Math.random() * 2000;
      let area = document.getElementById('reflex-area');
      area.onclick = () => { // 早押し防止
        if (!gameStarted) return;
        area.className = 'reflex-area early';
        area.innerHTML = 'まだです!<br>合図が出てから押してね';
        clearTimeout(timeoutId);
        setTimeout(startReflexTest, 1300);
      };
      timeoutId = setTimeout(() => {
        // 合図!
        area.className = 'reflex-area ready';
        area.innerHTML = 'クリックして!';
        startTime = Date.now();
        area.onclick = () => {
          if (!gameStarted) return;
          let reaction = Date.now() - startTime;
          showResultScreen(reaction);
        };
      }, waitTime);
    }

    // === 結果画面 ===
    function showResultScreen(reaction) {
      gameStarted = false;
      resultTime = reaction;
      records.push(reaction);
      // 記録は上位10件に制限
      if (records.length > 10) records = records.slice(-10);
      document.getElementById('main-container').innerHTML = `
        <h1>🔴 反射神経テストゲーム 🔴</h1>
        <img src="reflex_test_game_title.png" class="title-img" alt="反射神経テストタイトル">
        <div class="message-box">
          あなたの反射速度は...<br>
          <span style="font-size:2em;color:#d50000;">${reaction} ミリ秒</span>
        </div>
        <button class="btn center-btn" id="back-title-btn">タイトル画面に戻る</button>
        <div class="score-list" id="record-list"></div>
      `;
      updateRecords();
      document.getElementById('back-title-btn').onclick = showTitleScreen;
    }

    // 初期表示
    showTitleScreen();
  </script>
</body>
</html>

アルゴリズムの流れ

手順処理内容
1showTitleScreen() でタイトル画面を描画し、「スタート」ボタンに開始処理を紐付け
2ボタン押下で startReflexTest() → 待機状態の表示と早押し防止を設定
3ランダム待機時間後にテストエリアを合図状態(緑)に変更し、クリック受付を開始
4クリック時刻から開始時刻を引いて反射時間を算出し、showResultScreen() へ遷移
5showResultScreen() で結果表示・記録保存・直近記録表示・タイトル戻りを設定
6タイトル画面に戻ると再度 showTitleScreen() で状態リセット

関数の詳細

関数名機能概要詳細説明
showTitleScreen()タイトル画面の描画・初期化ルール説明と「スタート」ボタン、直近記録リストを表示。タイマー解除と状態リセットを行う。
updateRecords()記録リストの更新・表示records 配列の直近3件を HTML にフォーマットし、タイトル/結果画面に反映。
startReflexTest()反射テスト開始テストエリアを「waiting」状態にし、ランダム時間後に合図状態(ready)に切り替える仕組みを設定。
showResultScreen(time)結果画面の描画・記録追加測定した反射時間を表示し、records に追加。直近10件に制限して管理。

改造のポイント

  • 多段階テスト:クリック後に複数回の測定をまとめて行うモードを追加し、平均値を算出して総合的な反射神経を評価。
  • ビジュアルカスタマイズ:合図時の色やフォント、メッセージ文言をテーマごとに切り替え可能にすれば飽きずに楽しめます。
  • 統計表示:反射時間のヒストグラムや折れ線グラフを表示し、視覚的に自己成長を把握できるようにする。
  • ソーシャルシェア:結果画面に「Twitterでシェア」ボタンを置き、スコアを気軽に共有できるようにすると広がりやすいです。
  • モバイル最適化:タップ判定範囲やフォントサイズを調整し、スマホでも快適にプレイできるようにしましょう。

アドバイス
最初はシンプルな測定機能に集中し、徐々に「ランキング機能」「ビジュアル演出」「多回数モード」などを追加すると、ユーザーの継続プレイを促進できます。データを蓄積して「成績推移グラフ」を実装すると、モチベーションがさらに向上します!