DiamondVi's picture
Initial DeepSite commit
3714240 verified
// Game State
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, // degrees per frame
multiplier: 1,
specialEffectUnlocked: false,
lastTime: 0
};
// Country Data with Emoji Flags
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: '๐Ÿ‡ณ๐Ÿ‡ฑ' }
];
// DOM Elements
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')
};
// Skin Definitions
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' }
};
// Initialize Game
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();
}
}
}
// Country Selection
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);
// Initialize country score if not exists
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 : '๐ŸŒ';
}
// Orbit/Timing Mechanic Loop
function startOrbitLoop() {
function animate(currentTime) {
// Update orbit angle
game.orbitAngle += game.orbitSpeed;
if (game.orbitAngle >= 360) game.orbitAngle = 0;
// Calculate position (120px radius from center)
const radius = 120;
const centerX = 144; // half of 288 (w-72)
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';
// Visual cue when approaching top (perfect zone)
// Top is at angle 270 degrees (or -90)
const distanceFromTop = Math.abs(((game.orbitAngle + 90) % 360));
const normalizedDist = distanceFromTop > 180 ? 360 - distanceFromTop : distanceFromTop;
if (normalizedDist < 20) {
elements.orbitIndicator.style.backgroundColor = '#4ade80'; // Green
elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1.3)';
} else if (normalizedDist < 45) {
elements.orbitIndicator.style.backgroundColor = '#60a5fa'; // Blue
elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1.1)';
} else {
elements.orbitIndicator.style.backgroundColor = '#ffffff'; // White
elements.orbitIndicator.style.transform = 'translate(-50%, -50%) scale(1)';
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
}
// Calculate timing bonus based on orbit position
function getTimingBonus() {
// Top is at 270 degrees (or -90), which is where the perfect zone is
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: '' };
}
}
// Click Handler
function handleCookieClick(e) {
e.preventDefault();
const timing = getTimingBonus();
const baseGain = game.multiplier;
const totalGain = baseGain * timing.multiplier;
// Update personal score
game.personalScore += totalGain;
// Update global score
game.globalScore += totalGain;
// Update country score
if (game.playerCountry) {
game.countryScores[game.playerCountry] = (game.countryScores[game.playerCountry] || 0) + totalGain;
}
// Save all
localStorage.setItem('personalScore', game.personalScore);
localStorage.setItem('globalCookieScore', game.globalScore);
localStorage.setItem('countryScores', JSON.stringify(game.countryScores));
// Visual feedback
showFloatingText(totalGain, timing.text, timing.color);
createParticles(timing.multiplier);
// Apply timing glow to cookie
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);
}
// Cookie animation
elements.cookieBtn.style.transform = 'scale(0.95)';
setTimeout(() => {
elements.cookieBtn.style.transform = 'scale(1)';
}, 100);
// Special effects for 1M+
if (game.specialEffectUnlocked) {
createSpecialEffect();
}
updateMultiplier();
updateUI();
checkSkinsAvailability();
updateLeaderboard();
// Haptic feedback if available
if (navigator.vibrate) {
navigator.vibrate(timing.multiplier > 1 ? [20, 30, 20] : 10);
}
}
// Show floating text
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);
}
// Create particles
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);
}
}
// Special effect for 1M+
function createSpecialEffect() {
// Rainbow flash
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);
// Screen shake
document.body.classList.add('animate-shake');
setTimeout(() => document.body.classList.remove('animate-shake'), 500);
// Extra particles
createParticles(10);
// Shockwave ring
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);
}
// Update multiplier based on milestones
function updateMultiplier() {
let baseMult = 1;
let bonusText = 'x1';
// 1000 = +1 extra (total 2)
// 10000 = +1 extra (total 3)
// 1000000 = +3 extra (total 6) + special effect
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');
}
}
// Feed Destroyer
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();
// Visual feedback
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);
}
}
// Destroyer Loop
function startDestroyerLoop() {
setInterval(() => {
game.destroyerHunger -= 1;
if (game.destroyerHunger <= 0) {
game.destroyerHunger = 0;
triggerGlobalReset();
}
localStorage.setItem('destroyerHunger', game.destroyerHunger);
updateUI();
// Warning when low
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);
}
// Global Reset
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]);
}
// Leaderboard Management
function updateLeaderboard() {
// Simulate other countries having scores for atmosphere
const simulatedScores = { ...game.countryScores };
// Add simulated data for countries not played yet
countries.forEach(c => {
if (!simulatedScores[c.code]) {
// Random score between 0 and personal score * 0.8 for realism
simulatedScores[c.code] = Math.floor(Math.random() * game.personalScore * 0.8);
}
});
// Sort by score
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); // Top 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('');
}
// Skin Management
function applySkin(skinName) {
const skin = skins[skinName];
if (!skin) return;
// Remove all skin classes
Object.values(skins).forEach(s => {
elements.cookieVisual.classList.remove(s.class);
});
// Add new skin class
elements.cookieVisual.classList.add(skin.class);
game.currentSkin = skinName;
localStorage.setItem('currentSkin', skinName);
// Update UI selection
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();
// Celebration
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 {
// Check if affordable
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');
}
}
});
}
// Event Listeners
function setupEventListeners() {
// Cookie click
elements.cookieBtn.addEventListener('click', handleCookieClick);
elements.cookieBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
handleCookieClick(e);
}, { passive: false });
// Feed destroyer
elements.feedDestroyerBtn.addEventListener('click', feedDestroyer);
// Dismiss reset modal
elements.dismissReset.addEventListener('click', () => {
elements.resetModal.classList.add('hidden');
});
// Skin selection
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);
}
});
});
}
// UI Updates
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 + '%';
// Color code hunger bar
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';
}
// Update feed button state
if (game.personalScore < 10) {
elements.feedDestroyerBtn.classList.add('opacity-50', 'cursor-not-allowed');
} else {
elements.feedDestroyerBtn.classList.remove('opacity-50', 'cursor-not-allowed');
}
}
// Start game
init();
// Simulate other countries contributing (atmosphere)
setInterval(() => {
if (Math.random() > 0.6 && game.globalScore > 0) {
// Random country adds cookies
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);