User prompt
when game start, start the music
User prompt
when tap the circle, start tap sound
User prompt
when game start show the start asset
User prompt
when tap the circle start tap
User prompt
make main menu
Code edit (1 edits merged)
Please save this source code
User prompt
Hello World: Tap the Circles!
Initial prompt
hello
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Circle class: represents a tappable circle var TapCircle = Container.expand(function () { var self = Container.call(this); // Create and attach a colored ellipse asset // Color is randomized for each circle var color = TapCircle.randomColor(); var circle = self.attachAsset('tapCircle', { width: TapCircle.RADIUS * 2, height: TapCircle.RADIUS * 2, color: color, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); // Store color for possible future use self.color = color; // Set up a timer for auto-destroy self.lifetime = TapCircle.lifetime; // ms self.spawnTick = LK.ticks; // Mark as alive self.alive = true; // Called every tick by LK engine self.update = function () { // If lifetime expired, trigger game over if (self.alive && (LK.ticks - self.spawnTick) * (1000 / 60) > self.lifetime) { // Flash screen red and end game LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); self.alive = false; } }; // Called when the circle is tapped self.down = function (x, y, obj) { if (!self.alive) return; self.alive = false; // Animate: quick scale up and fade out tween(self, { scaleX: 1.3, scaleY: 1.3, alpha: 0 }, { duration: 180, easing: tween.cubicOut, onFinish: function onFinish() { self.destroy(); } }); // Score is handled in game.down }; return self; }); /**** * Initialize Game ****/ // Static properties for TapCircle var game = new LK.Game({ // No title, no description // Always backgroundColor is black backgroundColor: 0x000000 }); /**** * Game Code ****/ // Score display // Tween plugin for animations (not strictly needed for MVP, but included for future use) // Static properties for TapCircle TapCircle.RADIUS = 140; // px TapCircle.lifetime = 1200; // ms, will decrease as game speeds up // Helper: random pastel color TapCircle.randomColor = function () { // Pastel: high value, medium saturation var hue = Math.floor(Math.random() * 360); var rgb = TapCircle.hsvToRgb(hue / 360, 0.5, 0.95); return rgb[0] << 16 | rgb[1] << 8 | rgb[2]; }; // HSV to RGB helper TapCircle.hsvToRgb = function (h, s, v) { var r, g, b, i, f, p, q, t; i = Math.floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; }; var scoreTxt = new Text2('0', { size: 150, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Global state var circles = []; var canTap = true; // Prevents double taps in a single frame // Game speed state var minLifetime = 600; // ms, minimum allowed var maxLifetime = 1200; // ms, starting value var speedupEvery = 3; // Speed up every N points var speedupAmount = 80; // ms decrease per speedup // Spawn a new circle at a random position function spawnCircle() { // Remove any existing circles for (var i = circles.length - 1; i >= 0; i--) { if (circles[i] && circles[i].alive) { circles[i].destroy(); } circles.splice(i, 1); } // Calculate safe area (avoid top 200px and bottom 200px, and left/right 150px) var marginX = TapCircle.RADIUS + 150; var marginY = TapCircle.RADIUS + 200; var x = marginX + Math.random() * (2048 - marginX * 2); var y = marginY + Math.random() * (2732 - marginY * 2); // Create and position circle var circle = new TapCircle(); circle.x = x; circle.y = y; circle.scaleX = 1; circle.scaleY = 1; circle.alpha = 1; // Set current lifetime (difficulty) circle.lifetime = TapCircle.lifetime; game.addChild(circle); circles.push(circle); } // Handle tap events game.down = function (x, y, obj) { if (!canTap) return; canTap = false; // Check if tap is inside any alive circle var tapped = false; for (var i = 0; i < circles.length; i++) { var c = circles[i]; if (c && c.alive) { // Convert tap to local circle coordinates var local = c.toLocal(game.toGlobal({ x: x, y: y })); var dx = local.x - 0; var dy = local.y - 0; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= TapCircle.RADIUS) { // Correct tap tapped = true; LK.getSound('tap').play(); c.down(x, y, obj); // Animate and destroy // Score up var newScore = LK.getScore() + 1; LK.setScore(newScore); scoreTxt.setText(newScore); // Speed up game if (newScore % speedupEvery === 0 && TapCircle.lifetime > minLifetime) { TapCircle.lifetime = Math.max(minLifetime, TapCircle.lifetime - speedupAmount); } // Spawn next circle after a short delay LK.setTimeout(function () { spawnCircle(); canTap = true; }, 120); break; } } } if (!tapped) { // Tapped outside any circle: game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } }; // Allow tap again after up game.up = function (x, y, obj) { canTap = true; }; // Main update loop game.update = function () { // Update all circles for (var i = circles.length - 1; i >= 0; i--) { if (circles[i] && circles[i].update) { circles[i].update(); } } }; // Start the game function startGame() { LK.setScore(0); scoreTxt.setText(0); TapCircle.lifetime = maxLifetime; LK.playMusic('music'); spawnCircle(); canTap = true; gameStarted = true; } // Only spawn the first circle after the first tap var gameStarted = false; // Show the start asset at the center of the screen var startAsset = LK.getAsset('start', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(startAsset); game.down = function (x, y, obj) { if (!gameStarted) { // Remove the start asset if (startAsset && startAsset.parent) { startAsset.parent.removeChild(startAsset); } startGame(); return; } if (!canTap) return; canTap = false; // Check if tap is inside any alive circle var tapped = false; for (var i = 0; i < circles.length; i++) { var c = circles[i]; if (c && c.alive) { // Convert tap to local circle coordinates var local = c.toLocal(game.toGlobal({ x: x, y: y })); var dx = local.x - 0; var dy = local.y - 0; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= TapCircle.RADIUS) { // Correct tap tapped = true; LK.getSound('tap').play(); c.down(x, y, obj); // Animate and destroy // Score up var newScore = LK.getScore() + 1; LK.setScore(newScore); scoreTxt.setText(newScore); // Speed up game if (newScore % speedupEvery === 0 && TapCircle.lifetime > minLifetime) { TapCircle.lifetime = Math.max(minLifetime, TapCircle.lifetime - speedupAmount); } // Spawn next circle after a short delay LK.setTimeout(function () { spawnCircle(); canTap = true; }, 120); break; } } } if (!tapped) { // Tapped outside any circle: game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } }; // Allow tap again after up game.up = function (x, y, obj) { canTap = true; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Circle class: represents a tappable circle
var TapCircle = Container.expand(function () {
var self = Container.call(this);
// Create and attach a colored ellipse asset
// Color is randomized for each circle
var color = TapCircle.randomColor();
var circle = self.attachAsset('tapCircle', {
width: TapCircle.RADIUS * 2,
height: TapCircle.RADIUS * 2,
color: color,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Store color for possible future use
self.color = color;
// Set up a timer for auto-destroy
self.lifetime = TapCircle.lifetime; // ms
self.spawnTick = LK.ticks;
// Mark as alive
self.alive = true;
// Called every tick by LK engine
self.update = function () {
// If lifetime expired, trigger game over
if (self.alive && (LK.ticks - self.spawnTick) * (1000 / 60) > self.lifetime) {
// Flash screen red and end game
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
self.alive = false;
}
};
// Called when the circle is tapped
self.down = function (x, y, obj) {
if (!self.alive) return;
self.alive = false;
// Animate: quick scale up and fade out
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0
}, {
duration: 180,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Score is handled in game.down
};
return self;
});
/****
* Initialize Game
****/
// Static properties for TapCircle
var game = new LK.Game({
// No title, no description
// Always backgroundColor is black
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Score display
// Tween plugin for animations (not strictly needed for MVP, but included for future use)
// Static properties for TapCircle
TapCircle.RADIUS = 140; // px
TapCircle.lifetime = 1200; // ms, will decrease as game speeds up
// Helper: random pastel color
TapCircle.randomColor = function () {
// Pastel: high value, medium saturation
var hue = Math.floor(Math.random() * 360);
var rgb = TapCircle.hsvToRgb(hue / 360, 0.5, 0.95);
return rgb[0] << 16 | rgb[1] << 8 | rgb[2];
};
// HSV to RGB helper
TapCircle.hsvToRgb = function (h, s, v) {
var r, g, b, i, f, p, q, t;
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
};
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Global state
var circles = [];
var canTap = true; // Prevents double taps in a single frame
// Game speed state
var minLifetime = 600; // ms, minimum allowed
var maxLifetime = 1200; // ms, starting value
var speedupEvery = 3; // Speed up every N points
var speedupAmount = 80; // ms decrease per speedup
// Spawn a new circle at a random position
function spawnCircle() {
// Remove any existing circles
for (var i = circles.length - 1; i >= 0; i--) {
if (circles[i] && circles[i].alive) {
circles[i].destroy();
}
circles.splice(i, 1);
}
// Calculate safe area (avoid top 200px and bottom 200px, and left/right 150px)
var marginX = TapCircle.RADIUS + 150;
var marginY = TapCircle.RADIUS + 200;
var x = marginX + Math.random() * (2048 - marginX * 2);
var y = marginY + Math.random() * (2732 - marginY * 2);
// Create and position circle
var circle = new TapCircle();
circle.x = x;
circle.y = y;
circle.scaleX = 1;
circle.scaleY = 1;
circle.alpha = 1;
// Set current lifetime (difficulty)
circle.lifetime = TapCircle.lifetime;
game.addChild(circle);
circles.push(circle);
}
// Handle tap events
game.down = function (x, y, obj) {
if (!canTap) return;
canTap = false;
// Check if tap is inside any alive circle
var tapped = false;
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
if (c && c.alive) {
// Convert tap to local circle coordinates
var local = c.toLocal(game.toGlobal({
x: x,
y: y
}));
var dx = local.x - 0;
var dy = local.y - 0;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= TapCircle.RADIUS) {
// Correct tap
tapped = true;
LK.getSound('tap').play();
c.down(x, y, obj); // Animate and destroy
// Score up
var newScore = LK.getScore() + 1;
LK.setScore(newScore);
scoreTxt.setText(newScore);
// Speed up game
if (newScore % speedupEvery === 0 && TapCircle.lifetime > minLifetime) {
TapCircle.lifetime = Math.max(minLifetime, TapCircle.lifetime - speedupAmount);
}
// Spawn next circle after a short delay
LK.setTimeout(function () {
spawnCircle();
canTap = true;
}, 120);
break;
}
}
}
if (!tapped) {
// Tapped outside any circle: game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
};
// Allow tap again after up
game.up = function (x, y, obj) {
canTap = true;
};
// Main update loop
game.update = function () {
// Update all circles
for (var i = circles.length - 1; i >= 0; i--) {
if (circles[i] && circles[i].update) {
circles[i].update();
}
}
};
// Start the game
function startGame() {
LK.setScore(0);
scoreTxt.setText(0);
TapCircle.lifetime = maxLifetime;
LK.playMusic('music');
spawnCircle();
canTap = true;
gameStarted = true;
}
// Only spawn the first circle after the first tap
var gameStarted = false;
// Show the start asset at the center of the screen
var startAsset = LK.getAsset('start', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(startAsset);
game.down = function (x, y, obj) {
if (!gameStarted) {
// Remove the start asset
if (startAsset && startAsset.parent) {
startAsset.parent.removeChild(startAsset);
}
startGame();
return;
}
if (!canTap) return;
canTap = false;
// Check if tap is inside any alive circle
var tapped = false;
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
if (c && c.alive) {
// Convert tap to local circle coordinates
var local = c.toLocal(game.toGlobal({
x: x,
y: y
}));
var dx = local.x - 0;
var dy = local.y - 0;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= TapCircle.RADIUS) {
// Correct tap
tapped = true;
LK.getSound('tap').play();
c.down(x, y, obj); // Animate and destroy
// Score up
var newScore = LK.getScore() + 1;
LK.setScore(newScore);
scoreTxt.setText(newScore);
// Speed up game
if (newScore % speedupEvery === 0 && TapCircle.lifetime > minLifetime) {
TapCircle.lifetime = Math.max(minLifetime, TapCircle.lifetime - speedupAmount);
}
// Spawn next circle after a short delay
LK.setTimeout(function () {
spawnCircle();
canTap = true;
}, 120);
break;
}
}
}
if (!tapped) {
// Tapped outside any circle: game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
};
// Allow tap again after up
game.up = function (x, y, obj) {
canTap = true;
};