Creating a Whack-a-Mole Web Game

JavaScriptJavaScriptBeginner
Practice Now

Introduction

In this project, you will learn how to create a Whack-a-Mole game using HTML, CSS, and JavaScript. The game involves whacking moles that randomly appear from holes within a specified time limit. You will create the necessary HTML, CSS, and JavaScript files and implement the game logic step by step.

👀 Preview

Whack-a-Mole Web Game

🎯 Tasks

In this project, you will learn:

  • How to set up the project files for the Whack-a-Mole game
  • How to add the necessary CSS styles to create the game layout and design
  • How to implement the game logic for making moles appear and disappear, keeping score, and tracking time
  • How to create event listeners for whacking the moles and starting the game

🏆 Achievements

After completing this project, you will be able to:

  • Create HTML, CSS, and JavaScript files for a web-based game
  • Use CSS to style and layout game elements
  • Manipulate the DOM using JavaScript to make game elements appear and disappear
  • Handle user interactions and update the game state
  • Use timers in JavaScript to track time and control game flow

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL css(("`CSS`")) -.-> css/BasicConceptsGroup(["`Basic Concepts`"]) css(("`CSS`")) -.-> css/BasicStylingGroup(["`Basic Styling`"]) css(("`CSS`")) -.-> css/CoreLayoutGroup(["`Core Layout`"]) css(("`CSS`")) -.-> css/AdvancedLayoutGroup(["`Advanced Layout`"]) css(("`CSS`")) -.-> css/IntermediateStylingGroup(["`Intermediate Styling`"]) css(("`CSS`")) -.-> css/DynamicStylingGroup(["`Dynamic Styling`"]) css(("`CSS`")) -.-> css/CSSPreprocessorsGroup(["`CSS Preprocessors`"]) html(("`HTML`")) -.-> html/BasicStructureGroup(["`Basic Structure`"]) html(("`HTML`")) -.-> html/TextContentandFormattingGroup(["`Text Content and Formatting`"]) html(("`HTML`")) -.-> html/LayoutandSectioningGroup(["`Layout and Sectioning`"]) javascript(("`JavaScript`")) -.-> javascript/BasicConceptsGroup(["`Basic Concepts`"]) javascript(("`JavaScript`")) -.-> javascript/AdvancedConceptsGroup(["`Advanced Concepts`"]) javascript(("`JavaScript`")) -.-> javascript/DOMManipulationGroup(["`DOM Manipulation`"]) javascript(("`JavaScript`")) -.-> javascript/ToolsandEnvironmentGroup(["`Tools and Environment`"]) javascript(("`JavaScript`")) -.-> javascript/SecurityGroup(["`Security`"]) css/BasicConceptsGroup -.-> css/selectors("`Selectors`") css/BasicStylingGroup -.-> css/colors("`Colors`") css/BasicStylingGroup -.-> css/fonts("`Fonts`") css/BasicStylingGroup -.-> css/text_styling("`Text Styling`") css/CoreLayoutGroup -.-> css/margin_and_padding("`Margin and Padding`") css/CoreLayoutGroup -.-> css/borders("`Borders`") css/CoreLayoutGroup -.-> css/width_and_height("`Width and Height`") css/CoreLayoutGroup -.-> css/positioning("`Positioning`") css/AdvancedLayoutGroup -.-> css/flexbox("`Flexbox`") css/AdvancedLayoutGroup -.-> css/grid_layout("`Grid Layout`") css/IntermediateStylingGroup -.-> css/backgrounds("`Backgrounds`") css/DynamicStylingGroup -.-> css/transitions("`Transitions`") css/DynamicStylingGroup -.-> css/transformations("`Transformations`") css/CSSPreprocessorsGroup -.-> css/nesting("`Nesting`") html/BasicStructureGroup -.-> html/charset("`Character Encoding`") html/BasicStructureGroup -.-> html/lang_decl("`Language Declaration`") html/BasicStructureGroup -.-> html/viewport("`Viewport Declaration`") html/BasicStructureGroup -.-> html/head_elems("`Head Elements`") html/TextContentandFormattingGroup -.-> html/text_head("`Text and Headings`") html/TextContentandFormattingGroup -.-> html/para_br("`Paragraphs and Line Breaks`") html/LayoutandSectioningGroup -.-> html/doc_flow("`Document Flow Understanding`") css/IntermediateStylingGroup -.-> css/pseudo_classes("`Pseudo-classes`") javascript/BasicConceptsGroup -.-> javascript/variables("`Variables`") javascript/BasicConceptsGroup -.-> javascript/data_types("`Data Types`") javascript/BasicConceptsGroup -.-> javascript/arith_ops("`Arithmetic Operators`") javascript/BasicConceptsGroup -.-> javascript/comp_ops("`Comparison Operators`") javascript/BasicConceptsGroup -.-> javascript/cond_stmts("`Conditional Statements`") javascript/BasicConceptsGroup -.-> javascript/loops("`Loops`") javascript/BasicConceptsGroup -.-> javascript/functions("`Functions`") javascript/BasicConceptsGroup -.-> javascript/array_methods("`Array Methods`") javascript/BasicConceptsGroup -.-> javascript/obj_manip("`Object Manipulation`") javascript/AdvancedConceptsGroup -.-> javascript/async_prog("`Asynchronous Programming`") javascript/DOMManipulationGroup -.-> javascript/dom_select("`DOM Selection`") javascript/DOMManipulationGroup -.-> javascript/dom_manip("`DOM Manipulation`") javascript/DOMManipulationGroup -.-> javascript/event_handle("`Event Handling`") javascript/ToolsandEnvironmentGroup -.-> javascript/bom("`Browser Object Model`") javascript/SecurityGroup -.-> javascript/xss("`Cross-Site Scripting`") javascript/SecurityGroup -.-> javascript/web_sec("`Web Security Basics`") subgraph Lab Skills css/selectors -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/colors -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/fonts -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/text_styling -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/margin_and_padding -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/borders -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/width_and_height -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/positioning -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/flexbox -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/grid_layout -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/backgrounds -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/transitions -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/transformations -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/nesting -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/charset -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/lang_decl -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/viewport -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/head_elems -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/text_head -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/para_br -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} html/doc_flow -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} css/pseudo_classes -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/variables -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/data_types -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/arith_ops -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/comp_ops -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/cond_stmts -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/loops -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/functions -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/array_methods -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/obj_manip -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/async_prog -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/dom_select -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/dom_manip -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/event_handle -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/bom -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/xss -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} javascript/web_sec -.-> lab-298975{{"`Creating a Whack-a-Mole Web Game`"}} end

