Search code examples
javascripthtmlreset

Rock paper scissors Vanilla JS - Does NOT reset classes when restart


there are a lot of questiosn about this here but can't seen to find one for vanilla js..

Well here goes. New class assigment : Rock paper scissors with vanilla js.

The game works in itself, the problem is when i want it to restart. It seems to rung through all the new event listeners i put ? And i just don´t see why it does that, i only click on one of the buttons but it operates as if i clicked on them all in a row.

I'm sure the problem is in the lasts functions (the win, tie and lose screen). But i am at a loss as to what is the problem here.

Here is the git rep of the project : [https://github.com/emma673r/rockpaperscissors][1]

and here is the code

const gameField = document.getElementById(`gamefield`);
const player = document.getElementById(`player1`);
const computer = document.getElementById(`player2`);

const lose = document.getElementById(`lose`);
const win = document.getElementById(`win`);
const tie = document.getElementById(`tie`);

const rock = document.querySelector(`.rock`);
const paper = document.querySelector(`.paper`);
const scissors = document.querySelector(`.scissors`);

//rock = 0, paper = 1, scissors = 2
let compChoice;
compChoice = Math.floor(Math.random() * 3);

//rock = 0, paper = 1, scissors = 2
let userChoice;

// DOM load - send to titleScreen
window.addEventListener("DOMContentLoaded", titleScreen);

// titleScreen
function titleScreen() {
  console.log(`titleScreen`);

  tie.classList = "hidden";
  win.classList = "hidden";
  lose.classList = "hidden";

//   compChoice = Math.floor(Math.random() * 3);
//   console.log(`compChoice is : ${compChoice}`);

  // event listener rock btn click startGame
  rock.addEventListener("click", shakeHandsRock);
  // event listener paper btn click startGame
  paper.addEventListener("click", shakeHandsPaper);
  // event listener scissors btn click startGame
  scissors.addEventListener("click", shakeHandsScissors);
}

function shakeHandsRock() {
  console.log(`shakeHandsRock`);

    compChoice = Math.floor(Math.random() * 3);
    console.log(`compChoice is : ${compChoice}`);

  player.classList.add("shake");
  computer.classList.add("shake");
  player.addEventListener("animationend", rockClicked);
}

function shakeHandsPaper() {
  console.log(`shakeHandsPaper`);

    compChoice = Math.floor(Math.random() * 3);
    console.log(`compChoice is : ${compChoice}`);

  player.classList.add("shake");
  computer.classList.add("shake");
  player.addEventListener("animationend", paperClicked);
}

function shakeHandsScissors() {
  console.log(`shakeHandsScissors`);

    compChoice = Math.floor(Math.random() * 3);
  console.log(`compChoice is : ${compChoice}`);

  player.classList.add("shake");
  computer.classList.add("shake");
  player.addEventListener("animationend", scissorsClicked);
}

function rockClicked() {
  console.log(`rockClicked`);
  userChoice = 0;

  player.classList = "player rock";
  computer.classList = "player";

  player.classList.remove("shake");
  computer.classList.remove("shake");
  //   rock vs rock = tie
  if (userChoice == compChoice) {
    // shake animation

    // show hands pngs
    computer.classList.add(`rock`);

    tieScreen();
  }
  //   rock vs paper = player lose
  else if (compChoice == 1) {
    // shake animation

    // show hands pngs
    computer.classList.add(`paper`);

    loseScreen();
  }
  //   rock vs scissors = player win
  else if (compChoice == 2) {
    // shake animation

    // show hands pngs
    computer.classList.add(`scissors`);

    winScreen();
  }
}

function paperClicked() {
  console.log(`paperClicked`);
  userChoice = 1;

  player.classList = "player paper";
  computer.classList = "player";

  player.classList.remove("shake");
  computer.classList.remove("shake");

  //   paper vs rock = win
  if (compChoice == 0) {
    // shake animation

    // show hands pngs
    computer.classList.add("rock");

    winScreen();
  }
  //   paper vs paper = tie
  else if (compChoice == userChoice) {
    // shake animation

    // show hands pngs
    computer.classList.add(`paper`);

    tieScreen();
  }
  //   paper vs scissors = lose
  else if (compChoice == 2) {
    // shake animation

    // show hands pngs
    computer.classList.add(`scissors`);

    loseScreen();
  }
}

function scissorsClicked() {
  console.log(`scissorsClicked`);
  userChoice = 2;

  player.classList = "player scissors";
  computer.classList = "player";

  player.classList.remove("shake");
  computer.classList.remove("shake");

  //   scissors vs rock = lose
  if (compChoice == 0) {
    // show hands pngs
    computer.classList.add(`rock`);

    loseScreen();
  }
  //   scissors vs paper = win
  else if (compChoice == 1) {
    // shake animation

    // show hands pngs
    computer.classList.add(`paper`);

    winScreen();
  }
  //   scissors vs scissors = tie
  else if (compChoice == userChoice) {
    // shake animation

    // show hands pngs
    computer.classList.add(`scissors`);

    tieScreen();
  }
}

// tieScreen
function tieScreen() {
  console.log(`tieScreen`);

  // display block tie div
  tie.classList = "";
  win.classList = "hidden";
  lose.classList = "hidden";

  rock.addEventListener("click", shakeHandsRock);
  paper.addEventListener("click", shakeHandsPaper);
  scissors.addEventListener("click", shakeHandsScissors);
}

// winScreen
function winScreen() {
  console.log(`winScreen`);

  // display block win div
  win.classList = "";
  tie.classList = "hidden";
  lose.classList = "hidden";

  rock.addEventListener("click", shakeHandsRock);
  paper.addEventListener("click", shakeHandsPaper);
  scissors.addEventListener("click", shakeHandsScissors);
}
// loseScreen
function loseScreen() {
  console.log(`loseScreen`);

  // display block lose screen
  lose.classList = "";
  win.classList = "hidden";
  tie.classList = "hidden";

  rock.addEventListener("click", shakeHandsRock);
  paper.addEventListener("click", shakeHandsPaper);
  scissors.addEventListener("click", shakeHandsScissors);
}
body {
  margin: 0;
  background-color: #444059;
  font-family: 'Luckiest Guy', cursive;
  color: #eee;
}

h1 {
  text-align: center;
  font-size: 8vw;
}

#gamefield {
  position: relative;
  overflow: hidden;
  display: flex;
  justify-content: space-between;
}

