/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Tile class: represents a single tile on the board var Tile = Container.expand(function () { var self = Container.call(this); // Properties self.value = 0; // 0 means empty self.row = 0; self.col = 0; self.tileBG = null; self.tileText = null; // Set up tile self.setValue = function (val) { self.value = val; // Remove previous children if any if (self.tileBG) { self.removeChild(self.tileBG); self.tileBG = null; } if (self.tileText) { self.removeChild(self.tileText); self.tileText = null; } // Choose asset based on value var assetId = 'tile'; if (val === 0) { assetId = 'tileBG'; } else if (val === 2) { assetId = 'tile2'; } else if (val === 4) { assetId = 'tile4'; } else if (val === 8) { assetId = 'tile8'; } else if (val === 16) { assetId = 'tile16'; } else if (val === 32) { assetId = 'tile32'; } else if (val === 64) { assetId = 'tile64'; } else if (val === 128) { assetId = 'tile128'; } else if (val === 256) { assetId = 'tile256'; } else if (val === 512) { assetId = 'tile512'; } else if (val === 1024) { assetId = 'tile1024'; } else if (val === 2048) { assetId = 'tile2048'; } self.tileBG = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); if (val > 0) { var textColor = "#776e65"; if (val >= 8) textColor = "#f9f6f2"; self.tileText = new Text2(val + '', { size: 120, fill: textColor }); self.tileText.anchor.set(0.5, 0.5); self.addChild(self.tileText); } }; // Animate pop self.pop = function () { self.scaleX = 0.7; self.scaleY = 0.7; tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xfaf8ef }); /**** * Game Code ****/ // Tiles: We'll use colored boxes for tiles, and white for empty background. // Board constants var GRID_SIZE = 4; var TILE_SIZE = 400; var TILE_MARGIN = 20; var BOARD_SIZE = GRID_SIZE * TILE_SIZE + (GRID_SIZE + 1) * TILE_MARGIN; var BOARD_X = (2048 - BOARD_SIZE) / 2; var BOARD_Y = (2732 - BOARD_SIZE) / 2 + 100; // +100 to avoid top menu // Board background var boardBG = LK.getAsset('boardBG', { anchorX: 0, anchorY: 0, x: BOARD_X, y: BOARD_Y }); game.addChild(boardBG); // 2D array of tiles var tiles = []; // 2D array of tile values (for logic) var tileVals = []; // For swipe detection var touchStartX = 0, touchStartY = 0, touchEndX = 0, touchEndY = 0, isTouching = false; // Score var score = 0; var bestScore = 0; // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0xBBADA0 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Best score text var bestScoreTxt = new Text2('BEST: 0', { size: 60, fill: 0xBBADA0 }); bestScoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bestScoreTxt); bestScoreTxt.y = 130; // Position GUI elements scoreTxt.x = 2048 / 2; scoreTxt.y = 20; bestScoreTxt.x = 2048 / 2; bestScoreTxt.y = 150; // Initialize board function initBoard() { // Remove old tiles if any for (var r = 0; r < GRID_SIZE; r++) { for (var c = 0; c < GRID_SIZE; c++) { if (tiles[r] && tiles[r][c]) { tiles[r][c].destroy(); } } } tiles = []; tileVals = []; for (var r = 0; r < GRID_SIZE; r++) { tiles[r] = []; tileVals[r] = []; for (var c = 0; c < GRID_SIZE; c++) { var tile = new Tile(); tile.row = r; tile.col = c; tile.setValue(0); // Position tile.x = BOARD_X + TILE_MARGIN + c * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2; tile.y = BOARD_Y + TILE_MARGIN + r * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2; tile.scaleX = 1; tile.scaleY = 1; game.addChild(tile); tiles[r][c] = tile; tileVals[r][c] = 0; } } score = 0; updateScore(); addRandomTile(); addRandomTile(); } // Add a random tile (2 or 4) to an empty spot function addRandomTile() { var empties = []; for (var r = 0; r < GRID_SIZE; r++) { for (var c = 0; c < GRID_SIZE; c++) { if (tileVals[r][c] === 0) { empties.push({ r: r, c: c }); } } } if (empties.length === 0) return; var idx = Math.floor(Math.random() * empties.length); var pos = empties[idx]; var val = Math.random() < 0.9 ? 2 : 4; tileVals[pos.r][pos.c] = val; tiles[pos.r][pos.c].setValue(val); tiles[pos.r][pos.c].pop(); } // Update all tile visuals from tileVals function updateTiles() { for (var r = 0; r < GRID_SIZE; r++) { for (var c = 0; c < GRID_SIZE; c++) { tiles[r][c].setValue(tileVals[r][c]); } } } // Update score display function updateScore() { scoreTxt.setText(score + ''); if (score > bestScore) { bestScore = score; } bestScoreTxt.setText('BEST: ' + bestScore); LK.setScore(score); } // Check if any moves are possible function canMove() { for (var r = 0; r < GRID_SIZE; r++) { for (var c = 0; c < GRID_SIZE; c++) { if (tileVals[r][c] === 0) return true; if (c < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r][c + 1]) return true; if (r < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r + 1][c]) return true; } } return false; } // Check if 2048 tile exists function has2048() { for (var r = 0; r < GRID_SIZE; r++) { for (var c = 0; c < GRID_SIZE; c++) { if (tileVals[r][c] === 2048) return true; } } return false; } // Move logic function move(direction) { // direction: 'left', 'right', 'up', 'down' var moved = false; var merged = []; for (var r = 0; r < GRID_SIZE; r++) { merged[r] = []; for (var c = 0; c < GRID_SIZE; c++) { merged[r][c] = false; } } var start, end, step; if (direction === 'left') { for (var r = 0; r < GRID_SIZE; r++) { for (var c = 1; c < GRID_SIZE; c++) { if (tileVals[r][c] === 0) continue; var target = c; while (target > 0 && tileVals[r][target - 1] === 0) { target--; } if (target > 0 && tileVals[r][target - 1] === tileVals[r][c] && !merged[r][target - 1]) { // Merge tileVals[r][target - 1] *= 2; score += tileVals[r][target - 1]; tileVals[r][c] = 0; merged[r][target - 1] = true; moved = true; tiles[r][target - 1].pop(); } else if (target !== c) { // Move tileVals[r][target] = tileVals[r][c]; tileVals[r][c] = 0; moved = true; } } } } else if (direction === 'right') { for (var r = 0; r < GRID_SIZE; r++) { for (var c = GRID_SIZE - 2; c >= 0; c--) { if (tileVals[r][c] === 0) continue; var target = c; while (target < GRID_SIZE - 1 && tileVals[r][target + 1] === 0) { target++; } if (target < GRID_SIZE - 1 && tileVals[r][target + 1] === tileVals[r][c] && !merged[r][target + 1]) { // Merge tileVals[r][target + 1] *= 2; score += tileVals[r][target + 1]; tileVals[r][c] = 0; merged[r][target + 1] = true; moved = true; tiles[r][target + 1].pop(); } else if (target !== c) { // Move tileVals[r][target] = tileVals[r][c]; tileVals[r][c] = 0; moved = true; } } } } else if (direction === 'up') { for (var c = 0; c < GRID_SIZE; c++) { for (var r = 1; r < GRID_SIZE; r++) { if (tileVals[r][c] === 0) continue; var target = r; while (target > 0 && tileVals[target - 1][c] === 0) { target--; } if (target > 0 && tileVals[target - 1][c] === tileVals[r][c] && !merged[target - 1][c]) { // Merge tileVals[target - 1][c] *= 2; score += tileVals[target - 1][c]; tileVals[r][c] = 0; merged[target - 1][c] = true; moved = true; tiles[target - 1][c].pop(); } else if (target !== r) { // Move tileVals[target][c] = tileVals[r][c]; tileVals[r][c] = 0; moved = true; } } } } else if (direction === 'down') { for (var c = 0; c < GRID_SIZE; c++) { for (var r = GRID_SIZE - 2; r >= 0; r--) { if (tileVals[r][c] === 0) continue; var target = r; while (target < GRID_SIZE - 1 && tileVals[target + 1][c] === 0) { target++; } if (target < GRID_SIZE - 1 && tileVals[target + 1][c] === tileVals[r][c] && !merged[target + 1][c]) { // Merge tileVals[target + 1][c] *= 2; score += tileVals[target + 1][c]; tileVals[r][c] = 0; merged[target + 1][c] = true; moved = true; tiles[target + 1][c].pop(); } else if (target !== r) { // Move tileVals[target][c] = tileVals[r][c]; tileVals[r][c] = 0; moved = true; } } } } if (moved) { addRandomTile(); updateTiles(); updateScore(); if (has2048()) { LK.showYouWin(); } else if (!canMove()) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } } // Touch/drag/swipe handling game.down = function (x, y, obj) { // Only start if inside board area if (x >= BOARD_X && x <= BOARD_X + BOARD_SIZE && y >= BOARD_Y && y <= BOARD_Y + BOARD_SIZE) { touchStartX = x; touchStartY = y; isTouching = true; } }; game.move = function (x, y, obj) { if (!isTouching) return; touchEndX = x; touchEndY = y; }; game.up = function (x, y, obj) { if (!isTouching) return; var dx = touchEndX - touchStartX; var dy = touchEndY - touchStartY; var absDx = Math.abs(dx); var absDy = Math.abs(dy); if (absDx > 50 || absDy > 50) { if (absDx > absDy) { if (dx > 0) { move('right'); } else { move('left'); } } else { if (dy > 0) { move('down'); } else { move('up'); } } } isTouching = false; touchStartX = 0; touchStartY = 0; touchEndX = 0; touchEndY = 0; }; // Reset game on game over or win game.on('reset', function () { initBoard(); }); // Initialize initBoard();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,406 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Tile class: represents a single tile on the board
+var Tile = Container.expand(function () {
+ var self = Container.call(this);
+ // Properties
+ self.value = 0; // 0 means empty
+ self.row = 0;
+ self.col = 0;
+ self.tileBG = null;
+ self.tileText = null;
+ // Set up tile
+ self.setValue = function (val) {
+ self.value = val;
+ // Remove previous children if any
+ if (self.tileBG) {
+ self.removeChild(self.tileBG);
+ self.tileBG = null;
+ }
+ if (self.tileText) {
+ self.removeChild(self.tileText);
+ self.tileText = null;
+ }
+ // Choose asset based on value
+ var assetId = 'tile';
+ if (val === 0) {
+ assetId = 'tileBG';
+ } else if (val === 2) {
+ assetId = 'tile2';
+ } else if (val === 4) {
+ assetId = 'tile4';
+ } else if (val === 8) {
+ assetId = 'tile8';
+ } else if (val === 16) {
+ assetId = 'tile16';
+ } else if (val === 32) {
+ assetId = 'tile32';
+ } else if (val === 64) {
+ assetId = 'tile64';
+ } else if (val === 128) {
+ assetId = 'tile128';
+ } else if (val === 256) {
+ assetId = 'tile256';
+ } else if (val === 512) {
+ assetId = 'tile512';
+ } else if (val === 1024) {
+ assetId = 'tile1024';
+ } else if (val === 2048) {
+ assetId = 'tile2048';
+ }
+ self.tileBG = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ if (val > 0) {
+ var textColor = "#776e65";
+ if (val >= 8) textColor = "#f9f6f2";
+ self.tileText = new Text2(val + '', {
+ size: 120,
+ fill: textColor
+ });
+ self.tileText.anchor.set(0.5, 0.5);
+ self.addChild(self.tileText);
+ }
+ };
+ // Animate pop
+ self.pop = function () {
+ self.scaleX = 0.7;
+ self.scaleY = 0.7;
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 120,
+ easing: tween.easeOut
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xfaf8ef
+});
+
+/****
+* Game Code
+****/
+// Tiles: We'll use colored boxes for tiles, and white for empty background.
+// Board constants
+var GRID_SIZE = 4;
+var TILE_SIZE = 400;
+var TILE_MARGIN = 20;
+var BOARD_SIZE = GRID_SIZE * TILE_SIZE + (GRID_SIZE + 1) * TILE_MARGIN;
+var BOARD_X = (2048 - BOARD_SIZE) / 2;
+var BOARD_Y = (2732 - BOARD_SIZE) / 2 + 100; // +100 to avoid top menu
+// Board background
+var boardBG = LK.getAsset('boardBG', {
+ anchorX: 0,
+ anchorY: 0,
+ x: BOARD_X,
+ y: BOARD_Y
+});
+game.addChild(boardBG);
+// 2D array of tiles
+var tiles = [];
+// 2D array of tile values (for logic)
+var tileVals = [];
+// For swipe detection
+var touchStartX = 0,
+ touchStartY = 0,
+ touchEndX = 0,
+ touchEndY = 0,
+ isTouching = false;
+// Score
+var score = 0;
+var bestScore = 0;
+// Score text
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xBBADA0
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Best score text
+var bestScoreTxt = new Text2('BEST: 0', {
+ size: 60,
+ fill: 0xBBADA0
+});
+bestScoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(bestScoreTxt);
+bestScoreTxt.y = 130;
+// Position GUI elements
+scoreTxt.x = 2048 / 2;
+scoreTxt.y = 20;
+bestScoreTxt.x = 2048 / 2;
+bestScoreTxt.y = 150;
+// Initialize board
+function initBoard() {
+ // Remove old tiles if any
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ if (tiles[r] && tiles[r][c]) {
+ tiles[r][c].destroy();
+ }
+ }
+ }
+ tiles = [];
+ tileVals = [];
+ for (var r = 0; r < GRID_SIZE; r++) {
+ tiles[r] = [];
+ tileVals[r] = [];
+ for (var c = 0; c < GRID_SIZE; c++) {
+ var tile = new Tile();
+ tile.row = r;
+ tile.col = c;
+ tile.setValue(0);
+ // Position
+ tile.x = BOARD_X + TILE_MARGIN + c * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
+ tile.y = BOARD_Y + TILE_MARGIN + r * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
+ tile.scaleX = 1;
+ tile.scaleY = 1;
+ game.addChild(tile);
+ tiles[r][c] = tile;
+ tileVals[r][c] = 0;
+ }
+ }
+ score = 0;
+ updateScore();
+ addRandomTile();
+ addRandomTile();
+}
+// Add a random tile (2 or 4) to an empty spot
+function addRandomTile() {
+ var empties = [];
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ if (tileVals[r][c] === 0) {
+ empties.push({
+ r: r,
+ c: c
+ });
+ }
+ }
+ }
+ if (empties.length === 0) return;
+ var idx = Math.floor(Math.random() * empties.length);
+ var pos = empties[idx];
+ var val = Math.random() < 0.9 ? 2 : 4;
+ tileVals[pos.r][pos.c] = val;
+ tiles[pos.r][pos.c].setValue(val);
+ tiles[pos.r][pos.c].pop();
+}
+// Update all tile visuals from tileVals
+function updateTiles() {
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ tiles[r][c].setValue(tileVals[r][c]);
+ }
+ }
+}
+// Update score display
+function updateScore() {
+ scoreTxt.setText(score + '');
+ if (score > bestScore) {
+ bestScore = score;
+ }
+ bestScoreTxt.setText('BEST: ' + bestScore);
+ LK.setScore(score);
+}
+// Check if any moves are possible
+function canMove() {
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ if (tileVals[r][c] === 0) return true;
+ if (c < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r][c + 1]) return true;
+ if (r < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r + 1][c]) return true;
+ }
+ }
+ return false;
+}
+// Check if 2048 tile exists
+function has2048() {
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ if (tileVals[r][c] === 2048) return true;
+ }
+ }
+ return false;
+}
+// Move logic
+function move(direction) {
+ // direction: 'left', 'right', 'up', 'down'
+ var moved = false;
+ var merged = [];
+ for (var r = 0; r < GRID_SIZE; r++) {
+ merged[r] = [];
+ for (var c = 0; c < GRID_SIZE; c++) {
+ merged[r][c] = false;
+ }
+ }
+ var start, end, step;
+ if (direction === 'left') {
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = 1; c < GRID_SIZE; c++) {
+ if (tileVals[r][c] === 0) continue;
+ var target = c;
+ while (target > 0 && tileVals[r][target - 1] === 0) {
+ target--;
+ }
+ if (target > 0 && tileVals[r][target - 1] === tileVals[r][c] && !merged[r][target - 1]) {
+ // Merge
+ tileVals[r][target - 1] *= 2;
+ score += tileVals[r][target - 1];
+ tileVals[r][c] = 0;
+ merged[r][target - 1] = true;
+ moved = true;
+ tiles[r][target - 1].pop();
+ } else if (target !== c) {
+ // Move
+ tileVals[r][target] = tileVals[r][c];
+ tileVals[r][c] = 0;
+ moved = true;
+ }
+ }
+ }
+ } else if (direction === 'right') {
+ for (var r = 0; r < GRID_SIZE; r++) {
+ for (var c = GRID_SIZE - 2; c >= 0; c--) {
+ if (tileVals[r][c] === 0) continue;
+ var target = c;
+ while (target < GRID_SIZE - 1 && tileVals[r][target + 1] === 0) {
+ target++;
+ }
+ if (target < GRID_SIZE - 1 && tileVals[r][target + 1] === tileVals[r][c] && !merged[r][target + 1]) {
+ // Merge
+ tileVals[r][target + 1] *= 2;
+ score += tileVals[r][target + 1];
+ tileVals[r][c] = 0;
+ merged[r][target + 1] = true;
+ moved = true;
+ tiles[r][target + 1].pop();
+ } else if (target !== c) {
+ // Move
+ tileVals[r][target] = tileVals[r][c];
+ tileVals[r][c] = 0;
+ moved = true;
+ }
+ }
+ }
+ } else if (direction === 'up') {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ for (var r = 1; r < GRID_SIZE; r++) {
+ if (tileVals[r][c] === 0) continue;
+ var target = r;
+ while (target > 0 && tileVals[target - 1][c] === 0) {
+ target--;
+ }
+ if (target > 0 && tileVals[target - 1][c] === tileVals[r][c] && !merged[target - 1][c]) {
+ // Merge
+ tileVals[target - 1][c] *= 2;
+ score += tileVals[target - 1][c];
+ tileVals[r][c] = 0;
+ merged[target - 1][c] = true;
+ moved = true;
+ tiles[target - 1][c].pop();
+ } else if (target !== r) {
+ // Move
+ tileVals[target][c] = tileVals[r][c];
+ tileVals[r][c] = 0;
+ moved = true;
+ }
+ }
+ }
+ } else if (direction === 'down') {
+ for (var c = 0; c < GRID_SIZE; c++) {
+ for (var r = GRID_SIZE - 2; r >= 0; r--) {
+ if (tileVals[r][c] === 0) continue;
+ var target = r;
+ while (target < GRID_SIZE - 1 && tileVals[target + 1][c] === 0) {
+ target++;
+ }
+ if (target < GRID_SIZE - 1 && tileVals[target + 1][c] === tileVals[r][c] && !merged[target + 1][c]) {
+ // Merge
+ tileVals[target + 1][c] *= 2;
+ score += tileVals[target + 1][c];
+ tileVals[r][c] = 0;
+ merged[target + 1][c] = true;
+ moved = true;
+ tiles[target + 1][c].pop();
+ } else if (target !== r) {
+ // Move
+ tileVals[target][c] = tileVals[r][c];
+ tileVals[r][c] = 0;
+ moved = true;
+ }
+ }
+ }
+ }
+ if (moved) {
+ addRandomTile();
+ updateTiles();
+ updateScore();
+ if (has2048()) {
+ LK.showYouWin();
+ } else if (!canMove()) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ }
+ }
+}
+// Touch/drag/swipe handling
+game.down = function (x, y, obj) {
+ // Only start if inside board area
+ if (x >= BOARD_X && x <= BOARD_X + BOARD_SIZE && y >= BOARD_Y && y <= BOARD_Y + BOARD_SIZE) {
+ touchStartX = x;
+ touchStartY = y;
+ isTouching = true;
+ }
+};
+game.move = function (x, y, obj) {
+ if (!isTouching) return;
+ touchEndX = x;
+ touchEndY = y;
+};
+game.up = function (x, y, obj) {
+ if (!isTouching) return;
+ var dx = touchEndX - touchStartX;
+ var dy = touchEndY - touchStartY;
+ var absDx = Math.abs(dx);
+ var absDy = Math.abs(dy);
+ if (absDx > 50 || absDy > 50) {
+ if (absDx > absDy) {
+ if (dx > 0) {
+ move('right');
+ } else {
+ move('left');
+ }
+ } else {
+ if (dy > 0) {
+ move('down');
+ } else {
+ move('up');
+ }
+ }
+ }
+ isTouching = false;
+ touchStartX = 0;
+ touchStartY = 0;
+ touchEndX = 0;
+ touchEndY = 0;
+};
+// Reset game on game over or win
+game.on('reset', function () {
+ initBoard();
+});
+// Initialize
+initBoard();
\ No newline at end of file