User prompt
if I close the target play this track "endlevel" and I won the level change the track "main_menu"1
User prompt
if I won level, stop this track:"endlevel" and play this track "main_menu"
User prompt
increase the level target level 1: 100 level 30: 3000
User prompt
if I click any level button, first play this track:"startlevel" If i have a target/2 play this track:"levelmid" if i have a target play this track "endlevel"
User prompt
if I clicked any button play this sound in collect>"click"
User prompt
if music:on play this track:"main_menu"
User prompt
settings tab>Music:on/off settings tab>Sound:on/off
User prompt
if I in the main menu play this track:"main_menu"
User prompt
add a "setting" button in the main menu
User prompt
play "happy_and_lo-fi" track and loop
User prompt
update the "Assets" tab
User prompt
if i click the regular upit play button, play game "happy_and_lo-fi" track
User prompt
add background in the levels
User prompt
if I click regular upit play button, reset the progress
User prompt
reset the player progress
User prompt
level targets "Level 1: 25 score... Level 30 100 score
User prompt
if I won don't show regular "you win!" tab
User prompt
lock the levels, and put a target for levels "example if i have a 50 score in level 1, unlock level 2
User prompt
Please fix the bug: 'TypeError: storage.save is not a function' in or related to this line: 'storage.save();' Line Number: 661 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
add "5" perks
User prompt
if heart 0<3 return the main menu
User prompt
add a 3 heart for loss
User prompt
remake the game with main menu, "play>select levels 1-30" "shop>Character&perks"
User prompt
remake the game
User prompt
remake
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
coins: 0,
unlockedSkins: ["candyRed"],
selectedSkin: "candyRed"
});
/****
* Classes
****/
// Candy class
var Candy = Container.expand(function () {
var self = Container.call(this);
// Use selected skin or random unlocked skin
var skin = storage.selectedSkin || 'candyRed';
var candyAsset = self.attachAsset(skin, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = candyAsset.width;
self.height = candyAsset.height;
// Falling speed
self.speed = 10 + Math.random() * 6;
// For swipe detection
self.collected = false;
// For tracking last Y for off-screen detection
self.lastY = self.y;
// For tracking if already counted as missed
self.missed = false;
// For future: skin id
self.skin = skin;
// For future: coin drop
self.hasCoin = Math.random() < 0.15; // 15% chance to drop a coin
// Add coin visual if hasCoin
if (self.hasCoin) {
var coinAsset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
y: 30
});
coinAsset.alpha = 0.8;
}
// Animate in
candyAsset.scaleX = 0.2;
candyAsset.scaleY = 0.2;
tween(candyAsset, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
// Update method
self.update = function () {
if (self.collected) return;
self.y += self.speed;
};
return self;
});
// Coin collect animation
var CoinFly = Container.expand(function () {
var self = Container.call(this);
var coin = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coin.width;
self.height = coin.height;
self.update = function () {};
return self;
});
// Collector class (player's swipe area)
var Collector = Container.expand(function () {
var self = Container.call(this);
var collectorAsset = self.attachAsset('collector', {
anchorX: 0.5,
anchorY: 0.5
});
collectorAsset.alpha = 0.18;
self.width = collectorAsset.width;
self.height = collectorAsset.height;
self.update = function () {};
return self;
});
// Shop item class
var ShopItem = Container.expand(function () {
var self = Container.call(this);
var box = self.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5
});
self.icon = null;
self.price = 0;
self.skinId = '';
self.owned = false;
self.setSkin = function (skinId, price, owned) {
self.skinId = skinId;
self.price = price;
self.owned = owned;
if (self.icon) self.removeChild(self.icon);
self.icon = self.attachAsset(skinId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1
});
self.icon.y = -20;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222244
});
/****
* Game Code
****/
// Game states
var gameState = 'mainMenu'; // mainMenu, levelSelect, shop, playing
var currentLevel = 1;
// UI containers
var mainMenuContainer = null;
var levelSelectContainer = null;
var shopContainer = null;
var gameplayContainer = null;
// Game variables
var score = 0;
var candies = [];
var collector = null;
var candySpawnTimer = 0;
var levelConfig = {};
var lives = 3;
var heartsContainer = null;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
// Coins display
var coinsTxt = new Text2('Coins: ' + storage.coins, {
size: 80,
fill: '#ffd700'
});
coinsTxt.anchor.set(1, 0);
coinsTxt.x = -20;
LK.gui.topRight.addChild(coinsTxt);
// Create main menu
function createMainMenu() {
if (mainMenuContainer) mainMenuContainer.destroy();
mainMenuContainer = new Container();
// Title
var title = new Text2('Candy Catch', {
size: 200,
fill: '#ffffff'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 600;
mainMenuContainer.addChild(title);
// Play button
var playBtn = mainMenuContainer.addChild(new Container());
var playBg = playBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8,
tint: 0x3bff6e
});
playBtn.x = 1024;
playBtn.y = 1200;
var playTxt = new Text2('PLAY', {
size: 100,
fill: '#ffffff'
});
playTxt.anchor.set(0.5, 0.5);
playBtn.addChild(playTxt);
playBtn.down = function () {
gameState = 'levelSelect';
updateGameState();
};
// Shop button
var shopBtn = mainMenuContainer.addChild(new Container());
var shopBg = shopBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8,
tint: 0xffd700
});
shopBtn.x = 1024;
shopBtn.y = 1500;
var shopTxt = new Text2('SHOP', {
size: 100,
fill: '#ffffff'
});
shopTxt.anchor.set(0.5, 0.5);
shopBtn.addChild(shopTxt);
shopBtn.down = function () {
gameState = 'shop';
updateGameState();
};
game.addChild(mainMenuContainer);
}
// Create level select
function createLevelSelect() {
if (levelSelectContainer) levelSelectContainer.destroy();
levelSelectContainer = new Container();
// Title
var title = new Text2('Select Level', {
size: 120,
fill: '#ffffff'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 200;
levelSelectContainer.addChild(title);
// Back button
var backBtn = levelSelectContainer.addChild(new Container());
var backBg = backBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6,
tint: 0xff6666
});
backBtn.x = 200;
backBtn.y = 200;
var backTxt = new Text2('BACK', {
size: 60,
fill: '#ffffff'
});
backTxt.anchor.set(0.5, 0.5);
backBtn.addChild(backTxt);
backBtn.down = function () {
gameState = 'mainMenu';
updateGameState();
};
// Level buttons grid
var startX = 300;
var startY = 500;
var spacing = 250;
var cols = 6;
for (var i = 0; i < 30; i++) {
var levelBtn = levelSelectContainer.addChild(new Container());
var col = i % cols;
var row = Math.floor(i / cols);
var lvlBg = levelBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
tint: i < 10 ? 0x66ff66 : i < 20 ? 0xffff66 : 0xff6666
});
levelBtn.x = startX + col * spacing;
levelBtn.y = startY + row * spacing;
var lvlTxt = new Text2((i + 1).toString(), {
size: 80,
fill: '#ffffff'
});
lvlTxt.anchor.set(0.5, 0.5);
levelBtn.addChild(lvlTxt);
levelBtn.levelNum = i + 1;
levelBtn.down = function () {
currentLevel = this.levelNum;
gameState = 'playing';
updateGameState();
};
}
game.addChild(levelSelectContainer);
}
// Create shop
function createShop() {
if (shopContainer) shopContainer.destroy();
shopContainer = new Container();
// Title
var title = new Text2('Shop', {
size: 120,
fill: '#ffffff'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 200;
shopContainer.addChild(title);
// Back button
var backBtn = shopContainer.addChild(new Container());
var backBg = backBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6,
tint: 0xff6666
});
backBtn.x = 200;
backBtn.y = 200;
var backTxt = new Text2('BACK', {
size: 60,
fill: '#ffffff'
});
backTxt.anchor.set(0.5, 0.5);
backBtn.addChild(backTxt);
backBtn.down = function () {
gameState = 'mainMenu';
updateGameState();
};
// Character skins
var skins = [{
id: 'candyRed',
price: 0,
name: 'Red'
}, {
id: 'candyBlue',
price: 100,
name: 'Blue'
}, {
id: 'candyGreen',
price: 200,
name: 'Green'
}, {
id: 'candyPurple',
price: 300,
name: 'Purple'
}, {
id: 'candyYellow',
price: 500,
name: 'Yellow'
}];
var skinsTxt = new Text2('Character Skins', {
size: 80,
fill: '#ffffff'
});
skinsTxt.anchor.set(0.5, 0.5);
skinsTxt.x = 1024;
skinsTxt.y = 500;
shopContainer.addChild(skinsTxt);
// Skin items
var startX = 400;
var startY = 700;
var spacing = 300;
for (var i = 0; i < skins.length; i++) {
var skin = skins[i];
var owned = storage.unlockedSkins.indexOf(skin.id) !== -1;
var skinItem = shopContainer.addChild(new Container());
skinItem.x = startX + i * spacing;
skinItem.y = startY;
var itemBg = skinItem.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
tint: owned ? storage.selectedSkin === skin.id ? 0x66ff66 : 0xcccccc : 0x888888
});
var icon = skinItem.attachAsset(skin.id, {
anchorX: 0.5,
anchorY: 0.5,
y: -30
});
var priceTxt = new Text2(owned ? storage.selectedSkin === skin.id ? 'SELECTED' : 'OWNED' : skin.price + ' coins', {
size: 40,
fill: '#ffffff'
});
priceTxt.anchor.set(0.5, 0.5);
priceTxt.y = 60;
skinItem.addChild(priceTxt);
skinItem.skinData = skin;
skinItem.owned = owned;
skinItem.down = function () {
if (this.owned) {
storage.selectedSkin = this.skinData.id;
storage.save();
createShop();
} else if (storage.coins >= this.skinData.price) {
storage.coins -= this.skinData.price;
storage.unlockedSkins.push(this.skinData.id);
storage.selectedSkin = this.skinData.id;
storage.save();
coinsTxt.setText('Coins: ' + storage.coins);
createShop();
}
};
}
// Perks section
var perksTxt = new Text2('Perks (Coming Soon)', {
size: 80,
fill: '#ffffff'
});
perksTxt.anchor.set(0.5, 0.5);
perksTxt.x = 1024;
perksTxt.y = 1200;
shopContainer.addChild(perksTxt);
game.addChild(shopContainer);
}
// Start gameplay
function startGameplay() {
if (gameplayContainer) gameplayContainer.destroy();
gameplayContainer = new Container();
game.addChild(gameplayContainer);
// Reset game variables
score = 0;
candies = [];
candySpawnTimer = 0;
lives = 3;
scoreTxt.setText('0');
scoreTxt.visible = true;
// Level configuration
levelConfig = {
spawnRate: Math.max(30 - currentLevel, 10),
candySpeed: 8 + currentLevel * 0.5,
targetScore: 10 + currentLevel * 5
};
// Create collector
collector = new Collector();
collector.x = 1024;
collector.y = 2400;
gameplayContainer.addChild(collector);
// Level info
var levelTxt = new Text2('Level ' + currentLevel + ' - Collect ' + levelConfig.targetScore, {
size: 60,
fill: '#ffffff'
});
levelTxt.anchor.set(0.5, 0.5);
levelTxt.x = 1024;
levelTxt.y = 300;
gameplayContainer.addChild(levelTxt);
// Create hearts display
heartsContainer = new Container();
heartsContainer.x = 1024;
heartsContainer.y = 150;
gameplayContainer.addChild(heartsContainer);
// Add 3 hearts
for (var h = 0; h < 3; h++) {
var heart = heartsContainer.attachAsset('candyRed', {
anchorX: 0.5,
anchorY: 0.5,
x: (h - 1) * 140,
scaleX: 0.8,
scaleY: 0.8,
tint: 0xff6666
});
}
// Back button
var backBtn = gameplayContainer.addChild(new Container());
var backBg = backBtn.attachAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.5,
tint: 0xff6666
});
backBtn.x = 200;
backBtn.y = 200;
var backTxt = new Text2('EXIT', {
size: 50,
fill: '#ffffff'
});
backTxt.anchor.set(0.5, 0.5);
backBtn.addChild(backTxt);
backBtn.down = function () {
gameState = 'levelSelect';
updateGameState();
};
}
// Update game state
function updateGameState() {
// Hide all containers
if (mainMenuContainer) mainMenuContainer.visible = false;
if (levelSelectContainer) levelSelectContainer.visible = false;
if (shopContainer) shopContainer.visible = false;
if (gameplayContainer) gameplayContainer.visible = false;
scoreTxt.visible = false;
// Show current state
switch (gameState) {
case 'mainMenu':
createMainMenu();
break;
case 'levelSelect':
createLevelSelect();
break;
case 'shop':
createShop();
break;
case 'playing':
startGameplay();
break;
}
}
// Game update
game.update = function () {
if (gameState !== 'playing') return;
// Spawn candies
candySpawnTimer--;
if (candySpawnTimer <= 0) {
var candy = new Candy();
candy.x = 200 + Math.random() * 1648;
candy.y = -100;
candy.speed = levelConfig.candySpeed;
candies.push(candy);
gameplayContainer.addChild(candy);
candySpawnTimer = levelConfig.spawnRate;
}
// Update candies
for (var i = candies.length - 1; i >= 0; i--) {
var candy = candies[i];
candy.update();
// Check collection
if (!candy.collected && candy.intersects(collector)) {
candy.collected = true;
score++;
scoreTxt.setText(score.toString());
LK.getSound('collect').play();
// Coin drop
if (candy.hasCoin) {
storage.coins += 10;
storage.save();
coinsTxt.setText('Coins: ' + storage.coins);
// Coin animation
var coin = new CoinFly();
coin.x = candy.x;
coin.y = candy.y;
gameplayContainer.addChild(coin);
tween(coin, {
x: 2048 - 100,
y: 50,
alpha: 0
}, {
duration: 800,
onComplete: function onComplete() {
coin.destroy();
}
});
}
// Remove candy
candy.destroy();
candies.splice(i, 1);
// Check win
if (score >= levelConfig.targetScore) {
gameState = 'levelSelect';
updateGameState();
LK.showYouWin();
}
}
// Remove off-screen
if (candy.y > 2832) {
if (!candy.missed) {
candy.missed = true;
lives--;
// Update hearts display
if (heartsContainer && heartsContainer.children.length > lives) {
var heartToRemove = heartsContainer.children[lives];
tween(heartToRemove, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onComplete: function onComplete() {
heartToRemove.visible = false;
}
});
}
// Check game over
if (lives <= 0) {
gameState = 'levelSelect';
updateGameState();
LK.showGameOver();
}
}
candy.destroy();
candies.splice(i, 1);
}
}
};
// Touch controls for collector
game.down = function (x, y, obj) {
if (gameState === 'playing' && collector) {
collector.x = x;
}
};
game.move = function (x, y, obj) {
if (gameState === 'playing' && collector) {
collector.x = x;
}
};
// Initialize game
updateGameState(); ===================================================================
--- original.js
+++ change.js
@@ -137,8 +137,10 @@
var candies = [];
var collector = null;
var candySpawnTimer = 0;
var levelConfig = {};
+var lives = 3;
+var heartsContainer = null;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: '#fff'
@@ -405,8 +407,9 @@
// Reset game variables
score = 0;
candies = [];
candySpawnTimer = 0;
+ lives = 3;
scoreTxt.setText('0');
scoreTxt.visible = true;
// Level configuration
levelConfig = {
@@ -427,8 +430,24 @@
levelTxt.anchor.set(0.5, 0.5);
levelTxt.x = 1024;
levelTxt.y = 300;
gameplayContainer.addChild(levelTxt);
+ // Create hearts display
+ heartsContainer = new Container();
+ heartsContainer.x = 1024;
+ heartsContainer.y = 150;
+ gameplayContainer.addChild(heartsContainer);
+ // Add 3 hearts
+ for (var h = 0; h < 3; h++) {
+ var heart = heartsContainer.attachAsset('candyRed', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: (h - 1) * 140,
+ scaleX: 0.8,
+ scaleY: 0.8,
+ tint: 0xff6666
+ });
+ }
// Back button
var backBtn = gameplayContainer.addChild(new Container());
var backBg = backBtn.attachAsset('shopItem', {
anchorX: 0.5,
@@ -530,8 +549,32 @@
}
}
// Remove off-screen
if (candy.y > 2832) {
+ if (!candy.missed) {
+ candy.missed = true;
+ lives--;
+ // Update hearts display
+ if (heartsContainer && heartsContainer.children.length > lives) {
+ var heartToRemove = heartsContainer.children[lives];
+ tween(heartToRemove, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ }, {
+ duration: 300,
+ onComplete: function onComplete() {
+ heartToRemove.visible = false;
+ }
+ });
+ }
+ // Check game over
+ if (lives <= 0) {
+ gameState = 'levelSelect';
+ updateGameState();
+ LK.showGameOver();
+ }
+ }
candy.destroy();
candies.splice(i, 1);
}
}
red shiny candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
chocolate cupcake, blue detail, cherry. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
wood stick, green&white stripe apple candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
golden coin . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
chocolate ice-cream, cherry. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
chocolate bar, yellow packet. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
sparkle, rainbow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat