Button disappearing

Viewed 88

I am making a game, using HTML Canvas, in which the user has to find and then click on a squirrel. The button (which is outside of the canvas) is used to reset the score and start the game again. However, this button disappears after the user clicks inside the canvas for the first time.

Why is the restart button disappearing after the first click inside the canvas? and how to fix it?

// jshint esversion: 6

window.onload = function () {
    var canvas = document.getElementById("canvas");
    /** @type {CanvasRenderingContext2D} */
    var ctx = canvas.getContext("2d");

    // images
    var squirrel_img = document.getElementById("squirrel-img");
    var trees_img = document.getElementById("tree-img");

    var scoreboard_div = document.getElementById("scoreboard"); // scoreboard
    var score = 0; // score

    // styles
    canvas.width = window.innerWidth * 0.75;
    canvas.height = window.innerHeight;
    canvas.style.border = "15px ridge red";
    canvas.style.borderRadius = "5px";

    ctx.drawImage(trees_img, 0, 0, canvas.width, canvas.height); // background image

    function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // clear everything
        ctx.drawImage(trees_img, 0, 0, canvas.width, canvas.height); // draw background image again
    }

    var currentSquirrel = 0; // to keep track of which squirrel is to be shown

    // all squirrels [x, y, width, height, alpha]
    var squirrel1 = [10, 10, 50, 50, 1];
    var squirrel2 = [canvas.width * 0.85, canvas.height * 0.75, 50, 50, 0.7];
    var squirrel3 = [canvas.width * 0.5, canvas.height * 0.70, 50, 50, 0.6];
    var squirrel4 = [canvas.width * 0.5, canvas.height * 0.15, 50, 50, 0.5];
    var squirrel5 = [canvas.width * 0.82, canvas.height * 0.40, 50, 50, 0.4];

    // an array with all of the squirrels in it
    var allSquirrels = [squirrel1, squirrel2, squirrel3, squirrel4, squirrel5];
    var squirrel = allSquirrels[currentSquirrel]; // using the currentSquirrel variable as an index to see the properties of the current squirrel
    ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]); // index 0 is x pos, 1 is y pos, 2 is width and 3 is height

    // what happens on mouse click
    function mouseClick(squirrels) { // allSquirrels array will be passed as the 'squirrels' argument in this function
        console.log("Mouse has clicked!");

        // co-ordinates of the mouse click
        var click_x = event.pageX;
        var click_y = event.pageY;
        console.log(click_x, click_y);
        // co-ordinates of the canvas
        var canvascoor = canvas.getBoundingClientRect();
        // adding scrollX and scrollY to get the real position of the canvas, accounting for how much has been scrolled
        var canvasX = canvascoor.x + scrollX;
        var canvasY = canvascoor.y + scrollY;
        var canvasWidth = canvascoor.width;
        var canvasHeight = canvascoor.height;
        console.log(canvasX, canvasY);

        // co-ordinates of the squirrel - adding canvas coordinates to it to get the position of the squirrel relative to the screen and not just to the canvas
        var squirrel_x = canvasX + squirrel[0];
        var squirrel_y = canvasY + squirrel[1];
        var squirrel_width = squirrel[2];
        var squirrel_height = squirrel[3];
        // check if the click was within the squirrel's boundary
        if ((click_x >= squirrel_x && click_x <= squirrel_x + squirrel_width) && (click_y >= squirrel_y && click_y <= (squirrel_y + squirrel_height))) {
            score++;
            scoreboard_div.innerText = `Score: ${score}/5`;
            clearCanvas();

            // add green background and then remove it after 300 miliseconds
            document.getElementsByTagName("body")[0].classList.add("green");
            setTimeout(function () {
                document.getElementsByTagName("body")[0].classList.remove("green");
            }, 300);

            // the allSquirrels array's last index is 4 (as there are 5 items in it) so if the currentSquirrel is equal to or less than 3 (3 is the second-last squirrel), then continue the game as usual
            if (currentSquirrel <= 3) {
                currentSquirrel++; // next squirrel
                squirrel = allSquirrels[currentSquirrel];
                ctx.globalAlpha = squirrel[4];
                ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
                ctx.globalAlpha = 1;
            } 
            // if the currentSquirrel is the last one (4th index) or more, then stop the game
            else if (currentSquirrel >= 4) {
                currentSquirrel = 5;
                alert(`You have completed the game! You got ${score}/5.`);
                document.getElementsByTagName("body")[0].removeEventListener("click", mouseClickRun);
            }
        } 
        // if the click wasn't on the squirrel but on the canvas
        else if (event.target.id === "canvas") {
            scoreboard_div.innerText = `Score: ${score}/5`;
            clearCanvas();
            // add red background and then remove it after 300 miliseconds
            document.getElementsByTagName("body")[0].classList.add("red");
            setTimeout(function () {
                document.getElementsByTagName("body")[0].classList.remove("red");
            }, 300);

            // the allSquirrels array's last index is 4 (as there are 5 items in it) so if the currentSquirrel is equal to or less than 3 (3 is the second-last squirrel), then continue the game as usual
            if (currentSquirrel <= 3) {
                currentSquirrel++;
                squirrel = allSquirrels[currentSquirrel];
                ctx.globalAlpha = squirrel[4];
                ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
                ctx.globalAlpha = 1;
            } 
            // if the currentSquirrel is the last one (4th index) or more, then stop the game
            else if (currentSquirrel >= 4) {
                currentSquirrel = 5;
                console.log(currentSquirrel);
                alert(`You have completed the game! You got ${score}/5.`);
                document.getElementsByTagName("body")[0].removeEventListener("click", mouseClickRun);
            }
        }
    }

    // restart button
    var restart_btn = document.getElementById("restart-btn");
    restart_btn.addEventListener("click", () => {
        // if the squirrel is more than the last index number in the allSquirrels array, then restart the game 
        if (currentSquirrel >= 5) {
            currentSquirrel = 0;
            console.log(currentSquirrel);
            score = 0;
            scoreboard_div.innerText = `Score: ${score}/5`;
            var allSquirrels = [squirrel1, squirrel2, squirrel3, squirrel4, squirrel5];
            var squirrel = allSquirrels[currentSquirrel];
            ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
            document.getElementsByTagName("body")[0].addEventListener("click", mouseClickRun);
        } else {
            alert("The game is already running." + currentSquirrel);
        }
    });

    function mouseClickRun() {
        mouseClick(allSquirrels);
    }

    /* When the body is clicked, run the mouseClickRun function to:
    check if the click was on the squirrel, if not then on the canvas
    */
    document.getElementsByTagName("body")[0].addEventListener("click", mouseClickRun);
};
/* Import Vag Rounded and Merriweather font */
@import url("https://aaditya-baduni.github.io/vag-rounded-font.css");
@import url("https://fonts.googleapis.com/css2?family=Merriweather:wght@300;400&display=swap");

