LoginSignup
2
2

More than 5 years have passed since last update.

JavaScriptでタイピングゲームを作ろう(ドットインストールから引用)

Last updated at Posted at 2019-04-22

ドットインストールを参考にしてます。
https://dotinstall.com/
※プレミアム会員のみ閲覧可能

完成イメージ

スクリーンショット 2019-04-22 16.51.42.png
                  ↓
スクリーンショット 2019-04-22 16.52.00.png
                  ↓
スクリーンショット 2019-04-22 16.52.04.png

実装したい要件の整理

  • 初期画面:
    • UI設定。
    • 画面をクリックするとタイマー起動+クイズが出現
  • クイズ画面:
    • タイマー稼働。
    • 正解数、誤答数の表示
    • ランダムにクイズを出題。
    • 正解すると次のクイズがランダム表示
  • 結果画面
    • 正解数等、成績を表示
    • リプレイの選択肢を表示
ソースコード(body要素のみ表示/CSSは省略)
<p id="target">Click To Start</p>
  <p class="info">
    Letter count: <span id="score">0</span>,
    Miss count: <span id="miss">0</span>
    Timer left: <span id="timer">0</span>
  </p>

<script type="text/javascript">
  'use strict';

{
  // 初期値の設定
  const words = [
    "apple",
    "sky",
    "blue",
    "middle",
    "set"
  ];

  // Math.floor() → 引数の結果の小数点以下を切り捨てる
  // Math.random()関数は、0以上、1未満の範囲で浮動小数点の擬似乱数を返す。
  let word;
  let loc;
  let score;
  let miss;
  // 3000ミリ秒と設定
  const timeLimit = 3 * 1000;
  // ゲーム開始時刻を保持
  let startTime;
  // ゲームが始まっているかどうか変数で
  let isPlaying = false;

  // 各要素の取得
  const target = document.getElementById('target');
  const scoreLabel = document.getElementById('score');
  const missLabel = document.getElementById('miss');
  const timerLabel = document.getElementById('timer');

  function updateTarget(){
    let placeholder = '';
    for (let i = 0; i < loc; i++) {
      placeholder += '_';
    }
    target.textContent = placeholder + word.substring(loc);
  }

  function showResult(){
    // 条件演算子を使用
    const accuracy = score + miss === 0 ? 0 : score / (score+miss) * 100;
    // テンプレートリテラルで、結果を表示させる
    alert(`${score} letters, ${miss} misses, ${accuracy.toFixed(2)}% accuracy!`)
  }

  function updateTimer(){
    // ゲーム開始時刻 + 制限時間 - 現在の時刻
    const timeLeft = startTime + timeLimit - Date.now();
    // 小数点以下を2桁まで表示
    timerLabel.textContent = (timeLeft / 1000).toFixed(2);

    // setTimeout関数を定義。10ミリ秒毎に、updateTimer関数を呼ぶ。
    const timeoutId = setTimeout(() => {
      updateTimer();
    }, 10);

    // 解除したいタイマのID。 IDはsetTimeout()の返値によって取得できる。
    if (timeLeft < 0) {
      isPlaying = false;
      clearTimeout(timeoutId);
      // alert処理を100ミリ秒後に遅らせる。
      setTimeout(() => {
         showResult();
      },100);

      timerLabel.textContent = "0.00";
      target.textContent = "Click to Replay" 
    }
  }

  window.addEventListener('click', () => {
    if(isPlaying === true){
      return;
    }
    isPlaying = true;

    loc = 0;
    score = 0;
    miss = 0;
    scoreLabel.textContent = score;
    missLabel.textContent = miss;
    word = words[Math.floor(Math.random() * words.length)];


    updateTarget();
    // 基準日から経過ミリ秒を計算
    startTime = Date.now();
    updateTimer();
  });

  // キーボードから入力された値を取得
  window.addEventListener('keyup', e => {
    if(isPlaying !== true){
      return;
    }
    if (e.key === word[loc]) {
      loc++;
      // locの数がwordの文字数を超えたタイミングで
      if(loc === word.length){
        word= words[Math.floor(Math.random() * words.length)];
        loc = 0;
      }
      score++;
      scoreLabel.textContent = score;
      // updateTarget関数を呼び出す
      updateTarget();
    } else {
      miss++;
      missLabel.textContent = miss;
    }
  });
}
</script>

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2