User prompt
Tint the roombas red
User prompt
Make the enemies red
User prompt
Migrate to the latest version of LK
User prompt
Please fix the bug: 'Uncaught ReferenceError: polygon is not defined' in or related to this line: 'polygon.graphics.beginFill(0xFF3300);' Line Number: 314
User prompt
Please fix the bug: 'Uncaught TypeError: LK.Shape is not a constructor' in or related to this line: 'var polygon = new LK.Shape();' Line Number: 311
User prompt
Draw a polygon when 5 points
User prompt
Give me access to the graphics API
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'width')' in or related to this line: 'var fieldOfView = LK.getAsset('gridBackground', {' Line Number: 279
User prompt
Add s field of view for the room as
User prompt
Ensure the flag asset is created on level load
User prompt
Add a flag to the hole tile on the top right corner
User prompt
Debug, the flag is not visible
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var flag = LK.getAsset('Flag', {' Line Number: 279
User prompt
Create a flag placing it on the side of the hole tile, always outside the grid
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'x')' in or related to this line: 'enemies[0].x = floorTiles[0].x;' Line Number: 859
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'x')' in or related to this line: 'enemies[0].x = floorTiles[0].x;' Line Number: 859
User prompt
Create the flag tile last on the creste tile function
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var holeTile = LK.getAsset('holeTile', {' Line Number: 872
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var holeTile = LK.getAsset('holeTile', {' Line Number: 868
User prompt
Create the flag tile last on the create tile function
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var holeTile = LK.getAsset('holeTile', {' Line Number: 865
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var holeTile = LK.getAsset('holeTile', {' Line Number: 859
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var holeTile = LK.getAsset('holeTile', {' Line Number: 806
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'flagTile.x = holeTile.x;' Line Number: 806
User prompt
Instead of placing the flag random, place it aways on top of the hole tile
/****
* Classes
****/
var Character = Container.expand(function () {
var self = Container.call(this);
var characterShadow = self.attachAsset('CircularShadow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
y: 20
});
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,
tint: 0xFF0000 // Tint the Roombas red
});
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_migrated = 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', function (x, y, obj) {
obj.event = obj;
stopMovingCharacter(obj);
});
dpadUp.on('up', function (x, y, obj) {
obj.event = obj;
stopMovingCharacter(obj);
});
dpadRight.on('up', function (x, y, obj) {
obj.event = obj;
stopMovingCharacter(obj);
});
dpadDown.on('up', function (x, y, obj) {
obj.event = obj;
stopMovingCharacter(obj);
});
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf9e076 // Fun yellow background
});
/****
* Game Code
****/
// Define points for a 5-point polygon
var polygonPoints = [{
x: 1024,
y: 500
},
// Top center
{
x: 1300,
y: 800
},
// Right top
{
x: 1200,
y: 1200
},
// Right bottom
{
x: 800,
y: 1200
},
// Left bottom
{
x: 700,
y: 800
} // Left top
];
// Correct approach to simulate drawing a polygon using available assets
// This function creates a visual representation of a polygon by placing assets at the polygon's vertices.
function simulateDrawPolygon(points) {
points.forEach(function (point, index) {
// Use a small shape asset to represent each vertex of the polygon
var vertex = game.addChild(LK.getAsset('CircularShadow', {
anchorX: 0.5,
anchorY: 0.5,
x: point.x,
y: point.y,
scaleX: 0.1,
// Scale down to make the asset small
scaleY: 0.1,
tint: 0xFF3300 // Color the asset to match the intended polygon color
}));
// Optionally, connect vertices with lines using additional assets or by adjusting existing assets' positions and rotations
// This part is left as an exercise due to the complexity and limitations of the current asset system
});
}
// Call simulateDrawPolygon function with defined points
simulateDrawPolygon(polygonPoints);
// 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 + 50,
y: 1955
});
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,
scaleX: 0.7,
// Scale down by 0.7
scaleY: 0.7,
// Scale down by 0.7
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');
});
// Reset UI elements correctly when playing again
if (window.scoreBoardContainer) {
window.scoreBoardContainer.children.forEach(function (child) {
child.destroy(); // Destroy each child to ensure clean slate
});
window.scoreBoardContainer.destroy(); // Ensure the container is properly destroyed
window.scoreBoardContainer = null;
}
// Reinitialize the scoreboard container to prevent UI text overlap on game reset
window.scoreBoardInitialized = false;
// 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 = 0,
scoreBoardY = 0;
var cheeseIconForScore = window.scoreBoardContainer.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: -500,
y: 55
});
// Dynamically add one character lives icon per available life
var availableLives = 3; // Assuming 3 lives to start with
var livesIcons = [];
for (var i = availableLives - 1; i >= 0; i--) {
var lifeIcon = window.scoreBoardContainer.attachAsset('characterLivesIcon', {
anchorX: 0,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5,
x: (availableLives - 1 - i) * 90 + 250,
y: 0
});
livesIcons.unshift(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(14.5, -.8);
window.scoreBoardContainer.addChild(cheeseScoreDisplay);
// Update cheese score display function
window.updateCheeseScore = function (score) {
updateCheeseScore(score);
// Initiate bounce effect
var originalScaleX = cheeseScoreDisplay.scaleX;
var originalScaleY = cheeseScoreDisplay.scaleY;
var scaleUpDuration = 150; // Duration to scale up
var scaleDownDuration = 150; // Duration to scale down back to original size
var scaleAmount = 1.2; // Amount to scale up
// Scale up
cheeseScoreDisplay.scaleX = originalScaleX * scaleAmount;
cheeseScoreDisplay.scaleY = originalScaleY * scaleAmount;
// Delay before scaling down
LK.setTimeout(function () {
// Scale down back to original size
cheeseScoreDisplay.scaleX = originalScaleX;
cheeseScoreDisplay.scaleY = originalScaleY;
}, scaleUpDuration);
};
// 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: 0
});
playTimeDisplay.anchor.set(-0.75, 0); // Center the text horizontally
window.scoreBoardContainer.addChild(playTimeDisplay);
window.scoreBoardContainer.x = 0;
window.scoreBoardContainer.y = 55;
LK.gui.top.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 leftTopCornerTile = floorTiles[0]; // Assuming the first tile in the array is the top left corner
var scoreBoardPos = {
x: leftTopCornerTile.x - tileHeight,
y: leftTopCornerTile.y - tileHeight
};
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;
// Check if the current floor tile is surrounded by obstacles and change it to an obstacle tile if true
var leftTileIndex = i - 1;
var rightTileIndex = i + 1;
var topTileIndex = i - gridSize;
var bottomTileIndex = i + gridSize;
if (leftTileIndex >= 0 && obstacleTiles.includes(grid[leftTileIndex]) && rightTileIndex < grid.length && obstacleTiles.includes(grid[rightTileIndex]) && topTileIndex >= 0 && obstacleTiles.includes(grid[topTileIndex]) && bottomTileIndex < grid.length && obstacleTiles.includes(grid[bottomTileIndex])) {
// Remove the current tile from floorTiles and add to obstacleTiles
floorTiles.pop();
obstacleTiles.push(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_migrated();
// 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
@@ -62,9 +62,9 @@
anchorY: 0.5,
alpha: 0.5,
scaleX: shadowScale,
scaleY: shadowScale,
- tint: 0xFF0000 // Change shadow color to red
+ tint: 0xFF0000 // Tint the Roombas red
});
var enemyGraphics = self.attachAsset(enemyAssetId, {
anchorX: 0.5,
anchorY: 0.5
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.