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: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // --- Draw grid background --- var gridBg = LK.getAsset('gridBg', { anchorX: 0, anchorY: 0, x: gridX, y: gridY, width: gridWidth, height: gridHeight }); game.addChild(gridBg); // --- 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); 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); 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(); } 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); } startGame();
===================================================================
--- original.js
+++ change.js
@@ -103,35 +103,148 @@
self.col = col;
self.x = gridX + col * cellSize + cellSize / 2;
self.y = gridY + row * cellSize + cellSize / 2;
};
- // Add dancing animation (continuous scale up/down)
+ // Add dancing animation (continuous, unique per value)
self.startDancing = function () {
// Cancel any previous tweens on scale
tween.stop(self, {
scaleX: true,
scaleY: true
});
- // Start the dance loop
+ // 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: 1.12,
- scaleY: 0.88
+ scaleX: dance.sx1,
+ scaleY: dance.sy1
}, {
- duration: 220,
- easing: tween.easeInOut,
+ duration: dance.dur1,
+ easing: dance.ease1,
onFinish: function onFinish() {
danceDown();
}
});
}
function danceDown() {
tween(self, {
- scaleX: 0.92,
- scaleY: 1.08
+ scaleX: dance.sx2,
+ scaleY: dance.sy2
}, {
- duration: 220,
- easing: tween.easeInOut,
+ duration: dance.dur2,
+ easing: dance.ease2,
onFinish: function onFinish() {
danceUp();
}
});
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