* {
    color: black;
}

body {
    background-color: rgb(31, 42, 53);
}

header {
    padding: 0.5%;
    border-bottom: 2px solid white;
    margin-bottom: 3%;
}

header > a {
    position: absolute;
}

#logo {
    border-radius: 2.5px;
}

#website-name{
    font-family: VagRounded, sans-serif;
    font-size: 1.8rem;
    font-weight: 700;
    letter-spacing: 1px;
    color: rgb(229, 255, 0);
}
#website-name:hover {
    color: rgb(200, 200, 0);
}

#title {
    text-align: center;
    font-family: 'Merriweather', serif;
    margin-top: 0.5%;
    font-size: 2.5rem;
}

#title-description {
    text-align: center;
    margin-top: 1%;
}

/* Score board */
#scoreboard {
    width: 25%;
    background-color: white;
    color: black;

    text-align: center;
    font-family: 'Merriweather', serif;
    font-size: 2rem;
    border-radius: 5px;
    position: sticky;
    position: -webkit-sticky;
    top: 0;

    margin-bottom: 3%;
    margin-right: auto;
    margin-left: auto;
}

canvas:hover {
    cursor: pointer;
}

/* Background color changes according to user score */
.green {
    background-color: green;
}
.red {
    background-color: red;
}

/* Custom Scrollbar */
::-webkit-scrollbar {
    width: 5px;
}
::-webkit-scrollbar-thumb {
    background-color: rgb(150, 150, 150);
    border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
    background-color: rgb(100, 100, 100);
}

/* Images shouldnt be displayed */
#squirrel-img, #tree-img {
    display: none;
}

