Learn how to create whack a mole game in javascript.
It is a simple game in which every time a mole comes out from the ground we have to whack it. You get point every time you successfully whack a mole.
By building this game you will learn
- HTML:- How to position elements to give effect of something is coming up from underneath.
- CSS:- Create elements with aspect ratio 1:1 that is equal height and width and how to overlay one over anthoer.
- Javascript:- Randomly modify any elements at given intervals.
I have broken down the development in three different parts in which we will proceed to next after finishing the previous.
- Create the layout or skeleton of the game to show different ground.
- Design each area to show dirt and mole and how mole will appear.
- Show the moles in different ground at different interval and if it whacked that count the points.
I assume you now have good idea about what we are building and how we going to build it, so lets start the development.
HTML layout of whack a mole.
The layout is divided in basically two parts.
- An area where start button and score will be displayed.
- Play area where mole will popup from the ground.
The first part is pretty straight forward, we have to just define two elements, button and span to display the score.
The second will have different sections which will contain dirt and mole images. Dirt will be always visible and mole will popup.
This images are wrapped inside a wrapper to give spaces between two grounds.
The images will be added as background image to the elements so we will assign classes to add styles effectively.
You can dynamically generate the no of grounds, but here I am pre defining them.
<main> <section id="score-area"> <button class="primary">Start</button> <span id="score">Score: <span>0</span></span> </section> <!-- Play area --> <section id="play-area"> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> <section class="ground"> <div class="wrapper"> <div class="dirt"></div> <div class="mole"></div> </div> </section> </section> </main>
Styling the whack a mole game with CSS.
We will be using flexbox for aligning the elements.
Make sure you set the box-sizing:border-box
to restrict dimension inside the element. You can read more about it on how box-model works in CSS.
Also I have set the main wrapper to the 55% of window width. You can keep it as per your requirement.
* { box-sizing: border-box; } main { width: 55%; margin: 0 auto; }
Styling Score Area
The bottom and the score will be placed on the both the end of the main parent.
#score-area { display: flex; justify-content: space-between; padding: 0 20px; font-size: 30px; } button { position: relative; font-size: 14px; font-weight: 600; text-align: center; padding: 0.7em 1.2em; cursor: pointer; user-select: none; display: inline-flex; align-items: center; justify-content: center; height: 46px; min-width: 96px; border-radius: 4px; background-color: #fff; border: 1px solid; color: #fff; -webkit-transition: background 0.2s ease; -moz-transition: background 0.2s ease; -o-transition: background 0.2s ease; transition: background 0.2s ease; } .primary { background-color: #2fcb53; border-color: #2fcb53; color: #fff; } .primary:hover { background-color: #48dd84; border-color: #48dd84; }
Designing the ground
We are showing 4 grounds in a single row and each ground will be of 1:1 aspect ratio where width and height will be equal.
#play-area { display: flex; justify-content: center; align-items: center; flex-wrap: wrap; } .ground { display: inline-flex; flex: 1 1 25%; justify-content: center; align-items: center; padding: 10px; } .wrapper { position: relative; width: 100%; padding-bottom: 100%; overflow: hidden; }
If you can see we have made the .wrapper
relative positioned because mole will be placed inside it which will move up and down and adding padding-bottom: 100%
is a simple hack to make the height same as width.
Creating the mole and dirt
Dirt and mole both will be added as background image and the element will be positioned absolute to the parent so that we can move them up and down creating the effect of things are popping up.
Dirt will be in the front of the mole to give the effect that mole appears from back of the dirt.
.dirt, .mole { position: absolute; width: 100%; height: 100%; left: 0; background-size: contain; background-repeat: no-repeat; } .dirt { background-image: url("./assets/dirt.png"); z-index: 1; background-position: center 113%; } .mole { background-image: url(./assets/mole.png); transition: all 0.1s ease; top: 100%; background-position: bottom; background-size: 73%; } .ground.active .mole { top: 0; }
When the current ground has active
class then show the mole by bringing it to the top.
Adding life to whack a mole with javascript.
To show the mole in each different ground randomly, We will generate a random number between the number of grounds and add active
class to that ground.
Before adding the active
class we have to make sure that we remove this class from other grounds so that mole appears in only one ground.
const grounds = document.querySelectorAll(".ground"); const length = grounds.length; var interval = setInterval(() => { //Generate a random number const random = Math.floor(Math.random() * length); //Remove the active class from every ground grounds.forEach((e) => { e.classList.remove("active"); }); //Add the active class to random ground grounds[random].classList.add("active"); }, 700);
The frequency of showing the mole can be changed as per once requirement.
To count the score every time a mole appears in the ground and we click on it we have to increase the points.
For this we will listen to the click event on each ground and after click we will check if the ground has active
class which means mole has appeared then increase the score.
const score = document.querySelector("#score > span"); let count = 0; grounds.forEach((e) => { e.addEventListener("click", () => { //If ground has active class which means it has mole //So increase the count if (e.classList.contains("active")) { count++; score.innerHTML = count; } }); });
Now I want to start this game only when start button is clicked, so lets wrap all these inside a function then invoke the function when start button is clicked.
window.addEventListener("load", () => { document.querySelector("button").addEventListener("click", () => { startGame(); }); }); const startGame = () => { const grounds = document.querySelectorAll(".ground"); const length = grounds.length; const score = document.querySelector("#score > span"); let count = 0; grounds.forEach((e) => { e.addEventListener("click", () => { //If ground has active class which means it has mole //So increase the count if (e.classList.contains("active")) { count++; score.innerHTML = count; } }); }); var interval = setInterval(() => { //Generate a random number const random = Math.floor(Math.random() * length); //Remove the active class from every ground grounds.forEach((e) => { e.classList.remove("active"); }); //Add the active class to random ground grounds[random].classList.add("active"); }, 700); };
You have learned how to create a simple whack a mole game with javascript🎉🎉🎉✨.