Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Subhendu Tripathy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 🎮 Simon Says Game

A classic memory-enhancing game built with **Vanilla JavaScript**, featuring advanced DOM manipulation, smart audio feedback, and mobile responsiveness.

🔗 **Live Demo:** [Play the Game Here!](https://st-64.github.io/simon-says-game/)

## ✨ Key Features

- **🧠 Logic & State Management:** Tracks complex game sequences and validates user input in real-time.
- **⚡ Optimized Performance:** Uses **Event Delegation** to handle clicks efficiently with fewer event listeners.
- **📱 Fully Responsive:** Works seamlessly on Desktop (Keyboard/Mouse) and Mobile (Touch support).
- **🔊 Smart Audio Engine:**
- **Dynamic Sound Effects:** Distinct sounds for each actions.
- **Context-Aware Audio:** Plays a "Click" sound for normal moves but switches to a "Level Up" victory sound _only_ on the final winning move.
- **Background Music:** Loops automatically and pauses upon "Game Over."
- **🏆 High Score Tracking:** Persistently tracks and displays the user's personal best score during the session.

## 🛠️ Tech Stack

- **HTML5:** Semantic structure and audio elements.
- **CSS3:** Flexbox for layout, animations (flash/shake effects), and responsive media queries.
- **JavaScript (ES6+):** Game logic, DOM manipulation, `setTimeout` for timing, and `Audio()` object management.

## 🚀 How to Run Locally

1. **Clone the repository:**
```bash
git clone [https://github.com/st-64/simon-says-game.git](https://github.com/st-64/simon-says-game.git)
```
2. **Navigate to the folder:**
```bash
cd simon-says-game
```
3. **Open `index.html`:**
Simply double-click `index.html` or run it using VS Code "Live Server" to enable all audio features.

## 🕹️ How to Play

1. **Start:** Press any key (Desktop) or Tap the screen (Mobile) to begin.
2. **Watch:** The game will flash a color sequence.
3. **Repeat:** Click the buttons in the exact same order.
4. **Advance:** Each level adds one new step to the sequence.
5. **Game Over:** If you miss a step, the screen flashes red and the game resets. Try to beat your High Score!

## 📂 Project Structure

```text
/simon-says-game
├── index.html # Game structure and audio tags
├── style.css # Visual styling and animations
├── app.js # Game logic and event handling
└── /Sounds # Audio assets (bgm.mp3, click.mp3, etc.)
```
Binary file added Subhendu Tripathy/Simon Say Game/Sounds/bgm.mp3
Binary file not shown.
Binary file added Subhendu Tripathy/Simon Say Game/Sounds/click.mp3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added Subhendu Tripathy/Simon Say Game/Sounds/start.mp3
Binary file not shown.
139 changes: 139 additions & 0 deletions Subhendu Tripathy/Simon Say Game/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
let gameSeq = [];
let userSeq = [];

let btns = ['yellow', 'red', 'purple', 'green'];

let started = false;
let level = 0;
let highestScore = 0;

let h2 = document.querySelector("h2");
let scoreDisplay = document.querySelector(".score");

// 🔊 1. SETUP BACKGROUND MUSIC
let bgMusic = new Audio("Sounds/bgm.mp3");
bgMusic.loop = true;
bgMusic.volume = 0.5;

// 🔊 2. HELPER FUNCTION
function playSound(name) {
let audio = new Audio(`Sounds/${name}.mp3`);
audio.play();
}

function startGame() {
if (started == false) {
console.log("game is started");

// 🔊 3. PLAY START SOUND & BACKGROUND MUSIC
playSound("start");
bgMusic.play().catch(e => console.log("Audio play failed: ", e));

setTimeout(function () {
started = true;
levelUp();
}, 100);
}
}

document.addEventListener('keypress', startGame);
document.addEventListener('touchstart', startGame);

function gameFlash(btn) {
btn.classList.add('flash');
setTimeout(function () {
btn.classList.remove('flash');
}, 250);
}

function userFlash(btn) {
btn.classList.add('userflash');
setTimeout(function () {
btn.classList.remove('userflash');
}, 250);
}

function levelUp() {
userSeq = [];
level++;
h2.innerText = `Level ${level}`;

let randIdx = Math.floor(Math.random() * 4);
let randColor = btns[randIdx];
let randBtn = document.querySelector(`.${randColor}`);

gameSeq.push(randColor);
console.log("game seq: ", gameSeq);

gameFlash(randBtn);
};

function checkAns(idx) {
if (userSeq[idx] == gameSeq[idx]) {
// --- CORRECT MOVE ---

if (userSeq.length === gameSeq.length) {
// ✅ Case A: Level Completed (Victory!)
// We wait 250ms, then play Level Up sound (No click sound)
setTimeout(function () {
playSound("levelup");
}, 250);

setTimeout(levelUp, 1000);
} else {
// ✅ Case B: Middle of sequence (Normal)
// Play the normal click sound immediately
playSound("click");
}

} else {
// --- GAME OVER LOGIC ---
h2.innerHTML = `Game Over! Your score was <b>${level}</b> <br> Press any key to start`;

// 🔊 Stop Music & Play Game Over
bgMusic.pause();
bgMusic.currentTime = 0;
playSound("gameover");

document.querySelector("body").classList.add("game-over");
setTimeout(function () {
document.querySelector("body").classList.remove("game-over");
}, 200);

reset();
}
}

function btnPress() {
if (started) {
let btn = this;
userFlash(btn);

let userColor = btn.getAttribute("id");
userSeq.push(userColor);

// ❌ REMOVED: playSound("click");
// We removed it from here because checkAns now handles it!

checkAns(userSeq.length - 1);
}
}

let allBtns = document.querySelectorAll(".btn");
for (const btn of allBtns) {
btn.addEventListener('click', btnPress);
}

function reset() {
started = false;

if (highestScore < level) {
highestScore = level;
}

scoreDisplay.innerHTML = `Your Highest Score: <b>${highestScore}</b>`;

level = 0;
gameSeq = [];
userSeq = [];
}
24 changes: 24 additions & 0 deletions Subhendu Tripathy/Simon Say Game/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simon Says Game</title>
<link rel="stylesheet" href="style.css">
</head>

<body>
<h1>Simon Says Game</h1>
<h2>Press any key to Start the game</h2>
<h2 class="score"></h2>
<div class="btn-container">
<div class="btn red" type="button" id="red">1</div>
<div class="btn yellow" type="button" id="yellow">2</div>
<div class="btn green" type="button" id="green">3</div>
<div class="btn purple" type="button" id="purple">4</div>
</div>
<script src="app.js"></script>
</body>

</html>
123 changes: 123 additions & 0 deletions Subhendu Tripathy/Simon Say Game/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
body {
text-align: center;
/* High quality dark space background */
background: url('https://images.unsplash.com/photo-1534796636912-3b95b3ab5986?q=80&w=2072&auto=format&fit=crop') no-repeat center center/cover;

color: white;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

/* This darkens the image slightly so your game buttons shine brighter */
box-shadow: inset 0 0 0 1000px rgba(0, 0, 0, 0.3);

min-height: 100vh;
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
}

.btn-container {
display: flex;
flex-wrap: wrap;
/* This creates the 2x2 grid automatically */
justify-content: center;
max-width: 500px;
margin: 0 auto;
}

.btn {
height: 200px;
width: 200px;
margin: 0.75rem;
border-radius: 20%;
border: 8px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}

.red {
background-color: #d95980;
/* background-color: red; */
}

.green {
background-color: #63aac0;
/* background-color: green; */
}

.yellow {
background-color: #f99b49;
/* background-color: yellow; */
}

.purple {
background-color: #819ff9;
/* background-color: purple; */
}

.flash {
background-color: white;
}

.userflash {
background-color: green;
}

/* This class will be added briefly when the user fails */
.game-over {
/* A Red/Dark "Danger" Space Image */
background: linear-gradient(rgba(255, 0, 0, 0.6), rgba(255, 0, 0, 0.6)), url('https://images.unsplash.com/photo-1490730141103-6cac27aaab94?q=80&w=2070&auto=format&fit=crop') no-repeat center center/cover !important;

/* Optional: Shake animation */
animation: shake 0.2s ease-in-out;
}

/* Optional: Adds a shaking effect for extra impact */
@keyframes shake {
0% {
transform: translateX(0);
}

25% {
transform: translateX(-10px);
}

50% {
transform: translateX(10px);
}

75% {
transform: translateX(-10px);
}

100% {
transform: translateX(0);
}
}

/* 2. Media Query for Phones (Screens smaller than 768px) */
@media (max-width: 768px) {

/* Adjust the heading text size */
h2 {
font-size: 1.5rem;
}

/* Shrink the buttons */
.btn {
height: 130px;
/* Smaller size for mobile */
width: 130px;
margin: 10px;
/* Reduce gap between buttons */
border-width: 5px;
/* Thinner border for cleaner look */
}
}

/* 3. Media Query for Very Small Phones (Screens smaller than 400px) */
@media (max-width: 400px) {
.btn {
height: 110px;
width: 110px;
}
}