Skip to content

Commit f01f16a

Browse files
Kanavpreet-Singhsumn2u
authored andcommitted
added game
1 parent 8fc5f5b commit f01f16a

File tree

6 files changed

+353
-0
lines changed

6 files changed

+353
-0
lines changed

assets/whack-a-mole.png

213 KB
Loading
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# 🦫 Whack-a-Mole Game
2+
3+
![Whack-a-Mole Preview](../../assets/whack-a-mole.png)
4+
5+
## Description
6+
7+
A fun and fast-paced reflex game where players “whack” moles as they randomly pop out of holes. Each successful hit earns you points — but be quick, because the mole disappears in a second! The game runs for a limited time, making it both exciting and challenging.
8+
9+
## Features
10+
11+
- Start button to begin the game
12+
- Random mole appearances in 9 different holes
13+
- Real-time score tracking
14+
- Automatic 30-second game duration
15+
- Alert message showing final score when time’s up
16+
17+
## Concepts Practiced
18+
19+
- DOM manipulation and dynamic element creation
20+
- Event listeners for interactive clicks
21+
- Randomization and timing using `Math.random()` and `setTimeout()`
22+
- Basic game loop logic
23+
- CSS animations for mole movement
24+
25+
## Bonus Challenge
26+
27+
- Add **levels** (Easy, Medium, Hard) that increase mole speed
28+
- Add a **visible countdown timer**
29+
- Store and display **high scores** using `localStorage`
30+
- Add **sound effects** when the mole is clicked
31+
- Use **images or emojis** to customize the mole design
32+
33+
## Live Demo
34+
35+
<div align="center">
36+
<iframe src="https://codesandbox.io/p/sandbox/hwr4cq"
37+
style="width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;"
38+
title="whack-a-mole-game"
39+
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
40+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
41+
></iframe>
42+
</div>

examples/Whack-A-Mole/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Whack-a-Mole — Reflex Game 🦫
2+
3+
This is a fun and interactive **Whack-a-Mole** reflex game built using **HTML, CSS, and modern JavaScript (ES Modules)**.
4+
Players must click (or “whack”) the mole as it randomly pops out of one of the holes before it disappears — testing their speed and reaction time!
5+
6+
## Features
7+
8+
- 🎯 **Fast-paced gameplay** — moles appear randomly across the board.
9+
- ⏱️ **30-second timer** — challenge yourself to score as high as possible within the time limit.
10+
- 🧠 **Live score tracking** — updates instantly with each successful hit.
11+
- 💥 **Smooth animations** — CSS-based mole pop-up effect for a polished experience.
12+
- ⚡ Built using **pure HTML, CSS, and JavaScript (no libraries or frameworks)**.
13+
14+
## Files
15+
16+
- `index.html` — main structure and layout of the game board.
17+
- `styles.css` — visual design, layout grid, and animations.
18+
- `index.mjs` — game logic for mole appearance, scoring, and timer handling.
19+
20+
## How to Play
21+
22+
1. Open `index.html` in your browser (Chrome, Edge, or Firefox recommended).
23+
2. Click the **“Start Game”** button to begin.
24+
3. Moles will pop up randomly in different holes — **click them as fast as you can!**
25+
4. Each successful hit gives you **+1 point**.
26+
5. After 30 seconds, the game ends and your **final score** is displayed.
27+
6. Click **“Start Game”** again to play another round.
28+
29+
## Notes
30+
31+
- Uses **JavaScript’s `setTimeout()`** for mole timing and random placement.
32+
- A great beginner project to understand **event handling, DOM updates, and randomization**.
33+
- Fully responsive — works on both **desktop and mobile** devices.
34+
35+
---
36+
37+
**Test your reflexes and see how many moles you can whack!**

