Create a Whack-a-Mole Game with HTML, CSS, and JavaScript | Step-by-Step Guide

Faraz

By Faraz -

Learn how to create a Whack-a-Mole game using HTML, CSS, and JavaScript. Follow this step-by-step guide to build, style, and add logic to your game. Get the complete source code and tips for enhancements.


create-a-whack-a-mole-game-with-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Preview
  6. Conclusion

Whack-a-Mole is a classic arcade game that challenges players to hit moles popping up from holes within a time limit. Recreating this game using web technologies like HTML, CSS, and JavaScript is a fantastic way to enhance your coding skills. This guide will walk you through the entire process, from setting up your development environment to adding interactive features. By the end, you will have a fully functional Whack-a-Mole game that you can further customize and expand.

Setting Up Your Development Environment

Before diving into the code, you need to set up your development environment. Ensure you have a code editor like Visual Studio Code or Sublime Text. You'll also need a web browser for testing and debugging. Create a new directory for your project, and within it, create three files: index.html, style.css, and script.js. These files will hold the HTML structure, CSS styling, and JavaScript logic, respectively.

Source Code

Step 1 (HTML Code):

Start with the basic HTML structure in your index.html file. This includes the doctype declaration, head section, and body. Inside the body, create a container for the game with a class of game. Within this container, add several div elements with the class mole to represent the moles. Also, include a score display and a start button to initiate the game. Let's break it down:

1. <!DOCTYPE html>: This declaration specifies the document type and version of HTML being used, which in this case is HTML5.

2. <html lang="en">: This tag defines the beginning of the HTML document, with the language set to English (en).

3. <head>: This section contains meta-information about the HTML document, such as character encoding, viewport settings, and the title of the page.

  • <meta charset="UTF-8" />: This meta tag specifies the character encoding for the document, ensuring that it's interpreted correctly by browsers.
  • <meta http-equiv="X-UA-Compatible" content="IE=edge" />: This meta tag ensures the page renders in the highest mode available in Internet Explorer.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0" />: This meta tag sets the viewport properties, ensuring the page adapts properly to different device screen sizes.
  • <title>Whack-a-mole Game</title>: This specifies the title of the web page, which appears in the browser's title bar or tab.
  • <link rel="stylesheet" href="styles.css" />: This links an external CSS file (styles.css) to the HTML document, which is used to style the content of the page.

4. <body>: This section contains the visible content of the web page.

  • <h1>Whack-a-mole!</h1>: This is the main heading of the page, displaying the title of the game.
  • <h2>Score: <span class="score">0</span></h2>: This heading displays the score of the game, with the score initially set to 0. The score is wrapped in a <span> element with the class "score", which can be targeted by CSS or JavaScript.
  • <button id="start" onClick="startGame()">Start</button>: This is a button element used to start the game. It has an id of "start" and an onClick event handler that calls the JavaScript function startGame() when clicked.
  • <div class="game">: This div contains the game elements.
  • Inside this div, there are six <div> elements with the class "hole", each representing a hole in the game.
  • Inside each "hole" div, there is a <div> element with the class "mole", representing the mole that appears in that hole during the game.
  • <script src="script.js"></script>: This script tag links an external JavaScript file (script.js) to the HTML document, which contains the JavaScript code necessary to make the game interactive and functional.

Step 2 (CSS Code):

Next, move on to the style.css file to add styling to your game. Begin by setting up basic styles for the game container and moles. Use CSS Grid or Flexbox to position the moles within the container. Apply styles to make the moles visually distinct and to animate their appearance and disappearance. Here's a breakdown:

1. @import url('https://fonts.googleapis.com/css?family=Nunito');: This imports the Nunito font from Google Fonts, making it available for use in the page.

2. *, *:before, *:after { ... }: This applies the following styles to all elements, their before and after pseudo-elements:

  • -webkit-box-sizing: inherit;, -moz-box-sizing: inherit;, box-sizing: inherit;: This sets the box-sizing property to inherit, ensuring consistent box model behavior across all elements.

3. html { ... }: Styles applied to the html element:

  • -moz-box-sizing: border-box;, -webkit-box-sizing: border-box;, box-sizing: border-box;: This sets the box-sizing property to border-box, ensuring that padding and border are included in the element's total width and height.
  • font-size: 10px;: Sets the base font size for the entire document to 10 pixels.

4. body { ... }: Styles applied to the body element:

  • padding: 0;, margin: 0;: Removes default padding and margin.
  • font-family: 'Nunito', sans-serif;: Sets the font family to Nunito with a fallback to the generic sans-serif font family.
  • background: #fff9e2;: Sets the background color of the body to a light yellowish color.
  • text-align: center;: Aligns text content to the center horizontally.

5. h1 { ... }, h2 { ... }: Styles applied to h1 and h2 elements respectively:

  • Defines font size, color, and margins for heading elements.

6. .score { ... }: Styles applied to elements with class "score":

  • Sets background color, padding, border-radius, and color.

7. .game { ... }: Styles applied to elements with class "game":

  • Sets the width, height, and display properties, along with margin, for a game container.

