Happylab Logo
Published on

Day30: Whack-A-Mole

Authors

Introduction: How to implement a Whack-A-Mole game using JavaScript.

Project Page: https://iris1114.github.io/javascript30/30_Whack-A-Mole/

HTML

  • Contains a div container with multiple div elements to display moles.
  • Includes a button to start the game.
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Whack-A-Mole</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <h1>Whack-A-Mole! <span class="score">0</span></h1>
    <button class="start">Start!</button>
    <div class="game">
      <div class="hole hole1">
        <div class="mole"></div>
      </div>
      <div class="hole hole2">
        <div class="mole"></div>
      </div>
      <div class="hole hole3">
        <div class="mole"></div>
      </div>
      <div class="hole hole4">
        <div class="mole"></div>
      </div>
      <div class="hole hole5">
        <div class="mole"></div>
      </div>
      <div class="hole hole6">
        <div class="mole"></div>
      </div>
    </div>

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

CSS

  • Sets basic page styles, including fonts, colors, and layout.
  • Styles for the Whack-A-Mole game.
body {
  font-family: 'Arial', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: #f4f4f4;
  margin: 0;
}

h1 {
  font-size: 3rem;
  margin-bottom: 20px;
}

button.start {
  padding: 10px 20px;
  font-size: 1.2rem;
  cursor: pointer;
  margin-bottom: 20px;
}

.game {
  display: flex;
  flex-wrap: wrap;
  width: 600px;
  height: 400px;
  position: relative;
}

.hole {
  width: 33.333%;
  height: 50%;
  position: relative;
  overflow: hidden;
}

.mole {
  width: 100px;
  height: 100px;
  background: url('mole.png') no-repeat center center;
  background-size: contain;
  position: absolute;
  bottom: -100px;
  transition: all 0.3s;
}

.hole.up .mole {
  bottom: 0;
}

JavaScript

  • Uses JavaScript to implement the Whack-A-Mole game.
const holes = document.querySelectorAll('.hole')
const scoreBoard = document.querySelector('.score')
const moles = document.querySelectorAll('.mole')
const startButton = document.querySelector('.start')
let lastHole
let timeUp = false
let score = 0

// Randomly select a hole
function randomTime(min, max) {
  return Math.round(Math.random() * (max - min) + min)
}

// Randomly select a hole
function randomHole(holes) {
  const idx = Math.floor(Math.random() * holes.length)
  const hole = holes[idx]
  if (hole === lastHole) {
    return randomHole(holes)
  }
  lastHole = hole
  return hole
}

// Show the mole
function peep() {
  const time = randomTime(200, 1000)
  const hole = randomHole(holes)
  hole.classList.add('up')
  setTimeout(() => {
    hole.classList.remove('up')
    if (!timeUp) peep()
  }, time)
}

// Start the game
function startGame() {
  scoreBoard.textContent = 0
  timeUp = false
  score = 0
  peep()
  setTimeout(() => (timeUp = true), 10000)
}

// Whack the mole
function bonk(e) {
  if (!e.isTrusted) return // cheater!
  score++
  this.parentNode.classList.remove('up')
  scoreBoard.textContent = score
}

moles.forEach((mole) => mole.addEventListener('click', bonk))
startButton.addEventListener('click', startGame)

Note

  • Uses setTimeout to control the timing of the moles appearing.
  • Uses Math.random to randomly select holes and timing.
  • Uses addEventListener to listen for clicks on the moles.