/****
* 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