/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Balloon class (player) var Balloon = Container.expand(function () { var self = Container.call(this); // Shadow var shadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5, y: 180 }); shadow.alpha = 0.18; // Balloon body var balloon = self.attachAsset('balloon', { anchorX: 0.5, anchorY: 0.5 }); // For a little bounce effect on move self.bounce = function () { tween(self, { scaleX: 1.08, scaleY: 0.92 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); } }); }; // For a little shake on hit self.shake = function () { tween(self, { x: self.x + 30 }, { duration: 60, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: self.x - 60 }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: self.x + 30 }, { duration: 60, easing: tween.linear }); } }); } }); }; return self; }); // Spike class (obstacle) var Spike = Container.expand(function () { var self = Container.call(this); var spike = self.attachAsset('spike', { anchorX: 0.5, anchorY: 0.5 }); // For a little rotation self.rotationSpeed = (Math.random() - 0.5) * 0.04; // Speed will be set on spawn self.speedY = 8; // Update method self.update = function () { self.y += self.speedY; spike.rotation += self.rotationSpeed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // LK.init.sound('spike_spawn', {volume: 0.4}); // Sound for spike spawn (optional, can be omitted if not wanted) // Shadow for balloon // Spike (obstacle) // Balloon (player) // Game area var GAME_W = 2048; var GAME_H = 2732; // Balloon spawn position (centered horizontally, 80% down) var BALLOON_START_X = GAME_W / 2; var BALLOON_START_Y = GAME_H * 0.8; // Balloon instance var balloon = new Balloon(); balloon.x = BALLOON_START_X; balloon.y = BALLOON_START_Y; game.addChild(balloon); // Obstacles array var spikes = []; // Score var score = 0; var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Time survived (for increasing difficulty) var elapsedTicks = 0; // Dragging var dragNode = null; // For collision detection var lastColliding = false; // For spike spawn timing var spikeSpawnTick = 0; var spikeSpawnInterval = 90; // Initial interval (ticks) // Move handler (drag balloon) function handleMove(x, y, obj) { if (dragNode) { // Clamp balloon inside game area (with margin) var margin = 100; var bx = Math.max(margin, Math.min(GAME_W - margin, x)); var by = Math.max(margin + 100, Math.min(GAME_H - margin, y)); dragNode.x = bx; dragNode.y = by; dragNode.bounce(); } // Collision detection var colliding = false; for (var i = 0; i < spikes.length; i++) { if (balloon.intersects(spikes[i])) { colliding = true; break; } } // Always check collision, not just when dragging if (!lastColliding && colliding) { // Hit! balloon.shake(); LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } lastColliding = colliding; } // Touch/drag events game.down = function (x, y, obj) { // Only start drag if touch is on balloon or close to it var dx = x - balloon.x; var dy = y - balloon.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 180) { dragNode = balloon; handleMove(x, y, obj); } }; game.move = handleMove; game.up = function (x, y, obj) { dragNode = null; }; // Main update loop game.update = function () { elapsedTicks++; // Increase difficulty over time if (elapsedTicks % 600 === 0 && spikeSpawnInterval > 30) { spikeSpawnInterval -= 8; // Spikes spawn more often } // Extra difficulty after score 10 if (score >= 10) { spikeSpawnInterval = Math.max(18, spikeSpawnInterval - 1); // Faster spawn } // Spawn spikes spikeSpawnTick++; if (spikeSpawnTick >= spikeSpawnInterval) { spikeSpawnTick = 0; // Random X position (avoid spawning at extreme edges) var margin = 160; var sx = margin + Math.random() * (GAME_W - 2 * margin); // Create spike var spike = new Spike(); spike.x = sx; spike.y = -60; // Speed increases with time var minSpeed = 10 + Math.floor(elapsedTicks / 600) * 2; var maxSpeed = 18 + Math.floor(elapsedTicks / 600) * 2; if (score >= 10) { minSpeed += 6; maxSpeed += 8; } spike.speedY = minSpeed + Math.random() * (maxSpeed - minSpeed); spikes.push(spike); game.addChild(spike); // Optionally play sound // LK.getSound('spike_spawn').play(); } // Update spikes for (var i = spikes.length - 1; i >= 0; i--) { var s = spikes[i]; s.update(); // If spike goes off screen, remove and increase score if (s.y > GAME_H + 100) { s.destroy(); spikes.splice(i, 1); score++; scoreTxt.setText(score); } } ; // Also check collision if not dragging (so player can't avoid game over by not touching) var colliding = false; for (var i = 0; i < spikes.length; i++) { if (balloon.intersects(spikes[i])) { colliding = true; break; } } if (!lastColliding && colliding) { balloon.shake(); LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } lastColliding = colliding; }; // Center score text horizontally scoreTxt.setText(score); scoreTxt.anchor.set(0.5, 0); // Place score at top center, but not in top 100px (menu area) scoreTxt.y = 40; // Set background color (already set in init, but can be changed here if needed) // game.setBackgroundColor(0xb3e0ff);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Balloon class (player)
var Balloon = Container.expand(function () {
var self = Container.call(this);
// Shadow
var shadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5,
y: 180
});
shadow.alpha = 0.18;
// Balloon body
var balloon = self.attachAsset('balloon', {
anchorX: 0.5,
anchorY: 0.5
});
// For a little bounce effect on move
self.bounce = function () {
tween(self, {
scaleX: 1.08,
scaleY: 0.92
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
};
// For a little shake on hit
self.shake = function () {
tween(self, {
x: self.x + 30
}, {
duration: 60,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
x: self.x - 60
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
x: self.x + 30
}, {
duration: 60,
easing: tween.linear
});
}
});
}
});
};
return self;
});
// Spike class (obstacle)
var Spike = Container.expand(function () {
var self = Container.call(this);
var spike = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
// For a little rotation
self.rotationSpeed = (Math.random() - 0.5) * 0.04;
// Speed will be set on spawn
self.speedY = 8;
// Update method
self.update = function () {
self.y += self.speedY;
spike.rotation += self.rotationSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// LK.init.sound('spike_spawn', {volume: 0.4});
// Sound for spike spawn (optional, can be omitted if not wanted)
// Shadow for balloon
// Spike (obstacle)
// Balloon (player)
// Game area
var GAME_W = 2048;
var GAME_H = 2732;
// Balloon spawn position (centered horizontally, 80% down)
var BALLOON_START_X = GAME_W / 2;
var BALLOON_START_Y = GAME_H * 0.8;
// Balloon instance
var balloon = new Balloon();
balloon.x = BALLOON_START_X;
balloon.y = BALLOON_START_Y;
game.addChild(balloon);
// Obstacles array
var spikes = [];
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Time survived (for increasing difficulty)
var elapsedTicks = 0;
// Dragging
var dragNode = null;
// For collision detection
var lastColliding = false;
// For spike spawn timing
var spikeSpawnTick = 0;
var spikeSpawnInterval = 90; // Initial interval (ticks)
// Move handler (drag balloon)
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp balloon inside game area (with margin)
var margin = 100;
var bx = Math.max(margin, Math.min(GAME_W - margin, x));
var by = Math.max(margin + 100, Math.min(GAME_H - margin, y));
dragNode.x = bx;
dragNode.y = by;
dragNode.bounce();
}
// Collision detection
var colliding = false;
for (var i = 0; i < spikes.length; i++) {
if (balloon.intersects(spikes[i])) {
colliding = true;
break;
}
}
// Always check collision, not just when dragging
if (!lastColliding && colliding) {
// Hit!
balloon.shake();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
lastColliding = colliding;
}
// Touch/drag events
game.down = function (x, y, obj) {
// Only start drag if touch is on balloon or close to it
var dx = x - balloon.x;
var dy = y - balloon.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 180) {
dragNode = balloon;
handleMove(x, y, obj);
}
};
game.move = handleMove;
game.up = function (x, y, obj) {
dragNode = null;
};
// Main update loop
game.update = function () {
elapsedTicks++;
// Increase difficulty over time
if (elapsedTicks % 600 === 0 && spikeSpawnInterval > 30) {
spikeSpawnInterval -= 8; // Spikes spawn more often
}
// Extra difficulty after score 10
if (score >= 10) {
spikeSpawnInterval = Math.max(18, spikeSpawnInterval - 1); // Faster spawn
}
// Spawn spikes
spikeSpawnTick++;
if (spikeSpawnTick >= spikeSpawnInterval) {
spikeSpawnTick = 0;
// Random X position (avoid spawning at extreme edges)
var margin = 160;
var sx = margin + Math.random() * (GAME_W - 2 * margin);
// Create spike
var spike = new Spike();
spike.x = sx;
spike.y = -60;
// Speed increases with time
var minSpeed = 10 + Math.floor(elapsedTicks / 600) * 2;
var maxSpeed = 18 + Math.floor(elapsedTicks / 600) * 2;
if (score >= 10) {
minSpeed += 6;
maxSpeed += 8;
}
spike.speedY = minSpeed + Math.random() * (maxSpeed - minSpeed);
spikes.push(spike);
game.addChild(spike);
// Optionally play sound
// LK.getSound('spike_spawn').play();
}
// Update spikes
for (var i = spikes.length - 1; i >= 0; i--) {
var s = spikes[i];
s.update();
// If spike goes off screen, remove and increase score
if (s.y > GAME_H + 100) {
s.destroy();
spikes.splice(i, 1);
score++;
scoreTxt.setText(score);
}
}
;
// Also check collision if not dragging (so player can't avoid game over by not touching)
var colliding = false;
for (var i = 0; i < spikes.length; i++) {
if (balloon.intersects(spikes[i])) {
colliding = true;
break;
}
}
if (!lastColliding && colliding) {
balloon.shake();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
lastColliding = colliding;
};
// Center score text horizontally
scoreTxt.setText(score);
scoreTxt.anchor.set(0.5, 0);
// Place score at top center, but not in top 100px (menu area)
scoreTxt.y = 40;
// Set background color (already set in init, but can be changed here if needed)
// game.setBackgroundColor(0xb3e0ff);