/****
* 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