User prompt
You make the numbers even more readable
User prompt
Yes
User prompt
Make the game full screen
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'valueText.style.fill = "#F9F6F2";' Line Number: 295
Code edit (1 edits merged)
Please save this source code
User prompt
2048 Merge Master
Initial prompt
⭐ 2048 Puzzle — How It Works You have a grid (usually 4×4 squares). Each square can hold a number tile (like 2, 4, 8, 16, etc.). Swipe left, right, up, or down. All tiles slide in that direction. When two tiles with the same number touch, they merge into one tile with double the number. Example: 2 + 2 → 4 New tiles (usually 2 or sometimes 4) appear after each move. Goal: Reach the 2048 tile (or keep going for higher scores).
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Grid = Container.expand(function () { var self = Container.call(this); self.size = 4; self.cellSize = 120; self.gap = 10; self.tiles = []; // Initialize 2D array for (var i = 0; i < self.size; i++) { self.tiles[i] = []; for (var j = 0; j < self.size; j++) { self.tiles[i][j] = null; } } var gridBackground = self.attachAsset('grid', { anchorX: 0.5, anchorY: 0.5 }); self.getCellPosition = function (x, y) { var startX = -(self.size - 1) * (self.cellSize + self.gap) / 2; var startY = -(self.size - 1) * (self.cellSize + self.gap) / 2; return { x: startX + x * (self.cellSize + self.gap), y: startY + y * (self.cellSize + self.gap) }; }; self.addTile = function (x, y, value) { if (self.tiles[y][x] !== null) return null; var tile = new Tile(value); tile.gridX = x; tile.gridY = y; var pos = self.getCellPosition(x, y); tile.x = pos.x; tile.y = pos.y; self.tiles[y][x] = tile; self.addChild(tile); return tile; }; self.getEmptyCells = function () { var emptyCells = []; for (var y = 0; y < self.size; y++) { for (var x = 0; x < self.size; x++) { if (self.tiles[y][x] === null) { emptyCells.push({ x: x, y: y }); } } } return emptyCells; }; self.addRandomTile = function () { var emptyCells = self.getEmptyCells(); if (emptyCells.length === 0) return; var randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]; var value = Math.random() < 0.9 ? 2 : 4; self.addTile(randomCell.x, randomCell.y, value); }; self.canMove = function () { // Check for empty cells if (self.getEmptyCells().length > 0) return true; // Check for possible merges for (var y = 0; y < self.size; y++) { for (var x = 0; x < self.size; x++) { var tile = self.tiles[y][x]; if (tile !== null) { // Check right if (x < self.size - 1 && self.tiles[y][x + 1] !== null && self.tiles[y][x + 1].value === tile.value) { return true; } // Check down if (y < self.size - 1 && self.tiles[y + 1][x] !== null && self.tiles[y + 1][x].value === tile.value) { return true; } } } } return false; }; self.moveTiles = function (direction) { var moved = false; var merged = []; // Reset merged flags for (var y = 0; y < self.size; y++) { for (var x = 0; x < self.size; x++) { if (self.tiles[y][x] !== null) { self.tiles[y][x].merged = false; } } } if (direction === 'left') { for (var y = 0; y < self.size; y++) { for (var x = 1; x < self.size; x++) { if (self.tiles[y][x] !== null) { var currentTile = self.tiles[y][x]; var newX = x; // Move as far left as possible while (newX > 0 && self.tiles[y][newX - 1] === null) { newX--; } // Check for merge if (newX > 0 && self.tiles[y][newX - 1] !== null && self.tiles[y][newX - 1].value === currentTile.value && !self.tiles[y][newX - 1].merged) { // Merge self.tiles[y][newX - 1].value *= 2; self.tiles[y][newX - 1].merged = true; self.tiles[y][newX - 1].updateAppearance(); LK.setScore(LK.getScore() + self.tiles[y][newX - 1].value); currentTile.destroy(); self.tiles[y][x] = null; moved = true; if (self.tiles[y][newX - 1].value === 2048) { hasWon = true; } } else if (newX !== x) { // Just move self.tiles[y][newX] = currentTile; self.tiles[y][x] = null; currentTile.gridX = newX; var pos = self.getCellPosition(newX, y); tween(currentTile, { x: pos.x }, { duration: 150 }); moved = true; } } } } } else if (direction === 'right') { for (var y = 0; y < self.size; y++) { for (var x = self.size - 2; x >= 0; x--) { if (self.tiles[y][x] !== null) { var currentTile = self.tiles[y][x]; var newX = x; while (newX < self.size - 1 && self.tiles[y][newX + 1] === null) { newX++; } if (newX < self.size - 1 && self.tiles[y][newX + 1] !== null && self.tiles[y][newX + 1].value === currentTile.value && !self.tiles[y][newX + 1].merged) { self.tiles[y][newX + 1].value *= 2; self.tiles[y][newX + 1].merged = true; self.tiles[y][newX + 1].updateAppearance(); LK.setScore(LK.getScore() + self.tiles[y][newX + 1].value); currentTile.destroy(); self.tiles[y][x] = null; moved = true; if (self.tiles[y][newX + 1].value === 2048) { hasWon = true; } } else if (newX !== x) { self.tiles[y][newX] = currentTile; self.tiles[y][x] = null; currentTile.gridX = newX; var pos = self.getCellPosition(newX, y); tween(currentTile, { x: pos.x }, { duration: 150 }); moved = true; } } } } } else if (direction === 'up') { for (var x = 0; x < self.size; x++) { for (var y = 1; y < self.size; y++) { if (self.tiles[y][x] !== null) { var currentTile = self.tiles[y][x]; var newY = y; while (newY > 0 && self.tiles[newY - 1][x] === null) { newY--; } if (newY > 0 && self.tiles[newY - 1][x] !== null && self.tiles[newY - 1][x].value === currentTile.value && !self.tiles[newY - 1][x].merged) { self.tiles[newY - 1][x].value *= 2; self.tiles[newY - 1][x].merged = true; self.tiles[newY - 1][x].updateAppearance(); LK.setScore(LK.getScore() + self.tiles[newY - 1][x].value); currentTile.destroy(); self.tiles[y][x] = null; moved = true; if (self.tiles[newY - 1][x].value === 2048) { hasWon = true; } } else if (newY !== y) { self.tiles[newY][x] = currentTile; self.tiles[y][x] = null; currentTile.gridY = newY; var pos = self.getCellPosition(x, newY); tween(currentTile, { y: pos.y }, { duration: 150 }); moved = true; } } } } } else if (direction === 'down') { for (var x = 0; x < self.size; x++) { for (var y = self.size - 2; y >= 0; y--) { if (self.tiles[y][x] !== null) { var currentTile = self.tiles[y][x]; var newY = y; while (newY < self.size - 1 && self.tiles[newY + 1][x] === null) { newY++; } if (newY < self.size - 1 && self.tiles[newY + 1][x] !== null && self.tiles[newY + 1][x].value === currentTile.value && !self.tiles[newY + 1][x].merged) { self.tiles[newY + 1][x].value *= 2; self.tiles[newY + 1][x].merged = true; self.tiles[newY + 1][x].updateAppearance(); LK.setScore(LK.getScore() + self.tiles[newY + 1][x].value); currentTile.destroy(); self.tiles[y][x] = null; moved = true; if (self.tiles[newY + 1][x].value === 2048) { hasWon = true; } } else if (newY !== y) { self.tiles[newY][x] = currentTile; self.tiles[y][x] = null; currentTile.gridY = newY; var pos = self.getCellPosition(x, newY); tween(currentTile, { y: pos.y }, { duration: 150 }); moved = true; } } } } } return moved; }; return self; }); var Tile = Container.expand(function (value) { var self = Container.call(this); self.value = value || 2; self.gridX = 0; self.gridY = 0; self.merged = false; var tileBackground = self.attachAsset('tile', { anchorX: 0.5, anchorY: 0.5 }); var valueText = new Text2(self.value.toString(), { size: 48, fill: 0x776E65 }); valueText.anchor.set(0.5, 0.5); self.addChild(valueText); self.updateAppearance = function () { valueText.setText(self.value.toString()); // Color based on value var colors = { 2: 0xEEE4DA, 4: 0xEDE0C8, 8: 0xF2B179, 16: 0xF59563, 32: 0xF67C5F, 64: 0xF65E3B, 128: 0xEDCF72, 256: 0xEDCC61, 512: 0xEDC850, 1024: 0xEDC53F, 2048: 0xEDC22E }; var color = colors[self.value] || 0x3C3A32; tileBackground.tint = color; if (self.value >= 8) { valueText.style.fill = "#F9F6F2"; } }; self.updateAppearance(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xFAF8EF }); /**** * Game Code ****/ var grid; var scoreTxt; var hasWon = false; var gameOver = false; var startX = 0; var startY = 0; var isDragging = false; var minSwipeDistance = 50; // Create grid grid = game.addChild(new Grid()); grid.x = 2048 / 2; grid.y = 2732 / 2; // Create score display scoreTxt = new Text2('Score: 0', { size: 60, fill: 0x776E65 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 150; // Add initial tiles grid.addRandomTile(); grid.addRandomTile(); function updateScore() { scoreTxt.setText('Score: ' + LK.getScore()); } function handleSwipe(direction) { if (gameOver) return; var moved = grid.moveTiles(direction); if (moved) { updateScore(); LK.setTimeout(function () { grid.addRandomTile(); if (hasWon) { LK.showYouWin(); return; } if (!grid.canMove()) { gameOver = true; LK.showGameOver(); } }, 200); } } game.down = function (x, y, obj) { startX = x; startY = y; isDragging = true; }; game.up = function (x, y, obj) { if (!isDragging) return; isDragging = false; var deltaX = x - startX; var deltaY = y - startY; var absX = Math.abs(deltaX); var absY = Math.abs(deltaY); if (Math.max(absX, absY) < minSwipeDistance) return; if (absX > absY) { // Horizontal swipe if (deltaX > 0) { handleSwipe('right'); } else { handleSwipe('left'); } } else { // Vertical swipe if (deltaY > 0) { handleSwipe('down'); } else { handleSwipe('up'); } } }; game.update = function () { // Game loop runs here };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,375 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var Grid = Container.expand(function () {
+ var self = Container.call(this);
+ self.size = 4;
+ self.cellSize = 120;
+ self.gap = 10;
+ self.tiles = [];
+ // Initialize 2D array
+ for (var i = 0; i < self.size; i++) {
+ self.tiles[i] = [];
+ for (var j = 0; j < self.size; j++) {
+ self.tiles[i][j] = null;
+ }
+ }
+ var gridBackground = self.attachAsset('grid', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.getCellPosition = function (x, y) {
+ var startX = -(self.size - 1) * (self.cellSize + self.gap) / 2;
+ var startY = -(self.size - 1) * (self.cellSize + self.gap) / 2;
+ return {
+ x: startX + x * (self.cellSize + self.gap),
+ y: startY + y * (self.cellSize + self.gap)
+ };
+ };
+ self.addTile = function (x, y, value) {
+ if (self.tiles[y][x] !== null) return null;
+ var tile = new Tile(value);
+ tile.gridX = x;
+ tile.gridY = y;
+ var pos = self.getCellPosition(x, y);
+ tile.x = pos.x;
+ tile.y = pos.y;
+ self.tiles[y][x] = tile;
+ self.addChild(tile);
+ return tile;
+ };
+ self.getEmptyCells = function () {
+ var emptyCells = [];
+ for (var y = 0; y < self.size; y++) {
+ for (var x = 0; x < self.size; x++) {
+ if (self.tiles[y][x] === null) {
+ emptyCells.push({
+ x: x,
+ y: y
+ });
+ }
+ }
+ }
+ return emptyCells;
+ };
+ self.addRandomTile = function () {
+ var emptyCells = self.getEmptyCells();
+ if (emptyCells.length === 0) return;
+ var randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
+ var value = Math.random() < 0.9 ? 2 : 4;
+ self.addTile(randomCell.x, randomCell.y, value);
+ };
+ self.canMove = function () {
+ // Check for empty cells
+ if (self.getEmptyCells().length > 0) return true;
+ // Check for possible merges
+ for (var y = 0; y < self.size; y++) {
+ for (var x = 0; x < self.size; x++) {
+ var tile = self.tiles[y][x];
+ if (tile !== null) {
+ // Check right
+ if (x < self.size - 1 && self.tiles[y][x + 1] !== null && self.tiles[y][x + 1].value === tile.value) {
+ return true;
+ }
+ // Check down
+ if (y < self.size - 1 && self.tiles[y + 1][x] !== null && self.tiles[y + 1][x].value === tile.value) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ };
+ self.moveTiles = function (direction) {
+ var moved = false;
+ var merged = [];
+ // Reset merged flags
+ for (var y = 0; y < self.size; y++) {
+ for (var x = 0; x < self.size; x++) {
+ if (self.tiles[y][x] !== null) {
+ self.tiles[y][x].merged = false;
+ }
+ }
+ }
+ if (direction === 'left') {
+ for (var y = 0; y < self.size; y++) {
+ for (var x = 1; x < self.size; x++) {
+ if (self.tiles[y][x] !== null) {
+ var currentTile = self.tiles[y][x];
+ var newX = x;
+ // Move as far left as possible
+ while (newX > 0 && self.tiles[y][newX - 1] === null) {
+ newX--;
+ }
+ // Check for merge
+ if (newX > 0 && self.tiles[y][newX - 1] !== null && self.tiles[y][newX - 1].value === currentTile.value && !self.tiles[y][newX - 1].merged) {
+ // Merge
+ self.tiles[y][newX - 1].value *= 2;
+ self.tiles[y][newX - 1].merged = true;
+ self.tiles[y][newX - 1].updateAppearance();
+ LK.setScore(LK.getScore() + self.tiles[y][newX - 1].value);
+ currentTile.destroy();
+ self.tiles[y][x] = null;
+ moved = true;
+ if (self.tiles[y][newX - 1].value === 2048) {
+ hasWon = true;
+ }
+ } else if (newX !== x) {
+ // Just move
+ self.tiles[y][newX] = currentTile;
+ self.tiles[y][x] = null;
+ currentTile.gridX = newX;
+ var pos = self.getCellPosition(newX, y);
+ tween(currentTile, {
+ x: pos.x
+ }, {
+ duration: 150
+ });
+ moved = true;
+ }
+ }
+ }
+ }
+ } else if (direction === 'right') {
+ for (var y = 0; y < self.size; y++) {
+ for (var x = self.size - 2; x >= 0; x--) {
+ if (self.tiles[y][x] !== null) {
+ var currentTile = self.tiles[y][x];
+ var newX = x;
+ while (newX < self.size - 1 && self.tiles[y][newX + 1] === null) {
+ newX++;
+ }
+ if (newX < self.size - 1 && self.tiles[y][newX + 1] !== null && self.tiles[y][newX + 1].value === currentTile.value && !self.tiles[y][newX + 1].merged) {
+ self.tiles[y][newX + 1].value *= 2;
+ self.tiles[y][newX + 1].merged = true;
+ self.tiles[y][newX + 1].updateAppearance();
+ LK.setScore(LK.getScore() + self.tiles[y][newX + 1].value);
+ currentTile.destroy();
+ self.tiles[y][x] = null;
+ moved = true;
+ if (self.tiles[y][newX + 1].value === 2048) {
+ hasWon = true;
+ }
+ } else if (newX !== x) {
+ self.tiles[y][newX] = currentTile;
+ self.tiles[y][x] = null;
+ currentTile.gridX = newX;
+ var pos = self.getCellPosition(newX, y);
+ tween(currentTile, {
+ x: pos.x
+ }, {
+ duration: 150
+ });
+ moved = true;
+ }
+ }
+ }
+ }
+ } else if (direction === 'up') {
+ for (var x = 0; x < self.size; x++) {
+ for (var y = 1; y < self.size; y++) {
+ if (self.tiles[y][x] !== null) {
+ var currentTile = self.tiles[y][x];
+ var newY = y;
+ while (newY > 0 && self.tiles[newY - 1][x] === null) {
+ newY--;
+ }
+ if (newY > 0 && self.tiles[newY - 1][x] !== null && self.tiles[newY - 1][x].value === currentTile.value && !self.tiles[newY - 1][x].merged) {
+ self.tiles[newY - 1][x].value *= 2;
+ self.tiles[newY - 1][x].merged = true;
+ self.tiles[newY - 1][x].updateAppearance();
+ LK.setScore(LK.getScore() + self.tiles[newY - 1][x].value);
+ currentTile.destroy();
+ self.tiles[y][x] = null;
+ moved = true;
+ if (self.tiles[newY - 1][x].value === 2048) {
+ hasWon = true;
+ }
+ } else if (newY !== y) {
+ self.tiles[newY][x] = currentTile;
+ self.tiles[y][x] = null;
+ currentTile.gridY = newY;
+ var pos = self.getCellPosition(x, newY);
+ tween(currentTile, {
+ y: pos.y
+ }, {
+ duration: 150
+ });
+ moved = true;
+ }
+ }
+ }
+ }
+ } else if (direction === 'down') {
+ for (var x = 0; x < self.size; x++) {
+ for (var y = self.size - 2; y >= 0; y--) {
+ if (self.tiles[y][x] !== null) {
+ var currentTile = self.tiles[y][x];
+ var newY = y;
+ while (newY < self.size - 1 && self.tiles[newY + 1][x] === null) {
+ newY++;
+ }
+ if (newY < self.size - 1 && self.tiles[newY + 1][x] !== null && self.tiles[newY + 1][x].value === currentTile.value && !self.tiles[newY + 1][x].merged) {
+ self.tiles[newY + 1][x].value *= 2;
+ self.tiles[newY + 1][x].merged = true;
+ self.tiles[newY + 1][x].updateAppearance();
+ LK.setScore(LK.getScore() + self.tiles[newY + 1][x].value);
+ currentTile.destroy();
+ self.tiles[y][x] = null;
+ moved = true;
+ if (self.tiles[newY + 1][x].value === 2048) {
+ hasWon = true;
+ }
+ } else if (newY !== y) {
+ self.tiles[newY][x] = currentTile;
+ self.tiles[y][x] = null;
+ currentTile.gridY = newY;
+ var pos = self.getCellPosition(x, newY);
+ tween(currentTile, {
+ y: pos.y
+ }, {
+ duration: 150
+ });
+ moved = true;
+ }
+ }
+ }
+ }
+ }
+ return moved;
+ };
+ return self;
+});
+var Tile = Container.expand(function (value) {
+ var self = Container.call(this);
+ self.value = value || 2;
+ self.gridX = 0;
+ self.gridY = 0;
+ self.merged = false;
+ var tileBackground = self.attachAsset('tile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var valueText = new Text2(self.value.toString(), {
+ size: 48,
+ fill: 0x776E65
+ });
+ valueText.anchor.set(0.5, 0.5);
+ self.addChild(valueText);
+ self.updateAppearance = function () {
+ valueText.setText(self.value.toString());
+ // Color based on value
+ var colors = {
+ 2: 0xEEE4DA,
+ 4: 0xEDE0C8,
+ 8: 0xF2B179,
+ 16: 0xF59563,
+ 32: 0xF67C5F,
+ 64: 0xF65E3B,
+ 128: 0xEDCF72,
+ 256: 0xEDCC61,
+ 512: 0xEDC850,
+ 1024: 0xEDC53F,
+ 2048: 0xEDC22E
+ };
+ var color = colors[self.value] || 0x3C3A32;
+ tileBackground.tint = color;
+ if (self.value >= 8) {
+ valueText.style.fill = "#F9F6F2";
+ }
+ };
+ self.updateAppearance();
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xFAF8EF
+});
+
+/****
+* Game Code
+****/
+var grid;
+var scoreTxt;
+var hasWon = false;
+var gameOver = false;
+var startX = 0;
+var startY = 0;
+var isDragging = false;
+var minSwipeDistance = 50;
+// Create grid
+grid = game.addChild(new Grid());
+grid.x = 2048 / 2;
+grid.y = 2732 / 2;
+// Create score display
+scoreTxt = new Text2('Score: 0', {
+ size: 60,
+ fill: 0x776E65
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+scoreTxt.y = 150;
+// Add initial tiles
+grid.addRandomTile();
+grid.addRandomTile();
+function updateScore() {
+ scoreTxt.setText('Score: ' + LK.getScore());
+}
+function handleSwipe(direction) {
+ if (gameOver) return;
+ var moved = grid.moveTiles(direction);
+ if (moved) {
+ updateScore();
+ LK.setTimeout(function () {
+ grid.addRandomTile();
+ if (hasWon) {
+ LK.showYouWin();
+ return;
+ }
+ if (!grid.canMove()) {
+ gameOver = true;
+ LK.showGameOver();
+ }
+ }, 200);
+ }
+}
+game.down = function (x, y, obj) {
+ startX = x;
+ startY = y;
+ isDragging = true;
+};
+game.up = function (x, y, obj) {
+ if (!isDragging) return;
+ isDragging = false;
+ var deltaX = x - startX;
+ var deltaY = y - startY;
+ var absX = Math.abs(deltaX);
+ var absY = Math.abs(deltaY);
+ if (Math.max(absX, absY) < minSwipeDistance) return;
+ if (absX > absY) {
+ // Horizontal swipe
+ if (deltaX > 0) {
+ handleSwipe('right');
+ } else {
+ handleSwipe('left');
+ }
+ } else {
+ // Vertical swipe
+ if (deltaY > 0) {
+ handleSwipe('down');
+ } else {
+ handleSwipe('up');
+ }
+ }
+};
+game.update = function () {
+ // Game loop runs here
+};
\ No newline at end of file