/**** * 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
};