/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MazeCell = Container.expand(function () {
var self = Container.call(this);
self.isWall = false;
self.isExit = false;
self.gridX = 0;
self.gridY = 0;
self.setAsWall = function () {
self.isWall = true;
self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setAsFloor = function () {
self.isWall = false;
self.attachAsset('floor', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setAsExit = function () {
self.isExit = true;
self.attachAsset('exit', {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.isMoving = false;
self.moveToGrid = function (gridX, gridY) {
if (self.isMoving) return;
// Validate boundaries before moving
if (gridX < 1 || gridX >= MAZE_COLS - 1 || gridY < 1 || gridY >= MAZE_ROWS - 1) {
return;
}
self.isMoving = true;
self.gridX = gridX;
self.gridY = gridY;
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
var targetX = gridX * CELL_SIZE + CELL_SIZE / 2 + offsetX;
var targetY = gridY * CELL_SIZE + CELL_SIZE / 2 + offsetY;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
LK.getSound('move').play();
// Check if reached exit
if (gridX === exitX && gridY === exitY) {
completeLevel();
}
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1E1E1E
});
/****
* Game Code
****/
// Game constants
var CELL_SIZE = 80;
var MAZE_COLS = 20;
var MAZE_ROWS = 20;
var MAX_LEVEL = 30;
// Game variables
var currentLevel = storage.currentLevel || 1;
var player = null;
var maze = [];
var startX = 1;
var startY = 1;
var exitX = 18;
var exitY = 18;
var levelStartTime = Date.now();
var dragStartPos = null;
var isGameComplete = false;
// UI elements
var levelText = new Text2('Level 1', {
size: 80,
fill: '#FFFFFF'
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var timeText = new Text2('Time: 0s', {
size: 60,
fill: '#CCCCCC'
});
timeText.anchor.set(0, 0);
timeText.x = 50;
timeText.y = 150;
LK.gui.topLeft.addChild(timeText);
// Maze layouts for each level - Progressive difficulty
var mazeLevels = [
// Level 1 - Very easy, mostly empty
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
// Level 2 - Add some walls to create basic obstacles
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
// Level 3 - More complex with multiple obstacles
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]];
// Generate more complex maze layouts
function generateMazeLayout(level) {
if (level <= mazeLevels.length) {
return mazeLevels[level - 1];
}
// Generate procedural maze for higher levels
var layout = [];
for (var y = 0; y < MAZE_ROWS; y++) {
layout[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
if (x === 0 || y === 0 || x === MAZE_COLS - 1 || y === MAZE_ROWS - 1) {
layout[y][x] = 1; // Border walls
} else if (x === startX && y === startY) {
layout[y][x] = 0; // Start position
} else if (x === exitX && y === exitY) {
layout[y][x] = 0; // Exit position
} else {
// Progressive difficulty: increase wall density and complexity as level increases
var baseComplexity = 0.1; // Base 10% wall density
var levelMultiplier = Math.min(level * 0.05, 0.4); // Increase by 5% per level, max 40%
var finalComplexity = baseComplexity + levelMultiplier;
// Add pattern complexity for higher levels
if (level >= 5) {
// Create corridors and rooms for higher levels
var isCorridorX = x % 4 === 0;
var isCorridorY = y % 4 === 0;
if (isCorridorX || isCorridorY) {
layout[y][x] = Math.random() < finalComplexity * 0.3 ? 1 : 0;
} else {
layout[y][x] = Math.random() < finalComplexity ? 1 : 0;
}
} else {
layout[y][x] = Math.random() < finalComplexity ? 1 : 0;
}
}
}
}
// Ensure path from start to exit exists
layout[startY][startX] = 0;
layout[exitY][exitX] = 0;
return layout;
}
function initializeMaze() {
// Clear existing maze
for (var i = 0; i < maze.length; i++) {
for (var j = 0; j < maze[i].length; j++) {
if (maze[i][j]) {
maze[i][j].destroy();
}
}
}
maze = [];
// Get maze layout for current level
var layout = generateMazeLayout(currentLevel);
// Create maze
for (var y = 0; y < MAZE_ROWS; y++) {
maze[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
var cell = new MazeCell();
cell.gridX = x;
cell.gridY = y;
cell.x = x * CELL_SIZE + CELL_SIZE / 2;
cell.y = y * CELL_SIZE + CELL_SIZE / 2;
if (layout[y][x] === 1) {
cell.setAsWall();
} else {
cell.setAsFloor();
}
// Set exit
if (x === exitX && y === exitY) {
cell.setAsExit();
}
maze[y][x] = cell;
game.addChild(cell);
}
}
// Position maze in center of screen
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
for (var y = 0; y < MAZE_ROWS; y++) {
for (var x = 0; x < MAZE_COLS; x++) {
maze[y][x].x += offsetX;
maze[y][x].y += offsetY;
}
}
}
function initializePlayer() {
if (player) {
player.destroy();
}
player = new Player();
player.gridX = startX;
player.gridY = startY;
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
player.x = startX * CELL_SIZE + CELL_SIZE / 2 + offsetX;
player.y = startY * CELL_SIZE + CELL_SIZE / 2 + offsetY;
game.addChild(player);
}
function canMoveTo(gridX, gridY) {
if (gridX < 0 || gridX >= MAZE_COLS || gridY < 0 || gridY >= MAZE_ROWS) {
return false;
}
if (gridX < 1 || gridX >= MAZE_COLS - 1 || gridY < 1 || gridY >= MAZE_ROWS - 1) {
return false;
}
return !maze[gridY][gridX].isWall;
}
function movePlayer(deltaX, deltaY) {
if (player.isMoving) return;
// Try to move up to 2 steps, but stop at first wall
var steps = 2;
var validSteps = 0;
for (var i = 1; i <= steps; i++) {
var checkX = player.gridX + deltaX * i;
var checkY = player.gridY + deltaY * i;
// Strict boundary check to ensure player stays within valid maze bounds
if (checkX < 1 || checkX >= MAZE_COLS - 1 || checkY < 1 || checkY >= MAZE_ROWS - 1) {
break;
}
// Additional check to ensure we don't go outside maze grid
if (checkX < 0 || checkX >= MAZE_COLS || checkY < 0 || checkY >= MAZE_ROWS) {
break;
}
if (!canMoveTo(checkX, checkY)) {
break;
}
validSteps = i;
}
// Move to the last valid position (at least 1 step if possible)
if (validSteps > 0) {
var newX = player.gridX + deltaX * validSteps;
var newY = player.gridY + deltaY * validSteps;
player.moveToGrid(newX, newY);
}
}
function completeLevel() {
LK.getSound('complete').play();
var completionTime = Math.floor((Date.now() - levelStartTime) / 1000);
if (currentLevel >= MAX_LEVEL) {
// Game completed
isGameComplete = true;
LK.getSound('win').play();
LK.showYouWin();
return;
}
// Next level
currentLevel++;
storage.currentLevel = currentLevel;
LK.effects.flashScreen(0x4CAF50, 500);
// Start next level after delay
LK.setTimeout(function () {
startLevel();
}, 1000);
}
function startLevel() {
levelStartTime = Date.now();
levelText.setText('Level ' + currentLevel);
// Adjust exit position based on level
if (currentLevel <= 10) {
exitX = 18;
exitY = 18;
} else if (currentLevel <= 20) {
exitX = 18;
exitY = 1;
} else {
exitX = 1;
exitY = 18;
}
initializeMaze();
initializePlayer();
}
function restartLevel() {
levelStartTime = Date.now();
initializePlayer();
}
// Touch controls
function handleMove(x, y, obj) {
if (!dragStartPos || player.isMoving) return;
var deltaX = x - dragStartPos.x;
var deltaY = y - dragStartPos.y;
var threshold = 40;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal movement
if (deltaX > 0) {
movePlayer(1, 0); // Right
} else {
movePlayer(-1, 0); // Left
}
} else {
// Vertical movement
if (deltaY > 0) {
movePlayer(0, 1); // Down
} else {
movePlayer(0, -1); // Up
}
}
dragStartPos = null;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragStartPos = {
x: x,
y: y
};
};
game.up = function (x, y, obj) {
dragStartPos = null;
};
game.update = function () {
// Update timer
var currentTime = Math.floor((Date.now() - levelStartTime) / 1000);
timeText.setText('Time: ' + currentTime + 's');
// Check for level restart (tap on player)
if (player && !player.isMoving) {
// Additional game logic can be added here
}
};
// Arrow key UI controls
var arrowContainer = new Container();
arrowContainer.x = 2048 / 2;
arrowContainer.y = 2732 - 200;
LK.gui.addChild(arrowContainer);
// Arrow button size and positions
var ARROW_SIZE = 120;
var ARROW_SPACING = 160;
// Up arrow
var upArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x4CAF50
});
upArrow.x = 0;
upArrow.y = -ARROW_SPACING;
upArrow.down = function (x, y, obj) {
movePlayer(0, -1); // Move up
};
arrowContainer.addChild(upArrow);
// Down arrow
var downArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x4CAF50
});
downArrow.x = 0;
downArrow.y = ARROW_SPACING;
downArrow.down = function (x, y, obj) {
movePlayer(0, 1); // Move down
};
arrowContainer.addChild(downArrow);
// Left arrow
var leftArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x4CAF50
});
leftArrow.x = -ARROW_SPACING;
leftArrow.y = 0;
leftArrow.down = function (x, y, obj) {
movePlayer(-1, 0); // Move left
};
arrowContainer.addChild(leftArrow);
// Right arrow
var rightArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x4CAF50
});
rightArrow.x = ARROW_SPACING;
rightArrow.y = 0;
rightArrow.down = function (x, y, obj) {
movePlayer(1, 0); // Move right
};
arrowContainer.addChild(rightArrow);
// Arrow direction indicators using text
var upText = new Text2('↑', {
size: 80,
fill: '#FFFFFF'
});
upText.anchor.set(0.5, 0.5);
upText.x = upArrow.x;
upText.y = upArrow.y;
arrowContainer.addChild(upText);
var downText = new Text2('↓', {
size: 80,
fill: '#FFFFFF'
});
downText.anchor.set(0.5, 0.5);
downText.x = downArrow.x;
downText.y = downArrow.y;
arrowContainer.addChild(downText);
var leftText = new Text2('←', {
size: 80,
fill: '#FFFFFF'
});
leftText.anchor.set(0.5, 0.5);
leftText.x = leftArrow.x;
leftText.y = leftArrow.y;
arrowContainer.addChild(leftText);
var rightText = new Text2('→', {
size: 80,
fill: '#FFFFFF'
});
rightText.anchor.set(0.5, 0.5);
rightText.x = rightArrow.x;
rightText.y = rightArrow.y;
arrowContainer.addChild(rightText);
// Initialize game
startLevel(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MazeCell = Container.expand(function () {
var self = Container.call(this);
self.isWall = false;
self.isExit = false;
self.gridX = 0;
self.gridY = 0;
self.setAsWall = function () {
self.isWall = true;
self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setAsFloor = function () {
self.isWall = false;
self.attachAsset('floor', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setAsExit = function () {
self.isExit = true;
self.attachAsset('exit', {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.isMoving = false;
self.moveToGrid = function (gridX, gridY) {
if (self.isMoving) return;
// Validate boundaries before moving
if (gridX < 1 || gridX >= MAZE_COLS - 1 || gridY < 1 || gridY >= MAZE_ROWS - 1) {
return;
}
self.isMoving = true;
self.gridX = gridX;
self.gridY = gridY;
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
var targetX = gridX * CELL_SIZE + CELL_SIZE / 2 + offsetX;
var targetY = gridY * CELL_SIZE + CELL_SIZE / 2 + offsetY;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
LK.getSound('move').play();
// Check if reached exit
if (gridX === exitX && gridY === exitY) {
completeLevel();
}
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1E1E1E
});
/****
* Game Code
****/
// Game constants
var CELL_SIZE = 80;
var MAZE_COLS = 20;
var MAZE_ROWS = 20;
var MAX_LEVEL = 30;
// Game variables
var currentLevel = storage.currentLevel || 1;
var player = null;
var maze = [];
var startX = 1;
var startY = 1;
var exitX = 18;
var exitY = 18;
var levelStartTime = Date.now();
var dragStartPos = null;
var isGameComplete = false;
// UI elements
var levelText = new Text2('Level 1', {
size: 80,
fill: '#FFFFFF'
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var timeText = new Text2('Time: 0s', {
size: 60,
fill: '#CCCCCC'
});
timeText.anchor.set(0, 0);
timeText.x = 50;
timeText.y = 150;
LK.gui.topLeft.addChild(timeText);
// Maze layouts for each level - Progressive difficulty
var mazeLevels = [
// Level 1 - Very easy, mostly empty
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
// Level 2 - Add some walls to create basic obstacles
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
// Level 3 - More complex with multiple obstacles
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]];
// Generate more complex maze layouts
function generateMazeLayout(level) {
if (level <= mazeLevels.length) {
return mazeLevels[level - 1];
}
// Generate procedural maze for higher levels
var layout = [];
for (var y = 0; y < MAZE_ROWS; y++) {
layout[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
if (x === 0 || y === 0 || x === MAZE_COLS - 1 || y === MAZE_ROWS - 1) {
layout[y][x] = 1; // Border walls
} else if (x === startX && y === startY) {
layout[y][x] = 0; // Start position
} else if (x === exitX && y === exitY) {
layout[y][x] = 0; // Exit position
} else {
// Progressive difficulty: increase wall density and complexity as level increases
var baseComplexity = 0.1; // Base 10% wall density
var levelMultiplier = Math.min(level * 0.05, 0.4); // Increase by 5% per level, max 40%
var finalComplexity = baseComplexity + levelMultiplier;
// Add pattern complexity for higher levels
if (level >= 5) {
// Create corridors and rooms for higher levels
var isCorridorX = x % 4 === 0;
var isCorridorY = y % 4 === 0;
if (isCorridorX || isCorridorY) {
layout[y][x] = Math.random() < finalComplexity * 0.3 ? 1 : 0;
} else {
layout[y][x] = Math.random() < finalComplexity ? 1 : 0;
}
} else {
layout[y][x] = Math.random() < finalComplexity ? 1 : 0;
}
}
}
}
// Ensure path from start to exit exists
layout[startY][startX] = 0;
layout[exitY][exitX] = 0;
return layout;
}
function initializeMaze() {
// Clear existing maze
for (var i = 0; i < maze.length; i++) {
for (var j = 0; j < maze[i].length; j++) {
if (maze[i][j]) {
maze[i][j].destroy();
}
}
}
maze = [];
// Get maze layout for current level
var layout = generateMazeLayout(currentLevel);
// Create maze
for (var y = 0; y < MAZE_ROWS; y++) {
maze[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
var cell = new MazeCell();
cell.gridX = x;
cell.gridY = y;
cell.x = x * CELL_SIZE + CELL_SIZE / 2;
cell.y = y * CELL_SIZE + CELL_SIZE / 2;
if (layout[y][x] === 1) {
cell.setAsWall();
} else {
cell.setAsFloor();
}
// Set exit
if (x === exitX && y === exitY) {
cell.setAsExit();
}
maze[y][x] = cell;
game.addChild(cell);
}
}
// Position maze in center of screen
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
for (var y = 0; y < MAZE_ROWS; y++) {
for (var x = 0; x < MAZE_COLS; x++) {
maze[y][x].x += offsetX;
maze[y][x].y += offsetY;
}
}
}
function initializePlayer() {
if (player) {
player.destroy();
}
player = new Player();
player.gridX = startX;
player.gridY = startY;
var mazeWidth = MAZE_COLS * CELL_SIZE;
var mazeHeight = MAZE_ROWS * CELL_SIZE;
var offsetX = (2048 - mazeWidth) / 2;
var offsetY = (2732 - mazeHeight) / 2;
player.x = startX * CELL_SIZE + CELL_SIZE / 2 + offsetX;
player.y = startY * CELL_SIZE + CELL_SIZE / 2 + offsetY;
game.addChild(player);
}
function canMoveTo(gridX, gridY) {
if (gridX < 0 || gridX >= MAZE_COLS || gridY < 0 || gridY >= MAZE_ROWS) {
return false;
}
if (gridX < 1 || gridX >= MAZE_COLS - 1 || gridY < 1 || gridY >= MAZE_ROWS - 1) {
return false;
}
return !maze[gridY][gridX].isWall;
}
function movePlayer(deltaX, deltaY) {
if (player.isMoving) return;
// Try to move up to 2 steps, but stop at first wall
var steps = 2;
var validSteps = 0;
for (var i = 1; i <= steps; i++) {
var checkX = player.gridX + deltaX * i;
var checkY = player.gridY + deltaY * i;
// Strict boundary check to ensure player stays within valid maze bounds
if (checkX < 1 || checkX >= MAZE_COLS - 1 || checkY < 1 || checkY >= MAZE_ROWS - 1) {
break;
}
// Additional check to ensure we don't go outside maze grid
if (checkX < 0 || checkX >= MAZE_COLS || checkY < 0 || checkY >= MAZE_ROWS) {
break;
}
if (!canMoveTo(checkX, checkY)) {
break;
}
validSteps = i;
}
// Move to the last valid position (at least 1 step if possible)
if (validSteps > 0) {
var newX = player.gridX + deltaX * validSteps;
var newY = player.gridY + deltaY * validSteps;
player.moveToGrid(newX, newY);
}
}
function completeLevel() {
LK.getSound('complete').play();
var completionTime = Math.floor((Date.now() - levelStartTime) / 1000);
if (currentLevel >= MAX_LEVEL) {
// Game completed
isGameComplete = true;
LK.getSound('win').play();
LK.showYouWin();
return;
}
// Next level
currentLevel++;
storage.currentLevel = currentLevel;
LK.effects.flashScreen(0x4CAF50, 500);
// Start next level after delay
LK.setTimeout(function () {
startLevel();
}, 1000);
}
function startLevel() {
levelStartTime = Date.now();
levelText.setText('Level ' + currentLevel);
// Adjust exit position based on level
if (currentLevel <= 10) {
exitX = 18;
exitY = 18;
} else if (currentLevel <= 20) {
exitX = 18;
exitY = 1;
} else {
exitX = 1;
exitY = 18;
}
initializeMaze();
initializePlayer();
}
function restartLevel() {
levelStartTime = Date.now();
initializePlayer();
}
// Touch controls
function handleMove(x, y, obj) {
if (!dragStartPos || player.isMoving) return;
var deltaX = x - dragStartPos.x;
var deltaY = y - dragStartPos.y;
var threshold = 40;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal movement
if (deltaX > 0) {
movePlayer(1, 0); // Right
} else {
movePlayer(-1, 0); // Left
}
} else {
// Vertical movement
if (deltaY > 0) {
movePlayer(0, 1); // Down
} else {
movePlayer(0, -1); // Up
}
}
dragStartPos = null;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragStartPos = {
x: x,
y: y
};
};
game.up = function (x, y, obj) {
dragStartPos = null;
};
game.update = function () {
// Update timer
var currentTime = Math.floor((Date.now() - levelStartTime) / 1000);
timeText.setText('Time: ' + currentTime + 's');
// Check for level restart (tap on player)
if (player && !player.isMoving) {
// Additional game logic can be added here
}
};
// Arrow key UI controls
var arrowContainer = new Container();
arrowContainer.x = 2048 / 2;
arrowContainer.y = 2732 - 200;
LK.gui.addChild(arrowContainer);
// Arrow button size and positions
var ARROW_SIZE = 120;
var ARROW_SPACING = 160;
// Up arrow
var upArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x4CAF50
});
upArrow.x = 0;
upArrow.y = -ARROW_SPACING;
upArrow.down = function (x, y, obj) {
movePlayer(0, -1); // Move up
};
arrowContainer.addChild(upArrow);
// Down arrow
var downArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x4CAF50
});
downArrow.x = 0;
downArrow.y = ARROW_SPACING;
downArrow.down = function (x, y, obj) {
movePlayer(0, 1); // Move down
};
arrowContainer.addChild(downArrow);
// Left arrow
var leftArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x4CAF50
});
leftArrow.x = -ARROW_SPACING;
leftArrow.y = 0;
leftArrow.down = function (x, y, obj) {
movePlayer(-1, 0); // Move left
};
arrowContainer.addChild(leftArrow);
// Right arrow
var rightArrow = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x4CAF50
});
rightArrow.x = ARROW_SPACING;
rightArrow.y = 0;
rightArrow.down = function (x, y, obj) {
movePlayer(1, 0); // Move right
};
arrowContainer.addChild(rightArrow);
// Arrow direction indicators using text
var upText = new Text2('↑', {
size: 80,
fill: '#FFFFFF'
});
upText.anchor.set(0.5, 0.5);
upText.x = upArrow.x;
upText.y = upArrow.y;
arrowContainer.addChild(upText);
var downText = new Text2('↓', {
size: 80,
fill: '#FFFFFF'
});
downText.anchor.set(0.5, 0.5);
downText.x = downArrow.x;
downText.y = downArrow.y;
arrowContainer.addChild(downText);
var leftText = new Text2('←', {
size: 80,
fill: '#FFFFFF'
});
leftText.anchor.set(0.5, 0.5);
leftText.x = leftArrow.x;
leftText.y = leftArrow.y;
arrowContainer.addChild(leftText);
var rightText = new Text2('→', {
size: 80,
fill: '#FFFFFF'
});
rightText.anchor.set(0.5, 0.5);
rightText.x = rightArrow.x;
rightText.y = rightArrow.y;
arrowContainer.addChild(rightText);
// Initialize game
startLevel();