/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphic = self.attachAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPopped = false;
self.initialScale = 1;
self.pop = function () {
if (self.isPopped) {
return;
}
self.isPopped = true;
LK.getSound('pop').play();
// First shrink slightly
tween(bubbleGraphic, {
scaleX: 0.85,
scaleY: 0.85,
alpha: 0.8
}, {
duration: 60,
easing: tween.easeOut,
onFinish: function onFinish() {
// Then expand and fade out
tween(bubbleGraphic, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.onPopped) {
self.onPopped();
}
}
});
}
});
};
self.reset = function () {
self.isPopped = false;
bubbleGraphic.scaleX = self.initialScale;
bubbleGraphic.scaleY = self.initialScale;
bubbleGraphic.alpha = 1;
};
self.down = function (x, y, obj) {
self.pop();
};
return self;
});
var RestartButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphic = self.attachAsset('restartButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
resetGame();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x48d1cc // Cyan color for background
});
/****
* Game Code
****/
var paperTexture = game.attachAsset('crumpledPaper', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(paperTexture);
// Configuration
var bubbleSize = 150;
var bubblePadding = 30;
var bubbleCount = 0;
var totalBubbles = 0;
var bubbles = [];
var columns = 0;
var rows = 0;
// Text for remaining bubbles
var remainingBubblesTxt = new Text2('Bubbles: 0', {
size: 80,
fill: 0x000000
});
remainingBubblesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(remainingBubblesTxt);
// Initialize the game layout
function initializeGame() {
// Calculate grid layout based on screen dimensions
var gameWidth = 2048;
var gameHeight = 2732;
// Calculate how many bubbles we can fit
columns = Math.floor((gameWidth - bubblePadding) / (bubbleSize + bubblePadding));
rows = Math.floor((gameHeight - 200 - bubblePadding) / (bubbleSize + bubblePadding)); // Save space for UI
// Center grid horizontally
var startX = (gameWidth - (columns * (bubbleSize + bubblePadding) - bubblePadding)) / 2 + bubbleSize / 2;
var startY = 200 + bubbleSize / 2; // Start below UI area
// Clear existing bubbles if any
for (var i = 0; i < bubbles.length; i++) {
if (bubbles[i] && bubbles[i].parent) {
bubbles[i].parent.removeChild(bubbles[i]);
}
}
bubbles = [];
bubbleCount = 0;
totalBubbles = columns * rows;
// Create bubbles grid
for (var row = 0; row < rows; row++) {
for (var col = 0; col < columns; col++) {
var bubble = new Bubble();
bubble.x = startX + col * (bubbleSize + bubblePadding);
bubble.y = startY + row * (bubbleSize + bubblePadding);
// Random size variation for more natural look
var scale = 0.85 + Math.random() * 0.3;
bubble.initialScale = scale;
bubble.getChildAt(0).scale.set(scale, scale);
// Callback when bubble is popped
bubble.onPopped = function () {
bubbleCount++;
updateUI();
// Check win condition
if (bubbleCount >= totalBubbles) {
LK.setTimeout(resetGame, 1500);
}
};
game.addChild(bubble);
bubbles.push(bubble);
}
}
updateUI();
}
// Update UI elements
function updateUI() {
remainingBubblesTxt.setText('Bubbles: ' + bubbleCount + ' / ' + totalBubbles);
}
// Reset the game
function resetGame() {
initializeGame();
LK.getSound('girlVoice').play();
}
// Initialize game on start
LK.setTimeout(function () {
initializeGame();
// Play background music
LK.playMusic('relaxMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
LK.getSound('girlVoice').play();
// Initialize restart button
var restartButton = new RestartButton();
restartButton.x = 2048 - 100; // Position the button 100 pixels from the right edge
restartButton.y = 100; // Position the button 100 pixels from the top edge
game.addChild(restartButton);
}, 500);
// Mouse/touch handlers for game area
game.down = function (x, y, obj) {
// This is handled by individual bubbles
};
// Drag-to-pop: pop bubbles when dragging over them
game.move = function (x, y, obj) {
// For each bubble, check if the pointer is inside and not already popped
for (var i = 0; i < bubbles.length; i++) {
var bubble = bubbles[i];
if (!bubble.isPopped) {
// Calculate distance from pointer to bubble center
var dx = x - bubble.x;
var dy = y - bubble.y;
var radius = bubble.getChildAt(0).width * bubble.getChildAt(0).scaleX / 2;
if (dx * dx + dy * dy <= radius * radius) {
bubble.pop();
}
}
}
};
// Update function called every frame
game.update = function () {
// No additional per-frame logic needed as bubbles handle their own popping
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphic = self.attachAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPopped = false;
self.initialScale = 1;
self.pop = function () {
if (self.isPopped) {
return;
}
self.isPopped = true;
LK.getSound('pop').play();
// First shrink slightly
tween(bubbleGraphic, {
scaleX: 0.85,
scaleY: 0.85,
alpha: 0.8
}, {
duration: 60,
easing: tween.easeOut,
onFinish: function onFinish() {
// Then expand and fade out
tween(bubbleGraphic, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.onPopped) {
self.onPopped();
}
}
});
}
});
};
self.reset = function () {
self.isPopped = false;
bubbleGraphic.scaleX = self.initialScale;
bubbleGraphic.scaleY = self.initialScale;
bubbleGraphic.alpha = 1;
};
self.down = function (x, y, obj) {
self.pop();
};
return self;
});
var RestartButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphic = self.attachAsset('restartButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
resetGame();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x48d1cc // Cyan color for background
});
/****
* Game Code
****/
var paperTexture = game.attachAsset('crumpledPaper', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(paperTexture);
// Configuration
var bubbleSize = 150;
var bubblePadding = 30;
var bubbleCount = 0;
var totalBubbles = 0;
var bubbles = [];
var columns = 0;
var rows = 0;
// Text for remaining bubbles
var remainingBubblesTxt = new Text2('Bubbles: 0', {
size: 80,
fill: 0x000000
});
remainingBubblesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(remainingBubblesTxt);
// Initialize the game layout
function initializeGame() {
// Calculate grid layout based on screen dimensions
var gameWidth = 2048;
var gameHeight = 2732;
// Calculate how many bubbles we can fit
columns = Math.floor((gameWidth - bubblePadding) / (bubbleSize + bubblePadding));
rows = Math.floor((gameHeight - 200 - bubblePadding) / (bubbleSize + bubblePadding)); // Save space for UI
// Center grid horizontally
var startX = (gameWidth - (columns * (bubbleSize + bubblePadding) - bubblePadding)) / 2 + bubbleSize / 2;
var startY = 200 + bubbleSize / 2; // Start below UI area
// Clear existing bubbles if any
for (var i = 0; i < bubbles.length; i++) {
if (bubbles[i] && bubbles[i].parent) {
bubbles[i].parent.removeChild(bubbles[i]);
}
}
bubbles = [];
bubbleCount = 0;
totalBubbles = columns * rows;
// Create bubbles grid
for (var row = 0; row < rows; row++) {
for (var col = 0; col < columns; col++) {
var bubble = new Bubble();
bubble.x = startX + col * (bubbleSize + bubblePadding);
bubble.y = startY + row * (bubbleSize + bubblePadding);
// Random size variation for more natural look
var scale = 0.85 + Math.random() * 0.3;
bubble.initialScale = scale;
bubble.getChildAt(0).scale.set(scale, scale);
// Callback when bubble is popped
bubble.onPopped = function () {
bubbleCount++;
updateUI();
// Check win condition
if (bubbleCount >= totalBubbles) {
LK.setTimeout(resetGame, 1500);
}
};
game.addChild(bubble);
bubbles.push(bubble);
}
}
updateUI();
}
// Update UI elements
function updateUI() {
remainingBubblesTxt.setText('Bubbles: ' + bubbleCount + ' / ' + totalBubbles);
}
// Reset the game
function resetGame() {
initializeGame();
LK.getSound('girlVoice').play();
}
// Initialize game on start
LK.setTimeout(function () {
initializeGame();
// Play background music
LK.playMusic('relaxMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
LK.getSound('girlVoice').play();
// Initialize restart button
var restartButton = new RestartButton();
restartButton.x = 2048 - 100; // Position the button 100 pixels from the right edge
restartButton.y = 100; // Position the button 100 pixels from the top edge
game.addChild(restartButton);
}, 500);
// Mouse/touch handlers for game area
game.down = function (x, y, obj) {
// This is handled by individual bubbles
};
// Drag-to-pop: pop bubbles when dragging over them
game.move = function (x, y, obj) {
// For each bubble, check if the pointer is inside and not already popped
for (var i = 0; i < bubbles.length; i++) {
var bubble = bubbles[i];
if (!bubble.isPopped) {
// Calculate distance from pointer to bubble center
var dx = x - bubble.x;
var dy = y - bubble.y;
var radius = bubble.getChildAt(0).width * bubble.getChildAt(0).scaleX / 2;
if (dx * dx + dy * dy <= radius * radius) {
bubble.pop();
}
}
}
};
// Update function called every frame
game.update = function () {
// No additional per-frame logic needed as bubbles handle their own popping
};