Code edit (4 edits merged)
Please save this source code
User prompt
import storage plugin ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.gameData = gameData;' Line Number: 669
User prompt
Please fix the bug: 'TypeError: JSON is undefined' in or related to this line: 'storage.gameData = JSON.parse(JSON.stringify(gameData));' Line Number: 669
Code edit (1 edits merged)
Please save this source code
User prompt
update as needed with: function calculateOfflineProgress(timeDiff) { // Calculate basic BP as before... // Apply a stronger offline penalty (25% of normal production) totalBP *= 0.25; // Apply a hard cap totalBP = Math.min(totalBP, 8000); // Or apply diminishing returns var hoursMult = Math.min(1, 1 / Math.sqrt(secondsAway / 3600)); totalBP *= hoursMult; // Round to integer totalBP = Math.floor(totalBP); // Add the BP... }
Code edit (2 edits merged)
Please save this source code
User prompt
update with: function saveGame() { storage.bp = game.bp; try { // Store upgrades as JSON string storage.upgrades = JSON.stringify(UPGRADE_CONFIG); console.log("Saved upgrades: " + storage.upgrades); // Add debug output } catch (e) { console.log("Error saving upgrades: ", e); } storage.lastPlayTime = Date.now(); storage.tutorialComplete = game.tutorial.stage >= 7; }
User prompt
update with: // In loadGame function if (storage.upgrades) { try { var loadedUpgrades = JSON.parse(storage.upgrades); console.log("Loaded upgrades: ", loadedUpgrades); // Debug output // Merge the loaded config with default config for (var category in loadedUpgrades) { if (UPGRADE_CONFIG[category]) { for (var key in loadedUpgrades[category]) { if (UPGRADE_CONFIG[category][key]) { // For objects like machines if (typeof loadedUpgrades[category][key] === 'object' && loadedUpgrades[category][key] !== null) { for (var prop in loadedUpgrades[category][key]) { UPGRADE_CONFIG[category][key][prop] = loadedUpgrades[category][key][prop]; } } else { // For simple values UPGRADE_CONFIG[category][key] = loadedUpgrades[category][key]; } } } } } } catch (e) { console.log("Error loading upgrades: ", e); } }
User prompt
update as needed with: game.startGame = function () { // Remove title screen if (game.titleContainer) { game.titleContainer.destroy(); game.titleContainer = null; } // Start background music LK.playMusic('backgroundmusic', { fade: { start: 0, end: 0.5, duration: 2000 } }); // Exit title mode game.titleMode = false; // Load saved game data FIRST loadGame(); // Initialize BP display bpText.visible = true; // Initialize pufferfish for animation (not visible yet) playerMask.visible = true; // ... rest of the function ... // Only show tutorial if not completed if (!storage.tutorialComplete) { LK.setTimeout(function () { showTutorialPopup(1); }, 60); } }
Code edit (3 edits merged)
Please save this source code
User prompt
update with: // Inside the game.addBP function if (!isAutoPop) { game.lastPopTime = currentTime; // All combo-related code removed }
Code edit (3 edits merged)
Please save this source code
User prompt
update with: if (UPGRADE_CONFIG.player.sizeVariance.currentLevel > 0) { var variance = UPGRADE_CONFIG.player.sizeVariance.currentLevel; var minIncrease = 0.1 * variance; // +10% per level to min size // Cap maximum increase at 50% var maxIncrease = Math.min(0.5, 0.15 * variance); // Cap at +50% total // Apply size variance var sizeMultiplier = 1 - minIncrease + Math.random() * (minIncrease + maxIncrease); bubble.size *= sizeMultiplier; }
Code edit (1 edits merged)
Please save this source code
User prompt
update with: function getTreasureBonusMultiplier(x, y) { if (!game.treasureZones || game.treasureZones.length === 0) { return 1.0; // No bonus if no treasures } // Start with no bonus var totalBonus = 0; // Check each treasure zone game.treasureZones.forEach(function(zone) { var dx = x - zone.x; var dy = y - zone.y; var distance = Math.sqrt(dx * dx + dy * dy); // If bubble is in zone, add 30% bonus if (distance <= zone.radius) { totalBonus += 0.3; // +30% per overlapping zone } }); // Return multiplier (1.0 = no bonus, 1.3 = one zone, 1.6 = two zones, etc.) return 1.0 + totalBonus; }
Code edit (7 edits merged)
Please save this source code
User prompt
update as needed with: // In the game.update function, modify the title mode bubble spawning: if (game.titleMode) { // Just handle bubble spawning and updates during title // Random bubble spawning if (game.activeBubbles.length < game.MAX_BUBBLES) { if (LK.ticks % game.baseSpawnRate == 0) { var x = Math.random() * (game.width - 200) + 100; var titleBubble = spawnBubble(x, game.height + 100, 100, 0, true); // Apply saved color to the bubble if available if (titleBubble && game.titleColorSettings) { applyTitleScreenColor(titleBubble); } } } // ...rest of existing code }
Code edit (1 edits merged)
Please save this source code
User prompt
update with: // In the game.update function, in the title mode section: if (game.titleMode) { // Just handle bubble spawning and updates during title // Random bubble spawning if (game.activeBubbles.length < game.MAX_BUBBLES) { if (LK.ticks % game.baseSpawnRate == 0) { var x = Math.random() * (game.width - 200) + 100; var titleBubble = spawnBubble(x, game.height + 100, 100, 0, true); // Apply saved color to the bubble if available if (titleBubble && game.titleColorSettings) { applyTitleScreenColor(titleBubble); } } } // Update all active bubbles game.activeBubbles.forEach(function (bubble) { // Always apply color to ensure it's maintained, even for new bubbles from splits if (bubble.visible && game.titleColorSettings) { applyTitleScreenColor(bubble); } if (bubble.update) { bubble.update(); } }); return; // Skip rest of update when in title mode }
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: particle is undefined' in or related to this line: 'particle.visible = false;' Line Number: 2238
User prompt
update with: for (var i = 0; i < game.MAX_POP_PARTICLES; i++) { var particle = LK.getAsset('zoneIndicator', { width: 15, height: 15, // Start with larger size alpha: 0, visible: false, anchorX: 0.5, anchorY: 0.5 }); game.addChild(particle); game.popParticlePool.push(particle); }
Code edit (1 edits merged)
Please save this source code
===================================================================
--- original.js
+++ change.js
@@ -654,8 +654,18 @@
// Update all visuals based on loaded data
updateClamVisuals();
updateTreasureDecorations();
updateAllUpgradeTexts();
+ // Apply player upgrade effects
+ var lungCapacityLevel = UPGRADE_CONFIG.player.lungCapacity.currentLevel;
+ var quickBreathLevel = UPGRADE_CONFIG.player.quickBreath.currentLevel;
+ // Update max bubble size from Lung Capacity
+ var baseSize = UPGRADE_EFFECTS.lungCapacity.baseValue;
+ var increasePercent = UPGRADE_EFFECTS.lungCapacity.incrementPercent;
+ var multiplier = 1 + increasePercent / 100 * lungCapacityLevel;
+ game.maxBubbleSize = baseSize * multiplier;
+ // Update growth rate from Quick Breath
+ game.growthRate = UPGRADE_EFFECTS.quickBreath.baseValue * (1 + UPGRADE_EFFECTS.quickBreath.incrementPercent / 100 * quickBreathLevel);
// Calculate offline progress
if (storage.lastPlayTime) {
var currentTime = Date.now();
var timeDiff = currentTime - storage.lastPlayTime;
@@ -696,11 +706,12 @@
storage.lastPlayTime = Date.now();
storage.tutorialComplete = game.tutorial.stage >= 7;
}
// Calculate offline progress
+// Calculate offline progress
function calculateOfflineProgress(timeDiff) {
- // Convert time diff to seconds
- var secondsAway = Math.floor(timeDiff / 1000);
+ // Convert time diff to seconds, but cap at 12 hours (43200 seconds)
+ var secondsAway = Math.min(Math.floor(timeDiff / 1000), 43200);
// Calculate how many bubbles each clam would produce
var totalBP = 0;
// Calculate for each clam type
['basicClam', 'advancedClam', 'premiumClam'].forEach(function (clamType) {
@@ -710,11 +721,11 @@
// Calculate production time with speed upgrade
var baseTime = config.production;
var speedMultiplier = Math.pow(1 - UPGRADE_EFFECTS.autoBubbleSpeed.decrementPercent / 100, UPGRADE_CONFIG.machine.autoBubbleSpeed.currentLevel);
var adjustedTime = Math.max(1, baseTime * speedMultiplier);
- // Calculate bubbles per second
- var bubblesPerSecond = clamCount / adjustedTime;
- // Get base value of bubbles
+ // Calculate bubbles per second (ensure we're not dividing by zero)
+ var bubblesPerSecond = clamCount / Math.max(adjustedTime, 0.5);
+ // Get base value of bubbles - using the original formula
var bubbleValue = Math.pow(config.bubbleSize, 1.4) * 0.02;
// Apply quality upgrades
if (UPGRADE_CONFIG.machine.bubbleQuality.currentLevel > 0) {
bubbleValue *= 1 + 0.4 * UPGRADE_CONFIG.machine.bubbleQuality.currentLevel;
@@ -730,16 +741,19 @@
if (activeColorKey && UPGRADE_CONFIG.colors[activeColorKey]) {
colorMultiplier = UPGRADE_CONFIG.colors[activeColorKey].multiplier || 1.0;
}
bubbleValue *= colorMultiplier;
- // Calculate total BP this clam type would produce
- totalBP += bubblesPerSecond * bubbleValue * secondsAway;
+ // Calculate total BP this clam type would produce with a progressive penalty
+ // The longer you're away, the less efficient your clams become
+ var efficiencyFactor = Math.max(0.5, 1 - secondsAway / 86400); // Gradually drops to 50% over 24 hours
+ totalBP += bubblesPerSecond * bubbleValue * secondsAway * efficiencyFactor;
}
});
- // Apply a stronger offline penalty (25% of normal production)
- totalBP *= 0.25;
- // Apply a hard cap
- totalBP = Math.min(totalBP, 8000);
+ // Apply a stronger offline penalty (15% of normal production instead of 25%)
+ totalBP *= 0.15;
+ // Apply a progressive cap based on current BP to prevent huge jumps
+ var progressiveCap = Math.min(8000, Math.max(1000, game.bp * 0.5));
+ totalBP = Math.min(totalBP, progressiveCap);
// Round to integer
totalBP = Math.floor(totalBP);
// Add the BP and show a message
if (totalBP > 0) {
@@ -1005,8 +1019,15 @@
scaleY: 1
});
titleContainer.addChild(logo);
// Animate logo falling in
+ var savedActiveColor = storage.simpleUpgrades ? storage.simpleUpgrades.split(",")[13] || "auto" : "auto";
+ var savedColorUnlocks = storage.colorUnlocks ? storage.colorUnlocks.split(",") : [];
+ // Set temporary color settings for title screen
+ game.titleColorSettings = {
+ activeColor: savedActiveColor,
+ colorUnlocks: savedColorUnlocks
+ };
tween(logo, {
y: game.height / 2 - 300 // Stop at halfway mark
}, {
duration: 1500,
@@ -1107,8 +1128,42 @@
}
}
return UPGRADE_CONFIG.gameSettings.activeColor;
}
+// Add this new function outside of other functions
+function applyTitleScreenColor(bubble) {
+ if (!game.titleColorSettings) {
+ return;
+ }
+ var activeColorKey = game.titleColorSettings.activeColor;
+ var colorUnlocks = game.titleColorSettings.colorUnlocks;
+ // Check if we have color unlocks
+ if (colorUnlocks && colorUnlocks.length > 0) {
+ // Find highest unlocked color
+ var colorKeys = ["blueBubbles", "purpleBubbles", "greenBubbles", "orangeBubbles", "pinkBubbles", "tealBubbles", "goldBubbles", "crimsonBubbles", "silverBubbles", "rainbowBubbles", "prismaticBubbles"];
+ var color = 0xFFFFFF; // Default white
+ if (activeColorKey === "auto") {
+ // Auto mode - find highest unlocked color
+ for (var i = colorKeys.length - 1; i >= 0; i--) {
+ if (i < colorUnlocks.length && parseInt(colorUnlocks[i]) > 0) {
+ var key = colorKeys[i];
+ if (UPGRADE_CONFIG.colors[key]) {
+ color = UPGRADE_CONFIG.colors[key].color || 0xFFFFFF;
+ break;
+ }
+ }
+ }
+ } else if (UPGRADE_CONFIG.colors[activeColorKey]) {
+ // Specific color selected
+ color = UPGRADE_CONFIG.colors[activeColorKey].color || 0xFFFFFF;
+ }
+ // Apply the color
+ var bubbleSprite = bubble.children[0]; // Get the sprite of the bubble
+ if (bubbleSprite) {
+ bubbleSprite.tint = color;
+ }
+ }
+}
function setActiveColor(colorKey) {
if (colorKey === "auto" || UPGRADE_CONFIG.colors[colorKey].currentLevel > 0) {
UPGRADE_CONFIG.gameSettings.activeColor = colorKey;
// Update visual indicator in UI
@@ -1163,9 +1218,9 @@
tween(errorText, {
alpha: 0,
y: errorText.y - 50
}, {
- duration: 1200,
+ duration: 3000,
onFinish: function onFinish() {
errorText.destroy();
}
});
@@ -1188,9 +1243,9 @@
tween(messageText, {
alpha: 0,
y: messageText.y - 30
}, {
- duration: 1000,
+ duration: 3000,
onFinish: function onFinish() {
messageText.destroy();
}
});
@@ -2300,9 +2355,9 @@
game.lastMouthState = facekit.mouthOpen;
updateClams();
// Fish spawning (auto-pop upgrade)
if (UPGRADE_CONFIG.player.autoPop.currentLevel > 0) {
- if (LK.ticks % Math.max(60, 660 - UPGRADE_CONFIG.player.autoPop.currentLevel * 120) === 0) {
+ if (LK.ticks % Math.max(60, 960 - UPGRADE_CONFIG.player.autoPop.currentLevel * 120) === 0) {
var fish = new Fish();
game.addChild(fish);
// If menu is open, ensure fish is below menu
if (menuOpen) {
@@ -2335,15 +2390,33 @@
saveGame();
}
};
// Handle touch/mouse events for the game
+// Replace the game.down function with this improved version
game.down = function (x, y, obj) {
if (game.titleMode) {
return false; // Let containers handle their own clicks
}
+ // Check for bubbles first throughout the entire screen
+ var popped = false;
+ for (var i = game.activeBubbles.length - 1; i >= 0; i--) {
+ var bubble = game.activeBubbles[i];
+ var dx = x - bubble.x;
+ var dy = y - bubble.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= bubble.size / 2 + 50 && bubble.down) {
+ bubble.down();
+ popped = true;
+ break;
+ }
+ }
+ // If we popped a bubble, don't check for menu interaction
+ if (popped) {
+ return true;
+ }
+ // Now check for menu tab interaction
var localX = x - menuContainer.x;
var localY = y - menuContainer.y;
- // Tab click handling
var tabBounds = {
x: -menuTab.width * menuTab.scaleX / 2,
y: -menuTab.height * menuTab.scaleY,
width: menuTab.width * menuTab.scaleX,
@@ -2385,21 +2458,8 @@
}
if (menuOpen) {
return true; // Let containers handle their own clicks
}
- // Bubble popping logic
- var popped = false;
- for (var i = game.activeBubbles.length - 1; i >= 0; i--) {
- var bubble = game.activeBubbles[i];
- var dx = x - bubble.x;
- var dy = y - bubble.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (!popped && distance <= bubble.size / 2 + 50 && bubble.down) {
- bubble.down();
- popped = true;
- break;
- }
- }
};
// Initialize decoration visuals
updateClamVisuals();
updateTreasureDecorations();
A treasure chest with gold coins. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A golden skull with diamonds for eyes. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A golden necklace with a ruby pendant. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A filled in white circle.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A yellow star. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a game logo for a game called 'Bubble Blower Tycoon' about a happy purple pufferfish with yellow fins and spines that builds an underwater empire of bubbles. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
an SVG of the word 'Start'. word should be yellow and the font should look like its made out of bubbles. cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
bubblelow
Sound effect
backgroundmusic
Music
bubblehigh
Sound effect
bubble1
Sound effect
bubble2
Sound effect
bubble3
Sound effect
bubble4
Sound effect
blowing
Sound effect
bubbleshoot
Sound effect
fishtank
Sound effect
menuopen
Sound effect
upgrade
Sound effect
jellyfish
Sound effect
titlemusic
Music
startbutton
Sound effect