/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var DirtSpot = Container.expand(function () {
var self = Container.call(this);
var dirtGraphics = self.attachAsset('dirt', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBeingCleaned = false;
self.cleanProgress = 0;
self.maxCleanProgress = 3;
// Randomize dirt spot size and opacity
var scale = 0.5 + Math.random() * 1.0;
dirtGraphics.scaleX = scale;
dirtGraphics.scaleY = scale;
dirtGraphics.alpha = 0.3 + Math.random() * 0.4;
self.clean = function (amount) {
LK.getSound('spray').play();
self.cleanProgress += 1; // Count clicks instead of using amount
if (self.cleanProgress >= 3) {
return true; // Fully cleaned after 3 clicks
}
// Update visual feedback based on click count
var remaining = (3 - self.cleanProgress) / 3;
dirtGraphics.alpha = remaining * (0.3 + Math.random() * 0.4);
return false;
};
return self;
});
var SpecialButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('waterSpout', {
anchorX: 0.5,
anchorY: 0.5
});
buttonGraphics.width = 120;
buttonGraphics.height = 120;
buttonGraphics.tint = 0xFF0000; // Red color
self.isPressed = false;
self.down = function (x, y, obj) {
if (!self.isPressed) {
self.isPressed = true;
self.activate();
}
};
self.activate = function () {
// Remove all dirt spots
for (var i = dirtSpots.length - 1; i >= 0; i--) {
var dirt = dirtSpots[i];
dirt.destroy();
dirtSpots.splice(i, 1);
}
updateCoverage();
// Disable sprinklers for 15 seconds
sprinklersDisabled = true;
LK.setTimeout(function () {
sprinklersDisabled = false;
}, 15000);
// Hide instruction UI elements
buttonInstructionTxt.visible = false;
arrowTxt.visible = false;
tween.stop(arrowTxt);
// Hide button and schedule next appearance
self.destroy();
specialButton = null;
lastSpecialButtonTime = LK.ticks * (1000 / 60);
};
return self;
});
var Sprinkler = Container.expand(function () {
var self = Container.call(this);
var sprinklerGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastSprayTime = Math.random() * 2000; // Random initial delay
self.sprayInterval = 5000; // 5 seconds between sprays
self.isActive = false;
self.spray = function () {
var numDrops = 25 + Math.floor(Math.random() * 20);
for (var i = 0; i < numDrops; i++) {
var drop = new WaterDrop();
drop.x = self.x + (Math.random() - 0.5) * 200;
drop.y = self.y + 20;
drop.velocityY = -3 - Math.random() * 5;
drop.velocityX = (Math.random() - 0.5) * 4;
waterDrops.push(drop);
game.addChild(drop);
}
self.isActive = true;
// Animate sprinkler activation
tween(sprinklerGraphics, {
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(sprinklerGraphics, {
scaleY: 1.0
}, {
duration: 200,
onFinish: function onFinish() {
self.isActive = false;
}
});
}
});
};
return self;
});
var WaterDrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('waterDrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.gravity = 0.3;
self.velocityY = 0;
self.velocityX = 0;
self.lifespan = 240; // 4 seconds at 60fps
self.age = 0;
self.update = function () {
self.velocityY += self.gravity;
self.y += self.velocityY;
self.x += self.velocityX;
self.age++;
// Fade out over time
dropGraphics.alpha = Math.max(0, 1 - self.age / self.lifespan);
};
return self;
});
var WaterSpout = Container.expand(function () {
var self = Container.call(this);
var spoutGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5
});
spoutGraphics.scaleX = 1.5;
spoutGraphics.scaleY = 0.8;
spoutGraphics.tint = 0x888888;
self.lastSprayTime = Math.random() * 5000; // Random initial delay
self.sprayInterval = 15000; // 15 seconds between sprays
self.isActive = false;
self.spray = function () {
var numDrops = 40 + Math.floor(Math.random() * 30);
for (var i = 0; i < numDrops; i++) {
var drop = new WaterDrop();
var angle = Math.PI * 2 * i / numDrops;
var radius = 50 + Math.random() * 100;
drop.x = self.x + Math.cos(angle) * (Math.random() * 150);
drop.y = self.y + 20;
drop.velocityY = -4 - Math.random() * 6;
drop.velocityX = Math.cos(angle) * (2 + Math.random() * 3);
waterDrops.push(drop);
game.addChild(drop);
}
self.isActive = true;
// Animate spout activation
tween(spoutGraphics, {
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
tween(spoutGraphics, {
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
self.isActive = false;
}
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var dirtSpots = [];
var waterDrops = [];
var sprinklers = [];
var lastDirtSpawnTime = 0;
var dirtSpawnInterval = 5000; // 5 seconds
var gameStartTime = LK.ticks;
var isDragging = false;
var lastDragX = 0;
var lastDragY = 0;
var windowCoverage = 0;
var maxCoverage = 0.4; // 40% pollution triggers game over
var specialButton = null;
var lastSpecialButtonTime = 0;
var specialButtonInterval = 25000; // 25 seconds
var sprinklersDisabled = false;
// Create window frame
var windowFrame = game.addChild(LK.getAsset('windowFrame', {
anchorX: 0.5,
anchorY: 0.5
}));
windowFrame.x = 2048 / 2;
windowFrame.y = 2732 / 2;
// Create main window
var windowPane = game.addChild(LK.getAsset('window', {
anchorX: 0.5,
anchorY: 0.5
}));
windowPane.x = 2048 / 2;
windowPane.y = 2732 / 2;
windowPane.alpha = 0.8;
// Create sprinklers - two on each side
var leftSprinkler1 = new Sprinkler();
leftSprinkler1.x = windowPane.x - windowPane.width / 2 + 60;
leftSprinkler1.y = windowPane.y - windowPane.height / 2 - 60;
sprinklers.push(leftSprinkler1);
game.addChild(leftSprinkler1);
var leftSprinkler2 = new Sprinkler();
leftSprinkler2.x = windowPane.x - windowPane.width / 2 + 60;
leftSprinkler2.y = windowPane.y - windowPane.height / 2 - 200;
sprinklers.push(leftSprinkler2);
game.addChild(leftSprinkler2);
var rightSprinkler1 = new Sprinkler();
rightSprinkler1.x = windowPane.x + windowPane.width / 2 - 60;
rightSprinkler1.y = windowPane.y - windowPane.height / 2 - 60;
sprinklers.push(rightSprinkler1);
game.addChild(rightSprinkler1);
var rightSprinkler2 = new Sprinkler();
rightSprinkler2.x = windowPane.x + windowPane.width / 2 - 60;
rightSprinkler2.y = windowPane.y - windowPane.height / 2 - 200;
sprinklers.push(rightSprinkler2);
game.addChild(rightSprinkler2);
// Create center water spout
var centerSpout = new WaterSpout();
centerSpout.x = windowPane.x;
centerSpout.y = windowPane.y - windowPane.height / 2 - 100;
game.addChild(centerSpout);
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0x000000
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coverage warning
var coverageTxt = new Text2('Glass Pollution: 0%', {
size: 60,
fill: 0x006400
});
coverageTxt.anchor.set(0.5, 0);
coverageTxt.y = 100;
LK.gui.top.addChild(coverageTxt);
// Button instruction text (initially hidden)
var buttonInstructionTxt = new Text2('Press Button', {
size: 80,
fill: 0xFF0000
});
buttonInstructionTxt.anchor.set(0.5, 0.5);
buttonInstructionTxt.visible = false;
// Arrow pointing to button (initially hidden)
var arrowTxt = new Text2('↓', {
size: 120,
fill: 0xFF0000
});
arrowTxt.anchor.set(0.5, 0.5);
arrowTxt.visible = false;
// Function to spawn dirt
function spawnDirt() {
var numDirtSpots = 3 + Math.floor(Math.random() * 5); // 3-7 dirt spots
for (var i = 0; i < numDirtSpots; i++) {
var dirt = new DirtSpot();
// Position within window bounds
var windowBounds = {
left: windowPane.x - windowPane.width / 2 + 50,
right: windowPane.x + windowPane.width / 2 - 50,
top: windowPane.y - windowPane.height / 2 + 50,
bottom: windowPane.y + windowPane.height / 2 - 50
};
dirt.x = windowBounds.left + Math.random() * (windowBounds.right - windowBounds.left);
dirt.y = windowBounds.top + Math.random() * (windowBounds.bottom - windowBounds.top);
dirtSpots.push(dirt);
game.addChild(dirt);
}
LK.getSound('dirtAppear').play();
updateCoverage();
}
// Function to update window coverage
function updateCoverage() {
windowCoverage = Math.min(dirtSpots.length / 50, 1); // Normalize to 0-1
var pollution = Math.floor(windowCoverage * 100);
coverageTxt.setText('Glass Pollution: ' + pollution + '%');
if (pollution > 30) {
coverageTxt.fill = "#FF0000";
} else if (pollution > 20) {
coverageTxt.fill = "#FFA500";
} else {
coverageTxt.fill = "#006400";
}
if (windowCoverage >= maxCoverage) {
LK.effects.flashScreen(0x8B4513, 1000);
LK.showGameOver();
}
}
// Function to clean dirt at position
function cleanAtPosition(x, y, isWater) {
var cleanRadius = isWater ? 50 : 80;
var pointsPerClean = isWater ? 5 : 10;
for (var i = dirtSpots.length - 1; i >= 0; i--) {
var dirt = dirtSpots[i];
var distance = Math.sqrt(Math.pow(dirt.x - x, 2) + Math.pow(dirt.y - y, 2));
if (distance < cleanRadius) {
var cleanAmount = isWater ? Math.max(1, 10 - distance / 5) : Math.max(1, 20 - distance / 4);
if (dirt.clean(cleanAmount)) {
// Dirt spot fully cleaned
LK.setScore(LK.getScore() + pointsPerClean);
scoreTxt.setText('Score: ' + LK.getScore());
dirt.destroy();
dirtSpots.splice(i, 1);
if (!isWater) {
LK.getSound('wipe').play();
}
}
}
}
updateCoverage();
}
// Touch/drag handling
game.down = function (x, y, obj) {
isDragging = true;
lastDragX = x;
lastDragY = y;
cleanAtPosition(x, y);
};
game.move = function (x, y, obj) {
if (isDragging) {
// Clean along the drag path
var steps = Math.max(1, Math.floor(Math.sqrt(Math.pow(x - lastDragX, 2) + Math.pow(y - lastDragY, 2)) / 20));
for (var i = 0; i <= steps; i++) {
var t = steps > 0 ? i / steps : 0;
var cleanX = lastDragX + (x - lastDragX) * t;
var cleanY = lastDragY + (y - lastDragY) * t;
cleanAtPosition(cleanX, cleanY);
}
lastDragX = x;
lastDragY = y;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Main game update loop
game.update = function () {
var currentTime = LK.ticks * (1000 / 60); // Convert ticks to milliseconds
// Update water drops
for (var i = waterDrops.length - 1; i >= 0; i--) {
var drop = waterDrops[i];
if (drop.age >= drop.lifespan || drop.y > windowPane.y + windowPane.height / 2) {
drop.destroy();
waterDrops.splice(i, 1);
continue;
}
// Check if water drop hits dirt
if (drop.y >= windowPane.y - windowPane.height / 2 && drop.y <= windowPane.y + windowPane.height / 2 && drop.x >= windowPane.x - windowPane.width / 2 && drop.x <= windowPane.x + windowPane.width / 2) {
cleanAtPosition(drop.x, drop.y, true);
}
}
// Handle sprinkler spraying (only if not disabled)
if (!sprinklersDisabled) {
for (var j = 0; j < sprinklers.length; j++) {
var sprinkler = sprinklers[j];
if (currentTime - sprinkler.lastSprayTime >= sprinkler.sprayInterval) {
sprinkler.spray();
sprinkler.lastSprayTime = currentTime;
}
}
}
// Handle special button spawning
if (!specialButton && currentTime - lastSpecialButtonTime >= specialButtonInterval) {
specialButton = new SpecialButton();
specialButton.x = windowPane.x + (Math.random() - 0.5) * (windowPane.width - 200);
specialButton.y = windowPane.y + (Math.random() - 0.5) * (windowPane.height - 200);
game.addChild(specialButton);
// Show instruction text and arrow
buttonInstructionTxt.x = specialButton.x;
buttonInstructionTxt.y = specialButton.y - 100;
buttonInstructionTxt.visible = true;
game.addChild(buttonInstructionTxt);
arrowTxt.x = specialButton.x;
arrowTxt.y = specialButton.y - 40;
arrowTxt.visible = true;
game.addChild(arrowTxt);
// Animate the arrow bouncing
tween(arrowTxt, {
y: specialButton.y - 20
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(arrowTxt, {
y: specialButton.y - 40
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue bouncing if button still exists
if (specialButton && arrowTxt.visible) {
tween(arrowTxt, {
y: specialButton.y - 20
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (specialButton && arrowTxt.visible) {
tween(arrowTxt, {
y: specialButton.y - 40
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
});
}
}
});
}
});
}
// Handle water spout spraying
if (currentTime - centerSpout.lastSprayTime >= centerSpout.sprayInterval) {
centerSpout.spray();
centerSpout.lastSprayTime = currentTime;
}
// Spawn dirt every interval
if (currentTime - lastDirtSpawnTime >= dirtSpawnInterval) {
spawnDirt();
lastDirtSpawnTime = currentTime;
// Increase difficulty over time
var gameTime = (currentTime - gameStartTime) / 1000; // Game time in seconds
if (gameTime > 35) {
dirtSpawnInterval = 2000; // 2 seconds after 35 seconds
} else if (gameTime > 30) {
dirtSpawnInterval = Math.max(2000, 5000 - (gameTime - 30) * 50); // Minimum 2 seconds
}
}
// Victory condition - survive for 5 minutes with good cleanliness
var gameTimeMinutes = (currentTime - gameStartTime) / 60000;
if (gameTimeMinutes >= 5 && windowCoverage < 0.3) {
LK.showYouWin();
}
};
// Initial dirt spawn
LK.setTimeout(function () {
spawnDirt();
lastDirtSpawnTime = LK.ticks * (1000 / 60);
}, 1000); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var DirtSpot = Container.expand(function () {
var self = Container.call(this);
var dirtGraphics = self.attachAsset('dirt', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBeingCleaned = false;
self.cleanProgress = 0;
self.maxCleanProgress = 3;
// Randomize dirt spot size and opacity
var scale = 0.5 + Math.random() * 1.0;
dirtGraphics.scaleX = scale;
dirtGraphics.scaleY = scale;
dirtGraphics.alpha = 0.3 + Math.random() * 0.4;
self.clean = function (amount) {
LK.getSound('spray').play();
self.cleanProgress += 1; // Count clicks instead of using amount
if (self.cleanProgress >= 3) {
return true; // Fully cleaned after 3 clicks
}
// Update visual feedback based on click count
var remaining = (3 - self.cleanProgress) / 3;
dirtGraphics.alpha = remaining * (0.3 + Math.random() * 0.4);
return false;
};
return self;
});
var SpecialButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('waterSpout', {
anchorX: 0.5,
anchorY: 0.5
});
buttonGraphics.width = 120;
buttonGraphics.height = 120;
buttonGraphics.tint = 0xFF0000; // Red color
self.isPressed = false;
self.down = function (x, y, obj) {
if (!self.isPressed) {
self.isPressed = true;
self.activate();
}
};
self.activate = function () {
// Remove all dirt spots
for (var i = dirtSpots.length - 1; i >= 0; i--) {
var dirt = dirtSpots[i];
dirt.destroy();
dirtSpots.splice(i, 1);
}
updateCoverage();
// Disable sprinklers for 15 seconds
sprinklersDisabled = true;
LK.setTimeout(function () {
sprinklersDisabled = false;
}, 15000);
// Hide instruction UI elements
buttonInstructionTxt.visible = false;
arrowTxt.visible = false;
tween.stop(arrowTxt);
// Hide button and schedule next appearance
self.destroy();
specialButton = null;
lastSpecialButtonTime = LK.ticks * (1000 / 60);
};
return self;
});
var Sprinkler = Container.expand(function () {
var self = Container.call(this);
var sprinklerGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastSprayTime = Math.random() * 2000; // Random initial delay
self.sprayInterval = 5000; // 5 seconds between sprays
self.isActive = false;
self.spray = function () {
var numDrops = 25 + Math.floor(Math.random() * 20);
for (var i = 0; i < numDrops; i++) {
var drop = new WaterDrop();
drop.x = self.x + (Math.random() - 0.5) * 200;
drop.y = self.y + 20;
drop.velocityY = -3 - Math.random() * 5;
drop.velocityX = (Math.random() - 0.5) * 4;
waterDrops.push(drop);
game.addChild(drop);
}
self.isActive = true;
// Animate sprinkler activation
tween(sprinklerGraphics, {
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(sprinklerGraphics, {
scaleY: 1.0
}, {
duration: 200,
onFinish: function onFinish() {
self.isActive = false;
}
});
}
});
};
return self;
});
var WaterDrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('waterDrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.gravity = 0.3;
self.velocityY = 0;
self.velocityX = 0;
self.lifespan = 240; // 4 seconds at 60fps
self.age = 0;
self.update = function () {
self.velocityY += self.gravity;
self.y += self.velocityY;
self.x += self.velocityX;
self.age++;
// Fade out over time
dropGraphics.alpha = Math.max(0, 1 - self.age / self.lifespan);
};
return self;
});
var WaterSpout = Container.expand(function () {
var self = Container.call(this);
var spoutGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5
});
spoutGraphics.scaleX = 1.5;
spoutGraphics.scaleY = 0.8;
spoutGraphics.tint = 0x888888;
self.lastSprayTime = Math.random() * 5000; // Random initial delay
self.sprayInterval = 15000; // 15 seconds between sprays
self.isActive = false;
self.spray = function () {
var numDrops = 40 + Math.floor(Math.random() * 30);
for (var i = 0; i < numDrops; i++) {
var drop = new WaterDrop();
var angle = Math.PI * 2 * i / numDrops;
var radius = 50 + Math.random() * 100;
drop.x = self.x + Math.cos(angle) * (Math.random() * 150);
drop.y = self.y + 20;
drop.velocityY = -4 - Math.random() * 6;
drop.velocityX = Math.cos(angle) * (2 + Math.random() * 3);
waterDrops.push(drop);
game.addChild(drop);
}
self.isActive = true;
// Animate spout activation
tween(spoutGraphics, {
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
tween(spoutGraphics, {
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
self.isActive = false;
}
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var dirtSpots = [];
var waterDrops = [];
var sprinklers = [];
var lastDirtSpawnTime = 0;
var dirtSpawnInterval = 5000; // 5 seconds
var gameStartTime = LK.ticks;
var isDragging = false;
var lastDragX = 0;
var lastDragY = 0;
var windowCoverage = 0;
var maxCoverage = 0.4; // 40% pollution triggers game over
var specialButton = null;
var lastSpecialButtonTime = 0;
var specialButtonInterval = 25000; // 25 seconds
var sprinklersDisabled = false;
// Create window frame
var windowFrame = game.addChild(LK.getAsset('windowFrame', {
anchorX: 0.5,
anchorY: 0.5
}));
windowFrame.x = 2048 / 2;
windowFrame.y = 2732 / 2;
// Create main window
var windowPane = game.addChild(LK.getAsset('window', {
anchorX: 0.5,
anchorY: 0.5
}));
windowPane.x = 2048 / 2;
windowPane.y = 2732 / 2;
windowPane.alpha = 0.8;
// Create sprinklers - two on each side
var leftSprinkler1 = new Sprinkler();
leftSprinkler1.x = windowPane.x - windowPane.width / 2 + 60;
leftSprinkler1.y = windowPane.y - windowPane.height / 2 - 60;
sprinklers.push(leftSprinkler1);
game.addChild(leftSprinkler1);
var leftSprinkler2 = new Sprinkler();
leftSprinkler2.x = windowPane.x - windowPane.width / 2 + 60;
leftSprinkler2.y = windowPane.y - windowPane.height / 2 - 200;
sprinklers.push(leftSprinkler2);
game.addChild(leftSprinkler2);
var rightSprinkler1 = new Sprinkler();
rightSprinkler1.x = windowPane.x + windowPane.width / 2 - 60;
rightSprinkler1.y = windowPane.y - windowPane.height / 2 - 60;
sprinklers.push(rightSprinkler1);
game.addChild(rightSprinkler1);
var rightSprinkler2 = new Sprinkler();
rightSprinkler2.x = windowPane.x + windowPane.width / 2 - 60;
rightSprinkler2.y = windowPane.y - windowPane.height / 2 - 200;
sprinklers.push(rightSprinkler2);
game.addChild(rightSprinkler2);
// Create center water spout
var centerSpout = new WaterSpout();
centerSpout.x = windowPane.x;
centerSpout.y = windowPane.y - windowPane.height / 2 - 100;
game.addChild(centerSpout);
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0x000000
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coverage warning
var coverageTxt = new Text2('Glass Pollution: 0%', {
size: 60,
fill: 0x006400
});
coverageTxt.anchor.set(0.5, 0);
coverageTxt.y = 100;
LK.gui.top.addChild(coverageTxt);
// Button instruction text (initially hidden)
var buttonInstructionTxt = new Text2('Press Button', {
size: 80,
fill: 0xFF0000
});
buttonInstructionTxt.anchor.set(0.5, 0.5);
buttonInstructionTxt.visible = false;
// Arrow pointing to button (initially hidden)
var arrowTxt = new Text2('↓', {
size: 120,
fill: 0xFF0000
});
arrowTxt.anchor.set(0.5, 0.5);
arrowTxt.visible = false;
// Function to spawn dirt
function spawnDirt() {
var numDirtSpots = 3 + Math.floor(Math.random() * 5); // 3-7 dirt spots
for (var i = 0; i < numDirtSpots; i++) {
var dirt = new DirtSpot();
// Position within window bounds
var windowBounds = {
left: windowPane.x - windowPane.width / 2 + 50,
right: windowPane.x + windowPane.width / 2 - 50,
top: windowPane.y - windowPane.height / 2 + 50,
bottom: windowPane.y + windowPane.height / 2 - 50
};
dirt.x = windowBounds.left + Math.random() * (windowBounds.right - windowBounds.left);
dirt.y = windowBounds.top + Math.random() * (windowBounds.bottom - windowBounds.top);
dirtSpots.push(dirt);
game.addChild(dirt);
}
LK.getSound('dirtAppear').play();
updateCoverage();
}
// Function to update window coverage
function updateCoverage() {
windowCoverage = Math.min(dirtSpots.length / 50, 1); // Normalize to 0-1
var pollution = Math.floor(windowCoverage * 100);
coverageTxt.setText('Glass Pollution: ' + pollution + '%');
if (pollution > 30) {
coverageTxt.fill = "#FF0000";
} else if (pollution > 20) {
coverageTxt.fill = "#FFA500";
} else {
coverageTxt.fill = "#006400";
}
if (windowCoverage >= maxCoverage) {
LK.effects.flashScreen(0x8B4513, 1000);
LK.showGameOver();
}
}
// Function to clean dirt at position
function cleanAtPosition(x, y, isWater) {
var cleanRadius = isWater ? 50 : 80;
var pointsPerClean = isWater ? 5 : 10;
for (var i = dirtSpots.length - 1; i >= 0; i--) {
var dirt = dirtSpots[i];
var distance = Math.sqrt(Math.pow(dirt.x - x, 2) + Math.pow(dirt.y - y, 2));
if (distance < cleanRadius) {
var cleanAmount = isWater ? Math.max(1, 10 - distance / 5) : Math.max(1, 20 - distance / 4);
if (dirt.clean(cleanAmount)) {
// Dirt spot fully cleaned
LK.setScore(LK.getScore() + pointsPerClean);
scoreTxt.setText('Score: ' + LK.getScore());
dirt.destroy();
dirtSpots.splice(i, 1);
if (!isWater) {
LK.getSound('wipe').play();
}
}
}
}
updateCoverage();
}
// Touch/drag handling
game.down = function (x, y, obj) {
isDragging = true;
lastDragX = x;
lastDragY = y;
cleanAtPosition(x, y);
};
game.move = function (x, y, obj) {
if (isDragging) {
// Clean along the drag path
var steps = Math.max(1, Math.floor(Math.sqrt(Math.pow(x - lastDragX, 2) + Math.pow(y - lastDragY, 2)) / 20));
for (var i = 0; i <= steps; i++) {
var t = steps > 0 ? i / steps : 0;
var cleanX = lastDragX + (x - lastDragX) * t;
var cleanY = lastDragY + (y - lastDragY) * t;
cleanAtPosition(cleanX, cleanY);
}
lastDragX = x;
lastDragY = y;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Main game update loop
game.update = function () {
var currentTime = LK.ticks * (1000 / 60); // Convert ticks to milliseconds
// Update water drops
for (var i = waterDrops.length - 1; i >= 0; i--) {
var drop = waterDrops[i];
if (drop.age >= drop.lifespan || drop.y > windowPane.y + windowPane.height / 2) {
drop.destroy();
waterDrops.splice(i, 1);
continue;
}
// Check if water drop hits dirt
if (drop.y >= windowPane.y - windowPane.height / 2 && drop.y <= windowPane.y + windowPane.height / 2 && drop.x >= windowPane.x - windowPane.width / 2 && drop.x <= windowPane.x + windowPane.width / 2) {
cleanAtPosition(drop.x, drop.y, true);
}
}
// Handle sprinkler spraying (only if not disabled)
if (!sprinklersDisabled) {
for (var j = 0; j < sprinklers.length; j++) {
var sprinkler = sprinklers[j];
if (currentTime - sprinkler.lastSprayTime >= sprinkler.sprayInterval) {
sprinkler.spray();
sprinkler.lastSprayTime = currentTime;
}
}
}
// Handle special button spawning
if (!specialButton && currentTime - lastSpecialButtonTime >= specialButtonInterval) {
specialButton = new SpecialButton();
specialButton.x = windowPane.x + (Math.random() - 0.5) * (windowPane.width - 200);
specialButton.y = windowPane.y + (Math.random() - 0.5) * (windowPane.height - 200);
game.addChild(specialButton);
// Show instruction text and arrow
buttonInstructionTxt.x = specialButton.x;
buttonInstructionTxt.y = specialButton.y - 100;
buttonInstructionTxt.visible = true;
game.addChild(buttonInstructionTxt);
arrowTxt.x = specialButton.x;
arrowTxt.y = specialButton.y - 40;
arrowTxt.visible = true;
game.addChild(arrowTxt);
// Animate the arrow bouncing
tween(arrowTxt, {
y: specialButton.y - 20
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(arrowTxt, {
y: specialButton.y - 40
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue bouncing if button still exists
if (specialButton && arrowTxt.visible) {
tween(arrowTxt, {
y: specialButton.y - 20
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (specialButton && arrowTxt.visible) {
tween(arrowTxt, {
y: specialButton.y - 40
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
});
}
}
});
}
});
}
// Handle water spout spraying
if (currentTime - centerSpout.lastSprayTime >= centerSpout.sprayInterval) {
centerSpout.spray();
centerSpout.lastSprayTime = currentTime;
}
// Spawn dirt every interval
if (currentTime - lastDirtSpawnTime >= dirtSpawnInterval) {
spawnDirt();
lastDirtSpawnTime = currentTime;
// Increase difficulty over time
var gameTime = (currentTime - gameStartTime) / 1000; // Game time in seconds
if (gameTime > 35) {
dirtSpawnInterval = 2000; // 2 seconds after 35 seconds
} else if (gameTime > 30) {
dirtSpawnInterval = Math.max(2000, 5000 - (gameTime - 30) * 50); // Minimum 2 seconds
}
}
// Victory condition - survive for 5 minutes with good cleanliness
var gameTimeMinutes = (currentTime - gameStartTime) / 60000;
if (gameTimeMinutes >= 5 && windowCoverage < 0.3) {
LK.showYouWin();
}
};
// Initial dirt spawn
LK.setTimeout(function () {
spawnDirt();
lastDirtSpawnTime = LK.ticks * (1000 / 60);
}, 1000);