User prompt
Make a custom keyboard for entering words into text boxes like username and password
User prompt
Please fix the bug: 'Uncaught TypeError: LK.showLeaderboard is not a function' in or related to this line: 'LK.showLeaderboard();' Line Number: 868 āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
Restart all the way back to when we had leaderboards a log out button and a log in button a play button āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
It didn't work fix it so the exit button teleports you back to home screen
User prompt
Change the brown back to light blue and make the exit button teleport you to home screen
User prompt
Wait no keep leaderboard and change back the background and fix the exit button āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
Nevermind go back to how we were
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'y')' in or related to this line: 'createAccountButton.y = 1200;' Line Number: 1063
User prompt
Before you play a level you must create a account āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
When you get into a level there's a button that says exit under the board of foods
User prompt
Try again when I get 4 in a square it doesn't clear a row
User prompt
When ur target hits 1 make sure a 2x2 square of the same food appears on the front of the board of foods then click it and it will clear a row
User prompt
Make a chance of making a 2x2 square bigger
User prompt
When you get the same food in a square 2x2 it clears a row
User prompt
If the same food gets 4 in a row in a square it clears a row
User prompt
Try again didn't work
User prompt
Try again didn't work
User prompt
If you get 4 foods in a square it clears a row
User prompt
Now add pizza as red circles
User prompt
Now add hot dogs as light brown circles
User prompt
Try again didn't work
User prompt
While in game your profile picture and info should be hidden
User prompt
Get rid of the guest players on the leaderboard āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
Now remove everyone from the leaderboard āŖš” Consider importing and using the following plugins: @upit/storage.v1
User prompt
Change the leaderboard theme when people's names are displayed don't use a rose use a long pink line with the players name on it
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var FoodItem = Container.expand(function (foodType) { var self = Container.call(this); self.foodType = foodType; self.gridX = -1; self.gridY = -1; self.isMatched = false; self.isAnimating = false; var foodGraphics = self.attachAsset(foodType, { anchorX: 0.5, anchorY: 0.5 }); self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2; self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2; }; self.animateToPosition = function (targetX, targetY, callback) { self.isAnimating = true; tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.isAnimating = false; if (callback) callback(); } }); }; self.animateMatch = function (callback) { self.isMatched = true; // First make it bigger and sparkly tween(self, { scaleX: 1.3, scaleY: 1.3, tint: 0xFFD700 }, { duration: 150, easing: tween.bounceOut }); // Then shrink away with stars effect tween(self, { scaleX: 0, scaleY: 0, alpha: 0, rotation: Math.PI * 2 }, { duration: 300, easing: tween.easeIn, onFinish: callback }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c1810 }); /**** * Game Code ****/ var GRID_SIZE = 8; var CELL_SIZE = 240; var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var GRID_START_Y = 300; var FOOD_TYPES = ['apple', 'banana', 'orange', 'grape', 'lemon', 'hamburger']; var grid = []; var selectedFood = null; var isProcessingMatches = false; var movesLeft = 30; var currentScore = 0; var targetMatches = 10; var matchesCleared = 0; var swipeStartX = 0; var swipeStartY = 0; var swipeFood = null; var isSwipeActive = false; var SWIPE_THRESHOLD = 50; var currentLevel = storage.currentLevel || 1; var maxUnlockedLevel = storage.maxUnlockedLevel || 1; var totalScore = storage.totalScore || 0; var isAccountCreated = storage.isAccountCreated || false; var username = storage.username || ''; var gameState = 'playing'; // 'playing', 'levelComplete', 'levelSelect', 'loginScreen' var savedPassword = storage.savedPassword || ''; var savedUsername = storage.savedUsername || ''; var isLoggedOut = false; var levelCompleteShown = false; var usernameValue = ''; var usernameFocused = false; var usernameText = null; var passwordValue = ''; var passwordFocused = false; var passwordText = null; var passwordVisible = false; var isPCUser = false; // Detect if user is on PC (has physical keyboard) function detectPCUser() { // Check for common PC indicators if (typeof window !== 'undefined' && window.navigator) { var userAgent = window.navigator.userAgent || ''; var platform = window.navigator.platform || ''; // Check if it's not a mobile device var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent); var isTablet = /iPad|Android(?=.*Tablet)|Tablet/i.test(userAgent); // If not mobile and not tablet, assume PC isPCUser = !isMobile && !isTablet; } return isPCUser; } // Initialize PC detection detectPCUser(); // Initialize grid array for (var x = 0; x < GRID_SIZE; x++) { grid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { grid[x][y] = null; } } // Create grid background var gridBackground = new Container(); game.addChild(gridBackground); for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { var cell = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5 }); cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; cell.alpha = 0.3; gridBackground.addChild(cell); } } // Create UI var scoreText = new Text2('Score: 0', { size: 100, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 120; var movesText = new Text2('Moves: 30', { size: 80, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); LK.gui.topLeft.addChild(movesText); movesText.x = 150; movesText.y = 50; var tutorialText = new Text2('Lvl' + currentLevel, { size: 120, fill: 0xFFFFFF }); tutorialText.anchor.set(0.5, 0); LK.gui.top.addChild(tutorialText); tutorialText.y = 20; var targetText = new Text2('Target: ' + targetMatches, { size: 100, fill: 0xFFFFFF }); targetText.anchor.set(0, 0); LK.gui.top.addChild(targetText); targetText.x = tutorialText.x + tutorialText.width / 2 + 50; targetText.y = tutorialText.y; function getRandomFoodType() { return FOOD_TYPES[Math.floor(Math.random() * FOOD_TYPES.length)]; } function createFoodItem(x, y) { var foodType = getRandomFoodType(); var food = new FoodItem(foodType); food.setGridPosition(x, y); grid[x][y] = food; game.addChild(food); // Add fun spawn animation with rainbow colors food.scaleX = 0; food.scaleY = 0; food.alpha = 0; var rainbowColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECA57, 0xFF9FF3, 0x54A0FF]; var randomColor = rainbowColors[Math.floor(Math.random() * rainbowColors.length)]; food.tint = randomColor; tween(food, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 500, easing: tween.bounceOut }); // Reset to normal color after spawn tween(food, { tint: 0xFFFFFF }, { duration: 800, easing: tween.easeOut }); return food; } function initializeGrid() { for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { createFoodItem(x, y); } } // Remove initial matches var foundMatches = true; while (foundMatches) { var matches = findAllMatches(); if (matches.length > 0) { for (var i = 0; i < matches.length; i++) { var match = matches[i]; if (grid[match.x] && grid[match.x][match.y]) { grid[match.x][match.y].destroy(); grid[match.x][match.y] = null; } } fillEmptySpaces(); } else { foundMatches = false; } } } function isValidPosition(x, y) { return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE; } function isAdjacent(x1, y1, x2, y2) { var dx = Math.abs(x1 - x2); var dy = Math.abs(y1 - y2); return dx === 1 && dy === 0 || dx === 0 && dy === 1; } function swapFoods(food1, food2) { if (!food1 || !food2) return false; var x1 = food1.gridX; var y1 = food1.gridY; var x2 = food2.gridX; var y2 = food2.gridY; // Swap in grid grid[x1][y1] = food2; grid[x2][y2] = food1; // Update grid positions food1.setGridPosition(x2, y2); food2.setGridPosition(x1, y1); // Animate swap var targetX1 = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2; var targetY1 = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2; var targetX2 = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2; var targetY2 = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2; food1.animateToPosition(targetX1, targetY1); food2.animateToPosition(targetX2, targetY2); return true; } function findMatches(x, y) { var matches = []; if (!grid[x] || !grid[x][y]) return matches; var foodType = grid[x][y].foodType; // Check horizontal matches var horizontalMatches = [{ x: x, y: y }]; // Check left for (var i = x - 1; i >= 0; i--) { if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) { horizontalMatches.push({ x: i, y: y }); } else { break; } } // Check right for (var i = x + 1; i < GRID_SIZE; i++) { if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) { horizontalMatches.push({ x: i, y: y }); } else { break; } } if (horizontalMatches.length >= 3) { matches = matches.concat(horizontalMatches); } // Check vertical matches var verticalMatches = [{ x: x, y: y }]; // Check up for (var i = y - 1; i >= 0; i--) { if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) { verticalMatches.push({ x: x, y: i }); } else { break; } } // Check down for (var i = y + 1; i < GRID_SIZE; i++) { if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) { verticalMatches.push({ x: x, y: i }); } else { break; } } if (verticalMatches.length >= 3) { matches = matches.concat(verticalMatches); } return matches; } function findAllMatches() { var allMatches = []; var processed = {}; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x] && grid[x][y] && !processed[x + ',' + y]) { var matches = findMatches(x, y); for (var i = 0; i < matches.length; i++) { var match = matches[i]; var key = match.x + ',' + match.y; if (!processed[key]) { allMatches.push(match); processed[key] = true; } } } } } return allMatches; } function processMatches() { if (isProcessingMatches) return; var matches = findAllMatches(); if (matches.length === 0) return; isProcessingMatches = true; LK.getSound('match').play(); var matchCount = matches.length; currentScore += matchCount * 10; matchesCleared += matchCount; targetMatches = Math.max(0, targetMatches - 2); updateUI(); // Update total score and leaderboard instantly when getting points totalScore += matchCount * 10; storage.totalScore = totalScore; addToLeaderboard(totalScore); // Play squeaky voice when getting points LK.getSound('goodJobBooby').play(); // Add celebration effects for bigger matches if (matchCount >= 4) { // Big match celebration! LK.effects.flashScreen(0xFFD700, 500); // Make score text dance tween(scoreText, { scaleX: 1.3, scaleY: 1.3 }, { duration: 300, easing: tween.bounceOut }); tween(scoreText, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.bounceOut }); } var animationsCompleted = 0; for (var i = 0; i < matches.length; i++) { var match = matches[i]; if (grid[match.x] && grid[match.x][match.y]) { grid[match.x][match.y].animateMatch(function () { animationsCompleted++; if (animationsCompleted === matchCount) { // Remove matched foods for (var j = 0; j < matches.length; j++) { var m = matches[j]; if (grid[m.x] && grid[m.x][m.y]) { grid[m.x][m.y].destroy(); grid[m.x][m.y] = null; } } fillEmptySpaces(); LK.setTimeout(function () { isProcessingMatches = false; processMatches(); // Check for cascade matches }, 300); } }); } } if (matchCount === 0) { isProcessingMatches = false; } } function fillEmptySpaces() { // Drop existing foods for (var x = 0; x < GRID_SIZE; x++) { var writeIndex = GRID_SIZE - 1; for (var y = GRID_SIZE - 1; y >= 0; y--) { if (grid[x][y] !== null) { if (y !== writeIndex) { grid[x][writeIndex] = grid[x][y]; grid[x][y] = null; grid[x][writeIndex].setGridPosition(x, writeIndex); var targetY = GRID_START_Y + writeIndex * CELL_SIZE + CELL_SIZE / 2; grid[x][writeIndex].animateToPosition(grid[x][writeIndex].x, targetY); } writeIndex--; } } // Create new foods for empty spaces at top for (var y = 0; y <= writeIndex; y++) { var food = new FoodItem(getRandomFoodType()); food.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; food.y = GRID_START_Y - (writeIndex - y + 1) * CELL_SIZE + CELL_SIZE / 2; food.gridX = x; food.gridY = y; grid[x][y] = food; game.addChild(food); var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; food.animateToPosition(food.x, targetY); } } } function updateUI() { if (scoreText) { scoreText.setText('Score: ' + currentScore); } if (movesText) { movesText.setText('Moves: ' + movesLeft); } if (targetText) { targetText.setText('Target: ' + targetMatches); } } function checkGameEnd() { if (targetMatches <= 0) { if (currentLevel === 1 && !levelCompleteShown) { showLevelComplete(); } else { completeLevel(); } } else if (movesLeft <= 0) { LK.showGameOver(); } } function showLevelComplete() { levelCompleteShown = true; gameState = 'levelComplete'; // Play celebration music LK.playMusic('celebrationMusic', { loop: false }); // Play level complete sound LK.getSound('levelComplete').play(); // Add celebration effects LK.effects.flashScreen(0xFFD700, 1000); // Make all UI elements dance tween(scoreText, { scaleX: 1.5, scaleY: 1.5, rotation: 0.2 }, { duration: 500, easing: tween.bounceOut }); tween(tutorialText, { scaleX: 1.3, scaleY: 1.3, rotation: -0.1 }, { duration: 600, easing: tween.bounceOut }); tween(targetText, { scaleX: 1.2, scaleY: 1.2, rotation: 0.15 }, { duration: 700, easing: tween.bounceOut }); LK.setTimeout(function () { showWhiteScreen(); }, 3000); } function showWhiteScreen() { gameState = 'whiteScreen'; // Clear all game elements game.removeChildren(); // Clear tutorial UI elements if (tutorialText && tutorialText.parent) { tutorialText.destroy(); tutorialText = null; } if (targetText && targetText.parent) { targetText.destroy(); targetText = null; } if (scoreText && scoreText.parent) { scoreText.destroy(); scoreText = null; } if (movesText && movesText.parent) { movesText.destroy(); movesText = null; } // Set white background game.setBackgroundColor(0xFFFFFF); // Show white screen for 2 seconds then show home screen LK.setTimeout(function () { showHomeScreen(); }, 2000); } function showHomeScreen() { gameState = 'homeScreen'; // Clear all game elements first to remove any login screen elements game.removeChildren(); // Set cheerful rainbow gradient background game.setBackgroundColor(0x87CEEB); // Start playing happy background music LK.playMusic('happyBgMusic', { loop: true }); // Clear all UI elements from the screen if (tutorialText && tutorialText.parent) { tutorialText.destroy(); tutorialText = null; } if (targetText && targetText.parent) { targetText.destroy(); targetText = null; } if (scoreText && scoreText.parent) { scoreText.destroy(); scoreText = null; } if (movesText && movesText.parent) { movesText.destroy(); movesText = null; } // Create buttons container var buttonsContainer = new Container(); game.addChild(buttonsContainer); // Create Account button var createAccountButton = new Container(); var createAccountBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); createAccountBg.tint = 0x4CAF50; // Green tint createAccountButton.addChild(createAccountBg); var createAccountText = new Text2('Create Account', { size: 80, fill: 0xFFFFFF }); createAccountText.anchor.set(0.5, 0.5); createAccountButton.addChild(createAccountText); createAccountButton.x = 1024; createAccountButton.y = 1200; createAccountButton.down = function () { // Handle create account action console.log('Create Account pressed'); // Play button click sound LK.getSound('buttonClick').play(); // Add fun button press animation tween(createAccountButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); tween(createAccountButton, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); showCreateAccountScreen(); }; buttonsContainer.addChild(createAccountButton); // Play as Guest button var playAsGuestButton = new Container(); var playAsGuestBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); playAsGuestBg.tint = 0x2196F3; // Blue tint playAsGuestButton.addChild(playAsGuestBg); var playAsGuestText = new Text2('Play', { size: 80, fill: 0xFFFFFF }); playAsGuestText.anchor.set(0.5, 0.5); playAsGuestButton.addChild(playAsGuestText); playAsGuestButton.x = 1024; playAsGuestButton.y = 1500; playAsGuestButton.down = function () { // Handle play as guest action console.log('Play as Guest pressed'); // Play button click sound LK.getSound('buttonClick').play(); // Add fun button press animation tween(playAsGuestButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); tween(playAsGuestButton, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); // Start the game startLevel(1); }; buttonsContainer.addChild(playAsGuestButton); // Add floating animations to make buttons more lively // Add profile picture and user info in top right corner if account is created if (isAccountCreated) { var profileContainer = new Container(); LK.gui.topRight.addChild(profileContainer); // Profile picture background (circular) var profilePicBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); profilePicBg.tint = 0x4CAF50; // Green tint for profile pic profileContainer.addChild(profilePicBg); // Profile picture initial (first letter of username) var profileInitial = new Text2(username.charAt(0).toUpperCase(), { size: 60, fill: 0xFFFFFF }); profileInitial.anchor.set(0.5, 0.5); profileContainer.addChild(profileInitial); // Username text below profile pic var usernameDisplay = new Text2('User: ' + username, { size: 35, fill: 0xFFFFFF }); usernameDisplay.anchor.set(0.5, 0); usernameDisplay.y = 60; profileContainer.addChild(usernameDisplay); // Password text below username var passwordDisplay = new Text2('Pass: ' + (storage.password || savedPassword || ''), { size: 35, fill: 0xFFFFFF }); passwordDisplay.anchor.set(0.5, 0); passwordDisplay.y = 100; profileContainer.addChild(passwordDisplay); // Position profile container in top right profileContainer.x = -120; profileContainer.y = 80; // Add Log Out button in center area with other buttons var logOutButton = new Container(); var logOutBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); logOutBg.tint = 0xF44336; // Red tint logOutButton.addChild(logOutBg); var logOutText = new Text2('Log Out', { size: 80, fill: 0xFFFFFF }); logOutText.anchor.set(0.5, 0.5); logOutButton.addChild(logOutText); logOutButton.x = 1024; logOutButton.y = 1800; logOutButton.down = function () { // Add fun button press animation tween(logOutButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); tween(logOutButton, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); // Save credentials before logging out storage.savedUsername = username; storage.savedPassword = storage.password || ''; // Log out the user isAccountCreated = false; username = ''; storage.isAccountCreated = false; storage.username = ''; isLoggedOut = true; // Show login screen instead of home screen showLoginScreen(); }; buttonsContainer.addChild(logOutButton); // Add Leaderboard button if account is created var leaderboardButton = new Container(); var leaderboardBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); leaderboardBg.tint = 0xFF9800; // Orange tint leaderboardButton.addChild(leaderboardBg); var leaderboardText = new Text2('Leaderboard', { size: 80, fill: 0xFFFFFF }); leaderboardText.anchor.set(0.5, 0.5); leaderboardButton.addChild(leaderboardText); leaderboardButton.x = 1024; leaderboardButton.y = 900; leaderboardButton.down = function () { // Play button click sound LK.getSound('buttonClick').play(); // Add fun button press animation tween(leaderboardButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); tween(leaderboardButton, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); showLeaderboardScreen(); }; buttonsContainer.addChild(leaderboardButton); // Adjust other button positions createAccountButton.y = 1200; playAsGuestButton.y = 1400; logOutButton.y = 1600; } tween(createAccountButton, { y: createAccountButton.y - 10 }, { duration: 2000, easing: tween.easeInOut }); tween(createAccountButton, { y: createAccountButton.y + 10 }, { duration: 2000, easing: tween.easeInOut }); tween(playAsGuestButton, { y: playAsGuestButton.y + 10 }, { duration: 2500, easing: tween.easeInOut }); tween(playAsGuestButton, { y: playAsGuestButton.y - 10 }, { duration: 2500, easing: tween.easeInOut }); } function showCreateAccountScreen() { gameState = 'createAccount'; // Clear existing elements game.removeChildren(); // Keep green background game.setBackgroundColor(0x00FF00); // Create container for account creation elements var accountContainer = new Container(); game.addChild(accountContainer); // Title var titleText = new Text2('Create Account', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; accountContainer.addChild(titleText); // Username input field var usernameField = new Container(); var usernameBg = LK.getAsset('inputField', { width: 720, height: 144, color: 0xFFFFFF, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); usernameField.addChild(usernameBg); usernameText = new Text2('Enter username...', { size: 60, fill: 0x666666 }); usernameText.anchor.set(0.5, 0.5); usernameField.addChild(usernameText); usernameField.x = 1024; usernameField.y = 800; usernameField.down = function () { usernameFocused = true; passwordFocused = false; if (usernameValue === '') { usernameText.setText('|'); usernameText.fill = 0x000000; } showCustomKeyboard(); }; accountContainer.addChild(usernameField); // Password input field var passwordField = new Container(); var passwordBg = LK.getAsset('inputField', { width: 720, height: 144, color: 0xFFFFFF, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); passwordField.addChild(passwordBg); passwordField.x = 1024; passwordField.y = 1100; passwordText = new Text2('Enter password...', { size: 60, fill: 0x666666 }); passwordText.anchor.set(0.5, 0.5); passwordField.addChild(passwordText); // Password label beside the button var passwordLabel = new Text2('Password:', { size: 60, fill: 0x000000 }); passwordLabel.anchor.set(1, 0.5); passwordLabel.x = 1024 - 360 - 20; // Position to the left of the password field passwordLabel.y = 1100; accountContainer.addChild(passwordLabel); passwordField.down = function () { usernameFocused = false; passwordFocused = true; if (passwordValue === '') { passwordText.setText('|'); passwordText.fill = 0x000000; } showCustomKeyboard(); }; accountContainer.addChild(passwordField); // Eye button to toggle password visibility var eyeButton = new Container(); var eyeBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); eyeBg.tint = 0xCCCCCC; eyeButton.addChild(eyeBg); var eyeText = new Text2('š', { size: 50, fill: 0x000000 }); eyeText.anchor.set(0.5, 0.5); eyeButton.addChild(eyeText); eyeButton.x = 1024 + 360 + 80; // Position to the right of the password field eyeButton.y = 1100; var passwordVisible = false; eyeButton.down = function () { passwordVisible = !passwordVisible; if (passwordVisible) { // Show actual password eyeText.setText('š'); if (passwordValue !== '') { passwordText.setText(passwordValue); } } else { // Hide password with asterisks eyeText.setText('š'); if (passwordValue !== '') { passwordText.setText('*'.repeat(passwordValue.length)); } } }; accountContainer.addChild(eyeButton); // Create Account button var createButton = new Container(); var createBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); createBg.tint = 0x4CAF50; // Green tint createButton.addChild(createBg); var createText = new Text2('Create', { size: 80, fill: 0xFFFFFF }); createText.anchor.set(0.5, 0.5); createButton.addChild(createText); createButton.x = 1024; createButton.y = 1400; createButton.down = function () { // Play button click sound LK.getSound('buttonClick').play(); // Handle account creation and save progress console.log('Account created'); // Save account data to storage storage.isAccountCreated = true; storage.username = usernameValue; storage.password = passwordValue; storage.totalScore = totalScore; storage.currentLevel = currentLevel; storage.maxUnlockedLevel = maxUnlockedLevel; // Update global variables isAccountCreated = true; username = usernameValue; // Show leaderboard button and start game showLeaderboardScreen(); }; accountContainer.addChild(createButton); // Back button var backButton = new Container(); var backBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 0.6 }); backBg.tint = 0x757575; // Gray tint backButton.addChild(backBg); var backText = new Text2('Back', { size: 60, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backButton.addChild(backText); backButton.x = 1024; backButton.y = 1600; backButton.down = function () { showHomeScreen(); }; accountContainer.addChild(backButton); } var customKeyboard = null; var keyboardKeys = [['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'], ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], ['Z', 'X', 'C', 'V', 'B', 'N', 'M']]; function showCustomKeyboard() { // Don't show custom keyboard for PC users if (isPCUser) { setupPCKeyboardListeners(); return; } if (customKeyboard) { hideCustomKeyboard(); } customKeyboard = new Container(); game.addChild(customKeyboard); // Keyboard background var keyboardBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 4 }); keyboardBg.tint = 0x333333; keyboardBg.x = 1024; keyboardBg.y = 2200; customKeyboard.addChild(keyboardBg); // Create keyboard keys var startY = 1900; var keySize = 180; var keySpacing = 200; for (var row = 0; row < keyboardKeys.length; row++) { var rowKeys = keyboardKeys[row]; var rowWidth = rowKeys.length * keySpacing; var startX = 1024 - rowWidth / 2 + keySpacing / 2; for (var col = 0; col < rowKeys.length; col++) { var keyChar = rowKeys[col]; var keyButton = createKeyButton(keyChar, keySize); keyButton.x = startX + col * keySpacing; keyButton.y = startY + row * 220; customKeyboard.addChild(keyButton); } } // Add space bar var spaceButton = createKeyButton(' ', keySize * 4); spaceButton.x = 1024; spaceButton.y = startY + keyboardKeys.length * 220; customKeyboard.addChild(spaceButton); // Add backspace button var backspaceButton = createKeyButton('ā«', keySize * 1.5); backspaceButton.x = 1024 + 400; backspaceButton.y = startY + keyboardKeys.length * 220; customKeyboard.addChild(backspaceButton); // Add done button var doneButton = createKeyButton('Done', keySize * 1.5); doneButton.x = 1024 - 400; doneButton.y = startY + keyboardKeys.length * 220; customKeyboard.addChild(doneButton); } function setupPCKeyboardListeners() { if (typeof window === 'undefined' || !window.addEventListener) return; // Remove existing listeners to avoid duplicates removePCKeyboardListeners(); window.addEventListener('keydown', handlePCKeyDown); } function removePCKeyboardListeners() { if (typeof window === 'undefined' || !window.removeEventListener) return; window.removeEventListener('keydown', handlePCKeyDown); } function handlePCKeyDown(event) { if (!usernameFocused && !passwordFocused) return; event.preventDefault(); var key = event.key; // Handle special keys if (key === 'Enter' || key === 'Tab') { // Switch between fields or finish input if (usernameFocused) { usernameFocused = false; passwordFocused = true; if (usernameValue === '') { usernameText.setText('Enter username...'); usernameText.fill = 0x666666; } else { usernameText.setText(usernameValue); } if (passwordValue === '') { passwordText.setText('|'); passwordText.fill = 0x000000; } } else if (passwordFocused) { passwordFocused = false; if (passwordValue === '') { passwordText.setText('Enter password...'); passwordText.fill = 0x666666; } else { if (passwordVisible) { passwordText.setText(passwordValue); } else { passwordText.setText('*'.repeat(passwordValue.length)); } } } return; } if (key === 'Backspace') { if (usernameFocused && usernameValue.length > 0) { usernameValue = usernameValue.slice(0, -1); if (usernameValue === '') { usernameText.setText('|'); } else { usernameText.setText(usernameValue + '|'); } } else if (passwordFocused && passwordValue.length > 0) { passwordValue = passwordValue.slice(0, -1); if (passwordValue === '') { passwordText.setText('|'); } else { if (passwordVisible) { passwordText.setText(passwordValue + '|'); } else { passwordText.setText('*'.repeat(passwordValue.length) + '|'); } } } return; } // Handle regular character input if (key.length === 1) { if (usernameFocused && usernameValue.length < 20) { // Limit username length usernameValue += key; usernameText.setText(usernameValue + '|'); } else if (passwordFocused && passwordValue.length < 20) { // Limit password length if (passwordValue === '') { // Clear placeholder text when starting to type passwordText.fill = 0x000000; } passwordValue += key; if (passwordVisible) { passwordText.setText(passwordValue + '|'); } else { passwordText.setText('*'.repeat(passwordValue.length) + '|'); } } } } function createKeyButton(keyChar, width) { var keyButton = new Container(); var keyBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: width / 240, scaleY: 0.5 }); keyBg.tint = 0xCCCCCC; keyButton.addChild(keyBg); var keyText = new Text2(keyChar === ' ' ? 'Space' : keyChar, { size: keyChar === 'Done' ? 90 : 120, fill: 0x000000 }); keyText.anchor.set(0.5, 0.5); keyButton.addChild(keyText); keyButton.down = function () { // Add fun key press animation tween(keyButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 50, easing: tween.easeOut }); tween(keyButton, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.bounceOut }); if (keyChar === 'Done') { hideCustomKeyboard(); if (usernameFocused) { usernameFocused = false; if (usernameValue === '') { usernameText.setText('Enter username...'); usernameText.fill = 0x666666; } else { usernameText.setText(usernameValue); } } else if (passwordFocused) { passwordFocused = false; if (passwordValue === '') { passwordText.setText('Enter password...'); passwordText.fill = 0x666666; } else { if (passwordVisible) { passwordText.setText(passwordValue); } else { passwordText.setText('*'.repeat(passwordValue.length)); } } } } else if (keyChar === 'ā«') { if (usernameFocused && usernameValue.length > 0) { usernameValue = usernameValue.slice(0, -1); if (usernameValue === '') { usernameText.setText('|'); } else { usernameText.setText(usernameValue + '|'); } } else if (passwordFocused && passwordValue.length > 0) { passwordValue = passwordValue.slice(0, -1); if (passwordValue === '') { passwordText.setText('|'); } else { if (passwordVisible) { passwordText.setText(passwordValue + '|'); } else { passwordText.setText('*'.repeat(passwordValue.length) + '|'); } } } } else { if (usernameFocused && usernameValue.length < 20) { // Limit username length usernameValue += keyChar; usernameText.setText(usernameValue + '|'); } else if (passwordFocused && passwordValue.length < 20) { // Limit password length if (passwordValue === '') { // Clear placeholder text when starting to type passwordText.fill = 0x000000; } passwordValue += keyChar; if (passwordVisible) { passwordText.setText(passwordValue + '|'); } else { passwordText.setText('*'.repeat(passwordValue.length) + '|'); } } } // Visual feedback with fun colors var funColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECA57]; var randomColor = funColors[Math.floor(Math.random() * funColors.length)]; keyBg.tint = randomColor; LK.setTimeout(function () { keyBg.tint = 0xCCCCCC; }, 200); }; return keyButton; } function hideCustomKeyboard() { if (customKeyboard) { customKeyboard.destroy(); customKeyboard = null; } // Clean up PC keyboard listeners if (isPCUser) { removePCKeyboardListeners(); } } function completeLevel() { // Update progress if (currentLevel >= maxUnlockedLevel) { maxUnlockedLevel = currentLevel + 1; storage.maxUnlockedLevel = maxUnlockedLevel; } storage.currentLevel = currentLevel; // Add current score to total score totalScore += currentScore; storage.totalScore = totalScore; // Upload highest total score to leaderboard addToLeaderboard(totalScore); // Show home screen instead of level select showHomeScreen(); } function startLevel(levelNum) { currentLevel = levelNum; gameState = 'playing'; levelCompleteShown = false; // Continue playing background music during gameplay LK.playMusic('happyBgMusic', { loop: true }); // Adjust difficulty based on level targetMatches = Math.min(10 + (levelNum - 1) * 5, 100); movesLeft = Math.max(30 - Math.floor((levelNum - 1) / 3), 15); currentScore = 0; matchesCleared = 0; // Clear existing UI game.removeChildren(); // Recreate game setupGame(); } function setupGame() { // Recreate grid background gridBackground = new Container(); game.addChild(gridBackground); for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { var cell = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5 }); cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; cell.alpha = 0.3; gridBackground.addChild(cell); } } // Clear existing UI elements if (tutorialText && tutorialText.parent) { tutorialText.destroy(); } if (targetText && targetText.parent) { targetText.destroy(); } // Recreate UI elements if they don't exist if (!scoreText) { scoreText = new Text2('Score: 0', { size: 100, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 120; } if (!movesText) { movesText = new Text2('Moves: ' + movesLeft, { size: 80, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); LK.gui.topLeft.addChild(movesText); movesText.x = 150; movesText.y = 50; } // Update UI scoreText.setText('Score: 0'); movesText.setText('Moves: ' + movesLeft); tutorialText = new Text2('Lvl' + currentLevel, { size: 120, fill: 0xFFFFFF }); tutorialText.anchor.set(0.5, 0); LK.gui.top.addChild(tutorialText); tutorialText.y = 20; targetText = new Text2('Target: ' + targetMatches, { size: 100, fill: 0xFFFFFF }); targetText.anchor.set(0, 0); LK.gui.top.addChild(targetText); targetText.x = tutorialText.x + tutorialText.width / 2 + 50; targetText.y = tutorialText.y; // Initialize grid initializeGrid(); updateUI(); } function getFoodAtPosition(x, y) { var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE); var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE); if (isValidPosition(gridX, gridY) && grid[gridX] && grid[gridX][gridY]) { return grid[gridX][gridY]; } return null; } game.down = function (x, y, obj) { if (isProcessingMatches) return; var food = getFoodAtPosition(x, y); if (food && !food.isAnimating) { swipeStartX = x; swipeStartY = y; swipeFood = food; isSwipeActive = true; swipeFood.alpha = 0.7; // Add fun wobble animation when selected tween(swipeFood, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.bounceOut }); } }; game.up = function (x, y, obj) { if (!isSwipeActive || !swipeFood) return; var deltaX = x - swipeStartX; var deltaY = y - swipeStartY; var swipeDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (swipeDistance < SWIPE_THRESHOLD) { // Not a swipe, reset swipeFood.alpha = 1; isSwipeActive = false; swipeFood = null; return; } // Determine swipe direction var targetGridX = swipeFood.gridX; var targetGridY = swipeFood.gridY; var absDeltaX = Math.abs(deltaX); var absDeltaY = Math.abs(deltaY); if (absDeltaX > absDeltaY) { // Horizontal swipe if (deltaX > 0) { targetGridX++; // Swipe right } else { targetGridX--; // Swipe left } } else { // Vertical swipe if (deltaY > 0) { targetGridY++; // Swipe down } else { targetGridY--; // Swipe up } } // Check if target position is valid if (isValidPosition(targetGridX, targetGridY) && grid[targetGridX] && grid[targetGridX][targetGridY]) { var targetFood = grid[targetGridX][targetGridY]; if (!targetFood.isAnimating) { LK.getSound('swap').play(); // Store original positions BEFORE any swap var tempFood1 = swipeFood; var tempFood2 = targetFood; var originalX1 = tempFood1.gridX; var originalY1 = tempFood1.gridY; var originalX2 = tempFood2.gridX; var originalY2 = tempFood2.gridY; // Try swap swapFoods(tempFood1, tempFood2); LK.setTimeout(function () { var matches = findAllMatches(); if (matches.length === 0) { // Invalid move, animate swap back to original positions var targetX1 = GRID_START_X + originalX1 * CELL_SIZE + CELL_SIZE / 2; var targetY1 = GRID_START_Y + originalY1 * CELL_SIZE + CELL_SIZE / 2; var targetX2 = GRID_START_X + originalX2 * CELL_SIZE + CELL_SIZE / 2; var targetY2 = GRID_START_Y + originalY2 * CELL_SIZE + CELL_SIZE / 2; tempFood1.animateToPosition(targetX1, targetY1); tempFood2.animateToPosition(targetX2, targetY2); // Restore original grid positions grid[originalX1][originalY1] = tempFood1; grid[originalX2][originalY2] = tempFood2; tempFood1.gridX = originalX1; tempFood1.gridY = originalY1; tempFood2.gridX = originalX2; tempFood2.gridY = originalY2; } else { // Valid move movesLeft--; updateUI(); processMatches(); checkGameEnd(); } }, 350); } } // Reset swipe state with fun bounce back animation tween(swipeFood, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.bounceOut }); isSwipeActive = false; swipeFood = null; }; // Start background music when game loads LK.playMusic('happyBgMusic', { loop: true }); // Initialize the game - start with home screen showHomeScreen(); function showLeaderboardScreen() { gameState = 'leaderboard'; // Clear existing elements game.removeChildren(); // Set background game.setBackgroundColor(0x4CAF50); // Create container for leaderboard elements var leaderboardContainer = new Container(); game.addChild(leaderboardContainer); // Title var titleText = new Text2('Leaderboard', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 300; leaderboardContainer.addChild(titleText); // Get leaderboard data from storage - stored as separate arrays var leaderboardUsernames = storage.leaderboardUsernames || []; var leaderboardScores = storage.leaderboardScores || []; // Display leaderboard entries var startY = 500; var entryHeight = 120; for (var i = 0; i < Math.min(leaderboardUsernames.length, 10); i++) { var entryUsername = leaderboardUsernames[i]; var entryScore = leaderboardScores[i]; var rank = i + 1; // Long pink line background for leaderboard entry var entryBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 0.3 }); entryBg.tint = 0xFF69B4; // Pink color for all entries entryBg.x = 1024; entryBg.y = startY + i * entryHeight; leaderboardContainer.addChild(entryBg); // Rank and username var entryText = new Text2(rank + '. ' + entryUsername, { size: 70, fill: 0x000000 }); entryText.anchor.set(0, 0.5); entryText.x = 1024 - 400; entryText.y = startY + i * entryHeight; leaderboardContainer.addChild(entryText); // Score var scoreText = new Text2(entryScore.toString(), { size: 70, fill: 0x000000 }); scoreText.anchor.set(1, 0.5); scoreText.x = 1024 + 400; scoreText.y = startY + i * entryHeight; leaderboardContainer.addChild(scoreText); } // If no entries, show message if (leaderboardUsernames.length === 0) { var noDataText = new Text2('No scores yet! Play to set records!', { size: 80, fill: 0xFFFFFF }); noDataText.anchor.set(0.5, 0.5); noDataText.x = 1024; noDataText.y = 800; leaderboardContainer.addChild(noDataText); } // Start Game button var startButton = new Container(); var startBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); startBg.tint = 0x4CAF50; startButton.addChild(startBg); var startText = new Text2('Start Game', { size: 80, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startButton.addChild(startText); startButton.x = 1024; startButton.y = 2000; startButton.down = function () { startLevel(1); }; leaderboardContainer.addChild(startButton); // Back button var backButton = new Container(); var backBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 0.6 }); backBg.tint = 0x757575; backButton.addChild(backBg); var backText = new Text2('Back', { size: 60, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backButton.addChild(backText); backButton.x = 1024; backButton.y = 2200; backButton.down = function () { showHomeScreen(); }; leaderboardContainer.addChild(backButton); } function showLoginScreen() { gameState = 'loginScreen'; // Clear existing elements game.removeChildren(); // Clear all UI elements from the screen if (tutorialText && tutorialText.parent) { tutorialText.destroy(); tutorialText = null; } if (targetText && targetText.parent) { targetText.destroy(); targetText = null; } if (scoreText && scoreText.parent) { scoreText.destroy(); scoreText = null; } if (movesText && movesText.parent) { movesText.destroy(); movesText = null; } // Set white background game.setBackgroundColor(0xFFFFFF); // Create container for login elements var loginContainer = new Container(); game.addChild(loginContainer); // Black corner box in top right var blackCorner = LK.getAsset('gridCell', { anchorX: 1, anchorY: 0, scaleX: 3, scaleY: 3 }); blackCorner.tint = 0x000000; blackCorner.x = 2048; blackCorner.y = 0; loginContainer.addChild(blackCorner); // Login text var loginText = new Text2('Log In', { size: 150, fill: 0x000000 }); loginText.anchor.set(0.5, 0.5); loginText.x = 1024; loginText.y = 800; loginContainer.addChild(loginText); // Username input field var usernameField = new Container(); var usernameBg = LK.getAsset('inputField', { width: 720, height: 144, color: 0xFFFFFF, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); usernameField.addChild(usernameBg); // Auto-fill saved username usernameValue = savedUsername; usernameText = new Text2(usernameValue || 'Enter username...', { size: 60, fill: usernameValue ? 0x000000 : 0x666666 }); usernameText.anchor.set(0.5, 0.5); usernameField.addChild(usernameText); usernameField.x = 1024; usernameField.y = 1100; usernameField.down = function () { usernameFocused = true; passwordFocused = false; if (usernameValue === '') { usernameText.setText('|'); usernameText.fill = 0x000000; } showCustomKeyboard(); }; loginContainer.addChild(usernameField); // Password input field var passwordField = new Container(); var passwordBg = LK.getAsset('inputField', { width: 720, height: 144, color: 0xFFFFFF, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); passwordField.addChild(passwordBg); passwordField.x = 1024; passwordField.y = 1300; // Auto-fill saved password passwordValue = savedPassword; passwordText = new Text2(passwordValue ? '*'.repeat(passwordValue.length) : 'Enter password...', { size: 60, fill: passwordValue ? 0x000000 : 0x666666 }); passwordText.anchor.set(0.5, 0.5); passwordField.addChild(passwordText); passwordField.down = function () { usernameFocused = false; passwordFocused = true; if (passwordValue === '') { passwordText.setText('|'); passwordText.fill = 0x000000; } showCustomKeyboard(); }; loginContainer.addChild(passwordField); // Login button var loginButton = new Container(); var loginBg = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); loginBg.tint = 0x4CAF50; // Green tint loginButton.addChild(loginBg); var loginButtonText = new Text2('Log In', { size: 80, fill: 0xFFFFFF }); loginButtonText.anchor.set(0.5, 0.5); loginButton.addChild(loginButtonText); loginButton.x = 1024; loginButton.y = 1600; loginButton.down = function () { // Play button click sound LK.getSound('buttonClick').play(); // Handle login console.log('Login pressed'); // Validate credentials if (usernameValue === savedUsername && passwordValue === savedPassword) { // Correct credentials - restore account data storage.isAccountCreated = true; storage.username = usernameValue; storage.password = passwordValue; // Update global variables isAccountCreated = true; username = usernameValue; isLoggedOut = false; // Show home screen showHomeScreen(); } else { // Incorrect credentials - show error message var errorText = new Text2('Incorrect username or password!', { size: 60, fill: 0xff0000 }); errorText.anchor.set(0.5, 0.5); errorText.x = 1024; errorText.y = 1500; loginContainer.addChild(errorText); // Remove error message after 3 seconds LK.setTimeout(function () { if (errorText && errorText.parent) { errorText.destroy(); } }, 3000); } }; loginContainer.addChild(loginButton); } function addToLeaderboard(score) { // Get existing leaderboard data - stored as separate arrays var leaderboardUsernames = storage.leaderboardUsernames || []; var leaderboardScores = storage.leaderboardScores || []; // Determine player name var playerName = isAccountCreated && username ? username : 'Guest Player'; // Check if this guest player already exists (for account holders) var existingPlayerIndex = -1; if (isAccountCreated && username) { for (var i = 0; i < leaderboardUsernames.length; i++) { if (leaderboardUsernames[i] === username) { existingPlayerIndex = i; break; } } } if (existingPlayerIndex >= 0) { // Update existing player's score if it's higher if (score > leaderboardScores[existingPlayerIndex]) { leaderboardScores[existingPlayerIndex] = score; } } else { // Add new entry to leaderboard leaderboardUsernames.push(playerName); leaderboardScores.push(score); } // Create combined array for sorting var combined = []; for (var i = 0; i < leaderboardUsernames.length; i++) { combined.push({ username: leaderboardUsernames[i], score: leaderboardScores[i], index: i }); } // Sort by score (highest first) combined.sort(function (a, b) { return b.score - a.score; }); // Keep only top 20 entries and rebuild arrays var newUsernames = []; var newScores = []; for (var i = 0; i < Math.min(combined.length, 20); i++) { newUsernames.push(combined[i].username); newScores.push(combined[i].score); } // Save back to storage as separate arrays storage.leaderboardUsernames = newUsernames; storage.leaderboardScores = newScores; }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var FoodItem = Container.expand(function (foodType) {
var self = Container.call(this);
self.foodType = foodType;
self.gridX = -1;
self.gridY = -1;
self.isMatched = false;
self.isAnimating = false;
var foodGraphics = self.attachAsset(foodType, {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, callback) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (callback) callback();
}
});
};
self.animateMatch = function (callback) {
self.isMatched = true;
// First make it bigger and sparkly
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 150,
easing: tween.bounceOut
});
// Then shrink away with stars effect
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeIn,
onFinish: callback
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c1810
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 240;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = 300;
var FOOD_TYPES = ['apple', 'banana', 'orange', 'grape', 'lemon', 'hamburger'];
var grid = [];
var selectedFood = null;
var isProcessingMatches = false;
var movesLeft = 30;
var currentScore = 0;
var targetMatches = 10;
var matchesCleared = 0;
var swipeStartX = 0;
var swipeStartY = 0;
var swipeFood = null;
var isSwipeActive = false;
var SWIPE_THRESHOLD = 50;
var currentLevel = storage.currentLevel || 1;
var maxUnlockedLevel = storage.maxUnlockedLevel || 1;
var totalScore = storage.totalScore || 0;
var isAccountCreated = storage.isAccountCreated || false;
var username = storage.username || '';
var gameState = 'playing'; // 'playing', 'levelComplete', 'levelSelect', 'loginScreen'
var savedPassword = storage.savedPassword || '';
var savedUsername = storage.savedUsername || '';
var isLoggedOut = false;
var levelCompleteShown = false;
var usernameValue = '';
var usernameFocused = false;
var usernameText = null;
var passwordValue = '';
var passwordFocused = false;
var passwordText = null;
var passwordVisible = false;
var isPCUser = false;
// Detect if user is on PC (has physical keyboard)
function detectPCUser() {
// Check for common PC indicators
if (typeof window !== 'undefined' && window.navigator) {
var userAgent = window.navigator.userAgent || '';
var platform = window.navigator.platform || '';
// Check if it's not a mobile device
var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
var isTablet = /iPad|Android(?=.*Tablet)|Tablet/i.test(userAgent);
// If not mobile and not tablet, assume PC
isPCUser = !isMobile && !isTablet;
}
return isPCUser;
}
// Initialize PC detection
detectPCUser();
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
grid[x][y] = null;
}
}
// Create grid background
var gridBackground = new Container();
game.addChild(gridBackground);
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
cell.alpha = 0.3;
gridBackground.addChild(cell);
}
}
// Create UI
var scoreText = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 120;
var movesText = new Text2('Moves: 30', {
size: 80,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(movesText);
movesText.x = 150;
movesText.y = 50;
var tutorialText = new Text2('Lvl' + currentLevel, {
size: 120,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0);
LK.gui.top.addChild(tutorialText);
tutorialText.y = 20;
var targetText = new Text2('Target: ' + targetMatches, {
size: 100,
fill: 0xFFFFFF
});
targetText.anchor.set(0, 0);
LK.gui.top.addChild(targetText);
targetText.x = tutorialText.x + tutorialText.width / 2 + 50;
targetText.y = tutorialText.y;
function getRandomFoodType() {
return FOOD_TYPES[Math.floor(Math.random() * FOOD_TYPES.length)];
}
function createFoodItem(x, y) {
var foodType = getRandomFoodType();
var food = new FoodItem(foodType);
food.setGridPosition(x, y);
grid[x][y] = food;
game.addChild(food);
// Add fun spawn animation with rainbow colors
food.scaleX = 0;
food.scaleY = 0;
food.alpha = 0;
var rainbowColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECA57, 0xFF9FF3, 0x54A0FF];
var randomColor = rainbowColors[Math.floor(Math.random() * rainbowColors.length)];
food.tint = randomColor;
tween(food, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 500,
easing: tween.bounceOut
});
// Reset to normal color after spawn
tween(food, {
tint: 0xFFFFFF
}, {
duration: 800,
easing: tween.easeOut
});
return food;
}
function initializeGrid() {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
createFoodItem(x, y);
}
}
// Remove initial matches
var foundMatches = true;
while (foundMatches) {
var matches = findAllMatches();
if (matches.length > 0) {
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x] && grid[match.x][match.y]) {
grid[match.x][match.y].destroy();
grid[match.x][match.y] = null;
}
}
fillEmptySpaces();
} else {
foundMatches = false;
}
}
}
function isValidPosition(x, y) {
return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;
}
function isAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
function swapFoods(food1, food2) {
if (!food1 || !food2) return false;
var x1 = food1.gridX;
var y1 = food1.gridY;
var x2 = food2.gridX;
var y2 = food2.gridY;
// Swap in grid
grid[x1][y1] = food2;
grid[x2][y2] = food1;
// Update grid positions
food1.setGridPosition(x2, y2);
food2.setGridPosition(x1, y1);
// Animate swap
var targetX1 = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2;
var targetY1 = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2;
var targetX2 = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2;
var targetY2 = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2;
food1.animateToPosition(targetX1, targetY1);
food2.animateToPosition(targetX2, targetY2);
return true;
}
function findMatches(x, y) {
var matches = [];
if (!grid[x] || !grid[x][y]) return matches;
var foodType = grid[x][y].foodType;
// Check horizontal matches
var horizontalMatches = [{
x: x,
y: y
}];
// Check left
for (var i = x - 1; i >= 0; i--) {
if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) {
horizontalMatches.push({
x: i,
y: y
});
} else {
break;
}
}
// Check right
for (var i = x + 1; i < GRID_SIZE; i++) {
if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) {
horizontalMatches.push({
x: i,
y: y
});
} else {
break;
}
}
if (horizontalMatches.length >= 3) {
matches = matches.concat(horizontalMatches);
}
// Check vertical matches
var verticalMatches = [{
x: x,
y: y
}];
// Check up
for (var i = y - 1; i >= 0; i--) {
if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) {
verticalMatches.push({
x: x,
y: i
});
} else {
break;
}
}
// Check down
for (var i = y + 1; i < GRID_SIZE; i++) {
if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) {
verticalMatches.push({
x: x,
y: i
});
} else {
break;
}
}
if (verticalMatches.length >= 3) {
matches = matches.concat(verticalMatches);
}
return matches;
}
function findAllMatches() {
var allMatches = [];
var processed = {};
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x] && grid[x][y] && !processed[x + ',' + y]) {
var matches = findMatches(x, y);
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var key = match.x + ',' + match.y;
if (!processed[key]) {
allMatches.push(match);
processed[key] = true;
}
}
}
}
}
return allMatches;
}
function processMatches() {
if (isProcessingMatches) return;
var matches = findAllMatches();
if (matches.length === 0) return;
isProcessingMatches = true;
LK.getSound('match').play();
var matchCount = matches.length;
currentScore += matchCount * 10;
matchesCleared += matchCount;
targetMatches = Math.max(0, targetMatches - 2);
updateUI();
// Update total score and leaderboard instantly when getting points
totalScore += matchCount * 10;
storage.totalScore = totalScore;
addToLeaderboard(totalScore);
// Play squeaky voice when getting points
LK.getSound('goodJobBooby').play();
// Add celebration effects for bigger matches
if (matchCount >= 4) {
// Big match celebration!
LK.effects.flashScreen(0xFFD700, 500);
// Make score text dance
tween(scoreText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
easing: tween.bounceOut
});
tween(scoreText, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
}
var animationsCompleted = 0;
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x] && grid[match.x][match.y]) {
grid[match.x][match.y].animateMatch(function () {
animationsCompleted++;
if (animationsCompleted === matchCount) {
// Remove matched foods
for (var j = 0; j < matches.length; j++) {
var m = matches[j];
if (grid[m.x] && grid[m.x][m.y]) {
grid[m.x][m.y].destroy();
grid[m.x][m.y] = null;
}
}
fillEmptySpaces();
LK.setTimeout(function () {
isProcessingMatches = false;
processMatches(); // Check for cascade matches
}, 300);
}
});
}
}
if (matchCount === 0) {
isProcessingMatches = false;
}
}
function fillEmptySpaces() {
// Drop existing foods
for (var x = 0; x < GRID_SIZE; x++) {
var writeIndex = GRID_SIZE - 1;
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (grid[x][y] !== null) {
if (y !== writeIndex) {
grid[x][writeIndex] = grid[x][y];
grid[x][y] = null;
grid[x][writeIndex].setGridPosition(x, writeIndex);
var targetY = GRID_START_Y + writeIndex * CELL_SIZE + CELL_SIZE / 2;
grid[x][writeIndex].animateToPosition(grid[x][writeIndex].x, targetY);
}
writeIndex--;
}
}
// Create new foods for empty spaces at top
for (var y = 0; y <= writeIndex; y++) {
var food = new FoodItem(getRandomFoodType());
food.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
food.y = GRID_START_Y - (writeIndex - y + 1) * CELL_SIZE + CELL_SIZE / 2;
food.gridX = x;
food.gridY = y;
grid[x][y] = food;
game.addChild(food);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
food.animateToPosition(food.x, targetY);
}
}
}
function updateUI() {
if (scoreText) {
scoreText.setText('Score: ' + currentScore);
}
if (movesText) {
movesText.setText('Moves: ' + movesLeft);
}
if (targetText) {
targetText.setText('Target: ' + targetMatches);
}
}
function checkGameEnd() {
if (targetMatches <= 0) {
if (currentLevel === 1 && !levelCompleteShown) {
showLevelComplete();
} else {
completeLevel();
}
} else if (movesLeft <= 0) {
LK.showGameOver();
}
}
function showLevelComplete() {
levelCompleteShown = true;
gameState = 'levelComplete';
// Play celebration music
LK.playMusic('celebrationMusic', {
loop: false
});
// Play level complete sound
LK.getSound('levelComplete').play();
// Add celebration effects
LK.effects.flashScreen(0xFFD700, 1000);
// Make all UI elements dance
tween(scoreText, {
scaleX: 1.5,
scaleY: 1.5,
rotation: 0.2
}, {
duration: 500,
easing: tween.bounceOut
});
tween(tutorialText, {
scaleX: 1.3,
scaleY: 1.3,
rotation: -0.1
}, {
duration: 600,
easing: tween.bounceOut
});
tween(targetText, {
scaleX: 1.2,
scaleY: 1.2,
rotation: 0.15
}, {
duration: 700,
easing: tween.bounceOut
});
LK.setTimeout(function () {
showWhiteScreen();
}, 3000);
}
function showWhiteScreen() {
gameState = 'whiteScreen';
// Clear all game elements
game.removeChildren();
// Clear tutorial UI elements
if (tutorialText && tutorialText.parent) {
tutorialText.destroy();
tutorialText = null;
}
if (targetText && targetText.parent) {
targetText.destroy();
targetText = null;
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
scoreText = null;
}
if (movesText && movesText.parent) {
movesText.destroy();
movesText = null;
}
// Set white background
game.setBackgroundColor(0xFFFFFF);
// Show white screen for 2 seconds then show home screen
LK.setTimeout(function () {
showHomeScreen();
}, 2000);
}
function showHomeScreen() {
gameState = 'homeScreen';
// Clear all game elements first to remove any login screen elements
game.removeChildren();
// Set cheerful rainbow gradient background
game.setBackgroundColor(0x87CEEB);
// Start playing happy background music
LK.playMusic('happyBgMusic', {
loop: true
});
// Clear all UI elements from the screen
if (tutorialText && tutorialText.parent) {
tutorialText.destroy();
tutorialText = null;
}
if (targetText && targetText.parent) {
targetText.destroy();
targetText = null;
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
scoreText = null;
}
if (movesText && movesText.parent) {
movesText.destroy();
movesText = null;
}
// Create buttons container
var buttonsContainer = new Container();
game.addChild(buttonsContainer);
// Create Account button
var createAccountButton = new Container();
var createAccountBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
createAccountBg.tint = 0x4CAF50; // Green tint
createAccountButton.addChild(createAccountBg);
var createAccountText = new Text2('Create Account', {
size: 80,
fill: 0xFFFFFF
});
createAccountText.anchor.set(0.5, 0.5);
createAccountButton.addChild(createAccountText);
createAccountButton.x = 1024;
createAccountButton.y = 1200;
createAccountButton.down = function () {
// Handle create account action
console.log('Create Account pressed');
// Play button click sound
LK.getSound('buttonClick').play();
// Add fun button press animation
tween(createAccountButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(createAccountButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
showCreateAccountScreen();
};
buttonsContainer.addChild(createAccountButton);
// Play as Guest button
var playAsGuestButton = new Container();
var playAsGuestBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
playAsGuestBg.tint = 0x2196F3; // Blue tint
playAsGuestButton.addChild(playAsGuestBg);
var playAsGuestText = new Text2('Play', {
size: 80,
fill: 0xFFFFFF
});
playAsGuestText.anchor.set(0.5, 0.5);
playAsGuestButton.addChild(playAsGuestText);
playAsGuestButton.x = 1024;
playAsGuestButton.y = 1500;
playAsGuestButton.down = function () {
// Handle play as guest action
console.log('Play as Guest pressed');
// Play button click sound
LK.getSound('buttonClick').play();
// Add fun button press animation
tween(playAsGuestButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(playAsGuestButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
// Start the game
startLevel(1);
};
buttonsContainer.addChild(playAsGuestButton);
// Add floating animations to make buttons more lively
// Add profile picture and user info in top right corner if account is created
if (isAccountCreated) {
var profileContainer = new Container();
LK.gui.topRight.addChild(profileContainer);
// Profile picture background (circular)
var profilePicBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
profilePicBg.tint = 0x4CAF50; // Green tint for profile pic
profileContainer.addChild(profilePicBg);
// Profile picture initial (first letter of username)
var profileInitial = new Text2(username.charAt(0).toUpperCase(), {
size: 60,
fill: 0xFFFFFF
});
profileInitial.anchor.set(0.5, 0.5);
profileContainer.addChild(profileInitial);
// Username text below profile pic
var usernameDisplay = new Text2('User: ' + username, {
size: 35,
fill: 0xFFFFFF
});
usernameDisplay.anchor.set(0.5, 0);
usernameDisplay.y = 60;
profileContainer.addChild(usernameDisplay);
// Password text below username
var passwordDisplay = new Text2('Pass: ' + (storage.password || savedPassword || ''), {
size: 35,
fill: 0xFFFFFF
});
passwordDisplay.anchor.set(0.5, 0);
passwordDisplay.y = 100;
profileContainer.addChild(passwordDisplay);
// Position profile container in top right
profileContainer.x = -120;
profileContainer.y = 80;
// Add Log Out button in center area with other buttons
var logOutButton = new Container();
var logOutBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
logOutBg.tint = 0xF44336; // Red tint
logOutButton.addChild(logOutBg);
var logOutText = new Text2('Log Out', {
size: 80,
fill: 0xFFFFFF
});
logOutText.anchor.set(0.5, 0.5);
logOutButton.addChild(logOutText);
logOutButton.x = 1024;
logOutButton.y = 1800;
logOutButton.down = function () {
// Add fun button press animation
tween(logOutButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(logOutButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
// Save credentials before logging out
storage.savedUsername = username;
storage.savedPassword = storage.password || '';
// Log out the user
isAccountCreated = false;
username = '';
storage.isAccountCreated = false;
storage.username = '';
isLoggedOut = true;
// Show login screen instead of home screen
showLoginScreen();
};
buttonsContainer.addChild(logOutButton);
// Add Leaderboard button if account is created
var leaderboardButton = new Container();
var leaderboardBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
leaderboardBg.tint = 0xFF9800; // Orange tint
leaderboardButton.addChild(leaderboardBg);
var leaderboardText = new Text2('Leaderboard', {
size: 80,
fill: 0xFFFFFF
});
leaderboardText.anchor.set(0.5, 0.5);
leaderboardButton.addChild(leaderboardText);
leaderboardButton.x = 1024;
leaderboardButton.y = 900;
leaderboardButton.down = function () {
// Play button click sound
LK.getSound('buttonClick').play();
// Add fun button press animation
tween(leaderboardButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(leaderboardButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
showLeaderboardScreen();
};
buttonsContainer.addChild(leaderboardButton);
// Adjust other button positions
createAccountButton.y = 1200;
playAsGuestButton.y = 1400;
logOutButton.y = 1600;
}
tween(createAccountButton, {
y: createAccountButton.y - 10
}, {
duration: 2000,
easing: tween.easeInOut
});
tween(createAccountButton, {
y: createAccountButton.y + 10
}, {
duration: 2000,
easing: tween.easeInOut
});
tween(playAsGuestButton, {
y: playAsGuestButton.y + 10
}, {
duration: 2500,
easing: tween.easeInOut
});
tween(playAsGuestButton, {
y: playAsGuestButton.y - 10
}, {
duration: 2500,
easing: tween.easeInOut
});
}
function showCreateAccountScreen() {
gameState = 'createAccount';
// Clear existing elements
game.removeChildren();
// Keep green background
game.setBackgroundColor(0x00FF00);
// Create container for account creation elements
var accountContainer = new Container();
game.addChild(accountContainer);
// Title
var titleText = new Text2('Create Account', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
accountContainer.addChild(titleText);
// Username input field
var usernameField = new Container();
var usernameBg = LK.getAsset('inputField', {
width: 720,
height: 144,
color: 0xFFFFFF,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
usernameField.addChild(usernameBg);
usernameText = new Text2('Enter username...', {
size: 60,
fill: 0x666666
});
usernameText.anchor.set(0.5, 0.5);
usernameField.addChild(usernameText);
usernameField.x = 1024;
usernameField.y = 800;
usernameField.down = function () {
usernameFocused = true;
passwordFocused = false;
if (usernameValue === '') {
usernameText.setText('|');
usernameText.fill = 0x000000;
}
showCustomKeyboard();
};
accountContainer.addChild(usernameField);
// Password input field
var passwordField = new Container();
var passwordBg = LK.getAsset('inputField', {
width: 720,
height: 144,
color: 0xFFFFFF,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
passwordField.addChild(passwordBg);
passwordField.x = 1024;
passwordField.y = 1100;
passwordText = new Text2('Enter password...', {
size: 60,
fill: 0x666666
});
passwordText.anchor.set(0.5, 0.5);
passwordField.addChild(passwordText);
// Password label beside the button
var passwordLabel = new Text2('Password:', {
size: 60,
fill: 0x000000
});
passwordLabel.anchor.set(1, 0.5);
passwordLabel.x = 1024 - 360 - 20; // Position to the left of the password field
passwordLabel.y = 1100;
accountContainer.addChild(passwordLabel);
passwordField.down = function () {
usernameFocused = false;
passwordFocused = true;
if (passwordValue === '') {
passwordText.setText('|');
passwordText.fill = 0x000000;
}
showCustomKeyboard();
};
accountContainer.addChild(passwordField);
// Eye button to toggle password visibility
var eyeButton = new Container();
var eyeBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
eyeBg.tint = 0xCCCCCC;
eyeButton.addChild(eyeBg);
var eyeText = new Text2('š', {
size: 50,
fill: 0x000000
});
eyeText.anchor.set(0.5, 0.5);
eyeButton.addChild(eyeText);
eyeButton.x = 1024 + 360 + 80; // Position to the right of the password field
eyeButton.y = 1100;
var passwordVisible = false;
eyeButton.down = function () {
passwordVisible = !passwordVisible;
if (passwordVisible) {
// Show actual password
eyeText.setText('š');
if (passwordValue !== '') {
passwordText.setText(passwordValue);
}
} else {
// Hide password with asterisks
eyeText.setText('š');
if (passwordValue !== '') {
passwordText.setText('*'.repeat(passwordValue.length));
}
}
};
accountContainer.addChild(eyeButton);
// Create Account button
var createButton = new Container();
var createBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
createBg.tint = 0x4CAF50; // Green tint
createButton.addChild(createBg);
var createText = new Text2('Create', {
size: 80,
fill: 0xFFFFFF
});
createText.anchor.set(0.5, 0.5);
createButton.addChild(createText);
createButton.x = 1024;
createButton.y = 1400;
createButton.down = function () {
// Play button click sound
LK.getSound('buttonClick').play();
// Handle account creation and save progress
console.log('Account created');
// Save account data to storage
storage.isAccountCreated = true;
storage.username = usernameValue;
storage.password = passwordValue;
storage.totalScore = totalScore;
storage.currentLevel = currentLevel;
storage.maxUnlockedLevel = maxUnlockedLevel;
// Update global variables
isAccountCreated = true;
username = usernameValue;
// Show leaderboard button and start game
showLeaderboardScreen();
};
accountContainer.addChild(createButton);
// Back button
var backButton = new Container();
var backBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backBg.tint = 0x757575; // Gray tint
backButton.addChild(backBg);
var backText = new Text2('Back', {
size: 60,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backButton.addChild(backText);
backButton.x = 1024;
backButton.y = 1600;
backButton.down = function () {
showHomeScreen();
};
accountContainer.addChild(backButton);
}
var customKeyboard = null;
var keyboardKeys = [['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'], ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], ['Z', 'X', 'C', 'V', 'B', 'N', 'M']];
function showCustomKeyboard() {
// Don't show custom keyboard for PC users
if (isPCUser) {
setupPCKeyboardListeners();
return;
}
if (customKeyboard) {
hideCustomKeyboard();
}
customKeyboard = new Container();
game.addChild(customKeyboard);
// Keyboard background
var keyboardBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 4
});
keyboardBg.tint = 0x333333;
keyboardBg.x = 1024;
keyboardBg.y = 2200;
customKeyboard.addChild(keyboardBg);
// Create keyboard keys
var startY = 1900;
var keySize = 180;
var keySpacing = 200;
for (var row = 0; row < keyboardKeys.length; row++) {
var rowKeys = keyboardKeys[row];
var rowWidth = rowKeys.length * keySpacing;
var startX = 1024 - rowWidth / 2 + keySpacing / 2;
for (var col = 0; col < rowKeys.length; col++) {
var keyChar = rowKeys[col];
var keyButton = createKeyButton(keyChar, keySize);
keyButton.x = startX + col * keySpacing;
keyButton.y = startY + row * 220;
customKeyboard.addChild(keyButton);
}
}
// Add space bar
var spaceButton = createKeyButton(' ', keySize * 4);
spaceButton.x = 1024;
spaceButton.y = startY + keyboardKeys.length * 220;
customKeyboard.addChild(spaceButton);
// Add backspace button
var backspaceButton = createKeyButton('ā«', keySize * 1.5);
backspaceButton.x = 1024 + 400;
backspaceButton.y = startY + keyboardKeys.length * 220;
customKeyboard.addChild(backspaceButton);
// Add done button
var doneButton = createKeyButton('Done', keySize * 1.5);
doneButton.x = 1024 - 400;
doneButton.y = startY + keyboardKeys.length * 220;
customKeyboard.addChild(doneButton);
}
function setupPCKeyboardListeners() {
if (typeof window === 'undefined' || !window.addEventListener) return;
// Remove existing listeners to avoid duplicates
removePCKeyboardListeners();
window.addEventListener('keydown', handlePCKeyDown);
}
function removePCKeyboardListeners() {
if (typeof window === 'undefined' || !window.removeEventListener) return;
window.removeEventListener('keydown', handlePCKeyDown);
}
function handlePCKeyDown(event) {
if (!usernameFocused && !passwordFocused) return;
event.preventDefault();
var key = event.key;
// Handle special keys
if (key === 'Enter' || key === 'Tab') {
// Switch between fields or finish input
if (usernameFocused) {
usernameFocused = false;
passwordFocused = true;
if (usernameValue === '') {
usernameText.setText('Enter username...');
usernameText.fill = 0x666666;
} else {
usernameText.setText(usernameValue);
}
if (passwordValue === '') {
passwordText.setText('|');
passwordText.fill = 0x000000;
}
} else if (passwordFocused) {
passwordFocused = false;
if (passwordValue === '') {
passwordText.setText('Enter password...');
passwordText.fill = 0x666666;
} else {
if (passwordVisible) {
passwordText.setText(passwordValue);
} else {
passwordText.setText('*'.repeat(passwordValue.length));
}
}
}
return;
}
if (key === 'Backspace') {
if (usernameFocused && usernameValue.length > 0) {
usernameValue = usernameValue.slice(0, -1);
if (usernameValue === '') {
usernameText.setText('|');
} else {
usernameText.setText(usernameValue + '|');
}
} else if (passwordFocused && passwordValue.length > 0) {
passwordValue = passwordValue.slice(0, -1);
if (passwordValue === '') {
passwordText.setText('|');
} else {
if (passwordVisible) {
passwordText.setText(passwordValue + '|');
} else {
passwordText.setText('*'.repeat(passwordValue.length) + '|');
}
}
}
return;
}
// Handle regular character input
if (key.length === 1) {
if (usernameFocused && usernameValue.length < 20) {
// Limit username length
usernameValue += key;
usernameText.setText(usernameValue + '|');
} else if (passwordFocused && passwordValue.length < 20) {
// Limit password length
if (passwordValue === '') {
// Clear placeholder text when starting to type
passwordText.fill = 0x000000;
}
passwordValue += key;
if (passwordVisible) {
passwordText.setText(passwordValue + '|');
} else {
passwordText.setText('*'.repeat(passwordValue.length) + '|');
}
}
}
}
function createKeyButton(keyChar, width) {
var keyButton = new Container();
var keyBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: width / 240,
scaleY: 0.5
});
keyBg.tint = 0xCCCCCC;
keyButton.addChild(keyBg);
var keyText = new Text2(keyChar === ' ' ? 'Space' : keyChar, {
size: keyChar === 'Done' ? 90 : 120,
fill: 0x000000
});
keyText.anchor.set(0.5, 0.5);
keyButton.addChild(keyText);
keyButton.down = function () {
// Add fun key press animation
tween(keyButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 50,
easing: tween.easeOut
});
tween(keyButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.bounceOut
});
if (keyChar === 'Done') {
hideCustomKeyboard();
if (usernameFocused) {
usernameFocused = false;
if (usernameValue === '') {
usernameText.setText('Enter username...');
usernameText.fill = 0x666666;
} else {
usernameText.setText(usernameValue);
}
} else if (passwordFocused) {
passwordFocused = false;
if (passwordValue === '') {
passwordText.setText('Enter password...');
passwordText.fill = 0x666666;
} else {
if (passwordVisible) {
passwordText.setText(passwordValue);
} else {
passwordText.setText('*'.repeat(passwordValue.length));
}
}
}
} else if (keyChar === 'ā«') {
if (usernameFocused && usernameValue.length > 0) {
usernameValue = usernameValue.slice(0, -1);
if (usernameValue === '') {
usernameText.setText('|');
} else {
usernameText.setText(usernameValue + '|');
}
} else if (passwordFocused && passwordValue.length > 0) {
passwordValue = passwordValue.slice(0, -1);
if (passwordValue === '') {
passwordText.setText('|');
} else {
if (passwordVisible) {
passwordText.setText(passwordValue + '|');
} else {
passwordText.setText('*'.repeat(passwordValue.length) + '|');
}
}
}
} else {
if (usernameFocused && usernameValue.length < 20) {
// Limit username length
usernameValue += keyChar;
usernameText.setText(usernameValue + '|');
} else if (passwordFocused && passwordValue.length < 20) {
// Limit password length
if (passwordValue === '') {
// Clear placeholder text when starting to type
passwordText.fill = 0x000000;
}
passwordValue += keyChar;
if (passwordVisible) {
passwordText.setText(passwordValue + '|');
} else {
passwordText.setText('*'.repeat(passwordValue.length) + '|');
}
}
}
// Visual feedback with fun colors
var funColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECA57];
var randomColor = funColors[Math.floor(Math.random() * funColors.length)];
keyBg.tint = randomColor;
LK.setTimeout(function () {
keyBg.tint = 0xCCCCCC;
}, 200);
};
return keyButton;
}
function hideCustomKeyboard() {
if (customKeyboard) {
customKeyboard.destroy();
customKeyboard = null;
}
// Clean up PC keyboard listeners
if (isPCUser) {
removePCKeyboardListeners();
}
}
function completeLevel() {
// Update progress
if (currentLevel >= maxUnlockedLevel) {
maxUnlockedLevel = currentLevel + 1;
storage.maxUnlockedLevel = maxUnlockedLevel;
}
storage.currentLevel = currentLevel;
// Add current score to total score
totalScore += currentScore;
storage.totalScore = totalScore;
// Upload highest total score to leaderboard
addToLeaderboard(totalScore);
// Show home screen instead of level select
showHomeScreen();
}
function startLevel(levelNum) {
currentLevel = levelNum;
gameState = 'playing';
levelCompleteShown = false;
// Continue playing background music during gameplay
LK.playMusic('happyBgMusic', {
loop: true
});
// Adjust difficulty based on level
targetMatches = Math.min(10 + (levelNum - 1) * 5, 100);
movesLeft = Math.max(30 - Math.floor((levelNum - 1) / 3), 15);
currentScore = 0;
matchesCleared = 0;
// Clear existing UI
game.removeChildren();
// Recreate game
setupGame();
}
function setupGame() {
// Recreate grid background
gridBackground = new Container();
game.addChild(gridBackground);
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
cell.alpha = 0.3;
gridBackground.addChild(cell);
}
}
// Clear existing UI elements
if (tutorialText && tutorialText.parent) {
tutorialText.destroy();
}
if (targetText && targetText.parent) {
targetText.destroy();
}
// Recreate UI elements if they don't exist
if (!scoreText) {
scoreText = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 120;
}
if (!movesText) {
movesText = new Text2('Moves: ' + movesLeft, {
size: 80,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(movesText);
movesText.x = 150;
movesText.y = 50;
}
// Update UI
scoreText.setText('Score: 0');
movesText.setText('Moves: ' + movesLeft);
tutorialText = new Text2('Lvl' + currentLevel, {
size: 120,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0);
LK.gui.top.addChild(tutorialText);
tutorialText.y = 20;
targetText = new Text2('Target: ' + targetMatches, {
size: 100,
fill: 0xFFFFFF
});
targetText.anchor.set(0, 0);
LK.gui.top.addChild(targetText);
targetText.x = tutorialText.x + tutorialText.width / 2 + 50;
targetText.y = tutorialText.y;
// Initialize grid
initializeGrid();
updateUI();
}
function getFoodAtPosition(x, y) {
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
if (isValidPosition(gridX, gridY) && grid[gridX] && grid[gridX][gridY]) {
return grid[gridX][gridY];
}
return null;
}
game.down = function (x, y, obj) {
if (isProcessingMatches) return;
var food = getFoodAtPosition(x, y);
if (food && !food.isAnimating) {
swipeStartX = x;
swipeStartY = y;
swipeFood = food;
isSwipeActive = true;
swipeFood.alpha = 0.7;
// Add fun wobble animation when selected
tween(swipeFood, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.bounceOut
});
}
};
game.up = function (x, y, obj) {
if (!isSwipeActive || !swipeFood) return;
var deltaX = x - swipeStartX;
var deltaY = y - swipeStartY;
var swipeDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (swipeDistance < SWIPE_THRESHOLD) {
// Not a swipe, reset
swipeFood.alpha = 1;
isSwipeActive = false;
swipeFood = null;
return;
}
// Determine swipe direction
var targetGridX = swipeFood.gridX;
var targetGridY = swipeFood.gridY;
var absDeltaX = Math.abs(deltaX);
var absDeltaY = Math.abs(deltaY);
if (absDeltaX > absDeltaY) {
// Horizontal swipe
if (deltaX > 0) {
targetGridX++; // Swipe right
} else {
targetGridX--; // Swipe left
}
} else {
// Vertical swipe
if (deltaY > 0) {
targetGridY++; // Swipe down
} else {
targetGridY--; // Swipe up
}
}
// Check if target position is valid
if (isValidPosition(targetGridX, targetGridY) && grid[targetGridX] && grid[targetGridX][targetGridY]) {
var targetFood = grid[targetGridX][targetGridY];
if (!targetFood.isAnimating) {
LK.getSound('swap').play();
// Store original positions BEFORE any swap
var tempFood1 = swipeFood;
var tempFood2 = targetFood;
var originalX1 = tempFood1.gridX;
var originalY1 = tempFood1.gridY;
var originalX2 = tempFood2.gridX;
var originalY2 = tempFood2.gridY;
// Try swap
swapFoods(tempFood1, tempFood2);
LK.setTimeout(function () {
var matches = findAllMatches();
if (matches.length === 0) {
// Invalid move, animate swap back to original positions
var targetX1 = GRID_START_X + originalX1 * CELL_SIZE + CELL_SIZE / 2;
var targetY1 = GRID_START_Y + originalY1 * CELL_SIZE + CELL_SIZE / 2;
var targetX2 = GRID_START_X + originalX2 * CELL_SIZE + CELL_SIZE / 2;
var targetY2 = GRID_START_Y + originalY2 * CELL_SIZE + CELL_SIZE / 2;
tempFood1.animateToPosition(targetX1, targetY1);
tempFood2.animateToPosition(targetX2, targetY2);
// Restore original grid positions
grid[originalX1][originalY1] = tempFood1;
grid[originalX2][originalY2] = tempFood2;
tempFood1.gridX = originalX1;
tempFood1.gridY = originalY1;
tempFood2.gridX = originalX2;
tempFood2.gridY = originalY2;
} else {
// Valid move
movesLeft--;
updateUI();
processMatches();
checkGameEnd();
}
}, 350);
}
}
// Reset swipe state with fun bounce back animation
tween(swipeFood, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
isSwipeActive = false;
swipeFood = null;
};
// Start background music when game loads
LK.playMusic('happyBgMusic', {
loop: true
});
// Initialize the game - start with home screen
showHomeScreen();
function showLeaderboardScreen() {
gameState = 'leaderboard';
// Clear existing elements
game.removeChildren();
// Set background
game.setBackgroundColor(0x4CAF50);
// Create container for leaderboard elements
var leaderboardContainer = new Container();
game.addChild(leaderboardContainer);
// Title
var titleText = new Text2('Leaderboard', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
leaderboardContainer.addChild(titleText);
// Get leaderboard data from storage - stored as separate arrays
var leaderboardUsernames = storage.leaderboardUsernames || [];
var leaderboardScores = storage.leaderboardScores || [];
// Display leaderboard entries
var startY = 500;
var entryHeight = 120;
for (var i = 0; i < Math.min(leaderboardUsernames.length, 10); i++) {
var entryUsername = leaderboardUsernames[i];
var entryScore = leaderboardScores[i];
var rank = i + 1;
// Long pink line background for leaderboard entry
var entryBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 0.3
});
entryBg.tint = 0xFF69B4; // Pink color for all entries
entryBg.x = 1024;
entryBg.y = startY + i * entryHeight;
leaderboardContainer.addChild(entryBg);
// Rank and username
var entryText = new Text2(rank + '. ' + entryUsername, {
size: 70,
fill: 0x000000
});
entryText.anchor.set(0, 0.5);
entryText.x = 1024 - 400;
entryText.y = startY + i * entryHeight;
leaderboardContainer.addChild(entryText);
// Score
var scoreText = new Text2(entryScore.toString(), {
size: 70,
fill: 0x000000
});
scoreText.anchor.set(1, 0.5);
scoreText.x = 1024 + 400;
scoreText.y = startY + i * entryHeight;
leaderboardContainer.addChild(scoreText);
}
// If no entries, show message
if (leaderboardUsernames.length === 0) {
var noDataText = new Text2('No scores yet! Play to set records!', {
size: 80,
fill: 0xFFFFFF
});
noDataText.anchor.set(0.5, 0.5);
noDataText.x = 1024;
noDataText.y = 800;
leaderboardContainer.addChild(noDataText);
}
// Start Game button
var startButton = new Container();
var startBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
startBg.tint = 0x4CAF50;
startButton.addChild(startBg);
var startText = new Text2('Start Game', {
size: 80,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startButton.addChild(startText);
startButton.x = 1024;
startButton.y = 2000;
startButton.down = function () {
startLevel(1);
};
leaderboardContainer.addChild(startButton);
// Back button
var backButton = new Container();
var backBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backBg.tint = 0x757575;
backButton.addChild(backBg);
var backText = new Text2('Back', {
size: 60,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backButton.addChild(backText);
backButton.x = 1024;
backButton.y = 2200;
backButton.down = function () {
showHomeScreen();
};
leaderboardContainer.addChild(backButton);
}
function showLoginScreen() {
gameState = 'loginScreen';
// Clear existing elements
game.removeChildren();
// Clear all UI elements from the screen
if (tutorialText && tutorialText.parent) {
tutorialText.destroy();
tutorialText = null;
}
if (targetText && targetText.parent) {
targetText.destroy();
targetText = null;
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
scoreText = null;
}
if (movesText && movesText.parent) {
movesText.destroy();
movesText = null;
}
// Set white background
game.setBackgroundColor(0xFFFFFF);
// Create container for login elements
var loginContainer = new Container();
game.addChild(loginContainer);
// Black corner box in top right
var blackCorner = LK.getAsset('gridCell', {
anchorX: 1,
anchorY: 0,
scaleX: 3,
scaleY: 3
});
blackCorner.tint = 0x000000;
blackCorner.x = 2048;
blackCorner.y = 0;
loginContainer.addChild(blackCorner);
// Login text
var loginText = new Text2('Log In', {
size: 150,
fill: 0x000000
});
loginText.anchor.set(0.5, 0.5);
loginText.x = 1024;
loginText.y = 800;
loginContainer.addChild(loginText);
// Username input field
var usernameField = new Container();
var usernameBg = LK.getAsset('inputField', {
width: 720,
height: 144,
color: 0xFFFFFF,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
usernameField.addChild(usernameBg);
// Auto-fill saved username
usernameValue = savedUsername;
usernameText = new Text2(usernameValue || 'Enter username...', {
size: 60,
fill: usernameValue ? 0x000000 : 0x666666
});
usernameText.anchor.set(0.5, 0.5);
usernameField.addChild(usernameText);
usernameField.x = 1024;
usernameField.y = 1100;
usernameField.down = function () {
usernameFocused = true;
passwordFocused = false;
if (usernameValue === '') {
usernameText.setText('|');
usernameText.fill = 0x000000;
}
showCustomKeyboard();
};
loginContainer.addChild(usernameField);
// Password input field
var passwordField = new Container();
var passwordBg = LK.getAsset('inputField', {
width: 720,
height: 144,
color: 0xFFFFFF,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
passwordField.addChild(passwordBg);
passwordField.x = 1024;
passwordField.y = 1300;
// Auto-fill saved password
passwordValue = savedPassword;
passwordText = new Text2(passwordValue ? '*'.repeat(passwordValue.length) : 'Enter password...', {
size: 60,
fill: passwordValue ? 0x000000 : 0x666666
});
passwordText.anchor.set(0.5, 0.5);
passwordField.addChild(passwordText);
passwordField.down = function () {
usernameFocused = false;
passwordFocused = true;
if (passwordValue === '') {
passwordText.setText('|');
passwordText.fill = 0x000000;
}
showCustomKeyboard();
};
loginContainer.addChild(passwordField);
// Login button
var loginButton = new Container();
var loginBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
loginBg.tint = 0x4CAF50; // Green tint
loginButton.addChild(loginBg);
var loginButtonText = new Text2('Log In', {
size: 80,
fill: 0xFFFFFF
});
loginButtonText.anchor.set(0.5, 0.5);
loginButton.addChild(loginButtonText);
loginButton.x = 1024;
loginButton.y = 1600;
loginButton.down = function () {
// Play button click sound
LK.getSound('buttonClick').play();
// Handle login
console.log('Login pressed');
// Validate credentials
if (usernameValue === savedUsername && passwordValue === savedPassword) {
// Correct credentials - restore account data
storage.isAccountCreated = true;
storage.username = usernameValue;
storage.password = passwordValue;
// Update global variables
isAccountCreated = true;
username = usernameValue;
isLoggedOut = false;
// Show home screen
showHomeScreen();
} else {
// Incorrect credentials - show error message
var errorText = new Text2('Incorrect username or password!', {
size: 60,
fill: 0xff0000
});
errorText.anchor.set(0.5, 0.5);
errorText.x = 1024;
errorText.y = 1500;
loginContainer.addChild(errorText);
// Remove error message after 3 seconds
LK.setTimeout(function () {
if (errorText && errorText.parent) {
errorText.destroy();
}
}, 3000);
}
};
loginContainer.addChild(loginButton);
}
function addToLeaderboard(score) {
// Get existing leaderboard data - stored as separate arrays
var leaderboardUsernames = storage.leaderboardUsernames || [];
var leaderboardScores = storage.leaderboardScores || [];
// Determine player name
var playerName = isAccountCreated && username ? username : 'Guest Player';
// Check if this guest player already exists (for account holders)
var existingPlayerIndex = -1;
if (isAccountCreated && username) {
for (var i = 0; i < leaderboardUsernames.length; i++) {
if (leaderboardUsernames[i] === username) {
existingPlayerIndex = i;
break;
}
}
}
if (existingPlayerIndex >= 0) {
// Update existing player's score if it's higher
if (score > leaderboardScores[existingPlayerIndex]) {
leaderboardScores[existingPlayerIndex] = score;
}
} else {
// Add new entry to leaderboard
leaderboardUsernames.push(playerName);
leaderboardScores.push(score);
}
// Create combined array for sorting
var combined = [];
for (var i = 0; i < leaderboardUsernames.length; i++) {
combined.push({
username: leaderboardUsernames[i],
score: leaderboardScores[i],
index: i
});
}
// Sort by score (highest first)
combined.sort(function (a, b) {
return b.score - a.score;
});
// Keep only top 20 entries and rebuild arrays
var newUsernames = [];
var newScores = [];
for (var i = 0; i < Math.min(combined.length, 20); i++) {
newUsernames.push(combined[i].username);
newScores.push(combined[i].score);
}
// Save back to storage as separate arrays
storage.leaderboardUsernames = newUsernames;
storage.leaderboardScores = newScores;
}