Create the project files

First, let's create the project files for the Whack-a-Mole game.

  1. cd into the ~/project directory.
  2. Create a new file called index.html.
  3. Copy and paste the following code into index.html:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
    <title>Whack-a-Mole!</title>
  </head>

  <body
    class="bg-gradient-to-r from-yellow-400 via-red-500 to-pink-500 flex items-center justify-center h-screen"
  >
    <div class="game bg-white p-8 rounded-lg shadow-2xl text-center">
      <h1 class="text-4xl font-bold mb-4 text-red-600">Whack-a-Mole!</h1>
      <p class="score text-2xl text-red-600">
        Score: <span id="score">0</span>
      </p>
      <p class="time text-2xl text-red-600">
        Time Left: <span id="time">0</span>
      </p>
      <button
        id="startBtn"
        class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded mt-4 transition duration-500 ease-in-out transform hover:-translate-y-1 hover:scale-110"
      >
        Start Game
      </button>
      <div id="grid" class="grid grid-cols-3 gap-4 mt-4">
        <!-- Holes will be added here -->
      </div>
    </div>
    <script src="main.js"></script>
  </body>
</html>

Add the CSS styles

  1. Create a new file called styles.css.
  2. Copy and paste the following code into styles.css:
.game {
  width: 600px;
  border-radius: 2rem;
}

.hole {
  height: 0;
  padding-bottom: 100%;
  position: relative;
  background: #eee;
  border: 3px solid #ccc;
  border-radius: 50%;
  overflow: hidden;
}

.mole {
  width: 100%;
  height: 100%;
  background: #a0522d;
  border-radius: 50%;
  position: absolute;
  transform: translateY(100%);
  transition: transform 0.3s;
}

.mole.up {
  transform: translateY(0);
}

.mole.whacked {
  background: #008cff;
}

#startBtn {
  background-color: #0051ff;
  color: #fff;
  padding: 10px 20px;
  border-radius: 20px;
  border: none;
  cursor: pointer;
  transition: background-color 0.3s;
}

#startBtn:hover {
  background-color: #028a5f;
}

Add the game logic

  1. Create a new file called main.js.
  2. We will add the JavaScript code in the subsequent steps.

Now, let's add the game logic to the main.js file.

  1. Open the main.js file.
  2. Copy and paste the following code into main.js:
const grid = document.querySelector("#grid");
const scoreDisplay = document.querySelector("#score");
const timeDisplay = document.querySelector("#time");
const startBtn = document.querySelector("#startBtn");
let holes = [];
let score = 0;
let lastHole;
let timeUp = false;
let gameTimer;
let countdownTimer;
let countdown;