/* Different screen sizes optimization */
@media (max-width: 960px) {
    header > a {
        position: static;
    }
}
@media (max-width: 780px) {
    #title-description {
        line-height: 150%;
    }
}
<!DOCTYPE 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">
    <title>Find the Squirrel! | Aaditya's Website</title>
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
    <link rel="icon" href="https://aaditya-baduni.github.io/logo.png">
</head>

<body>
    <header>
        <a href="https://aaditya-baduni.github.io/games/" class="navbar-brand">
            <img src="https://aaditya-baduni.github.io/logo.png" alt="logo" id="logo">
            <span id="website-name">Aaditya's Games</span>
        </a>

        <h1 id="title">Find the Squirrel!</h1>
        <p id="title-description">
            There is a squirrel hiding in between those branches! Click on it and you will score points! <br>
            As soon as you click somewhere, a new squirrel will appear! There will be only 5 squirrels.
        </p>
    </header>

    <!-- Scoreboard -->
    <div id="scoreboard">
        Score: 0/5
        <input type="button" class="btn btn-success" id="restart-btn" value="Restart">
    </div>

    <!-- Center align the canvas -->
    <p style="text-align: center;">
        <canvas id="canvas"></canvas>
    </p>
    <!-- Squirrel and tree images - hidden (using CSS) and displayed only on the canvas -->
    <img src="https://aaditya-baduni.github.io/games/find-the-squirrel-2-canvas/squirrel.png" alt="Squirrel" id="squirrel-img">
    <img src="https://aaditya-baduni.github.io/games/find-the-squirrel-2-canvas/trees.jpg" alt="Trees-background" id="tree-img">

    <!-- Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj"
        crossorigin="anonymous"></script>
</body>

</html>

1 Answers

It is because you are completely replacing the scoreboard div inner text with a new score, which removes the button after 1st update

<div id="scoreboard">
    Score: 0/5
    <input type="button" class="btn btn-success" id="restart-btn" value="Restart">
</div>

....

var scoreboard_div = document.getElementById("scoreboard"); // scoreboard div

Problem is here and all occurences of this code, below:

scoreboard_div.innerText = `Score: ${score}/5`;

Solution

A slight change will help. (Added working code as well, you can run and check, please check CSS as well)

  1. Scoreboard HTML: Add a span for the score like
<div id="scoreboard">
  <span id='scoreCounter'>Score: 0/5 </span>
  <input type="button" class="btn btn-success" id="restart-btn" value="Restart">
</div>