#player1 {
  --rot: 1;
}

#player2 {
  --rot: -1;
}

.player {
  transform: scale(var(--rot),1);
  width: 40vw;
  height: 40vw;
  background-size: 100%;
  background-image: url(hand_rock.png);
}

.player.rock {
  background-image: url(hand_rock.png);
}

.player.paper {
  background-image: url(hand_paper.png);
}

.player.scissors {
  background-image: url(hand_scissors.png);
}

.player.shake {
  background-image: url(hand_rock.png);
  transform-origin: left center;
  animation: shake 1.8s ease-in 1 forwards;
}

@keyframes shake {
  0% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
  }
  16% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
  }
  24% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
  }
  32% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
  }
  48% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
  }
  56% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
  }
  64% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
  }
  80% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
  }
  96% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
  }
  100% {
    transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
  }
}

#texts {
  position: absolute;
  width: 100%;
  margin-top: 10vw;
  pointer-events: none;
}

#texts h1 {
  color: #ffde53;
  text-shadow: 4px 4px 1px red, -4px -4px 1px red, 4px -4px 1px red, -4px 4px 1px red;
}

.hidden {
  display: none;
}

#buttons {
  display: flex;
  justify-content: space-around;
  max-width: 50vw;
}

#buttons.disabled button {
  filter: grayscale(100%) brightness(.75);
}

#buttons button {
  background-size: 100%;
  border-radius: 10vw;
  width: 10vw;
  height: 10vw;
  transition: filter .8s;
}

button.rock {
  background-image: url(button_rock.png);
}

button.paper {
  background-image: url(button_paper.png);
}

