User prompt
Add property clear on reload go the scoreboard container
User prompt
Ensure single instance only for scoreboard container
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'setText')' in or related to this line: 'cheeseScoreDisplay.setText('0');' Line Number: 556
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'setText')' in or related to this line: 'playTimeDisplay.setText((minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds);' Line Number: 496
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'setText')' in or related to this line: 'playTimeDisplay.setText((minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds);' Line Number: 496
User prompt
Refactor score board container to properly handle game over reloads
User prompt
Implement that solution
User prompt
Delete old scoreboard after reload, keep.trsck of it on a variable
User prompt
Clear previous scoreboard after reloading to prevent overlapping
User prompt
Rework scoreboard to ensure proper handling on reloads
User prompt
Reduce the amount of changes of direction upon collision to avoid shaking
User prompt
Force Roombas to change directions when colliding with another enemy
User prompt
Place dakalo text on the bottom right corner of the screen with s bit of space
User prompt
Refactor ui elements to prevent overlapping text after loading the scene
User prompt
Debug, scoreboard wrongly drawn after game reload
User prompt
Clear the previous ui container to prevent overlapping text upon reload
User prompt
Move the grid down by using offset
Code edit (1 edits merged)
Please save this source code
User prompt
Try to keep roomas apart by picking different random points to move in the grid
User prompt
Rework Roombas behavior to avoid getting stuck
User prompt
Debug enemies behavior
User prompt
Make Roombas behavior different when collide with another Roomba, try to make them repell each other
User prompt
Fix bug, wen Roombas collide they stop moving and face each other
User prompt
Fix bug, Roombas stick to each other upon collision
User prompt
Please fix the bug: 'ReferenceError: selectNewTargetTileAvoidingObstacles is not defined' in or related to this line: 'self.targetTile = selectNewTargetTileAvoidingObstacles(self.x, self.y, floorTiles, obstacleTiles);' Line Number: 113
/****
* Classes
****/
var Character = Container.expand(function () {
var self = Container.call(this);
// Character shadow attachment removed
// Character shadow attachment removed
var characterGraphics = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5
});
characterGraphics.scaleX = 1;
characterGraphics.scaleY = 1;
});
var Cheese = Container.expand(function () {
var self = Container.call(this);
// Cheese shadow attachment removed
var cheeseGraphics = self.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5
});
self.lerpToPosition = function (startPos, endPos, duration, onComplete) {
self.x = endPos.x;
self.y = endPos.y;
if (onComplete) {
onComplete();
}
};
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
self.id = Math.random().toString(36).substr(2, 9); // Unique ID for each Roomba
var shadowAssetId, enemyAssetId, shadowScale, enemySpeed;
// Moved globalEnemySpeed initialization outside of Enemy class to fix 'ReferenceError'
var level = 0; // Initialize level variable
// Moved globalEnemySpeed initialization outside of Enemy class to fix 'ReferenceError'
var defaultEnemySpeed = globalEnemySpeed; // Use global enemy speed for initial speed
var EnemyTypes = {
Roomba: {
shadowAssetId: 'CircularShadow',
enemyAssetId: 'Roomba',
shadowScale: 3.2,
enemySpeed: defaultEnemySpeed * (1.03 + level * 0.05) // Increase speed by 3% plus an additional 5% per level
}
};
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;
var shadowGraphics = self.attachAsset(shadowAssetId, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
scaleX: shadowScale,
scaleY: shadowScale
});
var enemyGraphics = self.attachAsset(enemyAssetId, {
anchorX: 0.5,
anchorY: 0.5
});
// 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 () {
// Enhanced enemy behavior with dynamic avoidance and pathfinding
enemies.forEach(function (otherEnemy) {
if (otherEnemy.id !== self.id) {
var dx = self.x - otherEnemy.x;
var dy = self.y - otherEnemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 250 && distance > 0) {
var awayX = dx / distance;
var awayY = dy / distance;
// Adjust repulsion to be more dynamic based on distance
var repulsionStrength = Math.max(1, 250 - distance) / 50; // Increase repulsion as enemies get closer
self.x += awayX * self.speed * repulsionStrength;
self.y += awayY * self.speed * repulsionStrength;
// Force Roombas to change direction upon collision
self.targetTile = floorTiles[Math.floor(Math.random() * floorTiles.length)];
}
}
});
// Pick a random floor tile as a new target to keep Roombas apart
if (!self.targetTile || self.collisionCounter > 50 || Math.sqrt(Math.pow(self.x - self.targetTile.x, 2) + Math.pow(self.y - self.targetTile.y, 2)) < 15) {
var randomIndex = Math.floor(Math.random() * floorTiles.length);
self.targetTile = floorTiles[randomIndex];
self.collisionCounter = 0; // Reset collision counter after changing target
}
// 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);
}
isCharacterMoving = 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,
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
****/
// characterShadow asset initialization removed
// Function to spawn cheeses at random floor tile positions
function spawnCheeses() {
// Clear existing cheeses before spawning new ones
cheeses.forEach(function (cheese) {
cheese.destroy();
});
cheeses = []; // Reset the cheeses array
// Spawn new cheeses
for (var i = 0; i < totalCheeses; i++) {
cheeses.push(game.addChild(new Cheese()));
}
// Place cheeses on non-corner floor tiles that are far from the character
var nonCornerFloorTiles = floorTiles.filter(function (tile) {
return true;
});
var farthestTiles = nonCornerFloorTiles.filter(function (tile) {
// Ensure character is defined before calculating distance
var distanceToCharacter = typeof character !== 'undefined' && character !== null ? Math.sqrt(Math.pow(tile.x - character.x, 2) + Math.pow(tile.y - character.y, 2)) : Infinity;
return distanceToCharacter > LK.screen.width / 2; // Arbitrary distance threshold
});
// Exclude tiles that are too close to the hole tile
var safeDistanceTiles = nonCornerFloorTiles.filter(function (tile) {
var distanceToHole = Math.sqrt(Math.pow(tile.x - holeTile.x, 2) + Math.pow(tile.y - holeTile.y, 2));
return distanceToHole > LK.screen.width / 4; // Arbitrary distance threshold to keep cheese away from the hole
});
// Filter out tiles that are surrounded by obstacles horizontally and vertically
// Move the declaration of 'targetTiles' before its first use
var targetTiles = safeDistanceTiles.length > 0 ? safeDistanceTiles : farthestTiles;
var validTilesForCheese = targetTiles.filter(function (tile) {
var leftTile = getTileAtPosition(tile.x - tileWidth, tile.y);
var rightTile = getTileAtPosition(tile.x + tileWidth, tile.y);
var topTile = getTileAtPosition(tile.x, tile.y - tileHeight);
var bottomTile = getTileAtPosition(tile.x, tile.y + tileHeight);
// Check if the tile is surrounded by obstacles on all four sides
return !(obstacleTiles.includes(leftTile) || obstacleTiles.includes(rightTile) || obstacleTiles.includes(topTile) || obstacleTiles.includes(bottomTile));
});
var targetTiles = validTilesForCheese.length > 0 ? validTilesForCheese : nonCornerFloorTiles;
// Place each cheese on a unique random floor tile
cheeses.forEach(function (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) {
cheese.x = uniqueFloorTile.x;
cheese.y = uniqueFloorTile.y;
}
});
}
// Method to check if all cheeses have been delivered
function allCheesesDelivered() {
// Destroy grid and tiles
grid.forEach(function (tile) {
if (tile) {
tile.destroy();
}
});
grid = []; // Clear the grid array
floorTiles.forEach(function (tile) {
tile.destroy();
});
floorTiles = []; // Clear the floorTiles array
wallTiles.forEach(function (tile) {
tile.destroy();
});
wallTiles = []; // Clear the wallTiles array
obstacleTiles.forEach(function (tile) {
tile.destroy();
});
obstacleTiles = []; // Clear the obstacleTiles array
// Destroy character and cheese icon
if (character) {
if (cheeseIcon) {
cheeseIcon.destroy();
}
character.destroy();
character = null;
}
// Destroy enemies
enemies.forEach(function (enemy) {
enemy.destroy();
});
enemies = []; // Clear the enemies array
globalEnemySpeed *= 1.1; // Increase global enemy speed by 10% on each level load
console.log("building next level");
// Rebuild game elements
createTiles(); // Rebuild the tiles for the level
var nonCornerWallTiles = wallTiles.filter(function (tile) {
var x = tile.x,
y = tile.y;
var isCornerTile = x === gridOffsetX && y === gridOffsetY || x === gridOffsetX + (gridSize - 1) * tileWidth && y === gridOffsetY || x === gridOffsetX && y === gridOffsetY + (gridSize - 1) * tileHeight || x === gridOffsetX + (gridSize - 1) * tileWidth && y === gridOffsetY + (gridSize - 1) * tileHeight;
return !isCornerTile;
});
var randomWallTile = nonCornerWallTiles[Math.floor(Math.random() * nonCornerWallTiles.length)];
holeTile = LK.getAsset('holeTile', {
anchorX: 0.5,
anchorY: 0.5,
x: randomWallTile.x,
y: randomWallTile.y
});
game.addChild(holeTile);
game.removeChild(randomWallTile);
spawnCheeses(); // Spawn cheeses for the new level
// Re-instantiate character for the new level with correct shadow and position
character = game.addChild(new Character());
// Attach cheese icon to the new character if cheese is collected
if (cheeseIcon && cheeseIcon.visible) {
cheeseIcon = character.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: 0,
y: -character.height / 2 // Position closer to the character top
});
}
// Create a new cheese icon and disable it
cheeseIcon = character.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: 0,
y: -character.height / 2,
// Position closer to the character top
visible: false // Disable cheese icon after creation
});
// Attach cheese icon to the new character if cheese is collected
// Ensure the cheese icon is visible on the new character instance
character.x = holeTile.x; // Position character at the hole's location
character.y = holeTile.y - 50; // Adjust Y position to not overlap with the hole
enemies.forEach(function (enemy) {
enemy.destroy();
}); // Destroy existing enemies
enemies = []; // Clear enemies array
enemies.push(game.addChild(new Enemy('Roomba'))); // Add first Roomba enemy
enemies.push(game.addChild(new Enemy('Roomba'))); // Add second Roomba enemy
// Position Roombas on opposite sides of the grid
if (enemies[0]) {
enemies[0].x = floorTiles[0].x; // Position the first Roomba on the left side
enemies[0].y = floorTiles[0].y;
}
if (enemies[1]) {
var lastTileIndex = floorTiles.length - 1;
enemies[1].x = floorTiles[lastTileIndex].x; // Position the second Roomba on the right side
enemies[1].y = floorTiles[lastTileIndex].y;
}
}
// Ensure LK.screen dimensions are defined before using them
var globalEnemySpeed = 3; // Define initial global enemy speed
LK.screen = {
width: 2048,
height: 2732
}; // Initialize screen dimensions
// Instantiate and center the game logo asset on the screen
var gameLogo = LK.getAsset('stickerLogo', {
anchorX: 0.5,
anchorY: 0.5,
x: LK.screen.width / 2,
y: 1880
});
game.addChild(gameLogo);
var dakaloText = new Text2('@Dakalo777', {
size: 50,
fill: "#FFA500",
x: LK.screen.width - 20,
// Adjust for space from the right edge
y: LK.screen.height - 20 // Adjust for space from the bottom edge
});
dakaloText.anchor.set(1, 1); // Anchor to bottom right
LK.gui.bottomRight.addChild(dakaloText);
// Function to check if a new obstacle tile fully surrounds any cheese
// Removed redundant cheese tracking variables
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;
});
});
});
}
// 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: 2100,
y: 2300,
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: 2400,
// Moved sticker a bit down
rotation: 0.10
});
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;
// 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;
// Method to instantiate and return a new character
function createCharacter() {
return LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
x: holeTile.x,
y: holeTile.y - 50,
scaleX: 1,
scaleY: 1
});
}
character = createCharacter();
// Reset cheese score display to '0' to prevent UI text overlap on game reset
cheeseScoreDisplay.setText('0');
});
// Clear existing UI elements to prevent text overlap upon reload and add property clear on reload
if (window.scoreBoardContainer) {
window.scoreBoardContainer.children.forEach(function (child) {
child.destroy(); // Destroy each child to ensure clean slate
});
LK.gui.removeChild(window.scoreBoardContainer);
window.scoreBoardContainer.destroy(); // Ensure the container is properly destroyed
window.scoreBoardContainer = null;
window.scoreBoardContainer.clearOnReload = true; // Add property clear on reload to the scoreboard container
}
// 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: 110,
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: 1000 - i * 90,
// 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: "#ffffff",
stroke: "#ffffff",
strokeThickness: 4,
font: "Roboto, bold",
x: cheeseIconForScore.x + 60,
// Adjust x position to place score text right side of the cheese icon
y: cheeseIconForScore.y
});
cheeseScoreDisplay.anchor.set(0, 0.5);
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(-5, 0.45); // Center the text horizontally
window.scoreBoardContainer.addChild(playTimeDisplay);
window.scoreBoardContainer.x = scoreBoardX;
window.scoreBoardContainer.y = scoreBoardY;
LK.gui.addChild(window.scoreBoardContainer);
window.scoreBoardInitialized = true;
}
var onScreenController = game.addChild(new OnScreenController());
// Refactored event listener for A button press to manage cheese collection and scoring more efficiently
onScreenController.aButton.on('down', function () {
if (isWithinProximity(character, holeTile, 75) && cheeseIcon && cheeseIcon.visible) {
var createFlyingCheeseEffect = function createFlyingCheeseEffect(fromX, fromY) {
var flyingCheese = game.addChild(LK.getAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5,
x: fromX,
y: fromY,
scaleX: 1.0,
// Scale up by 100%
scaleY: 1.0 // Scale up by 100%
}));
var scoreBoardPos = {
x: window.scoreBoardContainer.x + cheeseIconForScore.x,
y: window.scoreBoardContainer.y + cheeseIconForScore.y
};
var cheeseFlyDuration = 750; // Duration in milliseconds
var startTime = Date.now();
LK.on('tick', function () {
var currentTime = Date.now();
var progress = (currentTime - startTime) / cheeseFlyDuration;
if (progress < 1) {
flyingCheese.x = fromX + (scoreBoardPos.x - fromX) * progress;
flyingCheese.y = fromY + (scoreBoardPos.y - fromY) * progress;
// Calculate the angle to rotate the flying cheese towards the scoreboard and add 180 degrees for rotation
var angle = Math.atan2(scoreBoardPos.y - fromY, scoreBoardPos.x - fromX) + Math.PI;
flyingCheese.rotation = angle;
} else {
game.removeChild(flyingCheese);
window.updateCheeseScore(LK.getScore()); // Update displayed score
}
});
}; // Invoke createFlyingCheeseEffect with character's position when cheese is delivered
console.log('Cheese delivered!');
cheeseIcon.visible = false; // Hide the cheese icon to indicate delivery
// If it's the last cheese, increment score by 2, otherwise by 1
if (cheeses.length === 0) {
LK.setScore(LK.getScore() + 2);
allCheesesDelivered(); // Invoke allCheesesDelivered method after scoring for the last cheese
} else {
LK.setScore(LK.getScore() + 1);
}
// Create a visual cheese flying effect towards the scoreboard on cheese delivery
createFlyingCheeseEffect(holeTile.x, holeTile.y);
} else {
if (!cheeseIcon || !cheeseIcon.visible) {
cheeses.forEach(function (cheese, index) {
if (isWithinProximity(character, cheese, 75)) {
console.log('Cheese collected!');
game.removeChild(cheese); // Remove cheese from game
cheeses.splice(index, 1); // Remove cheese from cheeses array
// Display cheese icon above character to indicate cheese collection
if (!cheeseIcon) {
cheeseIcon = character.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
// Scale down by 50%
scaleY: 0.8,
// Scale down by 50%
x: 0,
y: -character.height / 2 // Position closer to the character top
});
} else {
cheeseIcon.visible = true; // Make the cheese icon visible if already exists
}
}
});
}
}
});
// Helper function to check if two objects are within a certain distance
function isWithinProximity(obj1, obj2, threshold) {
if (!obj1 || !obj2) {
return false;
}
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
var dpadButtonSize = {
width: 450,
height: 450
};
function moveCharacter(xDir, yDir) {
if (availableLives <= 0) {
return;
}
if (character) {
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 (grid[nextTileIndex] && (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
// Removed redundant globalEnemySpeed initialization
var gridSize = 10;
// Character initialization removed to prevent duplication
var totalCheeses = Math.floor(Math.random() * 3) + 1; // Define total number of cheeses in the game as a random number between 1 and 3
var cheeses = []; // Initialize cheeses array globally
// Declare cheeseIcon as a global variable
var cheeseIcon;
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.75,
x: LK.screen.width / 2,
y: LK.screen.height / 2,
width: LK.screen.width * .9,
height: LK.screen.height * .65,
tint: 0xFFA500 // Apply orange tint
});
game.addChild(gridBackground);
var gridBackgroundShrunk = LK.getAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0.75,
x: LK.screen.width / 2,
y: LK.screen.height / 2,
width: LK.screen.width * .9 - 50,
height: LK.screen.height * .65 - 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)) {
// Obstacle tile creation logic removed to ensure no obstacles are added to the game
} 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 isCornerTile = x === 0 && y === 0 || x === 0 && y === gridSize - 1 || x === gridSize - 1 && y === 0 || x === gridSize - 1 && y === gridSize - 1;
if (isCornerTile) {
var tile = LK.getAsset('CornerTile', {
anchorX: 0.5,
anchorY: 0.5,
x: x * tileWidth + gridOffsetX,
y: y * tileHeight + gridOffsetY
});
game.addChild(tile);
grid[i] = tile;
} else {
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 is in a corner
// Corner logic removed
var randomWallTile = wallTiles[Math.floor(Math.random() * wallTiles.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);
LK.setTimeout(function () {
enemies.push(game.addChild(new Enemy('Roomba')));
enemies.push(game.addChild(new Enemy('Roomba')));
// 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;
}
}, 1000);
// Initialize cheese instances to place them on the floor
// No changes needed here as the character shadow consistency is maintained with the original creation.
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;
// Removed tint logic
}, 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 or all cheeses have been delivered to win the game
if (availableLives <= 0) {
character.visible = false; // Make character invisible
LK.setTimeout(function () {
LK.showGameOver("You've been caught! Better luck next time.");
}, 1000); // Wait one second before showing game over
} // Removed win game logic based on cheese delivery
}
});
});
spawnCheeses();
// Create instances of enemies and store them in an array
var enemies = [];
// 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;
}
// Function to select a new target tile avoiding obstacles
function selectNewTargetTileAvoidingObstacles(currentX, currentY, floorTiles, obstacleTiles) {
// Placeholder for pathfinding logic to select a new target tile
// For simplicity, this example randomly selects a floor tile not in the obstacleTiles array
var validTiles = floorTiles.filter(function (tile) {
return !obstacleTiles.includes(tile);
});
if (validTiles.length > 0) {
var randomIndex = Math.floor(Math.random() * validTiles.length);
return validTiles[randomIndex];
} else {
console.error('No valid tiles found to move to.');
return null; // Return null if no valid tiles are found
}
}
// 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);
if (index >= 0 && index < grid.length && grid[index]) {
return grid[index];
} else {
console.error('Tile at position', x, y, 'is out of bounds or null.');
return undefined; // Return undefined to indicate no tile found or out of bounds without error
}
} ===================================================================
--- original.js
+++ change.js
@@ -521,19 +521,20 @@
character = createCharacter();
// Reset cheese score display to '0' to prevent UI text overlap on game reset
cheeseScoreDisplay.setText('0');
});
-// Clear existing UI elements to prevent text overlap upon reload
+// Clear existing UI elements to prevent text overlap upon reload and add property clear on reload
if (window.scoreBoardContainer) {
window.scoreBoardContainer.children.forEach(function (child) {
child.destroy(); // Destroy each child to ensure clean slate
});
LK.gui.removeChild(window.scoreBoardContainer);
window.scoreBoardContainer.destroy(); // Ensure the container is properly destroyed
window.scoreBoardContainer = null;
+ window.scoreBoardContainer.clearOnReload = true; // Add property clear on reload to the scoreboard container
}
-// Ensure single instance only for scoreboard container and elements, and update score dynamically
-if (!window.scoreBoardContainer) {
+// 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();
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.