2 .Then instead of targeting your whole div, just target this span: (I haven't changed the variable name, please do it if you like)

var scoreboard_div = document.getElementById("scoreCounter"); // scoreboard

Working code below

// jshint esversion: 6

window.onload = function() {
  var canvas = document.getElementById("canvas");
  /** @type {CanvasRenderingContext2D} */
  var ctx = canvas.getContext("2d");

  // images
  var squirrel_img = document.getElementById("squirrel-img");
  var trees_img = document.getElementById("tree-img");

  var scoreboard_div = document.getElementById("scoreCounter"); // scoreboard
  var score = 0; // score

  // styles
  canvas.width = window.innerWidth * 0.75;
  canvas.height = window.innerHeight;
  canvas.style.border = "15px ridge red";
  canvas.style.borderRadius = "5px";

  ctx.drawImage(trees_img, 0, 0, canvas.width, canvas.height); // background image

  function clearCanvas() {
    ctx.clearRect(0, 0, canvas.width, canvas.height); // clear everything
    ctx.drawImage(trees_img, 0, 0, canvas.width, canvas.height); // draw background image again
  }

  var currentSquirrel = 0; // to keep track of which squirrel is to be shown

  // all squirrels [x, y, width, height, alpha]
  var squirrel1 = [10, 10, 50, 50, 1];
  var squirrel2 = [canvas.width * 0.85, canvas.height * 0.75, 50, 50, 0.7];
  var squirrel3 = [canvas.width * 0.5, canvas.height * 0.70, 50, 50, 0.6];
  var squirrel4 = [canvas.width * 0.5, canvas.height * 0.15, 50, 50, 0.5];
  var squirrel5 = [canvas.width * 0.82, canvas.height * 0.40, 50, 50, 0.4];

  // an array with all of the squirrels in it
  var allSquirrels = [squirrel1, squirrel2, squirrel3, squirrel4, squirrel5];
  var squirrel = allSquirrels[currentSquirrel]; // using the currentSquirrel variable as an index to see the properties of the current squirrel
  ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]); // index 0 is x pos, 1 is y pos, 2 is width and 3 is height

  // what happens on mouse click
  function mouseClick(squirrels) { // allSquirrels array will be passed as the 'squirrels' argument in this function
    console.log("Mouse has clicked!");

    // co-ordinates of the mouse click
    var click_x = event.pageX;
    var click_y = event.pageY;
    console.log(click_x, click_y);
    // co-ordinates of the canvas
    var canvascoor = canvas.getBoundingClientRect();
    // adding scrollX and scrollY to get the real position of the canvas, accounting for how much has been scrolled
    var canvasX = canvascoor.x + scrollX;
    var canvasY = canvascoor.y + scrollY;
    var canvasWidth = canvascoor.width;
    var canvasHeight = canvascoor.height;
    console.log(canvasX, canvasY);

    // co-ordinates of the squirrel - adding canvas coordinates to it to get the position of the squirrel relative to the screen and not just to the canvas
    var squirrel_x = canvasX + squirrel[0];
    var squirrel_y = canvasY + squirrel[1];
    var squirrel_width = squirrel[2];
    var squirrel_height = squirrel[3];
    // check if the click was within the squirrel's boundary
    if ((click_x >= squirrel_x && click_x <= squirrel_x + squirrel_width) && (click_y >= squirrel_y && click_y <= (squirrel_y + squirrel_height))) {
      score++;
      scoreboard_div.innerText = `Score: ${score}/5`;
      clearCanvas();

      // add green background and then remove it after 300 miliseconds
      document.getElementsByTagName("body")[0].classList.add("green");
      setTimeout(function() {
        document.getElementsByTagName("body")[0].classList.remove("green");
      }, 300);

      // the allSquirrels array's last index is 4 (as there are 5 items in it) so if the currentSquirrel is equal to or less than 3 (3 is the second-last squirrel), then continue the game as usual
      if (currentSquirrel <= 3) {
        currentSquirrel++; // next squirrel
        squirrel = allSquirrels[currentSquirrel];
        ctx.globalAlpha = squirrel[4];
        ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
        ctx.globalAlpha = 1;
      }
      // if the currentSquirrel is the last one (4th index) or more, then stop the game
      else if (currentSquirrel >= 4) {
        currentSquirrel = 5;
        alert(`You have completed the game! You got ${score}/5.`);
        document.getElementsByTagName("body")[0].removeEventListener("click", mouseClickRun);
      }
    }
    // if the click wasn't on the squirrel but on the canvas
    else if (event.target.id === "canvas") {
      scoreboard_div.innerText = `Score: ${score}/5`;
      clearCanvas();
      // add red background and then remove it after 300 miliseconds
      document.getElementsByTagName("body")[0].classList.add("red");
      setTimeout(function() {
        document.getElementsByTagName("body")[0].classList.remove("red");
      }, 300);

      // the allSquirrels array's last index is 4 (as there are 5 items in it) so if the currentSquirrel is equal to or less than 3 (3 is the second-last squirrel), then continue the game as usual
      if (currentSquirrel <= 3) {
        currentSquirrel++;
        squirrel = allSquirrels[currentSquirrel];
        ctx.globalAlpha = squirrel[4];
        ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
        ctx.globalAlpha = 1;
      }
      // if the currentSquirrel is the last one (4th index) or more, then stop the game
      else if (currentSquirrel >= 4) {
        currentSquirrel = 5;
        console.log(currentSquirrel);
        alert(`You have completed the game! You got ${score}/5.`);
        document.getElementsByTagName("body")[0].removeEventListener("click", mouseClickRun);
      }
    }
  }

  // restart button
  var restart_btn = document.getElementById("restart-btn");
  restart_btn.addEventListener("click", () => {
    // if the squirrel is more than the last index number in the allSquirrels array, then restart the game 
    if (currentSquirrel >= 5) {
      currentSquirrel = 0;
      console.log(currentSquirrel);
      score = 0;
      scoreboard_div.innerText = `Score: ${score}/5`;
      var allSquirrels = [squirrel1, squirrel2, squirrel3, squirrel4, squirrel5];
      var squirrel = allSquirrels[currentSquirrel];
      ctx.drawImage(squirrel_img, squirrel[0], squirrel[1], squirrel[2], squirrel[3]);
      document.getElementsByTagName("body")[0].addEventListener("click", mouseClickRun);
    } else {
      alert("The game is already running." + currentSquirrel);
    }
  });

  function mouseClickRun() {
    mouseClick(allSquirrels);
  }

  /* When the body is clicked, run the mouseClickRun function to:
  check if the click was on the squirrel, if not then on the canvas
  */
  document.getElementsByTagName("body")[0].addEventListener("click", mouseClickRun);
};
/* Import Vag Rounded and Merriweather font */

