User prompt
Please fix the bug: 'Timeout.tick error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = leaderboardData;' Line Number: 1812 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
When somebody gets a score in total there name gets instantly uploaded on the leaderboard ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Now upload the highest players score on the leaderboard in total ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
When I'm on the log in screen and I log in i still see the screen from the log in on the home screen behind all the buttons on the home screen fix that
User prompt
Make it bigger
User prompt
In the log in screen the top right corner should be black
User prompt
When your on the screen where you log in you must get your username and password right ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Locate the log out button somewhere else on the home screen
User prompt
Right next to your profile picture will show ur username and password ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of null (reading 'setText')' in or related to this line: 'scoreText.setText('Score: ' + currentScore);' Line Number: 476
User prompt
Once I log out get out of the home screen then the whole screen will be white it will say a text that says log in and if you try to log back in it will automatically fill in ur saved password and username ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
When my target gets near 0 it teleports to home screen make sure only when the target hits 0 it teleports to home screen
User prompt
Add Hamburgers to the game as brown circles
User prompt
Add a squeaky voice that says good job booby when you get points
User prompt
Change the play as guest button to play
User prompt
Lower even more
User prompt
Make the logo out button lower
User prompt
I made music now add it
User prompt
Add some fun kid friendly music
User prompt
also make a log out button under your profile
User prompt
once u create your account your profile picture will be in the top right corner in the home screen with your username and password along it
User prompt
when people play the game and they get a score they get on the leaderboard with some of the highest scores in total of ever playing ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
when you click on create account all of your progress will save and there will be a leaderboards button of people who have got the highest score in total after u finish the level ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
now add more fun features and make the game more kid friendly ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
if your on pc people should not see the custom keyboard make the pc keyboard compatible with the password and username button
/**** * 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; tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, 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']; 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 gameState = 'playing'; // 'playing', 'levelComplete', 'levelSelect' 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); 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(); 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() { scoreText.setText('Score: ' + currentScore); movesText.setText('Moves: ' + movesLeft); targetText.setText('Target: ' + targetMatches); } function checkGameEnd() { if (matchesCleared >= targetMatches) { if (currentLevel === 1 && !levelCompleteShown) { showLevelComplete(); } else { completeLevel(); } } else if (movesLeft <= 0) { LK.showGameOver(); } } function showLevelComplete() { levelCompleteShown = true; gameState = 'levelComplete'; 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'; // Set green background for home screen game.setBackgroundColor(0x00FF00); // 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'); 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 as Guest', { 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'); // Start the game startLevel(1); }; buttonsContainer.addChild(playAsGuestButton); } 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 () { // Handle account creation (for now just start the game) console.log('Account created'); startLevel(1); }; 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 () { 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 keyBg.tint = 0xAAAAAA; LK.setTimeout(function () { keyBg.tint = 0xCCCCCC; }, 100); }; 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; // Show home screen instead of level select showHomeScreen(); } function startLevel(levelNum) { currentLevel = levelNum; gameState = 'playing'; levelCompleteShown = false; // 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; } }; 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 swipeFood.alpha = 1; isSwipeActive = false; swipeFood = null; }; // Initialize the game - start with home screen showHomeScreen();
/****
* 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;
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 200,
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'];
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 gameState = 'playing'; // 'playing', 'levelComplete', 'levelSelect'
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);
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();
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() {
scoreText.setText('Score: ' + currentScore);
movesText.setText('Moves: ' + movesLeft);
targetText.setText('Target: ' + targetMatches);
}
function checkGameEnd() {
if (matchesCleared >= targetMatches) {
if (currentLevel === 1 && !levelCompleteShown) {
showLevelComplete();
} else {
completeLevel();
}
} else if (movesLeft <= 0) {
LK.showGameOver();
}
}
function showLevelComplete() {
levelCompleteShown = true;
gameState = 'levelComplete';
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';
// Set green background for home screen
game.setBackgroundColor(0x00FF00);
// 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');
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 as Guest', {
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');
// Start the game
startLevel(1);
};
buttonsContainer.addChild(playAsGuestButton);
}
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 () {
// Handle account creation (for now just start the game)
console.log('Account created');
startLevel(1);
};
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 () {
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
keyBg.tint = 0xAAAAAA;
LK.setTimeout(function () {
keyBg.tint = 0xCCCCCC;
}, 100);
};
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;
// Show home screen instead of level select
showHomeScreen();
}
function startLevel(levelNum) {
currentLevel = levelNum;
gameState = 'playing';
levelCompleteShown = false;
// 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;
}
};
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
swipeFood.alpha = 1;
isSwipeActive = false;
swipeFood = null;
};
// Initialize the game - start with home screen
showHomeScreen();