diff --git a/.github/workflows/pr_tags.yaml b/.github/workflows/pr_tags.yaml
deleted file mode 100644
index 44f8d599d4..0000000000
--- a/.github/workflows/pr_tags.yaml
+++ /dev/null
@@ -1,78 +0,0 @@
-# name: Pull Request Labels
-
-# on:
-# pull_request_target:
-# types:
-# - opened
-# - synchronize
-
-# jobs:
-# pr-validation:
-# runs-on: ubuntu-latest
-
-# steps:
-# - name: Checkout repository
-# uses: actions/checkout@v2
-
-# - name: Set up Node.js
-# uses: actions/setup-node@v2
-# with:
-# node-version: '14'
-
-# - name: Install dependencies
-# run: npm install --prefix .github octokit
-
-# - name: Fetch related issue and labels
-# id: fetch_issue
-# uses: actions/github-script@v4
-# with:
-# github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
-# script: |
-# const prNumber = context.payload.pull_request.number;
-# const repoOwner = context.payload.repository.owner.login;
-# const repoName = context.payload.repository.name;
-
-# const { data: pr } = await github.pulls.get({
-# owner: repoOwner,
-# repo: repoName,
-# pull_number: prNumber
-# });
-
-# const issueNumber = pr.body.match(/#([0-9]+)/)[1];
-
-# const { data: issue } = await github.issues.get({
-# owner: repoOwner,
-# repo: repoName,
-# issue_number: issueNumber
-# });
-
-# return {
-# issue: issue,
-# prNumber: prNumber,
-# repoOwner: repoOwner,
-# repoName: repoName
-# };
-
-# - name: Apply labels to PR
-# if: |
-# steps.fetch_issue.outputs.issue.labels.some(function(label) {
-# return label.name.toLowerCase() === 'gssoc';
-# })
-# run: |
-# const issueLabels = steps.fetch_issue.outputs.issue.labels;
-# const prNumber = steps.fetch_issue.outputs.prNumber;
-# const repoOwner = steps.fetch_issue.outputs.repoOwner;
-# const repoName = steps.fetch_issue.outputs.repoName;
-
-# const prLabels = issueLabels.filter(function(label) {
-# return label.name.toLowerCase().startsWith('level');
-# });
-# prLabels.push('gssoc');
-# await github.issues.addLabels({
-# owner: repoOwner,
-# repo: repoName,
-# issue_number: prNumber,
-# labels: prLabels.map(function(label) {
-# return label.name;
-# })
-# });
\ No newline at end of file
diff --git a/.github/workflows/restrict_pr.yml b/.github/workflows/restrict_pr.yml
new file mode 100644
index 0000000000..3a33b59262
--- /dev/null
+++ b/.github/workflows/restrict_pr.yml
@@ -0,0 +1,113 @@
+name: Restrict Contributor to limited contributions in GameZone
+
+on:
+ pull_request_target:
+ types:
+ - opened
+
+jobs:
+ evaluate_and_close:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check merged pull requests and calculate score
+ id: calculate_score
+ uses: actions/github-script@v4
+ with:
+ github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
+ script: |
+ const owner = context.repo.owner;
+ const repo = context.repo.repo;
+ const pullRequestOpener = context.payload.pull_request.user.login;
+
+ let mergedPullRequests = [];
+ let page = 1;
+ let perPage = 100;
+ let response;
+
+ do {
+ response = await github.pulls.list({
+ owner,
+ repo,
+ state: 'closed',
+ per_page: perPage,
+ page: page
+ });
+
+ mergedPullRequests = mergedPullRequests.concat(response.data.filter(pr => pr.user.login === pullRequestOpener && pr.merged_at !== null));
+ page++;
+ } while (response.data.length === perPage);
+
+ let score = 0;
+ let prDetails = [];
+ const scoreMap = {
+ 'level3': 45,
+ 'level2': 25,
+ 'level1': 10
+ };
+
+ for (const pr of mergedPullRequests) {
+ let prScore = 0;
+ let labelsWithScores = [];
+ for (const label of pr.labels) {
+ if (scoreMap[label.name]) {
+ prScore += scoreMap[label.name];
+ labelsWithScores.push(`${label.name} score: (${scoreMap[label.name]})`);
+ }
+ }
+ score += prScore;
+ if (labelsWithScores.length > 0) {
+ prDetails.push(`- [#${pr.number}](${pr.html_url}) with labels: ${labelsWithScores.join(', ')}`);
+ }
+ }
+
+ const threshold = 150;
+
+ console.log(`User score: ${score}`);
+ console.log(`Score threshold: ${threshold}`);
+
+ if (score >= threshold) {
+ const comment = `Hey @${pullRequestOpener}, You have reached your limit to contribute in GameZone with a score of ${score}. \n We believe in giving equal opportunity to everyone so you will not be able to contribute to GameZone now onwards. 💗 \n Thank you for your valuable time and contribution in GameZone 🕹️! \n\n Your merged pull requests:\n${prDetails.join('\n')}`;
+ core.exportVariable('comment_body', comment);
+ core.setOutput('close_pull_request', true);
+ } else {
+ core.exportVariable('comment_body', '');
+ core.setOutput('close_pull_request', false);
+ }
+
+ - name: Add spam label and close the pull request
+ if: always() && steps.calculate_score.outputs.close_pull_request == 'true'
+ uses: actions/github-script@v4
+ with:
+ github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
+ script: |
+ const owner = context.repo.owner;
+ const repo = context.repo.repo;
+ const pullRequestNumber = context.payload.pull_request.number;
+ const comment = process.env.comment_body;
+
+ if (comment.trim() === '') {
+ console.log('Comment body is empty. Skipping comment creation.');
+ return;
+ }
+
+ await github.issues.createComment({
+ owner,
+ repo,
+ issue_number: pullRequestNumber,
+ body: comment
+ });
+
+ await github.issues.addLabels({
+ owner,
+ repo,
+ issue_number: pullRequestNumber,
+ labels: ['spam🚨']
+ });
+
+ await github.pulls.update({
+ owner,
+ repo,
+ pull_number: pullRequestNumber,
+ state: 'closed'
+ });
diff --git a/Games/Alien_Invasion/.DS_Store b/Games/Alien_Invasion/.DS_Store
new file mode 100644
index 0000000000..74e30099e6
Binary files /dev/null and b/Games/Alien_Invasion/.DS_Store differ
diff --git a/Games/Alien_Invasion/README..md b/Games/Alien_Invasion/README..md
new file mode 100644
index 0000000000..17a09c4382
--- /dev/null
+++ b/Games/Alien_Invasion/README..md
@@ -0,0 +1,20 @@
+# AttackAlienInvaders Game App
+A cool 2D alien planet exploration steampunk-themed game application with techniques of vanilla JavaScript, HTML5, CSS3 and HTML Canvas. From sprite animation to parallax backgrounds, the game App is completely built from scratch, with no frameworks or libraries, using HTML, CSS and plain vanilla JavaScript. The game contains richful premium art assets for characters, environments and props.
+
+### [Game Won Demo](https://github.com/KrystalZhang612/KrystalZhang-AttackAlienInvaders-Game-App/blob/main/testing-result-AttackAlienInvader-game-app/Won%20Game.mov): Most Wondrous! Well done explorer!
+https://user-images.githubusercontent.com/72481348/198857930-95a5c040-1d47-4ca6-b5a6-15ac05e8e520.mov
+### [Game Lost Demo](https://github.com/KrystalZhang612/KrystalZhang-AttackAlienInvaders-Game-App/blob/main/testing-result-AttackAlienInvader-game-app/Lost%20Game.mov): Blazed! Get my repair kit and try again!
+https://user-images.githubusercontent.com/72481348/198857699-86d076d4-f746-435b-89ec-333ad1ba01b8.mov
+
+# Game Premiere Storyline
+***Central Computer***:
+`These alien creatures have very similar physiology to the earth seahorses. Their bodies can easily cut through the thick atmosphere. They can move very fast.`
+***Explorer***:
+`Seahorses hives are being attacked by something. This one has been damaged. I wonder if you can hack into this creature’s central computer to control it for a while.`
+***Central Computer***:
+`It is surprisingly easy to override its circuits. Seems like these machines are not used by our technology. I’m getting a lot of new data.`
+***Central Computer***:
+`The atmosphere on this planet is thick enough to allow heavy silicon-based lifeforms to float but smoke is blocking most of the sunlight. Many creatures developed artificial lights and glowing appendages to see through the heavy clouds. The Seahorse sentinel has a basic attack that’s powerful against weak enemies, but if it absorbs energy from one of the overcharged creatures, it gets additional firepower for a short period of time and it instantly replenishes its ammo. Ammo also automatically recharges over time. It seems we just need to help it to get through these aggressive swarms in time so it can join its hive.`
+- There is a stream of data about multiple different species.
+- The alien creatures in the hood of their ecosystem have special movements, special abilities, and interact with the environments on other planets.
+
diff --git a/Games/Alien_Invasion/index.html b/Games/Alien_Invasion/index.html
new file mode 100644
index 0000000000..760bb1af1b
--- /dev/null
+++ b/Games/Alien_Invasion/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
diff --git a/Games/Alphabet-and-Vowels/style.css b/Games/Alphabet-and-Vowels/style.css
new file mode 100644
index 0000000000..ae806620eb
--- /dev/null
+++ b/Games/Alphabet-and-Vowels/style.css
@@ -0,0 +1,69 @@
+body {
+ font-family: 'Arial', sans-serif;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ margin: 0;
+ background-color: #16d1e2;
+}
+
+.container {
+ text-align: center;
+ background: #fff;
+ padding: 20px;
+ border-radius: 10px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+}
+
+h1 {
+ color: #333;
+}
+
+.alphabet-grid {
+ display: grid;
+ grid-template-columns: repeat(6, 50px);
+ gap: 10px;
+ justify-content: center;
+ margin: 20px 0;
+}
+
+.alphabet-grid button {
+ background-color: #008cba;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ width: 50px;
+ height: 50px;
+ font-size: 18px;
+ cursor: pointer;
+ transition: background-color 0.3s;
+}
+
+.alphabet-grid button.correct {
+ background-color: #4caf50;
+}
+
+.alphabet-grid button.wrong {
+ background-color: #f44336;
+}
+
+#feedback {
+ margin-top: 20px;
+ font-size: 20px;
+}
+
+#resetButton {
+ background-color: #ff9800;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ padding: 10px 20px;
+ font-size: 18px;
+ cursor: pointer;
+ transition: background-color 0.3s;
+}
+
+#resetButton:hover {
+ background-color: #e68900;
+}
diff --git a/Games/Atlas_Game/README.md b/Games/Atlas_Game/README.md
new file mode 100644
index 0000000000..f3549cd47f
--- /dev/null
+++ b/Games/Atlas_Game/README.md
@@ -0,0 +1,35 @@
+# **Atlas: Indian Cities Edition**
+---
+
+
+## **Description 📃**
+
+Welcome to the Atlas Game! This game challenges players to name Indian cities based on the last letter of the previous city's name. Enjoy testing your knowledge of Indian geography while racing against the clock.
+
+
+
+## **Functionalities 🎮**
+- The game starts with a randomly selected Indian city displayed on the screen.
+- The player must enter an Indian city starting with the last letter of the current place.
+- The same Indian city cannot be used more than once during the game.
+- The player has 15 seconds to enter a valid Indian city. If the time runs out, the game ends.
+- The game continues until the player can no longer provide a valid Indian city or the time runs out.
+
+
+
+## **How to play? 🕹️**
+- Open index.html in your web browser to start the game.
+- The game will display a randomly selected Indian city.
+- Enter an Indian city starting with the last letter of the displayed city and press the "Submit" button.
+- The game will check your input and, if valid, will display the next city.
+- If the timer runs out or you enter an invalid city, the game ends.
+- Click the "Reset" button to start a new game.
+
+
+
+## **Screenshots 📸**
+
+
+![image](https://github.com/kunjgit/GameZone/assets/127378920/5d8325e1-7877-4edc-aaac-ab68813f7e6c)
+![Screenshot 2024-06-12 023938](https://github.com/kunjgit/GameZone/assets/127378920/dabcc50e-0f9a-4f48-96bb-267975070326)
+![image](https://github.com/kunjgit/GameZone/assets/127378920/fc823f97-b638-438a-8d98-627d13b5ca77)
diff --git a/Games/Atlas_Game/bg.webp b/Games/Atlas_Game/bg.webp
new file mode 100644
index 0000000000..f148133761
Binary files /dev/null and b/Games/Atlas_Game/bg.webp differ
diff --git a/Games/Atlas_Game/index.html b/Games/Atlas_Game/index.html
new file mode 100644
index 0000000000..7158881499
--- /dev/null
+++ b/Games/Atlas_Game/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ World Atlas Game
+
+
+
+
ATLAS GAME
+
(Indian Cities Edition)
+
+
+
+
+
+
+
15
+
+
+
+
Rules:
+
+
The game starts with a randomly selected Indian city displayed on the screen.
+
The player must enter an Indian city starting with the last letter of the current place.
+
The same Indian city cannot be used more than once during the game.
+
The player has 15 seconds to enter a valid Indian city. If the time runs out, the game ends.
+
The game continues until the player can no longer provide a valid Indian city or the time runs out.
+
+
+
+
+
+
diff --git a/Games/Atlas_Game/places.json b/Games/Atlas_Game/places.json
new file mode 100644
index 0000000000..fab1364544
--- /dev/null
+++ b/Games/Atlas_Game/places.json
@@ -0,0 +1,323 @@
+{
+ "places": [
+ "Agartala",
+ "Agra",
+ "Ahmedabad",
+ "Aizawl",
+ "Ajmer",
+ "Akola",
+ "Alappuzha",
+ "Aligarh",
+ "Allahabad",
+ "Alwar",
+ "Amaravati",
+ "Ambala",
+ "Ambarnath",
+ "Ambattur",
+ "Amravati",
+ "Amritsar",
+ "Amroha",
+ "Anand",
+ "Anantapur",
+ "Andheri",
+ "Ankleshwar",
+ "Arrah",
+ "Asansol",
+ "Aurangabad",
+ "Aurangabad",
+ "Avadi",
+ "Baharampur",
+ "Bahraich",
+ "Bangalore",
+ "Baranagar",
+ "Bardhaman",
+ "Bareilly",
+ "Bathinda",
+ "Beawar",
+ "Belgaum",
+ "Bellary",
+ "Berhampur",
+ "Betul",
+ "Bhagalpur",
+ "Bharatpur",
+ "Bharuch",
+ "Bhatpara",
+ "Bhavnagar",
+ "Bhilai",
+ "Bhilwara",
+ "Bhimavaram",
+ "Bhind",
+ "Bhiwadi",
+ "Bhiwandi",
+ "Bhiwani",
+ "Bhopal",
+ "Bhubaneswar",
+ "Bhuj",
+ "Bidar",
+ "Bihar Sharif",
+ "Bijapur",
+ "Bikaner",
+ "Bilaspur",
+ "Bokaro",
+ "Bombay",
+ "Bongaigaon",
+ "Bulandshahr",
+ "Burdwan",
+ "Burhanpur",
+ "Chandigarh",
+ "Chandrapur",
+ "Chapra",
+ "Chennai",
+ "Chhindwara",
+ "Chhota Udaipur",
+ "Chikkamagaluru",
+ "Chitradurga",
+ "Chittoor",
+ "Churu",
+ "Coimbatore",
+ "Cuddalore",
+ "Cuttack",
+ "Dadra and Nagar Haveli",
+ "Dahod",
+ "Daman and Diu",
+ "Darbhanga",
+ "Darjeeling",
+ "Davanagere",
+ "Dehradun",
+ "Dehri",
+ "Delhi",
+ "Deoghar",
+ "Dewas",
+ "Dhanbad",
+ "Dharmavaram",
+ "Dhule",
+ "Dibrugarh",
+ "Dimapur",
+ "Dindigul",
+ "Durg",
+ "Durgapur",
+ "Eluru",
+ "Erode",
+ "Etawah",
+ "Faridabad",
+ "Faridkot",
+ "Farrukhabad",
+ "Fatehpur",
+ "Fazilka",
+ "Firozabad",
+ "Firozpur",
+ "Gadag",
+ "Gandhidham",
+ "Gandhinagar",
+ "Ganganagar",
+ "Gangtok",
+ "Gaya",
+ "Ghaziabad",
+ "Giridih",
+ "Godhra",
+ "Gondia",
+ "Gorakhpur",
+ "Gudivada",
+ "Gulbarga",
+ "Guna",
+ "Guntur",
+ "Gurgaon",
+ "Guwahati",
+ "Gwalior",
+ "Hajipur",
+ "Haldia",
+ "Haldwani",
+ "Haridwar",
+ "Hassan",
+ "Hathras",
+ "Hazaribagh",
+ "Hisar",
+ "Hospet",
+ "Hubli",
+ "Hyderabad",
+ "Ichalkaranji",
+ "Imphal",
+ "Indore",
+ "Itanagar",
+ "Jabalpur",
+ "Jagdalpur",
+ "Jaipur",
+ "Jalandhar",
+ "Jalgaon",
+ "Jalna",
+ "Jamalpur",
+ "Jammu",
+ "Jamnagar",
+ "Jamshedpur",
+ "Jaunpur",
+ "Jhansi",
+ "Jodhpur",
+ "Jorhat",
+ "Junagadh",
+ "Kadapa",
+ "Kakinada",
+ "Kalaburagi",
+ "Kalyan",
+ "Kamarhati",
+ "Kanchipuram",
+ "Kannur",
+ "Kanpur",
+ "Karaikudi",
+ "Karachi",
+ "Karimnagar",
+ "Karnal",
+ "Karur",
+ "Kasaragod",
+ "Kathmandu",
+ "Katihar",
+ "Kayamkulam",
+ "Kendrapara",
+ "Kendujhar",
+ "Keshod",
+ "Khammam",
+ "Khandwa",
+ "Kharagpur",
+ "Khargone",
+ "Kishanganj",
+ "Kochi",
+ "Kohima",
+ "Kolar",
+ "Kolhapur",
+ "Kolkata",
+ "Kollam",
+ "Korba",
+ "Kota",
+ "Kottayam",
+ "Kozhikode",
+ "Krishnanagar",
+ "Kumarakom",
+ "Kumbakonam",
+ "Kurnool",
+ "Kurukshetra",
+ "Latur",
+ "Lonavala",
+ "Lucknow",
+ "Ludhiana",
+ "Madurai",
+ "Mahbubnagar",
+ "Malappuram",
+ "Malegaon",
+ "Mangalore",
+ "Mathura",
+ "Meerut",
+ "Mehsana",
+ "Mirzapur",
+ "Moradabad",
+ "Mumbai",
+ "Muzaffarnagar",
+ "Muzaffarpur",
+ "Mysore",
+ "Nagercoil",
+ "Nagpur",
+ "Nainital",
+ "Nalgonda",
+ "Namakkal",
+ "Nanded",
+ "Nashik",
+ "Navsari",
+ "Nellore",
+ "New Delhi",
+ "Nizamabad",
+ "Noida",
+ "Ongole",
+ "Ooty",
+ "Osmanabad",
+ "Pala",
+ "Palakkad",
+ "Pali",
+ "Pallavaram",
+ "Panchkula",
+ "Panipat",
+ "Panvel",
+ "Parbhani",
+ "Pathankot",
+ "Patiala",
+ "Patna",
+ "Pilibhit",
+ "Porbandar",
+ "Port Blair",
+ "Prayagraj",
+ "Proddatur",
+ "Puducherry",
+ "Pune",
+ "Puri",
+ "Purnia",
+ "Raebareli",
+ "Raichur",
+ "Raiganj",
+ "Raigarh",
+ "Raipur",
+ "Rajahmundry",
+ "Rajapalayam",
+ "Rajkot",
+ "Rajnandgaon",
+ "Rajnagar",
+ "Ramagundam",
+ "Ramanathapuram",
+ "Ranchi",
+ "Ratlam",
+ "Ratnagiri",
+ "Raurkela",
+ "Rewa",
+ "Rohtak",
+ "Rourkela",
+ "Saharanpur",
+ "Saharsa",
+ "Salem",
+ "Sambalpur",
+ "Sangli",
+ "Satara",
+ "Satna",
+ "Secunderabad",
+ "Shillong",
+ "Shimla",
+ "Shimoga",
+ "Sikar",
+ "Siliguri",
+ "Sivakasi",
+ "Solapur",
+ "Sonipat",
+ "Sri Ganganagar",
+ "Srikakulam",
+ "Srinagar",
+ "Surat",
+ "Surendranagar",
+ "Tadepalligudem",
+ "Tadpatri",
+ "Tandur",
+ "Tezpur",
+ "Thanjavur",
+ "Theni",
+ "Thiruvananthapuram",
+ "Thoothukudi",
+ "Thrissur",
+ "Tinsukia",
+ "Tiruchirappalli",
+ "Tirunelveli",
+ "Tirupati",
+ "Tiruppur",
+ "Tiruvannamalai",
+ "Udaipur",
+ "Udupi",
+ "Ujjain",
+ "Ulhasnagar",
+ "Unnao",
+ "Vadodara",
+ "Valsad",
+ "Varanasi",
+ "Vellore",
+ "Vijayawada",
+ "Visakhapatnam",
+ "Vizianagaram",
+ "Warangal",
+ "Wardha",
+ "Yamunanagar",
+ "Yavatmal"
+ ]
+ }
+
\ No newline at end of file
diff --git a/Games/Atlas_Game/script.js b/Games/Atlas_Game/script.js
new file mode 100644
index 0000000000..b1474c7840
--- /dev/null
+++ b/Games/Atlas_Game/script.js
@@ -0,0 +1,116 @@
+const currentPlaceElement = document.getElementById('current-place');
+const userInput = document.getElementById('user-input');
+const submitButton = document.getElementById('submit-button');
+const resetButton = document.getElementById('reset-button');
+const messageElement = document.getElementById('message');
+const timerElement = document.getElementById('timer');
+const timerContainer = document.getElementById('timer-container');
+
+let places = [];
+let usedPlaces = new Set();
+let timer;
+let timerInterval;
+
+async function fetchPlaces() {
+ const response = await fetch('places.json', {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const data = await response.json();
+ return data.places;
+}
+
+function getRandomPlace() {
+ const availablePlaces = places.filter(place => !usedPlaces.has(place.toLowerCase()));
+ if (availablePlaces.length === 0) {
+ return null;
+ }
+ return availablePlaces[Math.floor(Math.random() * availablePlaces.length)];
+}
+
+function isValidPlace(place) {
+ return places.some(p => p.toLowerCase() === place.toLowerCase());
+}
+
+function getNextPlaceStartingWith(letter) {
+ const availablePlaces = places.filter(place => !usedPlaces.has(place.toLowerCase()) && place[0].toLowerCase() === letter.toLowerCase());
+ if (availablePlaces.length === 0) {
+ return null;
+ }
+ return availablePlaces[Math.floor(Math.random() * availablePlaces.length)];
+}
+
+function startTimer() {
+ clearInterval(timerInterval);
+ timer = 15;
+ timerElement.textContent = timer;
+ userInput.disabled = false;
+ timerContainer.classList.remove('red');
+
+ timerInterval = setInterval(() => {
+ timer--;
+ timerElement.textContent = timer;
+ if (timer <= 5) {
+ timerContainer.classList.add('red');
+ }
+ if (timer <= 0) {
+ clearInterval(timerInterval);
+ messageElement.textContent = 'Time\'s up! You didn\'t enter a valid place in time.';
+ userInput.disabled = true;
+ }
+ }, 1000);
+}
+
+function resetGame() {
+ usedPlaces.clear();
+ userInput.value = '';
+ messageElement.textContent = '';
+ initializeGame();
+}
+
+async function initializeGame() {
+ try {
+ places = await fetchPlaces();
+ let currentPlace = getRandomPlace();
+ if (currentPlace) {
+ usedPlaces.add(currentPlace.toLowerCase());
+ currentPlaceElement.textContent = currentPlace;
+ startTimer();
+ } else {
+ messageElement.textContent = 'No more places available.';
+ }
+
+ submitButton.addEventListener('click', () => {
+ const userPlace = userInput.value.trim();
+ if (isValidPlace(userPlace) && !usedPlaces.has(userPlace.toLowerCase())) {
+ const lastLetter = userPlace.slice(-1).toLowerCase();
+ const nextPlace = getNextPlaceStartingWith(lastLetter);
+ if (nextPlace) {
+ usedPlaces.add(userPlace.toLowerCase());
+ currentPlace = nextPlace;
+ usedPlaces.add(currentPlace.toLowerCase());
+ currentPlaceElement.textContent = currentPlace;
+ userInput.value = '';
+ messageElement.textContent = '';
+ startTimer();
+ } else {
+ messageElement.textContent = 'No place found starting with "' + lastLetter.toUpperCase() + '".';
+ }
+ } else if (usedPlaces.has(userPlace.toLowerCase())) {
+ messageElement.textContent = '"' + userPlace + '" has already been used.';
+ } else {
+ messageElement.textContent = '"' + userPlace + '" is not a city in India.';
+ }
+ });
+
+ resetButton.addEventListener('click', resetGame);
+ } catch (error) {
+ console.error('Error fetching places:', error);
+ messageElement.textContent = 'Error fetching places. Please try again later.';
+ }
+}
+
+// Initialize the game
+initializeGame();
diff --git a/Games/Atlas_Game/style.css b/Games/Atlas_Game/style.css
new file mode 100644
index 0000000000..b763b40842
--- /dev/null
+++ b/Games/Atlas_Game/style.css
@@ -0,0 +1,99 @@
+body {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ height: 100vh;
+ font-family: 'Arial', sans-serif;
+ position: relative;
+ background-image: url('bg.webp');
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+#header {
+ font-size: 68px;
+ margin-bottom: 0;
+}
+
+#subheader {
+ margin-top: 0;
+ font-size: 25px;
+ font-style: italic;
+ margin-bottom: 0;
+}
+
+#game {
+ margin-top: 0px;
+ padding-top: 20px;
+ text-align: center;
+}
+
+#user-input {
+ margin: 10px;
+ padding: 10px;
+ font-size: 1em;
+}
+
+#current-place {
+ color: rgb(47, 1, 48);
+ font-style: italic;
+}
+
+.btn {
+ padding: 10px 20px;
+ font-size: 1em;
+ cursor: pointer;
+}
+
+.btn:hover{
+ background-color: aliceblue;
+}
+
+#message {
+ margin-top: 20px;
+ font-size: 1.2em;
+ color: white;
+ font-weight: bold;
+}
+
+#timer-container {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ width: 60px;
+ height: 60px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border: 5px solid darkblue;
+ border-radius: 50%;
+ font-size: 1.5em;
+}
+
+#timer-container.red {
+ border-color: red;
+}
+
+#timer {
+ color: white;
+}
+
+#rules{
+ text-align: left;
+ color: white;
+ position:absolute;
+ left: 10px;
+ bottom: 10px;
+ font-size: 18px;
+}
+
+#rules h3{
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+
+#rules ol{
+ margin-top: 0;
+}
\ No newline at end of file
diff --git a/Games/Audio_Wordle/README.md b/Games/Audio_Wordle/README.md
new file mode 100644
index 0000000000..418c2e51b6
--- /dev/null
+++ b/Games/Audio_Wordle/README.md
@@ -0,0 +1,37 @@
+# **Auddle: Audio Wordle**
+
+---
+
+
+
+## **Description 📃**
+Auddle is a fun and challenging word-guessing game where players must identify the correct word based on an audio clue. Each round provides a new audio clip, and players have six guesses to find the correct answer. The game combines the classic Wordle mechanics with an audio twist, offering a unique and engaging experience.
+-
+
+## **functionalities 🎮**
+1. Randomized Audio Clues: Each game round starts with a random audio clip from a pre-defined list.
+2. Multiple Attempts: Players have six attempts to guess the correct word.
+3. Feedback System: The game provides color-coded feedback to indicate correct letters, correct positions, and incorrect letters.
+4. Audio Playback: Players can replay the audio clue as many times as needed.
+-
+
+
+## **How to play? 🕹️**
+1. Start the Game: Click the start button to begin a new game round.
+2. Listen to the Audio Clue: An audio clip will play. You can replay the clip by clicking the replay button.
+3. Make a Guess: Type in your guess and submit it.
+4. Receive Feedback: The game will provide feedback with colored tiles:
+ - Green: Correct letter in the correct position.
+ - Yellow: Correct letter in the wrong position.
+ - Gray: Incorrect letter.
+5. Repeat: Use the feedback to make a better guess. You have six attempts to find the correct word.
+6. Win or Lose: If you guess the word correctly within six attempts, you win! Otherwise, the game will reveal the correct answer.
+-
+
+
+
+## **Screenshots 📸**
+
+![Screenshot](image.png)
+
+
diff --git a/Games/Audio_Wordle/images/backspace-outline.svg b/Games/Audio_Wordle/images/backspace-outline.svg
new file mode 100644
index 0000000000..7e3d5aac55
--- /dev/null
+++ b/Games/Audio_Wordle/images/backspace-outline.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Games/Audio_Wordle/images/d.svg b/Games/Audio_Wordle/images/d.svg
new file mode 100644
index 0000000000..ab0af87f63
--- /dev/null
+++ b/Games/Audio_Wordle/images/d.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/Games/Audio_Wordle/images/github.svg b/Games/Audio_Wordle/images/github.svg
new file mode 100644
index 0000000000..a1cb51389c
--- /dev/null
+++ b/Games/Audio_Wordle/images/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Games/Audio_Wordle/images/return.svg b/Games/Audio_Wordle/images/return.svg
new file mode 100644
index 0000000000..3c6451e679
--- /dev/null
+++ b/Games/Audio_Wordle/images/return.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Games/Audio_Wordle/index.html b/Games/Audio_Wordle/index.html
new file mode 100644
index 0000000000..b59819d35a
--- /dev/null
+++ b/Games/Audio_Wordle/index.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+ Auddle - Audio Wordle!
+
+
+
+
+
+
+
+
diff --git a/Games/Brick_Breaker/script.js b/Games/Brick_Breaker/script.js
index 00c32f35a9..54001cefab 100644
--- a/Games/Brick_Breaker/script.js
+++ b/Games/Brick_Breaker/script.js
@@ -51,6 +51,8 @@ function ballRest() {
function brickReset() {
brickCount = 0;
+ initializeBrickColors();
+
var i;
for (var i = 0; i < 3 * BRICK_COLS; i++) {
brickGrid[i] = false;
@@ -138,18 +140,54 @@ function ballBrickColl() {
}
if (brickCount === 0) {
brickReset();
- updateScore(0); // Reset the score to 0 when all bricks are destroyed
+ updateScore(0);
+ scoredisplay(false); // Reset the score to zero if no bricks are remaining
} else {
updateScore(brickCount); // Update the score with the remaining brick count
+ scoredisplay(true); // Increment the score if a brick is hit
}
+
// colorText(ballBrickCol+","+ballBrickRow+": "+brickIndexUnderBall, mouseX, mouseY, 'white');
+
+ if(brickCount=== 70){
+ scoredisplay(0);
+ }
}
function updateScore(score) {
var scoreElement = document.getElementById("score");
scoreElement.textContent = "Bricks Remaining: " + score;
+
+}
+
+var s = 0; // Declare the variable outside the function to store the score
+var y=0;
+function scoredisplay(hit) {
+ if (hit) {
+ s=70-brickCount;
+ if(s>20){
+ y=s-20;
+ s=s+y*4;
+ }
+ else if(s>10){
+ y=s-10;
+ s=s+y;
+ }
+
+
+ } else if(brickCount==70){
+ s = 0; // Reset the score to zero if no bricks are hit
+ }
+
+
+ // Update the content of the HTML element with id "s" to display the score
+ var scoredisplayElement = document.getElementById("s");
+ scoredisplayElement.textContent = "Score: " + s;
}
+
+
+
function paddleMove() {
// paddle
var paddleTopEdgeY = canvas.height - PADDLE_DIST_FROM_EDGE;
@@ -199,7 +237,7 @@ function updateMousePos(evt) {
/**********GamePlay Draw functions***********/
function playArea() {
// gameCanvas
- colorRect(0, 0, canvas.width, canvas.height, "white");
+ colorRect(0, 0, canvas.width, canvas.height, "#222");
// ball
colorCircle();
// paddle
@@ -208,7 +246,7 @@ function playArea() {
canvas.height - PADDLE_DIST_FROM_EDGE,
PADDLE_WIDTH,
PADDLE_THICKNESS,
- "black"
+ "#61dafb"
);
drawbricks();
@@ -228,17 +266,39 @@ function rowColToArrayIndex(col, row) {
return col + BRICK_COLS * row;
}
+var brickColors = [];
+
+// Function to initialize the brick colors
+function initializeBrickColors() {
+ brickColors = [];
+ for (var i = 0; i < BRICK_ROWS * BRICK_COLS; i++) {
+ // Add a random color to the array
+ brickColors.push(getRandomColor());
+ }
+}
+
+// Function to get a random color
+function getRandomColor() {
+ var colors = ["#f86257", "#5bb9a9", " #7d5ba6", "#0b5394", "#ec9b00"];
+ return colors[Math.floor(Math.random() * colors.length)];
+}
+
+// Call the function to initialize brick colors once during initialization
+initializeBrickColors();
+
function drawbricks() {
for (var eachRow = 0; eachRow < BRICK_ROWS; eachRow++) {
for (var eachCol = 0; eachCol < BRICK_COLS; eachCol++) {
var arrayIndex = rowColToArrayIndex(eachCol, eachRow);
if (brickGrid[arrayIndex]) {
+ // Choose a random color from an array of colors
+
colorRect(
BRICK_W * eachCol,
BRICK_H * eachRow,
BRICK_W - BRICK_GAP,
BRICK_H - BRICK_GAP,
- "green"
+ brickColors[arrayIndex]
);
} // if brick
} // each brick
@@ -254,9 +314,9 @@ function colorCircle() {
ballY,
10
);
- gradient.addColorStop(0, "blue");
- gradient.addColorStop(0.5, "grey");
- gradient.addColorStop(1, "black");
+ gradient.addColorStop(0, "#61dafb");
+ gradient.addColorStop(0.5, "#888");
+ gradient.addColorStop(1, "#000");
canvasContext.fillStyle = gradient;
canvasContext.beginPath();
diff --git a/Games/Brick_Breaker/styles.css b/Games/Brick_Breaker/styles.css
index a9b3968c1e..7cbb899ef7 100644
--- a/Games/Brick_Breaker/styles.css
+++ b/Games/Brick_Breaker/styles.css
@@ -1,19 +1,75 @@
body {
- background-color: black;
-}
-#canvas-container {
- margin: 0 auto;
- text-align: center;
+ margin: 20px;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ /* background-color: #282c34; */
+ background: linear-gradient(#282c34, rgb(4, 4, 17));
+ color: white;
+ font-family: 'Arial', sans-serif;
}
#header-container {
text-align: center;
- font-size: 40px;
- color: white;
+ margin: 20px;
+ font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
}
-#score-container {
- text-align: center;
- font-size: 24px;
- color: white;
- padding: 10px;
+
+#header-container h1 {
+ font-size: 2.7em;
+ color: #61dafb;
+ margin: 0;
+}
+.status{
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ width: 800px;;
+ margin-bottom: 20px;
+}
+#score-container #score-display {
+
+ font-size: 30px;
+ margin: 0px;
+ margin-bottom: 10px;
+
+}
+
+#score-display{
+ color:rgb(233, 243, 160);
+}
+
+.status span{
+ font-size: 20px;
+ border: 1px solid rgb(103, 101, 101) !important;
+ padding: 10px;
+}
+
+/* #canvas-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+} */
+ #canvas-container {
+ display: flex;
+ justify-content: center;
+ align-items: flex-start !important; /* Align bricks to the top */
+ height: calc(100vh - 100px);
+ top:0;
+}
+
+#gameCanvas {
+ border: 2px solid #61dafb;
+ background-color: #222;
+}
+
+.home-icon {
+ font-size: 1.5em;
+ position: absolute;
+ /* top: 20px; */
+ left: 20px;
+ color: #61dafb;
+ text-decoration: none;
}
diff --git a/Games/Bubble'z Popper/README.md b/Games/Bubble'z Popper/README.md
new file mode 100644
index 0000000000..5010724c48
--- /dev/null
+++ b/Games/Bubble'z Popper/README.md
@@ -0,0 +1,22 @@
+# Bubble'z-Popper
+
+Pop the Bubblez's
+
+A simple bubble popping game made using HTML, CSS, and Javascript.
+
+How to Play:
+
+1) Click the start button
+
+2) Hover the cursor on the bubbles
+
+3) The bubbles will pop and the score gets counted
+
+note: once you miss poping 10 bubbles the game will end and the score is added to the high score
+
+4) Click the start button again for the new game
+
+Demo Video:
+https://github.com/Chandu6702/GameZone/assets/125206920/a1df4cd5-3dfb-42ba-a94f-c9422ca3844e
+
+
diff --git a/Games/Bubble'z Popper/Sounds/background.mp3 b/Games/Bubble'z Popper/Sounds/background.mp3
new file mode 100644
index 0000000000..550b6abe37
Binary files /dev/null and b/Games/Bubble'z Popper/Sounds/background.mp3 differ
diff --git a/Games/Bubble'z Popper/Sounds/gameover.mp3 b/Games/Bubble'z Popper/Sounds/gameover.mp3
new file mode 100644
index 0000000000..4e6e45dd0a
Binary files /dev/null and b/Games/Bubble'z Popper/Sounds/gameover.mp3 differ
diff --git a/Games/Bubble'z Popper/Sounds/pop.mp3 b/Games/Bubble'z Popper/Sounds/pop.mp3
new file mode 100644
index 0000000000..e6ac8ba4f9
Binary files /dev/null and b/Games/Bubble'z Popper/Sounds/pop.mp3 differ
diff --git a/Games/Bubble'z Popper/index.css b/Games/Bubble'z Popper/index.css
new file mode 100644
index 0000000000..8d5588f0d0
--- /dev/null
+++ b/Games/Bubble'z Popper/index.css
@@ -0,0 +1,104 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
+
+* {
+ padding: 0;
+ margin: 0;
+ font-family: 'Poppins', sans-serif;
+}
+
+body {
+ height: 100vh;
+ background: linear-gradient(rgb(92, 23, 181) 80%, rgb(0, 0, 0));
+}
+
+#name {
+ text-align: center;
+ color: rgb(255, 247, 0);
+ font-weight: 700;
+ padding-top: 10px;
+}
+
+.main {
+ width: 100%;
+ height: 90%;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-evenly;
+ align-items: center;
+}
+
+.container {
+ width: 1000px;
+ height: 500px;
+ background: black;
+ border-radius: 10px;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+}
+
+.bubble {
+ width: 50px;
+ height: 50px;
+ position: relative;
+ border-radius: 50%;
+ animation: bubble 1.5s ease-in-out;
+}
+
+@keyframes bubble {
+ 0% {
+ transform: translateY(500px);
+ }
+}
+
+.utils {
+ width: 70%;
+ display: flex;
+ justify-content: space-evenly;
+}
+
+.start {
+ width: 70px;
+ height: 30px;
+ border: none;
+ font-size: 20px;
+ font-weight: 700;
+ border-radius: 5px;
+}
+
+.dis:hover {
+ background: yellow;
+ cursor: pointer;
+}
+
+#score,
+#high-score,
+#missed {
+ color: white;
+ font-size: 25px;
+}
+
+.game-over {
+ height: 100px;
+ color: white;
+ display: none;
+ flex-direction: column;
+ justify-content: space-evenly;
+ align-items: center;
+ font-weight: 700;
+ position: absolute;
+}
+
+.try-again {
+ border: none;
+ width: 90px;
+ height: 40px;
+ font-size: 18px;
+ border-radius: 5px;
+ font-weight: 700;
+}
+
+.try-again:hover {
+ background: yellow;
+ cursor: pointer;
+}
diff --git a/Games/Bubble'z Popper/index.html b/Games/Bubble'z Popper/index.html
new file mode 100644
index 0000000000..e3cb0954ed
--- /dev/null
+++ b/Games/Bubble'z Popper/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+ Bubble'z Popper
+
+
+
+
+
Bubble'z Popper
+
+
+
+
+
Game Over
+
+
+
+
+
+
+
+
+
Your Score - 0
+
+
+
High Score - 0
+
+
+
Missed - 0
+
+
+
+
+
+
+
+
+
diff --git a/Games/Bubble'z Popper/mobileView.css b/Games/Bubble'z Popper/mobileView.css
new file mode 100644
index 0000000000..926578b699
--- /dev/null
+++ b/Games/Bubble'z Popper/mobileView.css
@@ -0,0 +1,128 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
+
+* {
+ padding: 0;
+ margin: 0;
+ font-family: 'Poppins', sans-serif;
+}
+
+
+
+@media (max-width:500px) {
+
+ body {
+ height: 100vh;
+ width: 100vw;
+ background: linear-gradient(rgb(92, 23, 181) 80%, rgb(0, 0, 0)) no-repeat;
+ }
+
+ #name {
+ text-align: center;
+ color: rgb(255, 247, 0);
+ font-weight: 700;
+ }
+
+ .main {
+ width: 100%;
+ height: 90%;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-evenly;
+ align-items: center;
+ }
+
+ .container {
+ width: 95%;
+ height: 500px;
+ background: black;
+ border-radius: 10px;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+ }
+
+ .bubble {
+ width: 30px;
+ height: 30px;
+ position: relative;
+ border-radius: 50%;
+ animation: bubble 1.5s;
+ }
+
+ @keyframes bubble {
+ 0% {
+ transform: translateY(500px);
+ }
+ }
+
+ .utils {
+ width: 100%;
+ height: 100px;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: 1fr 1fr;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .start-div {
+ display: flex;
+ justify-content: center;
+ }
+
+ .start {
+ width: 70px;
+ height: 30px;
+ border: none;
+ font-size: 20px;
+ font-weight: 700;
+ border-radius: 5px;
+ align-self: center;
+ }
+
+ .start:hover {
+ background: yellow;
+ cursor: pointer;
+ }
+
+ #score,
+ #high-score,
+ #missed {
+ color: white;
+ font-size: 20px;
+ text-align: center;
+ }
+
+ .game-over {
+ height: 100px;
+ color: white;
+ display: none;
+ flex-direction: column;
+ justify-content: space-evenly;
+ align-items: center;
+ font-weight: 700;
+ position: absolute;
+ top: 40%;
+ left: 27%;
+ }
+
+ .game-over:hover {
+ background: yellow;
+ cursor: pointer;
+ }
+
+ .try-again {
+ border: none;
+ width: 90px;
+ height: 40px;
+ font-size: 18px;
+ border-radius: 5px;
+ font-weight: 700;
+ }
+
+ .try-again:hover {
+ background: yellow;
+ cursor: pointer;
+ }
+
+}
diff --git a/Games/Bunny_is_Lost/Bunny Game - Made with Clipchamp.mp4 b/Games/Bunny_is_Lost/Bunny Game - Made with Clipchamp.mp4
new file mode 100644
index 0000000000..0cebe80f78
Binary files /dev/null and b/Games/Bunny_is_Lost/Bunny Game - Made with Clipchamp.mp4 differ
diff --git a/Games/Bunny_is_Lost/README.md b/Games/Bunny_is_Lost/README.md
new file mode 100644
index 0000000000..d4d640f6e7
--- /dev/null
+++ b/Games/Bunny_is_Lost/README.md
@@ -0,0 +1,70 @@
+### Demo Video
+
+
+### Game Logic
+
+The game "Bunny is Lost!" is a 2D side-scrolling survival game where the player controls a bunny that must run away from a forest fire while avoiding and surviving various obstacles. The main objective is to keep the bunny alive for as long as possible by jumping over obstacles and collecting carrots to maintain its health. Here is a detailed breakdown of the game logic:
+
+1. **Initialization and Setup:**
+ - The game initializes the HTML and CSS elements required for the game interface and player interaction.
+ - The `resizeGame` function adjusts the game canvas based on the window size to ensure the game is displayed correctly on different devices.
+ - Background music is generated and played in a loop using the Web Audio API.
+
+2. **Game Start:**
+ - When the player clicks the "Run!" button, the game starts by hiding the intro screen and initiating the main game loop (`gameTic`).
+
+3. **Main Game Loop:**
+ - The main game loop updates the world’s rotation (`worldDeg`) to create the illusion of the bunny running.
+ - Background elements, like mountains and fire, are updated to match the world's rotation.
+ - The player’s status and position are updated based on user input and game events.
+
+4. **Player Interaction:**
+ - The player can prepare to jump by pressing the up arrow key or the spacebar, which increases the `jumpPrepare` value.
+ - Releasing the key triggers the bunny’s jump, calculated based on the `jumpPrepare` value.
+ - The bunny’s status transitions between "stopped", "prepare", "jump", and "landing" based on its vertical position and jump force.
+
+5. **Obstacles and Enemies:**
+ - Carrots appear at regular intervals and can be collected to increase the bunny’s life.
+ - Birds are spawned as enemies that attempt to capture the bunny. If a bird catches the bunny, it results in the bunny’s death.
+
+6. **Health and Status Updates:**
+ - The bunny’s health decreases over time and when it prepares to jump.
+ - If the bunny’s health drops to zero or if it gets caught by a bird, the game ends.
+ - The game displays the distance traveled by the bunny.
+
+7. **Collision Detection:**
+ - The game checks for collisions between the bunny and carrots or birds.
+ - Collecting a carrot increases the bunny’s health, while a collision with a bird ends the game.
+
+8. **Game Over Conditions:**
+ - The game ends when the bunny's health reaches zero, the bunny gets caught by a bird, or if the bunny is overtaken by the fire.
+ - On game over, a message is displayed, and the screen transitions to a sepia tone.
+
+### Game Features
+
+1. **Dynamic Scaling:**
+ - The game dynamically adjusts its size and layout based on the device’s screen size, ensuring an optimal viewing experience on both desktops and mobile devices.
+
+2. **Background Music:**
+ - A procedurally generated background score plays throughout the game, creating an engaging and immersive atmosphere.
+
+3. **Interactive Controls:**
+ - Players can control the bunny’s jumps through keyboard inputs (up arrow or spacebar) or touch inputs on mobile devices.
+
+4. **Collectibles:**
+ - Carrots are scattered throughout the game, which players can collect to replenish the bunny’s health.
+
+5. **Obstacles and Enemies:**
+ - Birds serve as enemies that add challenge by trying to catch the bunny.
+ - The fire serves as a constant threat that moves towards the bunny, adding urgency to the gameplay.
+
+6. **Visual Effects:**
+ - The game features various visual effects, including a rotating world, animated fire, and dynamically generated mountains and backgrounds.
+
+7. **Health and Jump Indicators:**
+ - The game provides visual indicators for the bunny’s health and jump preparation, helping players manage their actions effectively.
+
+8. **Endgame Feedback:**
+ - Upon the bunny’s death, the game provides feedback on how the bunny died, adding narrative depth to the game.
+
+The combination of these features creates an engaging and challenging game that requires players to balance their actions to keep the bunny alive while navigating through an ever-changing environment.
\ No newline at end of file
diff --git a/Games/Bunny_is_Lost/game.js b/Games/Bunny_is_Lost/game.js
new file mode 100644
index 0000000000..a6a54ae70b
--- /dev/null
+++ b/Games/Bunny_is_Lost/game.js
@@ -0,0 +1,473 @@
+"use strict";
+
+var d = document;
+var rnd = Math.random;
+var round = Math.round;
+var find = d.querySelector.bind(d);
+var worldDeg = 0;
+var life = 100;
+var jumpPrepare = 0;
+var jumpForce = 0;
+var unblockKeys = ['F5','F11','F12'];
+var timeout = (secs, fn)=> setTimeout(fn, secs*1000);
+var distM = 0;
+var gameTic = null;
+
+function resizeGame() {
+ var w = window.innerWidth;
+ var h = window.innerHeight;
+ canvas.style.transform = `scale(${w/1400})`;
+ if (w < h) {
+ d.body.className = 'vertical'
+ e.style.top = `-${h*.8}px`;
+ } else {
+ d.body.className = 'horizontal'
+ e.style.top = `-${h/5}px`;
+ }
+}
+resizeGame();
+window.onresize = resizeGame;
+
+var offAudioCtx = new OfflineAudioContext(2,44100*21,44100);
+
+var AudioContext = window.AudioContext || window.webkitAudioContext;
+var audioCtx = new AudioContext();
+
+// Cc Eb Fc Gc Bb
+// C D E F G A B
+var notes = [{
+ C:16.35, Cc:17.32, D:18.35, Eb:19.45, E:20.60, F:21.83,
+ Fc:23.12, G:24.50, Gc:25.96, A:27.50, Bb:29.14, B:30.87
+}];
+for (var i=1; i<=8; i++) {
+ notes[i] = { };
+ for (var n in notes[0]) notes[i][n] = notes[0][n] * Math.pow(2, i+1);
+}
+
+function playTone(freq, length, attack) {
+ if (!attack) attack = 2;
+ var o = audioCtx.createOscillator();
+ o.frequency.value = freq;
+ var g = audioCtx.createGain();
+ g.connect(audioCtx.destination);
+ g.gain.value = 0;
+ g.gain.setValueAtTime(attack, audioCtx.currentTime);
+ g.gain.linearRampToValueAtTime(0, audioCtx.currentTime + length);
+ o.connect(g);
+ o.start(0);
+}
+
+function playOffMusicNote(freq, start, end, attack) {
+ if (!attack) attack = 2;
+ var o = offAudioCtx.createOscillator();
+ o.frequency.value = freq;
+ var g = offAudioCtx.createGain();
+ g.connect(offAudioCtx.destination);
+ g.gain.value = 0;
+ g.gain.setValueAtTime(attack, offAudioCtx.currentTime + start);
+ g.gain.linearRampToValueAtTime(0, offAudioCtx.currentTime + end);
+ o.connect(g);
+ o.start(0);
+}
+
+// Parse and play ABC notation
+function playABC(opts) {
+ var callback = arguments[arguments.length-1] || function(){};
+ if (!opts.time) opts.time = 1;
+ if (!opts.attack) opts.attack = 1;
+ var timePos = 0;
+ var music = '';
+ for (var i=1; i{
+ var octave = ( 'abcdefg'.indexOf(n[0]) > -1 ) ? 4 : 3;
+ if (n[1] === ',') {
+ octave--;
+ n = n[0] + n.substring(2);
+ }
+ if (n[1] === "'") {
+ octave++;
+ n = n[0] + n.substring(2);
+ }
+ var length = (n[1] ? n.substring(1) : '1');
+ length = (length[0]==='/') ? (length.length===1) ? .5 : 1/parseInt(length[1]) : parseInt(length);
+ length *= opts.time;
+ n = n[0].toUpperCase();
+ if (n !== 'Z') {
+ playOffMusicNote(notes[octave][n], timePos, timePos+length, opts.attack);
+ }
+ timePos += length;
+ });
+ timeout(timePos+.1, callback);
+}
+
+// Create Song
+playABC(
+ {time:1/6, attack:1},
+ 'a2ed cAce eaae cAce a2ed cAce d2B2 B2ef',
+ 'a2ed cAce eaae cAce defg afed c2A2 A2',
+ 'ce',
+ 'f2cB AFce f2cB ABce f2cB AFGA G2E2 E2ce',
+ 'f2cB AFce fecB ABce fefg afed c2A2 A2',
+ null
+);
+
+// Render and loop play
+offAudioCtx.startRendering()
+.then((renderedBuffer)=> {
+ var song = audioCtx.createBufferSource();
+ song.buffer = renderedBuffer;
+ song.connect(audioCtx.destination);
+ song.loop = true;
+ song.start();
+})
+.catch((err)=> console.error('Music Fail', err) );
+
+
+HTMLElement.prototype.mkEl = function mkEl(tag, css, attrs) {
+ var att, el = d.createElement(tag);
+ for (att in css) el.style[att] = css[att];
+ if (attrs) for (att in attrs) el[att] = attrs[att];
+ this.appendChild(el);
+ el.del = ()=> this.removeChild(el);
+ return el;
+}
+
+var bloodList = [];
+function mkBlood(x, y, vx, vy) {
+ var b = e.mkEl('blood', {border:round((1+rnd())*5)+'px solid #B00', top:'50%', left:'50%', zIndex:2});
+ b.x = x;
+ b.y = y;
+ b.vx = vx;
+ b.vy = vy;
+ bloodList.push(b);
+ return b;
+}
+function updateBlood() {
+ bloodList.forEach((b)=> {
+ b.x += b.vx;
+ b.y += b.vy;
+ b.vy -= 3;
+ if (b.y <= 0) b.y = b.vx = b.vy = 0;
+ b.style.transform = `rotate(${b.x}deg) translate(0,-${1500+b.y}px)`;
+ });
+}
+
+function Bunny() {
+ // wrapper
+ // body
+ // back leg
+ // head
+ //
+ //
+ this.x = 0;
+ this.y = 33;
+ this.radius = 33;
+ this.wrap = e.mkEl('bw',{},{className:'stopped'});
+ var b = this.wrap.mkEl('b');
+ this.wrap.body = b;
+ b.mkEl('bl');
+ b.mkEl('bh');
+ //this.wrap.mkEl('div', {border:'1px solid red', outline:this.radius+'px solid rgba(0,255,0,.4)'});
+ this.update();
+}
+Bunny.prototype.status = function(s) {
+ if (s) this.wrap.className = s;
+ return this.wrap.className;
+}
+Bunny.prototype.statusIs = function(s) {
+ return this.status().indexOf(s) > -1;
+}
+Bunny.prototype.statusIsnt = function(s) {
+ return this.status().indexOf(s) === -1;
+}
+Bunny.prototype.update = function() {
+ this.wrap.style.transform = `rotate(${this.x+1.5}deg) translate(0,-${1460+this.y}px)`;
+}
+
+var player = new Bunny();
+
+function Carrot(x, y) {
+ Carrot.list.push(this);
+ this.x = x;
+ this.y = y;
+ this.radius = 17;
+ this.el = e.mkEl('carrot-wrap', {transform:`rotate(${x}deg)`, zIndex:2});
+ this.el.mkEl('leaves', {transform:`translate(-20px, ${-1503-y}px)`} );
+ this.el.mkEl('carrot', {transform:`translate(-20px, ${-1503-y}px)`} );
+ //this.el.mkEl('div', {transform:`translate(0, ${-1503-y}px)`, border:'1px solid red', outline:this.radius+'px solid rgba(0,255,0,.4)'});
+}
+Carrot.list = [];
+
+Carrot.prototype.remove = function() {
+ Carrot.list = Carrot.list.filter((c)=> c!==this );
+ this.el.del();
+}
+
+function updateCarrots() {
+ // Create carrots
+ if ( round(worldDeg*10) % 80 === 0 ) {
+ if (rnd()<.7) {
+ new Carrot(-worldDeg+30, 35+rnd()*200);
+ } else {
+ var y = 100 + rnd()*200
+ new Carrot(-worldDeg+28, y);
+ new Carrot(-worldDeg+30.5, y+40);
+ new Carrot(-worldDeg+32, y);
+ }
+ }
+ // Remove ast carrots
+ Carrot.list.forEach((c)=> {
+ if (c.x < -worldDeg-90) c.remove();
+ });
+ // Eat carrots
+ Carrot.list.forEach((c)=> {
+ if (touch(player, c, 20)) {
+ life += 10;
+ if (life>100) life=100;
+ timeout(.0, ()=> playTone(1900, .3) );
+ timeout(.1, ()=> playTone(1100, .3) );
+ c.remove();
+ }
+ });
+}
+
+new Carrot( 6, 40);
+new Carrot( 8, 40);
+new Carrot(10, 40);
+new Carrot(12, 40);
+new Carrot(15, 40);
+new Carrot(19, 40);
+new Carrot(24, 40);
+new Carrot(30, 40);
+
+function Bird(x, y) {
+ Bird.list.push(this);
+ this.velocity = 0.1 + rnd()/2;
+ this.x = x;
+ this.y = y;
+ this.radius = 75;
+ this.wrap = e.mkEl('bird-wrap', {transform:`rotate(${x}deg)`, zIndex:2});
+ //this.wrap.mkEl('test', {transform:`translate(0, ${-1500-y}px)`, zIndex:99, border:'1px solid red', outline:this.radius+'px solid rgba(0,255,0,.5)'}); // test mark
+ this.el = this.wrap.mkEl('div', {transform:`translate(0, ${-1500-y}px)`})
+ var bird = this.el.mkEl('bird');
+ this.el.mkEl('wing-right', {}, {className:'wing'});
+ this.el.mkEl('wing-left', {}, {className:'wing'});
+ bird.mkEl('head');
+}
+
+Bird.list = [];
+
+Bird.prototype.update = function() {
+ this.x -= this.velocity;
+ if (this.x-5 > -worldDeg) this.y -= this.velocity*4;
+ if (this.x+5 < -worldDeg) this.y += this.velocity*8;
+ if (this.y < 200) this.y = 200;
+ this.wrap.style.transform = `rotate(${this.x}deg)`;
+ this.el.style.transform = `translate(0, ${-1500-this.y}px)`;
+ if (this.x < -worldDeg-90) this.die();
+ this.testGetBunny();
+ if (this.hunted) {
+ this.hunted.x = (this.hunted.x*2 + (this.x-2)) / 3;
+ this.hunted.y = (this.hunted.y*2 + (this.y-100)) / 3;
+ mkBlood(this.hunted.x+rnd()*2, this.hunted.y, 0, 0);
+ }
+}
+Bird.update = function() {
+ Bird.list.forEach((b)=> b.update() );
+ if ( round(worldDeg*10) % 80 === 0 && rnd() < .4 )
+ new Bird(-worldDeg+25, 200+rnd()*300);
+};
+
+Bird.prototype.testGetBunny = function() {
+ if (player.y < this.y && player.statusIsnt('hunted')) {
+ if (touch(player, this)) {
+ die('hunted');
+ this.hunted = player;
+ }
+ }
+}
+
+Bird.prototype.die = function() {
+ Bird.list = Bird.list.filter((b)=> b!==this );
+ this.wrap.del();
+}
+
+var sin = (deg)=> Math.sin((deg%180)*Math.PI/180);
+var cos = (deg)=> Math.cos((deg%180)*Math.PI/180);
+
+function dist(obj1, obj2) {
+ var x1 = sin(obj1.x) * (obj1.y+1500);
+ var y1 = cos(obj1.y) * (obj1.y+1500);
+ var x2 = sin(obj2.x) * (obj2.y+1500);
+ var y2 = cos(obj2.y) * (obj2.y+1500);
+ var dX = x1 - x2;
+ var dY = y1 - y2;
+ return Math.sqrt(dX*dX + dY*dY);
+}
+
+function touch(obj1, obj2, inc) {
+ if (!inc) inc = 0;
+ return dist(obj1, obj2) <= (obj1.radius + obj2.radius + inc);
+}
+
+//new Bird(30, 300);
+//var bird = new Bird(20, 200);
+
+//player.status('dead');
+//player.status('hunted');
+//bird.hunted = player;
+//e.mkEl('qqqqq', {left:'50%',top:'50%',transform:'translate(0,-1500px)',border:'1px solid #00f', zIndex:99});
+
+for (var x=0; x<360; x++) { // grass (capim)
+ //e.mkEl('k', {transform:'rotate('+(x+rnd()*.4-.2)+'deg) translate(0,-'+(1511-rnd()*10)+'px)'});
+ if (rnd()<0.3) e.mkEl('f', {transform:'rotate('+(x+rnd()-.5)+'deg) translate(0,-'+(1498-rnd()*20)+'px)'});
+}
+
+jumpPF.update = function() {
+ if (player.status() == 'prepare') {
+ jumpPrepare += 1.5;
+ if (jumpPrepare > 50) jumpPrepare = 50;
+ this.style.height = jumpPrepare*2+'%';
+ }
+};
+
+var montains = { bg1:[], bg2:[] };
+function updateMontains(bg, prob) {
+ if (rnd()0; worldDeg-=0.1) {
+ if ( round(worldDeg*10) % 80 === 0 ) updateMontains(bg1, 0.6);
+ if ( round(worldDeg*10) % 60 === 0 ) updateMontains(bg2, 0.6);
+}
+
+function burnTest() {
+ if ( player.statusIs('stopped') ) {
+ if ( player.x < (-worldDeg-15) ) {
+ die('burned');
+ for (var i=0; i<15; i++) mkBlood(player.x, player.y, rnd(), 15+rnd()*5);
+ }
+ }
+}
+
+function die(status) {
+ player.status('dead '+status);
+ timeout(2, ()=> {
+ timeout(0, ()=> playTone(300, 1, 4) );
+ timeout(1, ()=> playTone(200, 2, 4) );
+ timeout(2, ()=> playTone(100, 4, 6) );
+ distEl.mkEl('div').innerText = `The bunny die ${status}, lost and alone.`;
+ timeout(3, ()=> {
+ d.body.style.transition = '2s';
+ d.body.style.filter = 'sepia(90%)';
+ });
+ timeout(4, ()=> clearInterval(gameTic) );
+ });
+}
+
+function start() {
+
+ intro.style.display = 'none';
+
+ // Make Fire
+ timeout(0.3, ()=> fire.mkEl('w', {left:'40%'}, {className:'fireBack fireBig'}) );
+ timeout(0.6, ()=> fire.mkEl('w', {left:'50%'}, {className:'fireMid fireBig'}) );
+ timeout(0.9, ()=> fire.mkEl('w', {left:'60%', zIndex:1}, {className:'fireBack fireBig'}) );
+ timeout(1.2, ()=> fire.mkEl('w', {left:'70%'}, {className:'fireMid fireBig'}) );
+ timeout(1.5, ()=> fire.mkEl('w', {right:'112px', zIndex:1}, {className:'fireBackEdge'}) );
+ timeout(1.8, ()=> fire.mkEl('w', {right:'60px'}, {className:'fireEdge'}) );
+
+ gameTic = setInterval(()=>{ // Tic
+ worldDeg -= 0.1;
+ if ( round(worldDeg*10) % 80 === 0 ) updateMontains(bg1, 0.6);
+ if ( round(worldDeg*10) % 60 === 0 ) updateMontains(bg2, 0.6);
+
+ // Roll the world
+ e.style.transform = 'rotate('+(worldDeg)+'deg)'
+ bg1.style.transform = 'rotate('+(-worldDeg/2)+'deg)'
+ bg2.style.transform = 'rotate('+(-worldDeg/4)+'deg)'
+
+ // Move fire
+ fireWrap.style.transform = 'rotate('+(-worldDeg-26)+'deg)'
+
+ // Update pitfals
+ burnTest();
+ Bird.update();
+ updateBlood();
+
+ // Update life;
+ life -= 0.05;
+ if (player.statusIs('prepare')) life -= 0.2;
+ if (life < 0) life = 0;
+ if (player.statusIs('stopped') && life === 0) die('hungry');
+ updateCarrots();
+
+ // Update Ctrl
+ lifePF.style.height = life + '%';
+ jumpPF.update();
+ if (round(player.x/6) !== distM) {
+ distM = round(player.x/6);
+ distEl.innerText = `Distance: ${distM}m`
+ }
+
+ var pStatus = player.status();
+ if ((jumpForce > 0 || player.y > player.radius) && ['jump','landing'].indexOf(pStatus)>-1) {
+ player.x += 0.5;
+ player.y += jumpForce;
+ jumpForce -= 4;
+ if (jumpForce < 0 && player.y < player.radius*3) player.status('landing');
+ if (player.y <= player.radius) { player.status('stopped'); player.y = player.radius; }
+ }
+ player.update();
+ }, 40);
+}
+
+function doJumpPrepare() {
+ if (player.statusIs('stopped')) {
+ player.status('prepare');
+ jumpPrepare = 5;
+ jumpPF.update();
+ }
+}
+
+function doJump() {
+ if (player.statusIs('prepare')) {
+ playTone(400, jumpPrepare/22);
+ playTone(300, jumpPrepare/20);
+ player.status('jump');
+ jumpForce = jumpPrepare;
+ jumpPrepare = 0;
+ jumpPF.style.height = 0;
+ }
+}
+
+d.addEventListener('keydown', function(ev) {
+ if (unblockKeys.indexOf(ev.key)==-1) ev.preventDefault();
+ if (ev.key==='ArrowUp' || ev.key===' ') doJumpPrepare();
+});
+
+d.addEventListener('keyup', function(ev) {
+ if (unblockKeys.indexOf(ev.key)==-1) ev.preventDefault();
+ if (ev.key==='ArrowUp' || ev.key===' ') doJump();
+});
+
+d.addEventListener('touchstart', doJumpPrepare);
+d.addEventListener('touchend', doJump);
\ No newline at end of file
diff --git a/Games/Bunny_is_Lost/index.html b/Games/Bunny_is_Lost/index.html
new file mode 100644
index 0000000000..0bda4ee400
--- /dev/null
+++ b/Games/Bunny_is_Lost/index.html
@@ -0,0 +1,39 @@
+
+
+ Bunny
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Distance: 0m
+
+
JUMP!
+
+
+
+
Bunny is Lost!
+
+ Your home was burned in the forest fire.
+ You must run and don't look behind.
+ You must protect yourself from birds of prey.
+ You are look, there are many carrots on the way!
+