/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
//Classes can only be defined here. You cannot create inline classes in the games code.
var Fox = Container.expand(function () {
var self = Container.call(this);
//Create and attach asset. This is the same as calling var xxx = self.addChild(LK.getAsset(...))
var foxGraphics = self.attachAsset('fox', {
anchorX: 0.5,
anchorY: 0.5
});
//Set fox speed
self.speed = 3.5; // Increased initial fox speed
self.scoreValue = 50; // Points gained for scaring a fox
self.lastY = 0;
self.lastWasIntersecting = false;
self.lastBelowToilet = false;
// Removed hasNormalcat property as Normalcat will spawn independently
//If this instance of bullet is attached, this method will be called every tick by the LK engine automatically.
//To not manually call .updated methods. If you want to manually call a method every tick on a class, use a different name than update.
//As .update is called from the LK engine directly, .update cannot have method arguments.
self.update = function () {
// Move the fox towards bottom of screen (simpler vertical fall)
self.y += self.speed;
// Initialize lastY and lastWasIntersecting if they are not defined
if (self.lastY === undefined) {
self.lastY = self.y;
}
if (self.lastWasIntersecting === undefined) {
self.lastWasIntersecting = self.intersects(toilet);
}
// Check if fox falls below the toilet
var isBelowToilet = self.y > toilet.y && (self.x < toilet.x - toilet.width / 2 || self.x > toilet.x + toilet.width / 2);
// Only track if fox is below toilet, don't end game here
self.lastBelowToilet = isBelowToilet;
};
return self; //You must return self if you want other classes to be able to inherit from this class
});
var Normalcat = Container.expand(function () {
var self = Container.call(this);
var catGraphics = self.attachAsset('Normalcat', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
// Import tween plugin
var game = new LK.Game({
backgroundColor: 0xFFC0CB // Init game with pink background
});
/****
* Game Code
****/
// Import tween plugin
// Add bathroom background
var background = LK.getAsset('bathroom', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF //Optional (this is the default string)
//font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", //Optional (this is the default string)
});
// Update and display the score in the game.
scoreTxt.setText(LK.getScore()); // LK.getScore is initialized to zero at game start.
// Center the score text horizontally, anchor point set at the middle of its top edge.
scoreTxt.anchor.set(0.5, 0); // Sets anchor to the center of the top edge of the text.
// Define valid targets for positioning GUI elements:
// gui.topLeft: Position at top-left corner (x=0, y=0).
// gui.top: Position at top-center (x=width/2, y=0).
// gui.topRight: Position at top-right corner (x=width, y=0).
// gui.left: Position at middle-left (x=0, y=height/2).
// gui.center: Position at center (x=width/2, y=height/2).
// gui.right: Position at middle-right (x=width, y=height/2).
// gui.bottomLeft: Position at bottom-left corner (x=0, y=height).
// gui.bottom: Position at bottom-center (x=width/2, y=height).
// gui.bottomRight: Position at bottom-right corner (x=width, y=height).
// Add the score text to the GUI overlay.
// The score text is attached to the top-center of the screen.
// Use LK.gui for overlaying interface elements that should be on top of the game scene.
// LK.gui does not have the same resolution as Game to allow for dynamically scaled GUI. Therefore take care to position elements relative to the core GUI targets.
LK.gui.top.addChild(scoreTxt);
// Create the toilet object and position it at the bottom center
var toilet = LK.getAsset('toilet', {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: 2732 - 50 // Position slightly above the bottom
});
game.addChild(toilet);
// Set up toilet dragging
var isDraggingToilet = false;
var minX = toilet.width / 2;
var maxX = 2048 - toilet.width / 2;
var dragOffset = {
x: 0
};
game.down = function (x, y, obj) {
// Always start dragging the toilet regardless of where the tap is
isDraggingToilet = true;
dragOffset.x = toilet.x - x;
};
game.move = function (x, y, obj) {
// Make toilet follow finger directly
toilet.x = Math.max(minX, Math.min(maxX, x));
};
game.up = function (x, y, obj) {
isDraggingToilet = false;
// Check if tap was on toilet and there are flushed cats to fling out
var toiletBounds = toilet.getBounds();
if (x >= toiletBounds.x && x <= toiletBounds.x + toiletBounds.width && y >= toiletBounds.y && y <= toiletBounds.y + toiletBounds.height && flushedCats.length > 0) {
// Fling out the oldest flushed cat
var catToFling = flushedCats.shift();
// Make cat appear and teleport to toilet position instantly
catToFling.x = toilet.x;
catToFling.y = toilet.y - 100; // Position above toilet
catToFling.alpha = 1;
catToFling.scaleX = 1;
catToFling.scaleY = 1;
catToFling.rotation = 0; // Reset rotation
// Calculate random fling direction to ensure cat flies completely off screen
var flingDirection = Math.random() < 0.5 ? -1 : 1; // Random left or right
var targetX = flingDirection > 0 ? 2048 + 300 : -300; // Fly completely off screen horizontally
var targetY = Math.random() * 800 - 400; // Random height, can go above or below screen
// Small delay to show the cat at toilet position before flinging
LK.setTimeout(function () {
// Animate cat flinging out completely off screen
tween(catToFling, {
x: targetX,
y: targetY,
rotation: Math.random() * Math.PI * 8,
// More spinning
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Cat has flown off screen, destroy it
catToFling.destroy();
}
});
}, 100); // 100ms delay to show cat at toilet before flinging
}
};
//Keep track of similar elements using arrays in the main 'Game' class
var foxes = [];
var normalcats = [];
var flushedCats = []; // Track cats that have been flushed but not yet flung out
// Timer to spawn foxes
var foxSpawnTimer = LK.setInterval(function () {
// Spawn a new fox from a random position at the top of the screen
var newFox = new Fox();
newFox.x = Math.random() * 2048;
newFox.y = -100; // Start above the screen
// Normalcat now spawns independently, removed from fox spawn
foxes.push(newFox);
game.addChild(newFox);
}, 1000); // Spawn a fox every second
// Timer to spawn Normalcats independently
var normalcatSpawnTimer = LK.setInterval(function () {
if (Math.random() < 0.051) {
// 5.1% chance to spawn a Normalcat
var newCat = new Normalcat();
// Find a position away from existing foxes
var attempts = 0;
var validPosition = false;
var catX, catY;
while (!validPosition && attempts < 50) {
catX = Math.random() * 2048;
catY = -100;
validPosition = true;
// Check distance from all existing foxes
for (var j = 0; j < foxes.length; j++) {
var fox = foxes[j];
var distance = Math.sqrt(Math.pow(catX - fox.x, 2) + Math.pow(catY - fox.y, 2));
if (distance < 150) {
// Minimum distance of 150 pixels from foxes
validPosition = false;
break;
}
}
attempts++;
}
// Position cat in random radius of 5 pixels around chosen position
var angle = Math.random() * Math.PI * 2; // Random angle
var radius = Math.random() * 5; // Random radius up to 5 pixels
newCat.x = catX + Math.cos(angle) * radius;
newCat.y = catY + Math.sin(angle) * radius;
normalcats.push(newCat);
game.addChild(newCat);
}
}, 1000); // Check for Normalcat spawn every second
// Ask LK engine to update game every game tick
game.update = function () {
// Always call move and tick methods from the main tick method in the 'Game' class.
for (var i = foxes.length - 1; i >= 0; i--) {
var fox = foxes[i];
// We always track last and current positions of properties which will trigger events.
// This way, we can understand when the state changes (for example, going out the screen or intersecting when it was not last frame)
// Check if fox reached the toilet based on state transition
var currentIntersecting = fox.intersects(toilet);
if (!fox.lastWasIntersecting && currentIntersecting) {
// Fox reached the toilet - score points
LK.setScore(LK.getScore() + fox.scoreValue);
scoreTxt.setText(LK.getScore());
// Play flushing sound
LK.getSound('flush').play();
// Create a different effect for fox (no rotation)
tween(fox, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
fox.destroy();
}
});
// Remove fox from array
foxes.splice(i, 1);
continue;
}
// Check if fox goes out of frame (below screen)
if (fox.y > 2732 + 100) {
// Add some buffer below screen height
// Fox went out of frame - game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
break;
}
// Update last known states
fox.lastY = fox.y;
fox.lastWasIntersecting = currentIntersecting;
// Check if fox is below toilet position
var isBelowToilet = fox.y > toilet.y && (fox.x < toilet.x - toilet.width / 2 || fox.x > toilet.x + toilet.width / 2);
fox.lastBelowToilet = isBelowToilet;
}
// Update Normalcats
for (var j = normalcats.length - 1; j >= 0; j--) {
var cat = normalcats[j];
// Make Normalcat fall like foxes
cat.y += 3.5;
// Check if Normalcat reached the toilet
var catIntersecting = cat.intersects(toilet);
if (catIntersecting) {
// Normalcat reached the toilet - lose 100 points
LK.setScore(LK.getScore() - 100);
scoreTxt.setText(LK.getScore());
// Play flushing sound
LK.getSound('flush').play();
// Add cat to flushed cats array and hide it temporarily
cat.alpha = 0;
cat.x = toilet.x;
cat.y = toilet.y - 50; // Position slightly above toilet
flushedCats.push(cat);
// Remove cat from normal cats array
normalcats.splice(j, 1);
continue;
}
// Let Normalcat fall infinitely - remove from array when far below screen
if (cat.y > 2732 + 500) {
// Remove cat from array when far below screen (no game over)
cat.destroy();
normalcats.splice(j, 1);
continue;
}
}
// Increase difficulty over time
if (LK.ticks % 600 === 0 && LK.ticks > 0) {
// Every 10 seconds
// Increase fox spawn rate by reducing the interval time
LK.clearInterval(foxSpawnTimer);
var spawnRate = Math.max(300, 1000 - Math.floor(LK.ticks / 600) * 100); // Minimum 300ms
foxSpawnTimer = LK.setInterval(function () {
var newFox = new Fox();
newFox.x = Math.random() * (2048 - 200) + 100; // Keep foxes away from edges
newFox.y = -100;
newFox.speed = 3.5 + Math.floor(LK.ticks / 1200) * 0.8; // Increased speed and scaling over time
// Normalcat now spawns independently, removed from fox spawn
foxes.push(newFox);
game.addChild(newFox);
}, spawnRate);
}
};
// Play music track with these musicOptions:
/*
* loop: (optional) a boolean which indicates if to loop the music track. Default is true and doesn't need to be passed if the track should be looping.
* fade: (optional) an object {fade: start: Number Volume to fade from (0.0 to 1.0), end: Number Volume to fade to (0.0 to 1.0), duration: number in miliseconds to fade} }
*/
// LK.playMusic('bgmusic'); // Assuming you have a 'bgmusic' asset initialized /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
//Classes can only be defined here. You cannot create inline classes in the games code.
var Fox = Container.expand(function () {
var self = Container.call(this);
//Create and attach asset. This is the same as calling var xxx = self.addChild(LK.getAsset(...))
var foxGraphics = self.attachAsset('fox', {
anchorX: 0.5,
anchorY: 0.5
});
//Set fox speed
self.speed = 3.5; // Increased initial fox speed
self.scoreValue = 50; // Points gained for scaring a fox
self.lastY = 0;
self.lastWasIntersecting = false;
self.lastBelowToilet = false;
// Removed hasNormalcat property as Normalcat will spawn independently
//If this instance of bullet is attached, this method will be called every tick by the LK engine automatically.
//To not manually call .updated methods. If you want to manually call a method every tick on a class, use a different name than update.
//As .update is called from the LK engine directly, .update cannot have method arguments.
self.update = function () {
// Move the fox towards bottom of screen (simpler vertical fall)
self.y += self.speed;
// Initialize lastY and lastWasIntersecting if they are not defined
if (self.lastY === undefined) {
self.lastY = self.y;
}
if (self.lastWasIntersecting === undefined) {
self.lastWasIntersecting = self.intersects(toilet);
}
// Check if fox falls below the toilet
var isBelowToilet = self.y > toilet.y && (self.x < toilet.x - toilet.width / 2 || self.x > toilet.x + toilet.width / 2);
// Only track if fox is below toilet, don't end game here
self.lastBelowToilet = isBelowToilet;
};
return self; //You must return self if you want other classes to be able to inherit from this class
});
var Normalcat = Container.expand(function () {
var self = Container.call(this);
var catGraphics = self.attachAsset('Normalcat', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
// Import tween plugin
var game = new LK.Game({
backgroundColor: 0xFFC0CB // Init game with pink background
});
/****
* Game Code
****/
// Import tween plugin
// Add bathroom background
var background = LK.getAsset('bathroom', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF //Optional (this is the default string)
//font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", //Optional (this is the default string)
});
// Update and display the score in the game.
scoreTxt.setText(LK.getScore()); // LK.getScore is initialized to zero at game start.
// Center the score text horizontally, anchor point set at the middle of its top edge.
scoreTxt.anchor.set(0.5, 0); // Sets anchor to the center of the top edge of the text.
// Define valid targets for positioning GUI elements:
// gui.topLeft: Position at top-left corner (x=0, y=0).
// gui.top: Position at top-center (x=width/2, y=0).
// gui.topRight: Position at top-right corner (x=width, y=0).
// gui.left: Position at middle-left (x=0, y=height/2).
// gui.center: Position at center (x=width/2, y=height/2).
// gui.right: Position at middle-right (x=width, y=height/2).
// gui.bottomLeft: Position at bottom-left corner (x=0, y=height).
// gui.bottom: Position at bottom-center (x=width/2, y=height).
// gui.bottomRight: Position at bottom-right corner (x=width, y=height).
// Add the score text to the GUI overlay.
// The score text is attached to the top-center of the screen.
// Use LK.gui for overlaying interface elements that should be on top of the game scene.
// LK.gui does not have the same resolution as Game to allow for dynamically scaled GUI. Therefore take care to position elements relative to the core GUI targets.
LK.gui.top.addChild(scoreTxt);
// Create the toilet object and position it at the bottom center
var toilet = LK.getAsset('toilet', {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: 2732 - 50 // Position slightly above the bottom
});
game.addChild(toilet);
// Set up toilet dragging
var isDraggingToilet = false;
var minX = toilet.width / 2;
var maxX = 2048 - toilet.width / 2;
var dragOffset = {
x: 0
};
game.down = function (x, y, obj) {
// Always start dragging the toilet regardless of where the tap is
isDraggingToilet = true;
dragOffset.x = toilet.x - x;
};
game.move = function (x, y, obj) {
// Make toilet follow finger directly
toilet.x = Math.max(minX, Math.min(maxX, x));
};
game.up = function (x, y, obj) {
isDraggingToilet = false;
// Check if tap was on toilet and there are flushed cats to fling out
var toiletBounds = toilet.getBounds();
if (x >= toiletBounds.x && x <= toiletBounds.x + toiletBounds.width && y >= toiletBounds.y && y <= toiletBounds.y + toiletBounds.height && flushedCats.length > 0) {
// Fling out the oldest flushed cat
var catToFling = flushedCats.shift();
// Make cat appear and teleport to toilet position instantly
catToFling.x = toilet.x;
catToFling.y = toilet.y - 100; // Position above toilet
catToFling.alpha = 1;
catToFling.scaleX = 1;
catToFling.scaleY = 1;
catToFling.rotation = 0; // Reset rotation
// Calculate random fling direction to ensure cat flies completely off screen
var flingDirection = Math.random() < 0.5 ? -1 : 1; // Random left or right
var targetX = flingDirection > 0 ? 2048 + 300 : -300; // Fly completely off screen horizontally
var targetY = Math.random() * 800 - 400; // Random height, can go above or below screen
// Small delay to show the cat at toilet position before flinging
LK.setTimeout(function () {
// Animate cat flinging out completely off screen
tween(catToFling, {
x: targetX,
y: targetY,
rotation: Math.random() * Math.PI * 8,
// More spinning
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Cat has flown off screen, destroy it
catToFling.destroy();
}
});
}, 100); // 100ms delay to show cat at toilet before flinging
}
};
//Keep track of similar elements using arrays in the main 'Game' class
var foxes = [];
var normalcats = [];
var flushedCats = []; // Track cats that have been flushed but not yet flung out
// Timer to spawn foxes
var foxSpawnTimer = LK.setInterval(function () {
// Spawn a new fox from a random position at the top of the screen
var newFox = new Fox();
newFox.x = Math.random() * 2048;
newFox.y = -100; // Start above the screen
// Normalcat now spawns independently, removed from fox spawn
foxes.push(newFox);
game.addChild(newFox);
}, 1000); // Spawn a fox every second
// Timer to spawn Normalcats independently
var normalcatSpawnTimer = LK.setInterval(function () {
if (Math.random() < 0.051) {
// 5.1% chance to spawn a Normalcat
var newCat = new Normalcat();
// Find a position away from existing foxes
var attempts = 0;
var validPosition = false;
var catX, catY;
while (!validPosition && attempts < 50) {
catX = Math.random() * 2048;
catY = -100;
validPosition = true;
// Check distance from all existing foxes
for (var j = 0; j < foxes.length; j++) {
var fox = foxes[j];
var distance = Math.sqrt(Math.pow(catX - fox.x, 2) + Math.pow(catY - fox.y, 2));
if (distance < 150) {
// Minimum distance of 150 pixels from foxes
validPosition = false;
break;
}
}
attempts++;
}
// Position cat in random radius of 5 pixels around chosen position
var angle = Math.random() * Math.PI * 2; // Random angle
var radius = Math.random() * 5; // Random radius up to 5 pixels
newCat.x = catX + Math.cos(angle) * radius;
newCat.y = catY + Math.sin(angle) * radius;
normalcats.push(newCat);
game.addChild(newCat);
}
}, 1000); // Check for Normalcat spawn every second
// Ask LK engine to update game every game tick
game.update = function () {
// Always call move and tick methods from the main tick method in the 'Game' class.
for (var i = foxes.length - 1; i >= 0; i--) {
var fox = foxes[i];
// We always track last and current positions of properties which will trigger events.
// This way, we can understand when the state changes (for example, going out the screen or intersecting when it was not last frame)
// Check if fox reached the toilet based on state transition
var currentIntersecting = fox.intersects(toilet);
if (!fox.lastWasIntersecting && currentIntersecting) {
// Fox reached the toilet - score points
LK.setScore(LK.getScore() + fox.scoreValue);
scoreTxt.setText(LK.getScore());
// Play flushing sound
LK.getSound('flush').play();
// Create a different effect for fox (no rotation)
tween(fox, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
fox.destroy();
}
});
// Remove fox from array
foxes.splice(i, 1);
continue;
}
// Check if fox goes out of frame (below screen)
if (fox.y > 2732 + 100) {
// Add some buffer below screen height
// Fox went out of frame - game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
break;
}
// Update last known states
fox.lastY = fox.y;
fox.lastWasIntersecting = currentIntersecting;
// Check if fox is below toilet position
var isBelowToilet = fox.y > toilet.y && (fox.x < toilet.x - toilet.width / 2 || fox.x > toilet.x + toilet.width / 2);
fox.lastBelowToilet = isBelowToilet;
}
// Update Normalcats
for (var j = normalcats.length - 1; j >= 0; j--) {
var cat = normalcats[j];
// Make Normalcat fall like foxes
cat.y += 3.5;
// Check if Normalcat reached the toilet
var catIntersecting = cat.intersects(toilet);
if (catIntersecting) {
// Normalcat reached the toilet - lose 100 points
LK.setScore(LK.getScore() - 100);
scoreTxt.setText(LK.getScore());
// Play flushing sound
LK.getSound('flush').play();
// Add cat to flushed cats array and hide it temporarily
cat.alpha = 0;
cat.x = toilet.x;
cat.y = toilet.y - 50; // Position slightly above toilet
flushedCats.push(cat);
// Remove cat from normal cats array
normalcats.splice(j, 1);
continue;
}
// Let Normalcat fall infinitely - remove from array when far below screen
if (cat.y > 2732 + 500) {
// Remove cat from array when far below screen (no game over)
cat.destroy();
normalcats.splice(j, 1);
continue;
}
}
// Increase difficulty over time
if (LK.ticks % 600 === 0 && LK.ticks > 0) {
// Every 10 seconds
// Increase fox spawn rate by reducing the interval time
LK.clearInterval(foxSpawnTimer);
var spawnRate = Math.max(300, 1000 - Math.floor(LK.ticks / 600) * 100); // Minimum 300ms
foxSpawnTimer = LK.setInterval(function () {
var newFox = new Fox();
newFox.x = Math.random() * (2048 - 200) + 100; // Keep foxes away from edges
newFox.y = -100;
newFox.speed = 3.5 + Math.floor(LK.ticks / 1200) * 0.8; // Increased speed and scaling over time
// Normalcat now spawns independently, removed from fox spawn
foxes.push(newFox);
game.addChild(newFox);
}, spawnRate);
}
};
// Play music track with these musicOptions:
/*
* loop: (optional) a boolean which indicates if to loop the music track. Default is true and doesn't need to be passed if the track should be looping.
* fade: (optional) an object {fade: start: Number Volume to fade from (0.0 to 1.0), end: Number Volume to fade to (0.0 to 1.0), duration: number in miliseconds to fade} }
*/
// LK.playMusic('bgmusic'); // Assuming you have a 'bgmusic' asset initialized
A bathroom with a pink toilet. In-Game asset. 2d. High contrast. No shadows
Make a toilet with a small bit of water leaking of the side. In-Game asset. 2d. High contrast. No shadows. Realistic
Make a realistic fox that is sooooo cute. In-Game asset. 2d. High contrast. No shadows. Realistic
Add a Minecraft emerald sword.