Javascript game project randomly stops working

Viewed 53

I'm currently making a speed typing game which when testing in the browser often works great (for what I have so far) but then sometimes it just randomly stops working (timer won't countdown, no functions will trigger even though they're appearing in the console). I'm stumped at what this can be as this happens even when I don't change any code from the working state. Could this just be from poorly optimized code?

HTML:

<html lang="en">
  <head>
    
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <link rel="stylesheet" href="/styles/styles.css"/>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
    

    <title>Lorem Ipsum!</title>
  </head>
  <body>
    <main>
      <section class="game-container">
        <header class="game-header">
        <button class="play-button btn btn-success">Play</button>
        <button class="pause-button btn btn-warning">Pause</button>
        <button class="quit-game btn btn-danger" id="quitButton">Quit</button> 
          <div class="player-score-container">
          <h3 class="player-name">Player Score</h2>
          <span id="playerScore" class="player-score">0</span>
        </div>
        </header>

        
          <div class="stats-container">
            <h3>Words Remaining</h3>
            <span class="words-remaining">12</span>
            <h3>Time Remaining</h3>
            <p id="timer">0</p>
          </div>
          
          <div class=timer-bar-container>
          <div class="timer-bar" id="timerBar"></div>
        </div>
          
          <section class="gameplay-text-container">
            <div  class="quote-display" id="quoteDisplay"></div>
            <textarea class="quote-input" id="textInput"  autofocus placeholder="type to begin!"></textarea>
            </section>
        </section>
 
    </main>
    <script
    src="https://code.jquery.com/jquery-3.6.0.slim.js"
    integrity="sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY="
    crossorigin="anonymous"></script>
    
    

    <script src="https://dummyjs.com/js" ></script>

    <script src="/script/scripts.js" ></script> 
  </body>
</html>

Javascript:


const game = {
  title: "Lorem Ipsum",
  isRunning: false,
  //timing
  timeLeft: 30,
  timerId: 10000,
  intervalDuration: 100,
  playerScore: $('#playerScore'),
  incrementScore: 0,
  
  //elements
  timerprogressBar: $("#timerBar"),
  timerClock: $("#timer"),
  playertextInput: $(".quote-input"),
  challengerText: $("#quoteDisplay"),
  incrementText: 1,
  incrementScore: 0,
  quitGameButton: $("#quitButton"),

  //add leading 0 to number 9
  
  
  
 
  
  countdown: function() {
    game.timerId = setInterval(game.intervalDuration);
    if (game.timeLeft == -1) {
      clearTimeout(game.timerId);
    } else {
      game.timerClock.text(game.timeLeft);
      
      game.timeLeft--;
      
    }

  },


  //create countdown timer
  
  //add time to timer

  //reduce time from timer

  //freeze input with wrong input

  //change progress bar display property

  //reset everything

  updateText: function () {
    let increaseWords = game.incrementText;
    $("#textInput").val("");
    game.challengerText = $("#quoteDisplay").dummy(increaseWords);
    game.challengerText = $("#quoteDisplay").text();
    game.addScore();  
  },

 
    

  addScore: function() {
     let increaseScore = game.incrementScore;
      increaseScore++;
     
  },


  //event listeners for: keyboard input, play button, pause button, end game
 
  //match input text to displayed text on page
  spellCheck: function () {
   
    let textEntered = game.playertextInput.val();
    let challengerTextMatch = game.challengerText.substr(0, textEntered.length);
  
    if (textEntered === game.challengerText) {
      
     game.updateText();
    } else {
      if (textEntered == challengerTextMatch) {
        game.playertextInput.addClass("correct");
        game.playertextInput.removeClass("incorrect");
      } else {
        if (textEntered != challengerTextMatch) {
          game.playertextInput.removeClass("correct");
          game.playertextInput.addClass("incorrect");
        }
      }
    }
    
  },

  // start timer
  startGame: function () {
    let textEnteredLength = game.playertextInput.val().length;
    
    if (textEnteredLength >= 1) {
      game.spellCheck();
      game.isRunning = true;
    }
    if (game.isRunning === true) {
      game.countdown();
    }
  },

 
};

// $( document ).ready(function() {
//   game.challengerText = $( "#quoteDisplay").text();

// });

$(document).ready(function () {
  $("input[type='text'], textarea").attr("spellcheck", false);
  //removes autocorrect underline in browser
});
game.updateText()

I'm using dummy.js to print in lorem ipsum into the text field but I don't think that's the issue because game.challengerText shows the correct presented string in the console even when not working. The other strange issue I have is that it only works when devtools is open in Chrome and not at all in firefox even with devtools open. I appreciate your help in advance!

1 Answers

I think the problem happend because the countdown function.

I don't know if the function setInterval without first argument event working correctly, because setInterval first argument is the function and then you pass the period.

And the second maybe you want use setTimeout and not setInterval because if you want call countdown function every 100ms then it will call it multiple times when the function start again... because every call of countdown create new interval by setInterval... then it will eventuely freeze like you write.

But if you move this block of code (remove it from here)

game.timerId = setInterval(game.intervalDuration);

To there

if (game.isRunning === true) {
  game.countdown();
}

Like this

if (game.isRunning === true) {
  game.timerId = setInterval(function(){ game.countdown(); }, game.intervalDuration);
}

It can work normally.

More help about setInterval can be found here https://developer.mozilla.org/en-US/docs/Web/API/setInterval

Full code: https://codesandbox.io/embed/shy-sky-pwh3p?fontsize=14&hidenavigation=1&theme=dark

Related