/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
self.touchCount = 0; // Add a counter to track the number of times the coin has been touched
self.lastWasIntersecting = false; // Initialize lastWasIntersecting for tracking intersection state
// Add rotation to the coin continuously when the game start
self.update = function () {
if (self.touchCount === 0) {
self.rotation += 0.05;
}
// Check if the point reaches the coin
if (!self.lastWasIntersecting && (point.intersects(self) || Math.abs(point.x - self.x) <= self.width / 2 && Math.abs(point.y - self.y) <= self.height / 2)) {
// Increase the touch count
self.touchCount++;
// Play a sound effect
LK.getSound('coin').play();
// Add score (only adds 1 point)
LK.setScore(LK.getScore() + 1);
// Update the score display to show the number of coins after a slash
scoreTxt.setText(LK.getScore() + '/7');
// Remove the coin from the game after it's been touched
self.destroy();
// If all coins are collected, we don't regenerate coins - game is complete
if (LK.getScore() === 7) {
if (currentLevel < totalLevels) {
// If not the last level, go to the next level
currentLevel++;
resetGame(); // Call a function to reset the game for the next level
} else {
// If it's the last level, show the "you win" message
LK.showYouWin();
}
}
}
self.lastWasIntersecting = point.intersects(self) || Math.abs(point.x - self.x) <= self.width / 2 && Math.abs(point.y - self.y) <= self.height / 2;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
var currentLevel = 1;
var totalLevels = 2;
// Create arrays to track walls and coins
var walls = [];
var coins = [];
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Create and position wall2 assets to form a maze inside the 4 main walls
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Calculate playable area dimensions
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
var _loop = function _loop() {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
return 1; // continue
}
;
// Function to create the maze (extracted from original Game Code)
function createMaze() {
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Create a grid-like maze with corridors sized for coins to pass through
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
for (var x = 0; x < gridSizeX - 1; x++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
});
// Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
}
horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
}); // Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
},
horizontalWall;
for (var x = 0; x < gridSizeX - 1; x++) {
if (_loop()) continue;
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// We won't add diagonal walls as we need only horizontal and vertical walls between the main walls
// We won't add circular/square patterns as we need only horizontal and vertical walls between the main walls
// We won't add zigzag walls as we need only horizontal and vertical walls between the main walls
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
var point = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(point);
// Handle mouse movement
// Add background to the game
var background = LK.getAsset('Background1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 1000,
scaleY: 2732 / 1075
});
game.addChildAt(background, 0);
background.x = 2048 / 2;
background.y = 2732 / 2 + 115; // Lower the background a bit from the top
game.down = function (x, y, obj) {
// Check if a wall2 asset is being clicked
game.children.forEach(function (child) {
if (child.assetId === 'wall2' && child.intersects(point)) {
game.draggedWall = child;
}
});
// Set a flag to track if the mouse is down
game.isMouseDown = true;
// Coin handling is now done exclusively in the Coin class update method
};
// Create a function to check if a position is clear of walls
function isPositionClear(x, y, minDistance) {
var isClear = true;
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
// Check if the point is too close to the wall
if (Math.abs(child.x - x) < minDistance && Math.abs(child.y - y) < minDistance) {
isClear = false;
}
}
});
return isClear;
}
// Create a function to find valid coin positions
function findValidCoinPositions(count) {
var positions = [];
var minDistanceFromWall = 50; // Minimum distance from any wall
var minDistanceBetweenCoins = 100; // Minimum distance between coins
var maxAttempts = 200; // Maximum attempts to find a valid position
// Try to find valid positions for all coins
for (var i = 0; i < count; i++) {
var validPosition = false;
var attempts = 0;
var x, y;
while (!validPosition && attempts < maxAttempts) {
// Generate a random position within the playable area
x = playableAreaLeft + cellWidth * (1 + Math.random() * (gridSizeX - 2));
y = playableAreaTop + cellHeight * (1 + Math.random() * (gridSizeY - 2));
// Check if position is clear of walls
validPosition = isPositionClear(x, y, minDistanceFromWall);
// Check if position is far enough from other coins
if (validPosition) {
for (var j = 0; j < positions.length; j++) {
if (Math.abs(positions[j].x - x) < minDistanceBetweenCoins && Math.abs(positions[j].y - y) < minDistanceBetweenCoins) {
validPosition = false;
break;
}
}
}
attempts++;
}
if (validPosition) {
positions.push({
x: x,
y: y
});
} else {
// Fallback position if we couldn't find a valid one
positions.push({
x: playableAreaLeft + (i + 1) * (playableWidth / (count + 1)),
y: playableAreaTop + (i % 2 === 0 ? playableHeight / 3 : playableHeight * 2 / 3)
});
}
}
return positions;
}
// Function to check if a position is at a corner or between wall edges
function isPositionBesideWall(x, y) {
var minProximity = 40; // Minimum distance a coin should be from a wall
var maxDistanceFromWall = 80; // Maximum distance to consider beside a wall
var isInsideWall = false;
var isAtCornerOrEdge = false;
var nearbyWalls = [];
// First check if the position is inside any wall
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
var safetyMargin = 20;
var halfWidth = child.width / 2 + safetyMargin;
var halfHeight = child.height / 2 + safetyMargin;
if (Math.abs(child.x - x) < halfWidth && Math.abs(child.y - y) < halfHeight) {
isInsideWall = true;
}
}
});
if (isInsideWall) {
return false; // Position is inside a wall, not valid
}
// Find all nearby walls
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
var distX = Math.max(Math.abs(child.x - x) - child.width / 2, 0);
var distY = Math.max(Math.abs(child.y - y) - child.height / 2, 0);
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance >= minProximity && distance <= maxDistanceFromWall) {
nearbyWalls.push({
wall: child,
distance: distance,
distX: distX,
distY: distY
});
}
}
});
// Check if position is at a corner (near multiple walls) or at wall edges
if (nearbyWalls.length >= 2) {
// Position is near multiple walls - likely a corner, which is good
isAtCornerOrEdge = true;
} else if (nearbyWalls.length === 1) {
// Position is near one wall - check if it's at the edge, not in the middle
var wall = nearbyWalls[0].wall;
var relativeX = x - wall.x;
var relativeY = y - wall.y;
var halfWidth = wall.width / 2;
var halfHeight = wall.height / 2;
// Check if position is near the edges (corners) of the wall, not in the middle
var nearLeftEdge = Math.abs(relativeX + halfWidth) < 30;
var nearRightEdge = Math.abs(relativeX - halfWidth) < 30;
var nearTopEdge = Math.abs(relativeY + halfHeight) < 30;
var nearBottomEdge = Math.abs(relativeY - halfHeight) < 30;
var nearVerticalCenter = Math.abs(relativeX) < halfWidth * 0.3;
var nearHorizontalCenter = Math.abs(relativeY) < halfHeight * 0.3;
// Position is valid if it's near an edge but not in the center of the wall
if ((nearLeftEdge || nearRightEdge || nearTopEdge || nearBottomEdge) && !(nearVerticalCenter && nearHorizontalCenter)) {
isAtCornerOrEdge = true;
}
}
return isAtCornerOrEdge;
}
// Modified findValidCoinPositions function to ensure coins are placed beside walls
function findValidCoinPositionsNextToWalls(count) {
var positions = [];
var minDistanceBetweenCoins = 100; // Minimum distance between coins
var maxAttempts = 500; // Increased max attempts to find valid positions
// Try to find valid positions for all coins
for (var i = 0; i < count; i++) {
var validPosition = false;
var attempts = 0;
var x, y;
while (!validPosition && attempts < maxAttempts) {
// Generate a random position within the playable area
x = playableAreaLeft + cellWidth * (1 + Math.random() * (gridSizeX - 2));
y = playableAreaTop + cellHeight * (1 + Math.random() * (gridSizeY - 2));
// Check if position is beside a wall but not inside it
// First verify if it's not inside any wall
var insideWall = false;
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
if (Math.abs(x - child.x) < child.width / 2 + 10 && Math.abs(y - child.y) < child.height / 2 + 10) {
insideWall = true;
}
}
});
if (!insideWall) {
// Then check if it's beside a wall
validPosition = isPositionBesideWall(x, y);
}
// Check if position is far enough from other coins
if (validPosition) {
for (var j = 0; j < positions.length; j++) {
if (Math.abs(positions[j].x - x) < minDistanceBetweenCoins && Math.abs(positions[j].y - y) < minDistanceBetweenCoins) {
validPosition = false;
break;
}
}
}
attempts++;
}
if (validPosition) {
positions.push({
x: x,
y: y
});
} else {
console.log("Could not find valid position for coin " + (i + 1) + ", using fallback");
// Fallback position if we couldn't find a valid one
// For fallback, try to find a clear position that's far from walls
var fallbackX = playableAreaLeft + (i + 1) * (playableWidth / (count + 1));
var fallbackY = playableAreaTop + (i % 2 === 0 ? playableHeight / 3 : playableHeight * 2 / 3);
// Try to adjust the fallback position to be beside a wall
for (var w = 0; w < game.children.length; w++) {
var child = game.children[w];
if (child.assetId === 'wall2') {
fallbackX = child.x + child.width / 2 + 50;
fallbackY = child.y;
var validFallback = true;
// Check if this fallback position works
game.children.forEach(function (otherChild) {
if (otherChild.assetId === 'wall1' || otherChild.assetId === 'wall2') {
if (Math.abs(fallbackX - otherChild.x) < otherChild.width / 2 + 10 && Math.abs(fallbackY - otherChild.y) < otherChild.height / 2 + 10) {
validFallback = false;
}
}
});
if (validFallback) {
break;
}
}
}
positions.push({
x: fallbackX,
y: fallbackY
});
}
}
return positions;
}
// Function to generate coin positions on each level load
function generateCoinPositions() {
// Set a completely random seed each time to ensure different positions
var randomSeed = Math.random() * 10000 + Date.now() % 10000;
// Shuffle the seed into playable area coordinates for more randomness
var seedX = Math.sin(randomSeed) * playableWidth * 0.8;
var seedY = Math.cos(randomSeed) * playableHeight * 0.8;
// Generate valid positions for 7 coins based on the current maze layout
// Use randomSeed to influence position generation
var coinPositions = [];
var attemptAreas = [
// Try different areas of the maze to distribute coins better with more randomness
{
x: playableAreaLeft + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.6 + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + playableHeight * 0.6 + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.6 + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + playableHeight * 0.6 + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.5 + (seedX + Math.random() * 200) % playableWidth * 0.5,
y: playableAreaTop + playableHeight * 0.5 + (seedY + Math.random() * 200) % playableHeight * 0.5
}];
// Use the findValidCoinPositionsNextToWalls but with more randomness
// Generate many more positions than needed so we have plenty to choose from
var allPossiblePositions = findValidCoinPositionsNextToWalls(15);
// Shuffle the positions array to add more randomness
for (var i = allPossiblePositions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allPossiblePositions[i];
allPossiblePositions[i] = allPossiblePositions[j];
allPossiblePositions[j] = temp;
}
// Take the first 7 positions
coinPositions = allPossiblePositions.slice(0, 7);
// Add small amount of randomness to each position
for (var i = 0; i < coinPositions.length; i++) {
// Add a smaller random offset to avoid pushing into walls
coinPositions[i].x += Math.sin(randomSeed + i * 47.3) * cellWidth * 0.1;
coinPositions[i].y += Math.cos(randomSeed + i * 53.2) * cellHeight * 0.1;
}
// Double check each position is valid and not inside any wall
// Use a more thorough validation with a safety margin
var safetyMargin = 20; // Extra space to ensure we're not on walls
for (var i = 0; i < coinPositions.length; i++) {
var posX = coinPositions[i].x;
var posY = coinPositions[i].y;
var invalidPos = false;
// First pass to check if position is inside any wall
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
// Use safety margin to ensure we're comfortably away from walls
if (Math.abs(posX - child.x) < child.width / 2 + safetyMargin && Math.abs(posY - child.y) < child.height / 2 + safetyMargin) {
console.log("Warning: Coin position too close to wall at:", posX, posY);
invalidPos = true;
// Try to move the position outside the wall with a significant offset
var dirX = posX > child.x ? 1 : -1;
var dirY = posY > child.y ? 1 : -1;
// Move the coin a safe distance away from the wall
coinPositions[i].x = child.x + dirX * (child.width / 2 + safetyMargin + 30 + Math.random() * 20);
coinPositions[i].y = child.y + dirY * (child.height / 2 + safetyMargin + 30 + Math.random() * 20);
// Verify the new position isn't inside another wall with a second check
var newPosX = coinPositions[i].x;
var newPosY = coinPositions[i].y;
var stillInvalid = false;
game.children.forEach(function (otherChild) {
if (otherChild.assetId === 'wall1' || otherChild.assetId === 'wall2') {
if (Math.abs(newPosX - otherChild.x) < otherChild.width / 2 + safetyMargin && Math.abs(newPosY - otherChild.y) < otherChild.height / 2 + safetyMargin) {
stillInvalid = true;
}
}
});
if (stillInvalid) {
// Try a different approach - find a clear space with more randomness
var attempts = 0;
var foundValid = false;
while (!foundValid && attempts < 20) {
// Generate a new random position in the playable area
var testX = playableAreaLeft + Math.random() * playableWidth;
var testY = playableAreaTop + Math.random() * playableHeight;
var testValid = true;
// Check if this position is clear of all walls
game.children.forEach(function (testChild) {
if (testChild.assetId === 'wall1' || testChild.assetId === 'wall2') {
if (Math.abs(testX - testChild.x) < testChild.width / 2 + safetyMargin && Math.abs(testY - testChild.y) < testChild.height / 2 + safetyMargin) {
testValid = false;
}
}
});
if (testValid) {
coinPositions[i].x = testX;
coinPositions[i].y = testY;
foundValid = true;
}
attempts++;
}
if (!foundValid) {
// Last resort - place in a known clear area
coinPositions[i].x = playableAreaLeft + playableWidth * (0.2 + 0.6 * Math.random());
coinPositions[i].y = playableAreaTop + playableHeight * (0.2 + 0.6 * Math.random());
}
}
}
}
});
}
return coinPositions;
}
// Generate initial coin positions
var coinPositions = generateCoinPositions();
// Create 7 new coin assets at positions that fit within maze corridors
for (var i = 0; i < 7; i++) {
var newCoin = new Coin();
game.addChild(newCoin);
coins.push(newCoin);
// Set the coins at positions within the maze corridors
newCoin.x = coinPositions[i].x;
newCoin.y = coinPositions[i].y;
console.log("Coin " + (i + 1) + " position: x=" + newCoin.x + ", y=" + newCoin.y);
}
// Function to reset the game for a new level
var resetGame = function resetGame() {
// Clear all existing children from the game stage except GUI
game.children.forEach(function (child) {
if (child !== LK.gui) {
child.destroy();
}
});
// Clear walls and coins arrays
walls.length = 0;
coins.length = 0;
// Reset score
LK.setScore(0);
scoreTxt.setText('0/7');
// Reset time
statusTime = 60;
statusTimeText.setText(statusTime.toString());
// Add background back
var background = LK.getAsset('Background1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 1000,
scaleY: 2732 / 1075
});
game.addChildAt(background, 0);
background.x = 2048 / 2;
background.y = 2732 / 2 + 115;
// Recreate point
point = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(point);
// Recreate walls and maze for the new level
createMaze();
// Generate new coin positions
var coinPositions = generateCoinPositions();
// Create 7 new coin assets at positions that fit within maze corridors
for (var i = 0; i < 7; i++) {
var newCoin = new Coin();
game.addChild(newCoin);
coins.push(newCoin);
// Set the coins at positions within the maze corridors
newCoin.x = coinPositions[i].x;
newCoin.y = coinPositions[i].y;
}
// Update the level text
levelText.setText('Level ' + currentLevel);
};
// Log the total number of walls and coins in the game
// Function to create the maze (extracted from original Game Code)
function createMaze() {
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Create a grid-like maze with corridors sized for coins to pass through
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
for (var x = 0; x < gridSizeX - 1; x++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
});
// Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
}
// Create the initial maze for Level 1
createMaze();
console.log("Total walls in game: " + walls.length);
console.log("Total coins in game: " + coins.length);
game.up = function (x, y, obj) {
// Reset the dragged wall when the mouse is released
game.draggedWall = null;
game.isMouseDown = false;
};
// Set a flag to track if the mouse is up
game.isMouseDown = false;
// Add level text to the top right side
var levelText = new Text2('Level 1', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0); // Sets anchor to the top right edge of the text.
LK.gui.topRight.addChild(levelText);
// Initialize status time
var statusTime = 60; // 60 seconds = 1 minute
// Initialize status time text
var statusTimeText = new Text2(statusTime.toString(), {
size: 80,
fill: 0xFFFFFF
});
// Initialize score text to display the number of coins after a slash
var scoreTxt = new Text2('0/7', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0); // Sets anchor to the top left edge of the text.
statusTimeText.anchor.set(-0.8, 0); // Sets anchor to the top center edge of the text.
LK.gui.top.addChild(statusTimeText);
// Position the score text directly to the left of the time text
scoreTxt.x = -400; // Position score text to the left of time text
LK.gui.top.addChild(scoreTxt);
// Create a timer that decreases the status time every second
var statusTimeTimer = LK.setInterval(function () {
statusTime--;
// Update the status time text
statusTimeText.setText(statusTime.toString());
// If the status time reaches 0, stop the timer and show game over
if (statusTime <= 0) {
LK.clearInterval(statusTimeTimer);
LK.showGameOver();
}
}, 1000); // 1000 milliseconds = 1 second
// Update the score display to show the number of coins after a slash
scoreTxt.setText(LK.getScore() + '/7');
game.move = function (x, y, obj) {
// Check if the mouse is down and a wall2 asset is being dragged
if (game.isMouseDown && game.draggedWall) {
game.draggedWall.x = x;
game.draggedWall.y = y;
} else {
// Check if the cursor reaches any wall2 asset
game.children.forEach(function (child) {
if (child.assetId === 'wall2' && point.intersects(child)) {
game.draggedWall = child;
}
});
}
// Update the position of the point asset to the current mouse position
point.x = x;
point.y = y;
// Draw the way of cursor by point asset when its moving
var newPoint = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
newPoint.x = x;
newPoint.y = y;
game.addChild(newPoint);
// Check for intersection with wall1 and wall2 assets
game.children.forEach(function (child) {
if ((child.assetId === 'wall1' || child.assetId === 'wall2') && point.intersects(child)) {
// Handle collision with wall1 or wall2
console.log("Collision detected with wall:", child.assetId);
// Implement any specific logic needed for collision with walls
}
});
// Coin collision is now handled in the Coin class update method
// We don't need to check for coin collisions here anymore
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
self.touchCount = 0; // Add a counter to track the number of times the coin has been touched
self.lastWasIntersecting = false; // Initialize lastWasIntersecting for tracking intersection state
// Add rotation to the coin continuously when the game start
self.update = function () {
if (self.touchCount === 0) {
self.rotation += 0.05;
}
// Check if the point reaches the coin
if (!self.lastWasIntersecting && (point.intersects(self) || Math.abs(point.x - self.x) <= self.width / 2 && Math.abs(point.y - self.y) <= self.height / 2)) {
// Increase the touch count
self.touchCount++;
// Play a sound effect
LK.getSound('coin').play();
// Add score (only adds 1 point)
LK.setScore(LK.getScore() + 1);
// Update the score display to show the number of coins after a slash
scoreTxt.setText(LK.getScore() + '/7');
// Remove the coin from the game after it's been touched
self.destroy();
// If all coins are collected, we don't regenerate coins - game is complete
if (LK.getScore() === 7) {
if (currentLevel < totalLevels) {
// If not the last level, go to the next level
currentLevel++;
resetGame(); // Call a function to reset the game for the next level
} else {
// If it's the last level, show the "you win" message
LK.showYouWin();
}
}
}
self.lastWasIntersecting = point.intersects(self) || Math.abs(point.x - self.x) <= self.width / 2 && Math.abs(point.y - self.y) <= self.height / 2;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
var currentLevel = 1;
var totalLevels = 2;
// Create arrays to track walls and coins
var walls = [];
var coins = [];
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Create and position wall2 assets to form a maze inside the 4 main walls
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Calculate playable area dimensions
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
var _loop = function _loop() {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
return 1; // continue
}
;
// Function to create the maze (extracted from original Game Code)
function createMaze() {
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Create a grid-like maze with corridors sized for coins to pass through
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
for (var x = 0; x < gridSizeX - 1; x++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
});
// Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
}
horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
}); // Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
},
horizontalWall;
for (var x = 0; x < gridSizeX - 1; x++) {
if (_loop()) continue;
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// We won't add diagonal walls as we need only horizontal and vertical walls between the main walls
// We won't add circular/square patterns as we need only horizontal and vertical walls between the main walls
// We won't add zigzag walls as we need only horizontal and vertical walls between the main walls
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
var point = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(point);
// Handle mouse movement
// Add background to the game
var background = LK.getAsset('Background1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 1000,
scaleY: 2732 / 1075
});
game.addChildAt(background, 0);
background.x = 2048 / 2;
background.y = 2732 / 2 + 115; // Lower the background a bit from the top
game.down = function (x, y, obj) {
// Check if a wall2 asset is being clicked
game.children.forEach(function (child) {
if (child.assetId === 'wall2' && child.intersects(point)) {
game.draggedWall = child;
}
});
// Set a flag to track if the mouse is down
game.isMouseDown = true;
// Coin handling is now done exclusively in the Coin class update method
};
// Create a function to check if a position is clear of walls
function isPositionClear(x, y, minDistance) {
var isClear = true;
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
// Check if the point is too close to the wall
if (Math.abs(child.x - x) < minDistance && Math.abs(child.y - y) < minDistance) {
isClear = false;
}
}
});
return isClear;
}
// Create a function to find valid coin positions
function findValidCoinPositions(count) {
var positions = [];
var minDistanceFromWall = 50; // Minimum distance from any wall
var minDistanceBetweenCoins = 100; // Minimum distance between coins
var maxAttempts = 200; // Maximum attempts to find a valid position
// Try to find valid positions for all coins
for (var i = 0; i < count; i++) {
var validPosition = false;
var attempts = 0;
var x, y;
while (!validPosition && attempts < maxAttempts) {
// Generate a random position within the playable area
x = playableAreaLeft + cellWidth * (1 + Math.random() * (gridSizeX - 2));
y = playableAreaTop + cellHeight * (1 + Math.random() * (gridSizeY - 2));
// Check if position is clear of walls
validPosition = isPositionClear(x, y, minDistanceFromWall);
// Check if position is far enough from other coins
if (validPosition) {
for (var j = 0; j < positions.length; j++) {
if (Math.abs(positions[j].x - x) < minDistanceBetweenCoins && Math.abs(positions[j].y - y) < minDistanceBetweenCoins) {
validPosition = false;
break;
}
}
}
attempts++;
}
if (validPosition) {
positions.push({
x: x,
y: y
});
} else {
// Fallback position if we couldn't find a valid one
positions.push({
x: playableAreaLeft + (i + 1) * (playableWidth / (count + 1)),
y: playableAreaTop + (i % 2 === 0 ? playableHeight / 3 : playableHeight * 2 / 3)
});
}
}
return positions;
}
// Function to check if a position is at a corner or between wall edges
function isPositionBesideWall(x, y) {
var minProximity = 40; // Minimum distance a coin should be from a wall
var maxDistanceFromWall = 80; // Maximum distance to consider beside a wall
var isInsideWall = false;
var isAtCornerOrEdge = false;
var nearbyWalls = [];
// First check if the position is inside any wall
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
var safetyMargin = 20;
var halfWidth = child.width / 2 + safetyMargin;
var halfHeight = child.height / 2 + safetyMargin;
if (Math.abs(child.x - x) < halfWidth && Math.abs(child.y - y) < halfHeight) {
isInsideWall = true;
}
}
});
if (isInsideWall) {
return false; // Position is inside a wall, not valid
}
// Find all nearby walls
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
var distX = Math.max(Math.abs(child.x - x) - child.width / 2, 0);
var distY = Math.max(Math.abs(child.y - y) - child.height / 2, 0);
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance >= minProximity && distance <= maxDistanceFromWall) {
nearbyWalls.push({
wall: child,
distance: distance,
distX: distX,
distY: distY
});
}
}
});
// Check if position is at a corner (near multiple walls) or at wall edges
if (nearbyWalls.length >= 2) {
// Position is near multiple walls - likely a corner, which is good
isAtCornerOrEdge = true;
} else if (nearbyWalls.length === 1) {
// Position is near one wall - check if it's at the edge, not in the middle
var wall = nearbyWalls[0].wall;
var relativeX = x - wall.x;
var relativeY = y - wall.y;
var halfWidth = wall.width / 2;
var halfHeight = wall.height / 2;
// Check if position is near the edges (corners) of the wall, not in the middle
var nearLeftEdge = Math.abs(relativeX + halfWidth) < 30;
var nearRightEdge = Math.abs(relativeX - halfWidth) < 30;
var nearTopEdge = Math.abs(relativeY + halfHeight) < 30;
var nearBottomEdge = Math.abs(relativeY - halfHeight) < 30;
var nearVerticalCenter = Math.abs(relativeX) < halfWidth * 0.3;
var nearHorizontalCenter = Math.abs(relativeY) < halfHeight * 0.3;
// Position is valid if it's near an edge but not in the center of the wall
if ((nearLeftEdge || nearRightEdge || nearTopEdge || nearBottomEdge) && !(nearVerticalCenter && nearHorizontalCenter)) {
isAtCornerOrEdge = true;
}
}
return isAtCornerOrEdge;
}
// Modified findValidCoinPositions function to ensure coins are placed beside walls
function findValidCoinPositionsNextToWalls(count) {
var positions = [];
var minDistanceBetweenCoins = 100; // Minimum distance between coins
var maxAttempts = 500; // Increased max attempts to find valid positions
// Try to find valid positions for all coins
for (var i = 0; i < count; i++) {
var validPosition = false;
var attempts = 0;
var x, y;
while (!validPosition && attempts < maxAttempts) {
// Generate a random position within the playable area
x = playableAreaLeft + cellWidth * (1 + Math.random() * (gridSizeX - 2));
y = playableAreaTop + cellHeight * (1 + Math.random() * (gridSizeY - 2));
// Check if position is beside a wall but not inside it
// First verify if it's not inside any wall
var insideWall = false;
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
if (Math.abs(x - child.x) < child.width / 2 + 10 && Math.abs(y - child.y) < child.height / 2 + 10) {
insideWall = true;
}
}
});
if (!insideWall) {
// Then check if it's beside a wall
validPosition = isPositionBesideWall(x, y);
}
// Check if position is far enough from other coins
if (validPosition) {
for (var j = 0; j < positions.length; j++) {
if (Math.abs(positions[j].x - x) < minDistanceBetweenCoins && Math.abs(positions[j].y - y) < minDistanceBetweenCoins) {
validPosition = false;
break;
}
}
}
attempts++;
}
if (validPosition) {
positions.push({
x: x,
y: y
});
} else {
console.log("Could not find valid position for coin " + (i + 1) + ", using fallback");
// Fallback position if we couldn't find a valid one
// For fallback, try to find a clear position that's far from walls
var fallbackX = playableAreaLeft + (i + 1) * (playableWidth / (count + 1));
var fallbackY = playableAreaTop + (i % 2 === 0 ? playableHeight / 3 : playableHeight * 2 / 3);
// Try to adjust the fallback position to be beside a wall
for (var w = 0; w < game.children.length; w++) {
var child = game.children[w];
if (child.assetId === 'wall2') {
fallbackX = child.x + child.width / 2 + 50;
fallbackY = child.y;
var validFallback = true;
// Check if this fallback position works
game.children.forEach(function (otherChild) {
if (otherChild.assetId === 'wall1' || otherChild.assetId === 'wall2') {
if (Math.abs(fallbackX - otherChild.x) < otherChild.width / 2 + 10 && Math.abs(fallbackY - otherChild.y) < otherChild.height / 2 + 10) {
validFallback = false;
}
}
});
if (validFallback) {
break;
}
}
}
positions.push({
x: fallbackX,
y: fallbackY
});
}
}
return positions;
}
// Function to generate coin positions on each level load
function generateCoinPositions() {
// Set a completely random seed each time to ensure different positions
var randomSeed = Math.random() * 10000 + Date.now() % 10000;
// Shuffle the seed into playable area coordinates for more randomness
var seedX = Math.sin(randomSeed) * playableWidth * 0.8;
var seedY = Math.cos(randomSeed) * playableHeight * 0.8;
// Generate valid positions for 7 coins based on the current maze layout
// Use randomSeed to influence position generation
var coinPositions = [];
var attemptAreas = [
// Try different areas of the maze to distribute coins better with more randomness
{
x: playableAreaLeft + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.6 + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + playableHeight * 0.6 + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.6 + (seedX + Math.random() * 200) % playableWidth * 0.4,
y: playableAreaTop + playableHeight * 0.6 + (seedY + Math.random() * 200) % playableHeight * 0.4
}, {
x: playableAreaLeft + playableWidth * 0.5 + (seedX + Math.random() * 200) % playableWidth * 0.5,
y: playableAreaTop + playableHeight * 0.5 + (seedY + Math.random() * 200) % playableHeight * 0.5
}];
// Use the findValidCoinPositionsNextToWalls but with more randomness
// Generate many more positions than needed so we have plenty to choose from
var allPossiblePositions = findValidCoinPositionsNextToWalls(15);
// Shuffle the positions array to add more randomness
for (var i = allPossiblePositions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allPossiblePositions[i];
allPossiblePositions[i] = allPossiblePositions[j];
allPossiblePositions[j] = temp;
}
// Take the first 7 positions
coinPositions = allPossiblePositions.slice(0, 7);
// Add small amount of randomness to each position
for (var i = 0; i < coinPositions.length; i++) {
// Add a smaller random offset to avoid pushing into walls
coinPositions[i].x += Math.sin(randomSeed + i * 47.3) * cellWidth * 0.1;
coinPositions[i].y += Math.cos(randomSeed + i * 53.2) * cellHeight * 0.1;
}
// Double check each position is valid and not inside any wall
// Use a more thorough validation with a safety margin
var safetyMargin = 20; // Extra space to ensure we're not on walls
for (var i = 0; i < coinPositions.length; i++) {
var posX = coinPositions[i].x;
var posY = coinPositions[i].y;
var invalidPos = false;
// First pass to check if position is inside any wall
game.children.forEach(function (child) {
if (child.assetId === 'wall1' || child.assetId === 'wall2') {
// Use safety margin to ensure we're comfortably away from walls
if (Math.abs(posX - child.x) < child.width / 2 + safetyMargin && Math.abs(posY - child.y) < child.height / 2 + safetyMargin) {
console.log("Warning: Coin position too close to wall at:", posX, posY);
invalidPos = true;
// Try to move the position outside the wall with a significant offset
var dirX = posX > child.x ? 1 : -1;
var dirY = posY > child.y ? 1 : -1;
// Move the coin a safe distance away from the wall
coinPositions[i].x = child.x + dirX * (child.width / 2 + safetyMargin + 30 + Math.random() * 20);
coinPositions[i].y = child.y + dirY * (child.height / 2 + safetyMargin + 30 + Math.random() * 20);
// Verify the new position isn't inside another wall with a second check
var newPosX = coinPositions[i].x;
var newPosY = coinPositions[i].y;
var stillInvalid = false;
game.children.forEach(function (otherChild) {
if (otherChild.assetId === 'wall1' || otherChild.assetId === 'wall2') {
if (Math.abs(newPosX - otherChild.x) < otherChild.width / 2 + safetyMargin && Math.abs(newPosY - otherChild.y) < otherChild.height / 2 + safetyMargin) {
stillInvalid = true;
}
}
});
if (stillInvalid) {
// Try a different approach - find a clear space with more randomness
var attempts = 0;
var foundValid = false;
while (!foundValid && attempts < 20) {
// Generate a new random position in the playable area
var testX = playableAreaLeft + Math.random() * playableWidth;
var testY = playableAreaTop + Math.random() * playableHeight;
var testValid = true;
// Check if this position is clear of all walls
game.children.forEach(function (testChild) {
if (testChild.assetId === 'wall1' || testChild.assetId === 'wall2') {
if (Math.abs(testX - testChild.x) < testChild.width / 2 + safetyMargin && Math.abs(testY - testChild.y) < testChild.height / 2 + safetyMargin) {
testValid = false;
}
}
});
if (testValid) {
coinPositions[i].x = testX;
coinPositions[i].y = testY;
foundValid = true;
}
attempts++;
}
if (!foundValid) {
// Last resort - place in a known clear area
coinPositions[i].x = playableAreaLeft + playableWidth * (0.2 + 0.6 * Math.random());
coinPositions[i].y = playableAreaTop + playableHeight * (0.2 + 0.6 * Math.random());
}
}
}
}
});
}
return coinPositions;
}
// Generate initial coin positions
var coinPositions = generateCoinPositions();
// Create 7 new coin assets at positions that fit within maze corridors
for (var i = 0; i < 7; i++) {
var newCoin = new Coin();
game.addChild(newCoin);
coins.push(newCoin);
// Set the coins at positions within the maze corridors
newCoin.x = coinPositions[i].x;
newCoin.y = coinPositions[i].y;
console.log("Coin " + (i + 1) + " position: x=" + newCoin.x + ", y=" + newCoin.y);
}
// Function to reset the game for a new level
var resetGame = function resetGame() {
// Clear all existing children from the game stage except GUI
game.children.forEach(function (child) {
if (child !== LK.gui) {
child.destroy();
}
});
// Clear walls and coins arrays
walls.length = 0;
coins.length = 0;
// Reset score
LK.setScore(0);
scoreTxt.setText('0/7');
// Reset time
statusTime = 60;
statusTimeText.setText(statusTime.toString());
// Add background back
var background = LK.getAsset('Background1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 1000,
scaleY: 2732 / 1075
});
game.addChildAt(background, 0);
background.x = 2048 / 2;
background.y = 2732 / 2 + 115;
// Recreate point
point = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(point);
// Recreate walls and maze for the new level
createMaze();
// Generate new coin positions
var coinPositions = generateCoinPositions();
// Create 7 new coin assets at positions that fit within maze corridors
for (var i = 0; i < 7; i++) {
var newCoin = new Coin();
game.addChild(newCoin);
coins.push(newCoin);
// Set the coins at positions within the maze corridors
newCoin.x = coinPositions[i].x;
newCoin.y = coinPositions[i].y;
}
// Update the level text
levelText.setText('Level ' + currentLevel);
};
// Log the total number of walls and coins in the game
// Function to create the maze (extracted from original Game Code)
function createMaze() {
// Create and position the wall1 asset at the bottom of the screen
var wall1 = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Keep the original height
});
wall1.x = 2048 / 2; // Center horizontally
wall1.y = 2732 - wall1.height / 2; // Position at the bottom
game.addChild(wall1);
walls.push(wall1);
// Create and position the wall1 asset at the top of the screen
var wallTop = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the width of the screen
scaleY: 1 // Increase the vertical thickness
});
wallTop.x = 2048 / 2; // Center horizontally
wallTop.y = wallTop.height / 2; // Position at the top
game.addChild(wallTop);
walls.push(wallTop);
// Create and position the wall1 asset at the left side of the screen
var wallLeft = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallLeft.x = wallLeft.width / 2; // Position at the left
wallLeft.y = 2732 / 2; // Center vertically
game.addChild(wallLeft);
walls.push(wallLeft);
// Create right wall1 once
var wallRight = LK.getAsset('wall1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
// Keep the original width
scaleY: 2732 / 100 // Scale to fit the height of the screen
});
wallRight.x = 2048 - wallRight.width / 2; // Position at the right
wallRight.y = 2732 / 2; // Center vertically
game.addChild(wallRight);
walls.push(wallRight);
// Calculate playable area dimensions
var playableAreaLeft = wallLeft.width;
var playableAreaRight = 2048 - wallRight.width;
var playableAreaTop = wallTop.height;
var playableAreaBottom = 2732 - wall1.height;
var playableWidth = playableAreaRight - playableAreaLeft;
var playableHeight = playableAreaBottom - playableAreaTop;
// Create a grid-like maze with corridors sized for coins to pass through
var gridSizeX = 12; // Number of vertical sections
var gridSizeY = 15; // Number of horizontal sections
var cellWidth = playableWidth / gridSizeX;
var cellHeight = playableHeight / gridSizeY;
var wallThickness = 0.8; // Wall thickness factor
// Create horizontal walls with gaps for a proper maze
for (var y = 1; y < gridSizeY; y += 2) {
for (var x = 0; x < gridSizeX - 1; x++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var horizontalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth / 100,
scaleY: wallThickness
});
// Position the wall between cells, inside the main walls
horizontalWall.x = playableAreaLeft + (x + 0.5) * cellWidth;
horizontalWall.y = playableAreaTop + y * cellHeight;
// Make sure the wall is inside the playable area
if (horizontalWall.x > playableAreaLeft + horizontalWall.width / 2 && horizontalWall.x < playableAreaRight - horizontalWall.width / 2) {
game.addChild(horizontalWall);
walls.push(horizontalWall);
}
}
}
// Create vertical walls with gaps for a proper maze
for (var x = 1; x < gridSizeX; x += 2) {
for (var y = 0; y < gridSizeY - 1; y++) {
// Skip some walls to create paths (40% chance)
if (Math.random() > 0.6) {
continue;
}
var verticalWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight / 100
});
// Position the wall between cells, inside the main walls
verticalWall.x = playableAreaLeft + x * cellWidth;
verticalWall.y = playableAreaTop + (y + 0.5) * cellHeight;
// Make sure the wall is inside the playable area
if (verticalWall.y > playableAreaTop + verticalWall.height / 2 && verticalWall.y < playableAreaBottom - verticalWall.height / 2) {
game.addChild(verticalWall);
walls.push(verticalWall);
}
}
}
// Add some additional wall2 sections to make the maze harder
for (var i = 0; i < 15; i++) {
// Random position within the playable area
var posX = playableAreaLeft + Math.random() * (playableWidth - 200) + 100;
var posY = playableAreaTop + Math.random() * (playableHeight - 200) + 100;
// 50% chance for horizontal or vertical wall
if (Math.random() > 0.5) {
// Horizontal wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellWidth * (1 + Math.random()) / 100,
scaleY: wallThickness
});
extraWall.x = posX;
extraWall.y = posY;
} else {
// Vertical wall
var extraWall = LK.getAsset('wall2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: wallThickness,
scaleY: cellHeight * (1 + Math.random()) / 100
});
extraWall.x = posX;
extraWall.y = posY;
}
// Make sure we're not adding walls too close to the coins
var tooClose = false;
game.children.forEach(function (child) {
if (child instanceof Coin && Math.abs(child.x - extraWall.x) < cellWidth * 1.5 && Math.abs(child.y - extraWall.y) < cellHeight * 1.5) {
tooClose = true;
}
});
if (!tooClose) {
game.addChild(extraWall);
walls.push(extraWall);
}
}
}
// Create the initial maze for Level 1
createMaze();
console.log("Total walls in game: " + walls.length);
console.log("Total coins in game: " + coins.length);
game.up = function (x, y, obj) {
// Reset the dragged wall when the mouse is released
game.draggedWall = null;
game.isMouseDown = false;
};
// Set a flag to track if the mouse is up
game.isMouseDown = false;
// Add level text to the top right side
var levelText = new Text2('Level 1', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0); // Sets anchor to the top right edge of the text.
LK.gui.topRight.addChild(levelText);
// Initialize status time
var statusTime = 60; // 60 seconds = 1 minute
// Initialize status time text
var statusTimeText = new Text2(statusTime.toString(), {
size: 80,
fill: 0xFFFFFF
});
// Initialize score text to display the number of coins after a slash
var scoreTxt = new Text2('0/7', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0); // Sets anchor to the top left edge of the text.
statusTimeText.anchor.set(-0.8, 0); // Sets anchor to the top center edge of the text.
LK.gui.top.addChild(statusTimeText);
// Position the score text directly to the left of the time text
scoreTxt.x = -400; // Position score text to the left of time text
LK.gui.top.addChild(scoreTxt);
// Create a timer that decreases the status time every second
var statusTimeTimer = LK.setInterval(function () {
statusTime--;
// Update the status time text
statusTimeText.setText(statusTime.toString());
// If the status time reaches 0, stop the timer and show game over
if (statusTime <= 0) {
LK.clearInterval(statusTimeTimer);
LK.showGameOver();
}
}, 1000); // 1000 milliseconds = 1 second
// Update the score display to show the number of coins after a slash
scoreTxt.setText(LK.getScore() + '/7');
game.move = function (x, y, obj) {
// Check if the mouse is down and a wall2 asset is being dragged
if (game.isMouseDown && game.draggedWall) {
game.draggedWall.x = x;
game.draggedWall.y = y;
} else {
// Check if the cursor reaches any wall2 asset
game.children.forEach(function (child) {
if (child.assetId === 'wall2' && point.intersects(child)) {
game.draggedWall = child;
}
});
}
// Update the position of the point asset to the current mouse position
point.x = x;
point.y = y;
// Draw the way of cursor by point asset when its moving
var newPoint = LK.getAsset('point', {
anchorX: 0.5,
anchorY: 0.5
});
newPoint.x = x;
newPoint.y = y;
game.addChild(newPoint);
// Check for intersection with wall1 and wall2 assets
game.children.forEach(function (child) {
if ((child.assetId === 'wall1' || child.assetId === 'wall2') && point.intersects(child)) {
// Handle collision with wall1 or wall2
console.log("Collision detected with wall:", child.assetId);
// Implement any specific logic needed for collision with walls
}
});
// Coin collision is now handled in the Coin class update method
// We don't need to check for coin collisions here anymore
};