User prompt
Add animation to the face of the fruits ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Let the grill be black
User prompt
Put the grill in the box
User prompt
Let it be a little more clear, the grill color should not cover the outer edges.
User prompt
Please fix the bug: 'null is not an object (evaluating 't.length')' in or related to this line: 'var lineAsset = LK.getAsset(null, {' Line Number: 348
User prompt
Add a transparent grill in gray among the fruits
User prompt
Let it all be different explosion animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Show the explosion effect
User prompt
Please fix the bug: 'TypeError: null is not an object (evaluating 'tile.destroy')' in or related to this line: 'tile.destroy();' Line Number: 505
User prompt
When combined, let the fruits explode ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Let them all have different dance animations ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add dancing animation to fruits ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove the names from the fruits
User prompt
Make the background white and make it a little bigger
User prompt
Remove the transparent fruits on the back
User prompt
Make the theme fruits
User prompt
Please fix the bug: 'LK.hasAsset is not a function. (In 'LK.hasAsset(assetId)', 'LK.hasAsset' is undefined)' in or related to this line: 'if (!LK.hasAsset(assetId)) {' Line Number: 43
Code edit (1 edits merged)
Please save this source code
User prompt
Galactic 2048: Space Merge
Initial prompt
Space themed 2048 game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Tile class for each grid cell var Tile = Container.expand(function () { var self = Container.call(this); // Properties self.value = 2; // Default value self.row = 0; self.col = 0; self.asset = null; self.text = null; // Set tile value and update appearance self.setValue = function (val) { self.value = val; // Remove old asset if exists if (self.asset) { self.removeChild(self.asset); } // Choose asset by value var assetId = 'tile' + val; var supportedAssets = { 'tile2': true, 'tile4': true, 'tile8': true, 'tile16': true, 'tile32': true, 'tile64': true, 'tile128': true, 'tile256': true, 'tile512': true, 'tile1024': true, 'tile2048': true }; if (!supportedAssets[assetId]) assetId = 'tile2048'; // fallback self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Remove old text if exists if (self.text) { self.removeChild(self.text); } // Add value text (empty label, no fruit names) var label = ''; self.text = new Text2(label, { size: 60, fill: 0xFFFFFF, align: "center" }); self.text.anchor.set(0.5, 0.5); self.text.y = 0; self.text.x = 0; self.addChild(self.text); // Restart dancing after value change if (self.startDancing) self.startDancing(); }; // Animate merge self.animateMerge = function () { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeIn, onFinish: function onFinish() { if (self.startDancing) self.startDancing(); } }); } }); }; // Animate spawn self.animateSpawn = function () { self.scaleX = 0.2; self.scaleY = 0.2; tween(self, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { if (self.startDancing) self.startDancing(); } }); }; // Set position on grid self.setGridPos = function (row, col, cellSize, gridX, gridY) { self.row = row; self.col = col; self.x = gridX + col * cellSize + cellSize / 2; self.y = gridY + row * cellSize + cellSize / 2; }; // Add dancing animation (continuous, unique per value) self.startDancing = function () { // Cancel any previous tweens on scale tween.stop(self, { scaleX: true, scaleY: true }); // Unique dance parameters per value var dances = { 2: { sx1: 1.10, sy1: 0.90, sx2: 0.90, sy2: 1.10, dur1: 220, dur2: 220, ease1: tween.easeInOut, ease2: tween.easeInOut }, 4: { sx1: 1.15, sy1: 0.85, sx2: 0.85, sy2: 1.15, dur1: 180, dur2: 180, ease1: tween.bounceIn, ease2: tween.bounceOut }, 8: { sx1: 1.08, sy1: 1.08, sx2: 0.92, sy2: 0.92, dur1: 260, dur2: 260, ease1: tween.elasticIn, ease2: tween.elasticOut }, 16: { sx1: 1.20, sy1: 0.80, sx2: 0.80, sy2: 1.20, dur1: 150, dur2: 150, ease1: tween.cubicOut, ease2: tween.cubicIn }, 32: { sx1: 1.05, sy1: 1.15, sx2: 1.15, sy2: 1.05, dur1: 200, dur2: 200, ease1: tween.quarticInOut, ease2: tween.quarticInOut }, 64: { sx1: 1.18, sy1: 0.95, sx2: 0.95, sy2: 1.18, dur1: 170, dur2: 170, ease1: tween.sineIn, ease2: tween.sineOut }, 128: { sx1: 1.12, sy1: 1.12, sx2: 0.88, sy2: 0.88, dur1: 250, dur2: 250, ease1: tween.elasticInOut, ease2: tween.elasticInOut }, 256: { sx1: 1.25, sy1: 0.75, sx2: 0.75, sy2: 1.25, dur1: 140, dur2: 140, ease1: tween.bounceOut, ease2: tween.bounceIn }, 512: { sx1: 1.10, sy1: 1.05, sx2: 1.05, sy2: 1.10, dur1: 210, dur2: 210, ease1: tween.cubicIn, ease2: tween.cubicOut }, 1024: { sx1: 1.22, sy1: 0.92, sx2: 0.92, sy2: 1.22, dur1: 160, dur2: 160, ease1: tween.quinticIn, ease2: tween.quinticOut }, 2048: { sx1: 1.30, sy1: 0.70, sx2: 0.70, sy2: 1.30, dur1: 120, dur2: 120, ease1: tween.expoIn, ease2: tween.expoOut } }; var dance = dances[self.value] || dances[2]; function danceUp() { tween(self, { scaleX: dance.sx1, scaleY: dance.sy1 }, { duration: dance.dur1, easing: dance.ease1, onFinish: function onFinish() { danceDown(); } }); } function danceDown() { tween(self, { scaleX: dance.sx2, scaleY: dance.sy2 }, { duration: dance.dur2, easing: dance.ease2, onFinish: function onFinish() { danceUp(); } }); } // Start the loop danceUp(); }; // Stop dancing animation self.stopDancing = function () { tween.stop(self, { scaleX: true, scaleY: true }); self.scaleX = 1; self.scaleY = 1; }; // Start dancing by default self.startDancing(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xffffff }); /**** * Game Code ****/ // Optionally, a subtle grid background // 2: Asteroid (gray), 4: Moon (light blue), 8: Planet (blue), 16: Star (yellow), 32: Red Giant (red), 64: Neutron Star (purple), 128: Black Hole (black), 256: Nebula (pink), 512: Galaxy (cyan), 1024: Quasar (orange), 2048: Universe (white) // Space tile assets: We'll use colored ellipses for different tile values // --- Grid and Layout --- var gridSize = 4; var cellSize = 370; // 370*4=1480, bigger board var gridPadding = 28; var gridWidth = cellSize * gridSize + gridPadding * (gridSize + 1); var gridHeight = cellSize * gridSize + gridPadding * (gridSize + 1); var gridX = Math.floor((2048 - gridWidth) / 2); var gridY = Math.floor((2732 - gridHeight) / 2); // --- Game State --- var grid = []; // 2D array of tiles or null var tiles = []; // All tile objects for easy management var score = 0; var scoreTxt = null; var isMoving = false; // Prevent input during animation // --- GUI: Score --- scoreTxt = new Text2('0', { size: 120, fill: "#000" }); // Anchor to top right (right edge, top) scoreTxt.anchor.set(1, 0); // Place in the top right GUI overlay, with a margin from the edge scoreTxt.x = LK.gui.width - 60; scoreTxt.y = 30; LK.gui.addChild(scoreTxt); // --- Draw grid background --- var gridBg = LK.getAsset('gridBg', { anchorX: 0, anchorY: 0, // Enlarge the background image to be much bigger than the grid, centered behind it x: gridX - 200, y: gridY - 200, width: gridWidth + 400, height: gridHeight + 400 }); game.addChild(gridBg); // --- Draw a more beautiful box outline with double border and subtle shadow --- // Outer border (thicker, dark, semi-transparent) var boxOuter = LK.getAsset('shape', { width: gridWidth + 24, height: gridHeight + 24, color: 0x222222, shape: 'box', anchorX: 0, anchorY: 0, alpha: 0.22, x: gridX - 12, y: gridY - 12 }); boxOuter.visible = true; boxOuter.interactive = false; game.addChild(boxOuter); // Inner border (thin, bright, more opaque) var boxInner = LK.getAsset('shape', { width: gridWidth, height: gridHeight, color: 0xffffff, shape: 'box', anchorX: 0, anchorY: 0, alpha: 0.13, x: gridX, y: gridY }); boxInner.visible = true; boxInner.interactive = false; game.addChild(boxInner); // Decorative shadow (soft, large, very transparent) var boxShadow = LK.getAsset('shape', { width: gridWidth + 80, height: gridHeight + 80, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, alpha: 0.08, x: gridX - 40, y: gridY - 20 }); boxShadow.visible = true; boxShadow.interactive = false; game.addChild(boxShadow); // --- Draw transparent gray grill overlay --- var grillContainer = new Container(); var grillLineColor = 0x000000; var grillAlpha = 0.25; var grillLineWidth = 24; // The grill lines should not cover the outer grid edges, so lines are drawn only between cells // The vertical lines go from the top inner padding to the bottom inner padding var grillInnerHeight = cellSize * gridSize + gridPadding * (gridSize - 1); var grillInnerWidth = cellSize * gridSize + gridPadding * (gridSize - 1); // Vertical lines (between columns, not at the very left/right) for (var c = 1; c < gridSize; c++) { var x = gridX + gridPadding + c * cellSize + (c - 0.5) * gridPadding; var lineAsset = LK.getAsset('shape', { width: grillLineWidth, height: grillInnerHeight, color: grillLineColor, shape: 'box', anchorX: 0.5, anchorY: 0, alpha: grillAlpha, x: x, y: gridY + gridPadding }); grillContainer.addChild(lineAsset); } // Horizontal lines (between rows, not at the very top/bottom) for (var r = 1; r < gridSize; r++) { var y = gridY + gridPadding + r * cellSize + (r - 0.5) * gridPadding; var lineAsset = LK.getAsset('shape', { width: grillInnerWidth, height: grillLineWidth, color: grillLineColor, shape: 'box', anchorX: 0, anchorY: 0.5, alpha: grillAlpha, x: gridX + gridPadding, y: y }); grillContainer.addChild(lineAsset); } game.addChild(grillContainer); // --- Draw grid cell backgrounds --- // (Removed transparent fruit tiles on the back) // --- Initialize grid state --- function resetGrid() { grid = []; for (var r = 0; r < gridSize; r++) { var row = []; for (var c = 0; c < gridSize; c++) { row.push(null); } grid.push(row); } // Remove all tiles from game for (var i = 0; i < tiles.length; i++) { tiles[i].destroy(); } tiles = []; score = 0; scoreTxt.setText(score); } // --- Add a new tile (2 or 4) at random empty position --- function addRandomTile() { var empties = []; for (var r = 0; r < gridSize; r++) { for (var c = 0; c < gridSize; c++) { if (!grid[r][c]) empties.push({ r: r, c: c }); } } if (empties.length === 0) return false; var idx = Math.floor(Math.random() * empties.length); var pos = empties[idx]; var val = Math.random() < 0.9 ? 2 : 4; var tile = new Tile(); tile.setValue(val); tile.setGridPos(pos.r, pos.c, cellSize, gridX + gridPadding, gridY + gridPadding); tile.animateSpawn(); grid[pos.r][pos.c] = tile; tiles.push(tile); game.addChild(tile); return true; } // --- Move/merge logic --- function canMove() { // Check for any empty cell for (var r = 0; r < gridSize; r++) { for (var c = 0; c < gridSize; c++) { if (!grid[r][c]) return true; } } // Check for any mergeable neighbor for (var r = 0; r < gridSize; r++) { for (var c = 0; c < gridSize; c++) { var tile = grid[r][c]; if (!tile) continue; // Right if (c + 1 < gridSize && grid[r][c + 1] && grid[r][c + 1].value === tile.value) return true; // Down if (r + 1 < gridSize && grid[r + 1][c] && grid[r + 1][c].value === tile.value) return true; } } return false; } // Returns true if any tile reached 2048 function has2048() { for (var r = 0; r < gridSize; r++) { for (var c = 0; c < gridSize; c++) { if (grid[r][c] && grid[r][c].value === 2048) return true; } } return false; } // Move tiles in a direction: 'up', 'down', 'left', 'right' function moveTiles(dir) { if (isMoving) return; isMoving = true; var moved = false; var mergedThisMove = []; // Helper to reset merged flags function resetMerged() { for (var i = 0; i < tiles.length; i++) { tiles[i].merged = false; } } resetMerged(); // For each direction, set up iteration order var startR = 0, endR = gridSize, stepR = 1; var startC = 0, endC = gridSize, stepC = 1; if (dir === 'up') { startR = 1; endR = gridSize; stepR = 1; } if (dir === 'down') { startR = gridSize - 2; endR = -1; stepR = -1; } if (dir === 'left') { startC = 1; endC = gridSize; stepC = 1; } if (dir === 'right') { startC = gridSize - 2; endC = -1; stepC = -1; } // Move/merge logic var movedTiles = []; if (dir === 'up' || dir === 'down') { for (var c = 0; c < gridSize; c++) { for (var r = startR; r != endR; r += stepR) { var tile = grid[r][c]; if (!tile) continue; var tr = r; while (true) { var nr = tr + (dir === 'up' ? -1 : 1); if (nr < 0 || nr >= gridSize) break; if (!grid[nr][c]) { // Move grid[nr][c] = tile; grid[tr][c] = null; tr = nr; moved = true; } else if (grid[nr][c].value === tile.value && !grid[nr][c].merged && !tile.merged) { // Merge grid[nr][c].setValue(tile.value * 2); grid[nr][c].animateMerge(); grid[nr][c].merged = true; score += tile.value * 2; scoreTxt.setText(score); // Explode animation for merged tile tile.stopDancing && tile.stopDancing(); // Show explosion effect // Unique explosion animation per value var explosionAnims = { 2: { scale: 1.6, alpha: 0, duration: 180, easing: tween.bounceOut, tint: 0xE0E0E0 }, 4: { scale: 2.0, alpha: 0, duration: 220, easing: tween.elasticOut, tint: 0xB0E0FF }, 8: { scale: 1.7, alpha: 0, duration: 200, easing: tween.cubicOut, tint: 0x6CA0FF }, 16: { scale: 2.2, alpha: 0, duration: 240, easing: tween.quarticInOut, tint: 0xFFF700 }, 32: { scale: 1.9, alpha: 0, duration: 210, easing: tween.sineOut, tint: 0xFF3A3A }, 64: { scale: 2.3, alpha: 0, duration: 250, easing: tween.elasticInOut, tint: 0xB000FF }, 128: { scale: 2.0, alpha: 0, duration: 230, easing: tween.bounceIn, tint: 0x000000 }, 256: { scale: 2.5, alpha: 0, duration: 260, easing: tween.cubicIn, tint: 0xFF7EB9 }, 512: { scale: 2.1, alpha: 0, duration: 200, easing: tween.quinticOut, tint: 0x00FFF7 }, 1024: { scale: 2.4, alpha: 0, duration: 270, easing: tween.expoIn, tint: 0xFFB84C }, 2048: { scale: 2.8, alpha: 0, duration: 300, easing: tween.expoOut, tint: 0xFFFFFF } }; var exp = explosionAnims[tile.value] || explosionAnims[2]; LK.effects.flashObject(tile, exp.tint, Math.min(180, exp.duration)); tween(tile, { scaleX: exp.scale, scaleY: exp.scale, alpha: exp.alpha }, { duration: exp.duration, easing: exp.easing, onFinish: function onFinish() { if (tile && typeof tile.destroy === "function") { tile.destroy(); } } }); tiles.splice(tiles.indexOf(tile), 1); grid[tr][c] = null; moved = true; break; } else { break; } } // Animate move if (tile && tr !== r) { tile.setGridPos(tr, c, cellSize, gridX + gridPadding, gridY + gridPadding); movedTiles.push(tile); } } } } else { for (var r = 0; r < gridSize; r++) { for (var c = startC; c != endC; c += stepC) { var tile = grid[r][c]; if (!tile) continue; var tc = c; while (true) { var nc = tc + (dir === 'left' ? -1 : 1); if (nc < 0 || nc >= gridSize) break; if (!grid[r][nc]) { // Move grid[r][nc] = tile; grid[r][tc] = null; tc = nc; moved = true; } else if (grid[r][nc].value === tile.value && !grid[r][nc].merged && !tile.merged) { // Merge grid[r][nc].setValue(tile.value * 2); grid[r][nc].animateMerge(); grid[r][nc].merged = true; score += tile.value * 2; scoreTxt.setText(score); // Explode animation for merged tile tile.stopDancing && tile.stopDancing(); // Show explosion effect // Unique explosion animation per value var explosionAnims = { 2: { scale: 1.6, alpha: 0, duration: 180, easing: tween.bounceOut, tint: 0xE0E0E0 }, 4: { scale: 2.0, alpha: 0, duration: 220, easing: tween.elasticOut, tint: 0xB0E0FF }, 8: { scale: 1.7, alpha: 0, duration: 200, easing: tween.cubicOut, tint: 0x6CA0FF }, 16: { scale: 2.2, alpha: 0, duration: 240, easing: tween.quarticInOut, tint: 0xFFF700 }, 32: { scale: 1.9, alpha: 0, duration: 210, easing: tween.sineOut, tint: 0xFF3A3A }, 64: { scale: 2.3, alpha: 0, duration: 250, easing: tween.elasticInOut, tint: 0xB000FF }, 128: { scale: 2.0, alpha: 0, duration: 230, easing: tween.bounceIn, tint: 0x000000 }, 256: { scale: 2.5, alpha: 0, duration: 260, easing: tween.cubicIn, tint: 0xFF7EB9 }, 512: { scale: 2.1, alpha: 0, duration: 200, easing: tween.quinticOut, tint: 0x00FFF7 }, 1024: { scale: 2.4, alpha: 0, duration: 270, easing: tween.expoIn, tint: 0xFFB84C }, 2048: { scale: 2.8, alpha: 0, duration: 300, easing: tween.expoOut, tint: 0xFFFFFF } }; var exp = explosionAnims[tile.value] || explosionAnims[2]; LK.effects.flashObject(tile, exp.tint, Math.min(180, exp.duration)); tween(tile, { scaleX: exp.scale, scaleY: exp.scale, alpha: exp.alpha }, { duration: exp.duration, easing: exp.easing, onFinish: function onFinish() { if (tile && typeof tile.destroy === "function") { tile.destroy(); } } }); tiles.splice(tiles.indexOf(tile), 1); grid[r][tc] = null; moved = true; break; } else { break; } } // Animate move if (tile && tc !== c) { tile.setGridPos(r, tc, cellSize, gridX + gridPadding, gridY + gridPadding); movedTiles.push(tile); } } } } // Animate all moved tiles var animCount = movedTiles.length; if (animCount === 0) { isMoving = false; afterMove(moved); } else { for (var i = 0; i < movedTiles.length; i++) { var t = movedTiles[i]; tween(t, { x: t.x, y: t.y }, { duration: 100, easing: tween.easeInOut, onFinish: function onFinish() { animCount--; if (animCount === 0) { isMoving = false; afterMove(moved); } } }); } } if (animCount === 0) { // No animation, call afterMove immediately afterMove(moved); } } // After move: add new tile, check win/lose function afterMove(moved) { if (moved) { addRandomTile(); } // Save best score if new high score if (typeof storage !== "undefined" && storage.setItem) { var prevBest = storage.getItem("fruitdance_bestscore"); if (typeof prevBest !== "number" || score > prevBest) { storage.setItem("fruitdance_bestscore", score); } } if (has2048()) { LK.showYouWin(); return; } if (!canMove()) { LK.showGameOver(); return; } } // --- Input: Swipe detection --- // We'll use game.down, game.move, game.up to detect swipe direction var touchStartX = 0, touchStartY = 0, touchMoved = false; game.down = function (x, y, obj) { if (isMoving) return; touchStartX = x; touchStartY = y; touchMoved = false; }; game.move = function (x, y, obj) { if (isMoving) return; if (touchStartX === undefined) return; var dx = x - touchStartX; var dy = y - touchStartY; if (!touchMoved && (Math.abs(dx) > 40 || Math.abs(dy) > 40)) { touchMoved = true; // Determine direction if (Math.abs(dx) > Math.abs(dy)) { if (dx > 0) moveTiles('right');else moveTiles('left'); } else { if (dy > 0) moveTiles('down');else moveTiles('up'); } // Reset to prevent multiple moves per swipe touchStartX = undefined; touchStartY = undefined; } }; game.up = function (x, y, obj) { touchStartX = undefined; touchStartY = undefined; touchMoved = false; }; // --- Game update (not used, but required for tick-based games) --- game.update = function () { // No per-frame logic needed }; // --- Start game --- function startGame() { resetGrid(); addRandomTile(); addRandomTile(); scoreTxt.setText(score); } // --- Start Page Overlay --- var startOverlay = new Container(); startOverlay.zIndex = 10000; // Ensure on top // Semi-transparent dark background var overlayBg = LK.getAsset('shape', { width: 2048, height: 2732, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, alpha: 0.72, x: 0, y: 0 }); startOverlay.addChild(overlayBg); // Game title var titleText = new Text2('Fruit Dance', { size: 180, fill: "#fff", align: "center" }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 900; startOverlay.addChild(titleText); // Scoreboard (shows best score if available, otherwise just 'Score: 0') var bestScore = 0; if (typeof storage !== "undefined" && storage.getItem) { var stored = storage.getItem("fruitdance_bestscore"); if (typeof stored === "number" && stored > 0) bestScore = stored; } var scoreboardText = new Text2(bestScore > 0 ? "Best Score: " + bestScore : "Score: 0", { size: 90, fill: 0xFFE066, align: "center" }); scoreboardText.anchor.set(0.5, 0.5); scoreboardText.x = 1024; scoreboardText.y = 1050; startOverlay.addChild(scoreboardText); // Subtitle var subtitleText = new Text2('Merge cosmic tiles to reach the Universe!', { size: 70, fill: 0xE0E0E0, align: "center" }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 1150; startOverlay.addChild(subtitleText); // Creator credit var creatorText = new Text2('Game by Osman Eren', { size: 54, fill: 0xCCCCCC, align: "center" }); creatorText.anchor.set(0.5, 0.5); creatorText.x = 1024; creatorText.y = 1230; startOverlay.addChild(creatorText); // Play button var playBtn = LK.getAsset('shape', { width: 520, height: 180, color: 0x2e8bfa, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, alpha: 0.95 }); playBtn.interactive = true; startOverlay.addChild(playBtn); var playBtnText = new Text2('Play', { size: 100, fill: "#fff", align: "center" }); playBtnText.anchor.set(0.5, 0.5); playBtnText.x = 1024; playBtnText.y = 1400; startOverlay.addChild(playBtnText); // Add overlay to game game.addChild(startOverlay); // Disable input until game starts var inputEnabled = false; // Play button handler playBtn.down = function (x, y, obj) { if (!inputEnabled) return; // Animate button press tween(playBtn, { scaleX: 0.92, scaleY: 0.92 }, { duration: 60, onFinish: function onFinish() { tween(playBtn, { scaleX: 1, scaleY: 1 }, { duration: 60 }); } }); // Remove overlay and start game startOverlay.visible = false; inputEnabled = false; startGame(); }; // Enable input after a short delay to prevent accidental skip LK.setTimeout(function () { inputEnabled = true; }, 400); // Prevent swipes before game starts var origDown = game.down; var origMove = game.move; var origUp = game.up; game.down = function (x, y, obj) { if (startOverlay.visible) return; if (origDown) origDown(x, y, obj); }; game.move = function (x, y, obj) { if (startOverlay.visible) return; if (origMove) origMove(x, y, obj); }; game.up = function (x, y, obj) { if (startOverlay.visible) return; if (origUp) origUp(x, y, obj); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Tile class for each grid cell
var Tile = Container.expand(function () {
var self = Container.call(this);
// Properties
self.value = 2; // Default value
self.row = 0;
self.col = 0;
self.asset = null;
self.text = null;
// Set tile value and update appearance
self.setValue = function (val) {
self.value = val;
// Remove old asset if exists
if (self.asset) {
self.removeChild(self.asset);
}
// Choose asset by value
var assetId = 'tile' + val;
var supportedAssets = {
'tile2': true,
'tile4': true,
'tile8': true,
'tile16': true,
'tile32': true,
'tile64': true,
'tile128': true,
'tile256': true,
'tile512': true,
'tile1024': true,
'tile2048': true
};
if (!supportedAssets[assetId]) assetId = 'tile2048'; // fallback
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Remove old text if exists
if (self.text) {
self.removeChild(self.text);
}
// Add value text (empty label, no fruit names)
var label = '';
self.text = new Text2(label, {
size: 60,
fill: 0xFFFFFF,
align: "center"
});
self.text.anchor.set(0.5, 0.5);
self.text.y = 0;
self.text.x = 0;
self.addChild(self.text);
// Restart dancing after value change
if (self.startDancing) self.startDancing();
};
// Animate merge
self.animateMerge = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
if (self.startDancing) self.startDancing();
}
});
}
});
};
// Animate spawn
self.animateSpawn = function () {
self.scaleX = 0.2;
self.scaleY = 0.2;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.startDancing) self.startDancing();
}
});
};
// Set position on grid
self.setGridPos = function (row, col, cellSize, gridX, gridY) {
self.row = row;
self.col = col;
self.x = gridX + col * cellSize + cellSize / 2;
self.y = gridY + row * cellSize + cellSize / 2;
};
// Add dancing animation (continuous, unique per value)
self.startDancing = function () {
// Cancel any previous tweens on scale
tween.stop(self, {
scaleX: true,
scaleY: true
});
// Unique dance parameters per value
var dances = {
2: {
sx1: 1.10,
sy1: 0.90,
sx2: 0.90,
sy2: 1.10,
dur1: 220,
dur2: 220,
ease1: tween.easeInOut,
ease2: tween.easeInOut
},
4: {
sx1: 1.15,
sy1: 0.85,
sx2: 0.85,
sy2: 1.15,
dur1: 180,
dur2: 180,
ease1: tween.bounceIn,
ease2: tween.bounceOut
},
8: {
sx1: 1.08,
sy1: 1.08,
sx2: 0.92,
sy2: 0.92,
dur1: 260,
dur2: 260,
ease1: tween.elasticIn,
ease2: tween.elasticOut
},
16: {
sx1: 1.20,
sy1: 0.80,
sx2: 0.80,
sy2: 1.20,
dur1: 150,
dur2: 150,
ease1: tween.cubicOut,
ease2: tween.cubicIn
},
32: {
sx1: 1.05,
sy1: 1.15,
sx2: 1.15,
sy2: 1.05,
dur1: 200,
dur2: 200,
ease1: tween.quarticInOut,
ease2: tween.quarticInOut
},
64: {
sx1: 1.18,
sy1: 0.95,
sx2: 0.95,
sy2: 1.18,
dur1: 170,
dur2: 170,
ease1: tween.sineIn,
ease2: tween.sineOut
},
128: {
sx1: 1.12,
sy1: 1.12,
sx2: 0.88,
sy2: 0.88,
dur1: 250,
dur2: 250,
ease1: tween.elasticInOut,
ease2: tween.elasticInOut
},
256: {
sx1: 1.25,
sy1: 0.75,
sx2: 0.75,
sy2: 1.25,
dur1: 140,
dur2: 140,
ease1: tween.bounceOut,
ease2: tween.bounceIn
},
512: {
sx1: 1.10,
sy1: 1.05,
sx2: 1.05,
sy2: 1.10,
dur1: 210,
dur2: 210,
ease1: tween.cubicIn,
ease2: tween.cubicOut
},
1024: {
sx1: 1.22,
sy1: 0.92,
sx2: 0.92,
sy2: 1.22,
dur1: 160,
dur2: 160,
ease1: tween.quinticIn,
ease2: tween.quinticOut
},
2048: {
sx1: 1.30,
sy1: 0.70,
sx2: 0.70,
sy2: 1.30,
dur1: 120,
dur2: 120,
ease1: tween.expoIn,
ease2: tween.expoOut
}
};
var dance = dances[self.value] || dances[2];
function danceUp() {
tween(self, {
scaleX: dance.sx1,
scaleY: dance.sy1
}, {
duration: dance.dur1,
easing: dance.ease1,
onFinish: function onFinish() {
danceDown();
}
});
}
function danceDown() {
tween(self, {
scaleX: dance.sx2,
scaleY: dance.sy2
}, {
duration: dance.dur2,
easing: dance.ease2,
onFinish: function onFinish() {
danceUp();
}
});
}
// Start the loop
danceUp();
};
// Stop dancing animation
self.stopDancing = function () {
tween.stop(self, {
scaleX: true,
scaleY: true
});
self.scaleX = 1;
self.scaleY = 1;
};
// Start dancing by default
self.startDancing();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// Optionally, a subtle grid background
// 2: Asteroid (gray), 4: Moon (light blue), 8: Planet (blue), 16: Star (yellow), 32: Red Giant (red), 64: Neutron Star (purple), 128: Black Hole (black), 256: Nebula (pink), 512: Galaxy (cyan), 1024: Quasar (orange), 2048: Universe (white)
// Space tile assets: We'll use colored ellipses for different tile values
// --- Grid and Layout ---
var gridSize = 4;
var cellSize = 370; // 370*4=1480, bigger board
var gridPadding = 28;
var gridWidth = cellSize * gridSize + gridPadding * (gridSize + 1);
var gridHeight = cellSize * gridSize + gridPadding * (gridSize + 1);
var gridX = Math.floor((2048 - gridWidth) / 2);
var gridY = Math.floor((2732 - gridHeight) / 2);
// --- Game State ---
var grid = []; // 2D array of tiles or null
var tiles = []; // All tile objects for easy management
var score = 0;
var scoreTxt = null;
var isMoving = false; // Prevent input during animation
// --- GUI: Score ---
scoreTxt = new Text2('0', {
size: 120,
fill: "#000"
});
// Anchor to top right (right edge, top)
scoreTxt.anchor.set(1, 0);
// Place in the top right GUI overlay, with a margin from the edge
scoreTxt.x = LK.gui.width - 60;
scoreTxt.y = 30;
LK.gui.addChild(scoreTxt);
// --- Draw grid background ---
var gridBg = LK.getAsset('gridBg', {
anchorX: 0,
anchorY: 0,
// Enlarge the background image to be much bigger than the grid, centered behind it
x: gridX - 200,
y: gridY - 200,
width: gridWidth + 400,
height: gridHeight + 400
});
game.addChild(gridBg);
// --- Draw a more beautiful box outline with double border and subtle shadow ---
// Outer border (thicker, dark, semi-transparent)
var boxOuter = LK.getAsset('shape', {
width: gridWidth + 24,
height: gridHeight + 24,
color: 0x222222,
shape: 'box',
anchorX: 0,
anchorY: 0,
alpha: 0.22,
x: gridX - 12,
y: gridY - 12
});
boxOuter.visible = true;
boxOuter.interactive = false;
game.addChild(boxOuter);
// Inner border (thin, bright, more opaque)
var boxInner = LK.getAsset('shape', {
width: gridWidth,
height: gridHeight,
color: 0xffffff,
shape: 'box',
anchorX: 0,
anchorY: 0,
alpha: 0.13,
x: gridX,
y: gridY
});
boxInner.visible = true;
boxInner.interactive = false;
game.addChild(boxInner);
// Decorative shadow (soft, large, very transparent)
var boxShadow = LK.getAsset('shape', {
width: gridWidth + 80,
height: gridHeight + 80,
color: 0x000000,
shape: 'box',
anchorX: 0,
anchorY: 0,
alpha: 0.08,
x: gridX - 40,
y: gridY - 20
});
boxShadow.visible = true;
boxShadow.interactive = false;
game.addChild(boxShadow);
// --- Draw transparent gray grill overlay ---
var grillContainer = new Container();
var grillLineColor = 0x000000;
var grillAlpha = 0.25;
var grillLineWidth = 24;
// The grill lines should not cover the outer grid edges, so lines are drawn only between cells
// The vertical lines go from the top inner padding to the bottom inner padding
var grillInnerHeight = cellSize * gridSize + gridPadding * (gridSize - 1);
var grillInnerWidth = cellSize * gridSize + gridPadding * (gridSize - 1);
// Vertical lines (between columns, not at the very left/right)
for (var c = 1; c < gridSize; c++) {
var x = gridX + gridPadding + c * cellSize + (c - 0.5) * gridPadding;
var lineAsset = LK.getAsset('shape', {
width: grillLineWidth,
height: grillInnerHeight,
color: grillLineColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0,
alpha: grillAlpha,
x: x,
y: gridY + gridPadding
});
grillContainer.addChild(lineAsset);
}
// Horizontal lines (between rows, not at the very top/bottom)
for (var r = 1; r < gridSize; r++) {
var y = gridY + gridPadding + r * cellSize + (r - 0.5) * gridPadding;
var lineAsset = LK.getAsset('shape', {
width: grillInnerWidth,
height: grillLineWidth,
color: grillLineColor,
shape: 'box',
anchorX: 0,
anchorY: 0.5,
alpha: grillAlpha,
x: gridX + gridPadding,
y: y
});
grillContainer.addChild(lineAsset);
}
game.addChild(grillContainer);
// --- Draw grid cell backgrounds ---
// (Removed transparent fruit tiles on the back)
// --- Initialize grid state ---
function resetGrid() {
grid = [];
for (var r = 0; r < gridSize; r++) {
var row = [];
for (var c = 0; c < gridSize; c++) {
row.push(null);
}
grid.push(row);
}
// Remove all tiles from game
for (var i = 0; i < tiles.length; i++) {
tiles[i].destroy();
}
tiles = [];
score = 0;
scoreTxt.setText(score);
}
// --- Add a new tile (2 or 4) at random empty position ---
function addRandomTile() {
var empties = [];
for (var r = 0; r < gridSize; r++) {
for (var c = 0; c < gridSize; c++) {
if (!grid[r][c]) empties.push({
r: r,
c: c
});
}
}
if (empties.length === 0) return false;
var idx = Math.floor(Math.random() * empties.length);
var pos = empties[idx];
var val = Math.random() < 0.9 ? 2 : 4;
var tile = new Tile();
tile.setValue(val);
tile.setGridPos(pos.r, pos.c, cellSize, gridX + gridPadding, gridY + gridPadding);
tile.animateSpawn();
grid[pos.r][pos.c] = tile;
tiles.push(tile);
game.addChild(tile);
return true;
}
// --- Move/merge logic ---
function canMove() {
// Check for any empty cell
for (var r = 0; r < gridSize; r++) {
for (var c = 0; c < gridSize; c++) {
if (!grid[r][c]) return true;
}
}
// Check for any mergeable neighbor
for (var r = 0; r < gridSize; r++) {
for (var c = 0; c < gridSize; c++) {
var tile = grid[r][c];
if (!tile) continue;
// Right
if (c + 1 < gridSize && grid[r][c + 1] && grid[r][c + 1].value === tile.value) return true;
// Down
if (r + 1 < gridSize && grid[r + 1][c] && grid[r + 1][c].value === tile.value) return true;
}
}
return false;
}
// Returns true if any tile reached 2048
function has2048() {
for (var r = 0; r < gridSize; r++) {
for (var c = 0; c < gridSize; c++) {
if (grid[r][c] && grid[r][c].value === 2048) return true;
}
}
return false;
}
// Move tiles in a direction: 'up', 'down', 'left', 'right'
function moveTiles(dir) {
if (isMoving) return;
isMoving = true;
var moved = false;
var mergedThisMove = [];
// Helper to reset merged flags
function resetMerged() {
for (var i = 0; i < tiles.length; i++) {
tiles[i].merged = false;
}
}
resetMerged();
// For each direction, set up iteration order
var startR = 0,
endR = gridSize,
stepR = 1;
var startC = 0,
endC = gridSize,
stepC = 1;
if (dir === 'up') {
startR = 1;
endR = gridSize;
stepR = 1;
}
if (dir === 'down') {
startR = gridSize - 2;
endR = -1;
stepR = -1;
}
if (dir === 'left') {
startC = 1;
endC = gridSize;
stepC = 1;
}
if (dir === 'right') {
startC = gridSize - 2;
endC = -1;
stepC = -1;
}
// Move/merge logic
var movedTiles = [];
if (dir === 'up' || dir === 'down') {
for (var c = 0; c < gridSize; c++) {
for (var r = startR; r != endR; r += stepR) {
var tile = grid[r][c];
if (!tile) continue;
var tr = r;
while (true) {
var nr = tr + (dir === 'up' ? -1 : 1);
if (nr < 0 || nr >= gridSize) break;
if (!grid[nr][c]) {
// Move
grid[nr][c] = tile;
grid[tr][c] = null;
tr = nr;
moved = true;
} else if (grid[nr][c].value === tile.value && !grid[nr][c].merged && !tile.merged) {
// Merge
grid[nr][c].setValue(tile.value * 2);
grid[nr][c].animateMerge();
grid[nr][c].merged = true;
score += tile.value * 2;
scoreTxt.setText(score);
// Explode animation for merged tile
tile.stopDancing && tile.stopDancing();
// Show explosion effect
// Unique explosion animation per value
var explosionAnims = {
2: {
scale: 1.6,
alpha: 0,
duration: 180,
easing: tween.bounceOut,
tint: 0xE0E0E0
},
4: {
scale: 2.0,
alpha: 0,
duration: 220,
easing: tween.elasticOut,
tint: 0xB0E0FF
},
8: {
scale: 1.7,
alpha: 0,
duration: 200,
easing: tween.cubicOut,
tint: 0x6CA0FF
},
16: {
scale: 2.2,
alpha: 0,
duration: 240,
easing: tween.quarticInOut,
tint: 0xFFF700
},
32: {
scale: 1.9,
alpha: 0,
duration: 210,
easing: tween.sineOut,
tint: 0xFF3A3A
},
64: {
scale: 2.3,
alpha: 0,
duration: 250,
easing: tween.elasticInOut,
tint: 0xB000FF
},
128: {
scale: 2.0,
alpha: 0,
duration: 230,
easing: tween.bounceIn,
tint: 0x000000
},
256: {
scale: 2.5,
alpha: 0,
duration: 260,
easing: tween.cubicIn,
tint: 0xFF7EB9
},
512: {
scale: 2.1,
alpha: 0,
duration: 200,
easing: tween.quinticOut,
tint: 0x00FFF7
},
1024: {
scale: 2.4,
alpha: 0,
duration: 270,
easing: tween.expoIn,
tint: 0xFFB84C
},
2048: {
scale: 2.8,
alpha: 0,
duration: 300,
easing: tween.expoOut,
tint: 0xFFFFFF
}
};
var exp = explosionAnims[tile.value] || explosionAnims[2];
LK.effects.flashObject(tile, exp.tint, Math.min(180, exp.duration));
tween(tile, {
scaleX: exp.scale,
scaleY: exp.scale,
alpha: exp.alpha
}, {
duration: exp.duration,
easing: exp.easing,
onFinish: function onFinish() {
if (tile && typeof tile.destroy === "function") {
tile.destroy();
}
}
});
tiles.splice(tiles.indexOf(tile), 1);
grid[tr][c] = null;
moved = true;
break;
} else {
break;
}
}
// Animate move
if (tile && tr !== r) {
tile.setGridPos(tr, c, cellSize, gridX + gridPadding, gridY + gridPadding);
movedTiles.push(tile);
}
}
}
} else {
for (var r = 0; r < gridSize; r++) {
for (var c = startC; c != endC; c += stepC) {
var tile = grid[r][c];
if (!tile) continue;
var tc = c;
while (true) {
var nc = tc + (dir === 'left' ? -1 : 1);
if (nc < 0 || nc >= gridSize) break;
if (!grid[r][nc]) {
// Move
grid[r][nc] = tile;
grid[r][tc] = null;
tc = nc;
moved = true;
} else if (grid[r][nc].value === tile.value && !grid[r][nc].merged && !tile.merged) {
// Merge
grid[r][nc].setValue(tile.value * 2);
grid[r][nc].animateMerge();
grid[r][nc].merged = true;
score += tile.value * 2;
scoreTxt.setText(score);
// Explode animation for merged tile
tile.stopDancing && tile.stopDancing();
// Show explosion effect
// Unique explosion animation per value
var explosionAnims = {
2: {
scale: 1.6,
alpha: 0,
duration: 180,
easing: tween.bounceOut,
tint: 0xE0E0E0
},
4: {
scale: 2.0,
alpha: 0,
duration: 220,
easing: tween.elasticOut,
tint: 0xB0E0FF
},
8: {
scale: 1.7,
alpha: 0,
duration: 200,
easing: tween.cubicOut,
tint: 0x6CA0FF
},
16: {
scale: 2.2,
alpha: 0,
duration: 240,
easing: tween.quarticInOut,
tint: 0xFFF700
},
32: {
scale: 1.9,
alpha: 0,
duration: 210,
easing: tween.sineOut,
tint: 0xFF3A3A
},
64: {
scale: 2.3,
alpha: 0,
duration: 250,
easing: tween.elasticInOut,
tint: 0xB000FF
},
128: {
scale: 2.0,
alpha: 0,
duration: 230,
easing: tween.bounceIn,
tint: 0x000000
},
256: {
scale: 2.5,
alpha: 0,
duration: 260,
easing: tween.cubicIn,
tint: 0xFF7EB9
},
512: {
scale: 2.1,
alpha: 0,
duration: 200,
easing: tween.quinticOut,
tint: 0x00FFF7
},
1024: {
scale: 2.4,
alpha: 0,
duration: 270,
easing: tween.expoIn,
tint: 0xFFB84C
},
2048: {
scale: 2.8,
alpha: 0,
duration: 300,
easing: tween.expoOut,
tint: 0xFFFFFF
}
};
var exp = explosionAnims[tile.value] || explosionAnims[2];
LK.effects.flashObject(tile, exp.tint, Math.min(180, exp.duration));
tween(tile, {
scaleX: exp.scale,
scaleY: exp.scale,
alpha: exp.alpha
}, {
duration: exp.duration,
easing: exp.easing,
onFinish: function onFinish() {
if (tile && typeof tile.destroy === "function") {
tile.destroy();
}
}
});
tiles.splice(tiles.indexOf(tile), 1);
grid[r][tc] = null;
moved = true;
break;
} else {
break;
}
}
// Animate move
if (tile && tc !== c) {
tile.setGridPos(r, tc, cellSize, gridX + gridPadding, gridY + gridPadding);
movedTiles.push(tile);
}
}
}
}
// Animate all moved tiles
var animCount = movedTiles.length;
if (animCount === 0) {
isMoving = false;
afterMove(moved);
} else {
for (var i = 0; i < movedTiles.length; i++) {
var t = movedTiles[i];
tween(t, {
x: t.x,
y: t.y
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
animCount--;
if (animCount === 0) {
isMoving = false;
afterMove(moved);
}
}
});
}
}
if (animCount === 0) {
// No animation, call afterMove immediately
afterMove(moved);
}
}
// After move: add new tile, check win/lose
function afterMove(moved) {
if (moved) {
addRandomTile();
}
// Save best score if new high score
if (typeof storage !== "undefined" && storage.setItem) {
var prevBest = storage.getItem("fruitdance_bestscore");
if (typeof prevBest !== "number" || score > prevBest) {
storage.setItem("fruitdance_bestscore", score);
}
}
if (has2048()) {
LK.showYouWin();
return;
}
if (!canMove()) {
LK.showGameOver();
return;
}
}
// --- Input: Swipe detection ---
// We'll use game.down, game.move, game.up to detect swipe direction
var touchStartX = 0,
touchStartY = 0,
touchMoved = false;
game.down = function (x, y, obj) {
if (isMoving) return;
touchStartX = x;
touchStartY = y;
touchMoved = false;
};
game.move = function (x, y, obj) {
if (isMoving) return;
if (touchStartX === undefined) return;
var dx = x - touchStartX;
var dy = y - touchStartY;
if (!touchMoved && (Math.abs(dx) > 40 || Math.abs(dy) > 40)) {
touchMoved = true;
// Determine direction
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 0) moveTiles('right');else moveTiles('left');
} else {
if (dy > 0) moveTiles('down');else moveTiles('up');
}
// Reset to prevent multiple moves per swipe
touchStartX = undefined;
touchStartY = undefined;
}
};
game.up = function (x, y, obj) {
touchStartX = undefined;
touchStartY = undefined;
touchMoved = false;
};
// --- Game update (not used, but required for tick-based games) ---
game.update = function () {
// No per-frame logic needed
};
// --- Start game ---
function startGame() {
resetGrid();
addRandomTile();
addRandomTile();
scoreTxt.setText(score);
}
// --- Start Page Overlay ---
var startOverlay = new Container();
startOverlay.zIndex = 10000; // Ensure on top
// Semi-transparent dark background
var overlayBg = LK.getAsset('shape', {
width: 2048,
height: 2732,
color: 0x000000,
shape: 'box',
anchorX: 0,
anchorY: 0,
alpha: 0.72,
x: 0,
y: 0
});
startOverlay.addChild(overlayBg);
// Game title
var titleText = new Text2('Fruit Dance', {
size: 180,
fill: "#fff",
align: "center"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 900;
startOverlay.addChild(titleText);
// Scoreboard (shows best score if available, otherwise just 'Score: 0')
var bestScore = 0;
if (typeof storage !== "undefined" && storage.getItem) {
var stored = storage.getItem("fruitdance_bestscore");
if (typeof stored === "number" && stored > 0) bestScore = stored;
}
var scoreboardText = new Text2(bestScore > 0 ? "Best Score: " + bestScore : "Score: 0", {
size: 90,
fill: 0xFFE066,
align: "center"
});
scoreboardText.anchor.set(0.5, 0.5);
scoreboardText.x = 1024;
scoreboardText.y = 1050;
startOverlay.addChild(scoreboardText);
// Subtitle
var subtitleText = new Text2('Merge cosmic tiles to reach the Universe!', {
size: 70,
fill: 0xE0E0E0,
align: "center"
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 1150;
startOverlay.addChild(subtitleText);
// Creator credit
var creatorText = new Text2('Game by Osman Eren', {
size: 54,
fill: 0xCCCCCC,
align: "center"
});
creatorText.anchor.set(0.5, 0.5);
creatorText.x = 1024;
creatorText.y = 1230;
startOverlay.addChild(creatorText);
// Play button
var playBtn = LK.getAsset('shape', {
width: 520,
height: 180,
color: 0x2e8bfa,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400,
alpha: 0.95
});
playBtn.interactive = true;
startOverlay.addChild(playBtn);
var playBtnText = new Text2('Play', {
size: 100,
fill: "#fff",
align: "center"
});
playBtnText.anchor.set(0.5, 0.5);
playBtnText.x = 1024;
playBtnText.y = 1400;
startOverlay.addChild(playBtnText);
// Add overlay to game
game.addChild(startOverlay);
// Disable input until game starts
var inputEnabled = false;
// Play button handler
playBtn.down = function (x, y, obj) {
if (!inputEnabled) return;
// Animate button press
tween(playBtn, {
scaleX: 0.92,
scaleY: 0.92
}, {
duration: 60,
onFinish: function onFinish() {
tween(playBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 60
});
}
});
// Remove overlay and start game
startOverlay.visible = false;
inputEnabled = false;
startGame();
};
// Enable input after a short delay to prevent accidental skip
LK.setTimeout(function () {
inputEnabled = true;
}, 400);
// Prevent swipes before game starts
var origDown = game.down;
var origMove = game.move;
var origUp = game.up;
game.down = function (x, y, obj) {
if (startOverlay.visible) return;
if (origDown) origDown(x, y, obj);
};
game.move = function (x, y, obj) {
if (startOverlay.visible) return;
if (origMove) origMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (startOverlay.visible) return;
if (origUp) origUp(x, y, obj);
};
Furit King!. In-Game asset. 2d. High contrast. No shadows
Orange with face. In-Game asset. 2d. High contrast. No shadows
Cherry with face. In-Game asset. 2d. High contrast. No shadows
Grape with face. In-Game asset. 2d. High contrast. No shadows
Lemon with face. In-Game asset. 2d. High contrast. No shadows
Pear with face. In-Game asset. 2d. High contrast. No shadows
Mango with face. In-Game asset. 2d. High contrast. No shadows
Apple with face. In-Game asset. 2d. High contrast. No shadows
Watermelon with face. In-Game asset. 2d. High contrast. No shadows
Strawberry with face. In-Game asset. 2d. High contrast. No shadows
Banana with face. In-Game asset. 2d. High contrast. No shadows
Let the clouds in the back move. In-Game asset. 2d. High contrast. No shadows