User prompt
Lütfen hatayı düzeltin: 'Script hatası.' bu satırda veya bu satırla ilgili: 'currentBoard.push(scoreEntry);' Satır Numarası: 1021 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'currentBoard.push(scoreEntry);' Line Number: 1021 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Oyunda skormuzu görek ve Sv mizide görək ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Ve öldüyümuzuzde ana menüye gedey
User prompt
Ve biz bu engelre deydiyimzde ölek
User prompt
Şimdi bu maniyelere deydiyimzde öley ve bu maiyeler hızlı gelsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ya ben sıkıldım diyorum ki bizim önüme maniyelr cıksın ve bizi zorlasın para kasabada ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyundakı o sarı altın şeyelr geliyor a onları kayb et onalrın yerine bizi zorluyan şeyler cıksın özumuze ve ölek ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Abi bir oyun skoru yap ve bir svy yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyuna kapak fotoğrafı köy
User prompt
Şimdi oyuna ana menü ekleyin içi dolu olsun yap kafana göre bir şeyelr ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Şimdide oyuna altın gelsin altında da basdımızda oyun hızılansın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yok bu bolanalr gelsin hemde altın para gelsin cobo 259 olun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyun biraz sıkıcı be ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Buna böyle bir şey yap bu oyuna bir en iyi skor köy ve hızlansın Bide biraz maraxlı şeyler ele lutven ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Bubble Pop Frenzy
Initial prompt
Selam bana bir Oyun yap kafana göre ama eyeleneceli bir şey olsun vakit geçirecek bir şey
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, leaderboard: [] }); /**** * Classes ****/ var Bubble = Container.expand(function (isGolden, isBonus) { var self = Container.call(this); self.isGolden = isGolden || false; self.isBonus = isBonus || false; self.speed = Math.random() * 2 + 1; // Random speed between 1-3 self.points = self.isBonus ? 259 : self.isGolden ? 50 : 10; var assetName = self.isBonus ? 'bonusBubble' : self.isGolden ? 'goldenBubble' : 'bubble'; var bubbleGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); // Bonus bubbles get extreme pulsing effect if (self.isBonus) { tween(bubbleGraphics, { scaleX: 1.5, scaleY: 1.5, rotation: Math.PI / 4 }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { tween(bubbleGraphics, { scaleX: 0.8, scaleY: 0.8, rotation: -Math.PI / 4 }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { // Loop the extreme pulsing effect if (self.parent) { tween(bubbleGraphics, { scaleX: 1.5, scaleY: 1.5, rotation: Math.PI / 4 }, { duration: 400, easing: tween.bounceOut }); } } }); } }); } else if (self.isGolden) { tween(bubbleGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(bubbleGraphics, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { // Loop the pulsing effect if (self.parent) { // Only continue if bubble still exists tween(bubbleGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut }); } } }); } }); } // Add slight floating animation var floatOffset = Math.random() * Math.PI * 2; self.update = function () { self.y -= self.speed; // Add slight horizontal wobble self.x += Math.sin(LK.ticks * 0.05 + floatOffset) * 0.5; // Add special effects for different bubble types if (self.isBonus) { // Bonus bubbles get super fast rainbow cycling and extra wobble var fastColorPhase = (LK.ticks * 0.1 + floatOffset) % (Math.PI * 2); var red = Math.floor(Math.sin(fastColorPhase) * 127 + 128); var green = Math.floor(Math.sin(fastColorPhase + 2.094) * 127 + 128); var blue = Math.floor(Math.sin(fastColorPhase + 4.188) * 127 + 128); var rainbowColor = red << 16 | green << 8 | blue; bubbleGraphics.tint = rainbowColor; // Extra wobble for bonus bubbles self.x += Math.sin(LK.ticks * 0.1 + floatOffset) * 2; } else if (!self.isGolden) { var colorPhase = (LK.ticks * 0.02 + floatOffset) % (Math.PI * 2); var red = Math.floor(Math.sin(colorPhase) * 127 + 128); var green = Math.floor(Math.sin(colorPhase + 2.094) * 127 + 128); var blue = Math.floor(Math.sin(colorPhase + 4.188) * 127 + 128); var rainbowColor = red << 16 | green << 8 | blue; bubbleGraphics.tint = rainbowColor; } }; self.down = function (x, y, obj) { self.pop(); }; self.pop = function () { // Combo system comboCount++; comboTimer = 180; // 3 seconds to maintain combo var comboMultiplier = Math.min(Math.floor(comboCount / 5) + 1, 5); var finalPoints = self.points * comboMultiplier; // Add points to score LK.setScore(LK.getScore() + finalPoints); // Create floating score indicator var scoreIndicator = new Text2('+' + finalPoints, { size: 50 + comboMultiplier * 10, fill: self.isGolden ? 0xFFD700 : 0x00FF88 }); scoreIndicator.anchor.set(0.5, 0.5); scoreIndicator.x = self.x; scoreIndicator.y = self.y; game.addChild(scoreIndicator); // Animate the floating score tween(scoreIndicator, { y: self.y - 100, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { scoreIndicator.destroy(); } }); // Show combo text for exciting combos if (comboCount >= 5 && comboCount % 5 === 0) { comboTxt.setText('COMBO x' + comboMultiplier + '!'); comboTxt.alpha = 1; comboTxt.scaleX = 1.5; comboTxt.scaleY = 1.5; tween(comboTxt, { alpha: 0, scaleX: 1, scaleY: 1 }, { duration: 1500 }); // Screen shake for big combos screenShakeIntensity = Math.min(comboMultiplier * 2, 10); // Add screen zoom effect for mega combos if (comboCount >= 10) { tween(game, { scaleX: 1.05, scaleY: 1.05 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.bounceOut }); } }); } } // Play pop sound and special effects if (self.isBonus) { LK.getSound('bonusPop').play(); // Bonus bubble creates intense orange screen flash LK.effects.flashScreen(0xFF6B35, 600); // Extra screen shake for bonus bubbles screenShakeIntensity = Math.max(screenShakeIntensity, 15); } else if (self.isGolden) { LK.getSound('goldenPop').play(); // Golden bubble creates screen flash LK.effects.flashScreen(0xFFD700, 300); } else { LK.getSound('pop').play(); } // Create particle burst effect var particleCount = self.isBonus ? 12 : 6; for (var p = 0; p < particleCount; p++) { var particle = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: self.isBonus ? 0.5 : 0.3, scaleY: self.isBonus ? 0.5 : 0.3, x: self.x, y: self.y }); particle.tint = self.isBonus ? 0xFF6B35 : self.isGolden ? 0xFFD700 : bubbleGraphics.tint; game.addChild(particle); var angle = p / particleCount * Math.PI * 2; var distance = self.isBonus ? 120 + Math.random() * 60 : 80 + Math.random() * 40; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0, scaleY: 0, rotation: Math.random() * Math.PI * 2 }, { duration: self.isBonus ? 800 + Math.random() * 400 : 400 + Math.random() * 200, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Enhanced pop animation with random rotation var randomRotation = (Math.random() - 0.5) * Math.PI; tween(self, { scaleX: 2, scaleY: 2, alpha: 0, rotation: randomRotation }, { duration: 250, easing: tween.bounceOut, onFinish: function onFinish() { self.destroy(); } }); // Remove from bubbles array for (var i = bubbles.length - 1; i >= 0; i--) { if (bubbles[i] === self) { bubbles.splice(i, 1); break; } } }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); self.speed = Math.random() * 1.5 + 1; // Random speed between 1-2.5 self.value = 10; var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); // Add spinning animation tween(coinGraphics, { rotation: Math.PI * 2 }, { duration: 1000, easing: tween.linear, onFinish: function onFinish() { if (self.parent) { // Loop the spinning tween(coinGraphics, { rotation: Math.PI * 4 }, { duration: 1000, easing: tween.linear }); } } }); // Add pulsing effect tween(coinGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(coinGraphics, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { // Loop the pulsing tween(coinGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut }); } } }); } }); self.update = function () { self.y += self.speed; // Add slight floating wobble self.x += Math.sin(LK.ticks * 0.08) * 0.8; }; self.down = function (x, y, obj) { self.collect(); }; self.collect = function () { // Add coins to player money playerMoney += self.value; // Play collect sound LK.getSound('coinCollect').play(); // Create floating money indicator var moneyIndicator = new Text2('+$' + self.value, { size: 50, fill: 0xFFD700 }); moneyIndicator.anchor.set(0.5, 0.5); moneyIndicator.x = self.x; moneyIndicator.y = self.y; game.addChild(moneyIndicator); // Animate the floating money indicator tween(moneyIndicator, { y: self.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { moneyIndicator.destroy(); } }); // Update money display moneyTxt.setText('Money: $' + playerMoney); // Coin collection animation tween(self, { scaleX: 2, scaleY: 2, alpha: 0, rotation: Math.PI * 2 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { self.destroy(); } }); // Remove from coins array for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === self) { coins.splice(i, 1); break; } } }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); self.speed = Math.random() * 4 + 3; // Random speed between 3-7 self.hitPlayer = false; var enemyGraphics = self.attachAsset('enemySpike', { anchorX: 0.5, anchorY: 0.5 }); // Add menacing rotation animation tween(enemyGraphics, { rotation: Math.PI * 2 }, { duration: 800, easing: tween.linear, onFinish: function onFinish() { if (self.parent) { // Loop the spinning tween(enemyGraphics, { rotation: Math.PI * 4 }, { duration: 800, easing: tween.linear }); } } }); // Add threatening pulsing effect tween(enemyGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(enemyGraphics, { scaleX: 0.9, scaleY: 0.9 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { // Loop the pulsing tween(enemyGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut }); } } }); } }); self.update = function () { self.y += self.speed; // Add aggressive zigzag movement self.x += Math.sin(LK.ticks * 0.15) * 2; }; self.down = function (x, y, obj) { if (!self.hasHitPlayer) { self.hitPlayer(); } }; self.hitPlayer = function () { if (self.hasHitPlayer) return; self.hasHitPlayer = true; // Play enemy hit sound LK.getSound('enemyHit').play(); // Create death indicator var deathIndicator = new Text2('GAME OVER!', { size: 80, fill: 0xff0000 }); deathIndicator.anchor.set(0.5, 0.5); deathIndicator.x = self.x; deathIndicator.y = self.y; game.addChild(deathIndicator); // Animate the death indicator tween(deathIndicator, { y: self.y - 120, alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { deathIndicator.destroy(); } }); // Enemy hit effect tween(self, { scaleX: 3, scaleY: 3, alpha: 0, rotation: Math.PI * 4 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { self.destroy(); } }); // Remove from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } // Flash screen red and trigger game over immediately LK.effects.flashScreen(0xff0000, 1000); screenShakeIntensity = Math.max(screenShakeIntensity, 20); // Update high score and leaderboard before returning to menu var currentScore = LK.getScore(); if (currentScore > storage.highScore) { storage.highScore = currentScore; } updateLeaderboard(currentScore); // Clean up game objects for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) { bubbles[cleanBubble].destroy(); } bubbles = []; for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) { enemies[cleanEnemy].destroy(); } enemies = []; for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) { obstacles[cleanObstacle].destroy(); } obstacles = []; for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) { coins[cleanCoin].destroy(); } coins = []; // Return to menu after short delay LK.setTimeout(function () { gameState = 'menu'; gameUIContainer.visible = false; gameUIContainer.alpha = 0; menuContainer.visible = true; tween(menuContainer, { alpha: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { animateMenu(); } }); }, 2000); }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); self.speed = Math.random() * 4 + 5; // Random speed between 5-9 (much faster) var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Add menacing glow effect tween(obstacleGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(obstacleGraphics, { scaleX: 0.9, scaleY: 0.9 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { // Loop the pulsing tween(obstacleGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 600, easing: tween.easeInOut }); } } }); } }); self.update = function () { self.y += self.speed; }; self.down = function (x, y, obj) { if (!self.hasHitPlayer) { self.hitPlayer(); } }; self.hitPlayer = function () { if (self.hasHitPlayer) return; self.hasHitPlayer = true; // Play enemy hit sound LK.getSound('enemyHit').play(); // Create death indicator var deathIndicator = new Text2('GAME OVER!', { size: 80, fill: 0xff0000 }); deathIndicator.anchor.set(0.5, 0.5); deathIndicator.x = self.x; deathIndicator.y = self.y; game.addChild(deathIndicator); // Animate the death indicator tween(deathIndicator, { y: self.y - 120, alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { deathIndicator.destroy(); } }); // Obstacle hit effect tween(self, { scaleX: 3, scaleY: 3, alpha: 0, rotation: Math.PI * 4 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { self.destroy(); } }); // Remove from obstacles array for (var i = obstacles.length - 1; i >= 0; i--) { if (obstacles[i] === self) { obstacles.splice(i, 1); break; } } // Flash screen red and trigger game over immediately LK.effects.flashScreen(0xff0000, 1000); screenShakeIntensity = Math.max(screenShakeIntensity, 20); // Update high score and leaderboard before returning to menu var currentScore = LK.getScore(); if (currentScore > storage.highScore) { storage.highScore = currentScore; } updateLeaderboard(currentScore); // Clean up game objects for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) { bubbles[cleanBubble].destroy(); } bubbles = []; for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) { enemies[cleanEnemy].destroy(); } enemies = []; for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) { obstacles[cleanObstacle].destroy(); } obstacles = []; for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) { coins[cleanCoin].destroy(); } coins = []; // Return to menu after short delay LK.setTimeout(function () { gameState = 'menu'; gameUIContainer.visible = false; gameUIContainer.alpha = 0; menuContainer.visible = true; tween(menuContainer, { alpha: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { animateMenu(); } }); }, 2000); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game state management var gameState = 'menu'; // 'menu', 'playing', 'gameOver', 'leaderboard' var bubbles = []; var bubblesEscaped = 0; var maxEscapedBubbles = 10; var spawnTimer = 0; var spawnInterval = 80; // Start spawning faster (80 ticks = ~1.3 seconds) var difficultyTimer = 0; var comboCount = 0; var comboTimer = 0; var screenShakeIntensity = 0; var enemies = []; var enemySpawnTimer = 0; var enemySpawnInterval = 400; // Spawn enemies every 6.7 seconds var obstacles = []; var obstacleSpawnTimer = 0; var obstacleSpawnInterval = 120; // Spawn obstacles every 2 seconds (faster spawning) var coins = []; var coinSpawnTimer = 0; var coinSpawnInterval = 150; // Spawn coins every 2.5 seconds var playerMoney = 0; var showingLeaderboard = false; var leaderboardContainer = new Container(); // Main Menu Elements var menuContainer = new Container(); // Add cover image var coverImage = LK.getAsset('coverImage', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 600, scaleX: 1.5, scaleY: 1.2 }); coverImage.tint = 0x87CEEB; menuContainer.addChild(coverImage); // Add decorative bubbles on cover image var decorBubbles = []; for (var d = 0; d < 8; d++) { var decorBubble = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3 + Math.random() * 0.4, scaleY: 0.3 + Math.random() * 0.4, x: 1024 + (Math.random() - 0.5) * 500, y: 600 + (Math.random() - 0.5) * 300 }); decorBubble.alpha = 0.7; decorBubbles.push(decorBubble); menuContainer.addChild(decorBubble); } // Add golden decorative bubbles for (var g = 0; g < 3; g++) { var goldenDecor = LK.getAsset('goldenBubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.25, scaleY: 0.25, x: 1024 + (Math.random() - 0.5) * 400, y: 600 + (Math.random() - 0.5) * 250 }); goldenDecor.alpha = 0.8; decorBubbles.push(goldenDecor); menuContainer.addChild(goldenDecor); } var titleTxt = new Text2('BUBBLE POP FRENZY', { size: 120, fill: 0xFFD700 }); titleTxt.anchor.set(0.5, 0.5); titleTxt.x = 1024; titleTxt.y = 450; menuContainer.addChild(titleTxt); var playBtn = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2.5, x: 1024, y: 1100 }); playBtn.tint = 0x00FF88; menuContainer.addChild(playBtn); var playTxt = new Text2('TAP TO PLAY', { size: 80, fill: 0xFFFFFF }); playTxt.anchor.set(0.5, 0.5); playTxt.x = 1024; playTxt.y = 1100; menuContainer.addChild(playTxt); var bestScoreMenuTxt = new Text2('Best Score: ' + storage.highScore, { size: 60, fill: 0xFFD700 }); bestScoreMenuTxt.anchor.set(0.5, 0.5); bestScoreMenuTxt.x = 1024; bestScoreMenuTxt.y = 1300; menuContainer.addChild(bestScoreMenuTxt); var instructionsTxt = new Text2('Pop bubbles before they escape!\nGolden bubbles = 50 points\nBonus bubbles = 259 points\nAvoid red spikes - they kill you!', { size: 45, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); instructionsTxt.x = 1024; instructionsTxt.y = 1550; menuContainer.addChild(instructionsTxt); var leaderboardBtn = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8, x: 1024, y: 1800 }); leaderboardBtn.tint = 0xFFD700; menuContainer.addChild(leaderboardBtn); var leaderboardBtnTxt = new Text2('LEADERBOARD', { size: 60, fill: 0x000000 }); leaderboardBtnTxt.anchor.set(0.5, 0.5); leaderboardBtnTxt.x = 1024; leaderboardBtnTxt.y = 1800; menuContainer.addChild(leaderboardBtnTxt); game.addChild(menuContainer); // Create leaderboard container var leaderboardBg = LK.getAsset('coverImage', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.8, scaleY: 2.2 }); leaderboardBg.tint = 0x2c3e50; leaderboardContainer.addChild(leaderboardBg); var leaderboardTitle = new Text2('🏆 LEADERBOARD 🏆', { size: 90, fill: 0xFFD700 }); leaderboardTitle.anchor.set(0.5, 0.5); leaderboardTitle.x = 1024; leaderboardTitle.y = 500; leaderboardContainer.addChild(leaderboardTitle); var backBtn = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, x: 1024, y: 2200 }); backBtn.tint = 0xFF6B35; leaderboardContainer.addChild(backBtn); var backBtnTxt = new Text2('BACK', { size: 60, fill: 0xFFFFFF }); backBtnTxt.anchor.set(0.5, 0.5); backBtnTxt.x = 1024; backBtnTxt.y = 2200; leaderboardContainer.addChild(backBtnTxt); leaderboardContainer.visible = false; game.addChild(leaderboardContainer); // Animate menu elements function animateMenu() { // Cover image gentle pulsing tween(coverImage, { scaleX: 1.6, scaleY: 1.3, alpha: 0.9 }, { duration: 2500, easing: tween.easeInOut, onFinish: function onFinish() { tween(coverImage, { scaleX: 1.5, scaleY: 1.2, alpha: 1 }, { duration: 2500, easing: tween.easeInOut }); } }); // Animate decorative bubbles for (var db = 0; db < decorBubbles.length; db++) { var bubble = decorBubbles[db]; var delay = db * 200; LK.setTimeout(function (b) { return function () { tween(b, { y: b.y - 20, rotation: Math.PI / 4 }, { duration: 1500 + Math.random() * 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(b, { y: b.y + 20, rotation: -Math.PI / 4 }, { duration: 1500 + Math.random() * 1000, easing: tween.easeInOut }); } }); }; }(bubble), delay); } // Title pulsing animation tween(titleTxt, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleTxt, { scaleX: 1, scaleY: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (gameState === 'menu') { animateMenu(); } } }); } }); // Play button floating animation tween(playBtn, { y: 1080 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(playBtn, { y: 1120 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { if (gameState === 'menu') { animateMenu(); } } }); } }); // Sync play text with button tween(playTxt, { y: 1080 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(playTxt, { y: 1120 }, { duration: 2000, easing: tween.easeInOut }); } }); // Leaderboard button floating animation tween(leaderboardBtn, { y: 1780 }, { duration: 2200, easing: tween.easeInOut, onFinish: function onFinish() { tween(leaderboardBtn, { y: 1820 }, { duration: 2200, easing: tween.easeInOut, onFinish: function onFinish() { if (gameState === 'menu') { animateMenu(); } } }); } }); // Sync leaderboard text with button tween(leaderboardBtnTxt, { y: 1780 }, { duration: 2200, easing: tween.easeInOut, onFinish: function onFinish() { tween(leaderboardBtnTxt, { y: 1820 }, { duration: 2200, easing: tween.easeInOut }); } }); // Rainbow color cycling for title var colorTimer = 0; function cycleColors() { if (gameState !== 'menu') return; colorTimer += 0.05; var red = Math.floor(Math.sin(colorTimer) * 127 + 128); var green = Math.floor(Math.sin(colorTimer + 2.094) * 127 + 128); var blue = Math.floor(Math.sin(colorTimer + 4.188) * 127 + 128); var rainbowColor = red << 16 | green << 8 | blue; titleTxt.tint = rainbowColor; LK.setTimeout(cycleColors, 50); } cycleColors(); } function updateLeaderboard(newScore) { if (newScore <= 0) return; // Initialize storage.leaderboard if it doesn't exist or is invalid if (!storage.leaderboard || !Array.isArray(storage.leaderboard)) { storage.leaderboard = []; } // Get current leaderboard and create a safe copy var currentBoard = []; try { currentBoard = storage.leaderboard.slice(); // Create a copy } catch (e) { // If slice fails, start with empty array currentBoard = []; storage.leaderboard = []; } // Add new score with timestamp var scoreEntry = { score: newScore, date: new Date().toLocaleDateString() }; // Ensure currentBoard is still an array before pushing if (!Array.isArray(currentBoard)) { currentBoard = []; } currentBoard.push(scoreEntry); // Sort by score (highest first) and keep top 10 currentBoard.sort(function (a, b) { return b.score - a.score; }); // Keep only top 10 scores if (currentBoard.length > 10) { currentBoard = currentBoard.slice(0, 10); } // Save back to storage storage.leaderboard = currentBoard; } function showLeaderboard() { if (showingLeaderboard) return; showingLeaderboard = true; gameState = 'leaderboard'; // Hide menu menuContainer.visible = false; // Clear previous leaderboard entries for (var i = leaderboardContainer.children.length - 1; i >= 0; i--) { var child = leaderboardContainer.children[i]; if (child.isScoreEntry) { leaderboardContainer.removeChild(child); } } // Display leaderboard scores var leaderboard = storage.leaderboard || []; for (var i = 0; i < Math.min(leaderboard.length, 10); i++) { var entry = leaderboard[i]; var position = i + 1; var medal = position === 1 ? '🥇' : position === 2 ? '🥈' : position === 3 ? '🥉' : position + '.'; var entryText = new Text2(medal + ' ' + entry.score + ' pts - ' + entry.date, { size: 55, fill: position <= 3 ? 0xFFD700 : 0xFFFFFF }); entryText.anchor.set(0.5, 0.5); entryText.x = 1024; entryText.y = 650 + i * 120; entryText.isScoreEntry = true; leaderboardContainer.addChild(entryText); // Add entrance animation entryText.alpha = 0; entryText.x = 1024 + 200; tween(entryText, { alpha: 1, x: 1024 }, { duration: 300 + i * 100, easing: tween.easeOut }); } // Show empty message if no scores if (leaderboard.length === 0) { var emptyText = new Text2('No scores yet!\nStart playing to set records!', { size: 60, fill: 0xAAAAAAA }); emptyText.anchor.set(0.5, 0.5); emptyText.x = 1024; emptyText.y = 1200; emptyText.isScoreEntry = true; leaderboardContainer.addChild(emptyText); } // Show leaderboard with animation leaderboardContainer.visible = true; leaderboardContainer.alpha = 0; tween(leaderboardContainer, { alpha: 1 }, { duration: 500, easing: tween.easeInOut }); } function hideLeaderboard() { if (!showingLeaderboard) return; showingLeaderboard = false; gameState = 'menu'; tween(leaderboardContainer, { alpha: 0 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { leaderboardContainer.visible = false; menuContainer.visible = true; menuContainer.alpha = 1; animateMenu(); } }); } // Start menu animations animateMenu(); // Play button interaction playBtn.down = function (x, y, obj) { startGame(); }; playTxt.down = function (x, y, obj) { startGame(); }; // Leaderboard button interactions leaderboardBtn.down = function (x, y, obj) { if (gameState === 'menu') { showLeaderboard(); } }; leaderboardBtnTxt.down = function (x, y, obj) { if (gameState === 'menu') { showLeaderboard(); } }; // Back button interactions backBtn.down = function (x, y, obj) { if (gameState === 'leaderboard') { hideLeaderboard(); } }; backBtnTxt.down = function (x, y, obj) { if (gameState === 'leaderboard') { hideLeaderboard(); } }; function startGame() { if (gameState !== 'menu') return; gameState = 'playing'; menuContainer.alpha = 0; menuContainer.visible = false; // Show game UI gameUIContainer.visible = true; gameUIContainer.alpha = 1; // Reset game variables bubbles = []; bubblesEscaped = 0; spawnTimer = 0; spawnInterval = 80; difficultyTimer = 0; comboCount = 0; comboTimer = 0; screenShakeIntensity = 0; enemies = []; enemySpawnTimer = 0; obstacles = []; obstacleSpawnTimer = 0; coins = []; coinSpawnTimer = 0; playerMoney = 0; LK.setScore(0); // Update displays scoreTxt.setText('Score: 0'); currentScoreTxt.setText('Score: 0'); escapedTxt.setText('Escaped: 0/10'); dangerTxt.setText('DANGER LEVEL: LOW'); moneyTxt.setText('Money: $0'); } // Game UI Container var gameUIContainer = new Container(); // UI Elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var escapedTxt = new Text2('Escaped: 0/10', { size: 50, fill: 0xFFFFFF }); escapedTxt.anchor.set(1, 0); escapedTxt.x = -20; escapedTxt.y = 80; LK.gui.topRight.addChild(escapedTxt); gameUIContainer.addChild(escapedTxt); var highScoreTxt = new Text2('Best: ' + storage.highScore, { size: 45, fill: 0xFFD700 }); highScoreTxt.anchor.set(0, 0); highScoreTxt.x = 20; highScoreTxt.y = 80; LK.gui.topLeft.addChild(highScoreTxt); var currentScoreTxt = new Text2('Score: 0', { size: 50, fill: 0x00FF88 }); currentScoreTxt.anchor.set(0, 0); currentScoreTxt.x = 20; currentScoreTxt.y = 200; LK.gui.topLeft.addChild(currentScoreTxt); var comboTxt = new Text2('', { size: 70, fill: 0xFF6B35 }); comboTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(comboTxt); gameUIContainer.addChild(comboTxt); var dangerTxt = new Text2('DANGER LEVEL: LOW', { size: 50, fill: 0xff6666 }); dangerTxt.anchor.set(0.5, 0); dangerTxt.y = 140; LK.gui.top.addChild(dangerTxt); gameUIContainer.addChild(dangerTxt); var moneyTxt = new Text2('Money: $0', { size: 55, fill: 0xFFD700 }); moneyTxt.anchor.set(0, 0); moneyTxt.x = 20; moneyTxt.y = 260; LK.gui.topLeft.addChild(moneyTxt); // Initially hide game UI gameUIContainer.visible = false; gameUIContainer.alpha = 0; function spawnBubble() { if (gameState !== 'playing') return; var isBonus = Math.random() < 0.02; // 2% chance for bonus bubble (259 points) var isGolden = !isBonus && Math.random() < 0.1; // 10% chance for golden bubble (only if not bonus) var bubble = new Bubble(isGolden, isBonus); // Random spawn position across screen width bubble.x = Math.random() * (2048 - 200) + 100; bubble.y = 2732 + 60; // Start just below screen bubbles.push(bubble); game.addChild(bubble); } function spawnEnemy() { if (gameState !== 'playing') return; var enemy = new Enemy(); // Random spawn position across screen width enemy.x = Math.random() * (2048 - 200) + 100; enemy.y = -120; // Start above screen enemies.push(enemy); game.addChild(enemy); } function spawnObstacle() { if (gameState !== 'playing') return; var obstacle = new Obstacle(); // Random spawn position across screen width obstacle.x = Math.random() * (2048 - 400) + 200; obstacle.y = -80; // Start above screen obstacles.push(obstacle); game.addChild(obstacle); } function spawnCoin() { if (gameState !== 'playing') return; var coin = new Coin(); // Random spawn position across screen width coin.x = Math.random() * (2048 - 200) + 100; coin.y = -60; // Start above screen coins.push(coin); game.addChild(coin); } function updateDifficulty() { difficultyTimer++; // Increase difficulty every 7 seconds (420 ticks) - faster progression if (difficultyTimer % 420 === 0) { // Decrease spawn interval (spawn faster) spawnInterval = Math.max(25, spawnInterval - 8); // Increase bubble speed more dramatically for (var i = 0; i < bubbles.length; i++) { bubbles[i].speed += 0.4; } } // Every 30 seconds, spawn a burst of golden bubbles for excitement if (difficultyTimer % 1800 === 0) { for (var j = 0; j < 3; j++) { LK.setTimeout(function () { var goldenBubble = new Bubble(true); goldenBubble.x = Math.random() * (2048 - 200) + 100; goldenBubble.y = 2732 + 60; goldenBubble.speed *= 0.7; // Slower so players can catch them bubbles.push(goldenBubble); game.addChild(goldenBubble); }, j * 300); } } // Every 45 seconds, spawn bonus bubble rain for mega excitement if (difficultyTimer % 2700 === 0) { for (var k = 0; k < 5; k++) { LK.setTimeout(function () { var bonusBubble = new Bubble(false, true); bonusBubble.x = Math.random() * (2048 - 200) + 100; bonusBubble.y = 2732 + 60; bonusBubble.speed *= 0.5; // Much slower so players can definitely catch them bubbles.push(bonusBubble); game.addChild(bonusBubble); }, k * 200); } } } game.update = function () { // Only run game logic when playing if (gameState !== 'playing') { // Update best score display in menu if (gameState === 'menu') { bestScoreMenuTxt.setText('Best Score: ' + storage.highScore); } return; } updateDifficulty(); // Combo timer countdown if (comboTimer > 0) { comboTimer--; if (comboTimer === 0) { comboCount = 0; // Reset combo when timer expires } } // Spawn enemies enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnInterval) { spawnEnemy(); enemySpawnTimer = 0; // Increase danger level over time var dangerLevel = Math.floor(difficultyTimer / 600); // Every 10 seconds var dangerText = dangerLevel < 3 ? 'LOW' : dangerLevel < 6 ? 'MEDIUM' : dangerLevel < 10 ? 'HIGH' : 'EXTREME'; dangerTxt.setText('DANGER LEVEL: ' + dangerText); if (dangerLevel >= 3) { dangerTxt.tint = 0xff4444; } if (dangerLevel >= 6) { dangerTxt.tint = 0xff0000; } } // Spawn obstacles obstacleSpawnTimer++; if (obstacleSpawnTimer >= obstacleSpawnInterval) { spawnObstacle(); obstacleSpawnTimer = 0; } // Spawn coins coinSpawnTimer++; if (coinSpawnTimer >= coinSpawnInterval) { spawnCoin(); coinSpawnTimer = 0; } // Screen shake effect if (screenShakeIntensity > 0) { game.x = (Math.random() - 0.5) * screenShakeIntensity; game.y = (Math.random() - 0.5) * screenShakeIntensity; screenShakeIntensity *= 0.9; // Gradually reduce shake if (screenShakeIntensity < 0.1) { screenShakeIntensity = 0; game.x = 0; game.y = 0; } } // Spawn bubbles faster spawnTimer++; if (spawnTimer >= spawnInterval) { spawnBubble(); spawnTimer = 0; } // Check for bubbles that escaped for (var i = bubbles.length - 1; i >= 0; i--) { var bubble = bubbles[i]; // Check if bubble escaped (reached top of screen) if (bubble.y < -60) { bubblesEscaped++; bubble.destroy(); bubbles.splice(i, 1); // Reset combo when bubble escapes comboCount = 0; comboTimer = 0; // Update escaped counter escapedTxt.setText('Escaped: ' + bubblesEscaped + '/' + maxEscapedBubbles); // Check game over condition if (bubblesEscaped >= maxEscapedBubbles) { // Update high score before game over var currentScore = LK.getScore(); if (currentScore > storage.highScore) { storage.highScore = currentScore; highScoreTxt.setText('Best: ' + storage.highScore); } // Add score to leaderboard updateLeaderboard(currentScore); // Clean up game objects for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) { bubbles[cleanBubble].destroy(); } bubbles = []; for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) { enemies[cleanEnemy].destroy(); } enemies = []; for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) { obstacles[cleanObstacle].destroy(); } obstacles = []; for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) { coins[cleanCoin].destroy(); } coins = []; // Return to menu after short delay LK.setTimeout(function () { gameState = 'menu'; gameUIContainer.visible = false; gameUIContainer.alpha = 0; menuContainer.visible = true; tween(menuContainer, { alpha: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { animateMenu(); } }); }, 2000); LK.showGameOver(); return; } } } // Check for enemies that fell off screen for (var e = enemies.length - 1; e >= 0; e--) { var enemy = enemies[e]; if (enemy.y > 2732 + 120) { enemy.destroy(); enemies.splice(e, 1); } } // Check for obstacles that fell off screen for (var o = obstacles.length - 1; o >= 0; o--) { var obstacle = obstacles[o]; if (obstacle.y > 2732 + 100) { obstacle.destroy(); obstacles.splice(o, 1); } } // Check for coins that fell off screen for (var c = coins.length - 1; c >= 0; c--) { var coin = coins[c]; if (coin.y > 2732 + 60) { coin.destroy(); coins.splice(c, 1); } } // Update score displays scoreTxt.setText('Score: ' + LK.getScore()); currentScoreTxt.setText('Score: ' + LK.getScore()); // Dynamic background color based on score for atmosphere var currentScore = LK.getScore(); var colorPhase = currentScore * 0.01 % (Math.PI * 2); var bgRed = Math.floor(Math.sin(colorPhase) * 40 + 100); var bgGreen = Math.floor(Math.sin(colorPhase + 2.094) * 40 + 150); var bgBlue = Math.floor(Math.sin(colorPhase + 4.188) * 40 + 200); var dynamicBgColor = bgRed << 16 | bgGreen << 8 | bgBlue; game.setBackgroundColor(dynamicBgColor); // Update high score display in real-time if beaten var currentScore = LK.getScore(); if (currentScore > storage.highScore) { storage.highScore = currentScore; highScoreTxt.setText('Best: ' + storage.highScore); highScoreTxt.tint = 0x00FF00; // Green highlight for new record } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
leaderboard: []
});
/****
* Classes
****/
var Bubble = Container.expand(function (isGolden, isBonus) {
var self = Container.call(this);
self.isGolden = isGolden || false;
self.isBonus = isBonus || false;
self.speed = Math.random() * 2 + 1; // Random speed between 1-3
self.points = self.isBonus ? 259 : self.isGolden ? 50 : 10;
var assetName = self.isBonus ? 'bonusBubble' : self.isGolden ? 'goldenBubble' : 'bubble';
var bubbleGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
// Bonus bubbles get extreme pulsing effect
if (self.isBonus) {
tween(bubbleGraphics, {
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI / 4
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(bubbleGraphics, {
scaleX: 0.8,
scaleY: 0.8,
rotation: -Math.PI / 4
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Loop the extreme pulsing effect
if (self.parent) {
tween(bubbleGraphics, {
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI / 4
}, {
duration: 400,
easing: tween.bounceOut
});
}
}
});
}
});
} else if (self.isGolden) {
tween(bubbleGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(bubbleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Loop the pulsing effect
if (self.parent) {
// Only continue if bubble still exists
tween(bubbleGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut
});
}
}
});
}
});
}
// Add slight floating animation
var floatOffset = Math.random() * Math.PI * 2;
self.update = function () {
self.y -= self.speed;
// Add slight horizontal wobble
self.x += Math.sin(LK.ticks * 0.05 + floatOffset) * 0.5;
// Add special effects for different bubble types
if (self.isBonus) {
// Bonus bubbles get super fast rainbow cycling and extra wobble
var fastColorPhase = (LK.ticks * 0.1 + floatOffset) % (Math.PI * 2);
var red = Math.floor(Math.sin(fastColorPhase) * 127 + 128);
var green = Math.floor(Math.sin(fastColorPhase + 2.094) * 127 + 128);
var blue = Math.floor(Math.sin(fastColorPhase + 4.188) * 127 + 128);
var rainbowColor = red << 16 | green << 8 | blue;
bubbleGraphics.tint = rainbowColor;
// Extra wobble for bonus bubbles
self.x += Math.sin(LK.ticks * 0.1 + floatOffset) * 2;
} else if (!self.isGolden) {
var colorPhase = (LK.ticks * 0.02 + floatOffset) % (Math.PI * 2);
var red = Math.floor(Math.sin(colorPhase) * 127 + 128);
var green = Math.floor(Math.sin(colorPhase + 2.094) * 127 + 128);
var blue = Math.floor(Math.sin(colorPhase + 4.188) * 127 + 128);
var rainbowColor = red << 16 | green << 8 | blue;
bubbleGraphics.tint = rainbowColor;
}
};
self.down = function (x, y, obj) {
self.pop();
};
self.pop = function () {
// Combo system
comboCount++;
comboTimer = 180; // 3 seconds to maintain combo
var comboMultiplier = Math.min(Math.floor(comboCount / 5) + 1, 5);
var finalPoints = self.points * comboMultiplier;
// Add points to score
LK.setScore(LK.getScore() + finalPoints);
// Create floating score indicator
var scoreIndicator = new Text2('+' + finalPoints, {
size: 50 + comboMultiplier * 10,
fill: self.isGolden ? 0xFFD700 : 0x00FF88
});
scoreIndicator.anchor.set(0.5, 0.5);
scoreIndicator.x = self.x;
scoreIndicator.y = self.y;
game.addChild(scoreIndicator);
// Animate the floating score
tween(scoreIndicator, {
y: self.y - 100,
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
scoreIndicator.destroy();
}
});
// Show combo text for exciting combos
if (comboCount >= 5 && comboCount % 5 === 0) {
comboTxt.setText('COMBO x' + comboMultiplier + '!');
comboTxt.alpha = 1;
comboTxt.scaleX = 1.5;
comboTxt.scaleY = 1.5;
tween(comboTxt, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 1500
});
// Screen shake for big combos
screenShakeIntensity = Math.min(comboMultiplier * 2, 10);
// Add screen zoom effect for mega combos
if (comboCount >= 10) {
tween(game, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
}
}
// Play pop sound and special effects
if (self.isBonus) {
LK.getSound('bonusPop').play();
// Bonus bubble creates intense orange screen flash
LK.effects.flashScreen(0xFF6B35, 600);
// Extra screen shake for bonus bubbles
screenShakeIntensity = Math.max(screenShakeIntensity, 15);
} else if (self.isGolden) {
LK.getSound('goldenPop').play();
// Golden bubble creates screen flash
LK.effects.flashScreen(0xFFD700, 300);
} else {
LK.getSound('pop').play();
}
// Create particle burst effect
var particleCount = self.isBonus ? 12 : 6;
for (var p = 0; p < particleCount; p++) {
var particle = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.isBonus ? 0.5 : 0.3,
scaleY: self.isBonus ? 0.5 : 0.3,
x: self.x,
y: self.y
});
particle.tint = self.isBonus ? 0xFF6B35 : self.isGolden ? 0xFFD700 : bubbleGraphics.tint;
game.addChild(particle);
var angle = p / particleCount * Math.PI * 2;
var distance = self.isBonus ? 120 + Math.random() * 60 : 80 + Math.random() * 40;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0,
scaleY: 0,
rotation: Math.random() * Math.PI * 2
}, {
duration: self.isBonus ? 800 + Math.random() * 400 : 400 + Math.random() * 200,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Enhanced pop animation with random rotation
var randomRotation = (Math.random() - 0.5) * Math.PI;
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0,
rotation: randomRotation
}, {
duration: 250,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from bubbles array
for (var i = bubbles.length - 1; i >= 0; i--) {
if (bubbles[i] === self) {
bubbles.splice(i, 1);
break;
}
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
self.speed = Math.random() * 1.5 + 1; // Random speed between 1-2.5
self.value = 10;
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Add spinning animation
tween(coinGraphics, {
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.linear,
onFinish: function onFinish() {
if (self.parent) {
// Loop the spinning
tween(coinGraphics, {
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.linear
});
}
}
});
// Add pulsing effect
tween(coinGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(coinGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
// Loop the pulsing
tween(coinGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut
});
}
}
});
}
});
self.update = function () {
self.y += self.speed;
// Add slight floating wobble
self.x += Math.sin(LK.ticks * 0.08) * 0.8;
};
self.down = function (x, y, obj) {
self.collect();
};
self.collect = function () {
// Add coins to player money
playerMoney += self.value;
// Play collect sound
LK.getSound('coinCollect').play();
// Create floating money indicator
var moneyIndicator = new Text2('+$' + self.value, {
size: 50,
fill: 0xFFD700
});
moneyIndicator.anchor.set(0.5, 0.5);
moneyIndicator.x = self.x;
moneyIndicator.y = self.y;
game.addChild(moneyIndicator);
// Animate the floating money indicator
tween(moneyIndicator, {
y: self.y - 80,
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
moneyIndicator.destroy();
}
});
// Update money display
moneyTxt.setText('Money: $' + playerMoney);
// Coin collection animation
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from coins array
for (var i = coins.length - 1; i >= 0; i--) {
if (coins[i] === self) {
coins.splice(i, 1);
break;
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.speed = Math.random() * 4 + 3; // Random speed between 3-7
self.hitPlayer = false;
var enemyGraphics = self.attachAsset('enemySpike', {
anchorX: 0.5,
anchorY: 0.5
});
// Add menacing rotation animation
tween(enemyGraphics, {
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.linear,
onFinish: function onFinish() {
if (self.parent) {
// Loop the spinning
tween(enemyGraphics, {
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.linear
});
}
}
});
// Add threatening pulsing effect
tween(enemyGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
// Loop the pulsing
tween(enemyGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 400,
easing: tween.easeInOut
});
}
}
});
}
});
self.update = function () {
self.y += self.speed;
// Add aggressive zigzag movement
self.x += Math.sin(LK.ticks * 0.15) * 2;
};
self.down = function (x, y, obj) {
if (!self.hasHitPlayer) {
self.hitPlayer();
}
};
self.hitPlayer = function () {
if (self.hasHitPlayer) return;
self.hasHitPlayer = true;
// Play enemy hit sound
LK.getSound('enemyHit').play();
// Create death indicator
var deathIndicator = new Text2('GAME OVER!', {
size: 80,
fill: 0xff0000
});
deathIndicator.anchor.set(0.5, 0.5);
deathIndicator.x = self.x;
deathIndicator.y = self.y;
game.addChild(deathIndicator);
// Animate the death indicator
tween(deathIndicator, {
y: self.y - 120,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
deathIndicator.destroy();
}
});
// Enemy hit effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 4
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
// Flash screen red and trigger game over immediately
LK.effects.flashScreen(0xff0000, 1000);
screenShakeIntensity = Math.max(screenShakeIntensity, 20);
// Update high score and leaderboard before returning to menu
var currentScore = LK.getScore();
if (currentScore > storage.highScore) {
storage.highScore = currentScore;
}
updateLeaderboard(currentScore);
// Clean up game objects
for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) {
bubbles[cleanBubble].destroy();
}
bubbles = [];
for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) {
enemies[cleanEnemy].destroy();
}
enemies = [];
for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) {
obstacles[cleanObstacle].destroy();
}
obstacles = [];
for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) {
coins[cleanCoin].destroy();
}
coins = [];
// Return to menu after short delay
LK.setTimeout(function () {
gameState = 'menu';
gameUIContainer.visible = false;
gameUIContainer.alpha = 0;
menuContainer.visible = true;
tween(menuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
animateMenu();
}
});
}, 2000);
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
self.speed = Math.random() * 4 + 5; // Random speed between 5-9 (much faster)
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Add menacing glow effect
tween(obstacleGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(obstacleGraphics, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
// Loop the pulsing
tween(obstacleGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.easeInOut
});
}
}
});
}
});
self.update = function () {
self.y += self.speed;
};
self.down = function (x, y, obj) {
if (!self.hasHitPlayer) {
self.hitPlayer();
}
};
self.hitPlayer = function () {
if (self.hasHitPlayer) return;
self.hasHitPlayer = true;
// Play enemy hit sound
LK.getSound('enemyHit').play();
// Create death indicator
var deathIndicator = new Text2('GAME OVER!', {
size: 80,
fill: 0xff0000
});
deathIndicator.anchor.set(0.5, 0.5);
deathIndicator.x = self.x;
deathIndicator.y = self.y;
game.addChild(deathIndicator);
// Animate the death indicator
tween(deathIndicator, {
y: self.y - 120,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
deathIndicator.destroy();
}
});
// Obstacle hit effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 4
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from obstacles array
for (var i = obstacles.length - 1; i >= 0; i--) {
if (obstacles[i] === self) {
obstacles.splice(i, 1);
break;
}
}
// Flash screen red and trigger game over immediately
LK.effects.flashScreen(0xff0000, 1000);
screenShakeIntensity = Math.max(screenShakeIntensity, 20);
// Update high score and leaderboard before returning to menu
var currentScore = LK.getScore();
if (currentScore > storage.highScore) {
storage.highScore = currentScore;
}
updateLeaderboard(currentScore);
// Clean up game objects
for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) {
bubbles[cleanBubble].destroy();
}
bubbles = [];
for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) {
enemies[cleanEnemy].destroy();
}
enemies = [];
for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) {
obstacles[cleanObstacle].destroy();
}
obstacles = [];
for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) {
coins[cleanCoin].destroy();
}
coins = [];
// Return to menu after short delay
LK.setTimeout(function () {
gameState = 'menu';
gameUIContainer.visible = false;
gameUIContainer.alpha = 0;
menuContainer.visible = true;
tween(menuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
animateMenu();
}
});
}, 2000);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing', 'gameOver', 'leaderboard'
var bubbles = [];
var bubblesEscaped = 0;
var maxEscapedBubbles = 10;
var spawnTimer = 0;
var spawnInterval = 80; // Start spawning faster (80 ticks = ~1.3 seconds)
var difficultyTimer = 0;
var comboCount = 0;
var comboTimer = 0;
var screenShakeIntensity = 0;
var enemies = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 400; // Spawn enemies every 6.7 seconds
var obstacles = [];
var obstacleSpawnTimer = 0;
var obstacleSpawnInterval = 120; // Spawn obstacles every 2 seconds (faster spawning)
var coins = [];
var coinSpawnTimer = 0;
var coinSpawnInterval = 150; // Spawn coins every 2.5 seconds
var playerMoney = 0;
var showingLeaderboard = false;
var leaderboardContainer = new Container();
// Main Menu Elements
var menuContainer = new Container();
// Add cover image
var coverImage = LK.getAsset('coverImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 600,
scaleX: 1.5,
scaleY: 1.2
});
coverImage.tint = 0x87CEEB;
menuContainer.addChild(coverImage);
// Add decorative bubbles on cover image
var decorBubbles = [];
for (var d = 0; d < 8; d++) {
var decorBubble = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + Math.random() * 0.4,
scaleY: 0.3 + Math.random() * 0.4,
x: 1024 + (Math.random() - 0.5) * 500,
y: 600 + (Math.random() - 0.5) * 300
});
decorBubble.alpha = 0.7;
decorBubbles.push(decorBubble);
menuContainer.addChild(decorBubble);
}
// Add golden decorative bubbles
for (var g = 0; g < 3; g++) {
var goldenDecor = LK.getAsset('goldenBubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25,
scaleY: 0.25,
x: 1024 + (Math.random() - 0.5) * 400,
y: 600 + (Math.random() - 0.5) * 250
});
goldenDecor.alpha = 0.8;
decorBubbles.push(goldenDecor);
menuContainer.addChild(goldenDecor);
}
var titleTxt = new Text2('BUBBLE POP FRENZY', {
size: 120,
fill: 0xFFD700
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 1024;
titleTxt.y = 450;
menuContainer.addChild(titleTxt);
var playBtn = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5,
x: 1024,
y: 1100
});
playBtn.tint = 0x00FF88;
menuContainer.addChild(playBtn);
var playTxt = new Text2('TAP TO PLAY', {
size: 80,
fill: 0xFFFFFF
});
playTxt.anchor.set(0.5, 0.5);
playTxt.x = 1024;
playTxt.y = 1100;
menuContainer.addChild(playTxt);
var bestScoreMenuTxt = new Text2('Best Score: ' + storage.highScore, {
size: 60,
fill: 0xFFD700
});
bestScoreMenuTxt.anchor.set(0.5, 0.5);
bestScoreMenuTxt.x = 1024;
bestScoreMenuTxt.y = 1300;
menuContainer.addChild(bestScoreMenuTxt);
var instructionsTxt = new Text2('Pop bubbles before they escape!\nGolden bubbles = 50 points\nBonus bubbles = 259 points\nAvoid red spikes - they kill you!', {
size: 45,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
instructionsTxt.x = 1024;
instructionsTxt.y = 1550;
menuContainer.addChild(instructionsTxt);
var leaderboardBtn = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
x: 1024,
y: 1800
});
leaderboardBtn.tint = 0xFFD700;
menuContainer.addChild(leaderboardBtn);
var leaderboardBtnTxt = new Text2('LEADERBOARD', {
size: 60,
fill: 0x000000
});
leaderboardBtnTxt.anchor.set(0.5, 0.5);
leaderboardBtnTxt.x = 1024;
leaderboardBtnTxt.y = 1800;
menuContainer.addChild(leaderboardBtnTxt);
game.addChild(menuContainer);
// Create leaderboard container
var leaderboardBg = LK.getAsset('coverImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.8,
scaleY: 2.2
});
leaderboardBg.tint = 0x2c3e50;
leaderboardContainer.addChild(leaderboardBg);
var leaderboardTitle = new Text2('🏆 LEADERBOARD 🏆', {
size: 90,
fill: 0xFFD700
});
leaderboardTitle.anchor.set(0.5, 0.5);
leaderboardTitle.x = 1024;
leaderboardTitle.y = 500;
leaderboardContainer.addChild(leaderboardTitle);
var backBtn = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
x: 1024,
y: 2200
});
backBtn.tint = 0xFF6B35;
leaderboardContainer.addChild(backBtn);
var backBtnTxt = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
backBtnTxt.anchor.set(0.5, 0.5);
backBtnTxt.x = 1024;
backBtnTxt.y = 2200;
leaderboardContainer.addChild(backBtnTxt);
leaderboardContainer.visible = false;
game.addChild(leaderboardContainer);
// Animate menu elements
function animateMenu() {
// Cover image gentle pulsing
tween(coverImage, {
scaleX: 1.6,
scaleY: 1.3,
alpha: 0.9
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(coverImage, {
scaleX: 1.5,
scaleY: 1.2,
alpha: 1
}, {
duration: 2500,
easing: tween.easeInOut
});
}
});
// Animate decorative bubbles
for (var db = 0; db < decorBubbles.length; db++) {
var bubble = decorBubbles[db];
var delay = db * 200;
LK.setTimeout(function (b) {
return function () {
tween(b, {
y: b.y - 20,
rotation: Math.PI / 4
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(b, {
y: b.y + 20,
rotation: -Math.PI / 4
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut
});
}
});
};
}(bubble), delay);
}
// Title pulsing animation
tween(titleTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
animateMenu();
}
}
});
}
});
// Play button floating animation
tween(playBtn, {
y: 1080
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(playBtn, {
y: 1120
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
animateMenu();
}
}
});
}
});
// Sync play text with button
tween(playTxt, {
y: 1080
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(playTxt, {
y: 1120
}, {
duration: 2000,
easing: tween.easeInOut
});
}
});
// Leaderboard button floating animation
tween(leaderboardBtn, {
y: 1780
}, {
duration: 2200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(leaderboardBtn, {
y: 1820
}, {
duration: 2200,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
animateMenu();
}
}
});
}
});
// Sync leaderboard text with button
tween(leaderboardBtnTxt, {
y: 1780
}, {
duration: 2200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(leaderboardBtnTxt, {
y: 1820
}, {
duration: 2200,
easing: tween.easeInOut
});
}
});
// Rainbow color cycling for title
var colorTimer = 0;
function cycleColors() {
if (gameState !== 'menu') return;
colorTimer += 0.05;
var red = Math.floor(Math.sin(colorTimer) * 127 + 128);
var green = Math.floor(Math.sin(colorTimer + 2.094) * 127 + 128);
var blue = Math.floor(Math.sin(colorTimer + 4.188) * 127 + 128);
var rainbowColor = red << 16 | green << 8 | blue;
titleTxt.tint = rainbowColor;
LK.setTimeout(cycleColors, 50);
}
cycleColors();
}
function updateLeaderboard(newScore) {
if (newScore <= 0) return;
// Initialize storage.leaderboard if it doesn't exist or is invalid
if (!storage.leaderboard || !Array.isArray(storage.leaderboard)) {
storage.leaderboard = [];
}
// Get current leaderboard and create a safe copy
var currentBoard = [];
try {
currentBoard = storage.leaderboard.slice(); // Create a copy
} catch (e) {
// If slice fails, start with empty array
currentBoard = [];
storage.leaderboard = [];
}
// Add new score with timestamp
var scoreEntry = {
score: newScore,
date: new Date().toLocaleDateString()
};
// Ensure currentBoard is still an array before pushing
if (!Array.isArray(currentBoard)) {
currentBoard = [];
}
currentBoard.push(scoreEntry);
// Sort by score (highest first) and keep top 10
currentBoard.sort(function (a, b) {
return b.score - a.score;
});
// Keep only top 10 scores
if (currentBoard.length > 10) {
currentBoard = currentBoard.slice(0, 10);
}
// Save back to storage
storage.leaderboard = currentBoard;
}
function showLeaderboard() {
if (showingLeaderboard) return;
showingLeaderboard = true;
gameState = 'leaderboard';
// Hide menu
menuContainer.visible = false;
// Clear previous leaderboard entries
for (var i = leaderboardContainer.children.length - 1; i >= 0; i--) {
var child = leaderboardContainer.children[i];
if (child.isScoreEntry) {
leaderboardContainer.removeChild(child);
}
}
// Display leaderboard scores
var leaderboard = storage.leaderboard || [];
for (var i = 0; i < Math.min(leaderboard.length, 10); i++) {
var entry = leaderboard[i];
var position = i + 1;
var medal = position === 1 ? '🥇' : position === 2 ? '🥈' : position === 3 ? '🥉' : position + '.';
var entryText = new Text2(medal + ' ' + entry.score + ' pts - ' + entry.date, {
size: 55,
fill: position <= 3 ? 0xFFD700 : 0xFFFFFF
});
entryText.anchor.set(0.5, 0.5);
entryText.x = 1024;
entryText.y = 650 + i * 120;
entryText.isScoreEntry = true;
leaderboardContainer.addChild(entryText);
// Add entrance animation
entryText.alpha = 0;
entryText.x = 1024 + 200;
tween(entryText, {
alpha: 1,
x: 1024
}, {
duration: 300 + i * 100,
easing: tween.easeOut
});
}
// Show empty message if no scores
if (leaderboard.length === 0) {
var emptyText = new Text2('No scores yet!\nStart playing to set records!', {
size: 60,
fill: 0xAAAAAAA
});
emptyText.anchor.set(0.5, 0.5);
emptyText.x = 1024;
emptyText.y = 1200;
emptyText.isScoreEntry = true;
leaderboardContainer.addChild(emptyText);
}
// Show leaderboard with animation
leaderboardContainer.visible = true;
leaderboardContainer.alpha = 0;
tween(leaderboardContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
function hideLeaderboard() {
if (!showingLeaderboard) return;
showingLeaderboard = false;
gameState = 'menu';
tween(leaderboardContainer, {
alpha: 0
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
leaderboardContainer.visible = false;
menuContainer.visible = true;
menuContainer.alpha = 1;
animateMenu();
}
});
}
// Start menu animations
animateMenu();
// Play button interaction
playBtn.down = function (x, y, obj) {
startGame();
};
playTxt.down = function (x, y, obj) {
startGame();
};
// Leaderboard button interactions
leaderboardBtn.down = function (x, y, obj) {
if (gameState === 'menu') {
showLeaderboard();
}
};
leaderboardBtnTxt.down = function (x, y, obj) {
if (gameState === 'menu') {
showLeaderboard();
}
};
// Back button interactions
backBtn.down = function (x, y, obj) {
if (gameState === 'leaderboard') {
hideLeaderboard();
}
};
backBtnTxt.down = function (x, y, obj) {
if (gameState === 'leaderboard') {
hideLeaderboard();
}
};
function startGame() {
if (gameState !== 'menu') return;
gameState = 'playing';
menuContainer.alpha = 0;
menuContainer.visible = false;
// Show game UI
gameUIContainer.visible = true;
gameUIContainer.alpha = 1;
// Reset game variables
bubbles = [];
bubblesEscaped = 0;
spawnTimer = 0;
spawnInterval = 80;
difficultyTimer = 0;
comboCount = 0;
comboTimer = 0;
screenShakeIntensity = 0;
enemies = [];
enemySpawnTimer = 0;
obstacles = [];
obstacleSpawnTimer = 0;
coins = [];
coinSpawnTimer = 0;
playerMoney = 0;
LK.setScore(0);
// Update displays
scoreTxt.setText('Score: 0');
currentScoreTxt.setText('Score: 0');
escapedTxt.setText('Escaped: 0/10');
dangerTxt.setText('DANGER LEVEL: LOW');
moneyTxt.setText('Money: $0');
}
// Game UI Container
var gameUIContainer = new Container();
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var escapedTxt = new Text2('Escaped: 0/10', {
size: 50,
fill: 0xFFFFFF
});
escapedTxt.anchor.set(1, 0);
escapedTxt.x = -20;
escapedTxt.y = 80;
LK.gui.topRight.addChild(escapedTxt);
gameUIContainer.addChild(escapedTxt);
var highScoreTxt = new Text2('Best: ' + storage.highScore, {
size: 45,
fill: 0xFFD700
});
highScoreTxt.anchor.set(0, 0);
highScoreTxt.x = 20;
highScoreTxt.y = 80;
LK.gui.topLeft.addChild(highScoreTxt);
var currentScoreTxt = new Text2('Score: 0', {
size: 50,
fill: 0x00FF88
});
currentScoreTxt.anchor.set(0, 0);
currentScoreTxt.x = 20;
currentScoreTxt.y = 200;
LK.gui.topLeft.addChild(currentScoreTxt);
var comboTxt = new Text2('', {
size: 70,
fill: 0xFF6B35
});
comboTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(comboTxt);
gameUIContainer.addChild(comboTxt);
var dangerTxt = new Text2('DANGER LEVEL: LOW', {
size: 50,
fill: 0xff6666
});
dangerTxt.anchor.set(0.5, 0);
dangerTxt.y = 140;
LK.gui.top.addChild(dangerTxt);
gameUIContainer.addChild(dangerTxt);
var moneyTxt = new Text2('Money: $0', {
size: 55,
fill: 0xFFD700
});
moneyTxt.anchor.set(0, 0);
moneyTxt.x = 20;
moneyTxt.y = 260;
LK.gui.topLeft.addChild(moneyTxt);
// Initially hide game UI
gameUIContainer.visible = false;
gameUIContainer.alpha = 0;
function spawnBubble() {
if (gameState !== 'playing') return;
var isBonus = Math.random() < 0.02; // 2% chance for bonus bubble (259 points)
var isGolden = !isBonus && Math.random() < 0.1; // 10% chance for golden bubble (only if not bonus)
var bubble = new Bubble(isGolden, isBonus);
// Random spawn position across screen width
bubble.x = Math.random() * (2048 - 200) + 100;
bubble.y = 2732 + 60; // Start just below screen
bubbles.push(bubble);
game.addChild(bubble);
}
function spawnEnemy() {
if (gameState !== 'playing') return;
var enemy = new Enemy();
// Random spawn position across screen width
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -120; // Start above screen
enemies.push(enemy);
game.addChild(enemy);
}
function spawnObstacle() {
if (gameState !== 'playing') return;
var obstacle = new Obstacle();
// Random spawn position across screen width
obstacle.x = Math.random() * (2048 - 400) + 200;
obstacle.y = -80; // Start above screen
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnCoin() {
if (gameState !== 'playing') return;
var coin = new Coin();
// Random spawn position across screen width
coin.x = Math.random() * (2048 - 200) + 100;
coin.y = -60; // Start above screen
coins.push(coin);
game.addChild(coin);
}
function updateDifficulty() {
difficultyTimer++;
// Increase difficulty every 7 seconds (420 ticks) - faster progression
if (difficultyTimer % 420 === 0) {
// Decrease spawn interval (spawn faster)
spawnInterval = Math.max(25, spawnInterval - 8);
// Increase bubble speed more dramatically
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].speed += 0.4;
}
}
// Every 30 seconds, spawn a burst of golden bubbles for excitement
if (difficultyTimer % 1800 === 0) {
for (var j = 0; j < 3; j++) {
LK.setTimeout(function () {
var goldenBubble = new Bubble(true);
goldenBubble.x = Math.random() * (2048 - 200) + 100;
goldenBubble.y = 2732 + 60;
goldenBubble.speed *= 0.7; // Slower so players can catch them
bubbles.push(goldenBubble);
game.addChild(goldenBubble);
}, j * 300);
}
}
// Every 45 seconds, spawn bonus bubble rain for mega excitement
if (difficultyTimer % 2700 === 0) {
for (var k = 0; k < 5; k++) {
LK.setTimeout(function () {
var bonusBubble = new Bubble(false, true);
bonusBubble.x = Math.random() * (2048 - 200) + 100;
bonusBubble.y = 2732 + 60;
bonusBubble.speed *= 0.5; // Much slower so players can definitely catch them
bubbles.push(bonusBubble);
game.addChild(bonusBubble);
}, k * 200);
}
}
}
game.update = function () {
// Only run game logic when playing
if (gameState !== 'playing') {
// Update best score display in menu
if (gameState === 'menu') {
bestScoreMenuTxt.setText('Best Score: ' + storage.highScore);
}
return;
}
updateDifficulty();
// Combo timer countdown
if (comboTimer > 0) {
comboTimer--;
if (comboTimer === 0) {
comboCount = 0; // Reset combo when timer expires
}
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnInterval) {
spawnEnemy();
enemySpawnTimer = 0;
// Increase danger level over time
var dangerLevel = Math.floor(difficultyTimer / 600); // Every 10 seconds
var dangerText = dangerLevel < 3 ? 'LOW' : dangerLevel < 6 ? 'MEDIUM' : dangerLevel < 10 ? 'HIGH' : 'EXTREME';
dangerTxt.setText('DANGER LEVEL: ' + dangerText);
if (dangerLevel >= 3) {
dangerTxt.tint = 0xff4444;
}
if (dangerLevel >= 6) {
dangerTxt.tint = 0xff0000;
}
}
// Spawn obstacles
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnInterval) {
spawnObstacle();
obstacleSpawnTimer = 0;
}
// Spawn coins
coinSpawnTimer++;
if (coinSpawnTimer >= coinSpawnInterval) {
spawnCoin();
coinSpawnTimer = 0;
}
// Screen shake effect
if (screenShakeIntensity > 0) {
game.x = (Math.random() - 0.5) * screenShakeIntensity;
game.y = (Math.random() - 0.5) * screenShakeIntensity;
screenShakeIntensity *= 0.9; // Gradually reduce shake
if (screenShakeIntensity < 0.1) {
screenShakeIntensity = 0;
game.x = 0;
game.y = 0;
}
}
// Spawn bubbles faster
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnBubble();
spawnTimer = 0;
}
// Check for bubbles that escaped
for (var i = bubbles.length - 1; i >= 0; i--) {
var bubble = bubbles[i];
// Check if bubble escaped (reached top of screen)
if (bubble.y < -60) {
bubblesEscaped++;
bubble.destroy();
bubbles.splice(i, 1);
// Reset combo when bubble escapes
comboCount = 0;
comboTimer = 0;
// Update escaped counter
escapedTxt.setText('Escaped: ' + bubblesEscaped + '/' + maxEscapedBubbles);
// Check game over condition
if (bubblesEscaped >= maxEscapedBubbles) {
// Update high score before game over
var currentScore = LK.getScore();
if (currentScore > storage.highScore) {
storage.highScore = currentScore;
highScoreTxt.setText('Best: ' + storage.highScore);
}
// Add score to leaderboard
updateLeaderboard(currentScore);
// Clean up game objects
for (var cleanBubble = bubbles.length - 1; cleanBubble >= 0; cleanBubble--) {
bubbles[cleanBubble].destroy();
}
bubbles = [];
for (var cleanEnemy = enemies.length - 1; cleanEnemy >= 0; cleanEnemy--) {
enemies[cleanEnemy].destroy();
}
enemies = [];
for (var cleanObstacle = obstacles.length - 1; cleanObstacle >= 0; cleanObstacle--) {
obstacles[cleanObstacle].destroy();
}
obstacles = [];
for (var cleanCoin = coins.length - 1; cleanCoin >= 0; cleanCoin--) {
coins[cleanCoin].destroy();
}
coins = [];
// Return to menu after short delay
LK.setTimeout(function () {
gameState = 'menu';
gameUIContainer.visible = false;
gameUIContainer.alpha = 0;
menuContainer.visible = true;
tween(menuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
animateMenu();
}
});
}, 2000);
LK.showGameOver();
return;
}
}
}
// Check for enemies that fell off screen
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (enemy.y > 2732 + 120) {
enemy.destroy();
enemies.splice(e, 1);
}
}
// Check for obstacles that fell off screen
for (var o = obstacles.length - 1; o >= 0; o--) {
var obstacle = obstacles[o];
if (obstacle.y > 2732 + 100) {
obstacle.destroy();
obstacles.splice(o, 1);
}
}
// Check for coins that fell off screen
for (var c = coins.length - 1; c >= 0; c--) {
var coin = coins[c];
if (coin.y > 2732 + 60) {
coin.destroy();
coins.splice(c, 1);
}
}
// Update score displays
scoreTxt.setText('Score: ' + LK.getScore());
currentScoreTxt.setText('Score: ' + LK.getScore());
// Dynamic background color based on score for atmosphere
var currentScore = LK.getScore();
var colorPhase = currentScore * 0.01 % (Math.PI * 2);
var bgRed = Math.floor(Math.sin(colorPhase) * 40 + 100);
var bgGreen = Math.floor(Math.sin(colorPhase + 2.094) * 40 + 150);
var bgBlue = Math.floor(Math.sin(colorPhase + 4.188) * 40 + 200);
var dynamicBgColor = bgRed << 16 | bgGreen << 8 | bgBlue;
game.setBackgroundColor(dynamicBgColor);
// Update high score display in real-time if beaten
var currentScore = LK.getScore();
if (currentScore > storage.highScore) {
storage.highScore = currentScore;
highScoreTxt.setText('Best: ' + storage.highScore);
highScoreTxt.tint = 0x00FF00; // Green highlight for new record
}
};