/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentLevel: 1, highestLevel: 1 }); /**** * Classes ****/ var EmptySpace = Container.expand(function (row, col, gridSize) { var self = Container.call(this); self.currentRow = row; self.currentCol = col; var tileSize = Math.floor(2000 / gridSize); // Create a visual representation of the empty space var emptyGraphics = self.attachAsset('emptySpace', { anchorX: 0.5, anchorY: 0.5, width: tileSize - 10, height: tileSize - 10, alpha: 0.5 }); self.moveTo = function (row, col) { var targetX = tileGame.getXPositionForCol(col); var targetY = tileGame.getYPositionForRow(row); self.currentRow = row; self.currentCol = col; self.x = targetX; self.y = targetY; }; return self; }); var LevelCompletePopup = Container.expand(function (level, moveCount) { var self = Container.call(this); // Background panel var panel = self.attachAsset('levelComplete', { anchorX: 0.5, anchorY: 0.5 }); // Title var titleText = new Text2("Level " + level + " Complete!", { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.y = -150; self.addChild(titleText); // Moves text var movesText = new Text2("Completed in " + moveCount + " moves", { size: 50, fill: 0xFFFFFF }); movesText.anchor.set(0.5, 0); movesText.y = -50; self.addChild(movesText); // Next level button text var nextLevelText = new Text2("Tap to continue", { size: 60, fill: 0xFFFFFF }); nextLevelText.anchor.set(0.5, 0); nextLevelText.y = 80; self.addChild(nextLevelText); // Handle tap to continue self.down = function () { if (tileGame) { self.destroy(); tileGame.startNextLevel(); } }; return self; }); var Tile = Container.expand(function (id, imageId, row, col, gridSize) { var self = Container.call(this); self.id = id; self.currentRow = row; self.currentCol = col; self.targetRow = row; self.targetCol = col; self.gridSize = gridSize; var tileSize = Math.floor(2000 / gridSize); // Create a background tile var background = self.attachAsset('tile', { anchorX: 0.5, anchorY: 0.5, width: tileSize - 10, height: tileSize - 10 }); // Add text showing the tile number (for development and as a fallback) var tileText = new Text2(String(id + 1), { size: tileSize / 3, fill: 0xFFFFFF }); tileText.anchor.set(0.5, 0.5); self.addChild(tileText); // If we have an image for this tile, we would create and add it here // This would be implemented in the final version with real images // Set up event handlers self.down = function (x, y, obj) { // Handle tile selection if (tileGame) { tileGame.attemptMove(self); } }; self.isMovable = function () { if (!tileGame || !tileGame.emptySpace) { return false; } // Check if this tile is adjacent to the empty space var emptyRow = tileGame.emptySpace.currentRow; var emptyCol = tileGame.emptySpace.currentCol; return self.currentRow === emptyRow && Math.abs(self.currentCol - emptyCol) === 1 || self.currentCol === emptyCol && Math.abs(self.currentRow - emptyRow) === 1; }; self.moveTo = function (row, col, animate) { var targetX = tileGame.getXPositionForCol(col); var targetY = tileGame.getYPositionForRow(row); self.currentRow = row; self.currentCol = col; if (animate) { // Use tween for smooth animation LK.getSound('slide').play(); tween(self, { x: targetX, y: targetY }, { duration: 200, easing: tween.easeOut }); } else { // Immediate positioning without animation self.x = targetX; self.y = targetY; } }; self.isInCorrectPosition = function () { return self.currentRow === self.targetRow && self.currentCol === self.targetCol; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x282c34 }); /**** * Game Code ****/ // Game variables var tileGame = null; var tiles = []; var moveCount = 0; var currentLevel = storage.currentLevel || 1; var highestLevel = storage.highestLevel || 1; var gridSizes = [3, 3, 4, 4, 4, 5, 5, 5, 6, 6]; // Grid size for each level var levelStartTime = 0; // Game UI elements var levelText = new Text2("Level: " + currentLevel, { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); LK.gui.topRight.addChild(levelText); levelText.x = -300; levelText.y = 30; var movesText = new Text2("Moves: 0", { size: 60, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); LK.gui.topRight.addChild(movesText); movesText.x = -300; movesText.y = 100; // Game object var TileGame = function TileGame() { this.tiles = []; this.emptySpace = null; this.boardSize = 0; this.gridSize = 3; this.tileSize = 0; this.boardX = 0; this.boardY = 0; this.isLevelComplete = false; this.init = function (level) { moveCount = 0; this.isLevelComplete = false; levelStartTime = Date.now(); // Update UI levelText.setText("Level: " + level); movesText.setText("Moves: " + moveCount); // Calculate grid size for this level this.gridSize = gridSizes[level - 1] || 3; // Default to 3 if level not found this.tileSize = Math.floor(2000 / this.gridSize); // Calculate board position to center it this.boardSize = this.tileSize * this.gridSize; this.boardX = (2048 - this.boardSize) / 2 + this.tileSize / 2; this.boardY = (2732 - this.boardSize) / 2 + this.tileSize / 2; // Clear existing tiles for (var i = 0; i < this.tiles.length; i++) { this.tiles[i].destroy(); } if (this.emptySpace) { this.emptySpace.destroy(); } this.tiles = []; // Create tiles var totalTiles = this.gridSize * this.gridSize - 1; // One spot remains empty for (var i = 0; i < totalTiles; i++) { var row = Math.floor(i / this.gridSize); var col = i % this.gridSize; var tile = new Tile(i, "image_" + level + "_" + i, row, col, this.gridSize); this.tiles.push(tile); game.addChild(tile); tile.moveTo(row, col, false); } // Create empty space at the bottom right var emptyRow = this.gridSize - 1; var emptyCol = this.gridSize - 1; this.emptySpace = new EmptySpace(emptyRow, emptyCol, this.gridSize); game.addChild(this.emptySpace); this.emptySpace.moveTo(emptyRow, emptyCol); // Shuffle the tiles this.shuffleTiles(); }; this.getXPositionForCol = function (col) { return this.boardX + col * this.tileSize; }; this.getYPositionForRow = function (row) { return this.boardY + row * this.tileSize; }; this.shuffleTiles = function () { // Perform random moves to shuffle var moves = this.gridSize * this.gridSize * 20; // Number of random moves for (var i = 0; i < moves; i++) { var adjacentTiles = this.getAdjacentTiles(); if (adjacentTiles.length > 0) { var randomIndex = Math.floor(Math.random() * adjacentTiles.length); var tileToMove = adjacentTiles[randomIndex]; this.moveTile(tileToMove, false); } } }; this.getAdjacentTiles = function () { var emptyRow = this.emptySpace.currentRow; var emptyCol = this.emptySpace.currentCol; var adjacentTiles = []; // Check all tiles for adjacency to empty space for (var i = 0; i < this.tiles.length; i++) { var tile = this.tiles[i]; if (tile.currentRow === emptyRow && Math.abs(tile.currentCol - emptyCol) === 1 || tile.currentCol === emptyCol && Math.abs(tile.currentRow - emptyRow) === 1) { adjacentTiles.push(tile); } } return adjacentTiles; }; this.moveTile = function (tile, countMove) { if (!tile || this.isLevelComplete) { return; } var emptyRow = this.emptySpace.currentRow; var emptyCol = this.emptySpace.currentCol; // Swap positions var tileRow = tile.currentRow; var tileCol = tile.currentCol; tile.moveTo(emptyRow, emptyCol, true); this.emptySpace.moveTo(tileRow, tileCol); if (countMove) { moveCount++; movesText.setText("Moves: " + moveCount); } // Check if puzzle is solved if (this.isPuzzleSolved()) { this.levelComplete(); } }; this.attemptMove = function (tile) { if (tile.isMovable()) { this.moveTile(tile, true); } }; this.isPuzzleSolved = function () { // Check if all tiles are in their correct positions for (var i = 0; i < this.tiles.length; i++) { if (!this.tiles[i].isInCorrectPosition()) { return false; } } return true; }; this.levelComplete = function () { if (this.isLevelComplete) { return; } this.isLevelComplete = true; // Play completion sound LK.getSound('complete').play(); // Flash screen to indicate success LK.effects.flashScreen(0x00ff00, 500); // Increment score based on level and moves var baseScore = currentLevel * 100; var moveScore = Math.max(0, 1000 - moveCount * 5); var totalScore = baseScore + moveScore; LK.setScore(LK.getScore() + totalScore); // Update storage if needed if (currentLevel >= highestLevel) { highestLevel = currentLevel + 1; storage.highestLevel = highestLevel; } // Show level complete popup after a short delay LK.setTimeout(function () { var popup = new LevelCompletePopup(currentLevel, moveCount); popup.x = 2048 / 2; popup.y = 2732 / 2; game.addChild(popup); }, 800); }; this.startNextLevel = function () { currentLevel++; if (currentLevel > 10) { // Player completed all levels LK.showYouWin(); return; } storage.currentLevel = currentLevel; this.init(currentLevel); }; }; // Initialize game tileGame = new TileGame(); tileGame.init(currentLevel); // Play background music LK.playMusic('bgmusic'); // Main game loop game.update = function () { // Game logic that needs to run every frame would go here }; // Handle game-wide touch events game.down = function (x, y, obj) { // Any game-wide touch handling logic would go here }; game.move = function (x, y, obj) { // Any game-wide move handling logic would go here }; game.up = function (x, y, obj) { // Any game-wide touch release handling logic would go here };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
highestLevel: 1
});
/****
* Classes
****/
var EmptySpace = Container.expand(function (row, col, gridSize) {
var self = Container.call(this);
self.currentRow = row;
self.currentCol = col;
var tileSize = Math.floor(2000 / gridSize);
// Create a visual representation of the empty space
var emptyGraphics = self.attachAsset('emptySpace', {
anchorX: 0.5,
anchorY: 0.5,
width: tileSize - 10,
height: tileSize - 10,
alpha: 0.5
});
self.moveTo = function (row, col) {
var targetX = tileGame.getXPositionForCol(col);
var targetY = tileGame.getYPositionForRow(row);
self.currentRow = row;
self.currentCol = col;
self.x = targetX;
self.y = targetY;
};
return self;
});
var LevelCompletePopup = Container.expand(function (level, moveCount) {
var self = Container.call(this);
// Background panel
var panel = self.attachAsset('levelComplete', {
anchorX: 0.5,
anchorY: 0.5
});
// Title
var titleText = new Text2("Level " + level + " Complete!", {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = -150;
self.addChild(titleText);
// Moves text
var movesText = new Text2("Completed in " + moveCount + " moves", {
size: 50,
fill: 0xFFFFFF
});
movesText.anchor.set(0.5, 0);
movesText.y = -50;
self.addChild(movesText);
// Next level button text
var nextLevelText = new Text2("Tap to continue", {
size: 60,
fill: 0xFFFFFF
});
nextLevelText.anchor.set(0.5, 0);
nextLevelText.y = 80;
self.addChild(nextLevelText);
// Handle tap to continue
self.down = function () {
if (tileGame) {
self.destroy();
tileGame.startNextLevel();
}
};
return self;
});
var Tile = Container.expand(function (id, imageId, row, col, gridSize) {
var self = Container.call(this);
self.id = id;
self.currentRow = row;
self.currentCol = col;
self.targetRow = row;
self.targetCol = col;
self.gridSize = gridSize;
var tileSize = Math.floor(2000 / gridSize);
// Create a background tile
var background = self.attachAsset('tile', {
anchorX: 0.5,
anchorY: 0.5,
width: tileSize - 10,
height: tileSize - 10
});
// Add text showing the tile number (for development and as a fallback)
var tileText = new Text2(String(id + 1), {
size: tileSize / 3,
fill: 0xFFFFFF
});
tileText.anchor.set(0.5, 0.5);
self.addChild(tileText);
// If we have an image for this tile, we would create and add it here
// This would be implemented in the final version with real images
// Set up event handlers
self.down = function (x, y, obj) {
// Handle tile selection
if (tileGame) {
tileGame.attemptMove(self);
}
};
self.isMovable = function () {
if (!tileGame || !tileGame.emptySpace) {
return false;
}
// Check if this tile is adjacent to the empty space
var emptyRow = tileGame.emptySpace.currentRow;
var emptyCol = tileGame.emptySpace.currentCol;
return self.currentRow === emptyRow && Math.abs(self.currentCol - emptyCol) === 1 || self.currentCol === emptyCol && Math.abs(self.currentRow - emptyRow) === 1;
};
self.moveTo = function (row, col, animate) {
var targetX = tileGame.getXPositionForCol(col);
var targetY = tileGame.getYPositionForRow(row);
self.currentRow = row;
self.currentCol = col;
if (animate) {
// Use tween for smooth animation
LK.getSound('slide').play();
tween(self, {
x: targetX,
y: targetY
}, {
duration: 200,
easing: tween.easeOut
});
} else {
// Immediate positioning without animation
self.x = targetX;
self.y = targetY;
}
};
self.isInCorrectPosition = function () {
return self.currentRow === self.targetRow && self.currentCol === self.targetCol;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x282c34
});
/****
* Game Code
****/
// Game variables
var tileGame = null;
var tiles = [];
var moveCount = 0;
var currentLevel = storage.currentLevel || 1;
var highestLevel = storage.highestLevel || 1;
var gridSizes = [3, 3, 4, 4, 4, 5, 5, 5, 6, 6]; // Grid size for each level
var levelStartTime = 0;
// Game UI elements
var levelText = new Text2("Level: " + currentLevel, {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topRight.addChild(levelText);
levelText.x = -300;
levelText.y = 30;
var movesText = new Text2("Moves: 0", {
size: 60,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
LK.gui.topRight.addChild(movesText);
movesText.x = -300;
movesText.y = 100;
// Game object
var TileGame = function TileGame() {
this.tiles = [];
this.emptySpace = null;
this.boardSize = 0;
this.gridSize = 3;
this.tileSize = 0;
this.boardX = 0;
this.boardY = 0;
this.isLevelComplete = false;
this.init = function (level) {
moveCount = 0;
this.isLevelComplete = false;
levelStartTime = Date.now();
// Update UI
levelText.setText("Level: " + level);
movesText.setText("Moves: " + moveCount);
// Calculate grid size for this level
this.gridSize = gridSizes[level - 1] || 3; // Default to 3 if level not found
this.tileSize = Math.floor(2000 / this.gridSize);
// Calculate board position to center it
this.boardSize = this.tileSize * this.gridSize;
this.boardX = (2048 - this.boardSize) / 2 + this.tileSize / 2;
this.boardY = (2732 - this.boardSize) / 2 + this.tileSize / 2;
// Clear existing tiles
for (var i = 0; i < this.tiles.length; i++) {
this.tiles[i].destroy();
}
if (this.emptySpace) {
this.emptySpace.destroy();
}
this.tiles = [];
// Create tiles
var totalTiles = this.gridSize * this.gridSize - 1; // One spot remains empty
for (var i = 0; i < totalTiles; i++) {
var row = Math.floor(i / this.gridSize);
var col = i % this.gridSize;
var tile = new Tile(i, "image_" + level + "_" + i, row, col, this.gridSize);
this.tiles.push(tile);
game.addChild(tile);
tile.moveTo(row, col, false);
}
// Create empty space at the bottom right
var emptyRow = this.gridSize - 1;
var emptyCol = this.gridSize - 1;
this.emptySpace = new EmptySpace(emptyRow, emptyCol, this.gridSize);
game.addChild(this.emptySpace);
this.emptySpace.moveTo(emptyRow, emptyCol);
// Shuffle the tiles
this.shuffleTiles();
};
this.getXPositionForCol = function (col) {
return this.boardX + col * this.tileSize;
};
this.getYPositionForRow = function (row) {
return this.boardY + row * this.tileSize;
};
this.shuffleTiles = function () {
// Perform random moves to shuffle
var moves = this.gridSize * this.gridSize * 20; // Number of random moves
for (var i = 0; i < moves; i++) {
var adjacentTiles = this.getAdjacentTiles();
if (adjacentTiles.length > 0) {
var randomIndex = Math.floor(Math.random() * adjacentTiles.length);
var tileToMove = adjacentTiles[randomIndex];
this.moveTile(tileToMove, false);
}
}
};
this.getAdjacentTiles = function () {
var emptyRow = this.emptySpace.currentRow;
var emptyCol = this.emptySpace.currentCol;
var adjacentTiles = [];
// Check all tiles for adjacency to empty space
for (var i = 0; i < this.tiles.length; i++) {
var tile = this.tiles[i];
if (tile.currentRow === emptyRow && Math.abs(tile.currentCol - emptyCol) === 1 || tile.currentCol === emptyCol && Math.abs(tile.currentRow - emptyRow) === 1) {
adjacentTiles.push(tile);
}
}
return adjacentTiles;
};
this.moveTile = function (tile, countMove) {
if (!tile || this.isLevelComplete) {
return;
}
var emptyRow = this.emptySpace.currentRow;
var emptyCol = this.emptySpace.currentCol;
// Swap positions
var tileRow = tile.currentRow;
var tileCol = tile.currentCol;
tile.moveTo(emptyRow, emptyCol, true);
this.emptySpace.moveTo(tileRow, tileCol);
if (countMove) {
moveCount++;
movesText.setText("Moves: " + moveCount);
}
// Check if puzzle is solved
if (this.isPuzzleSolved()) {
this.levelComplete();
}
};
this.attemptMove = function (tile) {
if (tile.isMovable()) {
this.moveTile(tile, true);
}
};
this.isPuzzleSolved = function () {
// Check if all tiles are in their correct positions
for (var i = 0; i < this.tiles.length; i++) {
if (!this.tiles[i].isInCorrectPosition()) {
return false;
}
}
return true;
};
this.levelComplete = function () {
if (this.isLevelComplete) {
return;
}
this.isLevelComplete = true;
// Play completion sound
LK.getSound('complete').play();
// Flash screen to indicate success
LK.effects.flashScreen(0x00ff00, 500);
// Increment score based on level and moves
var baseScore = currentLevel * 100;
var moveScore = Math.max(0, 1000 - moveCount * 5);
var totalScore = baseScore + moveScore;
LK.setScore(LK.getScore() + totalScore);
// Update storage if needed
if (currentLevel >= highestLevel) {
highestLevel = currentLevel + 1;
storage.highestLevel = highestLevel;
}
// Show level complete popup after a short delay
LK.setTimeout(function () {
var popup = new LevelCompletePopup(currentLevel, moveCount);
popup.x = 2048 / 2;
popup.y = 2732 / 2;
game.addChild(popup);
}, 800);
};
this.startNextLevel = function () {
currentLevel++;
if (currentLevel > 10) {
// Player completed all levels
LK.showYouWin();
return;
}
storage.currentLevel = currentLevel;
this.init(currentLevel);
};
};
// Initialize game
tileGame = new TileGame();
tileGame.init(currentLevel);
// Play background music
LK.playMusic('bgmusic');
// Main game loop
game.update = function () {
// Game logic that needs to run every frame would go here
};
// Handle game-wide touch events
game.down = function (x, y, obj) {
// Any game-wide touch handling logic would go here
};
game.move = function (x, y, obj) {
// Any game-wide move handling logic would go here
};
game.up = function (x, y, obj) {
// Any game-wide touch release handling logic would go here
};