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
****/
// --- Minimal Remake Demo Game ---
// Remove all previous game logic, UI, and overlays
// Score display (top center)
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Demo: a single falling candy, tap to collect for score
var fallingCandy = null;
var candySpeed = 12;
// Function to spawn a new candy
function spawnCandy() {
if (fallingCandy) {
fallingCandy.destroy();
}
fallingCandy = new Candy();
fallingCandy.x = 2048 / 2;
fallingCandy.y = -100;
fallingCandy.speed = candySpeed;
game.addChild(fallingCandy);
}
// Touch handler: tap the candy to collect
game.down = function (x, y, obj) {
if (!fallingCandy) return;
var dx = fallingCandy.x - x;
var dy = fallingCandy.y - y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < fallingCandy.width / 2 + 40) {
// Collect
score++;
scoreTxt.setText(score);
LK.getSound('collect').play();
fallingCandy.destroy();
fallingCandy = null;
// Spawn next candy after short delay
LK.setTimeout(function () {
spawnCandy();
}, 400);
}
};
// Game update: move candy down, respawn if missed
game.update = function () {
if (!fallingCandy) return;
fallingCandy.y += fallingCandy.speed;
if (fallingCandy.y > 2732 + 100) {
// Missed, respawn
fallingCandy.destroy();
fallingCandy = null;
LK.setTimeout(function () {
spawnCandy();
}, 400);
}
};
// Start the game with one candy
spawnCandy();
scoreTxt.setText(score); ===================================================================
--- original.js
+++ change.js
@@ -123,829 +123,63 @@
/****
* Game Code
****/
-// Tabs: 0=Game, 1=Shop, 2=Leaderboard
-// Candies (different colors/shapes for future shop unlocks)
-// Coin
-// Collector (player's swipe area)
-// Shop item placeholder
-// Sounds
-// Music
-var currentTab = 0;
-// GUI tab buttons
-var tabBtnGame, tabBtnShop, tabBtnLeaderboard;
-// GUI overlays
-var coinTxt,
- scoreTxt,
- shopCoinTxt,
- shopTitleTxt,
- shopItems = [],
- shopGroup,
- leaderboardGroup;
-// Game state
-var candies = [];
-var collector;
-var isDragging = false;
-var dragOffsetX = 0,
- dragOffsetY = 0;
-var score = 0;
-var coins = storage.coins || 0;
-var level = 1;
-var candiesToCollect = 10;
-var candiesCollected = 0;
-var gameActive = true;
-var candySpawnTimer = 0;
-var candySpawnInterval = 36; // frames
-// --- Health ---
-var health = 3;
-var healthTxt = new Text2('❤❤❤', {
- size: 90,
- fill: '#ff3b3b'
-});
-healthTxt.anchor.set(0, 0);
-healthTxt.x = 120;
-healthTxt.y = 0;
-LK.gui.top.addChild(healthTxt);
-// Shop data
-var shopSkins = [{
- id: 'candyRed',
- price: 0
-}, {
- id: 'candyGreen',
- price: 20
-}, {
- id: 'candyBlue',
- price: 40
-}, {
- id: 'candyYellow',
- price: 60
-}, {
- id: 'candyPurple',
- price: 100
-}];
-// --- GUI Setup ---
-// Coin display (top right)
-coinTxt = new Text2(coins + '', {
- size: 90,
- fill: '#ffe23b'
-});
-coinTxt.anchor.set(1, 0);
-LK.gui.topRight.addChild(coinTxt);
+// --- Minimal Remake Demo Game ---
+// Remove all previous game logic, UI, and overlays
// Score display (top center)
-scoreTxt = new Text2('0', {
- size: 110,
+var score = 0;
+var scoreTxt = new Text2('0', {
+ size: 120,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
-// Tab buttons (bottom)
-tabBtnGame = new Text2('Game', {
- size: 80,
- fill: '#fff'
-});
-tabBtnGame.anchor.set(0.5, 1);
-tabBtnGame.x = 2048 / 6;
-tabBtnGame.y = 0;
-tabBtnGame.interactive = true;
-tabBtnGame.buttonMode = true;
-LK.gui.bottom.addChild(tabBtnGame);
-tabBtnShop = new Text2('Shop', {
- size: 80,
- fill: '#fff'
-});
-tabBtnShop.anchor.set(0.5, 1);
-tabBtnShop.x = 2048 / 2;
-tabBtnShop.y = 0;
-tabBtnShop.interactive = true;
-tabBtnShop.buttonMode = true;
-LK.gui.bottom.addChild(tabBtnShop);
-tabBtnLeaderboard = new Text2('Leaderboard', {
- size: 80,
- fill: '#fff'
-});
-tabBtnLeaderboard.anchor.set(0.5, 1);
-tabBtnLeaderboard.x = 2048 * 5 / 6;
-tabBtnLeaderboard.y = 0;
-tabBtnLeaderboard.interactive = true;
-tabBtnLeaderboard.buttonMode = true;
-LK.gui.bottom.addChild(tabBtnLeaderboard);
-// Shop overlay group
-shopGroup = new Container();
-shopGroup.visible = false;
-game.addChild(shopGroup);
-// Shop background panel for visual separation
-var shopBgPanel = LK.getAsset('shopItem', {
- anchorX: 0.5,
- anchorY: 0,
- scaleX: 11,
- scaleY: 8.5,
- x: 2048 / 2,
- y: 40
-});
-shopBgPanel.alpha = 0.10;
-shopGroup.addChild(shopBgPanel);
-// Shop title
-shopTitleTxt = new Text2('Shop', {
- size: 150,
- fill: '#ffe23b'
-});
-shopTitleTxt.anchor.set(0.5, 0);
-shopTitleTxt.x = 2048 / 2;
-shopTitleTxt.y = 80;
-shopGroup.addChild(shopTitleTxt);
-// Shop coin display (top right in shop)
-shopCoinTxt = new Text2('Coins: ' + coins, {
- size: 100,
- fill: '#ffe23b'
-});
-shopCoinTxt.anchor.set(1, 0);
-shopCoinTxt.x = 2048 - 80;
-shopCoinTxt.y = 80;
-shopGroup.addChild(shopCoinTxt);
-// Shop return button (top left in shop)
-var shopReturnBtn = new Text2('← Back', {
- size: 90,
- fill: '#ffe23b'
-});
-shopReturnBtn.anchor.set(0, 0);
-shopReturnBtn.x = 100;
-shopReturnBtn.y = 80;
-shopReturnBtn.interactive = true;
-shopReturnBtn.buttonMode = true;
-shopReturnBtn.down = function (x, y, obj) {
- shopGroup.visible = false;
- mainMenuGroup.visible = true;
- shopCurrentTab = 0;
- updateShopTab();
- setTab(0);
-};
-shopGroup.addChild(shopReturnBtn);
-// Shop tab buttons (centered below title, visually grouped)
-var shopTabBar = new Container();
-shopTabBar.x = 2048 / 2;
-shopTabBar.y = 260;
-shopGroup.addChild(shopTabBar);
-var shopTabCharacter = new Text2('Characters', {
- size: 90,
- fill: '#fff'
-});
-shopTabCharacter.anchor.set(1, 0);
-shopTabCharacter.x = -60;
-shopTabCharacter.y = 0;
-shopTabCharacter.interactive = true;
-shopTabCharacter.buttonMode = true;
-var shopTabItem = new Text2('Items', {
- size: 90,
- fill: '#fff'
-});
-shopTabItem.anchor.set(0, 0);
-shopTabItem.x = 60;
-shopTabItem.y = 0;
-shopTabItem.interactive = true;
-shopTabItem.buttonMode = true;
-shopTabBar.addChild(shopTabCharacter);
-shopTabBar.addChild(shopTabItem);
-// Shop tab state: 0 = Characters, 1 = Items
-var shopCurrentTab = 0;
-// Shop tab switching logic
-function updateShopTab() {
- // Defensive: ensure shopItemItems is always an array
- if (typeof shopItemItems === "undefined" || !shopItemItems) {
- shopItemItems = [];
+// Demo: a single falling candy, tap to collect for score
+var fallingCandy = null;
+var candySpeed = 12;
+// Function to spawn a new candy
+function spawnCandy() {
+ if (fallingCandy) {
+ fallingCandy.destroy();
}
- // Characters tab
- if (shopCurrentTab === 0) {
- for (var i = 0; i < shopItems.length; i++) {
- shopItems[i].visible = true;
- // Center vertically for character tab
- shopItems[i].y = 700;
- }
- for (var i = 0; i < shopItemItems.length; i++) {
- shopItemItems[i].visible = false;
- }
- shopTabCharacter.fill = '#ffe23b';
- shopTabItem.fill = '#fff';
- shopTabCharacter.scaleX = shopTabCharacter.scaleY = 1.15;
- shopTabItem.scaleX = shopTabItem.scaleY = 1.0;
- }
- // Items tab
- if (shopCurrentTab === 1) {
- for (var i = 0; i < shopItems.length; i++) {
- shopItems[i].visible = false;
- }
- for (var i = 0; i < shopItemItems.length; i++) {
- shopItemItems[i].visible = true;
- // Center vertically for item tab
- shopItemItems[i].y = 700;
- }
- // Ensure item shop items are brought to front for visibility
- for (var i = 0; i < shopItemItems.length; i++) {
- if (shopGroup.children.indexOf(shopItemItems[i]) !== -1) {
- shopGroup.removeChild(shopItemItems[i]);
- shopGroup.addChild(shopItemItems[i]);
- }
- }
- shopTabCharacter.fill = '#fff';
- shopTabItem.fill = '#ffe23b';
- shopTabCharacter.scaleX = shopTabCharacter.scaleY = 1.0;
- shopTabItem.scaleX = shopTabItem.scaleY = 1.15;
- }
+ fallingCandy = new Candy();
+ fallingCandy.x = 2048 / 2;
+ fallingCandy.y = -100;
+ fallingCandy.speed = candySpeed;
+ game.addChild(fallingCandy);
}
-shopTabCharacter.down = function (x, y, obj) {
- shopCurrentTab = 0;
- updateShopTab();
-};
-shopTabItem.down = function (x, y, obj) {
- shopCurrentTab = 1;
- updateShopTab();
-};
-// Initialize tab highlight
-updateShopTab();
-// Shop items
-shopItems = [];
-for (var i = 0; i < shopSkins.length; i++) {
- var item = new ShopItem();
- var skin = shopSkins[i];
- var owned = storage.unlockedSkins.indexOf(skin.id) !== -1;
- item.setSkin(skin.id, skin.price, owned);
- item.x = 2048 / 2 + (i - 2) * 320;
- item.y = 600;
- // Price/owned label
- var label = new Text2(owned ? 'Owned' : skin.price + ' coins', {
- size: 60,
- fill: owned ? '#3bff6e' : '#fff'
- });
- label.anchor.set(0.5, 0);
- label.y = 120;
- item.addChild(label);
- item.label = label;
- // Selection highlight
- var selectTxt = new Text2('Selected', {
- size: 50,
- fill: '#ffe23b'
- });
- selectTxt.anchor.set(0.5, 0);
- selectTxt.y = 170;
- selectTxt.visible = storage.selectedSkin === skin.id;
- item.addChild(selectTxt);
- item.selectTxt = selectTxt;
- // Touch handler
- (function (item, skin, label, selectTxt) {
- item.down = function (x, y, obj) {
- if (item.owned) {
- storage.selectedSkin = skin.id;
- for (var j = 0; j < shopItems.length; j++) {
- shopItems[j].selectTxt.visible = shopItems[j].skinId === skin.id;
- }
- } else if (coins >= skin.price) {
- coins -= skin.price;
- storage.coins = coins;
- storage.unlockedSkins.push(skin.id);
- item.owned = true;
- item.label.setText('Owned');
- item.label.fill = '#3bff6e';
- item.selectTxt.visible = true;
- storage.selectedSkin = skin.id;
- for (var j = 0; j < shopItems.length; j++) {
- if (shopItems[j] !== item) shopItems[j].selectTxt.visible = false;
- }
- shopCoinTxt.setText('Coins: ' + coins);
- coinTxt.setText(coins);
- LK.getSound('shopBuy').play();
- }
- };
- })(item, skin, label, selectTxt);
- shopGroup.addChild(item);
- shopItems.push(item);
-}
-// --- Item Shop Items ---
-var shopItemItems = [];
-// Item shop data
-var itemShopData = [{
- id: 'healthBooster',
- label: '',
- desc: '+1 Heart (per game)',
- price: 10
-}, {
- id: 'slowMotion',
- label: '',
- desc: '-Y: Slow candies (10s)',
- price: 15
-}, {
- id: 'autoClicker',
- label: '',
- desc: 'Auto collect (10s)',
- price: 25
-}];
-// Track item inventory (permanent for health, consumable for others)
-if (!storage.itemInventory) storage.itemInventory = {
- healthBooster: 0,
- slowMotion: 0,
- autoClicker: 0
-};
-for (var i = 0; i < itemShopData.length; i++) {
- (function (i) {
- var itemData = itemShopData[i];
- var item = new ShopItem();
- // Use 'shopItem' asset for all items
- item.setSkin('shopItem', itemData.price, false);
- item.x = 2048 / 2 + (i - 1) * 320;
- item.y = 600;
- // --- Visual Item Icon ---
- var iconAssetId = null;
- if (itemData.id === "healthBooster") iconAssetId = "candyRed";
- if (itemData.id === "slowMotion") iconAssetId = "candyBlue";
- if (itemData.id === "autoClicker") iconAssetId = "coin";
- var iconVisual = null;
- if (iconAssetId) {
- iconVisual = LK.getAsset(iconAssetId, {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: itemData.id === "autoClicker" ? 1.1 : 0.8,
- scaleY: itemData.id === "autoClicker" ? 1.1 : 0.8,
- y: -60
- });
- item.addChild(iconVisual);
- }
- // Icon/label
- // Removed item name label (iconTxt)
- // Description
- var descTxt = new Text2(itemData.desc, {
- size: 38,
- fill: '#fff'
- });
- descTxt.anchor.set(0.5, 0);
- descTxt.y = 60;
- item.addChild(descTxt);
- // Price/owned label
- var ownedCount = storage.itemInventory[itemData.id] || 0;
- var priceLabel = new Text2('x' + ownedCount + ' ' + itemData.price + ' coins', {
- size: 48,
- fill: '#fff'
- });
- priceLabel.anchor.set(0.5, 0);
- priceLabel.y = 120;
- item.addChild(priceLabel);
- item.priceLabel = priceLabel;
- // Touch handler
- item.down = function (x, y, obj) {
- if (coins >= itemData.price) {
- coins -= itemData.price;
- storage.coins = coins;
- storage.itemInventory[itemData.id] = (storage.itemInventory[itemData.id] || 0) + 1;
- item.priceLabel.setText('x' + storage.itemInventory[itemData.id] + ' ' + itemData.price + ' coins');
- shopCoinTxt.setText('Coins: ' + coins);
- coinTxt.setText(coins);
- LK.getSound('shopBuy').play();
- }
- };
- shopGroup.addChild(item);
- item.visible = false;
- shopItemItems.push(item);
- })(i);
-}
-// Leaderboard overlay group (placeholder)
-leaderboardGroup = new Container();
-leaderboardGroup.visible = false;
-game.addChild(leaderboardGroup);
-var leaderboardTitle = new Text2('Leaderboard', {
- size: 120,
- fill: '#fff'
-});
-leaderboardTitle.anchor.set(0.5, 0);
-leaderboardTitle.x = 2048 / 2;
-leaderboardTitle.y = 180;
-leaderboardGroup.addChild(leaderboardTitle);
-// Leaderboard return button
-var leaderboardReturnBtn = new Text2('Return', {
- size: 80,
- fill: '#ffe23b'
-});
-leaderboardReturnBtn.anchor.set(0, 0);
-leaderboardReturnBtn.x = 80;
-leaderboardReturnBtn.y = 180;
-leaderboardReturnBtn.interactive = true;
-leaderboardReturnBtn.buttonMode = true;
-leaderboardReturnBtn.down = function (x, y, obj) {
- leaderboardGroup.visible = false;
- mainMenuGroup.visible = true;
- setTab(0);
-};
-leaderboardGroup.addChild(leaderboardReturnBtn);
-var leaderboardInfo = new Text2('Check your high score in the system leaderboard!', {
- size: 70,
- fill: '#fff'
-});
-leaderboardInfo.anchor.set(0.5, 0);
-leaderboardInfo.x = 2048 / 2;
-leaderboardInfo.y = 350;
-leaderboardGroup.addChild(leaderboardInfo);
-// --- Main Menu Overlay ---
-var mainMenuGroup = new Container();
-mainMenuGroup.visible = true;
-game.addChild(mainMenuGroup);
-var mainMenuTitle = new Text2('Candy Collector Deluxe', {
- size: 160,
- fill: '#ffe23b'
-});
-mainMenuTitle.anchor.set(0.5, 0);
-mainMenuTitle.x = 2048 / 2;
-mainMenuTitle.y = 400;
-mainMenuGroup.addChild(mainMenuTitle);
-var mainMenuPlayBtn = new Text2('Play', {
- size: 120,
- fill: '#fff'
-});
-mainMenuPlayBtn.anchor.set(0.5, 0.5);
-mainMenuPlayBtn.x = 2048 / 2;
-mainMenuPlayBtn.y = 900;
-mainMenuPlayBtn.interactive = true;
-mainMenuPlayBtn.buttonMode = true;
-mainMenuGroup.addChild(mainMenuPlayBtn);
-var mainMenuShopBtn = new Text2('Shop', {
- size: 100,
- fill: '#fff'
-});
-mainMenuShopBtn.anchor.set(0.5, 0.5);
-mainMenuShopBtn.x = 2048 / 2;
-mainMenuShopBtn.y = 1100;
-mainMenuShopBtn.interactive = true;
-mainMenuShopBtn.buttonMode = true;
-mainMenuGroup.addChild(mainMenuShopBtn);
-var mainMenuLeaderboardBtn = new Text2('Leaderboard', {
- size: 100,
- fill: '#fff'
-});
-mainMenuLeaderboardBtn.anchor.set(0.5, 0.5);
-mainMenuLeaderboardBtn.x = 2048 / 2;
-mainMenuLeaderboardBtn.y = 1250;
-mainMenuLeaderboardBtn.interactive = true;
-mainMenuLeaderboardBtn.buttonMode = true;
-mainMenuGroup.addChild(mainMenuLeaderboardBtn);
-mainMenuPlayBtn.down = function (x, y, obj) {
- mainMenuGroup.visible = false;
- setTab(0);
-};
-mainMenuShopBtn.down = function (x, y, obj) {
- mainMenuGroup.visible = false;
- setTab(1);
-};
-mainMenuLeaderboardBtn.down = function (x, y, obj) {
- mainMenuGroup.visible = false;
- setTab(2);
-};
-// --- Main Game Setup ---
-function resetGame() {
- // Remove candies
- for (var i = candies.length - 1; i >= 0; i--) {
- candies[i].destroy();
- candies.splice(i, 1);
- }
- score = 0;
- candiesCollected = 0;
- candiesToCollect = 10 + (level - 1) * 2;
- candySpawnTimer = 0;
- scoreTxt.setText('0');
- gameActive = true;
- // Reset health, add +1 if health booster owned
- health = 3 + (storage.itemInventory && storage.itemInventory.healthBooster ? storage.itemInventory.healthBooster : 0);
- var hearts = '';
- for (var h = 0; h < health; h++) hearts += '❤';
- healthTxt.setText(hearts);
- // Collector position
- collector.x = 2048 / 2;
- collector.y = 2732 - 220;
- // Reset item effect timers
- slowMotionActive = false;
- slowMotionTimer = 0;
- autoClickerActive = false;
- autoClickerTimer = 0;
-}
-// Collector (player's swipe area)
-collector = new Collector();
-collector.x = 2048 / 2;
-collector.y = 2732 - 220;
-game.addChild(collector);
-// --- Tab Switching ---
-function setTab(tabIdx) {
- currentTab = tabIdx;
- // Game tab
- if (tabIdx === 0) {
- game.visible = true;
- shopGroup.visible = false;
- leaderboardGroup.visible = false;
- coinTxt.visible = true;
- scoreTxt.visible = true;
- collector.visible = true;
- }
- // Shop tab
- if (tabIdx === 1) {
- game.visible = true;
- shopGroup.visible = true;
- leaderboardGroup.visible = false;
- coinTxt.visible = false;
- scoreTxt.visible = false;
- collector.visible = false;
- shopCoinTxt.setText('Coins: ' + coins);
- for (var i = 0; i < shopItems.length; i++) {
- var owned = storage.unlockedSkins.indexOf(shopItems[i].skinId) !== -1;
- shopItems[i].owned = owned;
- shopItems[i].label.setText(owned ? 'Owned' : shopSkins[i].price + ' coins');
- shopItems[i].label.fill = owned ? '#3bff6e' : '#fff';
- shopItems[i].selectTxt.visible = storage.selectedSkin === shopItems[i].skinId;
- // Show/hide based on tab
- shopItems[i].visible = shopCurrentTab === 0;
- }
- updateShopTab();
- }
- // Leaderboard tab
- if (tabIdx === 2) {
- game.visible = true;
- shopGroup.visible = false;
- leaderboardGroup.visible = true;
- coinTxt.visible = false;
- scoreTxt.visible = false;
- collector.visible = false;
- }
-}
-// Tab button handlers
-tabBtnGame.down = function (x, y, obj) {
- setTab(0);
-};
-tabBtnShop.down = function (x, y, obj) {
- setTab(1);
-};
-tabBtnLeaderboard.down = function (x, y, obj) {
- setTab(2);
-};
-// --- Item Usage Buttons ---
-var itemBtnSlow = new Text2('Slow', {
- size: 70,
- fill: '#3b9bff'
-});
-itemBtnSlow.anchor.set(0.5, 0);
-itemBtnSlow.x = 2048 / 2 - 200;
-itemBtnSlow.y = 120;
-itemBtnSlow.interactive = true;
-itemBtnSlow.buttonMode = true;
-LK.gui.top.addChild(itemBtnSlow);
-var itemBtnAuto = new Text2('Auto', {
- size: 70,
- fill: '#3b9bff'
-});
-itemBtnAuto.anchor.set(0.5, 0);
-itemBtnAuto.x = 2048 / 2 + 200;
-itemBtnAuto.y = 120;
-itemBtnAuto.interactive = true;
-itemBtnAuto.buttonMode = true;
-LK.gui.top.addChild(itemBtnAuto);
-// Effect state
-var slowMotionActive = false;
-var slowMotionTimer = 0;
-var autoClickerActive = false;
-var autoClickerTimer = 0;
-// Button handlers
-itemBtnSlow.down = function (x, y, obj) {
- if (!gameActive || mainMenuGroup.visible || currentTab !== 0) return;
- if (storage.itemInventory && storage.itemInventory.slowMotion > 0 && !slowMotionActive) {
- storage.itemInventory.slowMotion--;
- slowMotionActive = true;
- slowMotionTimer = 600; // 10 seconds at 60fps
- itemBtnSlow.setText('Slow (' + storage.itemInventory.slowMotion + ')');
- itemBtnSlow.fill = '#ffe23b';
- }
-};
-itemBtnAuto.down = function (x, y, obj) {
- if (!gameActive || mainMenuGroup.visible || currentTab !== 0) return;
- if (storage.itemInventory && storage.itemInventory.autoClicker > 0 && !autoClickerActive) {
- storage.itemInventory.autoClicker--;
- autoClickerActive = true;
- autoClickerTimer = 600; // 10 seconds at 60fps
- itemBtnAuto.setText('Auto (' + storage.itemInventory.autoClicker + ')');
- itemBtnAuto.fill = '#ffe23b';
- }
-};
-// Update button text on game start
-itemBtnSlow.setText('Slow (' + (storage.itemInventory && storage.itemInventory.slowMotion || 0) + ')');
-itemBtnAuto.setText('Auto (' + (storage.itemInventory && storage.itemInventory.autoClicker || 0) + ')');
-itemBtnSlow.fill = '#3b9bff';
-itemBtnAuto.fill = '#3b9bff';
-// --- Touch Controls ---
-// Drag collector
+// Touch handler: tap the candy to collect
game.down = function (x, y, obj) {
- if (mainMenuGroup.visible || currentTab !== 0 || !gameActive) return;
- // Only drag if touch is on collector
- var local = collector.toLocal({
- x: x,
- y: y
- });
- if (local.x > -collector.width / 2 && local.x < collector.width / 2 && local.y > -collector.height / 2 && local.y < collector.height / 2) {
- isDragging = true;
- dragOffsetX = collector.x - x;
- dragOffsetY = collector.y - y;
+ if (!fallingCandy) return;
+ var dx = fallingCandy.x - x;
+ var dy = fallingCandy.y - y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < fallingCandy.width / 2 + 40) {
+ // Collect
+ score++;
+ scoreTxt.setText(score);
+ LK.getSound('collect').play();
+ fallingCandy.destroy();
+ fallingCandy = null;
+ // Spawn next candy after short delay
+ LK.setTimeout(function () {
+ spawnCandy();
+ }, 400);
}
};
-game.up = function (x, y, obj) {
- if (mainMenuGroup.visible || currentTab !== 0 || !gameActive) return;
- isDragging = false;
-};
-game.move = function (x, y, obj) {
- if (mainMenuGroup.visible || currentTab !== 0 || !gameActive) return;
- if (isDragging) {
- collector.x = Math.max(collector.width / 2, Math.min(2048 - collector.width / 2, x + dragOffsetX));
- collector.y = Math.max(collector.height / 2 + 200, Math.min(2732 - collector.height / 2, y + dragOffsetY));
- }
- // Swipe detection: check for candies under finger
- for (var i = candies.length - 1; i >= 0; i--) {
- var candy = candies[i];
- if (!candy.collected && candy.visible) {
- var dx = candy.x - x;
- var dy = candy.y - y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- if (dist < candy.width / 2 + 40) {
- collectCandy(candy);
- }
- }
- }
-};
-// --- Candy Collection ---
-function collectCandy(candy) {
- if (candy.collected) return;
- candy.collected = true;
- candiesCollected++;
- score++;
- scoreTxt.setText(score);
- // Animate
- tween(candy, {
- scaleX: 1.4,
- scaleY: 1.4,
- alpha: 0
- }, {
- duration: 220,
- easing: tween.cubicIn,
- onFinish: function onFinish() {
- candy.destroy();
- }
- });
- LK.getSound('collect').play();
- // Coin drop
- if (candy.hasCoin) {
- coins++;
- storage.coins = coins;
- coinTxt.setText(coins);
- shopCoinTxt.setText('Coins: ' + coins);
- // Coin fly animation
- var coinFly = new CoinFly();
- coinFly.x = candy.x;
- coinFly.y = candy.y;
- game.addChild(coinFly);
- tween(coinFly, {
- x: 2048 - 120,
- y: 120,
- scaleX: 0.5,
- scaleY: 0.5,
- alpha: 0
- }, {
- duration: 600,
- easing: tween.cubicIn,
- onFinish: function onFinish() {
- coinFly.destroy();
- }
- });
- LK.getSound('coin').play();
- }
- // Remove from candies array
- for (var i = 0; i < candies.length; i++) {
- if (candies[i] === candy) {
- candies.splice(i, 1);
- break;
- }
- }
- // Win condition
- if (candiesCollected >= candiesToCollect) {
- // Save high score
- if (!storage.highScore || score > storage.highScore) {
- storage.highScore = score;
- }
- // Loop: advance to next level and reset game state
- level++;
- resetGame();
- setTab(0);
- return;
- }
-}
-// --- Game Update Loop ---
+// Game update: move candy down, respawn if missed
game.update = function () {
- if (mainMenuGroup.visible || currentTab !== 0 || !gameActive) return;
- // --- Item Effects ---
- if (slowMotionActive) {
- slowMotionTimer--;
- if (slowMotionTimer <= 0) {
- slowMotionActive = false;
- itemBtnSlow.fill = '#3b9bff';
- itemBtnSlow.setText('Slow (' + (storage.itemInventory && storage.itemInventory.slowMotion || 0) + ')');
- }
+ if (!fallingCandy) return;
+ fallingCandy.y += fallingCandy.speed;
+ if (fallingCandy.y > 2732 + 100) {
+ // Missed, respawn
+ fallingCandy.destroy();
+ fallingCandy = null;
+ LK.setTimeout(function () {
+ spawnCandy();
+ }, 400);
}
- if (autoClickerActive) {
- autoClickerTimer--;
- if (autoClickerTimer <= 0) {
- autoClickerActive = false;
- itemBtnAuto.fill = '#3b9bff';
- itemBtnAuto.setText('Auto (' + (storage.itemInventory && storage.itemInventory.autoClicker || 0) + ')');
- }
- }
- // Spawn candies
- candySpawnTimer++;
- var spawnInterval = slowMotionActive ? Math.round(candySpawnInterval * 1.5) : candySpawnInterval;
- if (candies.length < candiesToCollect && candySpawnTimer >= spawnInterval) {
- candySpawnTimer = 0;
- var candy = new Candy();
- // Use selected skin
- candy.skin = storage.selectedSkin || 'candyRed';
- // Random X, avoid edges
- candy.x = 120 + Math.random() * (2048 - 240);
- candy.y = -80;
- // Randomize speed a bit
- candy.speed = (slowMotionActive ? 0.5 : 1) * (10 + Math.random() * 6 + level * 0.5);
- candies.push(candy);
- game.addChild(candy);
- }
- // Update candies
- for (var i = candies.length - 1; i >= 0; i--) {
- var candy = candies[i];
- if (slowMotionActive) {
- // Slow down falling speed
- candy.y += (candy.speed || 12) * 0.5;
- } else {
- candy.update();
- }
- // Collector collision
- if (!candy.collected && collector.visible) {
- var dx = candy.x - collector.x;
- var dy = candy.y - collector.y;
- if (Math.abs(dx) < candy.width / 2 + collector.width / 2 - 30 && Math.abs(dy) < candy.height / 2 + collector.height / 2 - 30) {
- collectCandy(candy);
- }
- }
- // Off-screen (missed)
- if (!candy.collected && candy.y > 2732 + 80 && !candy.missed) {
- candy.missed = true;
- // Animate out
- tween(candy, {
- alpha: 0
- }, {
- duration: 200,
- onFinish: function onFinish() {
- candy.destroy();
- }
- });
- // Remove from candies array
- candies.splice(i, 1);
- // Decrease health and update display
- health--;
- var hearts = '';
- for (var h = 0; h < health; h++) hearts += '❤';
- healthTxt.setText(hearts);
- LK.effects.flashScreen(0xff0000, 600);
- if (health <= 0) {
- LK.showGameOver();
- gameActive = false;
- }
- }
- }
- // --- Auto Clicker effect: auto collect nearest candy ---
- if (autoClickerActive && candies.length > 0) {
- // Find lowest (closest to bottom) visible, uncollected candy
- var best = null,
- bestY = -Infinity;
- for (var i = 0; i < candies.length; i++) {
- if (!candies[i].collected && candies[i].visible && candies[i].y > bestY) {
- best = candies[i];
- bestY = candies[i].y;
- }
- }
- if (best) {
- collectCandy(best);
- }
- }
};
-// --- Music ---
-LK.playMusic('bgmusic');
-// --- Game Over/Win Handlers ---
-LK.on('gameover', function () {
- // Reset game state
- resetGame();
- mainMenuGroup.visible = true;
- setTab(0);
-});
-LK.on('youwin', function () {
- // Next level
- level++;
- resetGame();
- mainMenuGroup.visible = true;
- setTab(0);
-});
-// --- Initial State ---
-resetGame();
-mainMenuGroup.visible = true;
-setTab(0);
\ No newline at end of file
+// Start the game with one candy
+spawnCandy();
+scoreTxt.setText(score);
\ No newline at end of file
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