function createHoles() {
  for (let i = 0; i < 6; i++) {
    const hole = document.createElement("div");
    const mole = document.createElement("div");

    hole.classList.add("hole");
    mole.classList.add("mole");

    hole.appendChild(mole);
    grid.appendChild(hole);

    holes.push(hole);
  }
}

function randomTime(min, max) {
  return Math.round(Math.random() * (max - min) + min);
}

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;
}

function peep() {
  // TODO: Implement this function in Step 3.
}

function startGame() {
  // TODO: Implement this function in Step 4.
}

function whack(e) {
  // TODO: Implement this function in Step 5.
}

createHoles();
// TODO: Implement the rest of the code in Step 6.

This code defines variables to store references to various HTML elements and initializes other necessary variables. It also defines several functions for creating holes, generating random times and holes, making moles appear and disappear, starting the game, and handling mole whacks. Finally, it creates the holes, adds event listeners to the holes, and sets up the start button click event listener.

Implement the peep function

In this step, we'll implement the peep function, which makes the moles appear and disappear randomly.

  1. Open the main.js file.
  2. Locate the peep function.
  3. Replace the existing code with the following code:
function peep() {
  const time = randomTime(200, 1000);
  const hole = randomHole(holes);
  hole.querySelector(".mole").classList.add("up");

  setTimeout(() => {
    hole.querySelector(".mole").classList.remove("up");
    hole.querySelector(".mole").classList.remove("whacked");
    if (!timeUp) peep();
  }, time);
}

This function sets a random time interval between 200ms and 1000ms using the randomTime function. It selects a random hole using the randomHole function and makes the mole appear by adding the up class to the mole element. After the specified time interval, the mole disappears by removing the up class. If the game is not over (timeUp is false), the function calls itself recursively to make another mole appear.

Implement the startGame function

Next, we'll implement the startGame function, which initializes the game and starts the timer.

  1. Open the main.js file.
  2. Locate the startGame function.
  3. Replace the existing code with the following code:
function startGame() {
  scoreDisplay.textContent = 0;
  timeUp = false;
  score = 0;
  peep();
  gameTimer = setTimeout(() => (timeUp = true), 10000);
  countdown = 10;
  timeDisplay.textContent = countdown;
  startBtn.disabled = true;
  countdownTimer = setInterval(() => {
    countdown--;
    if (countdown < 0) {
      clearInterval(countdownTimer);
      startBtn.disabled = false;
      return;
    }
    timeDisplay.textContent = countdown;
  }, 1000);
}

This function initializes the score, sets timeUp to false, and resets the score display. It calls the peep function to start the mole appearances. It starts a game timer using setTimeout to set timeUp to true after 10 seconds. It also sets up a countdown timer to update the time display every second. The countdown is initially set to 10, and when it reaches 0, the countdown timer is cleared, the start button is enabled, and the function returns.

Implement the whack function

Now, let's implement the whack function, which handles whacking the moles and updating the score.

  1. Open the main.js file.
  2. Locate the whack function.
  3. Replace the existing code with the following code:
function whack(e) {
  if (!e.isTrusted || !this.querySelector(".mole").classList.contains("up"))
    return; // fake click detected or the mole is not up
  score++;
  this.querySelector(".mole").classList.remove("up");
  this.querySelector(".mole").classList.add("whacked");
  scoreDisplay.textContent = score;
}

This function is called when a mole is clicked. It checks if the click event is trusted (e.isTrusted) to prevent fake clicks. It also checks if the mole is currently up by checking if it has the up class. If the click is valid, it increments the score, removes the up class from the mole element, adds the whacked class to visually indicate that the mole has been whacked, and updates the score display.

Initialize the game and event listeners

In this step, we'll initialize the game by creating the holes and adding event listeners to the holes and the start button.

  1. Open the main.js file.
  2. Locate the line with the createHoles() function call.
  3. Add the following code after the createHoles() function call:
holes.forEach((hole) => hole.addEventListener("click", whack));

startBtn.addEventListener("click", startGame);

This code adds a click event listener to each hole element. When a hole is clicked, the whack function is called. It also adds a click event listener to the start button, which calls the startGame function when clicked.

Test the Whack-a-Mole game

Click on Go Live button in the bottom right corner of WebIDE, and switch to the Web 8080 tab.

Alt text

This will open the project in Web 8080 Tab.

Alt text

Summary

In this project, we have created the project files for the Whack-a-Mole game. We have created the HTML structure, added CSS styles, and implemented the game logic using JavaScript. The next steps would involve further customization and enhancement of the game, such as adding sounds, levels, and difficulty settings.

Other JavaScript Tutorials you may like