Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Quag Clicker V1</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Comic+Neue:wght@400;700&display=swap" rel="stylesheet" /> | |
| <style> | |
| body { | |
| background: #330000; /* dark red background */ | |
| font-family: 'Comic Neue', cursive; | |
| color: #f6e58d; /* pale yellow for text */ | |
| } | |
| .quag-click { | |
| transition: transform 0.1s; | |
| cursor: pointer; | |
| } | |
| .quag-click:active { | |
| transform: scale(0.95); | |
| } | |
| .bounce { | |
| animation: bounce 0.5s infinite alternate; | |
| } | |
| @keyframes bounce { | |
| from { | |
| transform: translateY(0); | |
| } | |
| to { | |
| transform: translateY(-10px); | |
| } | |
| } | |
| .ripple { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .ripple:after { | |
| content: ''; | |
| display: block; | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| top: 0; | |
| left: 0; | |
| pointer-events: none; | |
| background-image: radial-gradient(circle, #f6e58d 10%, transparent 10%); | |
| background-repeat: no-repeat; | |
| background-position: 50%; | |
| transform: scale(10, 10); | |
| opacity: 0; | |
| transition: transform 0.5s, opacity 1s; | |
| } | |
| .ripple:active:after { | |
| transform: scale(0, 0); | |
| opacity: 0.3; | |
| transition: 0s; | |
| } | |
| /* Player and boss circular styles with Quagmire images and colors */ | |
| #player { | |
| bottom: 10px ; | |
| top: auto ; | |
| width: 48px ; | |
| height: 48px ; | |
| border-radius: 50% ; | |
| background-image: url(https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSIpBN8xslzZf25jeVNT8qK4Byz3XxlfnJN8YmjQVS-KoL3YnCFHyiGPzNz_51CBcN5ZEF02LcKV7AnIxCOBy5ibvLgWEpp8SCdSpg-CzbOSQ); /* Quagmire face */ | |
| background-size: cover ; | |
| background-position: center ; | |
| background-repeat: no-repeat ; | |
| box-shadow: 0 0 8px #f6e58d ; /* yellow glow */ | |
| display: flex ; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 12px; | |
| color: transparent ; /* hide text inside */ | |
| font-weight: 700; | |
| user-select: none; | |
| position: absolute; | |
| } | |
| #player > div { | |
| display: none; /* hide inner avatar parts */ | |
| } | |
| #boss { | |
| top: 10px ; | |
| bottom: auto ; | |
| width: 64px ; | |
| height: 64px ; | |
| border-radius: 50% ; | |
| background-image: url(data:image/jpeg;base64,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); /* Herbert as boss */ | |
| background-size: cover; | |
| background-position: center; | |
| box-shadow: 0 0 12px #cc0000; /* red glow */ | |
| display: block ; | |
| user-select: none; | |
| position: absolute; | |
| overflow: visible; /* allow arms outside */ | |
| } | |
| #boss > div { | |
| display: none; /* hide inner avatar parts */ | |
| } | |
| /* Boss arms with Quagmire style colors */ | |
| #boss-arm-left, #boss-arm-right { | |
| position: absolute; | |
| width: 20px; | |
| height: 12px; | |
| background-color: #cc0000; /* dark red */ | |
| border-radius: 6px; | |
| top: 36px; | |
| opacity: 1; | |
| transform-origin: center center; | |
| transition: transform 0.3s ease, opacity 0.3s ease; | |
| pointer-events: none; | |
| z-index: 10; | |
| display: block; | |
| transform: rotate(0deg); | |
| } | |
| #boss-arm-left { | |
| left: -20px; | |
| transform: rotate(-10deg) translate(-5px, 3px); | |
| animation: boss-arm-idle-left 2s ease-in-out infinite alternate; | |
| } | |
| #boss-arm-right { | |
| right: -20px; | |
| transform: rotate(10deg) translate(5px, 3px); | |
| animation: boss-arm-idle-right 2s ease-in-out infinite alternate; | |
| } | |
| @keyframes boss-arm-idle-left { | |
| 0% { transform: rotate(-10deg) translate(-5px, 3px); } | |
| 100% { transform: rotate(-5deg) translate(-7px, 5px); } | |
| } | |
| @keyframes boss-arm-idle-right { | |
| 0% { transform: rotate(10deg) translate(5px, 3px); } | |
| 100% { transform: rotate(5deg) translate(7px, 5px); } | |
| } | |
| .boss-arm-attack-left { | |
| animation: none ; | |
| transform: rotate(-45deg) translate(-10px, 10px); | |
| opacity: 1; | |
| } | |
| .boss-arm-attack-right { | |
| animation: none ; | |
| transform: rotate(45deg) translate(10px, 10px); | |
| opacity: 1; | |
| } | |
| /* Container styles with Quagmire yellows and reds */ | |
| .container { | |
| background-color: #5a1a01; /* dark brownish red */ | |
| border-radius: 1rem; | |
| padding: 2rem; | |
| box-shadow: 0 0 20px #f6e58d; | |
| max-width: 900px; | |
| margin-top: 2rem; | |
| } | |
| h1, h2, h3 { | |
| color: #f6e58d; | |
| text-shadow: 1px 1px 4px #cc0000; | |
| } | |
| /* Buttons with Quagmire yellow/red theme */ | |
| button { | |
| background-color: #f6e58d; | |
| color: #330000; | |
| font-weight: bold; | |
| border-radius: 9999px; | |
| padding: 0.5rem 1rem; | |
| box-shadow: 0 0 6px #cc0000; | |
| transition: background-color 0.3s ease; | |
| cursor: pointer; | |
| } | |
| button:hover:not(:disabled) { | |
| background-color: #ffec99; | |
| } | |
| button:disabled { | |
| background-color: #bba24a; | |
| cursor: not-allowed; | |
| color: #5a1a01; | |
| box-shadow: none; | |
| } | |
| /* Upgrade cards */ | |
| .upgrade-card { | |
| background-color: #330000; | |
| border: 1px solid #cc0000; | |
| box-shadow: 0 0 10px #cc0000; | |
| color: #f6e58d; | |
| } | |
| /* Achievement styles */ | |
| .achievements { | |
| background-color: #440000; | |
| border: 1px solid #cc0000; | |
| box-shadow: 0 0 10px #f6e58d; | |
| color: #f6e58d; | |
| } | |
| .achievement { | |
| background-color: #330000; | |
| border: 1px solid #cc0000; | |
| color: #f6e58d; | |
| opacity: 0.5; | |
| transition: opacity 0.3s ease, background-color 0.3s ease; | |
| } | |
| .achievement.bg-green-100 { | |
| opacity: 1 ; | |
| background-color: #f6e58d ; | |
| color: #330000 ; | |
| box-shadow: 0 0 8px #cc0000; | |
| } | |
| /* Score display */ | |
| #score-display { | |
| color: #f6e58d; | |
| text-shadow: 1px 1px 3px #cc0000; | |
| } | |
| /* Input for name */ | |
| input#player-name { | |
| background-color: #330000; | |
| color: #f6e58d; | |
| border: 1px solid #cc0000; | |
| box-shadow: 0 0 6px #cc0000; | |
| font-weight: bold; | |
| } | |
| input#player-name::placeholder { | |
| color: #cc0000; | |
| } | |
| /* Boss fight overlay */ | |
| #boss-fight-overlay { | |
| background-color: #330000cc; | |
| color: #f6e58d; | |
| font-weight: bold; | |
| } | |
| #boss-fight-instructions { | |
| background-color: #440000dd; | |
| border: 2px solid #f6e58d; | |
| } | |
| #boss-fight-game { | |
| background-color: #440000dd; | |
| border: 2px solid #cc0000; | |
| } | |
| #fight-message { | |
| min-height: 24px; | |
| color: #f6e58d; | |
| text-shadow: 1px 1px 5px #cc0000; | |
| } | |
| #enter-boss-fight-btn { | |
| background-color: #f6e58d; | |
| color: #330000; | |
| font-weight: bold; | |
| border-radius: 10px; | |
| padding: 0.75rem 1.5rem; | |
| box-shadow: 0 0 10px #cc0000; | |
| transition: background-color 0.3s ease; | |
| } | |
| #enter-boss-fight-btn:hover:not(:disabled) { | |
| background-color: #ffec99; | |
| } | |
| #exit-boss-fight { | |
| background-color: #cc0000; | |
| color: #f6e58d; | |
| font-weight: bold; | |
| border-radius: 10px; | |
| padding: 0.75rem 1.5rem; | |
| box-shadow: 0 0 10px #330000; | |
| transition: background-color 0.3s ease; | |
| } | |
| #exit-boss-fight:hover { | |
| background-color: #a30000; | |
| } | |
| /* Click effect style */ | |
| #click-effect { | |
| color: #f6e58d; | |
| text-shadow: 0 0 6px #cc0000; | |
| } | |
| /* Cheat menu */ | |
| #cheat-menu { | |
| background-color: #330000; | |
| border: 2px solid #f6e58d; | |
| color: #f6e58d; | |
| box-shadow: 0 0 20px #cc0000; | |
| } | |
| /* Scrollbar styling for container overflow */ | |
| ::-webkit-scrollbar { | |
| width: 10px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #330000; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #cc0000; | |
| border-radius: 5px; | |
| } | |
| /* Power Ups menu styles */ | |
| #power-ups-menu { | |
| background-color: #330000; | |
| border: 1px solid #cc0000; | |
| box-shadow: 0 0 15px #cc0000; | |
| color: #f6e58d; | |
| max-width: 900px; | |
| margin: 2rem auto 0; | |
| border-radius: 1rem; | |
| padding: 1rem; | |
| } | |
| #power-ups-menu h2 { | |
| text-shadow: 1px 1px 4px #cc0000; | |
| margin-bottom: 1rem; | |
| } | |
| .power-up-card { | |
| background-color: #440000; | |
| border: 1px solid #cc0000; | |
| padding: 1rem; | |
| margin-bottom: 1rem; | |
| border-radius: 0.75rem; | |
| box-shadow: 0 0 10px #cc0000; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: space-between; | |
| } | |
| .power-up-card h3 { | |
| margin-bottom: 0.25rem; | |
| } | |
| .power-up-card p { | |
| font-size: 0.9rem; | |
| margin-bottom: 0.5rem; | |
| } | |
| .power-up-card button { | |
| align-self: flex-start; | |
| border-radius: 9999px; | |
| padding: 0.3rem 0.8rem; | |
| font-weight: bold; | |
| box-shadow: 0 0 6px #cc0000; | |
| background-color: #f6e58d; | |
| color: #330000; | |
| } | |
| .power-up-card button:disabled { | |
| background-color: #bba24a; | |
| color: #5a1a01; | |
| cursor: not-allowed; | |
| box-shadow: none; | |
| } | |
| /* Layout for upgrade cards with new Mega Click */ | |
| .upgrades-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(220px,1fr)); | |
| gap: 1rem; | |
| width: 100%; | |
| max-width: 900px; | |
| margin-bottom: 2rem; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container mx-auto px-4 py-8 text-center relative"> | |
| <div | |
| class="absolute top-0 right-0 font-bold px-4 py-2 rounded-lg shadow-md animate-pulse" | |
| style="background-color: #f6e58d; color: #cc0000;" | |
| > | |
| <a href="https://bbc123321-history-teacher-simulator.static.hf.space/index.html">Click Here for Another Game</a> | |
| </div> | |
| <h1 class="text-5xl font-bold mb-2" style="color:#f6e58d; text-shadow: 1px 1px 5px #cc0000;">Quag Clicker V1</h1> | |
| <p class="text-xl mb-4" style="color:#f6e58d;">Click Quagmire to collect Giggity Bucks!</p> | |
| <div class="mb-4"> | |
| <input | |
| type="text" | |
| id="player-name" | |
| placeholder="Name" | |
| class="text-center text-xl px-4 py-2 rounded-lg border focus:outline-none focus:ring-2" | |
| style="background-color:#330000; color:#f6e58d; border-color:#cc0000; box-shadow:0 0 6px #cc0000;" | |
| /> | |
| </div> | |
| <div class="flex flex-col items-center"> | |
| <div id="score-display" class="text-3xl font-bold mb-6" style="color:#f6e58d; text-shadow: 1px 1px 3px #cc0000;"> | |
| Giggity Bucks: <span id="score">0</span> | |
| </div> | |
| <div id="quag-container" class="relative mb-8"> | |
| <button id="frog" class="quag-click ripple bg-transparent border-none"> | |
| <img | |
| src="https://imgix.ranker.com/node_img/54/1077239/original/glenn-quagmire-tv-characters-photo-1?w=350&h=350&q=90&fm=jpg&fit=crop&crop=faces" | |
| alt="Quagmire" | |
| class="w-48 h-48 md:w-64 md:h-64 rounded-full object-cover shadow-lg bounce" | |
| /> | |
| </button> | |
| <div id="click-effect" class="absolute opacity-0 text-2xl font-bold" style="color:#f6e58d; text-shadow: 0 0 6px #cc0000;">+1</div> | |
| </div> | |
| <div class="upgrades-grid mb-8"> | |
| <!-- Click Power Upgrade Card --> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Click Power</h3> | |
| <p class="mb-3">Increases Giggity Bucks per click by 1</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="click-power-cost">50</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-click-power" | |
| > | |
| Buy (<span id="click-power-owned">0</span>) | |
| </button> | |
| </div> | |
| <!-- Mega Click Upgrade Card --> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Mega Click</h3> | |
| <p class="mb-3">Increases Giggity Bucks per click by 10</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="mega-click-cost">250</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-mega-click" | |
| > | |
| Buy (<span id="mega-click-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Auto Giggity</h3> | |
| <p class="mb-3">Earns 1 Giggity Buck every second</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="auto-tongue-cost">20</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-auto-tongue" | |
| > | |
| Buy (<span id="auto-tongue-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Giggity Army</h3> | |
| <p class="mb-3">Earns 5 Giggity Bucks every 2 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="frog-army-cost">100</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-frog-army" | |
| > | |
| Buy (<span id="frog-army-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Quag Paradise</h3> | |
| <p class="mb-3">Earns 20 Giggity Bucks every 3 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="pond-paradise-cost">500</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-pond-paradise" | |
| > | |
| Buy (<span id="pond-paradise-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Giggity Farm</h3> | |
| <p class="mb-3">Earns 50 Giggity Bucks every 4 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="fly-farm-cost">1500</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-fly-farm" | |
| > | |
| Buy (<span id="fly-farm-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Giggity Kingdom</h3> | |
| <p class="mb-3">Earns 100 Giggity Bucks every 6 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="frog-kingdom-cost">5000</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-frog-kingdom" | |
| > | |
| Buy (<span id="frog-kingdom-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Golden Quag</h3> | |
| <p class="mb-3">Earns 200 Giggity Bucks every 6 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="golden-harris-cost">20000</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-golden-harris" | |
| > | |
| Buy (<span id="golden-harris-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Giggity Factory</h3> | |
| <p class="mb-3">Earns 500 Giggity Bucks every 6 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="fly-factory-cost">50000</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-fly-factory" | |
| > | |
| Buy (<span id="fly-factory-owned">0</span>) | |
| </button> | |
| </div> | |
| <div class="upgrade-card p-4 rounded-lg shadow-md"> | |
| <h3 class="text-xl font-bold mb-2">Quag Empire</h3> | |
| <p class="mb-3">Earns 1000 Giggity Bucks every 12 seconds</p> | |
| <p class="text-sm mb-3"> | |
| Cost: <span id="harris-empire-cost">100000</span> Giggity Bucks | |
| </p> | |
| <button | |
| id="buy-harris-empire" | |
| > | |
| Buy (<span id="harris-empire-owned">0</span>) | |
| </button> | |
| </div> | |
| </div> | |
| <div id="power-ups-menu"> | |
| <h2 class="text-2xl font-bold mb-4">Power Ups</h2> | |
| <div class="power-up-card"> | |
| <h3>Giggity Rush</h3> | |
| <p>Doubles all Giggity Bucks income for 30 seconds.</p> | |
| <p>Cost: 25,000 Giggity Bucks</p> | |
| <button id="activate-giggity-rush">Activate</button> | |
| <div id="giggity-rush-timer" style="margin-top: 0.5rem; font-size: 0.9rem;"></div> | |
| </div> | |
| <div class="power-up-card"> | |
| <h3>Lucky</h3> | |
| <p>Increases chance of Harris Frenzy and secret stash by 50% for 60 seconds.</p> | |
| <p>Cost: 35,000 Giggity Bucks</p> | |
| <button id="activate-lucky">Activate</button> | |
| <div id="lucky-timer" style="margin-top: 0.5rem; font-size: 0.9rem;"></div> | |
| </div> | |
| <div class="power-up-card"> | |
| <h3>Quag Shield</h3> | |
| <p>Reduces damage taken in boss fight by 50% for 30 seconds.</p> | |
| <p>Cost: 40,000 Giggity Bucks</p> | |
| <button id="activate-quag-shield">Activate</button> | |
| <div id="quag-shield-timer" style="margin-top: 0.5rem; font-size: 0.9rem;"></div> | |
| </div> | |
| <div class="power-up-card"> | |
| <h3>Giggity Magnet</h3> | |
| <p>Increases Giggity Bucks gained per click by 50% for 45 seconds.</p> | |
| <p>Cost: 30,000 Giggity Bucks</p> | |
| <button id="activate-giggity-magnet">Activate</button> | |
| <div id="giggity-magnet-timer" style="margin-top: 0.5rem; font-size: 0.9rem;"></div> | |
| </div> | |
| </div> | |
| <div class="achievements p-6 rounded-lg shadow-lg max-w-3xl w-full"> | |
| <h2 class="text-2xl font-bold mb-4">Quag Achievements</h2> | |
| <div class="grid grid-cols-2 md:grid-cols-3 gap-3"> | |
| <div id="achievement-10" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>10 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-50" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>50 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-100" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>100 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-500" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>500 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-1000" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>1,000 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-5000" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>5,000 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-100000" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>100,000 Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-1000000" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>1 Million Giggity Bucks</span> | |
| </div> | |
| </div> | |
| <div id="achievement-10000000" class="achievement p-3 rounded border opacity-50"> | |
| <div class="flex items-center"> | |
| <i data-feather="award" class="text-yellow-400 mr-2"></i> | |
| <span>10 Million Giggity Bucks</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> <!-- End main container --> | |
| <!-- Enter Boss Fight Button on Main UI --> | |
| <div id="enter-boss-fight-container" class="text-center mt-4 hidden"> | |
| <button id="enter-boss-fight-btn" class="font-bold rounded-lg shadow transition"> | |
| Enter Boss Fight | |
| </button> | |
| </div> | |
| <!-- Boss Fight Overlay --> | |
| <div id="boss-fight-overlay" class="fixed inset-0 flex flex-col items-center justify-center font-bold text-lg z-50 hidden"> | |
| <div id="boss-fight-instructions" class="max-w-xl rounded-lg p-6 mb-6 text-center select-none"> | |
| <h2 class="text-3xl mb-4">Boss Fight Controls</h2> | |
| <p>Use <span class="underline">Arrow Left</span> and <span class="underline">Arrow Right</span> to move your avatar.</p> | |
| <p>Press <span class="underline">Z</span> for Melee Attack (close range).</p> | |
| <p>Press <span class="underline">X</span> for Ranged Attack (shoot projectile).</p> | |
| <p>Dodge the boss attacks by moving out of their way.</p> | |
| <button id="start-boss-fight-btn" class="mt-6 font-bold rounded hover:brightness-110 transition">Start Fight</button> | |
| </div> | |
| <div id="boss-fight-game" class="relative w-[800px] h-[400px] rounded-lg shadow-lg overflow-hidden select-none hidden"> | |
| <!-- Health bars --> | |
| <div class="flex justify-between px-4 pt-3 pb-1"> | |
| <div> | |
| <div class="text-sm mb-1">Player Health</div> | |
| <div class="w-48 h-6 bg-red-900 rounded overflow-hidden border border-red-800"> | |
| <div id="player-health-bar" class="h-6 bg-red-600 transition-all duration-300"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="text-sm mb-1">Boss Health</div> | |
| <div class="w-48 h-6 bg-red-900 rounded overflow-hidden border border-red-800"> | |
| <div id="boss-health-bar" class="h-6 bg-red-600 transition-all duration-300"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Game arena --> | |
| <div id="arena" class="relative w-full h-[320px] bg-red-800 border border-red-900 rounded-b-lg overflow-hidden mt-2"> | |
| <!-- Player avatar --> | |
| <div id="player" class="absolute bottom-10 left-10"> | |
| You | |
| </div> | |
| <!-- Boss avatar --> | |
| <div id="boss" class="absolute top-10 right-10"> | |
| Boss | |
| <div id="boss-arm-left"></div> | |
| <div id="boss-arm-right"></div> | |
| </div> | |
| </div> | |
| <!-- Fight status messages --> | |
| <div id="fight-message" class="text-center mt-3 min-h-[24px]"></div> | |
| <!-- Exit button --> | |
| <button id="exit-boss-fight" class="mt-4 rounded hover:brightness-90 transition">Exit Boss Fight</button> | |
| </div> | |
| </div> | |
| <!-- Cheat Menu --> | |
| <div id="cheat-menu" class="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white p-6 rounded-lg shadow-xl z-50 hidden border-2 border-yellow-400"> | |
| <h2 class="text-2xl font-bold text-green-700 mb-4" style="color:#f6e58d;">Cheat Menu</h2> | |
| <div class="grid gap-4"> | |
| <button id="add-1000" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded"> | |
| Add 1,000 Giggity Bucks | |
| </button> | |
| <button id="add-10000" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded"> | |
| Add 10,000 Giggity Bucks | |
| </button> | |
| <button id="add-100000" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded"> | |
| Add 100,000 Giggity Bucks | |
| </button> | |
| <button id="max-all" class="bg-yellow-500 hover:bg-yellow-600 text-white py-2 px-4 rounded"> | |
| Max All Upgrades | |
| </button> | |
| <button id="close-cheats" class="bg-red-500 hover:bg-red-600 text-white py-2 px-4 rounded"> | |
| Close Menu | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| // Game variables themed and renamed | |
| let score = 0; // Giggity Bucks | |
| let autoGiggity = 0; | |
| let giggityArmy = 0; | |
| let quagParadise = 0; | |
| let giggityFarm = 0; | |
| let giggityKingdom = 0; | |
| let goldenQuag = 0; | |
| let giggityFactory = 0; | |
| let quagEmpire = 0; | |
| // Click power upgrade variables | |
| let clickPower = 0; | |
| let clickPowerCost = 50; | |
| // Mega Click upgrade variables | |
| let megaClick = 0; | |
| let megaClickCost = 250; | |
| // Upgrade costs | |
| let autoGiggityCost = 20; | |
| let giggityArmyCost = 100; | |
| let quagParadiseCost = 500; | |
| let giggityFarmCost = 1500; | |
| let giggityKingdomCost = 5000; | |
| let goldenQuagCost = 20000; | |
| let giggityFactoryCost = 50000; | |
| let quagEmpireCost = 100000; | |
| // Power Ups state and timers | |
| let powerUps = { | |
| giggityRush: { | |
| active: false, | |
| duration: 30000, | |
| cost: 25000, | |
| timerId: null, | |
| remainingTime: 0, | |
| }, | |
| lucky: { | |
| active: false, | |
| duration: 60000, | |
| cost: 35000, | |
| timerId: null, | |
| remainingTime: 0, | |
| }, | |
| quagShield: { | |
| active: false, | |
| duration: 30000, | |
| cost: 40000, | |
| timerId: null, | |
| remainingTime: 0, | |
| }, | |
| giggityMagnet: { | |
| active: false, | |
| duration: 45000, | |
| cost: 30000, | |
| timerId: null, | |
| remainingTime: 0, | |
| } | |
| }; | |
| // DOM elements | |
| const scoreElement = document.getElementById('score'); | |
| const frogButton = document.getElementById('frog'); | |
| const clickEffect = document.getElementById('click-effect'); | |
| // Upgrade elements | |
| const clickPowerCostElement = document.getElementById('click-power-cost'); | |
| const clickPowerOwnedElement = document.getElementById('click-power-owned'); | |
| const buyClickPowerButton = document.getElementById('buy-click-power'); | |
| const megaClickCostElement = document.getElementById('mega-click-cost'); | |
| const megaClickOwnedElement = document.getElementById('mega-click-owned'); | |
| const buyMegaClickButton = document.getElementById('buy-mega-click'); | |
| const autoTongueCostElement = document.getElementById('auto-tongue-cost'); | |
| const autoTongueOwnedElement = document.getElementById('auto-tongue-owned'); | |
| const buyAutoTongueButton = document.getElementById('buy-auto-tongue'); | |
| const frogArmyCostElement = document.getElementById('frog-army-cost'); | |
| const frogArmyOwnedElement = document.getElementById('frog-army-owned'); | |
| const buyFrogArmyButton = document.getElementById('buy-frog-army'); | |
| const pondParadiseCostElement = document.getElementById('pond-paradise-cost'); | |
| const pondParadiseOwnedElement = document.getElementById('pond-paradise-owned'); | |
| const buyPondParadiseButton = document.getElementById('buy-pond-paradise'); | |
| const flyFarmCostElement = document.getElementById('fly-farm-cost'); | |
| const flyFarmOwnedElement = document.getElementById('fly-farm-owned'); | |
| const buyFlyFarmButton = document.getElementById('buy-fly-farm'); | |
| const frogKingdomCostElement = document.getElementById('frog-kingdom-cost'); | |
| const frogKingdomOwnedElement = document.getElementById('frog-kingdom-owned'); | |
| const buyFrogKingdomButton = document.getElementById('buy-frog-kingdom'); | |
| const goldenHarrisCostElement = document.getElementById('golden-harris-cost'); | |
| const goldenHarrisOwnedElement = document.getElementById('golden-harris-owned'); | |
| const buyGoldenHarrisButton = document.getElementById('buy-golden-harris'); | |
| const flyFactoryCostElement = document.getElementById('fly-factory-cost'); | |
| const flyFactoryOwnedElement = document.getElementById('fly-factory-owned'); | |
| const buyFlyFactoryButton = document.getElementById('buy-fly-factory'); | |
| const harrisEmpireCostElement = document.getElementById('harris-empire-cost'); | |
| const harrisEmpireOwnedElement = document.getElementById('harris-empire-owned'); | |
| const buyHarrisEmpireButton = document.getElementById('buy-harris-empire'); | |
| // Power Ups buttons and timers | |
| const activateGiggityRushBtn = document.getElementById('activate-giggity-rush'); | |
| const giggityRushTimerEl = document.getElementById('giggity-rush-timer'); | |
| const activateLuckyBtn = document.getElementById('activate-lucky'); | |
| const luckyTimerEl = document.getElementById('lucky-timer'); | |
| const activateQuagShieldBtn = document.getElementById('activate-quag-shield'); | |
| const quagShieldTimerEl = document.getElementById('quag-shield-timer'); | |
| const activateGiggityMagnetBtn = document.getElementById('activate-giggity-magnet'); | |
| const giggityMagnetTimerEl = document.getElementById('giggity-magnet-timer'); | |
| // Achievement elements | |
| const achievements = { | |
| 10: document.getElementById('achievement-10'), | |
| 50: document.getElementById('achievement-50'), | |
| 100: document.getElementById('achievement-100'), | |
| 500: document.getElementById('achievement-500'), | |
| 1000: document.getElementById('achievement-1000'), | |
| 5000: document.getElementById('achievement-5000'), | |
| 100000: document.getElementById('achievement-100000'), | |
| 1000000: document.getElementById('achievement-1000000'), | |
| 10000000: document.getElementById('achievement-10000000'), | |
| }; | |
| // Harris Frenzy variables | |
| let isFrenzyActive = false; | |
| let frenzyEndTime = 0; | |
| // Lucky powerup effect on frenzy chance (increases by 50%) | |
| let luckyActive = false; | |
| // Giggity Magnet effect active flag | |
| let giggityMagnetActive = false; | |
| // Quag Shield effect active flag for boss fight damage reduction | |
| let quagShieldActive = false; | |
| // Income intervals | |
| const incomeIntervals = { | |
| autoGiggity: 1000, | |
| giggityArmy: 2000, | |
| quagParadise: 3000, | |
| giggityFarm: 4000, | |
| giggityKingdom: 6000, | |
| goldenQuag: 6000, | |
| giggityFactory: 6000, | |
| quagEmpire: 12000 | |
| }; | |
| // Last income timestamps | |
| let lastIncomeTimes = { | |
| autoGiggity: 0, | |
| giggityArmy: 0, | |
| quagParadise: 0, | |
| giggityFarm: 0, | |
| giggityKingdom: 0, | |
| goldenQuag: 0, | |
| giggityFactory: 0, | |
| quagEmpire: 0 | |
| }; | |
| // Click handler | |
| frogButton.addEventListener('click', () => { | |
| const baseClick = isFrenzyActive ? 2 : 1; | |
| let totalClick = baseClick + clickPower + megaClick * 10; | |
| if (giggityMagnetActive) { | |
| totalClick = Math.floor(totalClick * 1.5); | |
| } | |
| score += totalClick; | |
| updateScore(); | |
| clickEffect.textContent = `+${totalClick}`; | |
| clickEffect.style.opacity = '1'; | |
| clickEffect.style.top = `${Math.random() * 100}%`; | |
| clickEffect.style.left = `${Math.random() * 100}%`; | |
| setTimeout(() => { | |
| clickEffect.style.opacity = '0'; | |
| }, 500); | |
| if (Math.random() > 0.7) { | |
| playSound('ribbit'); | |
| } | |
| }); | |
| // Upgrade handlers | |
| buyClickPowerButton.addEventListener('click', () => { | |
| if (score >= clickPowerCost) { | |
| score -= clickPowerCost; | |
| clickPower++; | |
| clickPowerCost = Math.floor(clickPowerCost * 1.3); | |
| updateScore(); | |
| clickPowerOwnedElement.textContent = clickPower; | |
| clickPowerCostElement.textContent = clickPowerCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyMegaClickButton.addEventListener('click', () => { | |
| if (score >= megaClickCost) { | |
| score -= megaClickCost; | |
| megaClick++; | |
| megaClickCost = Math.floor(megaClickCost * 1.3); | |
| updateScore(); | |
| megaClickOwnedElement.textContent = megaClick; | |
| megaClickCostElement.textContent = megaClickCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyAutoTongueButton.addEventListener('click', () => { | |
| if (score >= autoGiggityCost) { | |
| score -= autoGiggityCost; | |
| autoGiggity++; | |
| autoGiggityCost = Math.floor(autoGiggityCost * 1.2); | |
| updateScore(); | |
| autoTongueOwnedElement.textContent = autoGiggity; | |
| autoTongueCostElement.textContent = autoGiggityCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyFrogArmyButton.addEventListener('click', () => { | |
| if (score >= giggityArmyCost) { | |
| score -= giggityArmyCost; | |
| giggityArmy++; | |
| giggityArmyCost = Math.floor(giggityArmyCost * 1.2); | |
| updateScore(); | |
| frogArmyOwnedElement.textContent = giggityArmy; | |
| frogArmyCostElement.textContent = giggityArmyCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyPondParadiseButton.addEventListener('click', () => { | |
| if (score >= quagParadiseCost) { | |
| score -= quagParadiseCost; | |
| quagParadise++; | |
| quagParadiseCost = Math.floor(quagParadiseCost * 1.2); | |
| updateScore(); | |
| pondParadiseOwnedElement.textContent = quagParadise; | |
| pondParadiseCostElement.textContent = quagParadiseCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyFlyFarmButton.addEventListener('click', () => { | |
| if (score >= giggityFarmCost) { | |
| score -= giggityFarmCost; | |
| giggityFarm++; | |
| giggityFarmCost = Math.floor(giggityFarmCost * 1.2); | |
| updateScore(); | |
| flyFarmOwnedElement.textContent = giggityFarm; | |
| flyFarmCostElement.textContent = giggityFarmCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyFrogKingdomButton.addEventListener('click', () => { | |
| if (score >= giggityKingdomCost) { | |
| score -= giggityKingdomCost; | |
| giggityKingdom++; | |
| giggityKingdomCost = Math.floor(giggityKingdomCost * 1.2); | |
| updateScore(); | |
| frogKingdomOwnedElement.textContent = giggityKingdom; | |
| frogKingdomCostElement.textContent = giggityKingdomCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyGoldenHarrisButton.addEventListener('click', () => { | |
| if (score >= goldenQuagCost) { | |
| score -= goldenQuagCost; | |
| goldenQuag++; | |
| goldenQuagCost = Math.floor(goldenQuagCost * 1.2); | |
| updateScore(); | |
| goldenHarrisOwnedElement.textContent = goldenQuag; | |
| goldenHarrisCostElement.textContent = goldenQuagCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyFlyFactoryButton.addEventListener('click', () => { | |
| if (score >= giggityFactoryCost) { | |
| score -= giggityFactoryCost; | |
| giggityFactory++; | |
| giggityFactoryCost = Math.floor(giggityFactoryCost * 1.2); | |
| updateScore(); | |
| flyFactoryOwnedElement.textContent = giggityFactory; | |
| flyFactoryCostElement.textContent = giggityFactoryCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| buyHarrisEmpireButton.addEventListener('click', () => { | |
| if (score >= quagEmpireCost) { | |
| score -= quagEmpireCost; | |
| quagEmpire++; | |
| quagEmpireCost = Math.floor(quagEmpireCost * 1.2); | |
| updateScore(); | |
| harrisEmpireOwnedElement.textContent = quagEmpire; | |
| harrisEmpireCostElement.textContent = quagEmpireCost; | |
| playSound('purchase'); | |
| } | |
| }); | |
| // Power Ups activation handlers | |
| activateGiggityRushBtn.addEventListener('click', () => { | |
| if (!powerUps.giggityRush.active && score >= powerUps.giggityRush.cost) { | |
| score -= powerUps.giggityRush.cost; | |
| powerUps.giggityRush.active = true; | |
| powerUps.giggityRush.remainingTime = powerUps.giggityRush.duration; | |
| updateScore(); | |
| playSound('purchase'); | |
| updatePowerUpTimer('giggityRush'); | |
| activateGiggityRushBtn.disabled = true; | |
| } | |
| }); | |
| activateLuckyBtn.addEventListener('click', () => { | |
| if (!powerUps.lucky.active && score >= powerUps.lucky.cost) { | |
| score -= powerUps.lucky.cost; | |
| powerUps.lucky.active = true; | |
| powerUps.lucky.remainingTime = powerUps.lucky.duration; | |
| luckyActive = true; | |
| updateScore(); | |
| playSound('purchase'); | |
| updatePowerUpTimer('lucky'); | |
| activateLuckyBtn.disabled = true; | |
| } | |
| }); | |
| activateQuagShieldBtn.addEventListener('click', () => { | |
| if (!powerUps.quagShield.active && score >= powerUps.quagShield.cost) { | |
| score -= powerUps.quagShield.cost; | |
| powerUps.quagShield.active = true; | |
| powerUps.quagShield.remainingTime = powerUps.quagShield.duration; | |
| quagShieldActive = true; | |
| updateScore(); | |
| playSound('purchase'); | |
| updatePowerUpTimer('quagShield'); | |
| activateQuagShieldBtn.disabled = true; | |
| } | |
| }); | |
| activateGiggityMagnetBtn.addEventListener('click', () => { | |
| if (!powerUps.giggityMagnet.active && score >= powerUps.giggityMagnet.cost) { | |
| score -= powerUps.giggityMagnet.cost; | |
| powerUps.giggityMagnet.active = true; | |
| powerUps.giggityMagnet.remainingTime = powerUps.giggityMagnet.duration; | |
| giggityMagnetActive = true; | |
| updateScore(); | |
| playSound('purchase'); | |
| updatePowerUpTimer('giggityMagnet'); | |
| activateGiggityMagnetBtn.disabled = true; | |
| } | |
| }); | |
| // Utility to update power up timers | |
| function updatePowerUpTimer(powerUpKey) { | |
| const powerUp = powerUps[powerUpKey]; | |
| const timerElement = { | |
| giggityRush: giggityRushTimerEl, | |
| lucky: luckyTimerEl, | |
| quagShield: quagShieldTimerEl, | |
| giggityMagnet: giggityMagnetTimerEl, | |
| }[powerUpKey]; | |
| if (!powerUp.active) { | |
| timerElement.textContent = ''; | |
| return; | |
| } | |
| timerElement.textContent = `Time left: ${(powerUp.remainingTime / 1000).toFixed(1)}s`; | |
| if (powerUp.timerId) clearInterval(powerUp.timerId); | |
| powerUp.timerId = setInterval(() => { | |
| powerUp.remainingTime -= 100; | |
| if (powerUp.remainingTime <= 0) { | |
| clearInterval(powerUp.timerId); | |
| powerUp.active = false; | |
| powerUp.remainingTime = 0; | |
| timerElement.textContent = ''; | |
| // Deactivate effects | |
| if (powerUpKey === 'giggityRush') { | |
| // no special flag needed, handled in income calculation | |
| } else if (powerUpKey === 'lucky') { | |
| luckyActive = false; | |
| } else if (powerUpKey === 'quagShield') { | |
| quagShieldActive = false; | |
| } else if (powerUpKey === 'giggityMagnet') { | |
| giggityMagnetActive = false; | |
| } | |
| // Re-enable button | |
| { | |
| const btn = { | |
| giggityRush: activateGiggityRushBtn, | |
| lucky: activateLuckyBtn, | |
| quagShield: activateQuagShieldBtn, | |
| giggityMagnet: activateGiggityMagnetBtn | |
| }[powerUpKey]; | |
| if (btn) btn.disabled = false; | |
| } | |
| } else { | |
| timerElement.textContent = `Time left: ${(powerUp.remainingTime / 1000).toFixed(1)}s`; | |
| } | |
| }, 100); | |
| } | |
| // Update score display and button states | |
| function updateScore() { | |
| scoreElement.textContent = score; | |
| checkAchievements(); | |
| buyClickPowerButton.disabled = score < clickPowerCost; | |
| buyMegaClickButton.disabled = score < megaClickCost; | |
| buyAutoTongueButton.disabled = score < autoGiggityCost; | |
| buyFrogArmyButton.disabled = score < giggityArmyCost; | |
| buyPondParadiseButton.disabled = score < quagParadiseCost; | |
| buyFlyFarmButton.disabled = score < giggityFarmCost; | |
| buyFrogKingdomButton.disabled = score < giggityKingdomCost; | |
| buyGoldenHarrisButton.disabled = score < goldenQuagCost; | |
| buyFlyFactoryButton.disabled = score < giggityFactoryCost; | |
| buyHarrisEmpireButton.disabled = score < quagEmpireCost; | |
| activateGiggityRushBtn.disabled = powerUps.giggityRush.active || score < powerUps.giggityRush.cost; | |
| activateLuckyBtn.disabled = powerUps.lucky.active || score < powerUps.lucky.cost; | |
| activateQuagShieldBtn.disabled = powerUps.quagShield.active || score < powerUps.quagShield.cost; | |
| activateGiggityMagnetBtn.disabled = powerUps.giggityMagnet.active || score < powerUps.giggityMagnet.cost; | |
| } | |
| // Check achievements | |
| function checkAchievements() { | |
| if (score >= 10) { | |
| achievements[10].style.opacity = '1'; | |
| achievements[10].classList.add('bg-green-100'); | |
| } | |
| if (score >= 50) { | |
| achievements[50].style.opacity = '1'; | |
| achievements[50].classList.add('bg-green-100'); | |
| } | |
| if (score >= 100) { | |
| achievements[100].style.opacity = '1'; | |
| achievements[100].classList.add('bg-green-100'); | |
| } | |
| if (score >= 500) { | |
| achievements[500].style.opacity = '1'; | |
| achievements[500].classList.add('bg-green-100'); | |
| } | |
| if (score >= 1000) { | |
| achievements[1000].style.opacity = '1'; | |
| achievements[1000].classList.add('bg-green-100'); | |
| } | |
| if (score >= 5000) { | |
| achievements[5000].style.opacity = '1'; | |
| achievements[5000].classList.add('bg-green-100'); | |
| } | |
| if (score >= 100000) { | |
| achievements[100000].style.opacity = '1'; | |
| achievements[100000].classList.add('bg-green-100'); | |
| } | |
| if (score >= 1000000) { | |
| achievements[1000000].style.opacity = '1'; | |
| achievements[1000000].classList.add('bg-green-100'); | |
| } | |
| if (score >= 10000000) { | |
| achievements[10000000].style.opacity = '1'; | |
| achievements[10000000].classList.add('bg-green-100'); | |
| } | |
| } | |
| // Passive income and frenzy logic | |
| setInterval(() => { | |
| const now = Date.now(); | |
| // Harris Frenzy chance modified by Lucky power up | |
| let frenzyChance = 0.2; | |
| if (luckyActive) frenzyChance *= 1.5; | |
| if ( | |
| !isFrenzyActive && | |
| now % 600000 < 1000 && | |
| Math.random() < frenzyChance | |
| ) { | |
| isFrenzyActive = true; | |
| frenzyEndTime = now + 45000; | |
| const frenzyText = document.createElement('div'); | |
| frenzyText.textContent = 'QUAGMIRE FRENZY!'; | |
| frenzyText.className = | |
| 'fixed inset-0 flex items-center justify-center text-6xl font-bold text-yellow-400 animate-pulse z-50'; | |
| document.body.appendChild(frenzyText); | |
| setTimeout(() => { | |
| frenzyText.remove(); | |
| }, 3000); | |
| alert('🐸 Quagmire Frenzy Activated! Click the mini Quagmires for 1000 Giggity Bucks each!'); | |
| const spawnMiniQuag = () => { | |
| if (!isFrenzyActive) return; | |
| const miniQuag = document.createElement('img'); | |
| miniQuag.src = | |
| "https://imgix.ranker.com/node_img/54/1077239/original/glenn-quagmire-tv-characters-photo-1?w=350&h=350&q=90&fm=jpg&fit=crop&crop=faces"; | |
| miniQuag.className = 'absolute w-16 h-16 cursor-pointer animate-bounce'; | |
| miniQuag.style.top = `${Math.random() * 80 + 10}%`; | |
| miniQuag.style.left = `${Math.random() * 80 + 10}%`; | |
| miniQuag.addEventListener('click', () => { | |
| score += 1000; | |
| updateScore(); | |
| miniQuag.remove(); | |
| playSound('purchase'); | |
| }); | |
| document.body.appendChild(miniQuag); | |
| setTimeout(() => { | |
| if (miniQuag.parentNode) { | |
| miniQuag.remove(); | |
| } | |
| }, 3000); | |
| if (isFrenzyActive) { | |
| setTimeout(spawnMiniQuag, 1000); | |
| } | |
| }; | |
| spawnMiniQuag(); | |
| } | |
| if (isFrenzyActive && now > frenzyEndTime) { | |
| isFrenzyActive = false; | |
| alert('Quagmire Frenzy has ended!'); | |
| document.querySelectorAll('img[src="https://static.wikia.nocookie.net/familyguy/images/4/42/Quagmire_S5.png"]').forEach(el => { | |
| if (!el.classList.contains('bounce')) { | |
| el.remove(); | |
| } | |
| }); | |
| } | |
| const multiplier = (powerUps.giggityRush.active ? 2 : 1) * (isFrenzyActive ? 1 : 1); // Frenzy doubles clicks only, passive income doubled by Giggity Rush | |
| if (autoGiggity > 0 && now - lastIncomeTimes.autoGiggity >= incomeIntervals.autoGiggity) { | |
| score += autoGiggity * multiplier; | |
| lastIncomeTimes.autoGiggity = now; | |
| updateScore(); | |
| } | |
| if (giggityArmy > 0 && now - lastIncomeTimes.giggityArmy >= incomeIntervals.giggityArmy) { | |
| score += giggityArmy * 5 * multiplier; | |
| lastIncomeTimes.giggityArmy = now; | |
| updateScore(); | |
| } | |
| if (quagParadise > 0 && now - lastIncomeTimes.quagParadise >= incomeIntervals.quagParadise) { | |
| score += quagParadise * 20 * multiplier; | |
| lastIncomeTimes.quagParadise = now; | |
| updateScore(); | |
| } | |
| if (giggityFarm > 0 && now - lastIncomeTimes.giggityFarm >= incomeIntervals.giggityFarm) { | |
| score += giggityFarm * 50 * multiplier; | |
| lastIncomeTimes.giggityFarm = now; | |
| updateScore(); | |
| } | |
| if (giggityKingdom > 0 && now - lastIncomeTimes.giggityKingdom >= incomeIntervals.giggityKingdom) { | |
| score += giggityKingdom * 100 * multiplier; | |
| lastIncomeTimes.giggityKingdom = now; | |
| updateScore(); | |
| } | |
| if (goldenQuag > 0 && now - lastIncomeTimes.goldenQuag >= incomeIntervals.goldenQuag) { | |
| score += goldenQuag * 200 * multiplier; | |
| lastIncomeTimes.goldenQuag = now; | |
| updateScore(); | |
| } | |
| if (giggityFactory > 0 && now - lastIncomeTimes.giggityFactory >= incomeIntervals.giggityFactory) { | |
| score += giggityFactory * 500 * multiplier; | |
| lastIncomeTimes.giggityFactory = now; | |
| updateScore(); | |
| } | |
| if (quagEmpire > 0 && now - lastIncomeTimes.quagEmpire >= incomeIntervals.quagEmpire) { | |
| score += quagEmpire * 1000 * multiplier; | |
| lastIncomeTimes.quagEmpire = now; | |
| updateScore(); | |
| } | |
| }, 200); | |
| // Sound effects | |
| function playSound(type) { | |
| if (type === 'ribbit') { | |
| const sounds = [ | |
| 'https://assets.mixkit.co/sfx/preview/mixkit-frog-croaking-1411.mp3', | |
| 'https://assets.mixkit.co/sfx/preview/mixkit-frog-croaking-1449.mp3', | |
| ]; | |
| const sound = new Audio(sounds[Math.floor(Math.random() * sounds.length)]); | |
| sound.volume = 0.3; | |
| sound.play(); | |
| } else if (type === 'purchase') { | |
| const sound = new Audio('https://assets.mixkit.co/sfx/preview/mixkit-casino-win-notification-1980.mp3'); | |
| sound.volume = 0.2; | |
| sound.play(); | |
| } | |
| } | |
| // Save game state | |
| function saveGame() { | |
| const gameState = { | |
| isFrenzyActive, | |
| frenzyEndTime, | |
| score, | |
| autoGiggity, | |
| giggityArmy, | |
| quagParadise, | |
| giggityFarm, | |
| giggityKingdom, | |
| goldenQuag, | |
| giggityFactory, | |
| quagEmpire, | |
| autoGiggityCost, | |
| giggityArmyCost, | |
| quagParadiseCost, | |
| giggityFarmCost, | |
| giggityKingdomCost, | |
| goldenQuagCost, | |
| giggityFactoryCost, | |
| quagEmpireCost, | |
| clickPower, | |
| clickPowerCost, | |
| megaClick, | |
| megaClickCost, | |
| powerUps: { | |
| giggityRush: { | |
| active: powerUps.giggityRush.active, | |
| remainingTime: powerUps.giggityRush.remainingTime | |
| }, | |
| lucky: { | |
| active: powerUps.lucky.active, | |
| remainingTime: powerUps.lucky.remainingTime | |
| }, | |
| quagShield: { | |
| active: powerUps.quagShield.active, | |
| remainingTime: powerUps.quagShield.remainingTime | |
| }, | |
| giggityMagnet: { | |
| active: powerUps.giggityMagnet.active, | |
| remainingTime: powerUps.giggityMagnet.remainingTime | |
| } | |
| } | |
| }; | |
| localStorage.setItem('quagClicker', JSON.stringify(gameState)); | |
| } | |
| // Load game state | |
| function loadGame() { | |
| const savedGame = localStorage.getItem('quagClicker'); | |
| if (savedGame) { | |
| const gameState = JSON.parse(savedGame); | |
| isFrenzyActive = gameState.isFrenzyActive || false; | |
| frenzyEndTime = gameState.frenzyEndTime || 0; | |
| score = gameState.score || 0; | |
| autoGiggity = gameState.autoGiggity || 0; | |
| giggityArmy = gameState.giggityArmy || 0; | |
| quagParadise = gameState.quagParadise || 0; | |
| giggityFarm = gameState.giggityFarm || 0; | |
| giggityKingdom = gameState.giggityKingdom || 0; | |
| goldenQuag = gameState.goldenQuag || 0; | |
| giggityFactory = gameState.giggityFactory || 0; | |
| quagEmpire = gameState.quagEmpire || 0; | |
| autoGiggityCost = gameState.autoGiggityCost || 20; | |
| giggityArmyCost = gameState.giggityArmyCost || 100; | |
| quagParadiseCost = gameState.quagParadiseCost || 500; | |
| giggityFarmCost = gameState.giggityFarmCost || 1500; | |
| giggityKingdomCost = gameState.giggityKingdomCost || 5000; | |
| goldenQuagCost = gameState.goldenQuagCost || 20000; | |
| giggityFactoryCost = gameState.giggityFactoryCost || 50000; | |
| quagEmpireCost = gameState.quagEmpireCost || 100000; | |
| clickPower = gameState.clickPower || 0; | |
| clickPowerCost = gameState.clickPowerCost || 50; | |
| megaClick = gameState.megaClick || 0; | |
| megaClickCost = gameState.megaClickCost || 250; | |
| // Load power ups states | |
| if (gameState.powerUps) { | |
| Object.keys(gameState.powerUps).forEach(key => { | |
| if (powerUps[key]) { | |
| powerUps[key].active = gameState.powerUps[key].active || false; | |
| powerUps[key].remainingTime = gameState.powerUps[key].remainingTime || 0; | |
| if (powerUps[key].active && powerUps[key].remainingTime > 0) { | |
| // Reactivate timer and effects on load | |
| if (key === 'lucky') luckyActive = true; | |
| if (key === 'quagShield') quagShieldActive = true; | |
| if (key === 'giggityMagnet') giggityMagnetActive = true; | |
| updatePowerUpTimer(key); | |
| // Disable buttons accordingly | |
| { | |
| const btn = { | |
| giggityRush: activateGiggityRushBtn, | |
| lucky: activateLuckyBtn, | |
| quagShield: activateQuagShieldBtn, | |
| giggityMagnet: activateGiggityMagnetBtn | |
| }[key]; | |
| if (btn) btn.disabled = true; | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| scoreElement.textContent = score; | |
| autoTongueOwnedElement.textContent = autoGiggity; | |
| frogArmyOwnedElement.textContent = giggityArmy; | |
| pondParadiseOwnedElement.textContent = quagParadise; | |
| flyFarmOwnedElement.textContent = giggityFarm; | |
| frogKingdomOwnedElement.textContent = giggityKingdom; | |
| goldenHarrisOwnedElement.textContent = goldenQuag; | |
| flyFactoryOwnedElement.textContent = giggityFactory; | |
| harrisEmpireOwnedElement.textContent = quagEmpire; | |
| autoTongueCostElement.textContent = autoGiggityCost; | |
| frogArmyCostElement.textContent = giggityArmyCost; | |
| pondParadiseCostElement.textContent = quagParadiseCost; | |
| flyFarmCostElement.textContent = giggityFarmCost; | |
| frogKingdomCostElement.textContent = giggityKingdomCost; | |
| goldenHarrisCostElement.textContent = goldenQuagCost; | |
| flyFactoryCostElement.textContent = giggityFactoryCost; | |
| harrisEmpireCostElement.textContent = quagEmpireCost; | |
| clickPowerOwnedElement.textContent = clickPower; | |
| clickPowerCostElement.textContent = clickPowerCost; | |
| megaClickOwnedElement.textContent = megaClick; | |
| megaClickCostElement.textContent = megaClickCost; | |
| checkAchievements(); | |
| } | |
| } | |
| // Autosave every 10 seconds | |
| setInterval(saveGame, 10000); | |
| // Cheat menu | |
| const cheatMenu = document.getElementById('cheat-menu'); | |
| // Cheat buttons | |
| document.getElementById('add-1000').addEventListener('click', () => { | |
| score += 1000; | |
| updateScore(); | |
| playSound('purchase'); | |
| }); | |
| document.getElementById('add-10000').addEventListener('click', () => { | |
| score += 10000; | |
| updateScore(); | |
| playSound('purchase'); | |
| }); | |
| document.getElementById('add-100000').addEventListener('click', () => { | |
| score += 100000; | |
| updateScore(); | |
| playSound('purchase'); | |
| }); | |
| document.getElementById('max-all').addEventListener('click', () => { | |
| clickPower = 999; | |
| megaClick = 999; | |
| autoGiggity = 999; | |
| giggityArmy = 999; | |
| quagParadise = 999; | |
| giggityFarm = 999; | |
| giggityKingdom = 999; | |
| goldenQuag = 999; | |
| giggityFactory = 999; | |
| quagEmpire = 999; | |
| clickPowerOwnedElement.textContent = clickPower; | |
| megaClickOwnedElement.textContent = megaClick; | |
| autoTongueOwnedElement.textContent = autoGiggity; | |
| frogArmyOwnedElement.textContent = giggityArmy; | |
| pondParadiseOwnedElement.textContent = quagParadise; | |
| flyFarmOwnedElement.textContent = giggityFarm; | |
| frogKingdomOwnedElement.textContent = giggityKingdom; | |
| goldenHarrisOwnedElement.textContent = goldenQuag; | |
| flyFactoryOwnedElement.textContent = giggityFactory; | |
| harrisEmpireOwnedElement.textContent = quagEmpire; | |
| playSound('purchase'); | |
| }); | |
| document.getElementById('close-cheats').addEventListener('click', () => { | |
| cheatMenu.classList.add('hidden'); | |
| // Show reopen button | |
| const reopenBtn = document.createElement('button'); | |
| reopenBtn.id = 'reopen-cheats'; | |
| reopenBtn.className = | |
| 'fixed top-4 left-4 bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-lg shadow-md z-50'; | |
| reopenBtn.textContent = 'Open Cheats'; | |
| reopenBtn.addEventListener('click', () => { | |
| cheatMenu.classList.remove('hidden'); | |
| reopenBtn.remove(); | |
| }); | |
| document.body.appendChild(reopenBtn); | |
| }); | |
| // Remove reopen button when cheats are opened via name | |
| document.getElementById('player-name').addEventListener('change', e => { | |
| const reopenBtn = document.getElementById('reopen-cheats'); | |
| if (reopenBtn && e.target.value.toLowerCase().includes('elmore orang man')) { | |
| reopenBtn.remove(); | |
| } | |
| }); | |
| // Name input check for cheat menu, easter eggs, and QUAGMIRE special | |
| let gimmeGiggityUses = 0; | |
| document.getElementById('player-name').addEventListener('change', e => { | |
| const val = e.target.value.trim(); | |
| // QUAGMIRE Easter egg (exact uppercase) | |
| if (val === 'QUAGMIRE') { | |
| score += 10000; | |
| updateScore(); | |
| playSound('purchase'); | |
| // Create modal for YouTube embed | |
| const modal = document.createElement('div'); | |
| modal.style.position = 'fixed'; | |
| modal.style.top = 0; | |
| modal.style.left = 0; | |
| modal.style.width = '100vw'; | |
| modal.style.height = '100vh'; | |
| modal.style.backgroundColor = 'rgba(0,0,0,0.8)'; | |
| modal.style.display = 'flex'; | |
| modal.style.justifyContent = 'center'; | |
| modal.style.alignItems = 'center'; | |
| modal.style.zIndex = 10000; | |
| const playerContainer = document.createElement('div'); | |
| playerContainer.id = 'yt-player'; | |
| modal.appendChild(playerContainer); | |
| document.body.appendChild(modal); | |
| // Load YouTube Iframe API if not loaded | |
| if (!window.YT) { | |
| const tag = document.createElement('script'); | |
| tag.src = "https://www.youtube.com/iframe_api"; | |
| document.head.appendChild(tag); | |
| } | |
| window.onYouTubeIframeAPIReady = function() { | |
| new YT.Player('yt-player', { | |
| height: '315', | |
| width: '560', | |
| videoId: 'YWFW0B9EBx0', | |
| playerVars: { | |
| autoplay: 1, | |
| controls: 0, | |
| rel: 0, | |
| modestbranding: 1 | |
| }, | |
| events: { | |
| 'onStateChange': function(event) { | |
| if (event.data === YT.PlayerState.ENDED) { | |
| if (modal.parentNode) { | |
| modal.parentNode.removeChild(modal); | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| }; | |
| if (window.YT && window.YT.Player) { | |
| window.onYouTubeIframeAPIReady(); | |
| } | |
| return; | |
| } | |
| // X999999999 Easter egg (exact uppercase) | |
| if (val === 'X999999999') { | |
| cheatMaxClickPowerActive = true; | |
| updateScore(); | |
| playSound('purchase'); | |
| alert('Cheat activated: Click power set to 999,999,999 per click!'); | |
| }frogButton.addEventListener('click', () => { | |
| if (cheatMaxClickPowerActive) { | |
| score += 999999999; | |
| } else { | |
| const baseClick = isFrenzyActive ? 2 : 1; | |
| let totalClick = baseClick + clickPower + megaClick * 10; | |
| if (giggityMagnetActive) { | |
| totalClick = Math.floor(totalClick * 1.5); | |
| } | |
| score += totalClick; | |
| } | |
| updateScore(); | |
| clickEffect.textContent = `+${cheatMaxClickPowerActive ? '999999999' : (isFrenzyActive ? 2 : 1) + clickPower + megaClick * 10}`; | |
| clickEffect.style.opacity = '1'; | |
| clickEffect.style.top = `${Math.random() * 100}%`; | |
| clickEffect.style.left = `${Math.random() * 100}%`; | |
| setTimeout(() => { | |
| clickEffect.style.opacity = '0'; | |
| }, 500); | |
| if (Math.random() > 0.7) { | |
| playSound('ribbit'); | |
| } | |
| }); | |
| // Boss Fight Easter egg (case-insensitive) | |
| if (val.toLowerCase() === 'boss fight') { | |
| const enterBossFightBtn = document.getElementById('enter-boss-fight-btn'); | |
| if (enterBossFightBtn && !enterBossFightBtn.disabled) { | |
| enterBossFightBtn.click(); | |
| } | |
| } | |
| // Cheat menu Easter egg | |
| if (val.toLowerCase().includes('elmore orang man')) { | |
| if (cheatMenu) { | |
| cheatMenu.classList.remove('hidden'); | |
| } | |
| } | |
| // Gimme sum giggity bucks Easter egg (max 3 uses) | |
| if (val.toLowerCase() === 'gimme sum goos') { | |
| if (gimmeGiggityUses < 3) { | |
| score += 1000; | |
| gimmeGiggityUses++; | |
| updateScore(); | |
| const message = document.createElement('div'); | |
| message.textContent = `🤑 Here you go! +1000 Giggity Bucks! (${3 - gimmeGiggityUses} uses left)`; | |
| message.className = | |
| 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded z-50'; | |
| document.body.appendChild(message); | |
| setTimeout(() => message.remove(), 3000); | |
| playSound('purchase'); | |
| } else { | |
| const message = document.createElement('div'); | |
| message.textContent = '❌ No more free Giggity Bucks for you!'; | |
| message.className = | |
| 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded z-50'; | |
| document.body.appendChild(message); | |
| setTimeout(() => message.remove(), 3000); | |
| } | |
| } | |
| }); | |
| // Initialize | |
| window.addEventListener('load', () => { | |
| loadGame(); | |
| feather.replace(); | |
| updateScore(); | |
| // Easter egg - double click Quagmire image | |
| frogButton.addEventListener('dblclick', () => { | |
| if (Math.random() < 1 / 500) { | |
| score += 1000; | |
| updateScore(); | |
| alert('👨💻 Wow! You found Quagmire\'s secret stash! +1000 Giggity Bucks!'); | |
| } | |
| }); | |
| }); | |
| // Boss Fight Feature Integration | |
| (() => { | |
| // Reference to main game UI container (the outer container div) | |
| const mainGameContainer = document.querySelector('.container.mx-auto'); | |
| // Boss fight UI elements | |
| const bossFightOverlay = document.getElementById('boss-fight-overlay'); | |
| const bossFightInstructions = document.getElementById('boss-fight-instructions'); | |
| const bossFightGame = document.getElementById('boss-fight-game'); | |
| const startBossFightBtn = document.getElementById('start-boss-fight-btn'); | |
| const exitBossFightBtn = document.getElementById('exit-boss-fight'); | |
| const fightMessage = document.getElementById('fight-message'); | |
| const enterBossFightContainer = document.getElementById('enter-boss-fight-container'); | |
| const enterBossFightBtn = document.getElementById('enter-boss-fight-btn'); | |
| // Player and boss elements | |
| const playerEl = document.getElementById('player'); | |
| const bossEl = document.getElementById('boss'); | |
| const playerHealthBar = document.getElementById('player-health-bar'); | |
| const bossHealthBar = document.getElementById('boss-health-bar'); | |
| const arena = document.getElementById('arena'); | |
| // Game state variables | |
| let playerHealth = 150; // Increased player health | |
| let bossHealth = 300; | |
| const arenaWidth = 800; // match container width | |
| const arenaHeight = 320; // match container height | |
| // Player properties | |
| const playerWidth = 48; | |
| const playerHeight = 48; | |
| let playerX = 80; | |
| const playerSpeed = 8; | |
| let playerCanMove = false; | |
| // Boss properties | |
| const bossWidth = 64; | |
| const bossHeight = 64; | |
| let bossX = arenaWidth - 80 - bossWidth; | |
| const bossSpeed = 6; | |
| // Attack state | |
| let keysPressed = {}; | |
| let playerAttacking = false; | |
| let playerAttackType = null; | |
| let playerAttackCooldown = false; | |
| let bossAttacking = false; | |
| let bossAttackCooldown = false; | |
| // Projectiles arrays | |
| let playerProjectiles = []; | |
| let bossProjectiles = []; | |
| // Boss movement direction: 1=right, -1=left | |
| let bossDirection = -1; | |
| // Fight active flag | |
| let fightActive = false; | |
| // Show "Enter Boss Fight" button when score >= 10 million | |
| function checkBossFightUnlock() { | |
| if (score >= 10000000) { | |
| enterBossFightContainer.style.display = 'block'; | |
| } else { | |
| enterBossFightContainer.style.display = 'none'; | |
| } | |
| } | |
| // Call on score update in your existing updateScore() | |
| const originalUpdateScore = updateScore; | |
| updateScore = function () { | |
| originalUpdateScore(); | |
| checkBossFightUnlock(); | |
| }; | |
| // Utility: clamp value between min and max | |
| function clamp(val, min, max) { | |
| return Math.min(Math.max(val, min), max); | |
| } | |
| // Update health bars UI | |
| function updateHealthBars() { | |
| playerHealthBar.style.width = `${(playerHealth / 150) * 100}%`; | |
| bossHealthBar.style.width = `${(bossHealth / 300) * 100}%`; | |
| } | |
| // Reset fight state | |
| function resetFight() { | |
| playerHealth = 150; | |
| bossHealth = 300; | |
| updateHealthBars(); | |
| playerX = 80; | |
| bossX = arenaWidth - 80 - bossWidth; | |
| playerAttacking = false; | |
| playerAttackCooldown = false; | |
| bossAttacking = false; | |
| bossAttackCooldown = false; | |
| playerProjectiles.forEach(p => p.el.remove()); | |
| bossProjectiles.forEach(p => p.el.remove()); | |
| playerProjectiles = []; | |
| bossProjectiles = []; | |
| fightMessage.textContent = ''; | |
| } | |
| // Reset all giggity bucks and upgrades after boss fight ends | |
| function resetGameProgress() { | |
| score = 0; | |
| autoGiggity = 0; | |
| giggityArmy = 0; | |
| quagParadise = 0; | |
| giggityFarm = 0; | |
| giggityKingdom = 0; | |
| goldenQuag = 0; | |
| giggityFactory = 0; | |
| quagEmpire = 0; | |
| clickPower = 0; | |
| megaClick = 0; | |
| autoGiggityCost = 20; | |
| giggityArmyCost = 100; | |
| quagParadiseCost = 500; | |
| giggityFarmCost = 1500; | |
| giggityKingdomCost = 5000; | |
| goldenQuagCost = 20000; | |
| giggityFactoryCost = 50000; | |
| quagEmpireCost = 100000; | |
| clickPowerCost = 50; | |
| megaClickCost = 250; | |
| // Reset power ups | |
| Object.keys(powerUps).forEach(key => { | |
| powerUps[key].active = false; | |
| powerUps[key].remainingTime = 0; | |
| powerUps[key].timerId && clearInterval(powerUps[key].timerId); | |
| }); | |
| luckyActive = false; | |
| giggityMagnetActive = false; | |
| quagShieldActive = false; | |
| updateScore(); | |
| autoTongueOwnedElement.textContent = autoGiggity; | |
| frogArmyOwnedElement.textContent = giggityArmy; | |
| pondParadiseOwnedElement.textContent = quagParadise; | |
| flyFarmOwnedElement.textContent = giggityFarm; | |
| frogKingdomOwnedElement.textContent = giggityKingdom; | |
| goldenHarrisOwnedElement.textContent = goldenQuag; | |
| flyFactoryOwnedElement.textContent = giggityFactory; | |
| harrisEmpireOwnedElement.textContent = quagEmpire; | |
| clickPowerOwnedElement.textContent = clickPower; | |
| megaClickOwnedElement.textContent = megaClick; | |
| autoTongueCostElement.textContent = autoGiggityCost; | |
| frogArmyCostElement.textContent = giggityArmyCost; | |
| pondParadiseCostElement.textContent = quagParadiseCost; | |
| flyFarmCostElement.textContent = giggityFarmCost; | |
| frogKingdomCostElement.textContent = giggityKingdomCost; | |
| goldenHarrisCostElement.textContent = goldenQuagCost; | |
| flyFactoryCostElement.textContent = giggityFactoryCost; | |
| harrisEmpireCostElement.textContent = quagEmpireCost; | |
| clickPowerCostElement.textContent = clickPowerCost; | |
| megaClickCostElement.textContent = megaClickCost; | |
| saveGame(); | |
| } | |
| // Show boss fight screen | |
| function showBossFightScreen() { | |
| mainGameContainer.style.display = 'none'; | |
| enterBossFightContainer.style.display = 'none'; | |
| bossFightOverlay.style.display = 'flex'; | |
| bossFightInstructions.style.display = 'block'; | |
| bossFightGame.style.display = 'none'; | |
| fightActive = false; | |
| } | |
| // Hide boss fight screen, return to main game | |
| function hideBossFightScreen() { | |
| bossFightOverlay.style.display = 'none'; | |
| mainGameContainer.style.display = ''; | |
| checkBossFightUnlock(); | |
| } | |
| // Start the actual fight gameplay | |
| function startFight() { | |
| bossFightInstructions.style.display = 'none'; | |
| bossFightGame.style.display = 'block'; | |
| resetFight(); | |
| fightActive = true; | |
| playerCanMove = true; | |
| playerEl.style.left = `${playerX}px`; | |
| playerEl.style.bottom = '10px'; | |
| playerEl.style.top = 'auto'; | |
| bossEl.style.left = bossX + 'px'; | |
| bossEl.style.top = '10px'; | |
| bossEl.style.bottom = 'auto'; | |
| // Reset boss arms to idle visible state | |
| const leftArm = document.getElementById('boss-arm-left'); | |
| const rightArm = document.getElementById('boss-arm-right'); | |
| leftArm.style.opacity = '1'; | |
| rightArm.style.opacity = '1'; | |
| leftArm.style.display = 'block'; | |
| rightArm.style.display = 'block'; | |
| leftArm.classList.remove('boss-arm-attack-left'); | |
| rightArm.classList.remove('boss-arm-attack-right'); | |
| fightMessage.textContent = 'Fight! Defeat the boss!'; | |
| } | |
| // Create projectile element | |
| function createProjectile(x, y, width, height, color) { | |
| const proj = document.createElement('div'); | |
| proj.className = 'absolute rounded-full'; | |
| proj.style.width = `${width}px`; | |
| proj.style.height = `${height}px`; | |
| proj.style.backgroundColor = color; | |
| proj.style.left = `${x}px`; | |
| proj.style.top = `${y}px`; | |
| arena.appendChild(proj); | |
| return proj; | |
| } | |
| // Player melee attack hitbox rectangle | |
| function getPlayerMeleeHitbox() { | |
| return { | |
| x: playerX + playerWidth / 2 - 20, | |
| y: arenaHeight - playerHeight - 40, | |
| width: 40, | |
| height: 40, | |
| }; | |
| } | |
| // Boss melee attack hitbox rectangle | |
| function getBossMeleeHitbox() { | |
| return { | |
| x: bossX + bossWidth / 2 - 20, | |
| y: 10 + bossHeight, | |
| width: 40, | |
| height: 40, | |
| }; | |
| } | |
| // Rectangle collision detection | |
| function rectsCollide(r1, r2) { | |
| return !( | |
| r2.x > r1.x + r1.width || | |
| r2.x + r2.width < r1.x || | |
| r2.y > r1.y + r1.height || | |
| r2.y + r2.height < r1.y | |
| ); | |
| } | |
| // Player attack functions | |
| function playerMeleeAttack() { | |
| if (playerAttackCooldown) return; | |
| playerAttacking = true; | |
| playerAttackType = 'melee'; | |
| fightMessage.textContent = 'You performed a MELEE attack!'; | |
| playSound('purchase'); | |
| playerAttackCooldown = true; | |
| const meleeHitbox = getPlayerMeleeHitbox(); | |
| const bossHitbox = { | |
| x: bossX, | |
| y: 10 + bossHeight, | |
| width: bossWidth, | |
| height: 40, | |
| }; | |
| if (rectsCollide(meleeHitbox, bossHitbox)) { | |
| bossHealth -= 20; | |
| if (bossHealth < 0) bossHealth = 0; | |
| updateHealthBars(); | |
| fightMessage.textContent = 'You hit the Boss with MELEE attack!'; | |
| } else { | |
| fightMessage.textContent = 'Melee attack missed!'; | |
| } | |
| setTimeout(() => { | |
| playerAttacking = false; | |
| }, 300); | |
| setTimeout(() => { | |
| playerAttackCooldown = false; | |
| fightMessage.textContent = ''; | |
| }, 800); | |
| } | |
| function playerRangedAttack() { | |
| if (playerAttackCooldown) return; | |
| playerAttacking = true; | |
| playerAttackType = 'ranged'; | |
| playerAttackCooldown = true; | |
| fightMessage.textContent = 'You fired a RANGED attack!'; | |
| playSound('purchase'); | |
| const projWidth = 16; | |
| const projHeight = 16; | |
| const projX = playerX + playerWidth / 2 - projWidth / 2; | |
| const projY = arenaHeight - playerHeight - projHeight; | |
| const projEl = createProjectile(projX, projY, projWidth, projHeight, 'limegreen'); | |
| const projectile = { | |
| el: projEl, | |
| x: projX, | |
| y: projY, | |
| width: projWidth, | |
| height: projHeight, | |
| speed: 12, | |
| damage: 10, | |
| direction: -1, | |
| }; | |
| playerProjectiles.push(projectile); | |
| setTimeout(() => { | |
| playerAttacking = false; | |
| }, 300); | |
| setTimeout(() => { | |
| playerAttackCooldown = false; | |
| fightMessage.textContent = ''; | |
| }, 800); | |
| } | |
| // Boss attack patterns | |
| function bossMeleeAttack() { | |
| if (bossAttackCooldown) return; | |
| bossAttacking = true; | |
| bossAttackCooldown = true; | |
| fightMessage.textContent = 'Boss uses MELEE swipe!'; | |
| playSound('ribbit'); | |
| const leftArm = document.getElementById('boss-arm-left'); | |
| const rightArm = document.getElementById('boss-arm-right'); | |
| leftArm.classList.add('boss-arm-attack-left'); | |
| rightArm.classList.add('boss-arm-attack-right'); | |
| setTimeout(() => { | |
| leftArm.classList.remove('boss-arm-attack-left'); | |
| rightArm.classList.remove('boss-arm-attack-right'); | |
| }, 600); | |
| const bossMeleeBox = getBossMeleeHitbox(); | |
| const playerBox = { | |
| x: playerX, | |
| y: arenaHeight - playerHeight - 40, | |
| width: playerWidth, | |
| height: 40, | |
| }; | |
| if (rectsCollide(bossMeleeBox, playerBox)) { | |
| let damage = 25; | |
| if (quagShieldActive) damage = Math.floor(damage / 2); | |
| playerHealth -= damage; | |
| if (playerHealth < 0) playerHealth = 0; | |
| updateHealthBars(); | |
| fightMessage.textContent = `Boss hit you with MELEE swipe! (-${damage} HP)`; | |
| } else { | |
| fightMessage.textContent = 'Boss MELEE swipe missed!'; | |
| } | |
| setTimeout(() => { | |
| bossAttacking = false; | |
| }, 600); | |
| setTimeout(() => { | |
| bossAttackCooldown = false; | |
| fightMessage.textContent = ''; | |
| }, 1200); | |
| } | |
| function bossRangedAttack() { | |
| if (bossAttackCooldown) return; | |
| bossAttacking = true; | |
| bossAttackCooldown = true; | |
| fightMessage.textContent = 'Boss fires a projectile!'; | |
| playSound('ribbit'); | |
| const projWidth = 20; | |
| const projHeight = 20; | |
| const projX = bossX + bossWidth / 2 - projWidth / 2; | |
| const projY = 10 + bossHeight; | |
| const projEl = createProjectile(projX, projY, projWidth, projHeight, 'red'); | |
| const projectile = { | |
| el: projEl, | |
| x: projX, | |
| y: projY, | |
| width: projWidth, | |
| height: projHeight, | |
| speed: 10, | |
| damage: 20, | |
| direction: 1, | |
| }; | |
| bossProjectiles.push(projectile); | |
| setTimeout(() => { | |
| bossAttacking = false; | |
| }, 600); | |
| setTimeout(() => { | |
| bossAttackCooldown = false; | |
| fightMessage.textContent = ''; | |
| }, 1200); | |
| } | |
| // Handle projectiles movement and collision | |
| function updateProjectiles() { | |
| playerProjectiles.forEach((p, i) => { | |
| p.y += p.speed * p.direction; | |
| if (p.y + p.height < 0) { | |
| p.el.remove(); | |
| playerProjectiles.splice(i, 1); | |
| return; | |
| } | |
| p.el.style.top = p.y + 'px'; | |
| const bossBox = { | |
| x: bossX, | |
| y: 10, | |
| width: bossWidth, | |
| height: bossHeight, | |
| }; | |
| const projBox = { x: p.x, y: p.y, width: p.width, height: p.height }; | |
| if (rectsCollide(projBox, bossBox)) { | |
| bossHealth -= p.damage; | |
| if (bossHealth < 0) bossHealth = 0; | |
| updateHealthBars(); | |
| fightMessage.textContent = 'Your projectile hit the Boss!'; | |
| p.el.remove(); | |
| playerProjectiles.splice(i, 1); | |
| } | |
| }); | |
| bossProjectiles.forEach((p, i) => { | |
| p.y += p.speed * p.direction; | |
| if (p.y > arenaHeight) { | |
| p.el.remove(); | |
| bossProjectiles.splice(i, 1); | |
| return; | |
| } | |
| p.el.style.top = p.y + 'px'; | |
| const playerBox = { | |
| x: playerX, | |
| y: arenaHeight - playerHeight, | |
| width: playerWidth, | |
| height: playerHeight, | |
| }; | |
| const projBox = { x: p.x, y: p.y, width: p.width, height: p.height }; | |
| if (rectsCollide(projBox, playerBox)) { | |
| let damage = p.damage; | |
| if (quagShieldActive) damage = Math.floor(damage / 2); | |
| playerHealth -= damage; | |
| if (playerHealth < 0) playerHealth = 0; | |
| updateHealthBars(); | |
| fightMessage.textContent = `Boss projectile hit you! (-${damage} HP)`; | |
| p.el.remove(); | |
| bossProjectiles.splice(i, 1); | |
| } | |
| }); | |
| } | |
| // Boss movement AI (simple side to side) | |
| function updateBossPosition() { | |
| bossX += bossDirection * bossSpeed; | |
| if (bossX < 0) { | |
| bossDirection = 1; | |
| } else if (bossX > arenaWidth - bossWidth) { | |
| bossDirection = -1; | |
| } | |
| bossEl.style.left = bossX + 'px'; | |
| bossEl.style.top = '10px'; | |
| } | |
| // Player movement update | |
| function updatePlayerPosition() { | |
| if (!playerCanMove) return; | |
| if (keysPressed['ArrowLeft']) { | |
| playerX -= playerSpeed; | |
| } | |
| if (keysPressed['ArrowRight']) { | |
| playerX += playerSpeed; | |
| } | |
| playerX = clamp(playerX, 0, arenaWidth - playerWidth); | |
| playerEl.style.left = playerX + 'px'; | |
| playerEl.style.bottom = '10px'; | |
| } | |
| // Main game loop for boss fight | |
| let lastBossAttackTime = 0; | |
| const bossAttackInterval = 2500; | |
| function bossFightLoop(timestamp) { | |
| if (!fightActive) return; | |
| updatePlayerPosition(); | |
| updateBossPosition(); | |
| updateProjectiles(); | |
| if (timestamp - lastBossAttackTime > bossAttackInterval && !bossAttackCooldown) { | |
| lastBossAttackTime = timestamp; | |
| const attackChoice = Math.random(); | |
| if (bossHealth < 150) { | |
| if (attackChoice < 0.6) { | |
| bossMeleeAttack(); | |
| } else { | |
| bossRangedAttack(); | |
| } | |
| } else { | |
| if (attackChoice < 0.4) { | |
| bossMeleeAttack(); | |
| } else { | |
| bossRangedAttack(); | |
| } | |
| } | |
| } | |
| if (bossHealth <= 0) { | |
| fightMessage.textContent = '🎉 You defeated the Boss! Congratulations!'; | |
| fightActive = false; | |
| playerCanMove = false; | |
| setTimeout(() => { | |
| alert('You won the Boss Fight! Returning to the main game.'); | |
| resetGameProgress(); | |
| hideBossFightScreen(); | |
| }, 2000); | |
| } else if (playerHealth <= 0) { | |
| fightMessage.textContent = '💀 You were defeated by the Boss... Try again!'; | |
| fightActive = false; | |
| playerCanMove = false; | |
| setTimeout(() => { | |
| alert('You lost the Boss Fight. Returning to the main game.'); | |
| resetGameProgress(); | |
| hideBossFightScreen(); | |
| }, 2000); | |
| } else { | |
| requestAnimationFrame(bossFightLoop); | |
| } | |
| } | |
| // Keyboard input handlers for player control | |
| window.addEventListener('keydown', (e) => { | |
| if (!fightActive) return; | |
| if (['ArrowLeft', 'ArrowRight'].includes(e.key)) { | |
| keysPressed[e.key] = true; | |
| e.preventDefault(); | |
| } | |
| if (e.key === 'z' || e.key === 'Z') { | |
| e.preventDefault(); | |
| playerMeleeAttack(); | |
| } | |
| if (e.key === 'x' || e.key === 'X') { | |
| e.preventDefault(); | |
| playerRangedAttack(); | |
| } | |
| }); | |
| window.addEventListener('keyup', (e) => { | |
| if (!fightActive) return; | |
| if (keysPressed[e.key]) { | |
| keysPressed[e.key] = false; | |
| e.preventDefault(); | |
| } | |
| }); | |
| enterBossFightBtn.addEventListener('click', () => { | |
| showBossFightScreen(); | |
| }); | |
| startBossFightBtn.addEventListener('click', () => { | |
| startFight(); | |
| requestAnimationFrame(bossFightLoop); | |
| }); | |
| exitBossFightBtn.addEventListener('click', () => { | |
| if (fightActive) { | |
| if (!confirm('Are you sure you want to exit the boss fight? Your progress will be lost.')) return; | |
| } | |
| fightActive = false; | |
| playerCanMove = false; | |
| resetFight(); | |
| resetGameProgress(); | |
| hideBossFightScreen(); | |
| }); | |
| window.addEventListener('load', () => { | |
| checkBossFightUnlock(); | |
| }); | |
| })(); | |
| </script> | |
| </body> | |
| </html> |