button.scissors {
  background-image: url(button_scissors.png);
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Rock, Paper, Scissors</title>
    <link href="https://fonts.googleapis.com/css?family=Luckiest+Guy&display=swap" rel="stylesheet" />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <h1>Rock, Paper, Scissors</h1>

    <div id="gamefield">
      <div id="player1" class="player"></div>
      <div id="player2" class="player"></div>
      <div id="texts">
        <div id="lose" class="hidden"><h1>You lose</h1></div>
        <div id="win" class="hidden"><h1>You win</h1></div>
        <div id="tie" class="hidden"><h1>It's a tie</h1></div>
      </div>
    </div>

    <div id="buttons">
      <button class="rock"></button>
      <button class="paper"></button>
      <button class="scissors"></button>
    </div>
    <script src="script.js
"></script>
  </body>
</html>

If you need the images, check the git rep, i don't seem to be allowed to post them here yet.

Thank you in advance, i've been stuck on this bug for a few hours now and even with a break i just dont see how i can fix it. I have tried many things but they don't work on the problem. [1]: https://github.com/emma673r/rockpaperscissors


Solution

  • In JavaScript, eventListeners don't go away after they trigger the first time. You have to manually remove an eventListener to stop it.

    The bug was that your rockClicked was getting called every time the player finished its animation, once the eventListener had been set up. So I added a line to remove the eventListener when rockClicked, paperClicked, and scissorsClicked were called.

    const gameField = document.getElementById(`gamefield`);
    const player = document.getElementById(`player1`);
    const computer = document.getElementById(`player2`);
    
    const lose = document.getElementById(`lose`);
    const win = document.getElementById(`win`);
    const tie = document.getElementById(`tie`);
    
    const rock = document.querySelector(`.rock`);
    const paper = document.querySelector(`.paper`);
    const scissors = document.querySelector(`.scissors`);
    
    // event listener rock btn click startGame
    rock.addEventListener("click", shakeHandsRock);
    // event listener paper btn click startGame
    paper.addEventListener("click", shakeHandsPaper);
    // event listener scissors btn click startGame
    scissors.addEventListener("click", shakeHandsScissors);
    
    //rock = 0, paper = 1, scissors = 2
    let compChoice;
    compChoice = Math.floor(Math.random() * 3);
    
    //rock = 0, paper = 1, scissors = 2
    let userChoice;
    
    // DOM load - send to titleScreen
    window.addEventListener("DOMContentLoaded", titleScreen);
    
    // titleScreen
    function titleScreen() {
      console.log(`titleScreen`);
    
      tie.classList = "hidden";
      win.classList = "hidden";
      lose.classList = "hidden";
    
    //   compChoice = Math.floor(Math.random() * 3);
    //   console.log(`compChoice is : ${compChoice}`);
    
    }
    
    function shakeHandsRock() {
      console.log(`shakeHandsRock`);
    
        compChoice = Math.floor(Math.random() * 3);
        console.log(`compChoice is : ${compChoice}`);
    
      player.classList.add("shake");
      computer.classList.add("shake");
      player.addEventListener("animationend", rockClicked);
    }
    
    function shakeHandsPaper() {
      console.log(`shakeHandsPaper`);
    
        compChoice = Math.floor(Math.random() * 3);
        console.log(`compChoice is : ${compChoice}`);
    
      player.classList.add("shake");
      computer.classList.add("shake");
      player.addEventListener("animationend", paperClicked);
    }
    
    function shakeHandsScissors() {
      console.log(`shakeHandsScissors`);
    
        compChoice = Math.floor(Math.random() * 3);
      console.log(`compChoice is : ${compChoice}`);
    
      player.classList.add("shake");
      computer.classList.add("shake");
      player.addEventListener("animationend", scissorsClicked);
    }
    
    function rockClicked() {
      player.removeEventListener("animationend", rockClicked);
      console.log(`rockClicked`);
      userChoice = 0;
    
      player.classList = "player rock";
      computer.classList = "player";
    
      player.classList.remove("shake");
      computer.classList.remove("shake");
      //   rock vs rock = tie
      if (userChoice == compChoice) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`rock`);
    
        tieScreen();
      }
      //   rock vs paper = player lose
      else if (compChoice == 1) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`paper`);
    
        loseScreen();
      }
      //   rock vs scissors = player win
      else if (compChoice == 2) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`scissors`);
    
        winScreen();
      }
    }
    
    function paperClicked() {
      player.removeEventListener("animationend", paperClicked);
      console.log(`paperClicked`);
      userChoice = 1;
    
      player.classList = "player paper";
      computer.classList = "player";
    
      player.classList.remove("shake");
      computer.classList.remove("shake");
    
      //   paper vs rock = win
      if (compChoice == 0) {
        // shake animation
    
        // show hands pngs
        computer.classList.add("rock");
    
        winScreen();
      }
      //   paper vs paper = tie
      else if (compChoice == userChoice) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`paper`);
    
        tieScreen();
      }
      //   paper vs scissors = lose
      else if (compChoice == 2) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`scissors`);
    
        loseScreen();
      }
    }
    
    function scissorsClicked() {
      player.removeEventListener("animationend", scissorsClicked);
      console.log(`scissorsClicked`);
      userChoice = 2;
    
      player.classList = "player scissors";
      computer.classList = "player";
    
      player.classList.remove("shake");
      computer.classList.remove("shake");
    
      //   scissors vs rock = lose
      if (compChoice == 0) {
        // show hands pngs
        computer.classList.add(`rock`);
    
        loseScreen();
      }
      //   scissors vs paper = win
      else if (compChoice == 1) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`paper`);
    
        winScreen();
      }
      //   scissors vs scissors = tie
      else if (compChoice == userChoice) {
        // shake animation
    
        // show hands pngs
        computer.classList.add(`scissors`);
    
        tieScreen();
      }
    }
    
    // tieScreen
    function tieScreen() {
      console.log(`tieScreen`);
    
      // display block tie div
      tie.classList = "";
      win.classList = "hidden";
      lose.classList = "hidden";
    }
    
    // winScreen
    function winScreen() {
      console.log(`winScreen`);
    
      // display block win div
      win.classList = "";
      tie.classList = "hidden";
      lose.classList = "hidden";
    }
    // loseScreen
    function loseScreen() {
      console.log(`loseScreen`);
    
      // display block lose screen
      lose.classList = "";
      win.classList = "hidden";
      tie.classList = "hidden";
    }
    body {
      margin: 0;
      background-color: #444059;
      font-family: 'Luckiest Guy', cursive;
      color: #eee;
    }
    
    h1 {
      text-align: center;
      font-size: 8vw;
    }
    
    #gamefield {
      position: relative;
      overflow: hidden;
      display: flex;
      justify-content: space-between;
    }
    
    #player1 {
      --rot: 1;
    }
    
    #player2 {
      --rot: -1;
    }
    
    .player {
      transform: scale(var(--rot),1);
      width: 40vw;
      height: 40vw;
      background-size: 100%;
      background-image: url(hand_rock.png);
    }
    
    .player.rock {
      background-image: url(hand_rock.png);
    }
    
    .player.paper {
      background-image: url(hand_paper.png);
    }
    
    .player.scissors {
      background-image: url(hand_scissors.png);
    }
    
    .player.shake {
      background-image: url(hand_rock.png);
      transform-origin: left center;
      animation: shake 1.8s ease-in 1 forwards;
    }
    
    @keyframes shake {
      0% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
      }
      16% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
      }
      24% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
      }
      32% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
      }
      48% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
      }
      56% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
      }
      64% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
      }
      80% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(-40deg);
      }
      96% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(5deg);
      }
      100% {
        transform: scale(var(--rot),1) translateX(calc((var(--rot) - 1) * 50%)) rotate(0deg);
      }
    }
    
    #texts {
      position: absolute;
      width: 100%;
      margin-top: 10vw;
      pointer-events: none;
    }
    
    #texts h1 {
      color: #ffde53;
      text-shadow: 4px 4px 1px red, -4px -4px 1px red, 4px -4px 1px red, -4px 4px 1px red;
    }
    
    .hidden {
      display: none;
    }
    
    #buttons {
      display: flex;
      justify-content: space-around;
      max-width: 50vw;
    }
    
    #buttons.disabled button {
      filter: grayscale(100%) brightness(.75);
    }
    
    #buttons button {
      background-size: 100%;
      border-radius: 10vw;
      width: 10vw;
      height: 10vw;
      transition: filter .8s;
    }
    
    button.rock {
      background-image: url(button_rock.png);
    }
    
    button.paper {
      background-image: url(button_paper.png);
    }
    
    button.scissors {
      background-image: url(button_scissors.png);
    }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Rock, Paper, Scissors</title>
        <link href="https://fonts.googleapis.com/css?family=Luckiest+Guy&display=swap" rel="stylesheet" />
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <h1>Rock, Paper, Scissors</h1>
    
        <div id="gamefield">
          <div id="player1" class="player"></div>
          <div id="player2" class="player"></div>
          <div id="texts">
            <div id="lose" class="hidden"><h1>You lose</h1></div>
            <div id="win" class="hidden"><h1>You win</h1></div>
            <div id="tie" class="hidden"><h1>It's a tie</h1></div>
          </div>
        </div>
    
        <div id="buttons">
          <button class="rock"></button>
          <button class="paper"></button>
          <button class="scissors"></button>
        </div>
        <script src="script.js
    "></script>
      </body>
    </html>