Whack a Mole is a classic game where you whack any mole you see before they go into hiding. And it is actually quite easy to make in JavaScript. You’ll only need same basic JavaScript knowledge and this’ll be a good practice for you. This is the demo of the game we’ll make and this is the GitHub repository.
We’ll break the process into 3 parts :
- Preparing the files
- Building the interface (HTML)
- Styling the interface (CSS)
- Making the game logic (JS)
1. Preparing the files
For this project, you’ll need 4 files, index.html, style.css, script.js and a mole image that you can download from my GitHub Repository.
2. Building the interface (HTML)
For the HTML, we’ll need some texts to display score and remaining time, start button and the board with the cells for the game. We use data-index to identify the index the cell is at but you can also use id if you prefer that.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>Whack A Mole</title>
</head>
<body>
<h3>Whack A Mole</h3>
<p>
Score : <span id="score">0</span>
Time : <span id="time">10</span>
<button id="start">Start</button>
</p>
<div class="board">
<div class="cell" data-index="0"></div>
<div class="cell" data-index="1"></div>
<div class="cell" data-index="2"></div>
<div class="cell" data-index="3"></div>
<div class="cell" data-index="4"></div>
<div class="cell" data-index="5"></div>
<div class="cell" data-index="6"></div>
<div class="cell" data-index="7"></div>
<div class="cell" data-index="8"></div>
</div>
<script src="./script.js"></script>
</body>
</html>
Now, your page should look like this without styling and JS.
3. Styling the interface (CSS)
Below is the CSS we’ll use to style the game. I’ll explain it using list below.
- For the * rule, we set it so that all width or margin already includes border width so we don’t have to worry about overflowing because of margins
- body, we reset the margins and make it full-screen as well as centering the contents with the help of flex
- .board, we give it a fixed width and a wrap attribute to make the cells continue down if there’s already 3 cells in a row
- .cell, we give it a fixed width so that a row can only fit 3 cells. We also give it overflow hidden because inside it, we’ll show our mole with animation popping from below, and we want the mole only visible when it’s inside the cell
- .mole, a div that will be added with JavaScript
- appear, an animation to show the mole popping up from below
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.board {
width: 450px;
display: flex;
flex-wrap: wrap;
}
.cell {
width: 150px;
height: 150px;
border: 1px solid black;
overflow: hidden;
}
.mole {
width: 150px;
height: 150px;
background-image: url('./mole.png');
background-size: contain;
animation: appear 0.9s;
}
@keyframes appear {
0% {
transform: translateY(130px);
}
100% {
transform: translateY(0);
}
}
Now, your game should look like this, but you still can’t play it yet though
3. Making the game logic (JS)
Lastly, to add interactivity to the game, we need these codes in our script.js. I’ll explain the code directly with comments. Note : You might feel that 1 second interval might be too fact, in that case, you can change it to 2 seconds.
// the elements
const cells = document.querySelectorAll('.cell');
const scoreEl = document.querySelector('#score');
const timeEl = document.querySelector('#time');
const startBtn = document.querySelector('#start');
// global variables
let score = 0;
let time = 10;
let currentPos;
// when a cell is clicked, it checks if the mole is there and updates the score if it is
cells.forEach(cell => {
cell.addEventListener('click', () => {
if (parseInt(cell.getAttribute('data-index')) === currentPos) {
score++;
scoreEl.innerHTML = score;
}
})
});
// adding a listener to the start button
startBtn.addEventListener('click', start);
function start() {
let startGame = setInterval(() => { // looping the game until time's up
// emptying all cell at the start to ensure noo duplicate mole
cells.forEach(cell => {
cell.innerHTML = '';
});
// filling a random cell by adding a div with mole class
currentPos = Math.floor(Math.random() * 9);
cells[currentPos].innerHTML = '<div class="mole"></div>';
// checking if time's up
time--;
timeEl.innerHTML = time;
if (time === 0) { // time's up
clearInterval(startGame); // stop the loop
// we use setTimeout because without it, alert executes before time updates
setTimeout(() => {
alert('Game Done! Refresh to restart.');
}, 100);
}
}, 1000);
}
Conclusion
And now we’ve built a basic Whack A Mole game. You can explore further by improving the styling, adding more animations like for when hiding the mole, adding a restart button, etc.
If you want to host your result, you can do it on GitHub Pages for free or if you want it to look more professional, you can host it on Cloudways. It is a compatible, fast and reliable managed cloud hosting. Go ahead and check it out!
For you who want to brush up your JavaScript skills, whether to deepen or learn form zero, I recommend you try Codecademy. There are tons of JavaScript lessons that you can learn in a structured and interactive way. You can learn from the most basic materials to advanced stuffs and even preparing for technical interviews. Go try it now!
If you are interested to practice JavaScript by building other games, you can try my other posts :
Now, well done and go explore! What should I build next?