/**** * Classes ****/ var Bubble = Container.expand(function () { var self = Container.call(this); self.isRed = false; self.speed = { x: 0, y: 0 }; self.bubbleGraphics = null; self.setup = function (isRed) { self.isRed = isRed; // Choose asset based on bubble type var assetId = isRed ? 'R0' : 'B0'; self.bubbleGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Set random speed self.speed = { x: Math.random() * 4 - 2, y: Math.random() * 4 - 2 }; }; self.update = function () { // Move bubble self.x += self.speed.x; self.y += self.speed.y; // Bounce off walls if (self.x < 0 || self.x > 2048) { self.speed.x *= -1; } if (self.y < 0 || self.y > 2732) { self.speed.y *= -1; } }; // Handle tap/click on bubble self.down = function (x, y, obj) { if (self.isRed) { // Play lose sound effect when red bubble is tapped LK.getSound('Lse').play(); LK.effects.flashScreen(0xff0000, 500); LK.showGameOver(); return; } // Play bubble pop sound immediately after tap LK.getSound('Bubpop').play(); // Increase score if blue bubble is popped LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); // Remove this bubble self.destroy(); // Find and remove from bubbles array var index = bubbles.indexOf(self); if (index > -1) { bubbles.splice(index, 1); } // If all blue bubbles are popped, create a new wave if (bubbles.length === 1 && bubbles[0].isRed) { createBubbleWave(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ game.setBackgroundColor(0x87CEEB); // Light blue background // Track game state var gameStarted = false; // Array to hold all bubble instances var bubbles = []; // Create score text var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create welcome message var welcomeTxt = new Text2('Tap to Start', { size: 120, fill: 0xFFFFFF }); welcomeTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(welcomeTxt); // Function to create a new wave of bubbles function createBubbleWave() { // Clear existing bubbles if any for (var i = bubbles.length - 1; i >= 0; i--) { bubbles[i].destroy(); } bubbles = []; // Determine number of bubbles based on score var numBubbles = Math.min(5 + Math.floor(LK.getScore() / 5), 20); // Helper to avoid overlapping bubbles at spawn function getNonOverlappingPosition(existingBubbles, radius) { var maxTries = 100; for (var t = 0; t < maxTries; t++) { var x = Math.random() * (2048 - 2 * radius - 100) + radius + 50; var y = Math.random() * (2732 - 2 * radius - 100) + radius + 50; var overlap = false; for (var j = 0; j < existingBubbles.length; j++) { var dx = x - existingBubbles[j].x; var dy = y - existingBubbles[j].y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < radius * 2 + 10) { // 10px buffer overlap = true; break; } } if (!overlap) return { x: x, y: y }; } // fallback: just return a random position return { x: Math.random() * (2048 - 2 * radius - 100) + radius + 50, y: Math.random() * (2732 - 2 * radius - 100) + radius + 50 }; } // Get bubble radius from asset size (assuming all bubbles same size) var tempBubble = new Bubble(); tempBubble.setup(false); var bubbleRadius = tempBubble.bubbleGraphics.width * 1.5 / 2; tempBubble.destroy(); // Create blue bubbles for (var i = 0; i < numBubbles - 1; i++) { var bubble = new Bubble(); bubble.setup(false); // false = blue bubble var pos = getNonOverlappingPosition(bubbles, bubbleRadius); bubble.x = pos.x; bubble.y = pos.y; game.addChild(bubble); bubbles.push(bubble); } // Create one red bubble var redBubble = new Bubble(); redBubble.setup(true); // true = red bubble var posRed = getNonOverlappingPosition(bubbles, bubbleRadius); redBubble.x = posRed.x; redBubble.y = posRed.y; game.addChild(redBubble); bubbles.push(redBubble); } // Update game every frame game.update = function () { // Only update and create bubbles if game has started if (gameStarted) { // Update all bubbles for (var i = 0; i < bubbles.length; i++) { bubbles[i].update(); } // Create bubbles if none exist if (bubbles.length === 0) { createBubbleWave(); } } // Play lose sound effect when game over message is shown if (typeof LK !== "undefined" && typeof LK.isGameOver === "function" && LK.isGameOver()) { if (!game._loseSoundPlayed) { LK.getSound('De').play(); LK.stopMusic(); game._loseSoundPlayed = true; } } else { game._loseSoundPlayed = false; } }; // Create instructions text var instructionsTxt = new Text2('Pop the BLUE bubbles\nAvoid the RED one!', { size: 80, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionsTxt); // Hide instructions until game starts instructionsTxt.alpha = 0; // Add click event to start game game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; welcomeTxt.alpha = 0; instructionsTxt.alpha = 1; // Play background music LK.playMusic('Jb'); // Start the game createBubbleWave(); // Hide instructions after 3 seconds LK.setTimeout(function () { instructionsTxt.alpha = 0; }, 3000); } };
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
self.isRed = false;
self.speed = {
x: 0,
y: 0
};
self.bubbleGraphics = null;
self.setup = function (isRed) {
self.isRed = isRed;
// Choose asset based on bubble type
var assetId = isRed ? 'R0' : 'B0';
self.bubbleGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Set random speed
self.speed = {
x: Math.random() * 4 - 2,
y: Math.random() * 4 - 2
};
};
self.update = function () {
// Move bubble
self.x += self.speed.x;
self.y += self.speed.y;
// Bounce off walls
if (self.x < 0 || self.x > 2048) {
self.speed.x *= -1;
}
if (self.y < 0 || self.y > 2732) {
self.speed.y *= -1;
}
};
// Handle tap/click on bubble
self.down = function (x, y, obj) {
if (self.isRed) {
// Play lose sound effect when red bubble is tapped
LK.getSound('Lse').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Play bubble pop sound immediately after tap
LK.getSound('Bubpop').play();
// Increase score if blue bubble is popped
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Remove this bubble
self.destroy();
// Find and remove from bubbles array
var index = bubbles.indexOf(self);
if (index > -1) {
bubbles.splice(index, 1);
}
// If all blue bubbles are popped, create a new wave
if (bubbles.length === 1 && bubbles[0].isRed) {
createBubbleWave();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
game.setBackgroundColor(0x87CEEB); // Light blue background
// Track game state
var gameStarted = false;
// Array to hold all bubble instances
var bubbles = [];
// Create score text
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create welcome message
var welcomeTxt = new Text2('Tap to Start', {
size: 120,
fill: 0xFFFFFF
});
welcomeTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(welcomeTxt);
// Function to create a new wave of bubbles
function createBubbleWave() {
// Clear existing bubbles if any
for (var i = bubbles.length - 1; i >= 0; i--) {
bubbles[i].destroy();
}
bubbles = [];
// Determine number of bubbles based on score
var numBubbles = Math.min(5 + Math.floor(LK.getScore() / 5), 20);
// Helper to avoid overlapping bubbles at spawn
function getNonOverlappingPosition(existingBubbles, radius) {
var maxTries = 100;
for (var t = 0; t < maxTries; t++) {
var x = Math.random() * (2048 - 2 * radius - 100) + radius + 50;
var y = Math.random() * (2732 - 2 * radius - 100) + radius + 50;
var overlap = false;
for (var j = 0; j < existingBubbles.length; j++) {
var dx = x - existingBubbles[j].x;
var dy = y - existingBubbles[j].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < radius * 2 + 10) {
// 10px buffer
overlap = true;
break;
}
}
if (!overlap) return {
x: x,
y: y
};
}
// fallback: just return a random position
return {
x: Math.random() * (2048 - 2 * radius - 100) + radius + 50,
y: Math.random() * (2732 - 2 * radius - 100) + radius + 50
};
}
// Get bubble radius from asset size (assuming all bubbles same size)
var tempBubble = new Bubble();
tempBubble.setup(false);
var bubbleRadius = tempBubble.bubbleGraphics.width * 1.5 / 2;
tempBubble.destroy();
// Create blue bubbles
for (var i = 0; i < numBubbles - 1; i++) {
var bubble = new Bubble();
bubble.setup(false); // false = blue bubble
var pos = getNonOverlappingPosition(bubbles, bubbleRadius);
bubble.x = pos.x;
bubble.y = pos.y;
game.addChild(bubble);
bubbles.push(bubble);
}
// Create one red bubble
var redBubble = new Bubble();
redBubble.setup(true); // true = red bubble
var posRed = getNonOverlappingPosition(bubbles, bubbleRadius);
redBubble.x = posRed.x;
redBubble.y = posRed.y;
game.addChild(redBubble);
bubbles.push(redBubble);
}
// Update game every frame
game.update = function () {
// Only update and create bubbles if game has started
if (gameStarted) {
// Update all bubbles
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].update();
}
// Create bubbles if none exist
if (bubbles.length === 0) {
createBubbleWave();
}
}
// Play lose sound effect when game over message is shown
if (typeof LK !== "undefined" && typeof LK.isGameOver === "function" && LK.isGameOver()) {
if (!game._loseSoundPlayed) {
LK.getSound('De').play();
LK.stopMusic();
game._loseSoundPlayed = true;
}
} else {
game._loseSoundPlayed = false;
}
};
// Create instructions text
var instructionsTxt = new Text2('Pop the BLUE bubbles\nAvoid the RED one!', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionsTxt);
// Hide instructions until game starts
instructionsTxt.alpha = 0;
// Add click event to start game
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
welcomeTxt.alpha = 0;
instructionsTxt.alpha = 1;
// Play background music
LK.playMusic('Jb');
// Start the game
createBubbleWave();
// Hide instructions after 3 seconds
LK.setTimeout(function () {
instructionsTxt.alpha = 0;
}, 3000);
}
};