@import url("https://aaditya-baduni.github.io/vag-rounded-font.css");
@import url("https://fonts.googleapis.com/css2?family=Merriweather:wght@300;400&display=swap");
* {
  color: white;
}

body {
  background-color: rgb(31, 42, 53);
}

header {
  padding: 0.5%;
  border-bottom: 2px solid white;
  margin-bottom: 3%;
}

header>a {
  position: absolute;
}

#logo {
  border-radius: 2.5px;
}

#website-name {
  font-family: VagRounded, sans-serif;
  font-size: 1.8rem;
  font-weight: 700;
  letter-spacing: 1px;
  color: rgb(229, 255, 0);
}

#website-name:hover {
  color: rgb(200, 200, 0);
}

#title {
  text-align: center;
  font-family: 'Merriweather', serif;
  margin-top: 0.5%;
  font-size: 2.5rem;
}

#title-description {
  text-align: center;
  margin-top: 1%;
}


/* Score board */

#scoreboard,
#scoreCounter {
  width: 25%;
  background-color: white;
  color: black;
  text-align: center;
  font-family: 'Merriweather', serif;
  font-size: 2rem;
  border-radius: 5px;
  position: sticky;
  position: -webkit-sticky;
  top: 0;
  margin-bottom: 3%;
  margin-right: auto;
  margin-left: auto;
}

canvas:hover {
  cursor: pointer;
}


/* Background color changes according to user score */

.green {
  background-color: green;
}

.red {
  background-color: red;
}


/* Custom Scrollbar */

::-webkit-scrollbar {
  width: 5px;
}

::-webkit-scrollbar-thumb {
  background-color: rgb(150, 150, 150);
  border-radius: 10px;
}

::-webkit-scrollbar-thumb:hover {
  background-color: rgb(100, 100, 100);
}


/* Images shouldnt be displayed */

#squirrel-img,
#tree-img {
  display: none;
}


/* Different screen sizes optimization */

@media (max-width: 960px) {
  header>a {
    position: static;
  }
}

@media (max-width: 780px) {
  #title-description {
    line-height: 150%;
  }
}
<!DOCTYPE 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">
  <title>Find the Squirrel! | Aaditya's Website</title>
  <!-- Bootstrap -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
  <link rel="icon" href="https://aaditya-baduni.github.io/logo.png">
</head>

<body>
  <header>
    <a href="https://aaditya-baduni.github.io/games/" class="navbar-brand">
      <img src="https://aaditya-baduni.github.io/logo.png" alt="logo" id="logo">
      <span id="website-name">Aaditya's Games</span>
    </a>

    <h1 id="title">Find the Squirrel!</h1>
    <p id="title-description">
      There is a squirrel hiding in between those branches! Click on it and you will score points! <br> As soon as you click somewhere, a new squirrel will appear! There will be only 5 squirrels.
    </p>
  </header>

  <!-- Scoreboard -->
  <div id="scoreboard">
    <span id='scoreCounter'>Score: 0/5 </span>
    <input type="button" class="btn btn-success" id="restart-btn" value="Restart">
  </div>

  <!-- Center align the canvas -->
  <p style="text-align: center;">
    <canvas id="canvas"></canvas>
  </p>
  <!-- Squirrel and tree images - hidden (using CSS) and displayed only on the canvas -->
  <img src="https://aaditya-baduni.github.io/games/find-the-squirrel-2-canvas/squirrel.png" alt="Squirrel" id="squirrel-img">
  <img src="https://aaditya-baduni.github.io/games/find-the-squirrel-2-canvas/trees.jpg" alt="Trees-background" id="tree-img">

  <!-- Bootstrap JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>
</body>

</html>

Related