User prompt
Make sure that the collected cheese asset is visible on the hole tile after the A button is pressed
User prompt
Turn in the cheese when is collected on the hole tile
User prompt
Please fix the bug: 'ReferenceError: cheese is not defined' in or related to this line: 'isCharacterMoving = cheese.isMoving ? false : true;' Line Number: 217
User prompt
Stop character for moving while the cheese is moving to the scoreboard
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addEventListener')' in or related to this line: 'document.addEventListener('keydown', function (event) {' Line Number: 523
User prompt
add support to play the game with keyboard (W,A,S,D) for the Dpad and spacebar for the Abutton
User prompt
avoid that the hole tile has 2 empty Neighbours
User prompt
change the logic for placing obstacles, avoid obstacles touching walls
User prompt
Please fix the bug: 'Uncaught ReferenceError: obstacleTiles is not defined' in or related to this line: 'return Math.abs(tile.x - corner.x) < tileWidth / 2 && Math.abs(tile.y - corner.y) < tileHeight / 2;' Line Number: 674
User prompt
Please fix the bug: 'Uncaught ReferenceError: doesTileSurroundHole is not defined' in or related to this line: 'return Math.abs(tile.x - corner.x) < tileWidth / 2 && Math.abs(tile.y - corner.y) < tileHeight / 2;' Line Number: 666
User prompt
make sure the hole tile is never fully surrounded by obstacles, walls or obstacles and walls or at a a corner of the grid, use grid offsets in the calculations
User prompt
make sure cheeses are never fully surrounded by obstacles, walls or obstacles and walls
User prompt
remove obstacles from the floor if no valid path to the cheeses is available
User prompt
Please fix the bug: 'Uncaught ReferenceError: isTileBlockingPath is not defined' in or related to this line: 'if (!isTileBlockingPath(tile, cheeses, holeTile)) {' Line Number: 572
User prompt
add obstacle tiles at random by replacing some floor tiles, ensure at least one path from the hole tile to the cheeses is valid
User prompt
ensure always a path from the hole to all cheese
User prompt
force the refresh of the UI on game start
User prompt
make the moving cheese visible
User prompt
enable visibility of the last collected cheese one is placed on the hole tile
User prompt
smoothly move the last collected cheese from the hole tile to the cheese icon on the scoreboard
User prompt
remove outline from all text
User prompt
tint the character with this hex code: #eeeee4
User prompt
remove random color and just add random brightness changes
User prompt
make sure the random tint colors are just shades of grey, no hue
User prompt
Add a random shade of gray tint to all floor tiles
/**** * Classes ****/ var Cheese = Container.expand(function () { var self = Container.call(this); // Attach cheese asset with anchor point set to center var cheeseShadow = self.attachAsset('CircularShadow', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, alpha: 0.5, y: 20 // zIndex removed }); var cheeseGraphics = self.attachAsset('cheese', { anchorX: 0.5, anchorY: 0.5 // zIndex removed }); // Lerp cheese to a target position self.lerpToPosition = function (startPos, endPos, duration, onComplete) { var startTime = Date.now(); self.isMoving = true; // Flag cheese as moving var lerpInterval = LK.setInterval(function () { var currentTime = Date.now(); var timeElapsed = currentTime - startTime; var lerpFactor = timeElapsed / duration; if (lerpFactor >= 1) { LK.clearInterval(lerpInterval); self.x = endPos.x; self.y = endPos.y; if (onComplete) { onComplete(); } self.isMoving = false; // Reset cheese moving flag } else { self.x = startPos.x + (endPos.x - startPos.x) * lerpFactor; self.y = startPos.y + (endPos.y - startPos.y) * lerpFactor; } }, 16); // Update approximately every 16ms (~60fps) }; }); // Modular Enemy class to support different enemy types var Enemy = Container.expand(function (type) { var self = Container.call(this); var shadowAssetId, enemyAssetId, shadowScale, enemySpeed; // Enemy type enumerator with stats var EnemyTypes = { Roomba: { shadowAssetId: 'CircularShadow', enemyAssetId: 'Roomba', shadowScale: 3.2, enemySpeed: 2.64 } // Define additional enemy types here }; // Retrieve enemy type stats var enemyStats = EnemyTypes[type]; if (!enemyStats) { console.error('Unknown enemy type:', type); return; } shadowAssetId = enemyStats.shadowAssetId; enemyAssetId = enemyStats.enemyAssetId; shadowScale = enemyStats.shadowScale; enemySpeed = enemyStats.enemySpeed; // Attach a shadow asset to the enemy and make it semitransparent var shadowGraphics = self.attachAsset(shadowAssetId, { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, scaleX: shadowScale, scaleY: shadowScale // zIndex removed }); var enemyGraphics = self.attachAsset(enemyAssetId, { anchorX: 0.5, anchorY: 0.5 // zIndex removed }); // Adjust shadow position relative to the enemy shadowGraphics.x = enemyGraphics.x; shadowGraphics.y = enemyGraphics.y + 40; // Slightly below the enemy for a realistic shadow effect // Set enemy speed self.speed = enemySpeed; // Enemy movement logic self.move = function () { // Implement avoidance behavior for Roombas enemies.forEach(function (otherEnemy) { if (otherEnemy !== self) { var dx = self.x - otherEnemy.x; var dy = self.y - otherEnemy.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Calculate direction to move away from the other Roomba var awayX = dx / distance; var awayY = dy / distance; self.x += awayX * self.speed; // Move self away from the other Roomba self.y += awayY * self.speed; } } }); // Introduce a collision counter to track continuous collisions if (!self.collisionCounter) { self.collisionCounter = 0; } // Increase collision counter on collision if (self.colliding) { self.collisionCounter++; } else { self.collisionCounter = 0; // Reset counter if not colliding } // Change target tile if colliding for too long or reached current target if (!self.targetTile || self.collisionCounter > 30 || Math.sqrt(Math.pow(self.x - self.targetTile.x, 2) + Math.pow(self.y - self.targetTile.y, 2)) < 10) { self.targetTile = floorTiles[Math.floor(Math.random() * floorTiles.length)]; self.collisionCounter = 0; // Reset collision counter after changing target } // Reset colliding flag for the next tick self.colliding = false; var angleToTarget = Math.atan2(self.targetTile.y - self.y, self.targetTile.x - self.x); self.x += Math.cos(angleToTarget) * self.speed; self.y += Math.sin(angleToTarget) * self.speed; // Smoothly rotate the enemy towards the target angle var currentAngle = enemyGraphics.rotation; var targetAngle = angleToTarget; // Calculate the shortest direction to rotate var angleDifference = targetAngle - currentAngle; angleDifference += angleDifference > Math.PI ? -2 * Math.PI : angleDifference < -Math.PI ? 2 * Math.PI : 0; var rotationSpeed = 0.1; // Adjust rotation speed as needed enemyGraphics.rotation += angleDifference * rotationSpeed; }; }); // OnScreenController class encapsulating A, B buttons and D-pad var OnScreenController = Container.expand(function () { var self = Container.call(this); // Add a background for the on screen controllers var yPosAdjustment = -180; var buttonYPosAdjustment = -273.2; var dpadButtonSize = 350; // Increased size for better visibility and interaction // Removed redundant tint application on A and B buttons LK.screen = { width: 2048, height: 2732 }; // Initialize screen dimensions var aButtonPosition = { x: LK.screen.width * 0.75, y: LK.screen.height * 0.85 + buttonYPosAdjustment + LK.screen.height * 0.055 }; var buttonSize = { width: 400, height: 400 }; var dPadSize = { width: 750, height: 750 }; this.aButton = self.attachAsset('aButton', { anchorX: 0.5, anchorY: 0.5, x: aButtonPosition.x, y: aButtonPosition.y, width: buttonSize.width, height: buttonSize.height }); // D-pad var dpadBase = self.attachAsset('dpadBase', { anchorX: 0.5, anchorY: 0.5, x: LK.screen.width * 0.24, y: LK.screen.height * 0.89 + yPosAdjustment - 10, width: dPadSize.width, height: dPadSize.height }); self.setChildIndex(dpadBase, self.children.length - 1); var dpadLeft = self.attachAsset('dpadButtonLeft', { anchorX: 0.5, anchorY: 0.5, x: dpadBase.x - 300, y: dpadBase.y, width: dpadButtonSize, height: dpadButtonSize, alpha: 0, // Tint arrow yellow orientation: 3 }); var moveInterval; function startMovingCharacter(xDir, yDir) { if (moveInterval) { LK.clearInterval(moveInterval); } // Temporarily disable character movement while cheese is moving isCharacterMoving = cheeseIcon && cheeseIcon.isMoving ? false : true; moveCharacter(xDir, yDir); moveInterval = LK.setInterval(function () { moveCharacter(xDir, yDir); }, 150); } dpadLeft.on('down', function () { startMovingCharacter(-1, 0); }); var dpadUp = self.attachAsset('dpadButtonUp', { anchorX: 0.5, anchorY: 0.5, x: dpadBase.x, y: dpadBase.y - 300, width: dpadButtonSize, height: dpadButtonSize, alpha: 0, // Tint arrow yellow orientation: 0 }); dpadUp.on('down', function () { startMovingCharacter(0, -1); }); var dpadRight = self.attachAsset('dpadButtonRight', { anchorX: 0.5, anchorY: 0.5, x: dpadBase.x + 300, y: dpadBase.y, width: dpadButtonSize, height: dpadButtonSize, alpha: 0, orientation: 1 }); dpadRight.on('down', function () { startMovingCharacter(1, 0); }); var dpadDown = self.attachAsset('dpadButtonDown', { anchorX: 0.5, anchorY: 0.5, x: dpadBase.x, y: dpadBase.y + 300, width: dpadButtonSize, height: dpadButtonSize, alpha: 0, orientation: 2 }); dpadDown.on('down', function () { startMovingCharacter(0, 1); }); function stopMovingCharacter() { isCharacterMoving = false; LK.clearInterval(moveInterval); } dpadLeft.on('up', stopMovingCharacter); dpadUp.on('up', stopMovingCharacter); dpadRight.on('up', stopMovingCharacter); dpadDown.on('up', stopMovingCharacter); }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf9e076 // Fun yellow background }); /**** * Game Code ****/ // Function to check if a new obstacle tile fully surrounds any cheese function doesTileSurroundCheese(obstacleTile, cheeses) { return cheeses.some(function (cheese) { // Calculate adjacent tiles to the cheese var adjacentTiles = [{ x: cheese.x - tileWidth, y: cheese.y }, { x: cheese.x + tileWidth, y: cheese.y }, { x: cheese.x, y: cheese.y - tileHeight }, { x: cheese.x, y: cheese.y + tileHeight }]; // Check if all adjacent tiles are either walls, obstacles, or the new obstacle tile return adjacentTiles.every(function (tile) { return wallTiles.some(function (wallTile) { return wallTile.x === tile.x && wallTile.y === tile.y; }) || grid.some(function (gridTile) { return gridTile && gridTile.x === tile.x && gridTile.y === tile.y && gridTile !== cheese && gridTile !== obstacleTile; }); }); }); } // Function to check if placing a tile would block all paths to cheeses or the hole function isTileBlockingPath(tile, cheeses, holeTile) { // Placeholder for path checking logic // This should implement an algorithm to check if any cheese or the holeTile is unreachable due to the new tile // For simplicity, this example will just return false indicating the tile placement doesn't block the path // Implement actual path checking logic here return false; } // Add sticker02 asset to the bottom of the screen next to sticker and rotate it 32 degrees var sticker02 = game.addChild(LK.getAsset('sticker02', { anchorX: 1.0, anchorY: 1.0, x: 2200, y: 2100, rotation: -0.558 })); // Add sticker asset to the bottom of the screen and rotate it 32 degrees var sticker = LK.getAsset('sticker', { anchorX: 0.5, anchorY: 0.5, x: 900, y: 2300, // Considering half of the sticker's height for proper alignment rotation: 0.10 // Rotating 32 degrees in radians }); game.addChild(sticker); // Update play time display every second LK.on('tick', function () { var minutes = Math.floor(playTime / 60); var seconds = playTime % 60; playTimeDisplay.setText((minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds); }); // Create a timer to update play time every second var playTimeTimer = LK.setInterval(function () { playTime += 1; }, 1000); // Initialize play time tracking var playTime = 0; // EventManager class for centralized event handling // Initialize EventManager for global event handling var EventManager = { events: {}, subscribe: function subscribe(eventType, listener) { if (!this.events[eventType]) { this.events[eventType] = []; } this.events[eventType].push(listener); }, unsubscribe: function unsubscribe(eventType, listener) { if (this.events[eventType]) { var index = this.events[eventType].indexOf(listener); if (index > -1) { this.events[eventType].splice(index, 1); } } }, publish: function publish(eventType, data) { if (this.events[eventType]) { this.events[eventType].forEach(function (listener) { listener(data); }); } } }; game.eventManager = EventManager; // Subscribe to 'gameStart' event to initialize character and game state game.eventManager.subscribe('gameStart', function () { isGameStarted = true; character = LK.getAsset('character', { anchorX: 0.5, anchorY: 0.5, x: holeTile.x, y: holeTile.y - 50, scaleX: 1.5, scaleY: 1.5 }); // Force UI refresh window.updateCheeseScore(LK.getScore()); }); // Initialize scoreboard container and elements once and update score dynamically if (!window.scoreBoardInitialized) { var updateCheeseScore = function updateCheeseScore(score) { cheeseScoreDisplay.setText(score.toString()); }; window.scoreBoardContainer = new Container(); var scoreBoardX = 200, scoreBoardY = 125; var cheeseIconForScore = window.scoreBoardContainer.attachAsset('cheese', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: -35, y: 0 }); // Dynamically add one character lives icon per available life var availableLives = 3; // Assuming 3 lives to start with var livesIcons = []; for (var i = 0; i < availableLives; i++) { var lifeIcon = window.scoreBoardContainer.attachAsset('characterLivesIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, // Scale increased to make the icon 3 times bigger scaleY: 1.5, // Scale increased to make the icon 3 times bigger x: 1070 - i * 120, // Position each icon with a gap of 80px y: 0 }); livesIcons.push(lifeIcon); } // Cheese score display added to the scoreboard var cheeseScoreDisplay = new Text2('0', { size: 50, fill: "#E0E0E0", font: "Roboto, bold", x: cheeseIconForScore.x + 120, y: cheeseIconForScore.y }); cheeseScoreDisplay.anchor.set(-.4, 0.7); window.scoreBoardContainer.addChild(cheeseScoreDisplay); // Update cheese score display function window.updateCheeseScore = updateCheeseScore; // Character lives text asset creation and addition to scoreBoardContainer removed // Add play time display to the scoreboard // Initialize screen dimensions for playTimeDisplay positioning LK.screen = { width: 2048, height: 2732 }; var playTimeDisplay = new Text2('00:00', { size: 50, fill: "#E0E0E0", font: "Roboto, bold", x: -LK.screen.width / 2, y: 50 }); playTimeDisplay.anchor.set(-3, 0.5); // Center the text horizontally window.scoreBoardContainer.addChild(playTimeDisplay); window.scoreBoardContainer.x = scoreBoardX; window.scoreBoardContainer.y = scoreBoardY; LK.gui.addChild(window.scoreBoardContainer); window.scoreBoardInitialized = true; } // Update score dynamically without recreating the scoreboard elements // Update score dynamically without recreating the scoreboard elements // This block intentionally left blank to signify removal of the above code // Move the onScreenController initialization to the top of Game Code section to ensure it's available before adding event listeners var onScreenController = game.addChild(new OnScreenController()); // Event listener for A button press to pick up the cheese using a refined proximity check and method encapsulation onScreenController.aButton.on('down', function () { // Check if character is near any cheese to pick it up cheeses.forEach(function (cheese) { if (isWithinProximity(character, cheese, 75) && !cheese.collected) { console.log('Cheese picked up!'); cheese.visible = false; // Hide the picked cheese from the game cheese.collected = true; // Mark cheese as collected // Show UI icon indicating cheese has been picked up only if not already visible // This block intentionally left blank to signify removal of the above code // Increment availableCheeses count when a cheese is picked up availableCheeses += 1; // Update cheeseIcon visibility based on availableCheeses count if (availableCheeses > 0) { if (!cheeseIcon) { cheeseIcon = character.attachAsset('cheese', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -character.height * 0.75, scaleX: 0.5, scaleY: 0.5 }); } cheeseIcon.visible = true; } } }); // Check if character is on the hole tile to drop off collected cheese if (isWithinProximity(character, holeTile, 75) && cheeseIcon && cheeseIcon.visible) { console.log('Cheese placed on hole tile!'); // Smoothly move the last collected cheese to the hole tile instead of the scoreboard var lastCollectedCheese = cheeses.find(function (cheese) { return cheese.collected && !cheese.scoreCounted; }); if (lastCollectedCheese) { lastCollectedCheese.lerpToPosition({ x: lastCollectedCheese.x, y: lastCollectedCheese.y }, { x: holeTile.x, y: holeTile.y }, 1000, function () { // Hide cheese icon on character after moving to hole tile cheeseIcon.visible = false; // Increase score for each cheese collected and not yet scored cheeses.forEach(function (cheese) { if (cheese.collected && !cheese.scoreCounted) { LK.setScore(LK.getScore() + 1); // Add one to the score for each cheese collected cheese.scoreCounted = true; // Mark cheese as counted to prevent scoring it again window.updateCheeseScore(LK.getScore()); // Update cheese score display } }); }); } } }); // Helper function to check if two objects are within a certain distance function isWithinProximity(obj1, obj2, threshold) { return Math.abs(obj1.x - obj2.x) < threshold && Math.abs(obj1.y - obj2.y) < threshold; } var isCharacterMoving = false; // Function to move character based on direction and keyboard input // Keyboard event listener removed to prevent TypeError due to undefined 'document' var dpadButtonSize = { width: 450, height: 450 }; function moveCharacter(xDir, yDir) { if (availableLives <= 0) { return; } var nextX = character.x + xDir * tileWidth; var nextY = character.y + yDir * tileHeight; // Check if the next position is within the grid boundaries if (nextX >= gridOffsetX && nextX <= gridOffsetX + gridSize * tileWidth && nextY >= gridOffsetY && nextY <= gridOffsetY + gridSize * tileHeight) { // Check if the next tile is not a wall var nextTileIndex = Math.floor((nextY - gridOffsetY) / tileHeight) * gridSize + Math.floor((nextX - gridOffsetX) / tileWidth); if (floorTiles.includes(grid[nextTileIndex]) || holeTile && grid[nextTileIndex].x === holeTile.x && grid[nextTileIndex].y === holeTile.y) { character.x = nextX; character.y = nextY; character.currentTile = grid[nextTileIndex]; } } } LK.screen = { width: 2048, height: 2732 }; // Initialize screen dimensions var gridSize = 10; var character; var cheeses = []; // Initialize cheeses array globally var availableCheeses = 0; // Initialize variable to track available cheeses for collection var cheeseScore = 0; // Initialize cheese score variable var cheeseIcon; // Declare cheeseIcon as a global variable var wallTiles = []; var obstacleTiles = []; // Define obstacleTiles array var floorTiles = []; var grid = new Array(gridSize * gridSize); var tileWidth = LK.screen.width * .6 / (gridSize - 1); // Adjust tile width to ensure tiles are touching var tileHeight = tileWidth; // Ensure square tiles for a uniform grid var gridOffsetX = (LK.screen.width - tileWidth * gridSize) / 2; // Corrected grid offset X calculation var gridOffsetY = (LK.screen.height - tileHeight * gridSize) / 2 - LK.screen.height * 0.15; // Corrected grid offset Y calculation // Move the onScreenController initialization to the top of Game Code section to ensure it's available before adding event listeners var onScreenController = game.addChild(new OnScreenController()); // Removed the A button press event listener for picking up cheese based on tile comparison function createTiles() { // Create a black square background for the grid var gridBackground = LK.getAsset('gridBackground', { anchorX: 0.5, anchorY: 0.8, x: LK.screen.width / 2, y: LK.screen.height / 2, width: LK.screen.width * .9, height: LK.screen.height * .6, tint: 0xFFA500 // Apply orange tint }); game.addChild(gridBackground); var gridBackgroundShrunk = LK.getAsset('gridBackground', { anchorX: 0.5, anchorY: 0.8, x: LK.screen.width / 2, y: LK.screen.height / 2, width: LK.screen.width * .9 - 50, height: LK.screen.height * .6 - 50, tint: 0x000000 // Apply black tint }); game.addChild(gridBackgroundShrunk); game.setChildIndex(gridBackgroundShrunk, game.getChildIndex(gridBackground) + 1); for (var i = 0; i < gridSize * gridSize; i++) { var x = i % gridSize; var y = Math.floor(i / gridSize); var tile; var tileWidth = LK.screen.width * .6 / (gridSize - 1); // Adjust tile width to ensure tiles are touching var tileHeight = tileWidth; // Ensure square tiles for a uniform grid var gridOffsetX = (LK.screen.width - tileWidth * (gridSize - 1)) / 2; // Adjust grid offset to account for new tile width var gridOffsetY = (LK.screen.height - tileHeight * (gridSize - 1)) / 2 - LK.screen.height * 0.15; // Adjust grid offset to account for new tile height if (!(x === 0 || y === 0 || x === gridSize - 1 || y === gridSize - 1)) { tile = LK.getAsset('floorTile', { anchorX: 0.5, anchorY: 0.5, x: x * tileWidth + gridOffsetX, y: y * tileHeight + gridOffsetY }); // Randomly replace some floor tiles with obstacle tiles, ensuring at least one valid path remains // Placeholder logic for path validation and obstacle placement if (Math.random() < 0.3 && !(x === 1 || y === 1 || x === gridSize - 2 || y === gridSize - 2)) { // Temporarily turn a tile into an obstacle to check if it blocks any path var tempObstacleTile = LK.getAsset('obstacleTile', { anchorX: 0.5, anchorY: 0.5, x: x * tileWidth + gridOffsetX, y: y * tileHeight + gridOffsetY }); // Check if the temporary obstacle tile blocks the path or fully surrounds any cheese var blocksPathOrSurroundsCheese = isTileBlockingPath(tempObstacleTile, cheeses, holeTile) || doesTileSurroundCheese(tempObstacleTile, cheeses); if (!blocksPathOrSurroundsCheese) { // If it doesn't block the path or fully surround any cheese, add it to the game game.addChild(tempObstacleTile); grid[i] = tempObstacleTile; } else { // If it blocks the path or fully surrounds any cheese, revert to a floor tile floorTiles.push(tile); game.addChild(tile); grid[i] = tile; } } else { floorTiles.push(tile); game.addChild(tile); grid[i] = tile; } // Note: The function isTileBlockingPath() needs to be implemented to check if placing an obstacle would block all paths to cheeses or the hole } } // Add walls after floor tiles to ensure they render on top for (var i = 0; i < gridSize * gridSize; i++) { var x = i % gridSize; var y = Math.floor(i / gridSize); if (x === 0 || y === 0 || x === gridSize - 1 || y === gridSize - 1) { var tile = LK.getAsset('wallTile', { anchorX: 0.5, anchorY: 0.5, x: x * tileWidth + gridOffsetX, y: y * tileHeight + gridOffsetY }); wallTiles.push(tile); game.addChild(tile); grid[i] = tile; } } } createTiles(); // Function to check if a tile fully surrounds the hole function doesTileSurroundHole(tile, wallTiles, obstacleTiles) { // Placeholder for logic to check if the tile surrounds the hole // This should implement an algorithm to check if the hole is fully surrounded by walls or obstacles due to the new tile // For simplicity, this example will just return false indicating the tile placement doesn't surround the hole // Implement actual surrounding checking logic here return false; } // Function to check if a tile is in a corner function isTileInCorner(tile) { var corners = [{ x: LK.screen.width / 2 - tileWidth * gridSize / 2, y: LK.screen.height / 2 - tileHeight * gridSize / 2 }, { x: LK.screen.width / 2 - tileWidth * gridSize / 2, y: LK.screen.height / 2 + tileHeight * (gridSize - 1) / 2 }, { x: LK.screen.width / 2 + tileWidth * (gridSize - 1) / 2, y: LK.screen.height / 2 - tileHeight * gridSize / 2 }, { x: LK.screen.width / 2 + tileWidth * (gridSize - 1) / 2, y: LK.screen.height / 2 + tileHeight * (gridSize - 1) / 2 }]; return corners.some(function (corner) { return Math.abs(tile.x - corner.x) < tileWidth / 2 && Math.abs(tile.y - corner.y) < tileHeight / 2; }); } // Select a random wall tile and replace it with a hole tile, ensuring it's not in a corner var validWallTiles = wallTiles.filter(function (tile) { // Exclude tiles that are in the corners, could potentially fully surround the hole tile, or have more than 1 empty neighbour return !isTileInCorner(tile) && !doesTileSurroundHole(tile, wallTiles, obstacleTiles) && function () { var emptyNeighbours = 0; var neighbourOffsets = [[-1, 0], [1, 0], [0, -1], [0, 1]]; neighbourOffsets.forEach(function (offset) { var neighbourX = tile.x / tileWidth + offset[0]; var neighbourY = tile.y / tileHeight + offset[1]; if (neighbourX >= 0 && neighbourX < gridSize && neighbourY >= 0 && neighbourY < gridSize) { var neighbourIndex = neighbourY * gridSize + neighbourX; if (!wallTiles.some(function (wall) { return wall.x === neighbourX * tileWidth && wall.y === neighbourY * tileHeight; }) && !obstacleTiles.some(function (obstacle) { return obstacle.x === neighbourX * tileWidth && obstacle.y === neighbourY * tileHeight; })) { emptyNeighbours++; } } }); return emptyNeighbours <= 1; }(); }); var randomWallTile = validWallTiles[Math.floor(Math.random() * validWallTiles.length)]; var holeTile = LK.getAsset('holeTile', { anchorX: 0.5, anchorY: 0.5, x: randomWallTile.x, y: randomWallTile.y }); game.addChild(holeTile); game.removeChild(randomWallTile); var randomWallTileIndex = wallTiles.indexOf(randomWallTile); wallTiles[randomWallTileIndex] = holeTile; var isGameStarted = false; var cheesePlaced = false; LK.on('tick', function () { if (!isGameStarted) { game.eventManager.publish('gameStart', null); var currentCheesePosition = { x: 0, y: 0 }; // Initialize variable to store cheese position // Initialize cheese instances to place them on the floor cheeses.push(game.addChild(new Cheese())); cheeses.push(game.addChild(new Cheese())); cheeses.push(game.addChild(new Cheese())); if (!cheesePlaced) { // Ensure cheese is initialized before accessing its properties // Since cheeses are now handled as an array, we iterate over them to save their positions cheeses.forEach(function (cheese) { currentCheesePosition.x = cheese.x; // Save current cheese x position currentCheesePosition.y = cheese.y; // Save current cheese y position }); // Filter out tiles that are too close to corners var nonCornerFloorTiles = floorTiles.filter(function (tile) { return !isTileInCorner(tile); }); // Further filter to find tiles farthest from the character's starting position var farthestTiles = nonCornerFloorTiles.filter(function (tile) { var distanceToCharacter = Math.sqrt(Math.pow(tile.x - character.x, 2) + Math.pow(tile.y - character.y, 2)); return distanceToCharacter > LK.screen.width / 2; // Arbitrary distance threshold }); // If no tile is found far enough (unlikely but possible), default to non-corner tiles var targetTiles = farthestTiles.length > 0 ? farthestTiles : nonCornerFloorTiles; // Select a random tile from the final list var randomFloorTile = targetTiles[Math.floor(Math.random() * targetTiles.length)]; // Correctly iterate over cheeses array to place each cheese on a unique random floor tile cheeses.forEach(function (cheese) { // Ensure a unique tile is selected for each cheese var uniqueTileIndex = Math.floor(Math.random() * targetTiles.length); var uniqueFloorTile = targetTiles.splice(uniqueTileIndex, 1)[0]; // Remove the selected tile from the pool to ensure uniqueness if (uniqueFloorTile) { // Check if a tile was successfully selected cheese.x = uniqueFloorTile.x; cheese.y = uniqueFloorTile.y; } }); cheesePlaced = true; // Indicate that cheeses have been placed } var characterShadow = LK.getAsset('characterShadow', { anchorX: 0.5, anchorY: 0.5, x: -15, y: 50, scaleX: 0.6, scaleY: 0.6, alpha: 0.5 // zIndex removed }); character.addChild(characterShadow); character.currentTile = getTileAtPosition(holeTile.x, holeTile.y); // Correctly initialize character's current tile game.addChild(character); } // Iterate over enemies array to move each enemy and check for collision with character enemies.forEach(function (enemy) { enemy.move(); // Check if enemy intersects with character if (enemy.intersects(character) && Math.sqrt(Math.pow(enemy.x - character.x, 2) + Math.pow(enemy.y - character.y, 2)) < 200 && !character.isImmune && !(Math.abs(character.x - holeTile.x) < 75 && Math.abs(character.y - holeTile.y) < 75)) { // Reduce character lives by 1 availableLives -= 1; // Update lives display and make live icons disappear when player gets hit // Update lives display and make live icons disappear when player loses a life livesIcons.forEach(function (icon, index) { icon.visible = index < availableLives; }); // Make character blink to indicate damage and grant temporary immunity character.isImmune = true; // Set immunity flag to true var blinkInterval = LK.setInterval(function () { character.visible = !character.visible; // Tint character red when hit character.tint = character.visible ? 0xff0000 : 0xffffff; }, 100); LK.setTimeout(function () { LK.clearInterval(blinkInterval); character.visible = true; // Reset tint to normal after blinking character.tint = 0xffffff; character.isImmune = false; // Remove immunity after 1 second }, 1000); // Check if lives are depleted if (availableLives <= 0) { character.visible = false; // Make character invisible LK.setTimeout(function () { // Convert playTime to minutes and seconds var minutes = Math.floor(playTime / 60); var seconds = playTime % 60; var formattedTime = (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds; // Show game over pop up with final play time LK.showGameOver("Final Time: " + formattedTime); }, 1000); // Wait one second before showing game over } } }); }); // Create instances of enemies and store them in an array var enemies = []; // Create instances of enemies and store them in an array enemies.push(game.addChild(new Enemy('Roomba'))); enemies.push(game.addChild(new Enemy('Roomba'))); // Removed two Roomba enemies // Position enemies // Position Roombas on opposite sides of the grid if (enemies[0]) { // Position the first Roomba on the left side enemies[0].x = floorTiles[0].x; enemies[0].y = floorTiles[0].y; } if (enemies[1]) { // Position the second Roomba on the right side var lastTileIndex = floorTiles.length - 1; enemies[1].x = floorTiles[lastTileIndex].x; enemies[1].y = floorTiles[lastTileIndex].y; } // Define a function to get the tile at a given position function getTileAtPosition(x, y) { var index = Math.floor(y / 100) * gridSize + Math.floor(x / 100); return grid[index]; }
===================================================================
--- original.js
+++ change.js
@@ -466,21 +466,21 @@
});
// Check if character is on the hole tile to drop off collected cheese
if (isWithinProximity(character, holeTile, 75) && cheeseIcon && cheeseIcon.visible) {
console.log('Cheese placed on hole tile!');
- // Smoothly move the last collected cheese to the cheese icon on the scoreboard
+ // Smoothly move the last collected cheese to the hole tile instead of the scoreboard
var lastCollectedCheese = cheeses.find(function (cheese) {
return cheese.collected && !cheese.scoreCounted;
});
if (lastCollectedCheese) {
lastCollectedCheese.lerpToPosition({
x: lastCollectedCheese.x,
y: lastCollectedCheese.y
}, {
- x: cheeseIconForScore.x + window.scoreBoardContainer.x,
- y: cheeseIconForScore.y + window.scoreBoardContainer.y
+ x: holeTile.x,
+ y: holeTile.y
}, 1000, function () {
- // Hide cheese icon on character after moving to scoreboard
+ // Hide cheese icon on character after moving to hole tile
cheeseIcon.visible = false;
// Increase score for each cheese collected and not yet scored
cheeses.forEach(function (cheese) {
if (cheese.collected && !cheese.scoreCounted) {
grey square, black border. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
simple light yellow button front view game console, clean, rounded edges, high resolution, graphic. Single Game Texture. In-Game asset. 2d. Blank background. High contrast.
Worn out sticker for a video game, 90s style, cheese, simple, vintage. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
wall view from top-down, game asset videogame, black color, simple. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. worn out sticker. 90's style. vintage. simple. top-down view. poster. sticker
top-down view, videogame character enemy, roomba, 90s style sticker, flat, no perspective, silhouette, black and white, cartoon, fun, simple, from above. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
top-down view, videogame heart, 90s style sticker, flat, no perspective, silhouette, white, cartoon, fun, simple, from above. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Black square with white outline. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.