examples/Whack-A-Mole/index.html

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Whack-a-Mole Game 🦫</title>
7+
<link rel="stylesheet" href="styles.css" />
8+
</head>
9+
<body>
10+
<h1>Whack-a-Mole 🦫</h1>
11+
12+
<div class="scoreboard">
13+
<p>Score: <span id="score">0</span></p>
14+
<label for="difficulty">Difficulty:</label>
15+
<select id="difficulty">
16+
<option value="beginner" selected>Beginner</option>
17+
<option value="easy">Easy</option>
18+
<option value="medium">Medium</option>
19+
<option value="hard">Hard</option>
20+
</select>
21+
<p>Time: <span id="time-left">30</span>s</p>
22+
<button id="start-btn">Start Game</button>
23+
</div>
24+
25+
<div class="grid">
26+
<!-- 9 holes -->
27+
<div class="hole" data-index="0"></div>
28+
<div class="hole" data-index="1"></div>
29+
<div class="hole" data-index="2"></div>
30+
<div class="hole" data-index="3"></div>
31+
<div class="hole" data-index="4"></div>
32+
<div class="hole" data-index="5"></div>
33+
<div class="hole" data-index="6"></div>
34+
<div class="hole" data-index="7"></div>
35+
<div class="hole" data-index="8"></div>
36+
</div>
37+
38+
<script type="module" src="index.mjs"></script>
39+
</body>
40+
</html>

examples/Whack-A-Mole/index.mjs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const holes = document.querySelectorAll(".hole");
2+
const scoreDisplay = document.getElementById("score");
3+
const timeLeftDisplay = document.getElementById("time-left");
4+
const difficultySelect = document.getElementById("difficulty");
5+
const startBtn = document.getElementById("start-btn");
6+
7+
let score = 0;
8+
let gameActive = false;
9+
let moleTimer; // controls despawn/next-spawn timing
10+
let endTimer; // controls game end
11+
let tickTimer; // countdown display timer
12+
let currentMole = null;
13+
14+
const LEVELS = {
15+
beginner: {
16+
moleVisibleMs: 3000,
17+
respawnDelayMs: 1200,
18+
totalTimeSec: 30,
19+
animationSec: 1.8,
20+
},
21+
easy: {
22+
moleVisibleMs: 2200,
23+
respawnDelayMs: 900,
24+
totalTimeSec: 30,
25+
animationSec: 1.3,
26+
},
27+
medium: {
28+
moleVisibleMs: 1500,
29+
respawnDelayMs: 500,
30+
totalTimeSec: 30,
31+
animationSec: 1.0,
32+
},
33+
hard: {
34+
moleVisibleMs: 1000,
35+
respawnDelayMs: 300,
36+
totalTimeSec: 30,
37+
animationSec: 0.7,
38+
},
39+
};
40+
41+
// Spawn a mole in a random hole
42+
function showMole() {
43+
if (!gameActive) return;
44+
45+
// Cleanup any existing mole
46+
if (currentMole && currentMole.isConnected) {
47+
currentMole.remove();
48+
}
49+
50+
const randomIndex = Math.floor(Math.random() * holes.length);
51+
const hole = holes[randomIndex];
52+
53+
const mole = document.createElement("div");
54+
mole.classList.add("mole");
55+
hole.appendChild(mole);
56+
currentMole = mole;
57+
58+
// Tune the animation speed to the selected difficulty
59+
const { moleVisibleMs, respawnDelayMs, animationSec } = LEVELS[difficultySelect.value] || LEVELS.easy;
60+
mole.style.animationDuration = `${animationSec}s`;
61+
62+
// Despawn after a short time and spawn the next one with a brief delay
63+
clearTimeout(moleTimer);
64+
moleTimer = setTimeout(() => {
65+
if (mole.isConnected) mole.remove();
66+
if (gameActive) {
67+
setTimeout(() => showMole(), respawnDelayMs);
68+
}
69+
}, moleVisibleMs);
70+
}
71+
72+
// Handle hits (click or touch/pointer)
73+
holes.forEach((hole) => {
74+
// Use pointerdown for better responsiveness across mouse/touch
75+
hole.addEventListener("pointerdown", (e) => {
76+
const target = e.target;
77+
if (target && target.classList && target.classList.contains("mole")) {
78+
// Register hit
79+
score++;
80+
scoreDisplay.textContent = score;
81+
82+
// Remove current mole and spawn the next immediately
83+
clearTimeout(moleTimer);
84+
target.remove();
85+
if (gameActive) {
86+
const { respawnDelayMs } = LEVELS[difficultySelect.value] || LEVELS.easy;
87+
// Add a smooth delay after whack before next mole
88+
setTimeout(() => showMole(), respawnDelayMs);
89+
}
90+
}
91+
});
92+
});
93+
94+
// Start game logic
95+
startBtn.addEventListener("click", () => {
96+
if (gameActive) return;
97+
98+
// Reset state
99+
score = 0;
100+
scoreDisplay.textContent = score;
101+
gameActive = true;
102+
startBtn.textContent = "Playing...";
103+
const { totalTimeSec } = LEVELS[difficultySelect.value] || LEVELS.easy;
104+
timeLeftDisplay.textContent = totalTimeSec;
105+
106+
// Kick off the loop
107+
showMole();
108+
109+
// Stop after 30 seconds
110+
clearTimeout(endTimer);
111+
clearInterval(tickTimer);
112+
113+
const start = Date.now();
114+
const totalMs = totalTimeSec * 1000;
115+
116+
// Countdown display (per second)
117+
tickTimer = setInterval(() => {
118+
const elapsed = Date.now() - start;
119+
const remaining = Math.max(0, Math.ceil((totalMs - elapsed) / 1000));
120+
timeLeftDisplay.textContent = remaining;
121+
}, 200);
122+
123+
endTimer = setTimeout(() => {
124+
gameActive = false;
125+
clearTimeout(moleTimer);
126+
clearInterval(tickTimer);
127+
timeLeftDisplay.textContent = 0;
128+
if (currentMole && currentMole.isConnected) currentMole.remove();
129+
startBtn.textContent = "Start Game";
130+
alert(`⏱️ Time's up! Your score: ${score}`);
131+
}, totalMs);
132+
});

