Need a timer or delay function for a small card game

Viewed 233

I made a game in JavaScript and it seems to run pretty well. The rules are: There are 2 players who take turns. Draw cards to get points. You can draw multiple cards per turn. You don't get points until you press the End Turn button. If you draw a 2, 5, or 9 then you lose all points for that turn.

Everything works, however, when you draw a 2, 5, or 9 the turn changes before you even get to see the card. So you wouldn't even know if you drew that card.

  • I want to add a timer or delay function so that when you draw a 2, 5, or 9 it displays that card for a second or two.
  • And also I want to disable any clicking so you don't accidentally click for the next player.

Here's the link to the page: https://tneilson08.github.io/cardgame/

var scores, roundScore, activePlayer, gamePlaying;
gamePlaying = true;
init();

// Create the deck
const deck = ["2C", "2S", "2H", "2D", "3C", "3S", "3H", "3D", "4C", "4S", "4H", "4D", "5C", "5S", "5H", "5D", "6C", "6S", "6H", "6D", "7C", "7S", "7H", "7D", "8C", "8S", "8H", "8D", "9C", "9S", "9H", "9D", "10C", "10S", "10H", "10D", "JC", "JS", "JH", "JD", "QC", "QS", "QH", "QD", "KC", "KS", "KH", "KD", "AC", "AS", "AH", "AD"];
// const deck = ["two-club", "two-spade", "two-heart", "two-dia", "three-club", "three-spade", "three-heart", "three-dia"];
// Shuffle the deck
function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
}

shuffleArray(deck);

// Draw cards
function drawCard() {
  if (gamePlaying) {
    // 1. Draw from the deck and remove with shift()
    var card = deck.shift();

    // 2. Display the card
    var cardDOM = document.querySelector('.card');
    cardDOM.style.display = 'block'; // card becomes visible
    cardDOM.src = 'img/' + card + '.png'; // determines card drawn

    // 3. Determine card value
    if (card == "2C" || card == "2S" || card == "2H" || card == "2D") {
      card = 2;
    } else if (card == "3C" || card == "3S" || card == "3H" || card == "3D") {
      card = 3;
    } else if (card == "4C" || card == "4S" || card == "4H" || card == "4D") {
      card = 4;
    } else if (card == "5C" || card == "5S" || card == "5H" || card == "5D") {
      card = 5;
    } else if (card == "6C" || card == "6S" || card == "6H" || card == "6D") {
      card = 6;
    } else if (card == "7C" || card == "7S" || card == "7H" || card == "7D") {
      card = 7;
    } else if (card == "8C" || card == "8S" || card == "8H" || card == "8D") {
      card = 8;
    } else if (card == "9C" || card == "9C" || card == "9H" || card == "9D") {
      card = 9;
    } else {
      card = 10;
    }

    // 4. Update the round score IF the card drawn was NOT a 4 or a 9
    if (card !== 2 && card !== 5 && card !== 9) {
      // add score
      roundScore += card;
      document.querySelector('#current-' + activePlayer).textContent = roundScore;
    } else {
      // next player
      nextPlayer();
    }

    // if (card === 5) {
    //   // add score
    //   setTimeout(nextPlayer, 2000);
    // }
    //
    // if (card === 9) {
    //   // add score
    //   setTimeout(nextPlayer, 2000);
    // }

    // 5. If deck array runs out, replace all cards in deck ///MAYBE CHANGE THIS SO GAME ENDS AND PLAYER WITH HIGHEST DECK WINS
    if (deck.length === 0) {
      deck.push("2C", "2S", "2H", "2D", "3C", "3S", "3H", "3D", "4C", "4S", "4H", "4D", "5C", "5S", "5H", "5D", "6C", "6S", "6H", "6D", "7C", "7S", "7H", "7D", "8C", "8S", "8H", "8D", "9C", "9S", "9H", "9D", "10C", "10S", "10H", "10D", "JC", "JS", "JH", "JD", "QC", "QS", "QH", "QD", "KC", "KS", "KH", "KD", "AC", "AS", "AH", "AD");
      // deck.push("two-club", "two-spade", "two-heart", "two-dia", "three-club", "three-spade", "three-heart", "three-dia");
      shuffleArray(deck);
    }
  }
}

