/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Pancake = Container.expand(function () { var self = Container.call(this); // Cooking states: 0=raw, 1=cooking, 2=golden, 3=burnt self.cookingState = 0; self.flipped = false; self.cookingSpeed = 0.02; // How fast pancake cooks per frame self.baseSpeed = 0.02; // Store original base speed for scaling self.cookingProgress = 0; // 0 to 1 self.isActive = true; self.goldenTimer = 0; // Track how long pancake has been golden self.heartBroken = false; // Track if this pancake has already broken a heart // Create visual representation var pancakeGraphic = self.attachAsset('pancake_raw', { anchorX: 0.5, anchorY: 0.5 }); self.updateVisual = function () { self.removeChildren(); var assetName = 'pancake_raw'; if (self.cookingState === 0) assetName = 'pancake_raw';else if (self.cookingState === 1) assetName = 'pancake_cooking';else if (self.cookingState === 2) assetName = 'pancake_golden';else if (self.cookingState === 3) assetName = 'pancake_burnt'; pancakeGraphic = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); }; self.update = function () { if (!self.isActive) return; // Don't continue cooking if burnt if (self.cookingState === 3) return; // Cook the pancake self.cookingProgress += self.cookingSpeed; // Update cooking state based on progress var newState = self.cookingState; if (self.cookingState === 2) { // If already golden, increment timer self.goldenTimer += 1; // Calculate golden duration based on time elapsed (decreases every 4 seconds) var timeElapsed = (LK.ticks - gameStartTime) / 3600; // Convert to seconds var reductionCycles = Math.floor(timeElapsed / 4); // How many 4-second cycles have passed var goldenDuration = Math.max(0.5, 2.0 - reductionCycles * 0.1); // Reduce by 0.1 seconds every 4 seconds, minimum 0.5 seconds var goldenFrames = goldenDuration * 60; // Convert to frames // Only burn after being golden for calculated duration if (self.goldenTimer >= goldenFrames) { newState = 3; // burnt } } else { // Not golden yet, check normal progression // Raw duration is fixed at 0.5 seconds (30 frames at 60fps) if (self.cookingProgress >= 0.8) newState = 2; // golden else if (self.cookingProgress >= 0.5) newState = 1; // cooking - starts after 0.5 seconds } if (newState !== self.cookingState) { self.cookingState = newState; self.updateVisual(); if (self.cookingState === 3) { // Pancake burnt - keep it active so it remains visible LK.getSound('burn').play(); LK.effects.flashObject(self, 0xff0000, 500); // Break a heart (only if this pancake hasn't already broken a heart) if (currentHearts > 0 && !self.heartBroken) { self.heartBroken = true; // Mark this pancake as having broken a heart currentHearts--; // Update heart visual - break the heart at the current position var heartToBreak = hearts[currentHearts]; heartToBreak.removeChildren(); var brokenHeart = heartToBreak.attachAsset('heart_broken', { anchorX: 0.5, anchorY: 0.5 }); // Check for game over if (currentHearts <= 0) { LK.showGameOver(); } } } } }; self.flip = function () { if (!self.isActive || self.flipped) return false; self.flipped = true; self.isActive = false; // Flip animation tween(self, { scaleY: 0 }, { duration: 150, onFinish: function onFinish() { tween(self, { scaleY: 1 }, { duration: 150 }); } }); LK.getSound('flip').play(); // Calculate score based on timing var score = 0; if (self.cookingState === 2) { // Perfect golden pancake score = 100; LK.getSound('perfect').play(); LK.effects.flashObject(self, 0x00ff00, 300); } else if (self.cookingState === 1) { // Good timing but not perfect score = 50; } else if (self.cookingState === 0) { // Too early score = 10; } else { // Burnt - no points score = 0; } return score; }; self.down = function (x, y, obj) { if (self.isActive && !self.flipped && self.cookingState !== 3) { var earnedScore = self.flip(); LK.setScore(LK.getScore() + earnedScore); scoreTxt.setText(LK.getScore()); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x8B4513 }); /**** * Game Code ****/ // Add background image var background = game.addChild(LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); var griddle = game.addChild(LK.getAsset('griddle', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); var pancakes = []; // Game is now infinite - no timer needed var pancakeSpawnRate = 120; // frames between pancake spawns var maxPancakes = 6; var gameStartTime = LK.ticks; // Track when game started for golden duration calculations var hearts = []; var maxHearts = 5; var currentHearts = 5; // UI Elements var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Initialize hearts display for (var h = 0; h < maxHearts; h++) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, x: 150 + h * 90, y: 100 }); hearts.push(heart); LK.gui.topLeft.addChild(heart); } // Timer UI removed for infinite gameplay var instructionTxt = new Text2('Tap pancakes when golden!', { size: 60, fill: 0xFFFF00 }); instructionTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionTxt); // No timer countdown needed for infinite game function spawnPancake() { if (pancakes.length >= maxPancakes) return; var pancake = new Pancake(); // Position pancake on griddle var griddleLeft = griddle.x - griddle.width * 0.4; var griddleRight = griddle.x + griddle.width * 0.4; var griddleTop = griddle.y - griddle.height * 0.3; var griddleBottom = griddle.y + griddle.height * 0.3; pancake.x = griddleLeft + Math.random() * (griddleRight - griddleLeft); pancake.y = griddleTop + Math.random() * (griddleBottom - griddleTop); // Vary cooking speed slightly for difficulty and increase over time var baseSpeed = 0.015 + Math.random() * 0.01; pancake.baseSpeed = baseSpeed; var timeElapsed = LK.ticks / 3600; // Convert ticks to seconds (60fps) var speedMultiplier = 1 + timeElapsed / 60 * 2; // Speed increases up to 3x over first 60 seconds pancake.cookingSpeed = baseSpeed * speedMultiplier; pancakes.push(pancake); game.addChild(pancake); // Entry animation pancake.scaleX = 0; pancake.scaleY = 0; tween(pancake, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.bounceOut }); } game.update = function () { // Spawn new pancakes continuously if (LK.ticks % pancakeSpawnRate === 0) { spawnPancake(); } // Clean up finished pancakes for (var i = pancakes.length - 1; i >= 0; i--) { var pancake = pancakes[i]; if (pancake.flipped || pancake.cookingState === 3) { // Remove pancake after delay if (!pancake.removeTimer) { pancake.removeTimer = LK.setTimeout(function () { if (pancake.parent) { pancake.destroy(); } }, 4000); pancakes.splice(i, 1); } } } // Increase difficulty over time if (LK.ticks % 1800 === 0 && pancakeSpawnRate > 60) { // Every 30 seconds pancakeSpawnRate -= 10; if (maxPancakes < 8) maxPancakes++; } // Gradually increase spawn rate over time (more frequent spawning) if (LK.ticks % 600 === 0 && pancakeSpawnRate > 30) { // Every 10 seconds, decrease spawn delay by 5 frames pancakeSpawnRate -= 5; } // Update cooking speed for all active pancakes based on elapsed time var timeElapsed = LK.ticks / 3600; // Convert ticks to seconds (60fps) var speedMultiplier = 1 + timeElapsed / 60 * 2; // Speed increases up to 3x over first 60 seconds for (var j = 0; j < pancakes.length; j++) { var p = pancakes[j]; if (p.isActive && !p.flipped) { // Update base cooking speed (preserve the random variation from spawn) var baseSpeed = p.baseSpeed || 0.02; p.cookingSpeed = baseSpeed * speedMultiplier; } } // Update score display scoreTxt.setText('Score: ' + LK.getScore()); }; // Start background music LK.playMusic('background_music'); // Initial pancake spawn LK.setTimeout(function () { spawnPancake(); }, 500); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Pancake = Container.expand(function () {
var self = Container.call(this);
// Cooking states: 0=raw, 1=cooking, 2=golden, 3=burnt
self.cookingState = 0;
self.flipped = false;
self.cookingSpeed = 0.02; // How fast pancake cooks per frame
self.baseSpeed = 0.02; // Store original base speed for scaling
self.cookingProgress = 0; // 0 to 1
self.isActive = true;
self.goldenTimer = 0; // Track how long pancake has been golden
self.heartBroken = false; // Track if this pancake has already broken a heart
// Create visual representation
var pancakeGraphic = self.attachAsset('pancake_raw', {
anchorX: 0.5,
anchorY: 0.5
});
self.updateVisual = function () {
self.removeChildren();
var assetName = 'pancake_raw';
if (self.cookingState === 0) assetName = 'pancake_raw';else if (self.cookingState === 1) assetName = 'pancake_cooking';else if (self.cookingState === 2) assetName = 'pancake_golden';else if (self.cookingState === 3) assetName = 'pancake_burnt';
pancakeGraphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.update = function () {
if (!self.isActive) return;
// Don't continue cooking if burnt
if (self.cookingState === 3) return;
// Cook the pancake
self.cookingProgress += self.cookingSpeed;
// Update cooking state based on progress
var newState = self.cookingState;
if (self.cookingState === 2) {
// If already golden, increment timer
self.goldenTimer += 1;
// Calculate golden duration based on time elapsed (decreases every 4 seconds)
var timeElapsed = (LK.ticks - gameStartTime) / 3600; // Convert to seconds
var reductionCycles = Math.floor(timeElapsed / 4); // How many 4-second cycles have passed
var goldenDuration = Math.max(0.5, 2.0 - reductionCycles * 0.1); // Reduce by 0.1 seconds every 4 seconds, minimum 0.5 seconds
var goldenFrames = goldenDuration * 60; // Convert to frames
// Only burn after being golden for calculated duration
if (self.goldenTimer >= goldenFrames) {
newState = 3; // burnt
}
} else {
// Not golden yet, check normal progression
// Raw duration is fixed at 0.5 seconds (30 frames at 60fps)
if (self.cookingProgress >= 0.8) newState = 2; // golden
else if (self.cookingProgress >= 0.5) newState = 1; // cooking - starts after 0.5 seconds
}
if (newState !== self.cookingState) {
self.cookingState = newState;
self.updateVisual();
if (self.cookingState === 3) {
// Pancake burnt - keep it active so it remains visible
LK.getSound('burn').play();
LK.effects.flashObject(self, 0xff0000, 500);
// Break a heart (only if this pancake hasn't already broken a heart)
if (currentHearts > 0 && !self.heartBroken) {
self.heartBroken = true; // Mark this pancake as having broken a heart
currentHearts--;
// Update heart visual - break the heart at the current position
var heartToBreak = hearts[currentHearts];
heartToBreak.removeChildren();
var brokenHeart = heartToBreak.attachAsset('heart_broken', {
anchorX: 0.5,
anchorY: 0.5
});
// Check for game over
if (currentHearts <= 0) {
LK.showGameOver();
}
}
}
}
};
self.flip = function () {
if (!self.isActive || self.flipped) return false;
self.flipped = true;
self.isActive = false;
// Flip animation
tween(self, {
scaleY: 0
}, {
duration: 150,
onFinish: function onFinish() {
tween(self, {
scaleY: 1
}, {
duration: 150
});
}
});
LK.getSound('flip').play();
// Calculate score based on timing
var score = 0;
if (self.cookingState === 2) {
// Perfect golden pancake
score = 100;
LK.getSound('perfect').play();
LK.effects.flashObject(self, 0x00ff00, 300);
} else if (self.cookingState === 1) {
// Good timing but not perfect
score = 50;
} else if (self.cookingState === 0) {
// Too early
score = 10;
} else {
// Burnt - no points
score = 0;
}
return score;
};
self.down = function (x, y, obj) {
if (self.isActive && !self.flipped && self.cookingState !== 3) {
var earnedScore = self.flip();
LK.setScore(LK.getScore() + earnedScore);
scoreTxt.setText(LK.getScore());
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
// Add background image
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
var griddle = game.addChild(LK.getAsset('griddle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
var pancakes = [];
// Game is now infinite - no timer needed
var pancakeSpawnRate = 120; // frames between pancake spawns
var maxPancakes = 6;
var gameStartTime = LK.ticks; // Track when game started for golden duration calculations
var hearts = [];
var maxHearts = 5;
var currentHearts = 5;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize hearts display
for (var h = 0; h < maxHearts; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
x: 150 + h * 90,
y: 100
});
hearts.push(heart);
LK.gui.topLeft.addChild(heart);
}
// Timer UI removed for infinite gameplay
var instructionTxt = new Text2('Tap pancakes when golden!', {
size: 60,
fill: 0xFFFF00
});
instructionTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionTxt);
// No timer countdown needed for infinite game
function spawnPancake() {
if (pancakes.length >= maxPancakes) return;
var pancake = new Pancake();
// Position pancake on griddle
var griddleLeft = griddle.x - griddle.width * 0.4;
var griddleRight = griddle.x + griddle.width * 0.4;
var griddleTop = griddle.y - griddle.height * 0.3;
var griddleBottom = griddle.y + griddle.height * 0.3;
pancake.x = griddleLeft + Math.random() * (griddleRight - griddleLeft);
pancake.y = griddleTop + Math.random() * (griddleBottom - griddleTop);
// Vary cooking speed slightly for difficulty and increase over time
var baseSpeed = 0.015 + Math.random() * 0.01;
pancake.baseSpeed = baseSpeed;
var timeElapsed = LK.ticks / 3600; // Convert ticks to seconds (60fps)
var speedMultiplier = 1 + timeElapsed / 60 * 2; // Speed increases up to 3x over first 60 seconds
pancake.cookingSpeed = baseSpeed * speedMultiplier;
pancakes.push(pancake);
game.addChild(pancake);
// Entry animation
pancake.scaleX = 0;
pancake.scaleY = 0;
tween(pancake, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
}
game.update = function () {
// Spawn new pancakes continuously
if (LK.ticks % pancakeSpawnRate === 0) {
spawnPancake();
}
// Clean up finished pancakes
for (var i = pancakes.length - 1; i >= 0; i--) {
var pancake = pancakes[i];
if (pancake.flipped || pancake.cookingState === 3) {
// Remove pancake after delay
if (!pancake.removeTimer) {
pancake.removeTimer = LK.setTimeout(function () {
if (pancake.parent) {
pancake.destroy();
}
}, 4000);
pancakes.splice(i, 1);
}
}
}
// Increase difficulty over time
if (LK.ticks % 1800 === 0 && pancakeSpawnRate > 60) {
// Every 30 seconds
pancakeSpawnRate -= 10;
if (maxPancakes < 8) maxPancakes++;
}
// Gradually increase spawn rate over time (more frequent spawning)
if (LK.ticks % 600 === 0 && pancakeSpawnRate > 30) {
// Every 10 seconds, decrease spawn delay by 5 frames
pancakeSpawnRate -= 5;
}
// Update cooking speed for all active pancakes based on elapsed time
var timeElapsed = LK.ticks / 3600; // Convert ticks to seconds (60fps)
var speedMultiplier = 1 + timeElapsed / 60 * 2; // Speed increases up to 3x over first 60 seconds
for (var j = 0; j < pancakes.length; j++) {
var p = pancakes[j];
if (p.isActive && !p.flipped) {
// Update base cooking speed (preserve the random variation from spawn)
var baseSpeed = p.baseSpeed || 0.02;
p.cookingSpeed = baseSpeed * speedMultiplier;
}
}
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
};
// Start background music
LK.playMusic('background_music');
// Initial pancake spawn
LK.setTimeout(function () {
spawnPancake();
}, 500);
;
1800x400 not rotated not rounded Griddle. In-Game asset. 2d. 2d 2d 2d topdown view topdown view High contrast. No shadows
A pancake that has started cooking. Transparent transparent 2d 2d 2d topdown view topdown view. In-Game asset. 2d. High contrast. No shadows
Golden pancake transparent transparent 2d 2d 2d 2d 2d 2d 2d topdown view topdown view topdown view. In-Game asset. 2d. High contrast. No shadows
Burnt pancake 2d 2d topdown view topdown view. In-Game asset. 2d. High contrast. No shadows
Raw pancake perfect circle 2d 2d 2d topdown view topdown view. In-Game asset. 2d. High contrast. No shadows
Heart. In-Game asset. 2d. High contrast. No shadows
2048x2732 kitchen table background. In-Game asset. 2d. High contrast. No shadows
Broken heart with a little shadows. In-Game asset. 2d. High contrast. No shadows