/****
* 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);
}
};