document.querySelector('.btn-draw').addEventListener('click', function() {
  drawCard();
});


function endTurn() {
  if (gamePlaying) {
    // Add CURRENT score to GLOBAL score
    scores[activePlayer] += roundScore;

    // Update the UI
    document.querySelector('#score-' + activePlayer).textContent = scores[activePlayer];
    // Check if player won the game
    if (scores[activePlayer] >= 200) {
      document.querySelector('#name-' + activePlayer).textContent = 'Winner!';
      document.querySelector('.card').style.display = 'none';
      document.querySelector('.player-' + activePlayer + '-panel').classList.add('winner');
      document.querySelector('.player-' + activePlayer + '-panel').classList.remove('active');
      gamePlaying = false;
    } else {
      // Next Player
      nextPlayer();
    }
  }
}


document.querySelector('.btn-endturn').addEventListener('click', function() {
  endTurn();
});


function nextPlayer() {
  activePlayer === 0 ? activePlayer = 1 : activePlayer = 0;
  roundScore = 0;

  document.getElementById('current-0').textContent = '0';
  document.getElementById('current-1').textContent = '0';

  document.querySelector('.player-0-panel').classList.toggle('active');
  document.querySelector('.player-1-panel').classList.toggle('active');

  document.querySelector('.card').style.display = 'none';
}

document.querySelector('.btn-new').addEventListener('click', init);

