| |
| const game = { |
| personalScore: parseInt(localStorage.getItem('personalScore')) || 0, |
| globalScore: parseInt(localStorage.getItem('globalCookieScore')) || 0, |
| destroyerHunger: parseInt(localStorage.getItem('destroyerHunger')) || 50, |
| currentSkin: localStorage.getItem('currentSkin') || 'default', |
| unlockedSkins: JSON.parse(localStorage.getItem('unlockedSkins')) || ['default'], |
| playerCountry: localStorage.getItem('playerCountry') || null, |
| countryScores: JSON.parse(localStorage.getItem('countryScores')) || {}, |
| orbitAngle: 0, |
| orbitSpeed: 3, |
| multiplier: 1, |
| specialEffectUnlocked: false, |
| lastTime: 0 |
| }; |
|
|
| |
| const countries = [ |
| { code: 'US', name: 'United States', flag: '๐บ๐ธ' }, |
| { code: 'CN', name: 'China', flag: '๐จ๐ณ' }, |
| { code: 'JP', name: 'Japan', flag: '๐ฏ๐ต' }, |
| { code: 'DE', name: 'Germany', flag: '๐ฉ๐ช' }, |
| { code: 'GB', name: 'United Kingdom', flag: '๐ฌ๐ง' }, |
| { code: 'FR', name: 'France', flag: '๐ซ๐ท' }, |
| { code: 'IN', name: 'India', flag: '๐ฎ๐ณ' }, |
| { code: 'BR', name: 'Brazil', flag: '๐ง๐ท' }, |
| { code: 'RU', name: 'Russia', flag: '๐ท๐บ' }, |
| { code: 'KR', name: 'South Korea', flag: '๐ฐ๐ท' }, |
| { code: 'CA', name: 'Canada', flag: '๐จ๐ฆ' }, |
| { code: 'AU', name: 'Australia', flag: '๐ฆ๐บ' }, |
| { code: 'IT', name: 'Italy', flag: '๐ฎ๐น' }, |
| { code: 'ES', name: 'Spain', flag: '๐ช๐ธ' }, |
| { code: 'MX', name: 'Mexico', flag: '๐ฒ๐ฝ' }, |
| { code: 'NL', name: 'Netherlands', flag: '๐ณ๐ฑ' } |
| ]; |
|
|
| |
| const elements = { |
| personalScore: document.getElementById('personalScore'), |
| globalScore: document.getElementById('globalScore'), |
| destroyerHunger: document.getElementById('destroyerHunger'), |
| hungerPercent: document.getElementById('hungerPercent'), |
| cookieBtn: document.getElementById('cookieBtn'), |
| cookieVisual: document.getElementById('cookieVisual'), |
| orbitIndicator: document.getElementById('orbitIndicator'), |
| multiplierBadge: document.getElementById('multiplierBadge'), |
| multiplierText: document.getElementById('multiplierText'), |
| feedDestroyerBtn: document.getElementById('feedDestroyerBtn'), |
| warningOverlay: document.getElementById('warningOverlay'), |
| resetModal: document.getElementById('resetModal'), |
| dismissReset: document.getElementById('dismissReset'), |
| floatingText: document.getElementById('floatingText'), |
| particles: document.getElementById('particles'), |
| skinsGrid: document.getElementById('skinsGrid'), |
| countryModal: document.getElementById('countryModal'), |
| countryGrid: document.getElementById('countryGrid'), |
| playerCountry: document.getElementById('playerCountry'), |
| leaderboardList: document.getElementById('leaderboardList') |
| }; |
|
|
| |
| const skins = { |
| default: { class: 'cookie-skin-default', name: 'Classic' }, |
| chocolate: { class: 'cookie-skin-chocolate', name: 'Chocolate' }, |
| golden: { class: 'cookie-skin-golden', name: 'Golden' }, |
| galaxy: { class: 'cookie-skin-galaxy', name: 'Galaxy' }, |
| radioactive: { class: 'cookie-skin-radioactive', name: 'Radioactive' }, |
| cosmic: { class: 'cookie-skin-cosmic', name: 'Cosmic' }, |
| void: { class: 'cookie-skin-void', name: 'Void' } |
| }; |
|
|
| |
| function init() { |
| if (!game.playerCountry) { |
| showCountrySelection(); |
| } else { |
| elements.playerCountry.textContent = getCountryFlag(game.playerCountry); |
| updateMultiplier(); |
| applySkin(game.currentSkin); |
| updateUI(); |
| startOrbitLoop(); |
| startDestroyerLoop(); |
| setupEventListeners(); |
| checkSkinsAvailability(); |
| updateLeaderboard(); |
| |
| if (game.destroyerHunger <= 0) { |
| showResetModal(); |
| } |
| } |
| } |
|
|
| |
| function showCountrySelection() { |
| elements.countryModal.classList.remove('hidden'); |
| elements.countryGrid.innerHTML = countries.map(c => ` |
| <button class="country-btn p-3 bg-amber-800/50 hover:bg-amber-700 border border-amber-600 rounded-xl flex items-center gap-2 transition-all active:scale-95" data-code="${c.code}"> |
| <span class="text-2xl">${c.flag}</span> |
| <span class="text-amber-100 font-bold text-sm">${c.name}</span> |
| </button> |
| `).join(''); |
| |
| document.querySelectorAll('.country-btn').forEach(btn => { |
| btn.addEventListener('click', () => { |
| selectCountry(btn.dataset.code); |
| }); |
| }); |
| } |
|
|
| function selectCountry(code) { |
| game.playerCountry = code; |
| localStorage.setItem('playerCountry', code); |
| |
| |
| if (!game.countryScores[code]) { |
| game.countryScores[code] = 0; |
| localStorage.setItem('countryScores', JSON.stringify(game.countryScores)); |
| } |
| |
| elements.countryModal.classList.add('hidden'); |
| elements.playerCountry.textContent = getCountryFlag(code); |
| |
| updateMultiplier(); |
| applySkin(game.currentSkin); |
| updateUI(); |
| startOrbitLoop(); |
| startDestroyerLoop(); |
| setupEventListeners(); |
| checkSkinsAvailability(); |
| updateLeaderboard(); |
| } |
|
|
| function getCountryFlag(code) { |
| const country = countries.find(c => c.code === code); |
| return country ? country.flag : '๐'; |
| } |
|
|
| |
| function startOrbitLoop() { |
| function animate(currentTime) { |
| |
| game.orbitAngle += game.orbitSpeed; |
| if (game.orbitAngle >= 360) game.orbitAngle = 0; |
| |
| |
| const radius = 120; |
| const centerX = 144; |
| const centerY = 144; |
| const angleRad = (game.orbitAngle * Math.PI) / 180; |
| |
| const x = centerX + radius * Math.cos(angleRad); |
| const y = centerY + radius * Math.sin(angleRad); |
| |
| elements.orbitIndicator.style.left = x + 'px'; |
| elements.orbitIndicator.style.top = y + 'px'; |
| |
| |
| |
| const distanceFromTop = Math.abs(((game.orbitAngle + 90) % 360)); |
| const normalizedDist = distanceFromTop > 180 ? 360 - distanceFromTop : distanceFromTop; |
| |
| if (normalizedDist < 20) { |
| elements.orbitIndicator.style.backgroundColor = '#4ade80'; |
| elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1.3)'; |
| } else if (normalizedDist < 45) { |
| elements.orbitIndicator.style.backgroundColor = '#60a5fa'; |
| elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1.1)'; |
| } else { |
| elements.orbitIndicator.style.backgroundColor = '#ffffff'; |
| elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1)'; |
| } |
| |
| requestAnimationFrame(animate); |
| } |
| requestAnimationFrame(animate); |
| } |
|
|
| |
| function getTimingBonus() { |
| |
| const distanceFromTop = Math.abs(((game.orbitAngle + 90) % 360)); |
| const normalizedDist = distanceFromTop > 180 ? 360 - distanceFromTop : distanceFromTop; |
| |
| if (normalizedDist <= 10) { |
| return { multiplier: 5, text: 'PERFECT!', color: '#4ade80', class: 'timing-perfect' }; |
| } else if (normalizedDist <= 25) { |
| return { multiplier: 3, text: 'GREAT!', color: '#60a5fa', class: 'timing-great' }; |
| } else if (normalizedDist <= 45) { |
| return { multiplier: 2, text: 'GOOD', color: '#fbbf24', class: 'timing-good' }; |
| } else { |
| return { multiplier: 1, text: 'MISS', color: '#f87171', class: '' }; |
| } |
| } |
|
|
| |
| function handleCookieClick(e) { |
| e.preventDefault(); |
| |
| const timing = getTimingBonus(); |
| const baseGain = game.multiplier; |
| const totalGain = baseGain * timing.multiplier; |
| |
| |
| game.personalScore += totalGain; |
| |
| |
| game.globalScore += totalGain; |
| |
| |
| if (game.playerCountry) { |
| game.countryScores[game.playerCountry] = (game.countryScores[game.playerCountry] || 0) + totalGain; |
| } |
| |
| |
| localStorage.setItem('personalScore', game.personalScore); |
| localStorage.setItem('globalCookieScore', game.globalScore); |
| localStorage.setItem('countryScores', JSON.stringify(game.countryScores)); |
| |
| |
| showFloatingText(totalGain, timing.text, timing.color); |
| createParticles(timing.multiplier); |
| |
| |
| elements.cookieVisual.className = elements.cookieVisual.className.replace(/timing-\w+/g, ''); |
| if (timing.class) { |
| elements.cookieVisual.classList.add(timing.class); |
| setTimeout(() => { |
| elements.cookieVisual.classList.remove(timing.class); |
| }, 300); |
| } |
| |
| |
| elements.cookieBtn.style.transform = 'scale(0.95)'; |
| setTimeout(() => { |
| elements.cookieBtn.style.transform = 'scale(1)'; |
| }, 100); |
| |
| |
| if (game.specialEffectUnlocked) { |
| createSpecialEffect(); |
| } |
| |
| updateMultiplier(); |
| updateUI(); |
| checkSkinsAvailability(); |
| updateLeaderboard(); |
| |
| |
| if (navigator.vibrate) { |
| navigator.vibrate(timing.multiplier > 1 ? [20, 30, 20] : 10); |
| } |
| } |
|
|
| |
| function showFloatingText(amount, label, color) { |
| const rect = elements.cookieBtn.getBoundingClientRect(); |
| const containerRect = document.getElementById('cookieContainer').getBoundingClientRect(); |
| |
| const el = document.createElement('div'); |
| el.className = 'floating-text'; |
| el.style.left = '50%'; |
| el.style.top = '40%'; |
| el.style.transform = 'translate(-50%, -50%)'; |
| el.style.color = color; |
| el.style.fontSize = label === 'PERFECT!' ? '1.5rem' : '1.2rem'; |
| el.innerHTML = `<div class="text-center">${label}<br/>+${amount}</div>`; |
| |
| document.getElementById('cookieContainer').appendChild(el); |
| setTimeout(() => el.remove(), 1000); |
| } |
|
|
| |
| function createParticles(intensity) { |
| const count = intensity * 4; |
| const colors = ['#fbbf24', '#f59e0b', '#d97706', '#ffffff', '#4ade80', '#60a5fa']; |
| |
| for (let i = 0; i < count; i++) { |
| const particle = document.createElement('div'); |
| particle.className = 'particle'; |
| particle.style.left = '50%'; |
| particle.style.top = '50%'; |
| particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; |
| |
| const angle = (Math.PI * 2 * i) / count; |
| const velocity = 60 + Math.random() * 60; |
| const tx = Math.cos(angle) * velocity; |
| const ty = Math.sin(angle) * velocity; |
| |
| particle.style.setProperty('--tx', tx + 'px'); |
| particle.style.setProperty('--ty', ty + 'px'); |
| |
| elements.particles.appendChild(particle); |
| setTimeout(() => particle.remove(), 1000); |
| } |
| } |
|
|
| |
| function createSpecialEffect() { |
| |
| elements.cookieVisual.style.filter = 'hue-rotate(0deg)'; |
| let rotation = 0; |
| const rainbowInterval = setInterval(() => { |
| rotation += 30; |
| elements.cookieVisual.style.filter = `hue-rotate(${rotation}deg)`; |
| if (rotation >= 360) { |
| clearInterval(rainbowInterval); |
| elements.cookieVisual.style.filter = ''; |
| } |
| }, 50); |
| |
| |
| document.body.classList.add('animate-shake'); |
| setTimeout(() => document.body.classList.remove('animate-shake'), 500); |
| |
| |
| createParticles(10); |
| |
| |
| const ring = document.createElement('div'); |
| ring.style.cssText = ` |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| transform: translate(-50%, -50%); |
| width: 100%; |
| height: 100%; |
| border-radius: 50%; |
| border: 6px solid rgba(255,255,255,0.9); |
| animation: particle-float 0.8s ease-out forwards; |
| pointer-events: none; |
| z-index: 5; |
| `; |
| ring.style.setProperty('--tx', '0px'); |
| ring.style.setProperty('--ty', '0px'); |
| elements.particles.appendChild(ring); |
| setTimeout(() => ring.remove(), 800); |
| } |
|
|
| |
| function updateMultiplier() { |
| let baseMult = 1; |
| let bonusText = 'x1'; |
| |
| |
| |
| |
| |
| if (game.personalScore >= 1000000) { |
| baseMult = 6; |
| bonusText = 'x6 (LEGENDARY)'; |
| game.specialEffectUnlocked = true; |
| } else if (game.personalScore >= 10000) { |
| baseMult = 3; |
| bonusText = 'x3 (MASTER)'; |
| game.specialEffectUnlocked = false; |
| } else if (game.personalScore >= 1000) { |
| baseMult = 2; |
| bonusText = 'x2 (APPRENTICE)'; |
| game.specialEffectUnlocked = false; |
| } |
| |
| game.multiplier = baseMult; |
| elements.multiplierText.textContent = bonusText; |
| |
| if (baseMult > 1) { |
| elements.multiplierBadge.classList.remove('opacity-0'); |
| elements.multiplierBadge.classList.add('animate-pulse'); |
| } |
| } |
|
|
| |
| function feedDestroyer() { |
| if (game.personalScore >= 10) { |
| game.personalScore -= 10; |
| game.destroyerHunger = Math.min(100, game.destroyerHunger + 5); |
| |
| localStorage.setItem('personalScore', game.personalScore); |
| localStorage.setItem('destroyerHunger', game.destroyerHunger); |
| |
| updateUI(); |
| |
| |
| elements.feedDestroyerBtn.classList.add('animate-pulse'); |
| setTimeout(() => elements.feedDestroyerBtn.classList.remove('animate-pulse'), 500); |
| |
| if (navigator.vibrate) navigator.vibrate([10, 20]); |
| } else { |
| elements.feedDestroyerBtn.classList.add('animate-shake'); |
| setTimeout(() => elements.feedDestroyerBtn.classList.remove('animate-shake'), 500); |
| } |
| } |
|
|
| |
| function startDestroyerLoop() { |
| setInterval(() => { |
| game.destroyerHunger -= 1; |
| |
| if (game.destroyerHunger <= 0) { |
| game.destroyerHunger = 0; |
| triggerGlobalReset(); |
| } |
| |
| localStorage.setItem('destroyerHunger', game.destroyerHunger); |
| updateUI(); |
| |
| |
| if (game.destroyerHunger <= 20) { |
| elements.warningOverlay.classList.remove('opacity-0'); |
| if (game.destroyerHunger <= 10) { |
| elements.warningOverlay.classList.add('animate-pulse'); |
| } |
| } else { |
| elements.warningOverlay.classList.add('opacity-0'); |
| elements.warningOverlay.classList.remove('animate-pulse'); |
| } |
| }, 5000); |
| } |
|
|
| |
| function triggerGlobalReset() { |
| game.globalScore = 0; |
| game.countryScores = {}; |
| localStorage.setItem('globalCookieScore', 0); |
| localStorage.setItem('countryScores', JSON.stringify({})); |
| game.destroyerHunger = 50; |
| localStorage.setItem('destroyerHunger', 50); |
| |
| showResetModal(); |
| updateUI(); |
| updateLeaderboard(); |
| } |
|
|
| function showResetModal() { |
| elements.resetModal.classList.remove('hidden'); |
| if (navigator.vibrate) navigator.vibrate([100, 50, 100, 50, 200]); |
| } |
|
|
| |
| function updateLeaderboard() { |
| |
| const simulatedScores = { ...game.countryScores }; |
| |
| |
| countries.forEach(c => { |
| if (!simulatedScores[c.code]) { |
| |
| simulatedScores[c.code] = Math.floor(Math.random() * game.personalScore * 0.8); |
| } |
| }); |
| |
| |
| const sorted = Object.entries(simulatedScores) |
| .map(([code, score]) => ({ |
| code, |
| flag: getCountryFlag(code), |
| name: countries.find(c => c.code === code)?.name || code, |
| score, |
| isPlayer: code === game.playerCountry |
| })) |
| .sort((a, b) => b.score - a.score) |
| .slice(0, 5); |
| |
| elements.leaderboardList.innerHTML = sorted.map((item, index) => ` |
| <div class="leaderboard-item ${item.isPlayer ? 'current-player' : ''}"> |
| <div class="flex items-center gap-2"> |
| <span class="text-amber-400 font-bold w-6">#${index + 1}</span> |
| <span class="text-xl">${item.flag}</span> |
| <span class="text-amber-100 text-sm font-bold ${item.isPlayer ? 'text-amber-300' : ''}"> |
| ${item.name} ${item.isPlayer ? '(You)' : ''} |
| </span> |
| </div> |
| <span class="text-white font-mono font-bold">${item.score.toLocaleString()}</span> |
| </div> |
| `).join(''); |
| } |
|
|
| |
| function applySkin(skinName) { |
| const skin = skins[skinName]; |
| if (!skin) return; |
| |
| |
| Object.values(skins).forEach(s => { |
| elements.cookieVisual.classList.remove(s.class); |
| }); |
| |
| |
| elements.cookieVisual.classList.add(skin.class); |
| game.currentSkin = skinName; |
| localStorage.setItem('currentSkin', skinName); |
| |
| |
| document.querySelectorAll('.skin-btn').forEach(btn => { |
| btn.classList.remove('ring-4', 'ring-amber-400', 'scale-110'); |
| if (btn.dataset.skin === skinName) { |
| btn.classList.add('ring-4', 'ring-amber-400', 'scale-110'); |
| } |
| }); |
| } |
|
|
| function unlockSkin(skinName, cost) { |
| if (game.personalScore >= cost && !game.unlockedSkins.includes(skinName)) { |
| game.personalScore -= cost; |
| game.unlockedSkins.push(skinName); |
| localStorage.setItem('personalScore', game.personalScore); |
| localStorage.setItem('unlockedSkins', JSON.stringify(game.unlockedSkins)); |
| |
| applySkin(skinName); |
| updateUI(); |
| checkSkinsAvailability(); |
| |
| |
| createParticles(5); |
| } |
| } |
|
|
| function checkSkinsAvailability() { |
| document.querySelectorAll('.skin-btn').forEach(btn => { |
| const skin = btn.dataset.skin; |
| const cost = parseInt(btn.dataset.cost) || 0; |
| |
| if (game.unlockedSkins.includes(skin)) { |
| btn.classList.remove('locked', 'opacity-50', 'border-gray-600'); |
| btn.classList.add('unlocked', 'border-amber-500'); |
| const lockOverlay = btn.querySelector('.absolute.inset-0.bg-black\\/60'); |
| if (lockOverlay) lockOverlay.remove(); |
| |
| if (skin === game.currentSkin) { |
| btn.classList.add('ring-4', 'ring-amber-400', 'scale-110'); |
| } |
| } else { |
| |
| if (game.personalScore >= cost) { |
| btn.classList.add('border-amber-500', 'cursor-pointer'); |
| btn.classList.remove('border-gray-600', 'opacity-50'); |
| btn.classList.add('opacity-80'); |
| } |
| } |
| }); |
| } |
|
|
| |
| function setupEventListeners() { |
| |
| elements.cookieBtn.addEventListener('click', handleCookieClick); |
| elements.cookieBtn.addEventListener('touchstart', (e) => { |
| e.preventDefault(); |
| handleCookieClick(e); |
| }, { passive: false }); |
| |
| |
| elements.feedDestroyerBtn.addEventListener('click', feedDestroyer); |
| |
| |
| elements.dismissReset.addEventListener('click', () => { |
| elements.resetModal.classList.add('hidden'); |
| }); |
| |
| |
| document.querySelectorAll('.skin-btn').forEach(btn => { |
| btn.addEventListener('click', () => { |
| const skin = btn.dataset.skin; |
| const cost = parseInt(btn.dataset.cost) || 0; |
| |
| if (game.unlockedSkins.includes(skin)) { |
| applySkin(skin); |
| } else if (game.personalScore >= cost) { |
| unlockSkin(skin, cost); |
| } else { |
| btn.classList.add('animate-shake'); |
| setTimeout(() => btn.classList.remove('animate-shake'), 500); |
| } |
| }); |
| }); |
| } |
|
|
| |
| function updateUI() { |
| elements.personalScore.textContent = game.personalScore.toLocaleString(); |
| elements.globalScore.textContent = game.globalScore.toLocaleString(); |
| elements.destroyerHunger.style.width = game.destroyerHunger + '%'; |
| elements.hungerPercent.textContent = game.destroyerHunger + '%'; |
| |
| |
| if (game.destroyerHunger > 50) { |
| elements.destroyerHunger.className = 'h-full bg-gradient-to-r from-green-600 to-green-500 transition-all duration-500'; |
| } else if (game.destroyerHunger > 25) { |
| elements.destroyerHunger.className = 'h-full bg-gradient-to-r from-yellow-600 to-yellow-500 transition-all duration-500'; |
| } else { |
| elements.destroyerHunger.className = 'h-full bg-gradient-to-r from-red-600 to-red-500 transition-all duration-500 animate-pulse'; |
| } |
| |
| |
| if (game.personalScore < 10) { |
| elements.feedDestroyerBtn.classList.add('opacity-50', 'cursor-not-allowed'); |
| } else { |
| elements.feedDestroyerBtn.classList.remove('opacity-50', 'cursor-not-allowed'); |
| } |
| } |
|
|
| |
| init(); |
|
|
| |
| setInterval(() => { |
| if (Math.random() > 0.6 && game.globalScore > 0) { |
| |
| const randomCountry = countries[Math.floor(Math.random() * countries.length)].code; |
| const gain = Math.floor(Math.random() * 10) + 1; |
| |
| game.globalScore += gain; |
| game.countryScores[randomCountry] = (game.countryScores[randomCountry] || 0) + gain; |
| |
| localStorage.setItem('globalCookieScore', game.globalScore); |
| localStorage.setItem('countryScores', JSON.stringify(game.countryScores)); |
| |
| elements.globalScore.textContent = game.globalScore.toLocaleString(); |
| updateLeaderboard(); |
| } |
| }, 5000); |