/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
leaderboardNames: [],
leaderboardCookies: [],
leaderboardTimestamps: [],
leaderboardPrestiges: [],
playerName: "",
isOwner: false,
hasSetUsername: false,
usernameHistory: [],
lastUsernameChange: 0,
musicVolume: 0.8,
soundVolume: 0.7,
enableSoundEffects: true
});
/****
* Classes
****/
var Building = Container.expand(function (buildingType, cost, cps) {
var self = Container.call(this);
self.buildingType = buildingType;
self.cost = cost;
self.baseCost = cost;
self.cookiesPerSecond = cps;
self.count = 0;
var background = self.attachAsset('upgradeButton', {
anchorX: 0,
anchorY: 0
});
// Create detailed pixel art for each building type
if (buildingType === 'grandma') {
var grandmaBase = self.attachAsset('grandma', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var grandmaHair = self.attachAsset('grandmaHair', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 25
});
var grandmaFace = self.attachAsset('grandmaFace', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 35
});
var grandmaEyes1 = self.attachAsset('grandmaEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: 32
});
var grandmaEyes2 = self.attachAsset('grandmaEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 45,
y: 32
});
var grandmaNose = self.attachAsset('grandmaNose', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 37
});
var grandmaApron = self.attachAsset('grandmaApron', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 55
});
} else if (buildingType === 'oven') {
var ovenBase = self.attachAsset('oven', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenBody = self.attachAsset('ovenBody', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenDoor = self.attachAsset('ovenDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 45
});
var ovenWindow = self.attachAsset('ovenWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenHandle = self.attachAsset('ovenHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 45
});
var ovenKnob1 = self.attachAsset('ovenKnob', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 25
});
var ovenKnob2 = self.attachAsset('ovenKnob', {
anchorX: 0.5,
anchorY: 0.5,
x: 50,
y: 25
});
var ovenVents = self.attachAsset('ovenVents', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 20
});
} else if (buildingType === 'factory') {
var factoryBase = self.attachAsset('factory', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var factoryRoof = self.attachAsset('factoryRoof', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 15
});
var factoryChimney = self.attachAsset('factoryChimney', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 10
});
var factorySmoke1 = self.attachAsset('factorySmoke', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -10
});
var factorySmoke2 = self.attachAsset('factorySmoke', {
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: -15
});
var factoryWindow1 = self.attachAsset('factoryWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: 35
});
var factoryWindow2 = self.attachAsset('factoryWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 35
});
var factoryDoor = self.attachAsset('factoryDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 55
});
} else {
var icon = self.attachAsset(buildingType, {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
}
var nameText = new Text2(buildingType.toUpperCase(), {
size: 24,
fill: 0xFFFFFF
});
nameText.anchor.set(0, 0.5);
nameText.x = 90;
nameText.y = 25;
self.addChild(nameText);
self.costText = new Text2('Cost: ' + self.cost, {
size: 20,
fill: 0xFFFF00
});
self.costText.anchor.set(0, 0.5);
self.costText.x = 90;
self.costText.y = 45;
self.addChild(self.costText);
self.countText = new Text2('Owned: ' + self.count, {
size: 18,
fill: 0xCCCCCC
});
self.countText.anchor.set(0, 0.5);
self.countText.x = 90;
self.countText.y = 65;
self.addChild(self.countText);
self.updateDisplay = function () {
self.costText.setText('Cost: ' + formatNumber(self.cost));
self.countText.setText('Owned: ' + self.count);
if (cookies >= self.cost) {
background.tint = 0x4169E1;
} else {
background.tint = 0x666666;
}
};
self.purchase = function () {
if (cookies >= self.cost) {
cookies -= self.cost;
self.count++;
totalCPS += self.cookiesPerSecond;
// Increase cost by 15%
self.cost = Math.floor(self.cost * 1.15);
playSound('purchase');
self.updateDisplay();
updateDisplay();
saveGame();
}
};
self.down = function (x, y, obj) {
self.purchase();
};
return self;
});
var Cookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5
});
// Add detailed cookie decorations with pixel art style
var highlight = self.attachAsset('cookieHighlight', {
anchorX: 0.5,
anchorY: 0.5,
x: -40,
y: -60
});
highlight.alpha = 0.6;
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: -30
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 40
});
var chip3 = self.attachAsset('cookieChip3', {
anchorX: 0.5,
anchorY: 0.5,
x: -20,
y: 70
});
var chip4 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -50
});
var chip5 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: 20
});
self.originalScale = 1;
self.tap = function () {
// Check for auto-clicker
if (!recordClick() || clicksBlocked) {
return;
}
// Enhanced rotation animation without scaling
tween.stop(self, {
rotation: true
});
self.rotation += 0.1;
tween(self, {
rotation: 0
}, {
duration: 300,
easing: tween.elasticOut
});
// Color flash effect
tween.stop(cookieGraphics, {
tint: true
});
cookieGraphics.tint = 0xffff99;
tween(cookieGraphics, {
tint: 0xffffff
}, {
duration: 200
});
// Play sound effect
playSound('cookieTap');
// Track total clicks for achievements
totalClicks++;
// Add cookies with all bonuses
var cookiesGained = cookiesPerTap;
cookies += cookiesGained;
allTimeCookies += cookiesGained;
updateDisplay();
// Spawn mini cookie instead of floating number
var miniCookie = game.addChild(new MiniCookie());
miniCookie.x = self.x + (Math.random() - 0.5) * 100;
miniCookie.y = self.y + (Math.random() - 0.5) * 100;
};
self.down = function (x, y, obj) {
if (gameStarted && !upgradeMenu.isOpen && !settingsMenu.isOpen && !leaderboard.isOpen && !tutorialScreen.isOpen && (!prestigeMenu || !prestigeMenu.isOpen)) {
self.tap();
}
};
return self;
});
var FallingCookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -15,
y: -10
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: 15
});
self.fallSpeed = 3 + Math.random() * 4;
self.rotationSpeed = 0.05 + Math.random() * 0.1;
self.value = Math.floor(cookies * 0.01) + Math.floor(Math.random() * (cookies * 0.05)) + 1;
self.update = function () {
self.y += self.fallSpeed;
self.rotation += self.rotationSpeed;
if (self.y > 2800) {
self.destroy();
}
};
self.collect = function () {
cookies += self.value;
allTimeCookies += self.value;
playSound('fallingCookieClick', 0.8);
showFloatingNumber('+' + self.value, self.x, self.y);
updateDisplay();
self.destroy();
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var FloatingNumber = Container.expand(function (text, startX, startY) {
var self = Container.call(this);
var numberText = new Text2(text, {
size: 56,
fill: 0xFFD700
});
numberText.anchor.set(0.5, 0.5);
self.addChild(numberText);
self.x = startX;
self.y = startY;
self.alpha = 1;
// Animate upward and fade out
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var GoldenCookie = Container.expand(function () {
var self = Container.call(this);
self.bonusType = Math.random() < 0.5 ? 'multiply' : 'bonus';
self.multiplier = 2 + Math.random() * 5; // 2x to 7x multiplier
self.bonusAmount = Math.floor(cookies * 0.1 + Math.random() * cookies * 0.2);
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds at 60fps
var cookieGraphics = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
cookieGraphics.tint = 0xFFD700; // Golden tint
// Pulsing glow effect
var glow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
glow.tint = 0xFFFF88;
glow.alpha = 0.3;
self.update = function () {
self.lifetime++;
// Pulsing animation
var pulse = 1 + Math.sin(self.lifetime * 0.2) * 0.1;
self.scaleX = pulse;
self.scaleY = pulse;
glow.scaleX = 1.2 * pulse;
glow.scaleY = 1.2 * pulse;
// Fade out in last 2 seconds
if (self.lifetime > self.maxLifetime - 120) {
self.alpha = 1 - (self.lifetime - (self.maxLifetime - 120)) / 120;
}
// Remove when expired
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
self.collect = function () {
var bonusText = '';
if (self.bonusType === 'multiply') {
var oldCookies = cookies;
cookies *= self.multiplier;
allTimeCookies += cookies - oldCookies;
bonusText = 'GOLDEN BONUS! x' + Math.floor(self.multiplier);
} else {
cookies += self.bonusAmount;
allTimeCookies += self.bonusAmount;
bonusText = 'GOLDEN BONUS! +' + formatNumber(self.bonusAmount);
}
playSound('goldenCookie', 1.0);
showFloatingNumber(bonusText, self.x, self.y);
updateDisplay();
LK.effects.flashScreen(0xFFD700, 500);
self.destroy();
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var Leaderboard = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.scrollOffset = 0;
self.maxScroll = 0;
self.isDragging = false;
self.lastY = 0;
self.velocity = 0;
self.leaderboardData = [];
// Full screen background with gradient effect
var background = self.attachAsset('leaderboardBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x0a0a1e;
// Main panel with improved styling
var panel = self.attachAsset('leaderboardPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.1,
scaleY: 1.05
});
panel.tint = 0x1e1e2e;
// Header section with enhanced styling
var header = self.attachAsset('leaderboardHeader', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 350,
scaleX: 1.1,
scaleY: 0.8
});
header.tint = 0x2a2a3e;
// Animated title with glow effect
var titleText = new Text2('š COOKIE EMPIRE LEADERBOARD š', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 350;
self.addChild(titleText);
// Enhanced close button with better visibility
var closeBg = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
scaleX: 1.2,
scaleY: 1.2
});
closeBg.tint = 0x8B0000;
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
scaleX: 2.5,
scaleY: 2.5
});
closeBtn.tint = 0xFF4444;
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
rotation: Math.PI / 4,
scaleX: 2.5,
scaleY: 2.5
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
rotation: -Math.PI / 4,
scaleX: 2.5,
scaleY: 2.5
});
// Stats header
var statsText = new Text2('Showing Top 20 Players', {
size: 32,
fill: 0xCCCCCC
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 420;
self.addChild(statsText);
// Column headers with better positioning
var rankHeader = new Text2('RANK', {
size: 28,
fill: 0xFFFFFF
});
rankHeader.anchor.set(0.5, 0.5);
rankHeader.x = 250;
rankHeader.y = 480;
self.addChild(rankHeader);
var nameHeader = new Text2('PLAYER', {
size: 28,
fill: 0xFFFFFF
});
nameHeader.anchor.set(0, 0.5);
nameHeader.x = 400;
nameHeader.y = 480;
self.addChild(nameHeader);
var cookiesHeader = new Text2('COOKIES', {
size: 28,
fill: 0xFFFFFF
});
cookiesHeader.anchor.set(0, 0.5);
cookiesHeader.x = 900;
cookiesHeader.y = 480;
self.addChild(cookiesHeader);
var prestigeHeader = new Text2('PRESTIGE', {
size: 28,
fill: 0xFFFFFF
});
prestigeHeader.anchor.set(0, 0.5);
prestigeHeader.x = 1450;
prestigeHeader.y = 480;
self.addChild(prestigeHeader);
// Container for scrollable entries
self.entriesContainer = self.addChild(new Container());
self.entries = [];
// Scroll indicator
self.scrollIndicator = new Text2('Scroll to see more players', {
size: 24,
fill: 0x888888
});
self.scrollIndicator.anchor.set(0.5, 0.5);
self.scrollIndicator.x = 1024;
self.scrollIndicator.y = 2400;
self.addChild(self.scrollIndicator);
self.cleanLeaderboardData = function () {
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardCookies = storage.leaderboardCookies || [];
var leaderboardTimestamps = storage.leaderboardTimestamps || [];
var leaderboardPrestiges = storage.leaderboardPrestiges || [];
// Clean up any invalid entries
var cleanNames = [];
var cleanCookies = [];
var cleanTimestamps = [];
var cleanPrestiges = [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] && leaderboardNames[i].trim() !== '' && leaderboardCookies[i] >= 0 && !isNaN(leaderboardCookies[i])) {
cleanNames.push(leaderboardNames[i]);
cleanCookies.push(leaderboardCookies[i]);
cleanTimestamps.push(leaderboardTimestamps[i] || 0);
cleanPrestiges.push(leaderboardPrestiges[i] || 0);
}
}
// Update storage with cleaned data
storage.leaderboardNames = cleanNames;
storage.leaderboardCookies = cleanCookies;
storage.leaderboardTimestamps = cleanTimestamps;
storage.leaderboardPrestiges = cleanPrestiges;
return {
names: cleanNames,
cookies: cleanCookies,
timestamps: cleanTimestamps,
prestiges: cleanPrestiges
};
};
self.sortLeaderboard = function (data) {
var indices = [];
for (var i = 0; i < data.names.length; i++) {
indices.push(i);
}
// Enhanced sorting: cookies first, then prestige, then timestamp (most recent)
indices.sort(function (a, b) {
if (Math.abs(data.cookies[b] - data.cookies[a]) < 1) {
// Very close cookie counts
if (data.prestiges[b] === data.prestiges[a]) {
return data.timestamps[b] - data.timestamps[a]; // Most recent wins
}
return data.prestiges[b] - data.prestiges[a]; // Higher prestige wins
}
return data.cookies[b] - data.cookies[a];
});
return indices;
};
self.updateLeaderboard = function () {
// Clear existing entries
for (var i = 0; i < self.entries.length; i++) {
self.entries[i].destroy();
}
self.entries = [];
var cleanData = self.cleanLeaderboardData();
var sortedIndices = self.sortLeaderboard(cleanData);
// Show top 20 instead of 10
var maxEntries = Math.min(20, sortedIndices.length);
// Update stats display
statsText.setText('Showing Top ' + maxEntries + ' of ' + sortedIndices.length + ' Players');
for (var i = 0; i < maxEntries; i++) {
var idx = sortedIndices[i];
var yPos = 550 + i * 90;
// Enhanced entry styling with rank-based colors
var entryBg = self.entriesContainer.addChild(LK.getAsset('leaderboardEntry', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos,
scaleX: 1.05,
scaleY: 1.1
}));
// Special styling for top 3
if (i === 0) {
entryBg.tint = 0xFFD700; // Gold
} else if (i === 1) {
entryBg.tint = 0xC0C0C0; // Silver
} else if (i === 2) {
entryBg.tint = 0xCD7F32; // Bronze
} else if (cleanData.names[idx] === playerName) {
entryBg.tint = 0x4CAF50; // Player's entry in green
} else {
entryBg.tint = 0x3c3c4e; // Default
}
// Rank with medals for top 3
var rankText;
if (i === 0) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else if (i === 1) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else if (i === 2) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else {
rankText = new Text2(i + 1 + '.', {
size: 32,
fill: 0xFFFFFF
});
}
rankText.anchor.set(0.5, 0.5);
rankText.x = 250;
rankText.y = yPos;
self.entriesContainer.addChild(rankText);
var displayName = getDisplayName(cleanData.names[idx]);
var nameColor = cleanData.names[idx] === 'NEO' ? 0xFF6B35 : cleanData.names[idx] === playerName ? 0x4CAF50 : 0xFFD700;
var nameText = new Text2(displayName, {
size: 30,
fill: nameColor
});
nameText.anchor.set(0, 0.5);
nameText.x = 400;
nameText.y = yPos;
self.entriesContainer.addChild(nameText);
var cookieText = new Text2(formatNumber(Math.floor(cleanData.cookies[idx])), {
size: 28,
fill: 0x90EE90
});
cookieText.anchor.set(0, 0.5);
cookieText.x = 900;
cookieText.y = yPos;
self.entriesContainer.addChild(cookieText);
// Enhanced prestige display
var prestigeLevel = cleanData.prestiges[idx] || 0;
var prestigeDisplay = prestigeLevel > 0 ? 'Level ' + prestigeLevel : 'No Prestige';
var prestigeText = new Text2(prestigeDisplay, {
size: 26,
fill: prestigeLevel > 0 ? 0xFFB347 : 0x888888
});
prestigeText.anchor.set(0, 0.5);
prestigeText.x = 1450;
prestigeText.y = yPos;
self.entriesContainer.addChild(prestigeText);
// Activity indicator
var timeSinceUpdate = Date.now() - (cleanData.timestamps[idx] || 0);
var isActive = timeSinceUpdate < 300000; // Active within 5 minutes
if (isActive) {
var activeIndicator = new Text2('ā', {
size: 20,
fill: 0x00FF00
});
activeIndicator.anchor.set(0, 0.5);
activeIndicator.x = 350;
activeIndicator.y = yPos;
self.entriesContainer.addChild(activeIndicator);
}
self.entries.push(entryBg, rankText, nameText, cookieText, prestigeText);
if (isActive) {
self.entries.push(activeIndicator);
}
}
// Update scroll limits
self.maxScroll = Math.max(0, maxEntries * 90 - 1400);
self.scrollOffset = Math.max(0, Math.min(self.scrollOffset, self.maxScroll));
self.entriesContainer.y = -self.scrollOffset;
// Update scroll indicator
if (self.maxScroll > 0) {
self.scrollIndicator.setText('ā Swipe to scroll ⢠Showing ' + Math.min(16, maxEntries) + ' visible entries');
self.scrollIndicator.visible = true;
} else {
self.scrollIndicator.visible = false;
}
};
// Scrolling functionality
self.move = function (x, y, obj) {
if (self.isDragging && self.maxScroll > 0) {
var deltaY = y - self.lastY;
self.scrollOffset = Math.max(0, Math.min(self.scrollOffset - deltaY * 2, self.maxScroll));
self.entriesContainer.y = -self.scrollOffset;
self.lastY = y;
}
};
self.down = function (x, y, obj) {
if (y > 500 && y < 2300) {
// Only allow scrolling in the entries area
self.isDragging = true;
self.lastY = y;
}
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.open = function () {
self.isOpen = true;
self.scrollOffset = 0;
self.alpha = 0;
self.visible = true;
self.updateLeaderboard();
// Enhanced animation
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
// Animate title glow
tween(titleText, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Set up auto-refresh while leaderboard is open
self.refreshTimer = LK.setInterval(function () {
if (self.isOpen) {
self.updateLeaderboard();
}
}, 3000); // Refresh every 3 seconds while open
};
self.close = function () {
self.isOpen = false;
self.isDragging = false;
// Clear refresh timer when closing
if (self.refreshTimer) {
LK.clearInterval(self.refreshTimer);
self.refreshTimer = null;
}
// Stop title animation
tween.stop(titleText);
titleText.scaleX = 1;
titleText.scaleY = 1;
tween(self, {
alpha: 0,
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.visible = false;
self.scaleX = 1;
self.scaleY = 1;
}
});
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBg.down = handleClose;
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.visible = false;
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
// Modern gradient background with rich colors
var backgroundTop = self.attachAsset('mainMenuBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 1400
});
backgroundTop.tint = 0x2a1810; // Dark brown top
var backgroundBottom = self.attachAsset('mainMenuBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 1332,
y: 1400
});
backgroundBottom.tint = 0x4a2820; // Lighter brown bottom
// Animated background elements - floating cookies
self.floatingCookies = [];
for (var i = 0; i < 8; i++) {
var floatCookie = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
scaleX: 0.3 + Math.random() * 0.4,
scaleY: 0.3 + Math.random() * 0.4
});
floatCookie.alpha = 0.1 + Math.random() * 0.15;
floatCookie.rotationSpeed = (Math.random() - 0.5) * 0.02;
floatCookie.floatSpeed = 0.5 + Math.random() * 1.5;
self.floatingCookies.push(floatCookie);
}
// Central cookie showcase with enhanced visual effects
var cookieGlow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950,
scaleX: 3.2,
scaleY: 3.2
});
cookieGlow.tint = 0xFFFFAA;
cookieGlow.alpha = 0.15;
var centralCookie = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950,
scaleX: 2.8,
scaleY: 2.8
});
centralCookie.tint = 0xFFE4B5;
// Add cookie details with enhanced visibility
var cookieDetails = [{
asset: 'cookieHighlight',
x: -60,
y: -80,
scale: 1.8,
alpha: 0.4
}, {
asset: 'cookieChip1',
x: -70,
y: -40,
scale: 1.4,
alpha: 0.8
}, {
asset: 'cookieChip2',
x: 80,
y: 60,
scale: 1.2,
alpha: 0.8
}, {
asset: 'cookieChip3',
x: -30,
y: 90,
scale: 1.3,
alpha: 0.8
}, {
asset: 'cookieChip1',
x: 40,
y: -70,
scale: 1.2,
alpha: 0.8
}, {
asset: 'cookieChip2',
x: -90,
y: 30,
scale: 1.1,
alpha: 0.8
}];
for (var i = 0; i < cookieDetails.length; i++) {
var detail = cookieDetails[i];
var element = self.attachAsset(detail.asset, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + detail.x,
y: 950 + detail.y,
scaleX: detail.scale,
scaleY: detail.scale
});
element.alpha = detail.alpha;
}
// Modern title with enhanced styling and subtitle
var titleShadow = new Text2('COOKIE TAP EMPIRE', {
size: 88,
fill: 0x1a1a1a
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1026;
titleShadow.y = 352;
self.addChild(titleShadow);
var titleText = new Text2('COOKIE TAP EMPIRE', {
size: 88,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 350;
self.addChild(titleText);
var subtitleText = new Text2('THE ULTIMATE COOKIE CLICKING ADVENTURE', {
size: 32,
fill: 0xFFE4B5
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 420;
self.addChild(subtitleText);
// Simple white username box at middle top of screen
var usernameBg = self.attachAsset('usernameBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 200
});
usernameBg.tint = 0xffffff;
self.usernameDisplay = new Text2(getDisplayName(playerName) || 'Tap to set username', {
size: 28,
fill: playerName === 'NEO' ? 0xFF6B35 : 0x000000
});
self.usernameDisplay.anchor.set(0.5, 0.5);
self.usernameDisplay.x = 1024;
self.usernameDisplay.y = 200;
self.addChild(self.usernameDisplay);
// Add username status information display
self.usernameStatusDisplay = new Text2('', {
size: 16,
fill: 0x666666
});
self.usernameStatusDisplay.anchor.set(0.5, 0.5);
self.usernameStatusDisplay.x = 1024;
self.usernameStatusDisplay.y = 225;
self.addChild(self.usernameStatusDisplay);
// Enhanced visual feedback for username
self.usernameDisplay.originalTint = self.usernameDisplay.fill;
// Username editing functionality (keeping existing keyboard system)
self.editUsername = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (self.keyboardOverlay) return;
self.keyboardOverlay = self.addChild(LK.getAsset('leaderboardBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
}));
self.keyboardOverlay.alpha = 0.95;
self.keyboardOverlay.tint = 0x1a1a2e;
var inputPanel = self.keyboardOverlay.addChild(LK.getAsset('leaderboardPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.1,
scaleY: 1.0
}));
inputPanel.tint = 0x2a2a3a;
var titleText = new Text2('ENTER PLAYER NAME', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1000;
self.keyboardOverlay.addChild(titleText);
var instructionText = new Text2('Maximum 20 characters ⢠Leave blank for random name', {
size: 28,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1080;
self.keyboardOverlay.addChild(instructionText);
var inputBg = self.keyboardOverlay.addChild(LK.getAsset('leaderboardEntry', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1180,
scaleX: 1.2,
scaleY: 1.5
}));
inputBg.tint = 0x1a1a1a;
self.currentInput = playerName || '';
self.inputDisplay = new Text2(self.currentInput || 'Enter your name...', {
size: 44,
fill: self.currentInput ? 0xFFD700 : 0x888888
});
self.inputDisplay.anchor.set(0.5, 0.5);
self.inputDisplay.x = 1024;
self.inputDisplay.y = 1180;
self.keyboardOverlay.addChild(self.inputDisplay);
// Enhanced keyboard layout
var keyboardKeys = [['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'], ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], ['Z', 'X', 'C', 'V', 'B', 'N', 'M']];
var startY = 1320;
self.keyboardButtons = [];
for (var row = 0; row < keyboardKeys.length; row++) {
var rowKeys = keyboardKeys[row];
var rowWidth = rowKeys.length * 95;
var startX = 1024 - rowWidth / 2 + 47.5;
for (var col = 0; col < rowKeys.length; col++) {
var key = rowKeys[col];
var keyX = startX + col * 95;
var keyY = startY + row * 110;
var keyBorder = self.keyboardOverlay.addChild(LK.getAsset('leaderboardBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: keyX,
y: keyY,
scaleX: 0.22,
scaleY: 0.6
}));
keyBorder.tint = 0x4a4a5a;
var keyButton = self.keyboardOverlay.addChild(LK.getAsset('leaderboardButton', {
anchorX: 0.5,
anchorY: 0.5,
x: keyX,
y: keyY,
scaleX: 0.2,
scaleY: 0.5
}));
var keyText = new Text2(key, {
size: 36,
fill: 0xFFFFFF
});
keyText.anchor.set(0.5, 0.5);
keyText.x = keyX;
keyText.y = keyY;
self.keyboardOverlay.addChild(keyText);
keyButton.keyChar = key;
keyButton.down = function () {
if (self.currentInput.length < 20) {
self.currentInput += this.keyChar;
self.inputDisplay.setText(self.currentInput);
self.inputDisplay.fill = 0xFFD700;
}
};
self.keyboardButtons.push(keyButton);
}
}
// Enhanced control buttons
var spaceButton = self.keyboardOverlay.addChild(LK.getAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 350,
scaleX: 0.8,
scaleY: 0.6
}));
var spaceText = new Text2('SPACE', {
size: 28,
fill: 0xFFFFFF
});
spaceText.anchor.set(0.5, 0.5);
spaceText.x = 1024;
spaceText.y = startY + 350;
self.keyboardOverlay.addChild(spaceText);
spaceButton.down = function () {
if (self.currentInput.length < 20) {
self.currentInput += ' ';
self.inputDisplay.setText(self.currentInput);
self.inputDisplay.fill = 0xFFD700;
}
};
var backspaceButton = self.keyboardOverlay.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 - 250,
y: startY + 350,
scaleX: 0.4,
scaleY: 0.6
}));
var backspaceText = new Text2('ā« DELETE', {
size: 24,
fill: 0xFFFFFF
});
backspaceText.anchor.set(0.5, 0.5);
backspaceText.x = 1024 - 250;
backspaceText.y = startY + 350;
self.keyboardOverlay.addChild(backspaceText);
backspaceButton.down = function () {
if (self.currentInput.length > 0) {
self.currentInput = self.currentInput.slice(0, -1);
self.inputDisplay.setText(self.currentInput || 'Enter your name...');
self.inputDisplay.fill = self.currentInput ? 0xFFD700 : 0x888888;
}
};
var clearButton = self.keyboardOverlay.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + 250,
y: startY + 350,
scaleX: 0.4,
scaleY: 0.6
}));
var clearText = new Text2('CLEAR ALL', {
size: 24,
fill: 0xFFFFFF
});
clearText.anchor.set(0.5, 0.5);
clearText.x = 1024 + 250;
clearText.y = startY + 350;
self.keyboardOverlay.addChild(clearText);
clearButton.down = function () {
self.currentInput = '';
self.inputDisplay.setText('Enter your name...');
self.inputDisplay.fill = 0x888888;
};
// Confirm and cancel buttons
var confirmBorder = self.keyboardOverlay.addChild(LK.getAsset('playButtonBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 500,
scaleX: 1.2,
scaleY: 1.2
}));
var confirmButton = self.keyboardOverlay.addChild(LK.getAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 500,
scaleX: 1.0,
scaleY: 1.0
}));
var confirmText = new Text2('CONFIRM NAME', {
size: 32,
fill: 0xFFFFFF
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = 1024;
confirmText.y = startY + 500;
self.keyboardOverlay.addChild(confirmText);
confirmButton.down = function () {
self.confirmUsername();
};
var cancelButton = self.keyboardOverlay.addChild(LK.getAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
scaleX: 2.0,
scaleY: 2.0
}));
cancelButton.tint = 0x8B0000;
var cancelX1 = self.keyboardOverlay.addChild(LK.getAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
rotation: Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
}));
var cancelX2 = self.keyboardOverlay.addChild(LK.getAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
rotation: -Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
}));
cancelButton.down = function () {
self.closeKeyboard();
};
};
// Username confirmation and closing functions (keeping existing logic)
self.confirmUsername = function () {
var newUsername = self.currentInput.trim();
// Generate username if empty
if (!newUsername) {
newUsername = generateUniqueUsername();
}
// Enhanced validation
if (!isValidUsername(newUsername)) {
if (newUsername.length > 20) {
self.inputDisplay.setText('Too long! Maximum 20 characters');
} else if (newUsername.length === 0) {
self.inputDisplay.setText('Username cannot be empty');
} else {
self.inputDisplay.setText('Invalid characters in username');
}
self.inputDisplay.fill = 0xFF5555;
return;
}
// Check cooldown for existing users
if (playerName && playerName !== newUsername && !canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
var minutes = Math.floor(cooldownSeconds / 60);
var seconds = cooldownSeconds % 60;
self.inputDisplay.setText('Cooldown: ' + minutes + 'm ' + seconds + 's remaining');
self.inputDisplay.fill = 0xFF5555;
return;
}
// Check availability
if (isUsernameAvailable(newUsername) || newUsername === playerName) {
// Store previous username in history
if (playerName && playerName !== newUsername) {
var usernameHistory = storage.usernameHistory || [];
if (usernameHistory.indexOf(playerName) === -1) {
usernameHistory.push(playerName);
if (usernameHistory.length > 5) {
usernameHistory.shift(); // Keep only last 5 usernames
}
storage.usernameHistory = usernameHistory;
}
// Remove old username from leaderboard
var leaderboardNames = (storage.leaderboardNames || []).slice();
var leaderboardCookies = (storage.leaderboardCookies || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardNames.splice(i, 1);
leaderboardCookies.splice(i, 1);
leaderboardTimestamps.splice(i, 1);
leaderboardPrestiges.splice(i, 1);
break;
}
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardCookies = leaderboardCookies;
storage.leaderboardTimestamps = leaderboardTimestamps;
storage.leaderboardPrestiges = leaderboardPrestiges;
// Update cooldown timestamp
storage.lastUsernameChange = Date.now();
}
// Set new username with enhanced storage
playerName = newUsername;
storage.playerName = String(playerName);
storage.hasSetUsername = true;
// Update leaderboard and UI
updateLeaderboard();
self.updateUsername();
self.closeKeyboard();
playSound('buttonClick');
// Show success message
showFloatingNumber('Username set!', 1024, 500);
} else {
self.inputDisplay.setText('Username already taken!');
self.inputDisplay.fill = 0xFF5555;
}
};
self.closeKeyboard = function () {
if (self.keyboardOverlay) {
self.keyboardOverlay.destroy();
self.keyboardOverlay = null;
self.keyboardButtons = [];
self.inputDisplay = null;
self.currentInput = '';
}
};
// Make username clickable
usernameBg.down = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
tween.stop(usernameBg, {
tint: true
});
usernameBg.tint = 0xf0f0f0;
tween(usernameBg, {
tint: 0xffffff
}, {
duration: 200
});
self.editUsername();
};
self.usernameDisplay.down = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
tween.stop(usernameBg, {
tint: true
});
usernameBg.tint = 0xf0f0f0;
tween(usernameBg, {
tint: 0xffffff
}, {
duration: 200
});
self.editUsername();
};
// Modern menu buttons with enhanced layout
var buttonSpacing = 140;
var buttonsStartY = 1400;
var buttons = [];
// Play button (primary action)
var playBorder = self.attachAsset('playButtonBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY,
scaleX: 1.3,
scaleY: 1.3
});
playBorder.tint = 0x4CAF50;
var playButton = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY,
scaleX: 1.2,
scaleY: 1.2
});
playButton.tint = 0x2E7D32;
var playHighlight = self.attachAsset('playButtonHighlight', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY - 15,
scaleX: 1.1,
scaleY: 0.3
});
var playText = new Text2('šŖ START GAME', {
size: 40,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = buttonsStartY;
self.addChild(playText);
buttons.push({
border: playBorder,
button: playButton,
text: playText,
action: 'play'
});
// Secondary buttons in grid layout
var secondaryButtons = [{
name: 'LEADERBOARD',
icon: 'š',
border: 'leaderboardBorder',
button: 'leaderboardButton',
action: 'leaderboard',
pos: 0
}, {
name: 'SETTINGS',
icon: 'āļø',
border: 'settingsBorder',
button: 'settingsButton',
action: 'settings',
pos: 1
}, {
name: 'TUTORIAL',
icon: 'š',
border: 'tutorialBorder',
button: 'tutorialButton',
action: 'tutorial',
pos: 2
}];
var cols = 3;
var buttonWidth = 500;
var totalWidth = cols * buttonWidth;
var startX = 1024 - totalWidth / 2 + buttonWidth / 2;
for (var i = 0; i < secondaryButtons.length; i++) {
var btn = secondaryButtons[i];
var col = btn.pos % cols;
var buttonX = startX + col * buttonWidth;
var buttonY = buttonsStartY + 200;
var btnBorder = self.attachAsset(btn.border, {
anchorX: 0.5,
anchorY: 0.5,
x: buttonX,
y: buttonY,
scaleX: 1.1,
scaleY: 1.1
});
var btnButton = self.attachAsset(btn.button, {
anchorX: 0.5,
anchorY: 0.5,
x: buttonX,
y: buttonY
});
var btnText = new Text2(btn.icon + ' ' + btn.name, {
size: 28,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
btnText.x = buttonX;
btnText.y = buttonY;
self.addChild(btnText);
buttons.push({
border: btnBorder,
button: btnButton,
text: btnText,
action: btn.action
});
}
// Version and stats info
var versionText = new Text2('Cookie Tap Empire v2.1 ⢠Premium Cookie Experience', {
size: 24,
fill: 0x888888
});
versionText.anchor.set(0.5, 0.5);
versionText.x = 1024;
versionText.y = 2600;
self.addChild(versionText);
// Enhanced button handlers
function handlePlayClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
// Enhanced username generation for new players
if (!playerName || playerName.trim() === '' || !storage.hasSetUsername) {
playerName = generateUniqueUsername();
storage.playerName = String(playerName);
storage.hasSetUsername = false; // Mark as auto-generated
// Show helpful message for new players
if (!storage.hasSetUsername) {
showFloatingNumber('Auto-generated username: ' + playerName, 1024, 600);
showFloatingNumber('Change it anytime in the main menu!', 1024, 650);
}
}
gameStarted = true;
cookieCounterBg.visible = true;
cookieDisplay.visible = true;
cpsCounterBg.visible = true;
cpsDisplay.visible = true;
prestigeDisplay.visible = true;
self.close();
}
function handleLeaderboardClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
leaderboard.open();
}
function handleSettingsClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
settingsMenu.open();
}
function handleTutorialClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
showTutorial();
}
// Assign handlers to all button elements
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
var handler = null;
switch (btn.action) {
case 'play':
handler = handlePlayClick;
break;
case 'leaderboard':
handler = handleLeaderboardClick;
break;
case 'settings':
handler = handleSettingsClick;
break;
case 'tutorial':
handler = handleTutorialClick;
break;
}
if (handler) {
btn.border.down = handler;
btn.button.down = handler;
btn.text.down = handler;
}
}
// Enhanced username display update function with improved status indicators
self.updateUsername = function () {
var hasSetName = storage.hasSetUsername && playerName && playerName.trim() !== '';
var displayName;
var statusIndicator = '';
if (hasSetName) {
displayName = getDisplayName(playerName);
// Add detailed status indicators
if (!canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
if (cooldownSeconds > 0) {
var minutes = Math.floor(cooldownSeconds / 60);
var seconds = cooldownSeconds % 60;
statusIndicator = ' ā±ļø ' + minutes + 'm ' + seconds + 's';
}
} else {
// Show that username can be changed
statusIndicator = ' āļø';
}
} else {
displayName = 'Tap to set username';
statusIndicator = ' š';
}
self.usernameDisplay.setText(displayName + statusIndicator);
// Enhanced color coding with better visual hierarchy - adjusted for white background
if (!hasSetName) {
self.usernameDisplay.fill = 0x666666; // Dark gray for better visibility on white
} else if (playerName === 'NEO') {
self.usernameDisplay.fill = 0xFF6B35; // Special owner color
} else if (playerName && playerName.toLowerCase().indexOf('cookie') !== -1) {
self.usernameDisplay.fill = 0xCC8800; // Darker orange for cookie-themed names
} else if (storage.isOwner) {
self.usernameDisplay.fill = 0xFF6B35; // Special color for owners
} else {
self.usernameDisplay.fill = 0x000000; // Black text for regular users on white background
}
self.usernameDisplay.originalTint = self.usernameDisplay.fill;
// Enhanced visual effects based on username status
if (!hasSetName) {
// Pulsing effect for unset usernames
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
tween(self.usernameDisplay, {
alpha: 0.7,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (!canChangeUsername()) {
// Subtle animation for cooldown period
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
self.usernameDisplay.alpha = 1;
self.usernameDisplay.scaleX = 1;
self.usernameDisplay.scaleY = 1;
// Fade status indicator
tween(self.usernameDisplay, {
alpha: 0.8
}, {
duration: 800,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else {
// Normal state - no animation, full visibility
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
self.usernameDisplay.alpha = 1;
self.usernameDisplay.scaleX = 1;
self.usernameDisplay.scaleY = 1;
}
// Update status information display
var statusText = '';
if (hasSetName) {
var totalChanges = (storage.usernameHistory || []).length;
if (totalChanges > 0) {
statusText = 'Changed ' + totalChanges + ' time' + (totalChanges === 1 ? '' : 's');
} else {
statusText = playerName === storage.playerName && storage.hasSetUsername ? 'Custom username' : 'Auto-generated username';
}
if (!canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
if (cooldownSeconds > 0) {
statusText += ' ⢠Next change available in ' + Math.ceil(cooldownSeconds / 60) + ' min';
} else {
statusText += ' ⢠Can change now';
}
} else {
statusText += ' ⢠Can change anytime';
}
} else {
statusText = 'Click above to create your unique username ⢠Free to change';
}
self.usernameStatusDisplay.setText(statusText);
// Update status text color based on state - adjusted for white background
if (!hasSetName) {
self.usernameStatusDisplay.fill = 0x666666; // Encourage action
} else if (!canChangeUsername()) {
self.usernameStatusDisplay.fill = 0xFF0000; // Cooldown warning - red text
} else {
self.usernameStatusDisplay.fill = 0x666666; // Normal status
}
};
// Animation system for floating elements
self.update = function () {
// Animate floating cookies
for (var i = 0; i < self.floatingCookies.length; i++) {
var cookie = self.floatingCookies[i];
cookie.rotation += cookie.rotationSpeed;
cookie.y -= cookie.floatSpeed;
if (cookie.y < -100) {
cookie.y = 2832;
cookie.x = Math.random() * 2048;
}
}
// Gentle pulsing animation for central cookie
var pulseScale = 1 + Math.sin(LK.ticks * 0.02) * 0.05;
centralCookie.scaleX = 2.8 * pulseScale;
centralCookie.scaleY = 2.8 * pulseScale;
cookieGlow.scaleX = 3.2 * pulseScale;
cookieGlow.scaleY = 3.2 * pulseScale;
// Title shimmer effect
var shimmer = 0.8 + Math.sin(LK.ticks * 0.03) * 0.2;
titleText.alpha = shimmer;
};
// Close animation
self.close = function () {
tween(self, {
alpha: 0,
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.visible = false;
self.scaleX = 1;
self.scaleY = 1;
}
});
};
return self;
});
var MiniCookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -8,
y: -5
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 10,
y: 8
});
// Random movement direction
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = -2 - Math.random() * 4;
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.gravity = 0.15;
self.lifetime = 0;
self.maxLifetime = 120; // 2 seconds at 60fps
self.update = function () {
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Update rotation
self.rotation += self.rotationSpeed;
// Fade out over time
self.lifetime++;
if (self.lifetime > self.maxLifetime * 0.7) {
self.alpha = 1 - (self.lifetime - self.maxLifetime * 0.7) / (self.maxLifetime * 0.3);
}
// Remove when lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
// Powerup types with different effects
var powerupTypes = [{
name: 'Speed Boost',
color: 0x00FF00,
multiplier: 2,
duration: 15000
}, {
name: 'Golden Rush',
color: 0xFFD700,
multiplier: 3,
duration: 10000
}, {
name: 'Cookie Frenzy',
color: 0xFF6347,
multiplier: 5,
duration: 8000
}, {
name: 'Mega Power',
color: 0xFF00FF,
multiplier: 10,
duration: 5000
}];
// Select random powerup type
self.powerupData = powerupTypes[Math.floor(Math.random() * powerupTypes.length)];
self.lifetime = 0;
self.maxLifetime = 900; // 15 seconds at 60fps
// Create powerup visual with pulsing effect
var background = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
background.tint = self.powerupData.color;
// Add glow effect
var glow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
glow.tint = self.powerupData.color;
glow.alpha = 0.3;
// Powerup text
var powerupText = new Text2(self.powerupData.name, {
size: 28,
fill: 0xFFFFFF
});
powerupText.anchor.set(0.5, 0.5);
powerupText.y = 80;
self.addChild(powerupText);
// Duration text
var durationText = new Text2('+' + self.powerupData.multiplier + 'x CPS', {
size: 24,
fill: 0xFFFFFF
});
durationText.anchor.set(0.5, 0.5);
durationText.y = 110;
self.addChild(durationText);
// Start pulsing animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Glow pulsing
tween(glow, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.6
}, {
duration: 800,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
self.update = function () {
self.lifetime++;
// Fade out in last 3 seconds
if (self.lifetime > self.maxLifetime - 180) {
var fadeProgress = (self.lifetime - (self.maxLifetime - 180)) / 180;
self.alpha = 1 - fadeProgress;
}
// Remove when expired
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
self.collect = function () {
// Apply powerup effect
activePowerups.push({
name: self.powerupData.name,
multiplier: self.powerupData.multiplier,
duration: self.powerupData.duration,
timeLeft: self.powerupData.duration
});
// Visual feedback
showFloatingNumber(self.powerupData.name + ' ACTIVATED!', self.x, self.y - 50);
showFloatingNumber('+' + self.powerupData.multiplier + 'x CPS for ' + Math.floor(self.powerupData.duration / 1000) + 's', self.x, self.y - 100);
// Screen flash effect
LK.effects.flashScreen(self.powerupData.color, 500);
// Play sound
playSound('goldenCookie', 1.2);
// Animate collection
tween.stop(self);
tween(self, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var PrestigeButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('prestigeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
var titleText = new Text2('ASCEND', {
size: 64,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
self.addChild(titleText);
self.updateDisplay = function () {
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
var requiredUpgrades = 100 + prestigeLevel * 50;
var hasEnoughUpgrades = totalUpgrades >= requiredUpgrades;
var requiredCookies = 1000000 + prestigeLevel * 5000000; // 1M base, +5M per prestige
canPrestige = allTimeCookies >= requiredCookies && hasEnoughUpgrades;
if (canPrestige) {
background.tint = 0xFF4500;
background.alpha = 1;
titleText.setText('PRESTIGE');
} else {
background.tint = 0x666666;
background.alpha = 0.5;
titleText.setText('PRESTIGE');
}
};
self.showPrestigeMenu = function () {
if (!prestigeMenu) {
prestigeMenu = game.addChild(new PrestigeMenu());
prestigeMenu.x = 1024;
prestigeMenu.y = 1366;
}
prestigeMenu.open();
};
self.down = function (x, y, obj) {
self.showPrestigeMenu();
};
return self;
});
var PrestigeMenu = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
// Menu border and background
var border = self.attachAsset('prestigeBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
var background = self.attachAsset('prestigePanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
var titleText = new Text2('ASCENSION', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -150;
self.addChild(titleText);
self.reqText = new Text2('', {
size: 42,
fill: 0xFFFFFF
});
self.reqText.anchor.set(0.5, 0.5);
self.reqText.y = -80;
self.addChild(self.reqText);
// Prestige action button
var actionBtn = self.attachAsset('prestigeButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 120,
scaleX: 1.4,
scaleY: 1.4
});
self.actionText = new Text2('ASCEND', {
size: 36,
fill: 0xFFFFFF
});
self.actionText.anchor.set(0.5, 0.5);
self.actionText.y = 120;
self.addChild(self.actionText);
// Close button
var closeBtn = self.attachAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 320,
y: -180
});
var closeText = new Text2('X', {
size: 28,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 320;
closeText.y = -180;
self.addChild(closeText);
self.updateDisplay = function () {
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
var requiredUpgrades = 100 + prestigeLevel * 50;
var hasEnoughUpgrades = totalUpgrades >= requiredUpgrades;
var requiredCookies = 1000000 + prestigeLevel * 5000000;
var hasEnoughCookies = allTimeCookies >= requiredCookies;
var nextPrestigeLevel = prestigeLevel + 1;
self.reqText.setText('Level ' + nextPrestigeLevel + ' Requirements:\n\n' + requiredUpgrades + ' upgrades (' + totalUpgrades + '/' + requiredUpgrades + ')\n\n' + formatNumber(requiredCookies) + ' cookies (' + formatNumber(Math.floor(allTimeCookies)) + '/' + formatNumber(requiredCookies) + ')');
canPrestige = hasEnoughUpgrades && hasEnoughCookies;
if (canPrestige) {
actionBtn.tint = 0xFF4500;
actionBtn.alpha = 1;
self.actionText.setText('ASCEND');
} else {
actionBtn.tint = 0x666666;
actionBtn.alpha = 0.5;
self.actionText.setText('REQUIREMENTS NOT MET');
}
};
self.prestige = function () {
if (!canPrestige) return;
// Reset game state
cookies = 0;
totalCPS = 0;
for (var i = 0; i < buildings.length; i++) {
buildings[i].count = 0;
buildings[i].cost = buildings[i].baseCost;
}
// Increase prestige
prestigeLevel++;
prestigeBonus = prestigeLevel * 0.1;
allTimeCookies = 0;
canPrestige = false;
// Apply prestige bonus to tap multiplier
tapMultiplier = 1 + prestigeBonus;
playSound('prestige', 1.2);
updateDisplay();
saveGame();
// Flash effect and close menu
LK.effects.flashScreen(0xFFD700, 1000);
self.close();
};
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
self.updateDisplay();
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
actionBtn.down = function () {
self.prestige();
};
self.actionText.down = function () {
self.prestige();
};
closeBtn.down = function () {
self.close();
};
closeText.down = function () {
self.close();
};
self.visible = false;
return self;
});
var RainCookie = Container.expand(function () {
var self = Container.call(this);
// Create small cookie for rain effect
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + Math.random() * 0.2,
// Random size between 0.3-0.5
scaleY: 0.3 + Math.random() * 0.2
});
// Add small chocolate chips for detail
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -5 + Math.random() * 10,
y: -5 + Math.random() * 10,
scaleX: 0.8,
scaleY: 0.8
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: -5 + Math.random() * 10,
y: -5 + Math.random() * 10,
scaleX: 0.6,
scaleY: 0.6
});
// Set random properties for varied falling effect
self.fallSpeed = 2 + Math.random() * 3; // Random fall speed 2-5
self.rotationSpeed = (Math.random() - 0.5) * 0.08; // Random rotation
self.sway = Math.random() * 2; // Random horizontal sway
self.swaySpeed = 0.02 + Math.random() * 0.02;
self.swayOffset = Math.random() * Math.PI * 2;
// Make them semi-transparent for background effect
self.alpha = 0.4 + Math.random() * 0.3; // Random transparency 0.4-0.7
// Tint with slight variations for visual interest
var tints = [0xFFE4B5, 0xDEB887, 0xF4A460, 0xD2B48C, 0xBC9A6A];
cookieGraphics.tint = tints[Math.floor(Math.random() * tints.length)];
self.startX = self.x; // Remember starting X position for sway calculation
self.update = function () {
// Fall downward
self.y += self.fallSpeed;
// Add horizontal swaying motion using smooth sine wave
var swayAmount = Math.sin(LK.ticks * self.swaySpeed + self.swayOffset) * self.sway;
self.x = self.startX + swayAmount;
// Rotate as it falls (already animated by tween for smoothness)
self.rotation += self.rotationSpeed;
// Add subtle scale pulsing for more life
var pulseScale = 1 + Math.sin(LK.ticks * 0.05 + self.swayOffset) * 0.1;
var baseScale = 0.3 + Math.random() * 0.2; // Use original scale calculation
cookieGraphics.scaleX = baseScale * pulseScale;
cookieGraphics.scaleY = baseScale * pulseScale;
// Remove when off screen (with some buffer)
if (self.y > 2800) {
// Add exit animation with tween
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
var background = self.attachAsset('settingsPanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.1
});
var border = self.attachAsset('settingsBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.1
});
var titleText = new Text2('SETTINGS', {
size: 64,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
self.addChild(titleText);
// Master volume section
var masterVolumeLabel = new Text2('š MASTER VOLUME', {
size: 36,
fill: 0xFFFFFF
});
masterVolumeLabel.anchor.set(0.5, 0.5);
masterVolumeLabel.y = -150;
self.addChild(masterVolumeLabel);
// Master mute button
var muteButton = self.attachAsset('muteButton', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
scaleX: 1.2,
scaleY: 1.2
});
self.muteText = new Text2('SOUND: ON', {
size: 36,
fill: 0xFFFFFF
});
self.muteText.anchor.set(0.5, 0.5);
self.muteText.y = -100;
self.addChild(self.muteText);
// Music volume section
var musicSection = new Text2('šµ MUSIC VOLUME', {
size: 32,
fill: 0xFFD700
});
musicSection.anchor.set(0.5, 0.5);
musicSection.y = -30;
self.addChild(musicSection);
var volumeSlider = self.attachAsset('volumeSlider', {
anchorX: 0.5,
anchorY: 0.5,
y: 10,
scaleX: 1.2,
scaleY: 1.5
});
// Initialize with proper volume calculation
var initialVolume = storage.musicVolume !== undefined ? storage.musicVolume : 0.8;
var handleX = initialVolume * 380 - 190; // Adjusted for larger slider
self.volumeHandle = self.attachAsset('volumeHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: handleX,
y: 10,
scaleX: 1.3,
scaleY: 1.3
});
// Sound effects section
var soundSection = new Text2('š SOUND EFFECTS VOLUME', {
size: 32,
fill: 0xFFD700
});
soundSection.anchor.set(0.5, 0.5);
soundSection.y = 70;
self.addChild(soundSection);
var soundVolumeSlider = self.attachAsset('volumeSlider', {
anchorX: 0.5,
anchorY: 0.5,
y: 110,
scaleX: 1.2,
scaleY: 1.5
});
var initialSoundVolume = storage.soundVolume !== undefined ? storage.soundVolume : 0.7;
var soundHandleX = initialSoundVolume * 380 - 190; // Adjusted for larger slider
self.soundVolumeHandle = self.attachAsset('volumeHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: soundHandleX,
y: 110,
scaleX: 1.3,
scaleY: 1.3
});
// Sound effects toggle
var soundEffectsButton = self.attachAsset('muteButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 180,
scaleX: 1.1,
scaleY: 1.1
});
self.soundEffectsText = new Text2('SOUND EFFECTS: ON', {
size: 32,
fill: 0xFFFFFF
});
self.soundEffectsText.anchor.set(0.5, 0.5);
self.soundEffectsText.y = 180;
self.addChild(self.soundEffectsText);
// Close button enhanced
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
scaleX: 2.0,
scaleY: 2.0
});
closeBtn.tint = 0xFF4444;
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
rotation: Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
rotation: -Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
});
self.updateMuteDisplay = function () {
if (isMuted) {
self.muteText.setText('SOUND: OFF');
muteButton.tint = 0xFF5722;
LK.stopMusic();
} else {
self.muteText.setText('SOUND: ON');
muteButton.tint = 0x4CAF50;
var currentVolume = storage.musicVolume || 0.8;
LK.playMusic('bgmusic', {
loop: true,
volume: currentVolume
});
}
};
muteButton.down = function () {
isMuted = !isMuted;
storage.isMuted = isMuted;
self.updateMuteDisplay();
if (!isMuted) LK.getSound('buttonClick').play();
};
self.muteText.down = function () {
isMuted = !isMuted;
storage.isMuted = isMuted;
self.updateMuteDisplay();
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
// Sound effects toggle functionality
self.updateSoundEffectsDisplay = function () {
if (storage.enableSoundEffects) {
self.soundEffectsText.setText('SOUND EFFECTS: ON');
soundEffectsButton.tint = 0x4CAF50;
} else {
self.soundEffectsText.setText('SOUND EFFECTS: OFF');
soundEffectsButton.tint = 0xFF5722;
}
};
soundEffectsButton.down = function () {
storage.enableSoundEffects = !storage.enableSoundEffects;
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
self.soundEffectsText.down = function () {
storage.enableSoundEffects = !storage.enableSoundEffects;
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
// Sound volume handle functionality
self.soundVolumeHandle.down = function () {
self.draggingSoundVolume = true;
};
// Volume slider functionality
self.volumeHandle.down = function () {
self.draggingVolume = true;
};
self.move = function (x, y, obj) {
if (self.draggingVolume) {
var localX = Math.max(-190, Math.min(190, x));
self.volumeHandle.x = localX;
var volume = (localX + 190) / 380;
storage.musicVolume = volume;
// Actually update the music volume in real-time
if (!isMuted) {
LK.stopMusic();
LK.playMusic('bgmusic', {
loop: true,
volume: volume
});
}
}
if (self.draggingSoundVolume) {
var localX = Math.max(-190, Math.min(190, x));
self.soundVolumeHandle.x = localX;
var soundVolume = (localX + 190) / 380;
storage.soundVolume = soundVolume;
}
};
self.up = function (x, y, obj) {
self.draggingVolume = false;
self.draggingSoundVolume = false;
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
self.updateMuteDisplay();
self.updateSoundEffectsDisplay();
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
self.visible = false;
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.currentPage = 0;
self.itemsPerPage = 6;
// Full screen background
var background = self.attachAsset('shopFullscreen', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
// Header
var header = self.attachAsset('shopHeader', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 150
});
var headerText = new Text2('SHOP', {
size: 64,
fill: 0xFFD700
});
headerText.anchor.set(0.5, 0.5);
headerText.x = 1024;
headerText.y = 75;
self.addChild(headerText);
// Close button
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
scaleX: 1.5,
scaleY: 1.5
});
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
rotation: Math.PI / 4,
scaleX: 1.5,
scaleY: 1.5
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
rotation: -Math.PI / 4,
scaleX: 1.5,
scaleY: 1.5
});
// Page navigation
self.prevButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2500,
scaleX: 1.5,
scaleY: 0.8
});
self.nextButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 2500,
scaleX: 1.5,
scaleY: 0.8
});
self.prevText = new Text2('ā PREV', {
size: 36,
fill: 0xFFFFFF
});
self.prevText.anchor.set(0.5, 0.5);
self.prevText.x = 200;
self.prevText.y = 2500;
self.addChild(self.prevText);
self.nextText = new Text2('NEXT ā', {
size: 36,
fill: 0xFFFFFF
});
self.nextText.anchor.set(0.5, 0.5);
self.nextText.x = 1848;
self.nextText.y = 2500;
self.addChild(self.nextText);
// Page indicator
self.pageText = new Text2('Page 1 of 1', {
size: 32,
fill: 0xCCCCCC
});
self.pageText.anchor.set(0.5, 0.5);
self.pageText.x = 1024;
self.pageText.y = 2500;
self.addChild(self.pageText);
// Item slots
self.itemSlots = [];
self.createItemSlots = function () {
// Clear existing slots
for (var i = 0; i < self.itemSlots.length; i++) {
self.itemSlots[i].destroy();
}
self.itemSlots = [];
var cols = 2;
var rows = 3;
var slotWidth = 900;
var slotHeight = 320;
var startX = 1024 - cols * slotWidth / 2 + slotWidth / 2;
var startY = 300;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
var slotIndex = row * cols + col;
var x = startX + col * slotWidth;
var y = startY + row * slotHeight;
var slot = self.addChild(new ShopItem(x, y, slotIndex));
self.itemSlots.push(slot);
}
}
};
self.updatePage = function () {
var totalPages = Math.ceil(buildings.length / self.itemsPerPage);
// Update page indicator
self.pageText.setText('Page ' + (self.currentPage + 1) + ' of ' + totalPages);
// Update navigation buttons
self.prevButton.alpha = self.currentPage > 0 ? 1 : 0.3;
self.nextButton.alpha = self.currentPage < totalPages - 1 ? 1 : 0.3;
self.prevText.alpha = self.currentPage > 0 ? 1 : 0.3;
self.nextText.alpha = self.currentPage < totalPages - 1 ? 1 : 0.3;
// Update item slots
for (var i = 0; i < self.itemSlots.length; i++) {
var slot = self.itemSlots[i];
var buildingIndex = self.currentPage * self.itemsPerPage + i;
if (buildingIndex < buildings.length) {
slot.setBuilding(buildings[buildingIndex]);
slot.visible = true;
} else {
slot.visible = false;
}
}
};
self.prevPage = function () {
if (self.currentPage > 0) {
self.currentPage--;
self.updatePage();
if (!isMuted) LK.getSound('buttonClick').play();
}
};
self.nextPage = function () {
var totalPages = Math.ceil(buildings.length / self.itemsPerPage);
if (self.currentPage < totalPages - 1) {
self.currentPage++;
self.updatePage();
if (!isMuted) LK.getSound('buttonClick').play();
}
};
self.open = function () {
self.isOpen = true;
self.currentPage = 0;
self.alpha = 0;
self.visible = true;
// Hide prestige button when shop opens
prestigeButton.visible = false;
self.createItemSlots();
self.updatePage();
tween(self, {
alpha: 1
}, {
duration: 300
});
if (!isMuted) LK.getSound('menuOpen').play();
};
self.close = function () {
self.isOpen = false;
// Show prestige button when shop closes
prestigeButton.visible = true;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
if (!isMuted) LK.getSound('buttonClick').play();
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.prevButton.down = self.prevPage;
self.prevText.down = self.prevPage;
self.nextButton.down = self.nextPage;
self.nextText.down = self.nextPage;
self.visible = false;
return self;
});
var ShopItem = Container.expand(function (x, y, slotIndex) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.building = null;
// Item background
var background = self.attachAsset('upgradeSlot', {
anchorX: 0.5,
anchorY: 0.5,
width: 850,
height: 280
});
// Icon area
var iconBg = self.attachAsset('upgradeIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: 0,
scaleX: 2,
scaleY: 2
});
// Text elements
self.nameText = new Text2('', {
size: 56,
fill: 0xFFFFFF
});
self.nameText.anchor.set(0, 0.5);
self.nameText.x = -100;
self.nameText.y = -70;
self.addChild(self.nameText);
self.costText = new Text2('', {
size: 44,
fill: 0xFFFF00
});
self.costText.anchor.set(0, 0.5);
self.costText.x = -100;
self.costText.y = -20;
self.addChild(self.costText);
self.ownedText = new Text2('', {
size: 40,
fill: 0xCCCCCC
});
self.ownedText.anchor.set(0, 0.5);
self.ownedText.x = -100;
self.ownedText.y = 30;
self.addChild(self.ownedText);
self.cpsText = new Text2('', {
size: 42,
fill: 0x90EE90
});
self.cpsText.anchor.set(0, 0.5);
self.cpsText.x = -100;
self.cpsText.y = 80;
self.addChild(self.cpsText);
// Buy button
self.buyButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 60,
scaleX: 1.5,
scaleY: 0.8
});
self.buyText = new Text2('BUY', {
size: 36,
fill: 0xFFFFFF
});
self.buyText.anchor.set(0.5, 0.5);
self.buyText.x = 300;
self.buyText.y = 60;
self.addChild(self.buyText);
self.setBuilding = function (building) {
self.building = building;
self.updateDisplay();
};
self.updateDisplay = function () {
if (!self.building) return;
self.nameText.setText(self.building.buildingType.toUpperCase());
self.costText.setText('Cost: ' + formatNumber(self.building.cost));
self.ownedText.setText('Owned: ' + self.building.count);
self.cpsText.setText('+' + formatNumber(self.building.cookiesPerSecond) + ' CPS');
// Update affordability
var canAfford = cookies >= self.building.cost;
background.tint = canAfford ? 0x4169E1 : 0x666666;
iconBg.tint = canAfford ? 0xFFFFFF : 0x888888;
self.buyButton.tint = canAfford ? 0x4CAF50 : 0x666666;
self.buyButton.alpha = canAfford ? 1 : 0.5;
};
self.purchase = function () {
if (self.building && cookies >= self.building.cost) {
self.building.purchase();
self.updateDisplay();
}
};
self.down = function () {
self.purchase();
};
self.buyButton.down = function () {
self.purchase();
};
self.buyText.down = function () {
self.purchase();
};
return self;
});
var TutorialScreen = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
// Fullscreen background
var background = self.attachAsset('tutorialBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x1a1a2e;
var titleText = new Text2('TUTORIAL', {
size: 72,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
var tutorialText = new Text2('HOW TO PLAY COOKIE TAP EMPIRE:\n\n⢠Tap the large cookie to earn cookies\n⢠Use earned cookies to buy upgrades from the shop\n⢠Each upgrade increases your cookies per second (CPS)\n⢠Collect falling cookies for bonus rewards\n⢠Set your username to appear on the leaderboard\n⢠Username changes have a 5-minute cooldown\n⢠Reach 1M+ cookies and 100+ upgrades to unlock prestige\n⢠Prestige requirements increase moderately with each level\n⢠Prestiging resets your progress but gives permanent bonuses\n⢠Higher prestige levels provide greater production bonuses\n⢠Check the leaderboard to see how you rank against others!', {
size: 36,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1200;
self.addChild(tutorialText);
var continueButton = self.attachAsset('continueButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2000,
scaleX: 1.5,
scaleY: 1.5
});
var continueGlow = self.attachAsset('continueGlow', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1980
});
var continueText = new Text2('GOT IT!', {
size: 42,
fill: 0xFFFFFF
});
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 2000;
self.addChild(continueText);
// Close button
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400
});
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400,
rotation: Math.PI / 4
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400,
rotation: -Math.PI / 4
});
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
continueButton.down = handleClose;
continueText.down = handleClose;
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
self.visible = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Enhanced Settings and Menu Assets
// Enhanced Falling Cookie Assets
// Enhanced Cosmic/Endgame Assets
// Enhanced Ultra-Advanced Assets
// Enhanced Cosmic Building Assets
// Enhanced Special Building Assets
// Enhanced Advanced Building Assets
// Enhanced Menu Assets
// Enhanced Prestige Assets
// Enhanced Button Assets
// Enhanced Shop and UI Assets
// Enhanced Building Assets - More distinctive and detailed
// Enhanced UI Elements - More polished and professional
// Enhanced Cookie Assets - More detailed and visually appealing
// Tutorial pixel art
// Settings pixel art
// Leaderboard pixel art
// Menu and dialog pixel art
// Building pixel art textures
// Shop and upgrade pixel art
// Main menu pixel art
// HUD and UI pixel art
// Pixel art cookie assets
// Menu buttons
// UI Elements
// Building pixel textures
// Custom pixel-style cookie textures
// Game state variables
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var gameStarted = storage.gameStarted || false;
var isMuted = storage.isMuted || false;
var fallingCookies = [];
var miniCookies = [];
var playerName = storage.playerName || '';
// Enhanced username validation function
function isUsernameAvailable(username) {
if (!username || username.trim() === '') return false;
var trimmedUsername = username.trim();
var leaderboardNames = storage.leaderboardNames || [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === trimmedUsername) {
return false;
}
}
return true;
}
// Enhanced username validation with content filtering
function isValidUsername(username) {
if (!username || typeof username !== 'string') return false;
var trimmed = username.trim();
if (trimmed.length === 0 || trimmed.length > 20) return false;
// Check for inappropriate content (basic filtering)
var blockedWords = ['admin', 'mod', 'owner', 'system', 'null', 'undefined', 'test'];
var lowerTrimmed = trimmed.toLowerCase();
for (var i = 0; i < blockedWords.length; i++) {
if (lowerTrimmed.indexOf(blockedWords[i]) !== -1) return false;
}
// Check for only spaces or special characters
if (!/^[a-zA-Z0-9\s_-]+$/.test(trimmed)) return false;
if (/^\s*$/.test(trimmed)) return false;
return true;
}
// Generate unique username with enhanced algorithm
function generateUniqueUsername() {
var attempts = 0;
var maxAttempts = 100;
var prefixes = ['Cookie', 'Sweet', 'Sugar', 'Candy', 'Honey', 'Maple', 'Vanilla', 'Caramel', 'Cocoa', 'Mint'];
var suffixes = ['Baker', 'Master', 'Chef', 'Hero', 'Legend', 'Pro', 'Star', 'King', 'Queen', 'Ace'];
do {
var username;
if (attempts < 50) {
// First 50 attempts: use creative combinations
var prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
var suffix = suffixes[Math.floor(Math.random() * suffixes.length)];
var number = Math.floor(Math.random() * 999) + 1;
username = prefix + suffix + number;
} else {
// Fallback: simple Player + number
username = 'Player' + Math.floor(Math.random() * 99999 + 1);
}
attempts++;
} while (!isUsernameAvailable(username) && attempts < maxAttempts);
if (attempts >= maxAttempts) {
// Emergency fallback
username = 'Player' + Date.now().toString().slice(-5);
}
return username;
}
// Get display name with enhanced formatting
function getDisplayName(name) {
if (!name) return 'Anonymous';
if (name === 'NEO') {
return 'š [OWNER] ' + name;
}
// Add special formatting for certain usernames
if (name.toLowerCase().indexOf('cookie') !== -1) {
return 'šŖ ' + name;
}
if (storage.isOwner && name === playerName) {
return 'ā ' + name;
}
return name;
}
// Username change cooldown check
function canChangeUsername() {
var lastChange = storage.lastUsernameChange || 0;
var cooldownTime = 300000; // 5 minutes cooldown
return Date.now() - lastChange > cooldownTime;
}
// Get time remaining for username change
function getUsernameChangeCooldown() {
var lastChange = storage.lastUsernameChange || 0;
var cooldownTime = 300000; // 5 minutes
var remaining = cooldownTime - (Date.now() - lastChange);
if (remaining <= 0) return 0;
return Math.ceil(remaining / 1000); // Return seconds
}
// Username input function
function requestUsername() {
var username = prompt('Enter your username for the leaderboard:') || '';
if (username.length > 0 && username.length <= 20) {
if (isUsernameAvailable(username) || username === playerName) {
playerName = username;
try {
// Store as simple string literal to avoid storage restrictions
var nameToStore = String(playerName);
storage.playerName = nameToStore;
} catch (e) {
console.log('Storage not available for username save');
}
return true;
} else {
alert('Username already taken! Please choose another username.');
return requestUsername();
}
} else if (username.length > 20) {
alert('Username too long! Maximum 20 characters.');
return requestUsername();
}
return false;
}
// Click detection for auto-clicker prevention
var clickTimes = [];
var isWarned = false;
var clicksBlocked = false;
// Achievement system
var achievements = [{
id: 'first_cookie',
name: 'First Cookie',
desc: 'Click your first cookie',
condition: function condition() {
return allTimeCookies >= 1;
},
reward: 10,
unlocked: false
}, {
id: 'cookie_clicker',
name: 'Cookie Clicker',
desc: 'Click 100 times',
condition: function condition() {
return totalClicks >= 100;
},
reward: 50,
unlocked: false
}, {
id: 'baker_dozen',
name: "Baker's Dozen",
desc: 'Have 13 buildings total',
condition: function condition() {
var total = 0;
for (var i = 0; i < buildings.length; i++) total += buildings[i].count;
return total >= 13;
},
reward: 1000,
unlocked: false
}, {
id: 'millionaire',
name: 'Millionaire',
desc: 'Have 1 million cookies',
condition: function condition() {
return allTimeCookies >= 1000000;
},
reward: 10000,
unlocked: false
}, {
id: 'speed_demon',
name: 'Speed Demon',
desc: 'Generate 1000 CPS',
condition: function condition() {
return totalCPS >= 1000;
},
reward: 50000,
unlocked: false
}];
var totalClicks = storage.totalClicks || 0;
function checkAchievements() {
var newAchievements = 0;
for (var i = 0; i < achievements.length; i++) {
var ach = achievements[i];
if (!ach.unlocked && ach.condition()) {
ach.unlocked = true;
cookies += ach.reward;
allTimeCookies += ach.reward;
newAchievements++;
showFloatingNumber('ACHIEVEMENT: ' + ach.name, 1024, 400 + i * 50);
showFloatingNumber('+' + formatNumber(ach.reward) + ' cookies!', 1024, 450 + i * 50);
playSound('achievement', 1.2);
LK.effects.flashScreen(0x00FF00, 300);
// Save achievement state
storage['achievement_' + ach.id] = true;
}
}
if (newAchievements > 0) {
updateDisplay();
saveGame();
}
}
// Load achievement states
for (var i = 0; i < achievements.length; i++) {
if (storage['achievement_' + achievements[i].id]) {
achievements[i].unlocked = true;
}
}
// Game variables
var cookies = storage.cookies || 0;
var totalCPS = storage.totalCPS || 0;
var cookiesPerTap = 1;
var tapMultiplier = 1;
// Powerup system variables
var activePowerups = [];
var powerups = [];
var powerupSpawnTimer = 0;
var basePowerupInterval = 1800; // 30 seconds at 60fps
// Falling cookie rain system variables
var rainCookies = [];
var rainSpawnTimer = 0;
var baseRainInterval = 45; // Spawn every 45 frames (0.75 seconds at 60fps)
// Prestige system variables
var prestigeLevel = storage.prestigeLevel || 0;
var prestigeBonus = prestigeLevel * 0.1; // 10% bonus per prestige
var allTimeCookies = storage.allTimeCookies || 0;
var canPrestige = false;
// Leaderboard system
var lastLeaderboardUpdate = storage.lastLeaderboardUpdate || 0;
// Buildings data
var buildingsData = [{
type: 'grandma',
cost: 15,
cps: 1
}, {
type: 'oven',
cost: 100,
cps: 8
}, {
type: 'factory',
cost: 1100,
cps: 47
}, {
type: 'mine',
cost: 12000,
cps: 260
}, {
type: 'bank',
cost: 130000,
cps: 1400
}, {
type: 'temple',
cost: 1400000,
cps: 7800
}, {
type: 'portal',
cost: 20000000,
cps: 44000
}, {
type: 'machine',
cost: 150000000,
cps: 260000
}, {
type: 'condenser',
cost: 800000000,
cps: 1600000
}, {
type: 'prism',
cost: 5000000000,
cps: 10000000
}, {
type: 'chancemaker',
cost: 25000000000,
cps: 65000000
}, {
type: 'fractal',
cost: 120000000000,
cps: 430000000
}, {
type: 'console',
cost: 600000000000,
cps: 2900000000
}, {
type: 'idleverse',
cost: 3000000000000,
cps: 21000000000
}, {
type: 'cortex',
cost: 15000000000000,
cps: 150000000000
}, {
type: 'you',
cost: 75000000000000,
cps: 1100000000000
}, {
type: 'synclavier',
cost: 400000000000000,
cps: 51000000000000
}, {
type: 'ascendancy',
cost: 2000000000000000,
cps: 440000000000000
}, {
type: 'altruism',
cost: 10000000000000000,
cps: 4000000000000000
}, {
type: 'luminous',
cost: 50000000000000000,
cps: 100000000000000000
}, {
type: 'sucroblast',
cost: 250000000000000000,
cps: 30000000000000000000
}, {
type: 'infinitude',
cost: 1250000000000000000,
cps: 999999999999999999999
}, {
type: 'cortexbaker',
cost: 6250000000000000000,
cps: 9999999999999999999999999
}];
var buildings = [];
var floatingNumbers = [];
// Create custom HUD background - removed to hide black box
// var hudBg = LK.getAsset('hudBackground', {
// anchorX: 0,
// anchorY: 0,
// height: 250
// });
// hudBg.alpha = 0.9;
// LK.gui.top.addChild(hudBg);
// Create cookie (centered and much larger, matches menu cookie)
var mainCookie = game.addChild(new Cookie());
mainCookie.x = 1024;
mainCookie.y = 1200;
mainCookie.scaleX = 2.5;
mainCookie.scaleY = 2.5;
// Custom UI with styled backgrounds - moved to top center
var cookieCounterBg = LK.getAsset('cookieCounter', {
anchorX: 0.5,
anchorY: 0.5
});
cookieCounterBg.x = 0;
cookieCounterBg.y = 40;
cookieCounterBg.visible = false; // Hide in menu
LK.gui.top.addChild(cookieCounterBg);
var cookieDisplay = new Text2('Cookies: 0', {
size: 52,
fill: 0xFFD700
});
cookieDisplay.anchor.set(0.5, 0.5);
cookieDisplay.x = 0;
cookieDisplay.y = 40;
cookieDisplay.visible = false; // Hide in menu
LK.gui.top.addChild(cookieDisplay);
var cpsCounterBg = LK.getAsset('cpsCounter', {
anchorX: 0.5,
anchorY: 0.5
});
cpsCounterBg.x = 0;
cpsCounterBg.y = 90;
cpsCounterBg.visible = false; // Hide in menu
LK.gui.top.addChild(cpsCounterBg);
var cpsDisplay = new Text2('Per second: 0', {
size: 36,
fill: 0x90EE90
});
cpsDisplay.anchor.set(0.5, 0.5);
cpsDisplay.x = 0;
cpsDisplay.y = 90;
cpsDisplay.visible = false; // Hide in menu
LK.gui.top.addChild(cpsDisplay);
// Prestige display
var prestigeDisplay = new Text2('Prestige Level: 0 (+0% bonus)', {
size: 28,
fill: 0xFFD700
});
prestigeDisplay.anchor.set(0.5, 0.5);
prestigeDisplay.x = 0;
prestigeDisplay.y = 160;
LK.gui.top.addChild(prestigeDisplay);
// Powerup status display
var powerupDisplay = new Text2('', {
size: 24,
fill: 0xFF6347
});
powerupDisplay.anchor.set(0.5, 0.5);
powerupDisplay.x = 0;
powerupDisplay.y = 200;
powerupDisplay.visible = false;
LK.gui.top.addChild(powerupDisplay);
// Shopping cart menu button (middle-right screen, larger and more visible)
var shopIcon = game.addChild(LK.getAsset('shopIconBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
shopIcon.x = 1900;
shopIcon.y = 1366;
shopIcon.tint = 0x333333;
var shopBorder = game.addChild(LK.getAsset('shopIconBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
shopBorder.x = 1900;
shopBorder.y = 1366;
shopBorder.tint = 0x666666;
var cartBg = game.addChild(LK.getAsset('shoppingCart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
cartBg.x = 1900;
cartBg.y = 1366;
cartBg.tint = 0x888888;
var wheel1 = game.addChild(LK.getAsset('cartWheel1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
wheel1.x = 1875;
wheel1.y = 1390;
var wheel2 = game.addChild(LK.getAsset('cartWheel2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
wheel2.x = 1925;
wheel2.y = 1390;
var handle = game.addChild(LK.getAsset('cartHandle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
handle.x = 1940;
handle.y = 1350;
// Create back to main menu button (top right, below reserved area)
var backToMenuButton = game.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
backToMenuButton.x = 1900;
backToMenuButton.y = 200;
backToMenuButton.tint = 0xE67E22;
var backToMenuText = new Text2('MENU', {
size: 28,
fill: 0xFFFFFF
});
backToMenuText.anchor.set(0.5, 0.5);
backToMenuText.x = 1900;
backToMenuText.y = 200;
game.addChild(backToMenuText);
function goBackToMainMenu() {
if (!isMuted) LK.getSound('buttonClick').play();
gameStarted = false;
cookieCounterBg.visible = false;
cookieDisplay.visible = false;
cpsCounterBg.visible = false;
cpsDisplay.visible = false;
prestigeDisplay.visible = false;
// Close any open menus
if (shop && shop.isOpen) shop.close();
if (settingsMenu && settingsMenu.isOpen) settingsMenu.close();
if (leaderboard && leaderboard.isOpen) leaderboard.close();
if (prestigeMenu && prestigeMenu.isOpen) prestigeMenu.close();
// Save game before returning to menu
saveGame();
updateLeaderboard();
// Show main menu
mainMenu.visible = true;
mainMenu.alpha = 0;
tween(mainMenu, {
alpha: 1
}, {
duration: 300
});
}
backToMenuButton.down = goBackToMainMenu;
backToMenuText.down = goBackToMainMenu;
// Create shop (initially hidden)
var shop = game.addChild(new Shop());
shop.x = 0;
shop.y = 0;
// Close shop menu when tapping outside
game.down = function (x, y, obj) {
// If shop is open and tap is outside the shop area, close it
if (shop && shop.isOpen) {
// Allow taps on shop elements, close only on background taps
if (y < 150 || x < 100 || x > 1948) {
shop.close();
}
}
};
// Create prestige button (bottom of screen)
var prestigeButton = new PrestigeButton();
prestigeButton.x = 1024;
prestigeButton.y = 2600;
game.addChild(prestigeButton);
// Initialize menus
var mainMenu = game.addChild(new MainMenu());
mainMenu.x = 0;
mainMenu.y = 0;
var settingsMenu = game.addChild(new SettingsMenu());
settingsMenu.x = 1024;
settingsMenu.y = 1366;
var tutorialScreen = game.addChild(new TutorialScreen());
tutorialScreen.x = 0;
tutorialScreen.y = 0;
var leaderboard = game.addChild(new Leaderboard());
leaderboard.x = 0;
leaderboard.y = 0;
// Click multiplier upgrade system - moved here before first usage
var clickUpgrades = [{
name: 'Better Finger',
cost: 100,
multiplier: 2,
purchased: false
}, {
name: 'Steel Cursor',
cost: 500,
multiplier: 5,
purchased: false
}, {
name: 'Golden Finger',
cost: 10000,
multiplier: 10,
purchased: false
}, {
name: 'Diamond Touch',
cost: 100000,
multiplier: 25,
purchased: false
}, {
name: 'Divine Click',
cost: 1000000,
multiplier: 50,
purchased: false
}];
// Initialize click multiplier system
updateClickMultiplier();
// Load click upgrades state
for (var i = 0; i < clickUpgrades.length; i++) {
if (storage['clickUpgrade_' + i]) {
clickUpgrades[i].purchased = true;
}
}
updateClickMultiplier();
// Initialize upgrade menu (shop acts as upgrade menu)
var upgradeMenu = shop;
// Initialize music
function showTutorial() {
tutorialScreen.open();
}
// Auto-pause when user leaves
function pauseGame() {
saveGame();
// Additional pause logic can be added here
}
function unpauseGame() {
// Resume game logic
updateDisplay();
}
// Auto-save and leaderboard update system
function updateLeaderboard() {
if (!playerName || playerName === '') return;
var currentTime = Date.now();
// Update more frequently - every 30 seconds for better real-time experience
var shouldUpdate = currentTime - lastLeaderboardUpdate > 30000 || lastLeaderboardUpdate === 0;
if (shouldUpdate) {
// 30 seconds for more responsive leaderboard
lastLeaderboardUpdate = currentTime;
storage.lastLeaderboardUpdate = lastLeaderboardUpdate;
var leaderboardNames = (storage.leaderboardNames || []).slice();
var leaderboardCookies = (storage.leaderboardCookies || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
var playerExists = false;
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardCookies[i] = Math.max(leaderboardCookies[i], cookies);
leaderboardPrestiges[i] = Math.max(leaderboardPrestiges[i] || 0, prestigeLevel);
leaderboardTimestamps[i] = currentTime; // Update timestamp for activity tracking
playerExists = true;
break;
}
}
if (!playerExists) {
leaderboardNames.push(playerName);
leaderboardCookies.push(cookies);
leaderboardTimestamps.push(currentTime);
leaderboardPrestiges.push(prestigeLevel);
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardCookies = leaderboardCookies;
storage.leaderboardTimestamps = leaderboardTimestamps;
storage.leaderboardPrestiges = leaderboardPrestiges;
} else {
// Always update prestige level and timestamp even if not updating cookies frequently
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardPrestiges[i] = Math.max(leaderboardPrestiges[i] || 0, prestigeLevel);
if (leaderboardTimestamps.length > i) {
leaderboardTimestamps[i] = currentTime; // Keep activity current
}
storage.leaderboardPrestiges = leaderboardPrestiges;
storage.leaderboardTimestamps = leaderboardTimestamps;
break;
}
}
}
}
// Click detection system
function recordClick() {
var currentTime = Date.now();
clickTimes.push(currentTime);
// Remove clicks older than 1 second
clickTimes = clickTimes.filter(function (time) {
return currentTime - time < 1000;
});
// Check for suspicious clicking (over 20 clicks per second)
if (clickTimes.length > 20) {
if (!isWarned) {
isWarned = true;
showFloatingNumber('AUTO-CLICKER DETECTED!', 1024, 800);
}
if (clickTimes.length > 25) {
clicksBlocked = true;
showFloatingNumber('CLICKS BLOCKED!', 1024, 850);
LK.setTimeout(function () {
clicksBlocked = false;
isWarned = false;
}, 5000);
}
return false;
}
return true;
}
// Menu functionality
var prestigeMenu = null;
function openShopMenu() {
if (!gameStarted) return;
if (shop.isOpen) {
shop.close();
} else {
shop.open();
}
}
shopIcon.down = openShopMenu;
shopBorder.down = openShopMenu;
cartBg.down = openShopMenu;
wheel1.down = openShopMenu;
wheel2.down = openShopMenu;
handle.down = openShopMenu;
// Create buildings (no longer displayed directly, managed by upgrade menu)
for (var i = 0; i < buildingsData.length; i++) {
var buildingData = buildingsData[i];
var building = new Building(buildingData.type, buildingData.cost, buildingData.cps);
// Load saved data
var savedCount = storage['building_' + buildingData.type] || 0;
if (savedCount > 0) {
building.count = savedCount;
building.cost = Math.floor(building.baseCost * Math.pow(1.15, savedCount));
totalCPS += building.cookiesPerSecond * savedCount;
}
buildings.push(building);
}
// Click multiplier upgrade system moved earlier in code
function updateClickMultiplier() {
cookiesPerTap = 1;
for (var i = 0; i < clickUpgrades.length; i++) {
if (clickUpgrades[i].purchased) {
cookiesPerTap *= clickUpgrades[i].multiplier;
}
}
// Apply prestige bonus
cookiesPerTap *= tapMultiplier;
}
function buyClickUpgrade(upgradeIndex) {
var upgrade = clickUpgrades[upgradeIndex];
if (!upgrade.purchased && cookies >= upgrade.cost) {
cookies -= upgrade.cost;
upgrade.purchased = true;
updateClickMultiplier();
playSound('purchase');
updateDisplay();
saveGame();
showFloatingNumber('Click Power Up!', 1024, 600);
return true;
}
return false;
}
// Enhanced number formatting function
function formatNumber(num) {
if (num < 1000) {
return Math.floor(num).toString();
} else if (num < 10000) {
return Math.floor(num / 100) / 10 + 'k';
} else if (num < 1000000) {
return Math.floor(num / 1000) + 'k';
} else if (num < 10000000) {
return Math.floor(num / 100000) / 10 + 'mil';
} else if (num < 1000000000) {
return Math.floor(num / 1000000) + 'mil';
} else if (num < 10000000000) {
return Math.floor(num / 100000000) / 10 + 'bil';
} else if (num < 1000000000000) {
return Math.floor(num / 1000000000) + 'bil';
} else if (num < 10000000000000) {
return Math.floor(num / 100000000000) / 10 + 'tril';
} else if (num < 1000000000000000) {
return Math.floor(num / 1000000000000) + 'tril';
} else if (num < 10000000000000000) {
return Math.floor(num / 100000000000000) / 10 + 'quad';
} else if (num < 1000000000000000000) {
return Math.floor(num / 1000000000000000) + 'quad';
} else {
return Math.floor(num / 1000000000000000000) + 'quin';
}
}
// Enhanced sound system
function playSound(soundId, volumeMultiplier) {
if (!isMuted && storage.enableSoundEffects) {
var sound = LK.getSound(soundId);
var soundVolume = storage.soundVolume !== undefined ? storage.soundVolume : 0.7;
var finalVolume = soundVolume * (volumeMultiplier || 1);
// Set volume if the sound supports it
if (sound.volume !== undefined) {
sound.volume = finalVolume;
}
sound.play();
}
}
// Game functions
function updateDisplay() {
cookieDisplay.setText('Cookies: ' + formatNumber(cookies));
// Calculate total CPS with prestige bonus and powerup multipliers
var powerupMultiplier = 1;
for (var i = 0; i < activePowerups.length; i++) {
powerupMultiplier *= activePowerups[i].multiplier;
}
var prestigeCPSMultiplier = 1 + prestigeBonus;
var effectiveCPS = totalCPS * prestigeCPSMultiplier * powerupMultiplier;
cpsDisplay.setText('Per second: ' + formatNumber(effectiveCPS));
prestigeDisplay.setText('Prestige Level: ' + prestigeLevel + ' (+' + Math.floor(prestigeBonus * 100) + '% bonus)');
// Update powerup display
if (activePowerups.length > 0) {
var powerupText = '';
for (var i = 0; i < activePowerups.length; i++) {
var powerup = activePowerups[i];
var timeLeft = Math.ceil(powerup.timeLeft / 1000);
powerupText += powerup.name + ': +' + powerup.multiplier + 'x (' + timeLeft + 's)';
if (i < activePowerups.length - 1) powerupText += ' | ';
}
powerupDisplay.setText(powerupText);
powerupDisplay.visible = true;
} else {
powerupDisplay.visible = false;
}
for (var i = 0; i < buildings.length; i++) {
buildings[i].updateDisplay();
}
prestigeButton.updateDisplay();
if (shop && shop.isOpen) {
shop.updatePage();
}
if (prestigeMenu && prestigeMenu.isOpen) {
prestigeMenu.updateDisplay();
}
}
function showFloatingNumber(text, x, y) {
var floatingNum = new FloatingNumber(text, x, y);
game.addChild(floatingNum);
floatingNumbers.push(floatingNum);
}
function saveGame() {
storage.cookies = cookies;
storage.totalCPS = totalCPS;
storage.prestigeLevel = prestigeLevel;
storage.allTimeCookies = allTimeCookies;
storage.isMuted = isMuted;
storage.gameStarted = gameStarted;
try {
// Store as simple string literal to avoid storage restrictions
var nameToStore = String(playerName || '');
storage.playerName = nameToStore;
} catch (e) {
console.log('Storage not available for playerName save');
}
storage.lastLeaderboardUpdate = lastLeaderboardUpdate;
for (var i = 0; i < buildings.length; i++) {
storage['building_' + buildings[i].buildingType] = buildings[i].count;
}
}
// Auto-save timer
var saveTimer = LK.setInterval(function () {
saveGame();
}, 5000);
// CPS generation timer
var cpsTimer = LK.setInterval(function () {
if (totalCPS > 0) {
// Calculate powerup multiplier
var powerupMultiplier = 1;
for (var i = 0; i < activePowerups.length; i++) {
powerupMultiplier *= activePowerups[i].multiplier;
}
// Apply prestige bonus to CPS (same as tap multiplier)
var prestigeCPSMultiplier = 1 + prestigeBonus;
var cpsGain = totalCPS * prestigeCPSMultiplier * powerupMultiplier / 10; // 10 times per second for smoother increments
cookies += cpsGain;
allTimeCookies += cpsGain;
updateDisplay();
}
}, 100);
// Always start with main menu, do not show tutorial by default
gameStarted = false;
mainMenu.visible = true;
// Update username display in menu
mainMenu.updateUsername();
// Initial display update
updateDisplay();
// Completely purge player9240 from all storage - comprehensive cleanup
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardCookies = storage.leaderboardCookies || [];
var leaderboardTimestamps = storage.leaderboardTimestamps || [];
var leaderboardPrestiges = storage.leaderboardPrestiges || [];
// Remove all instances of player9240 and any variations
var playersToRemove = ['player9240', 'Player9240', 'PLAYER9240'];
var indicesToRemove = [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (playersToRemove.indexOf(leaderboardNames[i]) !== -1) {
indicesToRemove.push(i);
}
}
// Remove indices in reverse order to avoid index shifting issues
for (var j = indicesToRemove.length - 1; j >= 0; j--) {
var indexToRemove = indicesToRemove[j];
leaderboardNames.splice(indexToRemove, 1);
leaderboardCookies.splice(indexToRemove, 1);
leaderboardTimestamps.splice(indexToRemove, 1);
leaderboardPrestiges.splice(indexToRemove, 1);
}
// Force complete removal by creating fresh arrays without player9240
var cleanNames = [];
var cleanCookies = [];
var cleanTimestamps = [];
var cleanPrestiges = [];
for (var k = 0; k < leaderboardNames.length; k++) {
if (playersToRemove.indexOf(leaderboardNames[k]) === -1) {
cleanNames.push(leaderboardNames[k]);
cleanCookies.push(leaderboardCookies[k]);
cleanTimestamps.push(leaderboardTimestamps[k]);
cleanPrestiges.push(leaderboardPrestiges[k]);
}
}
// Overwrite storage completely
storage.leaderboardNames = cleanNames;
storage.leaderboardCookies = cleanCookies;
storage.leaderboardTimestamps = cleanTimestamps;
storage.leaderboardPrestiges = cleanPrestiges;
// Golden cookie spawning (every 30-60 seconds randomly)
if (LK.ticks % 60 === 0 && Math.random() < 0.03) {
// ~3% chance every second
var goldenCookie = game.addChild(new GoldenCookie());
goldenCookie.x = 200 + Math.random() * 1648;
goldenCookie.y = 200 + Math.random() * 1800;
}
// Start background music
// Check achievements periodically
if (LK.ticks % 180 === 0) {
// Every 3 seconds
checkAchievements();
}
// Clean up destroyed rain cookies
for (var i = rainCookies.length - 1; i >= 0; i--) {
if (rainCookies[i].destroyed) {
rainCookies.splice(i, 1);
}
}
// Spawn rain cookies for background effect (always visible during gameplay)
rainSpawnTimer++;
var rainInterval = baseRainInterval + Math.random() * 30; // Vary spawn timing slightly
if (rainSpawnTimer >= rainInterval) {
rainSpawnTimer = 0;
// Spawn 2-4 rain cookies at once for better visual effect
var spawnCount = 2 + Math.floor(Math.random() * 3);
for (var j = 0; j < spawnCount; j++) {
var rainCookie = game.addChild(new RainCookie());
// Spawn across full width with some spread
rainCookie.x = -100 + Math.random() * 2248; // Spawn slightly off-screen for better coverage
rainCookie.y = -50 - Math.random() * 200; // Stagger starting heights
rainCookie.startX = rainCookie.x; // Set starting X for sway calculations
rainCookies.push(rainCookie);
// Add smooth entrance animation using tween
rainCookie.alpha = 0;
var originalScale = rainCookie.scaleX;
rainCookie.scaleX = 0;
rainCookie.scaleY = 0;
tween(rainCookie, {
alpha: 0.3 + Math.random() * 0.4,
// Random transparency 0.3-0.7
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 400 + Math.random() * 600,
easing: tween.easeOut
});
// Add subtle rotation animation
tween(rainCookie, {
rotation: rainCookie.rotation + (Math.random() - 0.5) * Math.PI * 4
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.linear
});
}
}
// Update leaderboard periodically
updateLeaderboard();
if (!isMuted) {
var initialVolume = storage.musicVolume !== undefined ? storage.musicVolume : 0.8;
LK.playMusic('bgmusic', {
loop: true,
volume: initialVolume
});
}
// Falling cookie spawn timer - every 3 minutes based on upgrades
var fallingCookieTimer = 0;
var baseFallingInterval = 10800; // 3 minutes at 60fps
game.update = function () {
if (!gameStarted) {
// Hide cookie counters in menu
cookieCounterBg.visible = false;
cookieDisplay.visible = false;
cpsCounterBg.visible = false;
cpsDisplay.visible = false;
// Hide prestige level in menu
prestigeDisplay.visible = false;
// Hide back to menu button in menu
backToMenuButton.visible = false;
backToMenuText.visible = false;
// Show main menu if not started
if (!mainMenu.visible) {
mainMenu.visible = true;
mainMenu.alpha = 1;
}
return;
}
// Show back to menu button in game
backToMenuButton.visible = true;
backToMenuText.visible = true;
// Clean up destroyed floating numbers
for (var i = floatingNumbers.length - 1; i >= 0; i--) {
if (floatingNumbers[i].destroyed) {
floatingNumbers.splice(i, 1);
}
}
// Clean up destroyed falling cookies
for (var i = fallingCookies.length - 1; i >= 0; i--) {
if (fallingCookies[i].destroyed) {
fallingCookies.splice(i, 1);
}
}
// Clean up destroyed mini cookies
for (var i = miniCookies.length - 1; i >= 0; i--) {
if (miniCookies[i].destroyed) {
miniCookies.splice(i, 1);
}
}
// Calculate falling cookie interval based on upgrades
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
// Spawn falling cookies more frequently with more upgrades
var fallingInterval = Math.max(1800, baseFallingInterval - totalUpgrades * 30); // Minimum 30 seconds
fallingCookieTimer++;
if (fallingCookieTimer >= fallingInterval) {
fallingCookieTimer = 0;
var fallingCookie = game.addChild(new FallingCookie());
fallingCookie.x = 200 + Math.random() * 1648;
fallingCookie.y = -100;
fallingCookie.scaleX = 1.8; // Make them bigger
fallingCookie.scaleY = 1.8;
fallingCookies.push(fallingCookie);
}
// Clean up destroyed powerups
for (var i = powerups.length - 1; i >= 0; i--) {
if (powerups[i].destroyed) {
powerups.splice(i, 1);
}
}
// Spawn powerups randomly (every 30-60 seconds)
powerupSpawnTimer++;
var powerupInterval = basePowerupInterval + Math.random() * 1800; // 30-60 seconds
if (powerupSpawnTimer >= powerupInterval && totalCPS > 10) {
// Only spawn if player has some CPS AND no menus are open
var anyMenuOpen = shop && shop.isOpen || settingsMenu && settingsMenu.isOpen || leaderboard && leaderboard.isOpen || tutorialScreen && tutorialScreen.isOpen || prestigeMenu && prestigeMenu.isOpen;
if (!anyMenuOpen) {
powerupSpawnTimer = 0;
var powerup = game.addChild(new Powerup());
powerup.x = 300 + Math.random() * 1448; // Keep away from edges
powerup.y = 400 + Math.random() * 1200;
powerups.push(powerup);
}
}
// Update active powerups
for (var i = activePowerups.length - 1; i >= 0; i--) {
var powerup = activePowerups[i];
powerup.timeLeft -= 16.67; // Approximately 1 frame at 60fps
if (powerup.timeLeft <= 0) {
showFloatingNumber(powerup.name + ' EXPIRED', 1024, 500);
activePowerups.splice(i, 1);
}
}
// Update leaderboard periodically
updateLeaderboard();
// Update username display and status more frequently during cooldown
if (LK.ticks % 180 === 0 && mainMenu) {
// Every 3 seconds for more responsive cooldown updates
mainMenu.updateUsername();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
leaderboardNames: [],
leaderboardCookies: [],
leaderboardTimestamps: [],
leaderboardPrestiges: [],
playerName: "",
isOwner: false,
hasSetUsername: false,
usernameHistory: [],
lastUsernameChange: 0,
musicVolume: 0.8,
soundVolume: 0.7,
enableSoundEffects: true
});
/****
* Classes
****/
var Building = Container.expand(function (buildingType, cost, cps) {
var self = Container.call(this);
self.buildingType = buildingType;
self.cost = cost;
self.baseCost = cost;
self.cookiesPerSecond = cps;
self.count = 0;
var background = self.attachAsset('upgradeButton', {
anchorX: 0,
anchorY: 0
});
// Create detailed pixel art for each building type
if (buildingType === 'grandma') {
var grandmaBase = self.attachAsset('grandma', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var grandmaHair = self.attachAsset('grandmaHair', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 25
});
var grandmaFace = self.attachAsset('grandmaFace', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 35
});
var grandmaEyes1 = self.attachAsset('grandmaEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: 32
});
var grandmaEyes2 = self.attachAsset('grandmaEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 45,
y: 32
});
var grandmaNose = self.attachAsset('grandmaNose', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 37
});
var grandmaApron = self.attachAsset('grandmaApron', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 55
});
} else if (buildingType === 'oven') {
var ovenBase = self.attachAsset('oven', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenBody = self.attachAsset('ovenBody', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenDoor = self.attachAsset('ovenDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 45
});
var ovenWindow = self.attachAsset('ovenWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var ovenHandle = self.attachAsset('ovenHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 45
});
var ovenKnob1 = self.attachAsset('ovenKnob', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 25
});
var ovenKnob2 = self.attachAsset('ovenKnob', {
anchorX: 0.5,
anchorY: 0.5,
x: 50,
y: 25
});
var ovenVents = self.attachAsset('ovenVents', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 20
});
} else if (buildingType === 'factory') {
var factoryBase = self.attachAsset('factory', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
var factoryRoof = self.attachAsset('factoryRoof', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 15
});
var factoryChimney = self.attachAsset('factoryChimney', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 10
});
var factorySmoke1 = self.attachAsset('factorySmoke', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -10
});
var factorySmoke2 = self.attachAsset('factorySmoke', {
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: -15
});
var factoryWindow1 = self.attachAsset('factoryWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: 35
});
var factoryWindow2 = self.attachAsset('factoryWindow', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 35
});
var factoryDoor = self.attachAsset('factoryDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 55
});
} else {
var icon = self.attachAsset(buildingType, {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 40
});
}
var nameText = new Text2(buildingType.toUpperCase(), {
size: 24,
fill: 0xFFFFFF
});
nameText.anchor.set(0, 0.5);
nameText.x = 90;
nameText.y = 25;
self.addChild(nameText);
self.costText = new Text2('Cost: ' + self.cost, {
size: 20,
fill: 0xFFFF00
});
self.costText.anchor.set(0, 0.5);
self.costText.x = 90;
self.costText.y = 45;
self.addChild(self.costText);
self.countText = new Text2('Owned: ' + self.count, {
size: 18,
fill: 0xCCCCCC
});
self.countText.anchor.set(0, 0.5);
self.countText.x = 90;
self.countText.y = 65;
self.addChild(self.countText);
self.updateDisplay = function () {
self.costText.setText('Cost: ' + formatNumber(self.cost));
self.countText.setText('Owned: ' + self.count);
if (cookies >= self.cost) {
background.tint = 0x4169E1;
} else {
background.tint = 0x666666;
}
};
self.purchase = function () {
if (cookies >= self.cost) {
cookies -= self.cost;
self.count++;
totalCPS += self.cookiesPerSecond;
// Increase cost by 15%
self.cost = Math.floor(self.cost * 1.15);
playSound('purchase');
self.updateDisplay();
updateDisplay();
saveGame();
}
};
self.down = function (x, y, obj) {
self.purchase();
};
return self;
});
var Cookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5
});
// Add detailed cookie decorations with pixel art style
var highlight = self.attachAsset('cookieHighlight', {
anchorX: 0.5,
anchorY: 0.5,
x: -40,
y: -60
});
highlight.alpha = 0.6;
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: -30
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: 40
});
var chip3 = self.attachAsset('cookieChip3', {
anchorX: 0.5,
anchorY: 0.5,
x: -20,
y: 70
});
var chip4 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -50
});
var chip5 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: 20
});
self.originalScale = 1;
self.tap = function () {
// Check for auto-clicker
if (!recordClick() || clicksBlocked) {
return;
}
// Enhanced rotation animation without scaling
tween.stop(self, {
rotation: true
});
self.rotation += 0.1;
tween(self, {
rotation: 0
}, {
duration: 300,
easing: tween.elasticOut
});
// Color flash effect
tween.stop(cookieGraphics, {
tint: true
});
cookieGraphics.tint = 0xffff99;
tween(cookieGraphics, {
tint: 0xffffff
}, {
duration: 200
});
// Play sound effect
playSound('cookieTap');
// Track total clicks for achievements
totalClicks++;
// Add cookies with all bonuses
var cookiesGained = cookiesPerTap;
cookies += cookiesGained;
allTimeCookies += cookiesGained;
updateDisplay();
// Spawn mini cookie instead of floating number
var miniCookie = game.addChild(new MiniCookie());
miniCookie.x = self.x + (Math.random() - 0.5) * 100;
miniCookie.y = self.y + (Math.random() - 0.5) * 100;
};
self.down = function (x, y, obj) {
if (gameStarted && !upgradeMenu.isOpen && !settingsMenu.isOpen && !leaderboard.isOpen && !tutorialScreen.isOpen && (!prestigeMenu || !prestigeMenu.isOpen)) {
self.tap();
}
};
return self;
});
var FallingCookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -15,
y: -10
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: 15
});
self.fallSpeed = 3 + Math.random() * 4;
self.rotationSpeed = 0.05 + Math.random() * 0.1;
self.value = Math.floor(cookies * 0.01) + Math.floor(Math.random() * (cookies * 0.05)) + 1;
self.update = function () {
self.y += self.fallSpeed;
self.rotation += self.rotationSpeed;
if (self.y > 2800) {
self.destroy();
}
};
self.collect = function () {
cookies += self.value;
allTimeCookies += self.value;
playSound('fallingCookieClick', 0.8);
showFloatingNumber('+' + self.value, self.x, self.y);
updateDisplay();
self.destroy();
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var FloatingNumber = Container.expand(function (text, startX, startY) {
var self = Container.call(this);
var numberText = new Text2(text, {
size: 56,
fill: 0xFFD700
});
numberText.anchor.set(0.5, 0.5);
self.addChild(numberText);
self.x = startX;
self.y = startY;
self.alpha = 1;
// Animate upward and fade out
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var GoldenCookie = Container.expand(function () {
var self = Container.call(this);
self.bonusType = Math.random() < 0.5 ? 'multiply' : 'bonus';
self.multiplier = 2 + Math.random() * 5; // 2x to 7x multiplier
self.bonusAmount = Math.floor(cookies * 0.1 + Math.random() * cookies * 0.2);
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds at 60fps
var cookieGraphics = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
cookieGraphics.tint = 0xFFD700; // Golden tint
// Pulsing glow effect
var glow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
glow.tint = 0xFFFF88;
glow.alpha = 0.3;
self.update = function () {
self.lifetime++;
// Pulsing animation
var pulse = 1 + Math.sin(self.lifetime * 0.2) * 0.1;
self.scaleX = pulse;
self.scaleY = pulse;
glow.scaleX = 1.2 * pulse;
glow.scaleY = 1.2 * pulse;
// Fade out in last 2 seconds
if (self.lifetime > self.maxLifetime - 120) {
self.alpha = 1 - (self.lifetime - (self.maxLifetime - 120)) / 120;
}
// Remove when expired
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
self.collect = function () {
var bonusText = '';
if (self.bonusType === 'multiply') {
var oldCookies = cookies;
cookies *= self.multiplier;
allTimeCookies += cookies - oldCookies;
bonusText = 'GOLDEN BONUS! x' + Math.floor(self.multiplier);
} else {
cookies += self.bonusAmount;
allTimeCookies += self.bonusAmount;
bonusText = 'GOLDEN BONUS! +' + formatNumber(self.bonusAmount);
}
playSound('goldenCookie', 1.0);
showFloatingNumber(bonusText, self.x, self.y);
updateDisplay();
LK.effects.flashScreen(0xFFD700, 500);
self.destroy();
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var Leaderboard = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.scrollOffset = 0;
self.maxScroll = 0;
self.isDragging = false;
self.lastY = 0;
self.velocity = 0;
self.leaderboardData = [];
// Full screen background with gradient effect
var background = self.attachAsset('leaderboardBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x0a0a1e;
// Main panel with improved styling
var panel = self.attachAsset('leaderboardPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.1,
scaleY: 1.05
});
panel.tint = 0x1e1e2e;
// Header section with enhanced styling
var header = self.attachAsset('leaderboardHeader', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 350,
scaleX: 1.1,
scaleY: 0.8
});
header.tint = 0x2a2a3e;
// Animated title with glow effect
var titleText = new Text2('š COOKIE EMPIRE LEADERBOARD š', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 350;
self.addChild(titleText);
// Enhanced close button with better visibility
var closeBg = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
scaleX: 1.2,
scaleY: 1.2
});
closeBg.tint = 0x8B0000;
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
scaleX: 2.5,
scaleY: 2.5
});
closeBtn.tint = 0xFF4444;
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
rotation: Math.PI / 4,
scaleX: 2.5,
scaleY: 2.5
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
rotation: -Math.PI / 4,
scaleX: 2.5,
scaleY: 2.5
});
// Stats header
var statsText = new Text2('Showing Top 20 Players', {
size: 32,
fill: 0xCCCCCC
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 420;
self.addChild(statsText);
// Column headers with better positioning
var rankHeader = new Text2('RANK', {
size: 28,
fill: 0xFFFFFF
});
rankHeader.anchor.set(0.5, 0.5);
rankHeader.x = 250;
rankHeader.y = 480;
self.addChild(rankHeader);
var nameHeader = new Text2('PLAYER', {
size: 28,
fill: 0xFFFFFF
});
nameHeader.anchor.set(0, 0.5);
nameHeader.x = 400;
nameHeader.y = 480;
self.addChild(nameHeader);
var cookiesHeader = new Text2('COOKIES', {
size: 28,
fill: 0xFFFFFF
});
cookiesHeader.anchor.set(0, 0.5);
cookiesHeader.x = 900;
cookiesHeader.y = 480;
self.addChild(cookiesHeader);
var prestigeHeader = new Text2('PRESTIGE', {
size: 28,
fill: 0xFFFFFF
});
prestigeHeader.anchor.set(0, 0.5);
prestigeHeader.x = 1450;
prestigeHeader.y = 480;
self.addChild(prestigeHeader);
// Container for scrollable entries
self.entriesContainer = self.addChild(new Container());
self.entries = [];
// Scroll indicator
self.scrollIndicator = new Text2('Scroll to see more players', {
size: 24,
fill: 0x888888
});
self.scrollIndicator.anchor.set(0.5, 0.5);
self.scrollIndicator.x = 1024;
self.scrollIndicator.y = 2400;
self.addChild(self.scrollIndicator);
self.cleanLeaderboardData = function () {
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardCookies = storage.leaderboardCookies || [];
var leaderboardTimestamps = storage.leaderboardTimestamps || [];
var leaderboardPrestiges = storage.leaderboardPrestiges || [];
// Clean up any invalid entries
var cleanNames = [];
var cleanCookies = [];
var cleanTimestamps = [];
var cleanPrestiges = [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] && leaderboardNames[i].trim() !== '' && leaderboardCookies[i] >= 0 && !isNaN(leaderboardCookies[i])) {
cleanNames.push(leaderboardNames[i]);
cleanCookies.push(leaderboardCookies[i]);
cleanTimestamps.push(leaderboardTimestamps[i] || 0);
cleanPrestiges.push(leaderboardPrestiges[i] || 0);
}
}
// Update storage with cleaned data
storage.leaderboardNames = cleanNames;
storage.leaderboardCookies = cleanCookies;
storage.leaderboardTimestamps = cleanTimestamps;
storage.leaderboardPrestiges = cleanPrestiges;
return {
names: cleanNames,
cookies: cleanCookies,
timestamps: cleanTimestamps,
prestiges: cleanPrestiges
};
};
self.sortLeaderboard = function (data) {
var indices = [];
for (var i = 0; i < data.names.length; i++) {
indices.push(i);
}
// Enhanced sorting: cookies first, then prestige, then timestamp (most recent)
indices.sort(function (a, b) {
if (Math.abs(data.cookies[b] - data.cookies[a]) < 1) {
// Very close cookie counts
if (data.prestiges[b] === data.prestiges[a]) {
return data.timestamps[b] - data.timestamps[a]; // Most recent wins
}
return data.prestiges[b] - data.prestiges[a]; // Higher prestige wins
}
return data.cookies[b] - data.cookies[a];
});
return indices;
};
self.updateLeaderboard = function () {
// Clear existing entries
for (var i = 0; i < self.entries.length; i++) {
self.entries[i].destroy();
}
self.entries = [];
var cleanData = self.cleanLeaderboardData();
var sortedIndices = self.sortLeaderboard(cleanData);
// Show top 20 instead of 10
var maxEntries = Math.min(20, sortedIndices.length);
// Update stats display
statsText.setText('Showing Top ' + maxEntries + ' of ' + sortedIndices.length + ' Players');
for (var i = 0; i < maxEntries; i++) {
var idx = sortedIndices[i];
var yPos = 550 + i * 90;
// Enhanced entry styling with rank-based colors
var entryBg = self.entriesContainer.addChild(LK.getAsset('leaderboardEntry', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos,
scaleX: 1.05,
scaleY: 1.1
}));
// Special styling for top 3
if (i === 0) {
entryBg.tint = 0xFFD700; // Gold
} else if (i === 1) {
entryBg.tint = 0xC0C0C0; // Silver
} else if (i === 2) {
entryBg.tint = 0xCD7F32; // Bronze
} else if (cleanData.names[idx] === playerName) {
entryBg.tint = 0x4CAF50; // Player's entry in green
} else {
entryBg.tint = 0x3c3c4e; // Default
}
// Rank with medals for top 3
var rankText;
if (i === 0) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else if (i === 1) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else if (i === 2) {
rankText = new Text2('š„', {
size: 40,
fill: 0x000000
});
} else {
rankText = new Text2(i + 1 + '.', {
size: 32,
fill: 0xFFFFFF
});
}
rankText.anchor.set(0.5, 0.5);
rankText.x = 250;
rankText.y = yPos;
self.entriesContainer.addChild(rankText);
var displayName = getDisplayName(cleanData.names[idx]);
var nameColor = cleanData.names[idx] === 'NEO' ? 0xFF6B35 : cleanData.names[idx] === playerName ? 0x4CAF50 : 0xFFD700;
var nameText = new Text2(displayName, {
size: 30,
fill: nameColor
});
nameText.anchor.set(0, 0.5);
nameText.x = 400;
nameText.y = yPos;
self.entriesContainer.addChild(nameText);
var cookieText = new Text2(formatNumber(Math.floor(cleanData.cookies[idx])), {
size: 28,
fill: 0x90EE90
});
cookieText.anchor.set(0, 0.5);
cookieText.x = 900;
cookieText.y = yPos;
self.entriesContainer.addChild(cookieText);
// Enhanced prestige display
var prestigeLevel = cleanData.prestiges[idx] || 0;
var prestigeDisplay = prestigeLevel > 0 ? 'Level ' + prestigeLevel : 'No Prestige';
var prestigeText = new Text2(prestigeDisplay, {
size: 26,
fill: prestigeLevel > 0 ? 0xFFB347 : 0x888888
});
prestigeText.anchor.set(0, 0.5);
prestigeText.x = 1450;
prestigeText.y = yPos;
self.entriesContainer.addChild(prestigeText);
// Activity indicator
var timeSinceUpdate = Date.now() - (cleanData.timestamps[idx] || 0);
var isActive = timeSinceUpdate < 300000; // Active within 5 minutes
if (isActive) {
var activeIndicator = new Text2('ā', {
size: 20,
fill: 0x00FF00
});
activeIndicator.anchor.set(0, 0.5);
activeIndicator.x = 350;
activeIndicator.y = yPos;
self.entriesContainer.addChild(activeIndicator);
}
self.entries.push(entryBg, rankText, nameText, cookieText, prestigeText);
if (isActive) {
self.entries.push(activeIndicator);
}
}
// Update scroll limits
self.maxScroll = Math.max(0, maxEntries * 90 - 1400);
self.scrollOffset = Math.max(0, Math.min(self.scrollOffset, self.maxScroll));
self.entriesContainer.y = -self.scrollOffset;
// Update scroll indicator
if (self.maxScroll > 0) {
self.scrollIndicator.setText('ā Swipe to scroll ⢠Showing ' + Math.min(16, maxEntries) + ' visible entries');
self.scrollIndicator.visible = true;
} else {
self.scrollIndicator.visible = false;
}
};
// Scrolling functionality
self.move = function (x, y, obj) {
if (self.isDragging && self.maxScroll > 0) {
var deltaY = y - self.lastY;
self.scrollOffset = Math.max(0, Math.min(self.scrollOffset - deltaY * 2, self.maxScroll));
self.entriesContainer.y = -self.scrollOffset;
self.lastY = y;
}
};
self.down = function (x, y, obj) {
if (y > 500 && y < 2300) {
// Only allow scrolling in the entries area
self.isDragging = true;
self.lastY = y;
}
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.open = function () {
self.isOpen = true;
self.scrollOffset = 0;
self.alpha = 0;
self.visible = true;
self.updateLeaderboard();
// Enhanced animation
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
// Animate title glow
tween(titleText, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Set up auto-refresh while leaderboard is open
self.refreshTimer = LK.setInterval(function () {
if (self.isOpen) {
self.updateLeaderboard();
}
}, 3000); // Refresh every 3 seconds while open
};
self.close = function () {
self.isOpen = false;
self.isDragging = false;
// Clear refresh timer when closing
if (self.refreshTimer) {
LK.clearInterval(self.refreshTimer);
self.refreshTimer = null;
}
// Stop title animation
tween.stop(titleText);
titleText.scaleX = 1;
titleText.scaleY = 1;
tween(self, {
alpha: 0,
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.visible = false;
self.scaleX = 1;
self.scaleY = 1;
}
});
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBg.down = handleClose;
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.visible = false;
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
// Modern gradient background with rich colors
var backgroundTop = self.attachAsset('mainMenuBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 1400
});
backgroundTop.tint = 0x2a1810; // Dark brown top
var backgroundBottom = self.attachAsset('mainMenuBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 1332,
y: 1400
});
backgroundBottom.tint = 0x4a2820; // Lighter brown bottom
// Animated background elements - floating cookies
self.floatingCookies = [];
for (var i = 0; i < 8; i++) {
var floatCookie = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
scaleX: 0.3 + Math.random() * 0.4,
scaleY: 0.3 + Math.random() * 0.4
});
floatCookie.alpha = 0.1 + Math.random() * 0.15;
floatCookie.rotationSpeed = (Math.random() - 0.5) * 0.02;
floatCookie.floatSpeed = 0.5 + Math.random() * 1.5;
self.floatingCookies.push(floatCookie);
}
// Central cookie showcase with enhanced visual effects
var cookieGlow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950,
scaleX: 3.2,
scaleY: 3.2
});
cookieGlow.tint = 0xFFFFAA;
cookieGlow.alpha = 0.15;
var centralCookie = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950,
scaleX: 2.8,
scaleY: 2.8
});
centralCookie.tint = 0xFFE4B5;
// Add cookie details with enhanced visibility
var cookieDetails = [{
asset: 'cookieHighlight',
x: -60,
y: -80,
scale: 1.8,
alpha: 0.4
}, {
asset: 'cookieChip1',
x: -70,
y: -40,
scale: 1.4,
alpha: 0.8
}, {
asset: 'cookieChip2',
x: 80,
y: 60,
scale: 1.2,
alpha: 0.8
}, {
asset: 'cookieChip3',
x: -30,
y: 90,
scale: 1.3,
alpha: 0.8
}, {
asset: 'cookieChip1',
x: 40,
y: -70,
scale: 1.2,
alpha: 0.8
}, {
asset: 'cookieChip2',
x: -90,
y: 30,
scale: 1.1,
alpha: 0.8
}];
for (var i = 0; i < cookieDetails.length; i++) {
var detail = cookieDetails[i];
var element = self.attachAsset(detail.asset, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + detail.x,
y: 950 + detail.y,
scaleX: detail.scale,
scaleY: detail.scale
});
element.alpha = detail.alpha;
}
// Modern title with enhanced styling and subtitle
var titleShadow = new Text2('COOKIE TAP EMPIRE', {
size: 88,
fill: 0x1a1a1a
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1026;
titleShadow.y = 352;
self.addChild(titleShadow);
var titleText = new Text2('COOKIE TAP EMPIRE', {
size: 88,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 350;
self.addChild(titleText);
var subtitleText = new Text2('THE ULTIMATE COOKIE CLICKING ADVENTURE', {
size: 32,
fill: 0xFFE4B5
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 420;
self.addChild(subtitleText);
// Simple white username box at middle top of screen
var usernameBg = self.attachAsset('usernameBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 200
});
usernameBg.tint = 0xffffff;
self.usernameDisplay = new Text2(getDisplayName(playerName) || 'Tap to set username', {
size: 28,
fill: playerName === 'NEO' ? 0xFF6B35 : 0x000000
});
self.usernameDisplay.anchor.set(0.5, 0.5);
self.usernameDisplay.x = 1024;
self.usernameDisplay.y = 200;
self.addChild(self.usernameDisplay);
// Add username status information display
self.usernameStatusDisplay = new Text2('', {
size: 16,
fill: 0x666666
});
self.usernameStatusDisplay.anchor.set(0.5, 0.5);
self.usernameStatusDisplay.x = 1024;
self.usernameStatusDisplay.y = 225;
self.addChild(self.usernameStatusDisplay);
// Enhanced visual feedback for username
self.usernameDisplay.originalTint = self.usernameDisplay.fill;
// Username editing functionality (keeping existing keyboard system)
self.editUsername = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (self.keyboardOverlay) return;
self.keyboardOverlay = self.addChild(LK.getAsset('leaderboardBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
}));
self.keyboardOverlay.alpha = 0.95;
self.keyboardOverlay.tint = 0x1a1a2e;
var inputPanel = self.keyboardOverlay.addChild(LK.getAsset('leaderboardPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.1,
scaleY: 1.0
}));
inputPanel.tint = 0x2a2a3a;
var titleText = new Text2('ENTER PLAYER NAME', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1000;
self.keyboardOverlay.addChild(titleText);
var instructionText = new Text2('Maximum 20 characters ⢠Leave blank for random name', {
size: 28,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1080;
self.keyboardOverlay.addChild(instructionText);
var inputBg = self.keyboardOverlay.addChild(LK.getAsset('leaderboardEntry', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1180,
scaleX: 1.2,
scaleY: 1.5
}));
inputBg.tint = 0x1a1a1a;
self.currentInput = playerName || '';
self.inputDisplay = new Text2(self.currentInput || 'Enter your name...', {
size: 44,
fill: self.currentInput ? 0xFFD700 : 0x888888
});
self.inputDisplay.anchor.set(0.5, 0.5);
self.inputDisplay.x = 1024;
self.inputDisplay.y = 1180;
self.keyboardOverlay.addChild(self.inputDisplay);
// Enhanced keyboard layout
var keyboardKeys = [['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'], ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], ['Z', 'X', 'C', 'V', 'B', 'N', 'M']];
var startY = 1320;
self.keyboardButtons = [];
for (var row = 0; row < keyboardKeys.length; row++) {
var rowKeys = keyboardKeys[row];
var rowWidth = rowKeys.length * 95;
var startX = 1024 - rowWidth / 2 + 47.5;
for (var col = 0; col < rowKeys.length; col++) {
var key = rowKeys[col];
var keyX = startX + col * 95;
var keyY = startY + row * 110;
var keyBorder = self.keyboardOverlay.addChild(LK.getAsset('leaderboardBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: keyX,
y: keyY,
scaleX: 0.22,
scaleY: 0.6
}));
keyBorder.tint = 0x4a4a5a;
var keyButton = self.keyboardOverlay.addChild(LK.getAsset('leaderboardButton', {
anchorX: 0.5,
anchorY: 0.5,
x: keyX,
y: keyY,
scaleX: 0.2,
scaleY: 0.5
}));
var keyText = new Text2(key, {
size: 36,
fill: 0xFFFFFF
});
keyText.anchor.set(0.5, 0.5);
keyText.x = keyX;
keyText.y = keyY;
self.keyboardOverlay.addChild(keyText);
keyButton.keyChar = key;
keyButton.down = function () {
if (self.currentInput.length < 20) {
self.currentInput += this.keyChar;
self.inputDisplay.setText(self.currentInput);
self.inputDisplay.fill = 0xFFD700;
}
};
self.keyboardButtons.push(keyButton);
}
}
// Enhanced control buttons
var spaceButton = self.keyboardOverlay.addChild(LK.getAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 350,
scaleX: 0.8,
scaleY: 0.6
}));
var spaceText = new Text2('SPACE', {
size: 28,
fill: 0xFFFFFF
});
spaceText.anchor.set(0.5, 0.5);
spaceText.x = 1024;
spaceText.y = startY + 350;
self.keyboardOverlay.addChild(spaceText);
spaceButton.down = function () {
if (self.currentInput.length < 20) {
self.currentInput += ' ';
self.inputDisplay.setText(self.currentInput);
self.inputDisplay.fill = 0xFFD700;
}
};
var backspaceButton = self.keyboardOverlay.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 - 250,
y: startY + 350,
scaleX: 0.4,
scaleY: 0.6
}));
var backspaceText = new Text2('ā« DELETE', {
size: 24,
fill: 0xFFFFFF
});
backspaceText.anchor.set(0.5, 0.5);
backspaceText.x = 1024 - 250;
backspaceText.y = startY + 350;
self.keyboardOverlay.addChild(backspaceText);
backspaceButton.down = function () {
if (self.currentInput.length > 0) {
self.currentInput = self.currentInput.slice(0, -1);
self.inputDisplay.setText(self.currentInput || 'Enter your name...');
self.inputDisplay.fill = self.currentInput ? 0xFFD700 : 0x888888;
}
};
var clearButton = self.keyboardOverlay.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + 250,
y: startY + 350,
scaleX: 0.4,
scaleY: 0.6
}));
var clearText = new Text2('CLEAR ALL', {
size: 24,
fill: 0xFFFFFF
});
clearText.anchor.set(0.5, 0.5);
clearText.x = 1024 + 250;
clearText.y = startY + 350;
self.keyboardOverlay.addChild(clearText);
clearButton.down = function () {
self.currentInput = '';
self.inputDisplay.setText('Enter your name...');
self.inputDisplay.fill = 0x888888;
};
// Confirm and cancel buttons
var confirmBorder = self.keyboardOverlay.addChild(LK.getAsset('playButtonBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 500,
scaleX: 1.2,
scaleY: 1.2
}));
var confirmButton = self.keyboardOverlay.addChild(LK.getAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: startY + 500,
scaleX: 1.0,
scaleY: 1.0
}));
var confirmText = new Text2('CONFIRM NAME', {
size: 32,
fill: 0xFFFFFF
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = 1024;
confirmText.y = startY + 500;
self.keyboardOverlay.addChild(confirmText);
confirmButton.down = function () {
self.confirmUsername();
};
var cancelButton = self.keyboardOverlay.addChild(LK.getAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
scaleX: 2.0,
scaleY: 2.0
}));
cancelButton.tint = 0x8B0000;
var cancelX1 = self.keyboardOverlay.addChild(LK.getAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
rotation: Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
}));
var cancelX2 = self.keyboardOverlay.addChild(LK.getAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 1000,
rotation: -Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
}));
cancelButton.down = function () {
self.closeKeyboard();
};
};
// Username confirmation and closing functions (keeping existing logic)
self.confirmUsername = function () {
var newUsername = self.currentInput.trim();
// Generate username if empty
if (!newUsername) {
newUsername = generateUniqueUsername();
}
// Enhanced validation
if (!isValidUsername(newUsername)) {
if (newUsername.length > 20) {
self.inputDisplay.setText('Too long! Maximum 20 characters');
} else if (newUsername.length === 0) {
self.inputDisplay.setText('Username cannot be empty');
} else {
self.inputDisplay.setText('Invalid characters in username');
}
self.inputDisplay.fill = 0xFF5555;
return;
}
// Check cooldown for existing users
if (playerName && playerName !== newUsername && !canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
var minutes = Math.floor(cooldownSeconds / 60);
var seconds = cooldownSeconds % 60;
self.inputDisplay.setText('Cooldown: ' + minutes + 'm ' + seconds + 's remaining');
self.inputDisplay.fill = 0xFF5555;
return;
}
// Check availability
if (isUsernameAvailable(newUsername) || newUsername === playerName) {
// Store previous username in history
if (playerName && playerName !== newUsername) {
var usernameHistory = storage.usernameHistory || [];
if (usernameHistory.indexOf(playerName) === -1) {
usernameHistory.push(playerName);
if (usernameHistory.length > 5) {
usernameHistory.shift(); // Keep only last 5 usernames
}
storage.usernameHistory = usernameHistory;
}
// Remove old username from leaderboard
var leaderboardNames = (storage.leaderboardNames || []).slice();
var leaderboardCookies = (storage.leaderboardCookies || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardNames.splice(i, 1);
leaderboardCookies.splice(i, 1);
leaderboardTimestamps.splice(i, 1);
leaderboardPrestiges.splice(i, 1);
break;
}
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardCookies = leaderboardCookies;
storage.leaderboardTimestamps = leaderboardTimestamps;
storage.leaderboardPrestiges = leaderboardPrestiges;
// Update cooldown timestamp
storage.lastUsernameChange = Date.now();
}
// Set new username with enhanced storage
playerName = newUsername;
storage.playerName = String(playerName);
storage.hasSetUsername = true;
// Update leaderboard and UI
updateLeaderboard();
self.updateUsername();
self.closeKeyboard();
playSound('buttonClick');
// Show success message
showFloatingNumber('Username set!', 1024, 500);
} else {
self.inputDisplay.setText('Username already taken!');
self.inputDisplay.fill = 0xFF5555;
}
};
self.closeKeyboard = function () {
if (self.keyboardOverlay) {
self.keyboardOverlay.destroy();
self.keyboardOverlay = null;
self.keyboardButtons = [];
self.inputDisplay = null;
self.currentInput = '';
}
};
// Make username clickable
usernameBg.down = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
tween.stop(usernameBg, {
tint: true
});
usernameBg.tint = 0xf0f0f0;
tween(usernameBg, {
tint: 0xffffff
}, {
duration: 200
});
self.editUsername();
};
self.usernameDisplay.down = function () {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
tween.stop(usernameBg, {
tint: true
});
usernameBg.tint = 0xf0f0f0;
tween(usernameBg, {
tint: 0xffffff
}, {
duration: 200
});
self.editUsername();
};
// Modern menu buttons with enhanced layout
var buttonSpacing = 140;
var buttonsStartY = 1400;
var buttons = [];
// Play button (primary action)
var playBorder = self.attachAsset('playButtonBorder', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY,
scaleX: 1.3,
scaleY: 1.3
});
playBorder.tint = 0x4CAF50;
var playButton = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY,
scaleX: 1.2,
scaleY: 1.2
});
playButton.tint = 0x2E7D32;
var playHighlight = self.attachAsset('playButtonHighlight', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonsStartY - 15,
scaleX: 1.1,
scaleY: 0.3
});
var playText = new Text2('šŖ START GAME', {
size: 40,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = buttonsStartY;
self.addChild(playText);
buttons.push({
border: playBorder,
button: playButton,
text: playText,
action: 'play'
});
// Secondary buttons in grid layout
var secondaryButtons = [{
name: 'LEADERBOARD',
icon: 'š',
border: 'leaderboardBorder',
button: 'leaderboardButton',
action: 'leaderboard',
pos: 0
}, {
name: 'SETTINGS',
icon: 'āļø',
border: 'settingsBorder',
button: 'settingsButton',
action: 'settings',
pos: 1
}, {
name: 'TUTORIAL',
icon: 'š',
border: 'tutorialBorder',
button: 'tutorialButton',
action: 'tutorial',
pos: 2
}];
var cols = 3;
var buttonWidth = 500;
var totalWidth = cols * buttonWidth;
var startX = 1024 - totalWidth / 2 + buttonWidth / 2;
for (var i = 0; i < secondaryButtons.length; i++) {
var btn = secondaryButtons[i];
var col = btn.pos % cols;
var buttonX = startX + col * buttonWidth;
var buttonY = buttonsStartY + 200;
var btnBorder = self.attachAsset(btn.border, {
anchorX: 0.5,
anchorY: 0.5,
x: buttonX,
y: buttonY,
scaleX: 1.1,
scaleY: 1.1
});
var btnButton = self.attachAsset(btn.button, {
anchorX: 0.5,
anchorY: 0.5,
x: buttonX,
y: buttonY
});
var btnText = new Text2(btn.icon + ' ' + btn.name, {
size: 28,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
btnText.x = buttonX;
btnText.y = buttonY;
self.addChild(btnText);
buttons.push({
border: btnBorder,
button: btnButton,
text: btnText,
action: btn.action
});
}
// Version and stats info
var versionText = new Text2('Cookie Tap Empire v2.1 ⢠Premium Cookie Experience', {
size: 24,
fill: 0x888888
});
versionText.anchor.set(0.5, 0.5);
versionText.x = 1024;
versionText.y = 2600;
self.addChild(versionText);
// Enhanced button handlers
function handlePlayClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
// Enhanced username generation for new players
if (!playerName || playerName.trim() === '' || !storage.hasSetUsername) {
playerName = generateUniqueUsername();
storage.playerName = String(playerName);
storage.hasSetUsername = false; // Mark as auto-generated
// Show helpful message for new players
if (!storage.hasSetUsername) {
showFloatingNumber('Auto-generated username: ' + playerName, 1024, 600);
showFloatingNumber('Change it anytime in the main menu!', 1024, 650);
}
}
gameStarted = true;
cookieCounterBg.visible = true;
cookieDisplay.visible = true;
cpsCounterBg.visible = true;
cpsDisplay.visible = true;
prestigeDisplay.visible = true;
self.close();
}
function handleLeaderboardClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
leaderboard.open();
}
function handleSettingsClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
settingsMenu.open();
}
function handleTutorialClick() {
if (shop && shop.isOpen) return; // Block if shop is open
if (!isMuted) LK.getSound('buttonClick').play();
showTutorial();
}
// Assign handlers to all button elements
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
var handler = null;
switch (btn.action) {
case 'play':
handler = handlePlayClick;
break;
case 'leaderboard':
handler = handleLeaderboardClick;
break;
case 'settings':
handler = handleSettingsClick;
break;
case 'tutorial':
handler = handleTutorialClick;
break;
}
if (handler) {
btn.border.down = handler;
btn.button.down = handler;
btn.text.down = handler;
}
}
// Enhanced username display update function with improved status indicators
self.updateUsername = function () {
var hasSetName = storage.hasSetUsername && playerName && playerName.trim() !== '';
var displayName;
var statusIndicator = '';
if (hasSetName) {
displayName = getDisplayName(playerName);
// Add detailed status indicators
if (!canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
if (cooldownSeconds > 0) {
var minutes = Math.floor(cooldownSeconds / 60);
var seconds = cooldownSeconds % 60;
statusIndicator = ' ā±ļø ' + minutes + 'm ' + seconds + 's';
}
} else {
// Show that username can be changed
statusIndicator = ' āļø';
}
} else {
displayName = 'Tap to set username';
statusIndicator = ' š';
}
self.usernameDisplay.setText(displayName + statusIndicator);
// Enhanced color coding with better visual hierarchy - adjusted for white background
if (!hasSetName) {
self.usernameDisplay.fill = 0x666666; // Dark gray for better visibility on white
} else if (playerName === 'NEO') {
self.usernameDisplay.fill = 0xFF6B35; // Special owner color
} else if (playerName && playerName.toLowerCase().indexOf('cookie') !== -1) {
self.usernameDisplay.fill = 0xCC8800; // Darker orange for cookie-themed names
} else if (storage.isOwner) {
self.usernameDisplay.fill = 0xFF6B35; // Special color for owners
} else {
self.usernameDisplay.fill = 0x000000; // Black text for regular users on white background
}
self.usernameDisplay.originalTint = self.usernameDisplay.fill;
// Enhanced visual effects based on username status
if (!hasSetName) {
// Pulsing effect for unset usernames
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
tween(self.usernameDisplay, {
alpha: 0.7,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (!canChangeUsername()) {
// Subtle animation for cooldown period
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
self.usernameDisplay.alpha = 1;
self.usernameDisplay.scaleX = 1;
self.usernameDisplay.scaleY = 1;
// Fade status indicator
tween(self.usernameDisplay, {
alpha: 0.8
}, {
duration: 800,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else {
// Normal state - no animation, full visibility
tween.stop(self.usernameDisplay, {
alpha: true,
scaleX: true,
scaleY: true
});
self.usernameDisplay.alpha = 1;
self.usernameDisplay.scaleX = 1;
self.usernameDisplay.scaleY = 1;
}
// Update status information display
var statusText = '';
if (hasSetName) {
var totalChanges = (storage.usernameHistory || []).length;
if (totalChanges > 0) {
statusText = 'Changed ' + totalChanges + ' time' + (totalChanges === 1 ? '' : 's');
} else {
statusText = playerName === storage.playerName && storage.hasSetUsername ? 'Custom username' : 'Auto-generated username';
}
if (!canChangeUsername()) {
var cooldownSeconds = getUsernameChangeCooldown();
if (cooldownSeconds > 0) {
statusText += ' ⢠Next change available in ' + Math.ceil(cooldownSeconds / 60) + ' min';
} else {
statusText += ' ⢠Can change now';
}
} else {
statusText += ' ⢠Can change anytime';
}
} else {
statusText = 'Click above to create your unique username ⢠Free to change';
}
self.usernameStatusDisplay.setText(statusText);
// Update status text color based on state - adjusted for white background
if (!hasSetName) {
self.usernameStatusDisplay.fill = 0x666666; // Encourage action
} else if (!canChangeUsername()) {
self.usernameStatusDisplay.fill = 0xFF0000; // Cooldown warning - red text
} else {
self.usernameStatusDisplay.fill = 0x666666; // Normal status
}
};
// Animation system for floating elements
self.update = function () {
// Animate floating cookies
for (var i = 0; i < self.floatingCookies.length; i++) {
var cookie = self.floatingCookies[i];
cookie.rotation += cookie.rotationSpeed;
cookie.y -= cookie.floatSpeed;
if (cookie.y < -100) {
cookie.y = 2832;
cookie.x = Math.random() * 2048;
}
}
// Gentle pulsing animation for central cookie
var pulseScale = 1 + Math.sin(LK.ticks * 0.02) * 0.05;
centralCookie.scaleX = 2.8 * pulseScale;
centralCookie.scaleY = 2.8 * pulseScale;
cookieGlow.scaleX = 3.2 * pulseScale;
cookieGlow.scaleY = 3.2 * pulseScale;
// Title shimmer effect
var shimmer = 0.8 + Math.sin(LK.ticks * 0.03) * 0.2;
titleText.alpha = shimmer;
};
// Close animation
self.close = function () {
tween(self, {
alpha: 0,
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.visible = false;
self.scaleX = 1;
self.scaleY = 1;
}
});
};
return self;
});
var MiniCookie = Container.expand(function () {
var self = Container.call(this);
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -8,
y: -5
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: 10,
y: 8
});
// Random movement direction
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = -2 - Math.random() * 4;
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.gravity = 0.15;
self.lifetime = 0;
self.maxLifetime = 120; // 2 seconds at 60fps
self.update = function () {
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Update rotation
self.rotation += self.rotationSpeed;
// Fade out over time
self.lifetime++;
if (self.lifetime > self.maxLifetime * 0.7) {
self.alpha = 1 - (self.lifetime - self.maxLifetime * 0.7) / (self.maxLifetime * 0.3);
}
// Remove when lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
// Powerup types with different effects
var powerupTypes = [{
name: 'Speed Boost',
color: 0x00FF00,
multiplier: 2,
duration: 15000
}, {
name: 'Golden Rush',
color: 0xFFD700,
multiplier: 3,
duration: 10000
}, {
name: 'Cookie Frenzy',
color: 0xFF6347,
multiplier: 5,
duration: 8000
}, {
name: 'Mega Power',
color: 0xFF00FF,
multiplier: 10,
duration: 5000
}];
// Select random powerup type
self.powerupData = powerupTypes[Math.floor(Math.random() * powerupTypes.length)];
self.lifetime = 0;
self.maxLifetime = 900; // 15 seconds at 60fps
// Create powerup visual with pulsing effect
var background = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
background.tint = self.powerupData.color;
// Add glow effect
var glow = self.attachAsset('cookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
glow.tint = self.powerupData.color;
glow.alpha = 0.3;
// Powerup text
var powerupText = new Text2(self.powerupData.name, {
size: 28,
fill: 0xFFFFFF
});
powerupText.anchor.set(0.5, 0.5);
powerupText.y = 80;
self.addChild(powerupText);
// Duration text
var durationText = new Text2('+' + self.powerupData.multiplier + 'x CPS', {
size: 24,
fill: 0xFFFFFF
});
durationText.anchor.set(0.5, 0.5);
durationText.y = 110;
self.addChild(durationText);
// Start pulsing animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Glow pulsing
tween(glow, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.6
}, {
duration: 800,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
self.update = function () {
self.lifetime++;
// Fade out in last 3 seconds
if (self.lifetime > self.maxLifetime - 180) {
var fadeProgress = (self.lifetime - (self.maxLifetime - 180)) / 180;
self.alpha = 1 - fadeProgress;
}
// Remove when expired
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
self.collect = function () {
// Apply powerup effect
activePowerups.push({
name: self.powerupData.name,
multiplier: self.powerupData.multiplier,
duration: self.powerupData.duration,
timeLeft: self.powerupData.duration
});
// Visual feedback
showFloatingNumber(self.powerupData.name + ' ACTIVATED!', self.x, self.y - 50);
showFloatingNumber('+' + self.powerupData.multiplier + 'x CPS for ' + Math.floor(self.powerupData.duration / 1000) + 's', self.x, self.y - 100);
// Screen flash effect
LK.effects.flashScreen(self.powerupData.color, 500);
// Play sound
playSound('goldenCookie', 1.2);
// Animate collection
tween.stop(self);
tween(self, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
var PrestigeButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('prestigeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
var titleText = new Text2('ASCEND', {
size: 64,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
self.addChild(titleText);
self.updateDisplay = function () {
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
var requiredUpgrades = 100 + prestigeLevel * 50;
var hasEnoughUpgrades = totalUpgrades >= requiredUpgrades;
var requiredCookies = 1000000 + prestigeLevel * 5000000; // 1M base, +5M per prestige
canPrestige = allTimeCookies >= requiredCookies && hasEnoughUpgrades;
if (canPrestige) {
background.tint = 0xFF4500;
background.alpha = 1;
titleText.setText('PRESTIGE');
} else {
background.tint = 0x666666;
background.alpha = 0.5;
titleText.setText('PRESTIGE');
}
};
self.showPrestigeMenu = function () {
if (!prestigeMenu) {
prestigeMenu = game.addChild(new PrestigeMenu());
prestigeMenu.x = 1024;
prestigeMenu.y = 1366;
}
prestigeMenu.open();
};
self.down = function (x, y, obj) {
self.showPrestigeMenu();
};
return self;
});
var PrestigeMenu = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
// Menu border and background
var border = self.attachAsset('prestigeBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
var background = self.attachAsset('prestigePanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
var titleText = new Text2('ASCENSION', {
size: 52,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -150;
self.addChild(titleText);
self.reqText = new Text2('', {
size: 42,
fill: 0xFFFFFF
});
self.reqText.anchor.set(0.5, 0.5);
self.reqText.y = -80;
self.addChild(self.reqText);
// Prestige action button
var actionBtn = self.attachAsset('prestigeButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 120,
scaleX: 1.4,
scaleY: 1.4
});
self.actionText = new Text2('ASCEND', {
size: 36,
fill: 0xFFFFFF
});
self.actionText.anchor.set(0.5, 0.5);
self.actionText.y = 120;
self.addChild(self.actionText);
// Close button
var closeBtn = self.attachAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 320,
y: -180
});
var closeText = new Text2('X', {
size: 28,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 320;
closeText.y = -180;
self.addChild(closeText);
self.updateDisplay = function () {
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
var requiredUpgrades = 100 + prestigeLevel * 50;
var hasEnoughUpgrades = totalUpgrades >= requiredUpgrades;
var requiredCookies = 1000000 + prestigeLevel * 5000000;
var hasEnoughCookies = allTimeCookies >= requiredCookies;
var nextPrestigeLevel = prestigeLevel + 1;
self.reqText.setText('Level ' + nextPrestigeLevel + ' Requirements:\n\n' + requiredUpgrades + ' upgrades (' + totalUpgrades + '/' + requiredUpgrades + ')\n\n' + formatNumber(requiredCookies) + ' cookies (' + formatNumber(Math.floor(allTimeCookies)) + '/' + formatNumber(requiredCookies) + ')');
canPrestige = hasEnoughUpgrades && hasEnoughCookies;
if (canPrestige) {
actionBtn.tint = 0xFF4500;
actionBtn.alpha = 1;
self.actionText.setText('ASCEND');
} else {
actionBtn.tint = 0x666666;
actionBtn.alpha = 0.5;
self.actionText.setText('REQUIREMENTS NOT MET');
}
};
self.prestige = function () {
if (!canPrestige) return;
// Reset game state
cookies = 0;
totalCPS = 0;
for (var i = 0; i < buildings.length; i++) {
buildings[i].count = 0;
buildings[i].cost = buildings[i].baseCost;
}
// Increase prestige
prestigeLevel++;
prestigeBonus = prestigeLevel * 0.1;
allTimeCookies = 0;
canPrestige = false;
// Apply prestige bonus to tap multiplier
tapMultiplier = 1 + prestigeBonus;
playSound('prestige', 1.2);
updateDisplay();
saveGame();
// Flash effect and close menu
LK.effects.flashScreen(0xFFD700, 1000);
self.close();
};
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
self.updateDisplay();
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
actionBtn.down = function () {
self.prestige();
};
self.actionText.down = function () {
self.prestige();
};
closeBtn.down = function () {
self.close();
};
closeText.down = function () {
self.close();
};
self.visible = false;
return self;
});
var RainCookie = Container.expand(function () {
var self = Container.call(this);
// Create small cookie for rain effect
var cookieGraphics = self.attachAsset('fallingCookie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + Math.random() * 0.2,
// Random size between 0.3-0.5
scaleY: 0.3 + Math.random() * 0.2
});
// Add small chocolate chips for detail
var chip1 = self.attachAsset('cookieChip1', {
anchorX: 0.5,
anchorY: 0.5,
x: -5 + Math.random() * 10,
y: -5 + Math.random() * 10,
scaleX: 0.8,
scaleY: 0.8
});
var chip2 = self.attachAsset('cookieChip2', {
anchorX: 0.5,
anchorY: 0.5,
x: -5 + Math.random() * 10,
y: -5 + Math.random() * 10,
scaleX: 0.6,
scaleY: 0.6
});
// Set random properties for varied falling effect
self.fallSpeed = 2 + Math.random() * 3; // Random fall speed 2-5
self.rotationSpeed = (Math.random() - 0.5) * 0.08; // Random rotation
self.sway = Math.random() * 2; // Random horizontal sway
self.swaySpeed = 0.02 + Math.random() * 0.02;
self.swayOffset = Math.random() * Math.PI * 2;
// Make them semi-transparent for background effect
self.alpha = 0.4 + Math.random() * 0.3; // Random transparency 0.4-0.7
// Tint with slight variations for visual interest
var tints = [0xFFE4B5, 0xDEB887, 0xF4A460, 0xD2B48C, 0xBC9A6A];
cookieGraphics.tint = tints[Math.floor(Math.random() * tints.length)];
self.startX = self.x; // Remember starting X position for sway calculation
self.update = function () {
// Fall downward
self.y += self.fallSpeed;
// Add horizontal swaying motion using smooth sine wave
var swayAmount = Math.sin(LK.ticks * self.swaySpeed + self.swayOffset) * self.sway;
self.x = self.startX + swayAmount;
// Rotate as it falls (already animated by tween for smoothness)
self.rotation += self.rotationSpeed;
// Add subtle scale pulsing for more life
var pulseScale = 1 + Math.sin(LK.ticks * 0.05 + self.swayOffset) * 0.1;
var baseScale = 0.3 + Math.random() * 0.2; // Use original scale calculation
cookieGraphics.scaleX = baseScale * pulseScale;
cookieGraphics.scaleY = baseScale * pulseScale;
// Remove when off screen (with some buffer)
if (self.y > 2800) {
// Add exit animation with tween
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
var background = self.attachAsset('settingsPanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.1
});
var border = self.attachAsset('settingsBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.1
});
var titleText = new Text2('SETTINGS', {
size: 64,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
self.addChild(titleText);
// Master volume section
var masterVolumeLabel = new Text2('š MASTER VOLUME', {
size: 36,
fill: 0xFFFFFF
});
masterVolumeLabel.anchor.set(0.5, 0.5);
masterVolumeLabel.y = -150;
self.addChild(masterVolumeLabel);
// Master mute button
var muteButton = self.attachAsset('muteButton', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
scaleX: 1.2,
scaleY: 1.2
});
self.muteText = new Text2('SOUND: ON', {
size: 36,
fill: 0xFFFFFF
});
self.muteText.anchor.set(0.5, 0.5);
self.muteText.y = -100;
self.addChild(self.muteText);
// Music volume section
var musicSection = new Text2('šµ MUSIC VOLUME', {
size: 32,
fill: 0xFFD700
});
musicSection.anchor.set(0.5, 0.5);
musicSection.y = -30;
self.addChild(musicSection);
var volumeSlider = self.attachAsset('volumeSlider', {
anchorX: 0.5,
anchorY: 0.5,
y: 10,
scaleX: 1.2,
scaleY: 1.5
});
// Initialize with proper volume calculation
var initialVolume = storage.musicVolume !== undefined ? storage.musicVolume : 0.8;
var handleX = initialVolume * 380 - 190; // Adjusted for larger slider
self.volumeHandle = self.attachAsset('volumeHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: handleX,
y: 10,
scaleX: 1.3,
scaleY: 1.3
});
// Sound effects section
var soundSection = new Text2('š SOUND EFFECTS VOLUME', {
size: 32,
fill: 0xFFD700
});
soundSection.anchor.set(0.5, 0.5);
soundSection.y = 70;
self.addChild(soundSection);
var soundVolumeSlider = self.attachAsset('volumeSlider', {
anchorX: 0.5,
anchorY: 0.5,
y: 110,
scaleX: 1.2,
scaleY: 1.5
});
var initialSoundVolume = storage.soundVolume !== undefined ? storage.soundVolume : 0.7;
var soundHandleX = initialSoundVolume * 380 - 190; // Adjusted for larger slider
self.soundVolumeHandle = self.attachAsset('volumeHandle', {
anchorX: 0.5,
anchorY: 0.5,
x: soundHandleX,
y: 110,
scaleX: 1.3,
scaleY: 1.3
});
// Sound effects toggle
var soundEffectsButton = self.attachAsset('muteButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 180,
scaleX: 1.1,
scaleY: 1.1
});
self.soundEffectsText = new Text2('SOUND EFFECTS: ON', {
size: 32,
fill: 0xFFFFFF
});
self.soundEffectsText.anchor.set(0.5, 0.5);
self.soundEffectsText.y = 180;
self.addChild(self.soundEffectsText);
// Close button enhanced
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
scaleX: 2.0,
scaleY: 2.0
});
closeBtn.tint = 0xFF4444;
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
rotation: Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: -250,
rotation: -Math.PI / 4,
scaleX: 2.0,
scaleY: 2.0
});
self.updateMuteDisplay = function () {
if (isMuted) {
self.muteText.setText('SOUND: OFF');
muteButton.tint = 0xFF5722;
LK.stopMusic();
} else {
self.muteText.setText('SOUND: ON');
muteButton.tint = 0x4CAF50;
var currentVolume = storage.musicVolume || 0.8;
LK.playMusic('bgmusic', {
loop: true,
volume: currentVolume
});
}
};
muteButton.down = function () {
isMuted = !isMuted;
storage.isMuted = isMuted;
self.updateMuteDisplay();
if (!isMuted) LK.getSound('buttonClick').play();
};
self.muteText.down = function () {
isMuted = !isMuted;
storage.isMuted = isMuted;
self.updateMuteDisplay();
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
// Sound effects toggle functionality
self.updateSoundEffectsDisplay = function () {
if (storage.enableSoundEffects) {
self.soundEffectsText.setText('SOUND EFFECTS: ON');
soundEffectsButton.tint = 0x4CAF50;
} else {
self.soundEffectsText.setText('SOUND EFFECTS: OFF');
soundEffectsButton.tint = 0xFF5722;
}
};
soundEffectsButton.down = function () {
storage.enableSoundEffects = !storage.enableSoundEffects;
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
self.soundEffectsText.down = function () {
storage.enableSoundEffects = !storage.enableSoundEffects;
self.updateSoundEffectsDisplay();
if (!isMuted && storage.enableSoundEffects) LK.getSound('buttonClick').play();
};
// Sound volume handle functionality
self.soundVolumeHandle.down = function () {
self.draggingSoundVolume = true;
};
// Volume slider functionality
self.volumeHandle.down = function () {
self.draggingVolume = true;
};
self.move = function (x, y, obj) {
if (self.draggingVolume) {
var localX = Math.max(-190, Math.min(190, x));
self.volumeHandle.x = localX;
var volume = (localX + 190) / 380;
storage.musicVolume = volume;
// Actually update the music volume in real-time
if (!isMuted) {
LK.stopMusic();
LK.playMusic('bgmusic', {
loop: true,
volume: volume
});
}
}
if (self.draggingSoundVolume) {
var localX = Math.max(-190, Math.min(190, x));
self.soundVolumeHandle.x = localX;
var soundVolume = (localX + 190) / 380;
storage.soundVolume = soundVolume;
}
};
self.up = function (x, y, obj) {
self.draggingVolume = false;
self.draggingSoundVolume = false;
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
self.updateMuteDisplay();
self.updateSoundEffectsDisplay();
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
self.visible = false;
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.currentPage = 0;
self.itemsPerPage = 6;
// Full screen background
var background = self.attachAsset('shopFullscreen', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
// Header
var header = self.attachAsset('shopHeader', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 150
});
var headerText = new Text2('SHOP', {
size: 64,
fill: 0xFFD700
});
headerText.anchor.set(0.5, 0.5);
headerText.x = 1024;
headerText.y = 75;
self.addChild(headerText);
// Close button
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
scaleX: 1.5,
scaleY: 1.5
});
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
rotation: Math.PI / 4,
scaleX: 1.5,
scaleY: 1.5
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 75,
rotation: -Math.PI / 4,
scaleX: 1.5,
scaleY: 1.5
});
// Page navigation
self.prevButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2500,
scaleX: 1.5,
scaleY: 0.8
});
self.nextButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 2500,
scaleX: 1.5,
scaleY: 0.8
});
self.prevText = new Text2('ā PREV', {
size: 36,
fill: 0xFFFFFF
});
self.prevText.anchor.set(0.5, 0.5);
self.prevText.x = 200;
self.prevText.y = 2500;
self.addChild(self.prevText);
self.nextText = new Text2('NEXT ā', {
size: 36,
fill: 0xFFFFFF
});
self.nextText.anchor.set(0.5, 0.5);
self.nextText.x = 1848;
self.nextText.y = 2500;
self.addChild(self.nextText);
// Page indicator
self.pageText = new Text2('Page 1 of 1', {
size: 32,
fill: 0xCCCCCC
});
self.pageText.anchor.set(0.5, 0.5);
self.pageText.x = 1024;
self.pageText.y = 2500;
self.addChild(self.pageText);
// Item slots
self.itemSlots = [];
self.createItemSlots = function () {
// Clear existing slots
for (var i = 0; i < self.itemSlots.length; i++) {
self.itemSlots[i].destroy();
}
self.itemSlots = [];
var cols = 2;
var rows = 3;
var slotWidth = 900;
var slotHeight = 320;
var startX = 1024 - cols * slotWidth / 2 + slotWidth / 2;
var startY = 300;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
var slotIndex = row * cols + col;
var x = startX + col * slotWidth;
var y = startY + row * slotHeight;
var slot = self.addChild(new ShopItem(x, y, slotIndex));
self.itemSlots.push(slot);
}
}
};
self.updatePage = function () {
var totalPages = Math.ceil(buildings.length / self.itemsPerPage);
// Update page indicator
self.pageText.setText('Page ' + (self.currentPage + 1) + ' of ' + totalPages);
// Update navigation buttons
self.prevButton.alpha = self.currentPage > 0 ? 1 : 0.3;
self.nextButton.alpha = self.currentPage < totalPages - 1 ? 1 : 0.3;
self.prevText.alpha = self.currentPage > 0 ? 1 : 0.3;
self.nextText.alpha = self.currentPage < totalPages - 1 ? 1 : 0.3;
// Update item slots
for (var i = 0; i < self.itemSlots.length; i++) {
var slot = self.itemSlots[i];
var buildingIndex = self.currentPage * self.itemsPerPage + i;
if (buildingIndex < buildings.length) {
slot.setBuilding(buildings[buildingIndex]);
slot.visible = true;
} else {
slot.visible = false;
}
}
};
self.prevPage = function () {
if (self.currentPage > 0) {
self.currentPage--;
self.updatePage();
if (!isMuted) LK.getSound('buttonClick').play();
}
};
self.nextPage = function () {
var totalPages = Math.ceil(buildings.length / self.itemsPerPage);
if (self.currentPage < totalPages - 1) {
self.currentPage++;
self.updatePage();
if (!isMuted) LK.getSound('buttonClick').play();
}
};
self.open = function () {
self.isOpen = true;
self.currentPage = 0;
self.alpha = 0;
self.visible = true;
// Hide prestige button when shop opens
prestigeButton.visible = false;
self.createItemSlots();
self.updatePage();
tween(self, {
alpha: 1
}, {
duration: 300
});
if (!isMuted) LK.getSound('menuOpen').play();
};
self.close = function () {
self.isOpen = false;
// Show prestige button when shop closes
prestigeButton.visible = true;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
if (!isMuted) LK.getSound('buttonClick').play();
};
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.prevButton.down = self.prevPage;
self.prevText.down = self.prevPage;
self.nextButton.down = self.nextPage;
self.nextText.down = self.nextPage;
self.visible = false;
return self;
});
var ShopItem = Container.expand(function (x, y, slotIndex) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.building = null;
// Item background
var background = self.attachAsset('upgradeSlot', {
anchorX: 0.5,
anchorY: 0.5,
width: 850,
height: 280
});
// Icon area
var iconBg = self.attachAsset('upgradeIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: 0,
scaleX: 2,
scaleY: 2
});
// Text elements
self.nameText = new Text2('', {
size: 56,
fill: 0xFFFFFF
});
self.nameText.anchor.set(0, 0.5);
self.nameText.x = -100;
self.nameText.y = -70;
self.addChild(self.nameText);
self.costText = new Text2('', {
size: 44,
fill: 0xFFFF00
});
self.costText.anchor.set(0, 0.5);
self.costText.x = -100;
self.costText.y = -20;
self.addChild(self.costText);
self.ownedText = new Text2('', {
size: 40,
fill: 0xCCCCCC
});
self.ownedText.anchor.set(0, 0.5);
self.ownedText.x = -100;
self.ownedText.y = 30;
self.addChild(self.ownedText);
self.cpsText = new Text2('', {
size: 42,
fill: 0x90EE90
});
self.cpsText.anchor.set(0, 0.5);
self.cpsText.x = -100;
self.cpsText.y = 80;
self.addChild(self.cpsText);
// Buy button
self.buyButton = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 60,
scaleX: 1.5,
scaleY: 0.8
});
self.buyText = new Text2('BUY', {
size: 36,
fill: 0xFFFFFF
});
self.buyText.anchor.set(0.5, 0.5);
self.buyText.x = 300;
self.buyText.y = 60;
self.addChild(self.buyText);
self.setBuilding = function (building) {
self.building = building;
self.updateDisplay();
};
self.updateDisplay = function () {
if (!self.building) return;
self.nameText.setText(self.building.buildingType.toUpperCase());
self.costText.setText('Cost: ' + formatNumber(self.building.cost));
self.ownedText.setText('Owned: ' + self.building.count);
self.cpsText.setText('+' + formatNumber(self.building.cookiesPerSecond) + ' CPS');
// Update affordability
var canAfford = cookies >= self.building.cost;
background.tint = canAfford ? 0x4169E1 : 0x666666;
iconBg.tint = canAfford ? 0xFFFFFF : 0x888888;
self.buyButton.tint = canAfford ? 0x4CAF50 : 0x666666;
self.buyButton.alpha = canAfford ? 1 : 0.5;
};
self.purchase = function () {
if (self.building && cookies >= self.building.cost) {
self.building.purchase();
self.updateDisplay();
}
};
self.down = function () {
self.purchase();
};
self.buyButton.down = function () {
self.purchase();
};
self.buyText.down = function () {
self.purchase();
};
return self;
});
var TutorialScreen = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
// Fullscreen background
var background = self.attachAsset('tutorialBg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x1a1a2e;
var titleText = new Text2('TUTORIAL', {
size: 72,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
var tutorialText = new Text2('HOW TO PLAY COOKIE TAP EMPIRE:\n\n⢠Tap the large cookie to earn cookies\n⢠Use earned cookies to buy upgrades from the shop\n⢠Each upgrade increases your cookies per second (CPS)\n⢠Collect falling cookies for bonus rewards\n⢠Set your username to appear on the leaderboard\n⢠Username changes have a 5-minute cooldown\n⢠Reach 1M+ cookies and 100+ upgrades to unlock prestige\n⢠Prestige requirements increase moderately with each level\n⢠Prestiging resets your progress but gives permanent bonuses\n⢠Higher prestige levels provide greater production bonuses\n⢠Check the leaderboard to see how you rank against others!', {
size: 36,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1200;
self.addChild(tutorialText);
var continueButton = self.attachAsset('continueButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2000,
scaleX: 1.5,
scaleY: 1.5
});
var continueGlow = self.attachAsset('continueGlow', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1980
});
var continueText = new Text2('GOT IT!', {
size: 42,
fill: 0xFFFFFF
});
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 2000;
self.addChild(continueText);
// Close button
var closeBtn = self.attachAsset('closeButtonPixel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400
});
var closeX1 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400,
rotation: Math.PI / 4
});
var closeX2 = self.attachAsset('closeButtonX', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 400,
rotation: -Math.PI / 4
});
function handleClose() {
if (!isMuted) LK.getSound('buttonClick').play();
self.close();
}
continueButton.down = handleClose;
continueText.down = handleClose;
closeBtn.down = handleClose;
closeX1.down = handleClose;
closeX2.down = handleClose;
self.open = function () {
self.isOpen = true;
self.alpha = 0;
self.visible = true;
tween(self, {
alpha: 1
}, {
duration: 300
});
};
self.close = function () {
self.isOpen = false;
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
};
self.visible = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Enhanced Settings and Menu Assets
// Enhanced Falling Cookie Assets
// Enhanced Cosmic/Endgame Assets
// Enhanced Ultra-Advanced Assets
// Enhanced Cosmic Building Assets
// Enhanced Special Building Assets
// Enhanced Advanced Building Assets
// Enhanced Menu Assets
// Enhanced Prestige Assets
// Enhanced Button Assets
// Enhanced Shop and UI Assets
// Enhanced Building Assets - More distinctive and detailed
// Enhanced UI Elements - More polished and professional
// Enhanced Cookie Assets - More detailed and visually appealing
// Tutorial pixel art
// Settings pixel art
// Leaderboard pixel art
// Menu and dialog pixel art
// Building pixel art textures
// Shop and upgrade pixel art
// Main menu pixel art
// HUD and UI pixel art
// Pixel art cookie assets
// Menu buttons
// UI Elements
// Building pixel textures
// Custom pixel-style cookie textures
// Game state variables
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var gameStarted = storage.gameStarted || false;
var isMuted = storage.isMuted || false;
var fallingCookies = [];
var miniCookies = [];
var playerName = storage.playerName || '';
// Enhanced username validation function
function isUsernameAvailable(username) {
if (!username || username.trim() === '') return false;
var trimmedUsername = username.trim();
var leaderboardNames = storage.leaderboardNames || [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === trimmedUsername) {
return false;
}
}
return true;
}
// Enhanced username validation with content filtering
function isValidUsername(username) {
if (!username || typeof username !== 'string') return false;
var trimmed = username.trim();
if (trimmed.length === 0 || trimmed.length > 20) return false;
// Check for inappropriate content (basic filtering)
var blockedWords = ['admin', 'mod', 'owner', 'system', 'null', 'undefined', 'test'];
var lowerTrimmed = trimmed.toLowerCase();
for (var i = 0; i < blockedWords.length; i++) {
if (lowerTrimmed.indexOf(blockedWords[i]) !== -1) return false;
}
// Check for only spaces or special characters
if (!/^[a-zA-Z0-9\s_-]+$/.test(trimmed)) return false;
if (/^\s*$/.test(trimmed)) return false;
return true;
}
// Generate unique username with enhanced algorithm
function generateUniqueUsername() {
var attempts = 0;
var maxAttempts = 100;
var prefixes = ['Cookie', 'Sweet', 'Sugar', 'Candy', 'Honey', 'Maple', 'Vanilla', 'Caramel', 'Cocoa', 'Mint'];
var suffixes = ['Baker', 'Master', 'Chef', 'Hero', 'Legend', 'Pro', 'Star', 'King', 'Queen', 'Ace'];
do {
var username;
if (attempts < 50) {
// First 50 attempts: use creative combinations
var prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
var suffix = suffixes[Math.floor(Math.random() * suffixes.length)];
var number = Math.floor(Math.random() * 999) + 1;
username = prefix + suffix + number;
} else {
// Fallback: simple Player + number
username = 'Player' + Math.floor(Math.random() * 99999 + 1);
}
attempts++;
} while (!isUsernameAvailable(username) && attempts < maxAttempts);
if (attempts >= maxAttempts) {
// Emergency fallback
username = 'Player' + Date.now().toString().slice(-5);
}
return username;
}
// Get display name with enhanced formatting
function getDisplayName(name) {
if (!name) return 'Anonymous';
if (name === 'NEO') {
return 'š [OWNER] ' + name;
}
// Add special formatting for certain usernames
if (name.toLowerCase().indexOf('cookie') !== -1) {
return 'šŖ ' + name;
}
if (storage.isOwner && name === playerName) {
return 'ā ' + name;
}
return name;
}
// Username change cooldown check
function canChangeUsername() {
var lastChange = storage.lastUsernameChange || 0;
var cooldownTime = 300000; // 5 minutes cooldown
return Date.now() - lastChange > cooldownTime;
}
// Get time remaining for username change
function getUsernameChangeCooldown() {
var lastChange = storage.lastUsernameChange || 0;
var cooldownTime = 300000; // 5 minutes
var remaining = cooldownTime - (Date.now() - lastChange);
if (remaining <= 0) return 0;
return Math.ceil(remaining / 1000); // Return seconds
}
// Username input function
function requestUsername() {
var username = prompt('Enter your username for the leaderboard:') || '';
if (username.length > 0 && username.length <= 20) {
if (isUsernameAvailable(username) || username === playerName) {
playerName = username;
try {
// Store as simple string literal to avoid storage restrictions
var nameToStore = String(playerName);
storage.playerName = nameToStore;
} catch (e) {
console.log('Storage not available for username save');
}
return true;
} else {
alert('Username already taken! Please choose another username.');
return requestUsername();
}
} else if (username.length > 20) {
alert('Username too long! Maximum 20 characters.');
return requestUsername();
}
return false;
}
// Click detection for auto-clicker prevention
var clickTimes = [];
var isWarned = false;
var clicksBlocked = false;
// Achievement system
var achievements = [{
id: 'first_cookie',
name: 'First Cookie',
desc: 'Click your first cookie',
condition: function condition() {
return allTimeCookies >= 1;
},
reward: 10,
unlocked: false
}, {
id: 'cookie_clicker',
name: 'Cookie Clicker',
desc: 'Click 100 times',
condition: function condition() {
return totalClicks >= 100;
},
reward: 50,
unlocked: false
}, {
id: 'baker_dozen',
name: "Baker's Dozen",
desc: 'Have 13 buildings total',
condition: function condition() {
var total = 0;
for (var i = 0; i < buildings.length; i++) total += buildings[i].count;
return total >= 13;
},
reward: 1000,
unlocked: false
}, {
id: 'millionaire',
name: 'Millionaire',
desc: 'Have 1 million cookies',
condition: function condition() {
return allTimeCookies >= 1000000;
},
reward: 10000,
unlocked: false
}, {
id: 'speed_demon',
name: 'Speed Demon',
desc: 'Generate 1000 CPS',
condition: function condition() {
return totalCPS >= 1000;
},
reward: 50000,
unlocked: false
}];
var totalClicks = storage.totalClicks || 0;
function checkAchievements() {
var newAchievements = 0;
for (var i = 0; i < achievements.length; i++) {
var ach = achievements[i];
if (!ach.unlocked && ach.condition()) {
ach.unlocked = true;
cookies += ach.reward;
allTimeCookies += ach.reward;
newAchievements++;
showFloatingNumber('ACHIEVEMENT: ' + ach.name, 1024, 400 + i * 50);
showFloatingNumber('+' + formatNumber(ach.reward) + ' cookies!', 1024, 450 + i * 50);
playSound('achievement', 1.2);
LK.effects.flashScreen(0x00FF00, 300);
// Save achievement state
storage['achievement_' + ach.id] = true;
}
}
if (newAchievements > 0) {
updateDisplay();
saveGame();
}
}
// Load achievement states
for (var i = 0; i < achievements.length; i++) {
if (storage['achievement_' + achievements[i].id]) {
achievements[i].unlocked = true;
}
}
// Game variables
var cookies = storage.cookies || 0;
var totalCPS = storage.totalCPS || 0;
var cookiesPerTap = 1;
var tapMultiplier = 1;
// Powerup system variables
var activePowerups = [];
var powerups = [];
var powerupSpawnTimer = 0;
var basePowerupInterval = 1800; // 30 seconds at 60fps
// Falling cookie rain system variables
var rainCookies = [];
var rainSpawnTimer = 0;
var baseRainInterval = 45; // Spawn every 45 frames (0.75 seconds at 60fps)
// Prestige system variables
var prestigeLevel = storage.prestigeLevel || 0;
var prestigeBonus = prestigeLevel * 0.1; // 10% bonus per prestige
var allTimeCookies = storage.allTimeCookies || 0;
var canPrestige = false;
// Leaderboard system
var lastLeaderboardUpdate = storage.lastLeaderboardUpdate || 0;
// Buildings data
var buildingsData = [{
type: 'grandma',
cost: 15,
cps: 1
}, {
type: 'oven',
cost: 100,
cps: 8
}, {
type: 'factory',
cost: 1100,
cps: 47
}, {
type: 'mine',
cost: 12000,
cps: 260
}, {
type: 'bank',
cost: 130000,
cps: 1400
}, {
type: 'temple',
cost: 1400000,
cps: 7800
}, {
type: 'portal',
cost: 20000000,
cps: 44000
}, {
type: 'machine',
cost: 150000000,
cps: 260000
}, {
type: 'condenser',
cost: 800000000,
cps: 1600000
}, {
type: 'prism',
cost: 5000000000,
cps: 10000000
}, {
type: 'chancemaker',
cost: 25000000000,
cps: 65000000
}, {
type: 'fractal',
cost: 120000000000,
cps: 430000000
}, {
type: 'console',
cost: 600000000000,
cps: 2900000000
}, {
type: 'idleverse',
cost: 3000000000000,
cps: 21000000000
}, {
type: 'cortex',
cost: 15000000000000,
cps: 150000000000
}, {
type: 'you',
cost: 75000000000000,
cps: 1100000000000
}, {
type: 'synclavier',
cost: 400000000000000,
cps: 51000000000000
}, {
type: 'ascendancy',
cost: 2000000000000000,
cps: 440000000000000
}, {
type: 'altruism',
cost: 10000000000000000,
cps: 4000000000000000
}, {
type: 'luminous',
cost: 50000000000000000,
cps: 100000000000000000
}, {
type: 'sucroblast',
cost: 250000000000000000,
cps: 30000000000000000000
}, {
type: 'infinitude',
cost: 1250000000000000000,
cps: 999999999999999999999
}, {
type: 'cortexbaker',
cost: 6250000000000000000,
cps: 9999999999999999999999999
}];
var buildings = [];
var floatingNumbers = [];
// Create custom HUD background - removed to hide black box
// var hudBg = LK.getAsset('hudBackground', {
// anchorX: 0,
// anchorY: 0,
// height: 250
// });
// hudBg.alpha = 0.9;
// LK.gui.top.addChild(hudBg);
// Create cookie (centered and much larger, matches menu cookie)
var mainCookie = game.addChild(new Cookie());
mainCookie.x = 1024;
mainCookie.y = 1200;
mainCookie.scaleX = 2.5;
mainCookie.scaleY = 2.5;
// Custom UI with styled backgrounds - moved to top center
var cookieCounterBg = LK.getAsset('cookieCounter', {
anchorX: 0.5,
anchorY: 0.5
});
cookieCounterBg.x = 0;
cookieCounterBg.y = 40;
cookieCounterBg.visible = false; // Hide in menu
LK.gui.top.addChild(cookieCounterBg);
var cookieDisplay = new Text2('Cookies: 0', {
size: 52,
fill: 0xFFD700
});
cookieDisplay.anchor.set(0.5, 0.5);
cookieDisplay.x = 0;
cookieDisplay.y = 40;
cookieDisplay.visible = false; // Hide in menu
LK.gui.top.addChild(cookieDisplay);
var cpsCounterBg = LK.getAsset('cpsCounter', {
anchorX: 0.5,
anchorY: 0.5
});
cpsCounterBg.x = 0;
cpsCounterBg.y = 90;
cpsCounterBg.visible = false; // Hide in menu
LK.gui.top.addChild(cpsCounterBg);
var cpsDisplay = new Text2('Per second: 0', {
size: 36,
fill: 0x90EE90
});
cpsDisplay.anchor.set(0.5, 0.5);
cpsDisplay.x = 0;
cpsDisplay.y = 90;
cpsDisplay.visible = false; // Hide in menu
LK.gui.top.addChild(cpsDisplay);
// Prestige display
var prestigeDisplay = new Text2('Prestige Level: 0 (+0% bonus)', {
size: 28,
fill: 0xFFD700
});
prestigeDisplay.anchor.set(0.5, 0.5);
prestigeDisplay.x = 0;
prestigeDisplay.y = 160;
LK.gui.top.addChild(prestigeDisplay);
// Powerup status display
var powerupDisplay = new Text2('', {
size: 24,
fill: 0xFF6347
});
powerupDisplay.anchor.set(0.5, 0.5);
powerupDisplay.x = 0;
powerupDisplay.y = 200;
powerupDisplay.visible = false;
LK.gui.top.addChild(powerupDisplay);
// Shopping cart menu button (middle-right screen, larger and more visible)
var shopIcon = game.addChild(LK.getAsset('shopIconBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
shopIcon.x = 1900;
shopIcon.y = 1366;
shopIcon.tint = 0x333333;
var shopBorder = game.addChild(LK.getAsset('shopIconBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
shopBorder.x = 1900;
shopBorder.y = 1366;
shopBorder.tint = 0x666666;
var cartBg = game.addChild(LK.getAsset('shoppingCart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
cartBg.x = 1900;
cartBg.y = 1366;
cartBg.tint = 0x888888;
var wheel1 = game.addChild(LK.getAsset('cartWheel1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
wheel1.x = 1875;
wheel1.y = 1390;
var wheel2 = game.addChild(LK.getAsset('cartWheel2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
wheel2.x = 1925;
wheel2.y = 1390;
var handle = game.addChild(LK.getAsset('cartHandle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
}));
handle.x = 1940;
handle.y = 1350;
// Create back to main menu button (top right, below reserved area)
var backToMenuButton = game.addChild(LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
backToMenuButton.x = 1900;
backToMenuButton.y = 200;
backToMenuButton.tint = 0xE67E22;
var backToMenuText = new Text2('MENU', {
size: 28,
fill: 0xFFFFFF
});
backToMenuText.anchor.set(0.5, 0.5);
backToMenuText.x = 1900;
backToMenuText.y = 200;
game.addChild(backToMenuText);
function goBackToMainMenu() {
if (!isMuted) LK.getSound('buttonClick').play();
gameStarted = false;
cookieCounterBg.visible = false;
cookieDisplay.visible = false;
cpsCounterBg.visible = false;
cpsDisplay.visible = false;
prestigeDisplay.visible = false;
// Close any open menus
if (shop && shop.isOpen) shop.close();
if (settingsMenu && settingsMenu.isOpen) settingsMenu.close();
if (leaderboard && leaderboard.isOpen) leaderboard.close();
if (prestigeMenu && prestigeMenu.isOpen) prestigeMenu.close();
// Save game before returning to menu
saveGame();
updateLeaderboard();
// Show main menu
mainMenu.visible = true;
mainMenu.alpha = 0;
tween(mainMenu, {
alpha: 1
}, {
duration: 300
});
}
backToMenuButton.down = goBackToMainMenu;
backToMenuText.down = goBackToMainMenu;
// Create shop (initially hidden)
var shop = game.addChild(new Shop());
shop.x = 0;
shop.y = 0;
// Close shop menu when tapping outside
game.down = function (x, y, obj) {
// If shop is open and tap is outside the shop area, close it
if (shop && shop.isOpen) {
// Allow taps on shop elements, close only on background taps
if (y < 150 || x < 100 || x > 1948) {
shop.close();
}
}
};
// Create prestige button (bottom of screen)
var prestigeButton = new PrestigeButton();
prestigeButton.x = 1024;
prestigeButton.y = 2600;
game.addChild(prestigeButton);
// Initialize menus
var mainMenu = game.addChild(new MainMenu());
mainMenu.x = 0;
mainMenu.y = 0;
var settingsMenu = game.addChild(new SettingsMenu());
settingsMenu.x = 1024;
settingsMenu.y = 1366;
var tutorialScreen = game.addChild(new TutorialScreen());
tutorialScreen.x = 0;
tutorialScreen.y = 0;
var leaderboard = game.addChild(new Leaderboard());
leaderboard.x = 0;
leaderboard.y = 0;
// Click multiplier upgrade system - moved here before first usage
var clickUpgrades = [{
name: 'Better Finger',
cost: 100,
multiplier: 2,
purchased: false
}, {
name: 'Steel Cursor',
cost: 500,
multiplier: 5,
purchased: false
}, {
name: 'Golden Finger',
cost: 10000,
multiplier: 10,
purchased: false
}, {
name: 'Diamond Touch',
cost: 100000,
multiplier: 25,
purchased: false
}, {
name: 'Divine Click',
cost: 1000000,
multiplier: 50,
purchased: false
}];
// Initialize click multiplier system
updateClickMultiplier();
// Load click upgrades state
for (var i = 0; i < clickUpgrades.length; i++) {
if (storage['clickUpgrade_' + i]) {
clickUpgrades[i].purchased = true;
}
}
updateClickMultiplier();
// Initialize upgrade menu (shop acts as upgrade menu)
var upgradeMenu = shop;
// Initialize music
function showTutorial() {
tutorialScreen.open();
}
// Auto-pause when user leaves
function pauseGame() {
saveGame();
// Additional pause logic can be added here
}
function unpauseGame() {
// Resume game logic
updateDisplay();
}
// Auto-save and leaderboard update system
function updateLeaderboard() {
if (!playerName || playerName === '') return;
var currentTime = Date.now();
// Update more frequently - every 30 seconds for better real-time experience
var shouldUpdate = currentTime - lastLeaderboardUpdate > 30000 || lastLeaderboardUpdate === 0;
if (shouldUpdate) {
// 30 seconds for more responsive leaderboard
lastLeaderboardUpdate = currentTime;
storage.lastLeaderboardUpdate = lastLeaderboardUpdate;
var leaderboardNames = (storage.leaderboardNames || []).slice();
var leaderboardCookies = (storage.leaderboardCookies || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
var playerExists = false;
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardCookies[i] = Math.max(leaderboardCookies[i], cookies);
leaderboardPrestiges[i] = Math.max(leaderboardPrestiges[i] || 0, prestigeLevel);
leaderboardTimestamps[i] = currentTime; // Update timestamp for activity tracking
playerExists = true;
break;
}
}
if (!playerExists) {
leaderboardNames.push(playerName);
leaderboardCookies.push(cookies);
leaderboardTimestamps.push(currentTime);
leaderboardPrestiges.push(prestigeLevel);
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardCookies = leaderboardCookies;
storage.leaderboardTimestamps = leaderboardTimestamps;
storage.leaderboardPrestiges = leaderboardPrestiges;
} else {
// Always update prestige level and timestamp even if not updating cookies frequently
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardPrestiges = (storage.leaderboardPrestiges || []).slice();
var leaderboardTimestamps = (storage.leaderboardTimestamps || []).slice();
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
leaderboardPrestiges[i] = Math.max(leaderboardPrestiges[i] || 0, prestigeLevel);
if (leaderboardTimestamps.length > i) {
leaderboardTimestamps[i] = currentTime; // Keep activity current
}
storage.leaderboardPrestiges = leaderboardPrestiges;
storage.leaderboardTimestamps = leaderboardTimestamps;
break;
}
}
}
}
// Click detection system
function recordClick() {
var currentTime = Date.now();
clickTimes.push(currentTime);
// Remove clicks older than 1 second
clickTimes = clickTimes.filter(function (time) {
return currentTime - time < 1000;
});
// Check for suspicious clicking (over 20 clicks per second)
if (clickTimes.length > 20) {
if (!isWarned) {
isWarned = true;
showFloatingNumber('AUTO-CLICKER DETECTED!', 1024, 800);
}
if (clickTimes.length > 25) {
clicksBlocked = true;
showFloatingNumber('CLICKS BLOCKED!', 1024, 850);
LK.setTimeout(function () {
clicksBlocked = false;
isWarned = false;
}, 5000);
}
return false;
}
return true;
}
// Menu functionality
var prestigeMenu = null;
function openShopMenu() {
if (!gameStarted) return;
if (shop.isOpen) {
shop.close();
} else {
shop.open();
}
}
shopIcon.down = openShopMenu;
shopBorder.down = openShopMenu;
cartBg.down = openShopMenu;
wheel1.down = openShopMenu;
wheel2.down = openShopMenu;
handle.down = openShopMenu;
// Create buildings (no longer displayed directly, managed by upgrade menu)
for (var i = 0; i < buildingsData.length; i++) {
var buildingData = buildingsData[i];
var building = new Building(buildingData.type, buildingData.cost, buildingData.cps);
// Load saved data
var savedCount = storage['building_' + buildingData.type] || 0;
if (savedCount > 0) {
building.count = savedCount;
building.cost = Math.floor(building.baseCost * Math.pow(1.15, savedCount));
totalCPS += building.cookiesPerSecond * savedCount;
}
buildings.push(building);
}
// Click multiplier upgrade system moved earlier in code
function updateClickMultiplier() {
cookiesPerTap = 1;
for (var i = 0; i < clickUpgrades.length; i++) {
if (clickUpgrades[i].purchased) {
cookiesPerTap *= clickUpgrades[i].multiplier;
}
}
// Apply prestige bonus
cookiesPerTap *= tapMultiplier;
}
function buyClickUpgrade(upgradeIndex) {
var upgrade = clickUpgrades[upgradeIndex];
if (!upgrade.purchased && cookies >= upgrade.cost) {
cookies -= upgrade.cost;
upgrade.purchased = true;
updateClickMultiplier();
playSound('purchase');
updateDisplay();
saveGame();
showFloatingNumber('Click Power Up!', 1024, 600);
return true;
}
return false;
}
// Enhanced number formatting function
function formatNumber(num) {
if (num < 1000) {
return Math.floor(num).toString();
} else if (num < 10000) {
return Math.floor(num / 100) / 10 + 'k';
} else if (num < 1000000) {
return Math.floor(num / 1000) + 'k';
} else if (num < 10000000) {
return Math.floor(num / 100000) / 10 + 'mil';
} else if (num < 1000000000) {
return Math.floor(num / 1000000) + 'mil';
} else if (num < 10000000000) {
return Math.floor(num / 100000000) / 10 + 'bil';
} else if (num < 1000000000000) {
return Math.floor(num / 1000000000) + 'bil';
} else if (num < 10000000000000) {
return Math.floor(num / 100000000000) / 10 + 'tril';
} else if (num < 1000000000000000) {
return Math.floor(num / 1000000000000) + 'tril';
} else if (num < 10000000000000000) {
return Math.floor(num / 100000000000000) / 10 + 'quad';
} else if (num < 1000000000000000000) {
return Math.floor(num / 1000000000000000) + 'quad';
} else {
return Math.floor(num / 1000000000000000000) + 'quin';
}
}
// Enhanced sound system
function playSound(soundId, volumeMultiplier) {
if (!isMuted && storage.enableSoundEffects) {
var sound = LK.getSound(soundId);
var soundVolume = storage.soundVolume !== undefined ? storage.soundVolume : 0.7;
var finalVolume = soundVolume * (volumeMultiplier || 1);
// Set volume if the sound supports it
if (sound.volume !== undefined) {
sound.volume = finalVolume;
}
sound.play();
}
}
// Game functions
function updateDisplay() {
cookieDisplay.setText('Cookies: ' + formatNumber(cookies));
// Calculate total CPS with prestige bonus and powerup multipliers
var powerupMultiplier = 1;
for (var i = 0; i < activePowerups.length; i++) {
powerupMultiplier *= activePowerups[i].multiplier;
}
var prestigeCPSMultiplier = 1 + prestigeBonus;
var effectiveCPS = totalCPS * prestigeCPSMultiplier * powerupMultiplier;
cpsDisplay.setText('Per second: ' + formatNumber(effectiveCPS));
prestigeDisplay.setText('Prestige Level: ' + prestigeLevel + ' (+' + Math.floor(prestigeBonus * 100) + '% bonus)');
// Update powerup display
if (activePowerups.length > 0) {
var powerupText = '';
for (var i = 0; i < activePowerups.length; i++) {
var powerup = activePowerups[i];
var timeLeft = Math.ceil(powerup.timeLeft / 1000);
powerupText += powerup.name + ': +' + powerup.multiplier + 'x (' + timeLeft + 's)';
if (i < activePowerups.length - 1) powerupText += ' | ';
}
powerupDisplay.setText(powerupText);
powerupDisplay.visible = true;
} else {
powerupDisplay.visible = false;
}
for (var i = 0; i < buildings.length; i++) {
buildings[i].updateDisplay();
}
prestigeButton.updateDisplay();
if (shop && shop.isOpen) {
shop.updatePage();
}
if (prestigeMenu && prestigeMenu.isOpen) {
prestigeMenu.updateDisplay();
}
}
function showFloatingNumber(text, x, y) {
var floatingNum = new FloatingNumber(text, x, y);
game.addChild(floatingNum);
floatingNumbers.push(floatingNum);
}
function saveGame() {
storage.cookies = cookies;
storage.totalCPS = totalCPS;
storage.prestigeLevel = prestigeLevel;
storage.allTimeCookies = allTimeCookies;
storage.isMuted = isMuted;
storage.gameStarted = gameStarted;
try {
// Store as simple string literal to avoid storage restrictions
var nameToStore = String(playerName || '');
storage.playerName = nameToStore;
} catch (e) {
console.log('Storage not available for playerName save');
}
storage.lastLeaderboardUpdate = lastLeaderboardUpdate;
for (var i = 0; i < buildings.length; i++) {
storage['building_' + buildings[i].buildingType] = buildings[i].count;
}
}
// Auto-save timer
var saveTimer = LK.setInterval(function () {
saveGame();
}, 5000);
// CPS generation timer
var cpsTimer = LK.setInterval(function () {
if (totalCPS > 0) {
// Calculate powerup multiplier
var powerupMultiplier = 1;
for (var i = 0; i < activePowerups.length; i++) {
powerupMultiplier *= activePowerups[i].multiplier;
}
// Apply prestige bonus to CPS (same as tap multiplier)
var prestigeCPSMultiplier = 1 + prestigeBonus;
var cpsGain = totalCPS * prestigeCPSMultiplier * powerupMultiplier / 10; // 10 times per second for smoother increments
cookies += cpsGain;
allTimeCookies += cpsGain;
updateDisplay();
}
}, 100);
// Always start with main menu, do not show tutorial by default
gameStarted = false;
mainMenu.visible = true;
// Update username display in menu
mainMenu.updateUsername();
// Initial display update
updateDisplay();
// Completely purge player9240 from all storage - comprehensive cleanup
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardCookies = storage.leaderboardCookies || [];
var leaderboardTimestamps = storage.leaderboardTimestamps || [];
var leaderboardPrestiges = storage.leaderboardPrestiges || [];
// Remove all instances of player9240 and any variations
var playersToRemove = ['player9240', 'Player9240', 'PLAYER9240'];
var indicesToRemove = [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (playersToRemove.indexOf(leaderboardNames[i]) !== -1) {
indicesToRemove.push(i);
}
}
// Remove indices in reverse order to avoid index shifting issues
for (var j = indicesToRemove.length - 1; j >= 0; j--) {
var indexToRemove = indicesToRemove[j];
leaderboardNames.splice(indexToRemove, 1);
leaderboardCookies.splice(indexToRemove, 1);
leaderboardTimestamps.splice(indexToRemove, 1);
leaderboardPrestiges.splice(indexToRemove, 1);
}
// Force complete removal by creating fresh arrays without player9240
var cleanNames = [];
var cleanCookies = [];
var cleanTimestamps = [];
var cleanPrestiges = [];
for (var k = 0; k < leaderboardNames.length; k++) {
if (playersToRemove.indexOf(leaderboardNames[k]) === -1) {
cleanNames.push(leaderboardNames[k]);
cleanCookies.push(leaderboardCookies[k]);
cleanTimestamps.push(leaderboardTimestamps[k]);
cleanPrestiges.push(leaderboardPrestiges[k]);
}
}
// Overwrite storage completely
storage.leaderboardNames = cleanNames;
storage.leaderboardCookies = cleanCookies;
storage.leaderboardTimestamps = cleanTimestamps;
storage.leaderboardPrestiges = cleanPrestiges;
// Golden cookie spawning (every 30-60 seconds randomly)
if (LK.ticks % 60 === 0 && Math.random() < 0.03) {
// ~3% chance every second
var goldenCookie = game.addChild(new GoldenCookie());
goldenCookie.x = 200 + Math.random() * 1648;
goldenCookie.y = 200 + Math.random() * 1800;
}
// Start background music
// Check achievements periodically
if (LK.ticks % 180 === 0) {
// Every 3 seconds
checkAchievements();
}
// Clean up destroyed rain cookies
for (var i = rainCookies.length - 1; i >= 0; i--) {
if (rainCookies[i].destroyed) {
rainCookies.splice(i, 1);
}
}
// Spawn rain cookies for background effect (always visible during gameplay)
rainSpawnTimer++;
var rainInterval = baseRainInterval + Math.random() * 30; // Vary spawn timing slightly
if (rainSpawnTimer >= rainInterval) {
rainSpawnTimer = 0;
// Spawn 2-4 rain cookies at once for better visual effect
var spawnCount = 2 + Math.floor(Math.random() * 3);
for (var j = 0; j < spawnCount; j++) {
var rainCookie = game.addChild(new RainCookie());
// Spawn across full width with some spread
rainCookie.x = -100 + Math.random() * 2248; // Spawn slightly off-screen for better coverage
rainCookie.y = -50 - Math.random() * 200; // Stagger starting heights
rainCookie.startX = rainCookie.x; // Set starting X for sway calculations
rainCookies.push(rainCookie);
// Add smooth entrance animation using tween
rainCookie.alpha = 0;
var originalScale = rainCookie.scaleX;
rainCookie.scaleX = 0;
rainCookie.scaleY = 0;
tween(rainCookie, {
alpha: 0.3 + Math.random() * 0.4,
// Random transparency 0.3-0.7
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 400 + Math.random() * 600,
easing: tween.easeOut
});
// Add subtle rotation animation
tween(rainCookie, {
rotation: rainCookie.rotation + (Math.random() - 0.5) * Math.PI * 4
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.linear
});
}
}
// Update leaderboard periodically
updateLeaderboard();
if (!isMuted) {
var initialVolume = storage.musicVolume !== undefined ? storage.musicVolume : 0.8;
LK.playMusic('bgmusic', {
loop: true,
volume: initialVolume
});
}
// Falling cookie spawn timer - every 3 minutes based on upgrades
var fallingCookieTimer = 0;
var baseFallingInterval = 10800; // 3 minutes at 60fps
game.update = function () {
if (!gameStarted) {
// Hide cookie counters in menu
cookieCounterBg.visible = false;
cookieDisplay.visible = false;
cpsCounterBg.visible = false;
cpsDisplay.visible = false;
// Hide prestige level in menu
prestigeDisplay.visible = false;
// Hide back to menu button in menu
backToMenuButton.visible = false;
backToMenuText.visible = false;
// Show main menu if not started
if (!mainMenu.visible) {
mainMenu.visible = true;
mainMenu.alpha = 1;
}
return;
}
// Show back to menu button in game
backToMenuButton.visible = true;
backToMenuText.visible = true;
// Clean up destroyed floating numbers
for (var i = floatingNumbers.length - 1; i >= 0; i--) {
if (floatingNumbers[i].destroyed) {
floatingNumbers.splice(i, 1);
}
}
// Clean up destroyed falling cookies
for (var i = fallingCookies.length - 1; i >= 0; i--) {
if (fallingCookies[i].destroyed) {
fallingCookies.splice(i, 1);
}
}
// Clean up destroyed mini cookies
for (var i = miniCookies.length - 1; i >= 0; i--) {
if (miniCookies[i].destroyed) {
miniCookies.splice(i, 1);
}
}
// Calculate falling cookie interval based on upgrades
var totalUpgrades = 0;
for (var i = 0; i < buildings.length; i++) {
totalUpgrades += buildings[i].count;
}
// Spawn falling cookies more frequently with more upgrades
var fallingInterval = Math.max(1800, baseFallingInterval - totalUpgrades * 30); // Minimum 30 seconds
fallingCookieTimer++;
if (fallingCookieTimer >= fallingInterval) {
fallingCookieTimer = 0;
var fallingCookie = game.addChild(new FallingCookie());
fallingCookie.x = 200 + Math.random() * 1648;
fallingCookie.y = -100;
fallingCookie.scaleX = 1.8; // Make them bigger
fallingCookie.scaleY = 1.8;
fallingCookies.push(fallingCookie);
}
// Clean up destroyed powerups
for (var i = powerups.length - 1; i >= 0; i--) {
if (powerups[i].destroyed) {
powerups.splice(i, 1);
}
}
// Spawn powerups randomly (every 30-60 seconds)
powerupSpawnTimer++;
var powerupInterval = basePowerupInterval + Math.random() * 1800; // 30-60 seconds
if (powerupSpawnTimer >= powerupInterval && totalCPS > 10) {
// Only spawn if player has some CPS AND no menus are open
var anyMenuOpen = shop && shop.isOpen || settingsMenu && settingsMenu.isOpen || leaderboard && leaderboard.isOpen || tutorialScreen && tutorialScreen.isOpen || prestigeMenu && prestigeMenu.isOpen;
if (!anyMenuOpen) {
powerupSpawnTimer = 0;
var powerup = game.addChild(new Powerup());
powerup.x = 300 + Math.random() * 1448; // Keep away from edges
powerup.y = 400 + Math.random() * 1200;
powerups.push(powerup);
}
}
// Update active powerups
for (var i = activePowerups.length - 1; i >= 0; i--) {
var powerup = activePowerups[i];
powerup.timeLeft -= 16.67; // Approximately 1 frame at 60fps
if (powerup.timeLeft <= 0) {
showFloatingNumber(powerup.name + ' EXPIRED', 1024, 500);
activePowerups.splice(i, 1);
}
}
// Update leaderboard periodically
updateLeaderboard();
// Update username display and status more frequently during cooldown
if (LK.ticks % 180 === 0 && mainMenu) {
// Every 3 seconds for more responsive cooldown updates
mainMenu.updateUsername();
}
};