8. .hole { ... }: Styles applied to elements with class "hole":

  • Defines flex properties, overflow, and positioning for "hole" elements.
  • Applies a background image to simulate a hole.

9. .mole { ... }: Styles applied to elements with class "mole":

  • Sets a background image and positioning for mole elements.
  • Includes a transition for smooth animation.

10. .hole.up .mole { ... }: Styles applied to mole elements within holes that have the class "up". This likely indicates the mole is in the "up" state.

11. #start { ... }, #start:hover { ... }: Styles applied to the element with id "start" and its hover state:

  • Defines font family, background color, padding, and cursor for a start button.
  • Adjusts opacity on hover for a visual effect.
@import url('https://fonts.googleapis.com/css?family=Nunito');

*, *:before, *:after {
  -webkit-box-sizing: inherit;
  -moz-box-sizing: inherit;
  box-sizing: inherit;
}

html {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  font-size: 10px;
}

body {
  padding: 0;
  margin: 0;
  font-family: 'Nunito', sans-serif;
  background: #fff9e2;
  text-align: center;
}


h1 {
  font-size: 4.5rem;
  line-height: 1;
  margin: 2rem 0 0 0;
  color: #ff7660;
}

h2 {
  font-size: 3rem;
  color: #3b1010;
  margin: 2rem;
}

.score {
  background: #ffe5cf;
  padding: 0 3rem;
  line-height: 1;
  -webkit-border-radius: 1rem;
  -moz-border-radius: 1rem;
  border-radius: 1rem;
  color: #3b1010;
}

.game {
  width: 600px;
  height: 400px;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  flex-wrap: wrap;
  margin: 0 auto;
}

.hole {
  flex: 1 0 33.33%;
  overflow: hidden;
  position: relative;
}

.hole:after {
  display: block;
  background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1159990/dirt.svg') bottom center no-repeat;
  background-size: contain;
  content: '';
  width: 100%;
  height: 70px;
  position: absolute;
  z-index: 2;
  bottom: -30px;
}

.mole {
  background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1159990/mole.svg') bottom center no-repeat;
  background-size: 60%;
  position: absolute;
  top: 100%;
  width: 100%;
  height: 100%;
  transition: all 0.4s;
}

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

#start {
  font-family: 'Nunito', sans-serif;
  display: inline-block;
  text-decoration: none;
  border: 0;
  background: #3b1010;
  color: #fff;
  font-size: 2rem;
  padding: 1rem 2rem;
  cursor: pointer;
  margin: 1rem;
}

#start:hover {
  opacity: 0.8;
} 

Step 3 (JavaScript Code):

With the structure and styling in place, it’s time to add the game logic using JavaScript. Open your script.js file and start by defining variables for the moles, score, and game state. Create functions to randomly display moles, handle mole clicks to increase the score, and control the game’s start and stop behavior. Let's break down what each part of the code does:

1. Variable Declarations:

  • const holes, scoreBoard, moles, and button are variables that store references to various elements in the HTML document, identified by their classes or IDs.
  • let lastHole, timeUp, and score are variables used to keep track of game state.

2. Utility Functions:

  • randomTime(min, max): Generates a random time interval between min and max milliseconds.
  • randomHole(holes): Randomly selects a hole from the provided list of holes. It ensures that the same hole doesn't appear consecutively.
  • peep(): Causes a mole to pop up randomly from a hole for a random amount of time.

3. Game Functions:

  • startGame(): Resets the game state, hides the start button, and starts the game by calling the peep() function. After a fixed time (10 seconds), it ends the game and displays a "Try again?" button.
  • bonk(e): Handles the "bonking" of moles. When a mole is clicked, it increments the score, updates the score display, and removes the mole from view.

4. Event Listeners:

  • Adds a click event listener to each mole element. When a mole is clicked, the bonk function is called.
const holes = document.querySelectorAll('.hole');
const scoreBoard = document.querySelector('.score');
const moles = document.querySelectorAll('.mole');
const button = document.querySelector('#start');
let lastHole;
let timeUp = false;
let score = 0;

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) {
    console.log('Same one');
    return randomHole(holes);
  }

  lastHole = hole;
  return hole;
}

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

function startGame() {
  scoreBoard.textContent = 0;
  timeUp = false;
  score = 0;
  button.style.visibility = 'hidden';
  peep();
  setTimeout(() => {
    timeUp = true;
    button.innerHTML = 'Try again?'
    button.style.visibility = 'visible';
  }, 10000);
}

function bonk(e) {
  if(!e.isTrusted) return;
  score++;
  this.classList.remove('up');
  scoreBoard.textContent = score;
}

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

Final Output:

create-a-whack-a-mole-game-with-html-css-and-javascript.gif

Conclusion:

Creating a Whack-a-Mole game with HTML, CSS, and JavaScript is a rewarding project that hones your web development skills. You’ve learned how to set up your environment, structure HTML, style with CSS, and add interactivity with JavaScript. Keep experimenting with new features and improvements to further develop your skills. Share your game with friends and challenge them to beat your high score!

Code by: Katherine Kato

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post