examples/Whack-A-Mole/styles.css

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
* {
2+
box-sizing: border-box;
3+
margin: 0;
4+
padding: 0;
5+
font-family: "Poppins", sans-serif;
6+
}
7+
8+
body {
9+
background: linear-gradient(135deg, #3b1c32, #1b1a55);
10+
color: #fff;
11+
text-align: center;
12+
height: 100vh;
13+
display: flex;
14+
flex-direction: column;
15+
align-items: center;
16+
justify-content: center;
17+
}
18+
19+
h1 {
20+
font-size: 2.5rem;
21+
margin-bottom: 20px;
22+
}
23+
24+
.scoreboard {
25+
display: flex;
26+
align-items: center;
27+
gap: 1rem;
28+
margin-bottom: 25px;
29+
}
30+
31+
#difficulty {
32+
padding: 6px 10px;
33+
border-radius: 5px;
34+
border: 1px solid #fdbb2d;
35+
background: #1b1a55;
36+
color: #fff;
37+
font-weight: bold;
38+
outline: none;
39+
}
40+
41+
#difficulty option {
42+
background: #1b1a55;
43+
color: #fff;
44+
font-weight: bold;
45+
}
46+
47+
#start-btn {
48+
padding: 8px 20px;
49+
background: #fdbb2d;
50+
border: none;
51+
border-radius: 5px;
52+
font-weight: bold;
53+
cursor: pointer;
54+
transition: transform 0.2s, background 0.3s;
55+
}
56+
57+
#start-btn:hover {
58+
transform: scale(1.05);
59+
background: #ffc94d;
60+
}
61+
62+
.grid {
63+
display: grid;
64+
grid-template-columns: repeat(3, 100px);
65+
grid-gap: 15px;
66+
justify-content: center;
67+
}
68+
69+
.hole {
70+
width: 100px;
71+
height: 100px;
72+
background: #333;
73+
border-radius: 50%;
74+
position: relative;
75+
overflow: hidden;
76+
box-shadow: inset 0 5px 10px rgba(0, 0, 0, 0.5);
77+
}
78+
79+
.mole {
80+
width: 70px;
81+
height: 70px;
82+
background: url("https://cdn-icons-png.flaticon.com/512/616/616408.png")
83+
no-repeat center/contain;
84+
position: absolute;
85+
bottom: -70px;
86+
left: 50%;
87+
transform: translateX(-50%);
88+
animation: pop 0.9s ease-out forwards;
89+
cursor: pointer;
90+
}
91+
92+
@keyframes pop {
93+
0% {
94+
bottom: -70px;
95+
}
96+
50% {
97+
bottom: 10px;
98+
}
99+
100% {
100+
bottom: -70px;
101+
}
102+
}

0 commit comments

Comments
 (0)