function init() {
  scores = [0, 0];
  roundScore = 0;
  activePlayer = 0;
  gamePlaying = true;

  document.querySelector('.card').style.display = 'none';

  document.getElementById('score-0').textContent = '0';
  document.getElementById('score-1').textContent = '0';
  document.getElementById('current-0').textContent = '0';
  document.getElementById('current-1').textContent = '0';
  document.getElementById('name-0').textContent = 'Player 1';
  document.getElementById('name-1').textContent = 'Player 2';
  document.querySelector('.player-0-panel').classList.remove('winner');
  document.querySelector('.player-1-panel').classList.remove('winner');
  document.querySelector('.player-0-panel').classList.remove('active');
  document.querySelector('.player-1-panel').classList.remove('active');
  document.querySelector('.player-0-panel').classList.add('active');
}
@import url('https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght@300;700&display=swap');
.final-score {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 520px;
  color: #555;
  font-size: 18px;
  font-family: 'Open Sans Condensed', sans-serif;
  text-align: center;
  padding: 10px;
  width: 160px;
  text-transform: uppercase;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

body {
  background-image: url("img/bg.gif");
  background-size: cover;
  background-position: center;
  font-family: 'Open Sans Condensed', sans-serif;
  font-weight: 300;
  position: relative;
  height: 100vh;
  color: #161624;
}

.wrapper {
  width: 1000px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #400000;
  box-shadow: 0px 10px 50px rgba(0, 0, 0, 1);
  overflow: hidden;
  color: white;
}

.player-0-panel,
.player-1-panel {
  width: 50%;
  float: left;
  height: 600px;
  padding: 100px;
}


/**********************************************
*** PLAYERS
**********************************************/

.player-name {
  font-size: 40px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 2px;
  font-weight: 100;
  margin-top: 20px;
  margin-bottom: 10px;
  position: relative;
}

.player-score {
  text-align: center;
  font-size: 80px;
  font-weight: 200;
  color: white;
  margin-bottom: 130px;
}

.active {
  background-color: rgb(255, 0, 0, .1);
}

.active .player-name {
  font-weight: 700;
}

.active .player-score {
  font-weight: 700;
}

.player-current-box {
  background-color: #EB4D4D;
  color: #fff;
  width: 40%;
  margin: 0 auto;
  padding: 12px;
  text-align: center;
}

.player-current-label {
  text-transform: uppercase;
  margin-bottom: 10px;
  font-size: 20px;
  color: #fff;
}

.player-current-score {
  font-size: 40px;
}

button {
  position: absolute;
  width: 200px;
  left: 50%;
  transform: translateX(-50%);
  color: #555;
  background: none;
  border: none;
  font-family: 'Open Sans Condensed', sans-serif;
  font-size: 30px;
  text-transform: uppercase;
  cursor: pointer;
  font-weight: 300;
  transition: background-color 0.3s, color 0.3s;
}

button:hover {
  font-weight: 600;
  border: 1px solid white;
}

button:focus {
  outline: none;
}


/* i {
    color: #EB4D4D;
    display: inline-block;
    margin-right: 15px;
    font-size: 32px;
    line-height: 1;
    vertical-align: text-top;
    margin-top: -4px;
    transition: margin 0.3s;
} */

.btn-new {
  top: 45px;
  color: white;
  border: 2px solid white;
  transition: 0.25s;
}

.btn-draw {
  top: 403px;
  color: white;
  border: 2px solid white;
  transition: 0.25s;
}

.btn-endturn {
  top: 467px;
  color: white;
  border: 2px solid white;
  transition: 0.25s;
}

.card {
  position: absolute;
  left: 50%;
  top: 178px;
  transform: translateX(-50%);
  height: 200px;
}

.back-card {
  position: absolute;
  left: 50%;
  top: 178px;
  transform: translateX(-50%);
  height: 200px;
}

.winner {
  background-color: #b00000;
}

.winner .player-name {
  font-weight: 700;
  color: #ff7878;
}

.winner .player-score {
  font-weight: 700;
  color: #ff7878;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="styles.css">
  <title>Card Game</title>
</head>

<body>
  <div class="wrapper clearfix">
    <div class="player-0-panel active">
      <div class="player-name" id="name-0">Player 1</div>
      <div class="player-score" id="score-0">43</div>
      <div class="player-current-box">
        <div class="player-current-label">Current</div>
        <div class="player-current-score" id="current-0">11</div>
      </div>
    </div>

    <div class="player-1-panel">
      <div class="player-name" id="name-1">Player 2</div>
      <div class="player-score" id="score-1">72</div>
      <div class="player-current-box">
        <div class="player-current-label">Current</div>
        <div class="player-current-score" id="current-1">0</div>
      </div>
    </div>

    <button class="btn-new"><i class="ion-ios-plus-outline"></i>New game</button>
    <button class="btn-draw"><i class="ion-ios-loop"></i>Draw Card</button>
    <button class="btn-endturn"><i class="ion-ios-download-outline"></i>End Turn</button>

    <img src="img/back-card.png" alt="Back of Card" class="back-card">
    <img src="card-5.png" alt="Card" class="card">
  </div>
  <script src="script.js"></script>
</body>

</html>

1 Answers

I think you already have the answer using setTimeout. But where? Based on your rules I would say you should use on the else, like so:

// 4. Update the round score IF the card drawn was NOT a 4 or a 9
if (card !== 2 && card !== 5 && card !== 9) {
  // add score
  roundScore += card;
  document.querySelector('#current-' + activePlayer).textContent = roundScore;
} else {
  // next player
  setTimeout(() => {
    nextPlayer();
  }, 2000);
}

But you should freeze the buttons, before you schedule this setTimeout. Because the user would continue playing.

I'd would put something, like so:

 freezeButtons();
 // next player
  setTimeout(() => {
    nextPlayer();
  }, 2000);

So finally it should work like so:

// 4. Update the round score IF the card drawn was NOT a 4 or a 9
    if (card !== 2 && card !== 5 && card !== 9) {
      // add score
      roundScore += card;
      document.querySelector('#current-' + activePlayer).textContent = roundScore;
    } else {

      const buttons = document.querySelectorAll('button');
      for(const button of buttons) {
        button.disabled = true;
      }
      
      // next player
      setTimeout(() => {
        nextPlayer();
        for(const button of buttons) {
          button.disabled = false;
        }
      }, 2000);
    }
Related