User prompt
I don't want to drag and drop tiles. I just want to click it to add the bar
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (prevGrid[row][col]) {' Line Number: 326
User prompt
Make it harder every level
User prompt
I want to see my level and my point
User prompt
Make the layer system
User prompt
No every color tile need to 3 or it's multiples
User prompt
I can't clear the layer because tiles not matching at the end. Make tile count 3 or it's multiplication
User prompt
I want a multiple layer design. Every level layers gonna increase
User prompt
I want to select tiles and grab to bottom bar to match same shaped tiles
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'row')' in or related to this line: 'var temp = board[tileA.row][tileA.col];' Line Number: 132
Code edit (1 edits merged)
Please save this source code
User prompt
Tile Match Mania
Initial prompt
Make me a basic tile matching game for mobile devices
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Tile class
var Tile = Container.expand(function () {
var self = Container.call(this);
// Properties
self.row = 0;
self.col = 0;
self.colorId = 0; // 0-5
self.isMoving = false;
// Attach asset
self.setColor = function (colorId) {
self.colorId = colorId;
if (self.tileAsset) {
self.removeChild(self.tileAsset);
}
var colorNames = ['red', 'blue', 'green', 'yellow', 'purple', 'orange'];
var assetId = 'tile_' + colorNames[colorId];
self.tileAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
// Animate to a new position (row, col)
self.moveTo = function (row, col, duration, _onFinish) {
self.row = row;
self.col = col;
self.isMoving = true;
var targetX = boardOffsetX + col * tileSize + tileSize / 2;
var targetY = boardOffsetY + row * tileSize + tileSize / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.isMoving = false;
if (_onFinish) _onFinish();
}
});
};
// Instantly set position
self.setPosition = function (row, col) {
self.row = row;
self.col = col;
self.x = boardOffsetX + col * tileSize + tileSize / 2;
self.y = boardOffsetY + row * tileSize + tileSize / 2;
};
// Flash when matched
self.flash = function (_onFinish2) {
tween(self.tileAsset, {
alpha: 0
}, {
duration: 150,
easing: tween.linear,
onFinish: function onFinish() {
self.tileAsset.alpha = 1;
if (_onFinish2) _onFinish2();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Simple pop sound for matches
// 6 tile colors for variety
// --- Board settings ---
var boardRows = 8;
var boardCols = 8;
var tileSize = 180;
var boardWidth = boardCols * tileSize;
var boardHeight = boardRows * tileSize;
var boardOffsetX = Math.floor((2048 - boardWidth) / 2);
var boardOffsetY = Math.floor((2732 - boardHeight) / 2);
// --- Game state ---
var board = []; // 2D array [row][col] of Tile
var tiles = []; // Flat array of all Tile objects
var selectedTile = null;
var swappingTile = null;
var isSwapping = false;
var isProcessing = false;
var score = 0;
var timeLeft = 60; // seconds
var timerInterval = null;
var scoreTxt = null;
var timerTxt = null;
// --- Utility functions ---
function randomColorId() {
return Math.floor(Math.random() * 6);
}
// Check if two tiles are adjacent
function areAdjacent(tileA, tileB) {
var dr = Math.abs(tileA.row - tileB.row);
var dc = Math.abs(tileA.col - tileB.col);
return dr + dc === 1;
}
// Swap two tiles in board and animate
function swapTiles(tileA, tileB, animate, onFinish) {
// Swap in board array
var temp = board[tileA.row][tileA.col];
board[tileA.row][tileA.col] = board[tileB.row][tileB.col];
board[tileB.row][tileB.col] = temp;
// Swap row/col
var tempRow = tileA.row,
tempCol = tileA.col;
if (animate) {
tileA.moveTo(tileB.row, tileB.col, 120);
tileB.moveTo(tempRow, tempCol, 120, onFinish);
} else {
tileA.setPosition(tileB.row, tileB.col);
tileB.setPosition(tempRow, tempCol);
if (onFinish) onFinish();
}
var trow = tileA.row,
tcol = tileA.col;
tileA.row = tileB.row;
tileA.col = tileB.col;
tileB.row = tempRow;
tileB.col = tempCol;
}
// Find all matches on the board. Returns array of arrays of matched tiles.
function findAllMatches() {
var matches = [];
// Horizontal
for (var r = 0; r < boardRows; r++) {
var run = [board[r][0]];
for (var c = 1; c < boardCols; c++) {
if (board[r][c].colorId === board[r][c - 1].colorId) {
run.push(board[r][c]);
} else {
if (run.length >= 3) matches.push(run.slice());
run = [board[r][c]];
}
}
if (run.length >= 3) matches.push(run.slice());
}
// Vertical
for (var c = 0; c < boardCols; c++) {
var run = [board[0][c]];
for (var r = 1; r < boardRows; r++) {
if (board[r][c].colorId === board[r - 1][c].colorId) {
run.push(board[r][c]);
} else {
if (run.length >= 3) matches.push(run.slice());
run = [board[r][c]];
}
}
if (run.length >= 3) matches.push(run.slice());
}
return matches;
}
// Remove matched tiles, return array of removed tiles
function removeMatches(matches, onFinish) {
var removed = [];
var toRemove = {};
for (var i = 0; i < matches.length; i++) {
for (var j = 0; j < matches[i].length; j++) {
var t = matches[i][j];
var key = t.row + ',' + t.col;
if (!toRemove[key]) {
toRemove[key] = t;
removed.push(t);
}
}
}
var count = removed.length;
if (count === 0) {
if (onFinish) onFinish();
return;
}
var finished = 0;
for (var i = 0; i < removed.length; i++) {
(function (tile) {
tile.flash(function () {
tile.visible = false;
finished++;
if (finished === count && onFinish) onFinish();
});
})(removed[i]);
}
LK.getSound('pop').play();
score += removed.length * 10;
scoreTxt.setText(score);
}
// Drop tiles to fill empty spaces, return true if any tile moved
function dropTiles(onFinish) {
var moved = false;
var dropCount = 0;
for (var c = 0; c < boardCols; c++) {
for (var r = boardRows - 1; r >= 0; r--) {
if (!board[r][c].visible) {
// Find nearest above visible tile
for (var rr = r - 1; rr >= 0; rr--) {
if (board[rr][c].visible) {
// Move tile down
var tile = board[rr][c];
board[r][c] = tile;
tile.moveTo(r, c, 120, function () {});
board[rr][c] = new Tile();
board[rr][c].setColor(randomColorId());
board[rr][c].setPosition(rr, c);
board[rr][c].visible = false;
game.addChild(board[rr][c]);
moved = true;
dropCount++;
break;
}
}
}
}
}
// Animate new tiles for empty spaces at top
for (var c = 0; c < boardCols; c++) {
for (var r = 0; r < boardRows; r++) {
if (!board[r][c].visible) {
var tile = board[r][c];
tile.setColor(randomColorId());
tile.visible = true;
tile.y = boardOffsetY - tileSize / 2;
tile.moveTo(r, c, 180, function () {});
moved = true;
dropCount++;
}
}
}
// Wait for all drops to finish
if (dropCount === 0) {
if (onFinish) onFinish();
} else {
LK.setTimeout(function () {
if (onFinish) onFinish();
}, 200);
}
}
// Check if any tile is moving
function anyTileMoving() {
for (var i = 0; i < tiles.length; i++) {
if (tiles[i].isMoving) return true;
}
return false;
}
// Deselect all tiles
function deselectTiles() {
if (selectedTile) {
tween.stop(selectedTile.tileAsset, {
scaleX: true,
scaleY: true
});
selectedTile.tileAsset.scaleX = 1;
selectedTile.tileAsset.scaleY = 1;
selectedTile = null;
}
}
// --- Board initialization ---
function fillBoardNoMatches() {
// Fill board with random tiles, but avoid initial matches
for (var r = 0; r < boardRows; r++) {
board[r] = [];
for (var c = 0; c < boardCols; c++) {
var colorId;
do {
colorId = randomColorId();
// Avoid horizontal match
if (c >= 2 && board[r][c - 1].colorId === colorId && board[r][c - 2].colorId === colorId) continue;
// Avoid vertical match
if (r >= 2 && board[r - 1][c].colorId === colorId && board[r - 2][c].colorId === colorId) continue;
break;
} while (true);
var tile = new Tile();
tile.setColor(colorId);
tile.setPosition(r, c);
board[r][c] = tile;
tiles.push(tile);
game.addChild(tile);
}
}
}
// --- GUI ---
scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
timerTxt = new Text2('60', {
size: 100,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0);
LK.gui.topRight.addChild(timerTxt);
// --- Timer ---
function startTimer() {
timeLeft = 60;
timerTxt.setText(timeLeft);
if (timerInterval) LK.clearInterval(timerInterval);
timerInterval = LK.setInterval(function () {
timeLeft--;
timerTxt.setText(timeLeft);
if (timeLeft <= 0) {
LK.clearInterval(timerInterval);
LK.showGameOver();
}
}, 1000);
}
// --- Input handling ---
var dragStartTile = null;
var dragStartX = 0,
dragStartY = 0;
var dragMoved = false;
function getTileAtPos(x, y) {
var col = Math.floor((x - boardOffsetX) / tileSize);
var row = Math.floor((y - boardOffsetY) / tileSize);
if (row >= 0 && row < boardRows && col >= 0 && col < boardCols) {
return board[row][col];
}
return null;
}
game.down = function (x, y, obj) {
if (isProcessing || anyTileMoving()) return;
if (x < boardOffsetX || x > boardOffsetX + boardWidth || y < boardOffsetY || y > boardOffsetY + boardHeight) return;
var tile = getTileAtPos(x, y);
if (!tile) return;
dragStartTile = tile;
dragStartX = x;
dragStartY = y;
dragMoved = false;
deselectTiles();
selectedTile = tile;
tween(selectedTile.tileAsset, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 80,
easing: tween.linear
});
};
game.move = function (x, y, obj) {
if (!dragStartTile || isProcessing || anyTileMoving()) return;
var dx = x - dragStartX;
var dy = y - dragStartY;
if (!dragMoved && (Math.abs(dx) > tileSize / 3 || Math.abs(dy) > tileSize / 3)) {
// Determine direction
var dir = null;
if (Math.abs(dx) > Math.abs(dy)) {
dir = dx > 0 ? 'right' : 'left';
} else {
dir = dy > 0 ? 'down' : 'up';
}
var row = dragStartTile.row,
col = dragStartTile.col;
var targetRow = row,
targetCol = col;
if (dir === 'right') targetCol++;
if (dir === 'left') targetCol--;
if (dir === 'down') targetRow++;
if (dir === 'up') targetRow--;
if (targetRow >= 0 && targetRow < boardRows && targetCol >= 0 && targetCol < boardCols) {
var targetTile = board[targetRow][targetCol];
dragMoved = true;
isProcessing = true;
deselectTiles();
swapTiles(dragStartTile, targetTile, true, function () {
// After swap, check for matches
var matches = findAllMatches();
if (matches.length > 0) {
processMatches(function () {
isProcessing = false;
});
} else {
// No match, swap back
swapTiles(dragStartTile, targetTile, true, function () {
isProcessing = false;
});
}
});
}
}
};
game.up = function (x, y, obj) {
dragStartTile = null;
dragMoved = false;
deselectTiles();
};
// --- Match processing loop ---
function processMatches(onFinish) {
var matches = findAllMatches();
if (matches.length === 0) {
if (onFinish) onFinish();
return;
}
removeMatches(matches, function () {
dropTiles(function () {
LK.setTimeout(function () {
processMatches(onFinish);
}, 80);
});
});
}
// --- Game update ---
game.update = function () {
// No per-frame logic needed for MVP
};
// --- Start game ---
function startGame() {
// Reset state
for (var i = 0; i < tiles.length; i++) {
tiles[i].destroy();
}
tiles = [];
board = [];
score = 0;
scoreTxt.setText(score);
deselectTiles();
fillBoardNoMatches();
startTimer();
}
startGame(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,434 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Tile class
+var Tile = Container.expand(function () {
+ var self = Container.call(this);
+ // Properties
+ self.row = 0;
+ self.col = 0;
+ self.colorId = 0; // 0-5
+ self.isMoving = false;
+ // Attach asset
+ self.setColor = function (colorId) {
+ self.colorId = colorId;
+ if (self.tileAsset) {
+ self.removeChild(self.tileAsset);
+ }
+ var colorNames = ['red', 'blue', 'green', 'yellow', 'purple', 'orange'];
+ var assetId = 'tile_' + colorNames[colorId];
+ self.tileAsset = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ };
+ // Animate to a new position (row, col)
+ self.moveTo = function (row, col, duration, _onFinish) {
+ self.row = row;
+ self.col = col;
+ self.isMoving = true;
+ var targetX = boardOffsetX + col * tileSize + tileSize / 2;
+ var targetY = boardOffsetY + row * tileSize + tileSize / 2;
+ tween(self, {
+ x: targetX,
+ y: targetY
+ }, {
+ duration: duration,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ self.isMoving = false;
+ if (_onFinish) _onFinish();
+ }
+ });
+ };
+ // Instantly set position
+ self.setPosition = function (row, col) {
+ self.row = row;
+ self.col = col;
+ self.x = boardOffsetX + col * tileSize + tileSize / 2;
+ self.y = boardOffsetY + row * tileSize + tileSize / 2;
+ };
+ // Flash when matched
+ self.flash = function (_onFinish2) {
+ tween(self.tileAsset, {
+ alpha: 0
+ }, {
+ duration: 150,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ self.tileAsset.alpha = 1;
+ if (_onFinish2) _onFinish2();
+ }
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Simple pop sound for matches
+// 6 tile colors for variety
+// --- Board settings ---
+var boardRows = 8;
+var boardCols = 8;
+var tileSize = 180;
+var boardWidth = boardCols * tileSize;
+var boardHeight = boardRows * tileSize;
+var boardOffsetX = Math.floor((2048 - boardWidth) / 2);
+var boardOffsetY = Math.floor((2732 - boardHeight) / 2);
+// --- Game state ---
+var board = []; // 2D array [row][col] of Tile
+var tiles = []; // Flat array of all Tile objects
+var selectedTile = null;
+var swappingTile = null;
+var isSwapping = false;
+var isProcessing = false;
+var score = 0;
+var timeLeft = 60; // seconds
+var timerInterval = null;
+var scoreTxt = null;
+var timerTxt = null;
+// --- Utility functions ---
+function randomColorId() {
+ return Math.floor(Math.random() * 6);
+}
+// Check if two tiles are adjacent
+function areAdjacent(tileA, tileB) {
+ var dr = Math.abs(tileA.row - tileB.row);
+ var dc = Math.abs(tileA.col - tileB.col);
+ return dr + dc === 1;
+}
+// Swap two tiles in board and animate
+function swapTiles(tileA, tileB, animate, onFinish) {
+ // Swap in board array
+ var temp = board[tileA.row][tileA.col];
+ board[tileA.row][tileA.col] = board[tileB.row][tileB.col];
+ board[tileB.row][tileB.col] = temp;
+ // Swap row/col
+ var tempRow = tileA.row,
+ tempCol = tileA.col;
+ if (animate) {
+ tileA.moveTo(tileB.row, tileB.col, 120);
+ tileB.moveTo(tempRow, tempCol, 120, onFinish);
+ } else {
+ tileA.setPosition(tileB.row, tileB.col);
+ tileB.setPosition(tempRow, tempCol);
+ if (onFinish) onFinish();
+ }
+ var trow = tileA.row,
+ tcol = tileA.col;
+ tileA.row = tileB.row;
+ tileA.col = tileB.col;
+ tileB.row = tempRow;
+ tileB.col = tempCol;
+}
+// Find all matches on the board. Returns array of arrays of matched tiles.
+function findAllMatches() {
+ var matches = [];
+ // Horizontal
+ for (var r = 0; r < boardRows; r++) {
+ var run = [board[r][0]];
+ for (var c = 1; c < boardCols; c++) {
+ if (board[r][c].colorId === board[r][c - 1].colorId) {
+ run.push(board[r][c]);
+ } else {
+ if (run.length >= 3) matches.push(run.slice());
+ run = [board[r][c]];
+ }
+ }
+ if (run.length >= 3) matches.push(run.slice());
+ }
+ // Vertical
+ for (var c = 0; c < boardCols; c++) {
+ var run = [board[0][c]];
+ for (var r = 1; r < boardRows; r++) {
+ if (board[r][c].colorId === board[r - 1][c].colorId) {
+ run.push(board[r][c]);
+ } else {
+ if (run.length >= 3) matches.push(run.slice());
+ run = [board[r][c]];
+ }
+ }
+ if (run.length >= 3) matches.push(run.slice());
+ }
+ return matches;
+}
+// Remove matched tiles, return array of removed tiles
+function removeMatches(matches, onFinish) {
+ var removed = [];
+ var toRemove = {};
+ for (var i = 0; i < matches.length; i++) {
+ for (var j = 0; j < matches[i].length; j++) {
+ var t = matches[i][j];
+ var key = t.row + ',' + t.col;
+ if (!toRemove[key]) {
+ toRemove[key] = t;
+ removed.push(t);
+ }
+ }
+ }
+ var count = removed.length;
+ if (count === 0) {
+ if (onFinish) onFinish();
+ return;
+ }
+ var finished = 0;
+ for (var i = 0; i < removed.length; i++) {
+ (function (tile) {
+ tile.flash(function () {
+ tile.visible = false;
+ finished++;
+ if (finished === count && onFinish) onFinish();
+ });
+ })(removed[i]);
+ }
+ LK.getSound('pop').play();
+ score += removed.length * 10;
+ scoreTxt.setText(score);
+}
+// Drop tiles to fill empty spaces, return true if any tile moved
+function dropTiles(onFinish) {
+ var moved = false;
+ var dropCount = 0;
+ for (var c = 0; c < boardCols; c++) {
+ for (var r = boardRows - 1; r >= 0; r--) {
+ if (!board[r][c].visible) {
+ // Find nearest above visible tile
+ for (var rr = r - 1; rr >= 0; rr--) {
+ if (board[rr][c].visible) {
+ // Move tile down
+ var tile = board[rr][c];
+ board[r][c] = tile;
+ tile.moveTo(r, c, 120, function () {});
+ board[rr][c] = new Tile();
+ board[rr][c].setColor(randomColorId());
+ board[rr][c].setPosition(rr, c);
+ board[rr][c].visible = false;
+ game.addChild(board[rr][c]);
+ moved = true;
+ dropCount++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // Animate new tiles for empty spaces at top
+ for (var c = 0; c < boardCols; c++) {
+ for (var r = 0; r < boardRows; r++) {
+ if (!board[r][c].visible) {
+ var tile = board[r][c];
+ tile.setColor(randomColorId());
+ tile.visible = true;
+ tile.y = boardOffsetY - tileSize / 2;
+ tile.moveTo(r, c, 180, function () {});
+ moved = true;
+ dropCount++;
+ }
+ }
+ }
+ // Wait for all drops to finish
+ if (dropCount === 0) {
+ if (onFinish) onFinish();
+ } else {
+ LK.setTimeout(function () {
+ if (onFinish) onFinish();
+ }, 200);
+ }
+}
+// Check if any tile is moving
+function anyTileMoving() {
+ for (var i = 0; i < tiles.length; i++) {
+ if (tiles[i].isMoving) return true;
+ }
+ return false;
+}
+// Deselect all tiles
+function deselectTiles() {
+ if (selectedTile) {
+ tween.stop(selectedTile.tileAsset, {
+ scaleX: true,
+ scaleY: true
+ });
+ selectedTile.tileAsset.scaleX = 1;
+ selectedTile.tileAsset.scaleY = 1;
+ selectedTile = null;
+ }
+}
+// --- Board initialization ---
+function fillBoardNoMatches() {
+ // Fill board with random tiles, but avoid initial matches
+ for (var r = 0; r < boardRows; r++) {
+ board[r] = [];
+ for (var c = 0; c < boardCols; c++) {
+ var colorId;
+ do {
+ colorId = randomColorId();
+ // Avoid horizontal match
+ if (c >= 2 && board[r][c - 1].colorId === colorId && board[r][c - 2].colorId === colorId) continue;
+ // Avoid vertical match
+ if (r >= 2 && board[r - 1][c].colorId === colorId && board[r - 2][c].colorId === colorId) continue;
+ break;
+ } while (true);
+ var tile = new Tile();
+ tile.setColor(colorId);
+ tile.setPosition(r, c);
+ board[r][c] = tile;
+ tiles.push(tile);
+ game.addChild(tile);
+ }
+ }
+}
+// --- GUI ---
+scoreTxt = new Text2('0', {
+ size: 100,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+timerTxt = new Text2('60', {
+ size: 100,
+ fill: 0xFFFFFF
+});
+timerTxt.anchor.set(0.5, 0);
+LK.gui.topRight.addChild(timerTxt);
+// --- Timer ---
+function startTimer() {
+ timeLeft = 60;
+ timerTxt.setText(timeLeft);
+ if (timerInterval) LK.clearInterval(timerInterval);
+ timerInterval = LK.setInterval(function () {
+ timeLeft--;
+ timerTxt.setText(timeLeft);
+ if (timeLeft <= 0) {
+ LK.clearInterval(timerInterval);
+ LK.showGameOver();
+ }
+ }, 1000);
+}
+// --- Input handling ---
+var dragStartTile = null;
+var dragStartX = 0,
+ dragStartY = 0;
+var dragMoved = false;
+function getTileAtPos(x, y) {
+ var col = Math.floor((x - boardOffsetX) / tileSize);
+ var row = Math.floor((y - boardOffsetY) / tileSize);
+ if (row >= 0 && row < boardRows && col >= 0 && col < boardCols) {
+ return board[row][col];
+ }
+ return null;
+}
+game.down = function (x, y, obj) {
+ if (isProcessing || anyTileMoving()) return;
+ if (x < boardOffsetX || x > boardOffsetX + boardWidth || y < boardOffsetY || y > boardOffsetY + boardHeight) return;
+ var tile = getTileAtPos(x, y);
+ if (!tile) return;
+ dragStartTile = tile;
+ dragStartX = x;
+ dragStartY = y;
+ dragMoved = false;
+ deselectTiles();
+ selectedTile = tile;
+ tween(selectedTile.tileAsset, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 80,
+ easing: tween.linear
+ });
+};
+game.move = function (x, y, obj) {
+ if (!dragStartTile || isProcessing || anyTileMoving()) return;
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ if (!dragMoved && (Math.abs(dx) > tileSize / 3 || Math.abs(dy) > tileSize / 3)) {
+ // Determine direction
+ var dir = null;
+ if (Math.abs(dx) > Math.abs(dy)) {
+ dir = dx > 0 ? 'right' : 'left';
+ } else {
+ dir = dy > 0 ? 'down' : 'up';
+ }
+ var row = dragStartTile.row,
+ col = dragStartTile.col;
+ var targetRow = row,
+ targetCol = col;
+ if (dir === 'right') targetCol++;
+ if (dir === 'left') targetCol--;
+ if (dir === 'down') targetRow++;
+ if (dir === 'up') targetRow--;
+ if (targetRow >= 0 && targetRow < boardRows && targetCol >= 0 && targetCol < boardCols) {
+ var targetTile = board[targetRow][targetCol];
+ dragMoved = true;
+ isProcessing = true;
+ deselectTiles();
+ swapTiles(dragStartTile, targetTile, true, function () {
+ // After swap, check for matches
+ var matches = findAllMatches();
+ if (matches.length > 0) {
+ processMatches(function () {
+ isProcessing = false;
+ });
+ } else {
+ // No match, swap back
+ swapTiles(dragStartTile, targetTile, true, function () {
+ isProcessing = false;
+ });
+ }
+ });
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ dragStartTile = null;
+ dragMoved = false;
+ deselectTiles();
+};
+// --- Match processing loop ---
+function processMatches(onFinish) {
+ var matches = findAllMatches();
+ if (matches.length === 0) {
+ if (onFinish) onFinish();
+ return;
+ }
+ removeMatches(matches, function () {
+ dropTiles(function () {
+ LK.setTimeout(function () {
+ processMatches(onFinish);
+ }, 80);
+ });
+ });
+}
+// --- Game update ---
+game.update = function () {
+ // No per-frame logic needed for MVP
+};
+// --- Start game ---
+function startGame() {
+ // Reset state
+ for (var i = 0; i < tiles.length; i++) {
+ tiles[i].destroy();
+ }
+ tiles = [];
+ board = [];
+ score = 0;
+ scoreTxt.setText(score);
+ deselectTiles();
+ fillBoardNoMatches();
+ startTimer();
+}
+startGame();
\ No newline at end of file