/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bubble = Container.expand(function () { var self = Container.call(this); self.isGolden = false; self.isForbidden = false; self.bubbleSize = 1; self.speed = 2; self.floatSpeed = 0; self.floatAmplitude = 0; self.floatOffset = 0; self.bubbleGraphics = null; self.skullOverlay = null; self.init = function (size, golden, forbidden, colorType) { self.bubbleSize = size; self.isGolden = golden || false; self.isForbidden = forbidden || false; self.colorType = colorType || 'red'; // default to red if not specified // Choose assetId based on type var assetId = 'bubble'; if (self.isGolden) assetId = 'goldenBubble';else if (self.isForbidden) assetId = 'forbiddenBalloon';else if (self.colorType === 'blue') assetId = 'blueBalloon';else if (self.colorType === 'green') assetId = 'Blue'; // using 'Blue' asset for green for now else if (self.colorType === 'yellow') assetId = 'goldenBubble'; // yellow uses goldenBubble asset for now self.bubbleGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, scaleX: size, scaleY: size }); // Add shimmer effect to golden bubbles if (golden) { self.bubbleGraphics.alpha = 0.9; } // Add skull overlay for forbidden balloon if (self.isForbidden) { self.skullOverlay = self.attachAsset('skull', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7 * size, scaleY: 0.7 * size }); } // Set speed based on size (smaller = faster) self.speed = 2 + (1 - size) * 3; // Random floating movement self.floatSpeed = 0.02 + Math.random() * 0.02; self.floatAmplitude = 20 + Math.random() * 30; self.floatOffset = Math.random() * Math.PI * 2; }; self.update = function () { // Move upward self.y -= self.speed; // Floating side-to-side movement self.x += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * self.floatAmplitude * 0.05; }; self.getPoints = function () { if (self.isGolden) { return 50; } if (self.isForbidden) { return 0; } // Smaller bubbles worth more points return Math.floor((2 - self.bubbleSize) * 20 + 5); }; return self; }); var Needle = Container.expand(function () { var self = Container.call(this); var needleGraphics = self.attachAsset('needle', { anchorX: 0.5, anchorY: 1.0 }); // Add a sharp point indicator at the top var point = self.attachAsset('needle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, y: -180 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Set background image using the 'Set' asset var background = LK.getAsset('Set', { anchorX: 0, anchorY: 0, scaleX: 2048 / 100, scaleY: 2732 / 100, x: 0, y: 0 }); game.addChild(background); // skull overlay // black balloon // Game variables var needle; var bubbles = []; var missedBubbles = 0; var maxMissedBubbles = 100; var spawnTimer = 0; var spawnDelay = 60; var difficultyTimer = 0; var goldenBubbleChance = 0.05; // UI elements var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var missedTxt = new Text2('Missed: 0/' + maxMissedBubbles, { size: 60, fill: 0xFF0000 }); missedTxt.anchor.set(1, 0); missedTxt.x = -20; LK.gui.topRight.addChild(missedTxt); // Create needle needle = game.addChild(new Needle()); needle.x = 1024; needle.y = 2400; // Dragging logic var dragNode = null; game.down = function (x, y, obj) { dragNode = needle; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; }; function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; } } game.move = handleMove; // Game update loop game.update = function () { // Increase difficulty based on score and time difficultyTimer++; // Make spawnDelay decrease faster as score increases var score = LK.getScore(); if (difficultyTimer % 300 === 0 && spawnDelay > 10) { // Decrease spawn delay more rapidly as score increases if (score > 200) { spawnDelay -= 6; } else if (score > 100) { spawnDelay -= 4; } else { spawnDelay -= 2; } if (spawnDelay < 10) spawnDelay = 10; } // Also, increase all bubble speeds slightly as score increases for (var i = 0; i < bubbles.length; i++) { if (score > 200) { bubbles[i].speed += 0.03; } else if (score > 100) { bubbles[i].speed += 0.02; } else if (score > 50) { bubbles[i].speed += 0.01; } } // Spawn bubbles spawnTimer++; if (spawnTimer >= spawnDelay) { spawnTimer = 0; spawnBubble(); } // Update bubbles for (var i = bubbles.length - 1; i >= 0; i--) { var bubble = bubbles[i]; // Track last position if (bubble.lastY === undefined) bubble.lastY = bubble.y; if (bubble.lastPopped === undefined) bubble.lastPopped = false; // Check if bubble escaped off screen if (bubble.lastY > -100 && bubble.y <= -100) { if (!bubble.isGolden && !bubble.skullOverlay) { missedBubbles++; missedTxt.setText('Missed: ' + missedBubbles + '/' + maxMissedBubbles); LK.getSound('miss').play(); if (missedBubbles >= maxMissedBubbles) { LK.showGameOver(); } } bubble.destroy(); bubbles.splice(i, 1); continue; } // Check collision with needle var currentPopped = bubble.intersects(needle); if (!bubble.lastPopped && currentPopped) { // If this is a skull (skullOverlay present), lose immediately if (bubble.skullOverlay) { // Immediate game over effect LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); // Remove the bubble bubble.destroy(); bubbles.splice(i, 1); continue; } else { // Only pop and score for non-skull balloons var points = bubble.getPoints(); LK.setScore(LK.getScore() + points); scoreTxt.setText('Score: ' + LK.getScore()); // Play appropriate sound if (bubble.isGolden) { LK.getSound('bonus').play(); LK.effects.flashScreen(0xFFD700, 300); } else { LK.getSound('pop').play(); } // Visual pop effect tween(bubble, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { bubble.destroy(); } }); bubbles.splice(i, 1); continue; } } bubble.lastY = bubble.y; bubble.lastPopped = currentPopped; } }; function spawnBubble() { var bubble = new Bubble(); // Random size between 0.5 and 1.5 var size = 0.5 + Math.random(); // Increase golden bubble chance as score increases var score = LK.getScore(); var dynamicGoldenChance = goldenBubbleChance; if (score > 200) { dynamicGoldenChance = 0.12; } else if (score > 100) { dynamicGoldenChance = 0.09; } else if (score > 50) { dynamicGoldenChance = 0.07; } var isGolden = false; var isForbidden = false; // 10% chance for forbidden balloon, but never both golden and forbidden var forbiddenChance = 0.10 + Math.min(0.10, score / 1000); // up to 20% at high score var rand = Math.random(); if (rand < dynamicGoldenChance) { isGolden = true; } else if (rand < dynamicGoldenChance + forbiddenChance) { isForbidden = true; } // Pick a color for normal bubbles (not golden, not forbidden) var colorType = 'red'; if (!isGolden && !isForbidden) { // Randomly pick between red, blue, green, yellow var colorOptions = ['red', 'blue', 'green', 'yellow']; colorType = colorOptions[Math.floor(Math.random() * colorOptions.length)]; } bubble.init(size, isGolden, isForbidden, colorType); // Random x position bubble.x = 100 + Math.random() * 1848; bubble.y = 2832; bubbles.push(bubble); game.addChild(bubble); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
self.isGolden = false;
self.isForbidden = false;
self.bubbleSize = 1;
self.speed = 2;
self.floatSpeed = 0;
self.floatAmplitude = 0;
self.floatOffset = 0;
self.bubbleGraphics = null;
self.skullOverlay = null;
self.init = function (size, golden, forbidden, colorType) {
self.bubbleSize = size;
self.isGolden = golden || false;
self.isForbidden = forbidden || false;
self.colorType = colorType || 'red'; // default to red if not specified
// Choose assetId based on type
var assetId = 'bubble';
if (self.isGolden) assetId = 'goldenBubble';else if (self.isForbidden) assetId = 'forbiddenBalloon';else if (self.colorType === 'blue') assetId = 'blueBalloon';else if (self.colorType === 'green') assetId = 'Blue'; // using 'Blue' asset for green for now
else if (self.colorType === 'yellow') assetId = 'goldenBubble'; // yellow uses goldenBubble asset for now
self.bubbleGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size,
scaleY: size
});
// Add shimmer effect to golden bubbles
if (golden) {
self.bubbleGraphics.alpha = 0.9;
}
// Add skull overlay for forbidden balloon
if (self.isForbidden) {
self.skullOverlay = self.attachAsset('skull', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7 * size,
scaleY: 0.7 * size
});
}
// Set speed based on size (smaller = faster)
self.speed = 2 + (1 - size) * 3;
// Random floating movement
self.floatSpeed = 0.02 + Math.random() * 0.02;
self.floatAmplitude = 20 + Math.random() * 30;
self.floatOffset = Math.random() * Math.PI * 2;
};
self.update = function () {
// Move upward
self.y -= self.speed;
// Floating side-to-side movement
self.x += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * self.floatAmplitude * 0.05;
};
self.getPoints = function () {
if (self.isGolden) {
return 50;
}
if (self.isForbidden) {
return 0;
}
// Smaller bubbles worth more points
return Math.floor((2 - self.bubbleSize) * 20 + 5);
};
return self;
});
var Needle = Container.expand(function () {
var self = Container.call(this);
var needleGraphics = self.attachAsset('needle', {
anchorX: 0.5,
anchorY: 1.0
});
// Add a sharp point indicator at the top
var point = self.attachAsset('needle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
y: -180
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Set background image using the 'Set' asset
var background = LK.getAsset('Set', {
anchorX: 0,
anchorY: 0,
scaleX: 2048 / 100,
scaleY: 2732 / 100,
x: 0,
y: 0
});
game.addChild(background);
// skull overlay
// black balloon
// Game variables
var needle;
var bubbles = [];
var missedBubbles = 0;
var maxMissedBubbles = 100;
var spawnTimer = 0;
var spawnDelay = 60;
var difficultyTimer = 0;
var goldenBubbleChance = 0.05;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var missedTxt = new Text2('Missed: 0/' + maxMissedBubbles, {
size: 60,
fill: 0xFF0000
});
missedTxt.anchor.set(1, 0);
missedTxt.x = -20;
LK.gui.topRight.addChild(missedTxt);
// Create needle
needle = game.addChild(new Needle());
needle.x = 1024;
needle.y = 2400;
// Dragging logic
var dragNode = null;
game.down = function (x, y, obj) {
dragNode = needle;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
}
}
game.move = handleMove;
// Game update loop
game.update = function () {
// Increase difficulty based on score and time
difficultyTimer++;
// Make spawnDelay decrease faster as score increases
var score = LK.getScore();
if (difficultyTimer % 300 === 0 && spawnDelay > 10) {
// Decrease spawn delay more rapidly as score increases
if (score > 200) {
spawnDelay -= 6;
} else if (score > 100) {
spawnDelay -= 4;
} else {
spawnDelay -= 2;
}
if (spawnDelay < 10) spawnDelay = 10;
}
// Also, increase all bubble speeds slightly as score increases
for (var i = 0; i < bubbles.length; i++) {
if (score > 200) {
bubbles[i].speed += 0.03;
} else if (score > 100) {
bubbles[i].speed += 0.02;
} else if (score > 50) {
bubbles[i].speed += 0.01;
}
}
// Spawn bubbles
spawnTimer++;
if (spawnTimer >= spawnDelay) {
spawnTimer = 0;
spawnBubble();
}
// Update bubbles
for (var i = bubbles.length - 1; i >= 0; i--) {
var bubble = bubbles[i];
// Track last position
if (bubble.lastY === undefined) bubble.lastY = bubble.y;
if (bubble.lastPopped === undefined) bubble.lastPopped = false;
// Check if bubble escaped off screen
if (bubble.lastY > -100 && bubble.y <= -100) {
if (!bubble.isGolden && !bubble.skullOverlay) {
missedBubbles++;
missedTxt.setText('Missed: ' + missedBubbles + '/' + maxMissedBubbles);
LK.getSound('miss').play();
if (missedBubbles >= maxMissedBubbles) {
LK.showGameOver();
}
}
bubble.destroy();
bubbles.splice(i, 1);
continue;
}
// Check collision with needle
var currentPopped = bubble.intersects(needle);
if (!bubble.lastPopped && currentPopped) {
// If this is a skull (skullOverlay present), lose immediately
if (bubble.skullOverlay) {
// Immediate game over effect
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
// Remove the bubble
bubble.destroy();
bubbles.splice(i, 1);
continue;
} else {
// Only pop and score for non-skull balloons
var points = bubble.getPoints();
LK.setScore(LK.getScore() + points);
scoreTxt.setText('Score: ' + LK.getScore());
// Play appropriate sound
if (bubble.isGolden) {
LK.getSound('bonus').play();
LK.effects.flashScreen(0xFFD700, 300);
} else {
LK.getSound('pop').play();
}
// Visual pop effect
tween(bubble, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
bubble.destroy();
}
});
bubbles.splice(i, 1);
continue;
}
}
bubble.lastY = bubble.y;
bubble.lastPopped = currentPopped;
}
};
function spawnBubble() {
var bubble = new Bubble();
// Random size between 0.5 and 1.5
var size = 0.5 + Math.random();
// Increase golden bubble chance as score increases
var score = LK.getScore();
var dynamicGoldenChance = goldenBubbleChance;
if (score > 200) {
dynamicGoldenChance = 0.12;
} else if (score > 100) {
dynamicGoldenChance = 0.09;
} else if (score > 50) {
dynamicGoldenChance = 0.07;
}
var isGolden = false;
var isForbidden = false;
// 10% chance for forbidden balloon, but never both golden and forbidden
var forbiddenChance = 0.10 + Math.min(0.10, score / 1000); // up to 20% at high score
var rand = Math.random();
if (rand < dynamicGoldenChance) {
isGolden = true;
} else if (rand < dynamicGoldenChance + forbiddenChance) {
isForbidden = true;
}
// Pick a color for normal bubbles (not golden, not forbidden)
var colorType = 'red';
if (!isGolden && !isForbidden) {
// Randomly pick between red, blue, green, yellow
var colorOptions = ['red', 'blue', 'green', 'yellow'];
colorType = colorOptions[Math.floor(Math.random() * colorOptions.length)];
}
bubble.init(size, isGolden, isForbidden, colorType);
// Random x position
bubble.x = 100 + Math.random() * 1848;
bubble.y = 2832;
bubbles.push(bubble);
game.addChild(bubble);
}
Skapa en realistic nål. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Create a cool sky background. In-Game asset. 2d. No shadows
Black Ballon with white skull on. In-Game asset. 2d. No shadows
Create a green Ballon with happy face. In-Game asset. 2d. No shadows