User prompt
Every time the player's score increases by 3, increase the number of falling bubbles by 1. This should progressively make the game harder by adding more bubbles to the screen as the score grows.
Code edit (2 edits merged)
Please save this source code
User prompt
make red, play text
User prompt
remove square in the center
User prompt
remove square in main menu
User prompt
change main menu design
User prompt
“Make the square in the center a bit bigger. Use a soft font style for the text inside. Also, make the square’s color a lighter shade.”
User prompt
“Make the main screen look nicer and more polished. The current design is too rough and plain.”
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'highScoreTxt.visible = false;' Line Number: 208
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'livesTxt.visible = false;' Line Number: 205
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'scoreTxt.visible = false;' Line Number: 202
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'player.visible = false;' Line Number: 198
User prompt
“On the main screen, do not show ‘catch: blue’. Do not show the player. Do not show score, lives, or high score.”
User prompt
add home screen to play game
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // FallingShape class var FallingShape = Container.expand(function () { var self = Container.call(this); // Pick a random color/shape var colorList = ['shapeRed', 'shapeBlue', 'shapeGreen', 'shapeYellow', 'shapePurple']; var colorIdx = Math.floor(Math.random() * colorList.length); self.shapeId = colorList[colorIdx]; // Attach the shape asset var shape = self.attachAsset(self.shapeId, { anchorX: 0.5, anchorY: 0.5 }); // Set speed (randomize a bit for variety) self.speed = 12 + Math.floor(Math.random() * 6); // For collision detection self.radius = shape.width * 0.5; // For state tracking self.caught = false; self.missed = false; // Update method called every tick self.update = function () { self.y += self.speed; }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); // Attach player asset var playerShape = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // For collision detection self.width = playerShape.width; self.height = playerShape.height; // For touch feedback self.flash = function () { tween(self, { alpha: 0.5 }, { duration: 80, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 120 }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf0f8ff // Light blue background }); /**** * Game Code ****/ // Use a neutral (gray) color for the catching bar asset, not a color from the falling shapes // Game constants // Shapes for falling objects (different colors) // Player character // Sound effects // Music var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var PLAYER_Y = GAME_HEIGHT - 180; var SHAPE_SPAWN_INTERVAL = 48; // Ticks (0.8s at 60fps) var SHAPE_MIN_X = 120; var SHAPE_MAX_X = GAME_WIDTH - 120; var TARGET_SCORE = 20; var MAX_LIVES = 5; // Game state var player; var fallingShapes = []; var score = 0; var lives = MAX_LIVES; var dragNode = null; var lastTouchX = 0; // Target color logic var colorList = [{ id: 'shapeRed', name: 'Red' }, { id: 'shapeBlue', name: 'Blue' }, { id: 'shapeGreen', name: 'Green' }, { id: 'shapeYellow', name: 'Yellow' }, { id: 'shapePurple', name: 'Purple' }]; var targetColorIdx = Math.floor(Math.random() * colorList.length); var targetColor = colorList[targetColorIdx].id; var targetColorName = colorList[targetColorIdx].name; var targetColorTimer = null; // Target color display (centered) var targetColorTxt = new Text2('Catch: ' + targetColorName, { size: 140, fill: 0x333333 }); targetColorTxt.anchor.set(0.5, 0.5); targetColorTxt.x = LK.gui.center.width / 2; targetColorTxt.y = LK.gui.center.height / 2 - 100; LK.gui.center.addChild(targetColorTxt); // Score display var scoreTxt = new Text2('Score: 0', { size: 120, fill: 0x222222 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // High score display var highScore = storage.highScore || 0; var highScoreTxt = new Text2('High Score: ' + highScore, { size: 90, fill: 0x888800 }); highScoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(highScoreTxt); // Lives display var livesTxt = new Text2('Lives: ' + MAX_LIVES, { size: 30, fill: 0x444444 }); livesTxt.anchor.set(0.5, 0); LK.gui.top.addChild(livesTxt); livesTxt.y = 130; // Center score, high score, and lives horizontally, but not in the top 100px scoreTxt.x = LK.gui.top.width / 2; scoreTxt.y = 20; highScoreTxt.x = LK.gui.top.width / 2; highScoreTxt.y = 220; livesTxt.x = LK.gui.top.width / 2; // Helper to update target color function updateTargetColor() { var prevIdx = targetColorIdx; // Pick a new color different from the last do { targetColorIdx = Math.floor(Math.random() * colorList.length); } while (targetColorIdx === prevIdx && colorList.length > 1); targetColor = colorList[targetColorIdx].id; targetColorName = colorList[targetColorIdx].name; targetColorTxt.setText('Catch: ' + targetColorName); } // Start/restart the 10s timer for target color function startTargetColorTimer() { if (targetColorTimer) { LK.clearInterval(targetColorTimer); } targetColorTimer = LK.setInterval(function () { updateTargetColor(); }, 10000); } startTargetColorTimer(); // Start music LK.playMusic('bgmusic'); // Create player player = new Player(); game.addChild(player); player.x = GAME_WIDTH / 2; player.y = PLAYER_Y; // Helper: clamp player within screen function clampPlayerX(x) { var halfW = player.width * 0.5; if (x < halfW) { return halfW; } if (x > GAME_WIDTH - halfW) { return GAME_WIDTH - halfW; } return x; } // Touch/move handling function handleMove(x, y, obj) { if (dragNode) { // Clamp to screen dragNode.x = clampPlayerX(x); lastTouchX = dragNode.x; } } game.move = handleMove; game.down = function (x, y, obj) { // Only allow drag if touch is near player (within 200px vertically) if (y > player.y - 200) { dragNode = player; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { dragNode = null; }; // Spawn a new falling shape function spawnShape() { var shape = new FallingShape(); // Apply speed boost if any if (typeof game.shapeSpeedBoost !== "undefined") { shape.speed += game.shapeSpeedBoost; } // Random X within bounds shape.x = SHAPE_MIN_X + Math.random() * (SHAPE_MAX_X - SHAPE_MIN_X); shape.y = -100; fallingShapes.push(shape); game.addChild(shape); } // Animate positive feedback function animateCatch(shape) { tween(shape, { scaleX: 1.4, scaleY: 1.4, alpha: 0 }, { duration: 350, easing: tween.easeOut, onFinish: function onFinish() { shape.destroy(); } }); } // Animate negative feedback function animateMiss(shape) { tween(shape, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { shape.destroy(); } }); } // Update score/lives display function updateScoreLives() { scoreTxt.setText('Score: ' + score); livesTxt.setText('Lives: ' + lives); if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreTxt.setText('High Score: ' + highScore); } } // Main game update loop game.update = function () { // Increase speed every time score reaches a new multiple of 10 (but only once per threshold) if (typeof game.lastSpeedScore === "undefined") { game.lastSpeedScore = 0; } if (score >= 10 && score % 10 === 0 && game.lastSpeedScore !== score) { // Increase speed of new shapes if (typeof game.shapeSpeedBoost === "undefined") { game.shapeSpeedBoost = 0; } game.shapeSpeedBoost += 2; // Increase by 2 pixels per tick per 10 points game.lastSpeedScore = score; } // Spawn shapes at interval if (LK.ticks % SHAPE_SPAWN_INTERVAL === 0) { spawnShape(); } // Update all falling shapes for (var i = fallingShapes.length - 1; i >= 0; i--) { var shape = fallingShapes[i]; shape.update(); // Check for catch (simple AABB) if (!shape.caught && !shape.missed) { var dx = Math.abs(shape.x - player.x); var dy = Math.abs(shape.y - player.y); var catchW = player.width * 0.5 + shape.radius * 0.7; var catchH = player.height * 0.5 + shape.radius * 0.7; if (dx < catchW && dy < catchH) { // Caught! shape.caught = true; if (shape.shapeId === targetColor) { // Correct color score += 1; updateScoreLives(); LK.getSound('catch').play(); player.flash(); animateCatch(shape); fallingShapes.splice(i, 1); // Win condition if (score >= TARGET_SCORE) { LK.effects.flashScreen(0x00ff00, 800); LK.showYouWin(); return; } } else { // Wrong color // Only penalize if the shape's color is mentioned in the target color text var isMentioned = false; for (var c = 0; c < colorList.length; c++) { if (shape.shapeId === colorList[c].id) { isMentioned = true; break; } } if (isMentioned) { lives -= 1; updateScoreLives(); LK.getSound('miss').play(); player.flash(); animateMiss(shape); fallingShapes.splice(i, 1); // Lose condition if (lives <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } else { // Not a mentioned color, just remove the shape with no penalty animateMiss(shape); fallingShapes.splice(i, 1); } } continue; } } // Check for miss (off bottom) if (!shape.caught && !shape.missed && shape.y > GAME_HEIGHT + 100) { shape.missed = true; // Only penalize if the shape's color is mentioned in the target color text AND is the current target color var isMentioned = false; for (var c = 0; c < colorList.length; c++) { if (shape.shapeId === colorList[c].id) { isMentioned = true; break; } } // Only decrease lives if the missed shape is the current target color if (isMentioned && shape.shapeId === targetColor) { lives -= 1; updateScoreLives(); LK.getSound('miss').play(); animateMiss(shape); fallingShapes.splice(i, 1); // Lose condition if (lives <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } else { // Not a mentioned color or not the target color, just remove the shape with no penalty animateMiss(shape); fallingShapes.splice(i, 1); } } } }; // On game reset, clear state game.on('destroy', function () { fallingShapes = []; score = 0; lives = MAX_LIVES; dragNode = null; lastTouchX = 0; LK.stopMusic(); // Reset target color and timer if (targetColorTimer) { LK.clearInterval(targetColorTimer); } updateTargetColor(); startTargetColorTimer(); targetColorTxt.setText('Catch: ' + targetColorName); // Update high score display from storage in case it changed highScore = storage.highScore || 0; highScoreTxt.setText('High Score: ' + highScore); });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// FallingShape class
var FallingShape = Container.expand(function () {
var self = Container.call(this);
// Pick a random color/shape
var colorList = ['shapeRed', 'shapeBlue', 'shapeGreen', 'shapeYellow', 'shapePurple'];
var colorIdx = Math.floor(Math.random() * colorList.length);
self.shapeId = colorList[colorIdx];
// Attach the shape asset
var shape = self.attachAsset(self.shapeId, {
anchorX: 0.5,
anchorY: 0.5
});
// Set speed (randomize a bit for variety)
self.speed = 12 + Math.floor(Math.random() * 6);
// For collision detection
self.radius = shape.width * 0.5;
// For state tracking
self.caught = false;
self.missed = false;
// Update method called every tick
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset
var playerShape = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// For collision detection
self.width = playerShape.width;
self.height = playerShape.height;
// For touch feedback
self.flash = function () {
tween(self, {
alpha: 0.5
}, {
duration: 80,
onFinish: function onFinish() {
tween(self, {
alpha: 1
}, {
duration: 120
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf0f8ff // Light blue background
});
/****
* Game Code
****/
// Use a neutral (gray) color for the catching bar asset, not a color from the falling shapes
// Game constants
// Shapes for falling objects (different colors)
// Player character
// Sound effects
// Music
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_Y = GAME_HEIGHT - 180;
var SHAPE_SPAWN_INTERVAL = 48; // Ticks (0.8s at 60fps)
var SHAPE_MIN_X = 120;
var SHAPE_MAX_X = GAME_WIDTH - 120;
var TARGET_SCORE = 20;
var MAX_LIVES = 5;
// Game state
var player;
var fallingShapes = [];
var score = 0;
var lives = MAX_LIVES;
var dragNode = null;
var lastTouchX = 0;
// Target color logic
var colorList = [{
id: 'shapeRed',
name: 'Red'
}, {
id: 'shapeBlue',
name: 'Blue'
}, {
id: 'shapeGreen',
name: 'Green'
}, {
id: 'shapeYellow',
name: 'Yellow'
}, {
id: 'shapePurple',
name: 'Purple'
}];
var targetColorIdx = Math.floor(Math.random() * colorList.length);
var targetColor = colorList[targetColorIdx].id;
var targetColorName = colorList[targetColorIdx].name;
var targetColorTimer = null;
// Target color display (centered)
var targetColorTxt = new Text2('Catch: ' + targetColorName, {
size: 140,
fill: 0x333333
});
targetColorTxt.anchor.set(0.5, 0.5);
targetColorTxt.x = LK.gui.center.width / 2;
targetColorTxt.y = LK.gui.center.height / 2 - 100;
LK.gui.center.addChild(targetColorTxt);
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 120,
fill: 0x222222
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// High score display
var highScore = storage.highScore || 0;
var highScoreTxt = new Text2('High Score: ' + highScore, {
size: 90,
fill: 0x888800
});
highScoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(highScoreTxt);
// Lives display
var livesTxt = new Text2('Lives: ' + MAX_LIVES, {
size: 30,
fill: 0x444444
});
livesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(livesTxt);
livesTxt.y = 130;
// Center score, high score, and lives horizontally, but not in the top 100px
scoreTxt.x = LK.gui.top.width / 2;
scoreTxt.y = 20;
highScoreTxt.x = LK.gui.top.width / 2;
highScoreTxt.y = 220;
livesTxt.x = LK.gui.top.width / 2;
// Helper to update target color
function updateTargetColor() {
var prevIdx = targetColorIdx;
// Pick a new color different from the last
do {
targetColorIdx = Math.floor(Math.random() * colorList.length);
} while (targetColorIdx === prevIdx && colorList.length > 1);
targetColor = colorList[targetColorIdx].id;
targetColorName = colorList[targetColorIdx].name;
targetColorTxt.setText('Catch: ' + targetColorName);
}
// Start/restart the 10s timer for target color
function startTargetColorTimer() {
if (targetColorTimer) {
LK.clearInterval(targetColorTimer);
}
targetColorTimer = LK.setInterval(function () {
updateTargetColor();
}, 10000);
}
startTargetColorTimer();
// Start music
LK.playMusic('bgmusic');
// Create player
player = new Player();
game.addChild(player);
player.x = GAME_WIDTH / 2;
player.y = PLAYER_Y;
// Helper: clamp player within screen
function clampPlayerX(x) {
var halfW = player.width * 0.5;
if (x < halfW) {
return halfW;
}
if (x > GAME_WIDTH - halfW) {
return GAME_WIDTH - halfW;
}
return x;
}
// Touch/move handling
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to screen
dragNode.x = clampPlayerX(x);
lastTouchX = dragNode.x;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is near player (within 200px vertically)
if (y > player.y - 200) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Spawn a new falling shape
function spawnShape() {
var shape = new FallingShape();
// Apply speed boost if any
if (typeof game.shapeSpeedBoost !== "undefined") {
shape.speed += game.shapeSpeedBoost;
}
// Random X within bounds
shape.x = SHAPE_MIN_X + Math.random() * (SHAPE_MAX_X - SHAPE_MIN_X);
shape.y = -100;
fallingShapes.push(shape);
game.addChild(shape);
}
// Animate positive feedback
function animateCatch(shape) {
tween(shape, {
scaleX: 1.4,
scaleY: 1.4,
alpha: 0
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
shape.destroy();
}
});
}
// Animate negative feedback
function animateMiss(shape) {
tween(shape, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
shape.destroy();
}
});
}
// Update score/lives display
function updateScoreLives() {
scoreTxt.setText('Score: ' + score);
livesTxt.setText('Lives: ' + lives);
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
highScoreTxt.setText('High Score: ' + highScore);
}
}
// Main game update loop
game.update = function () {
// Increase speed every time score reaches a new multiple of 10 (but only once per threshold)
if (typeof game.lastSpeedScore === "undefined") {
game.lastSpeedScore = 0;
}
if (score >= 10 && score % 10 === 0 && game.lastSpeedScore !== score) {
// Increase speed of new shapes
if (typeof game.shapeSpeedBoost === "undefined") {
game.shapeSpeedBoost = 0;
}
game.shapeSpeedBoost += 2; // Increase by 2 pixels per tick per 10 points
game.lastSpeedScore = score;
}
// Spawn shapes at interval
if (LK.ticks % SHAPE_SPAWN_INTERVAL === 0) {
spawnShape();
}
// Update all falling shapes
for (var i = fallingShapes.length - 1; i >= 0; i--) {
var shape = fallingShapes[i];
shape.update();
// Check for catch (simple AABB)
if (!shape.caught && !shape.missed) {
var dx = Math.abs(shape.x - player.x);
var dy = Math.abs(shape.y - player.y);
var catchW = player.width * 0.5 + shape.radius * 0.7;
var catchH = player.height * 0.5 + shape.radius * 0.7;
if (dx < catchW && dy < catchH) {
// Caught!
shape.caught = true;
if (shape.shapeId === targetColor) {
// Correct color
score += 1;
updateScoreLives();
LK.getSound('catch').play();
player.flash();
animateCatch(shape);
fallingShapes.splice(i, 1);
// Win condition
if (score >= TARGET_SCORE) {
LK.effects.flashScreen(0x00ff00, 800);
LK.showYouWin();
return;
}
} else {
// Wrong color
// Only penalize if the shape's color is mentioned in the target color text
var isMentioned = false;
for (var c = 0; c < colorList.length; c++) {
if (shape.shapeId === colorList[c].id) {
isMentioned = true;
break;
}
}
if (isMentioned) {
lives -= 1;
updateScoreLives();
LK.getSound('miss').play();
player.flash();
animateMiss(shape);
fallingShapes.splice(i, 1);
// Lose condition
if (lives <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
} else {
// Not a mentioned color, just remove the shape with no penalty
animateMiss(shape);
fallingShapes.splice(i, 1);
}
}
continue;
}
}
// Check for miss (off bottom)
if (!shape.caught && !shape.missed && shape.y > GAME_HEIGHT + 100) {
shape.missed = true;
// Only penalize if the shape's color is mentioned in the target color text AND is the current target color
var isMentioned = false;
for (var c = 0; c < colorList.length; c++) {
if (shape.shapeId === colorList[c].id) {
isMentioned = true;
break;
}
}
// Only decrease lives if the missed shape is the current target color
if (isMentioned && shape.shapeId === targetColor) {
lives -= 1;
updateScoreLives();
LK.getSound('miss').play();
animateMiss(shape);
fallingShapes.splice(i, 1);
// Lose condition
if (lives <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
} else {
// Not a mentioned color or not the target color, just remove the shape with no penalty
animateMiss(shape);
fallingShapes.splice(i, 1);
}
}
}
};
// On game reset, clear state
game.on('destroy', function () {
fallingShapes = [];
score = 0;
lives = MAX_LIVES;
dragNode = null;
lastTouchX = 0;
LK.stopMusic();
// Reset target color and timer
if (targetColorTimer) {
LK.clearInterval(targetColorTimer);
}
updateTargetColor();
startTargetColorTimer();
targetColorTxt.setText('Catch: ' + targetColorName);
// Update high score display from storage in case it changed
highScore = storage.highScore || 0;
highScoreTxt.setText('High Score: ' + highScore);
});