/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
selectedSkin: 0
});
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bread = Container.expand(function () {
var self = Container.call(this);
var breadGraphics = self.attachAsset('bread', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Bread position is controlled by drag
};
return self;
});
var Glass = Container.expand(function () {
var self = Container.call(this);
var glassGraphics = self.attachAsset('glass', {
anchorX: 0.5,
anchorY: 0.5
});
self.alpha = 1;
self.update = function () {
// Glass does not move, it just fades out via tween
};
return self;
});
var Hammer = Container.expand(function () {
var self = Container.call(this);
var hammerGraphics = self.attachAsset('hammer', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.lastY = self.y;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Jam = Container.expand(function () {
var self = Container.call(this);
var jamGraphics = self.attachAsset('jam', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastY = self.y;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFFF8DC
});
/****
* Game Code
****/
// Game state variables
var bread = null;
var jams = [];
var hammers = [];
var score = 0;
var waveCount = 0;
var jamSpawnRate = 30;
var jamBaseSpeed = 3;
var dragNode = null;
var lastDodgeTime = 0;
var activeHammer = null;
// UI elements
var scoreText = new Text2('0', {
size: 140,
fill: '#8B4513'
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var waveText = new Text2('Wave: 1', {
size: 100,
fill: '#8B4513'
});
waveText.anchor.set(0.5, 0);
waveText.x = 1024;
LK.gui.top.addChild(waveText);
// Initialize bread at center bottom
bread = game.addChild(new Bread());
bread.x = 1024;
bread.y = 2400;
// Wave progression timer
var waveTimer = LK.setInterval(function () {
waveCount++;
jamSpawnRate = Math.max(15, 30 - waveCount * 2);
jamBaseSpeed = 3 + waveCount * 0.5;
waveText.setText('Wave: ' + waveCount);
}, 8000);
// Jam spawn system
var spawnCounter = 0;
var hammerSpawnCounter = 0;
function spawnJam() {
var newJam = new Jam();
newJam.x = Math.random() * 1900 + 50;
newJam.y = -80;
newJam.speed = jamBaseSpeed + (Math.random() * 1 - 0.5);
newJam.lastY = newJam.y;
newJam.lastIntersecting = false;
jams.push(newJam);
game.addChild(newJam);
}
function spawnHammer() {
var newHammer = new Hammer();
newHammer.x = Math.random() * 1900 + 50;
newHammer.y = -80;
newHammer.speed = 2.5;
newHammer.lastY = newHammer.y;
newHammer.lastIntersecting = false;
hammers.push(newHammer);
game.addChild(newHammer);
}
// Game loop
game.update = function () {
// Spawn jams based on current spawn rate
spawnCounter++;
if (spawnCounter >= jamSpawnRate) {
spawnJam();
spawnCounter = 0;
}
// Spawn hammers occasionally (every 200 ticks when no hammer is active)
hammerSpawnCounter++;
if (hammerSpawnCounter >= 200 && activeHammer === null) {
spawnHammer();
hammerSpawnCounter = 0;
}
// Update and check all jams
for (var i = jams.length - 1; i >= 0; i--) {
var jam = jams[i];
// Off-screen detection
if (jam.lastY <= 2832 && jam.y > 2832) {
jam.destroy();
jams.splice(i, 1);
continue;
}
// Glass effect when jam exits bottom edge
if (jam.lastY <= 2832 && jam.y > 2832) {
var glassEffect = game.addChild(new Glass());
glassEffect.x = jam.x;
glassEffect.y = jam.y;
tween(glassEffect, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
glassEffect.destroy();
}
});
}
// Intersection detection with hammer
var hammerIntersecting = activeHammer !== null && jam.intersects(activeHammer);
if (hammerIntersecting) {
// Create glass effect at jam position
var glassEffect = game.addChild(new Glass());
glassEffect.x = jam.x;
glassEffect.y = jam.y;
// Tween glass to fade out and disappear over 600ms
tween(glassEffect, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
glassEffect.destroy();
}
});
jam.destroy();
jams.splice(i, 1);
score += 5;
scoreText.setText(score);
LK.getSound('dodge').play();
continue;
}
// Intersection detection with bread
var currentIntersecting = jam.intersects(bread);
if (!jam.lastIntersecting && currentIntersecting) {
// Collision detected - game over
LK.effects.flashScreen(0xFF0000, 800);
LK.getSound('hit').play();
// Hide bread and display bread_dead sprite
bread.alpha = 0;
var breadDead = LK.getAsset('Bread_dead', {
anchorX: 0.5,
anchorY: 0.5,
x: bread.x,
y: bread.y
});
game.addChild(breadDead);
// Convert score to coins (1 point = 1 coin)
var coinsEarned = Math.floor(score / 10);
storage.coins = (storage.coins || 0) + coinsEarned;
LK.setScore(score);
LK.showGameOver();
}
// Dodge detection - when jam passes bread without collision
if (jam.lastY < bread.y && jam.y >= bread.y && !currentIntersecting) {
if (LK.ticks - lastDodgeTime > 10) {
score++;
scoreText.setText(score);
LK.getSound('dodge').play();
lastDodgeTime = LK.ticks;
}
}
jam.lastY = jam.y;
jam.lastIntersecting = currentIntersecting;
}
// Update and check all hammers
for (var h = hammers.length - 1; h >= 0; h--) {
var hammer = hammers[h];
// Off-screen detection
if (hammer.lastY >= -100 && hammer.y < -100) {
hammer.destroy();
hammers.splice(h, 1);
if (activeHammer === hammer) activeHammer = null;
continue;
}
// Intersection detection with bread
var hammerBreadIntersecting = hammer.intersects(bread);
if (!hammer.lastIntersecting && hammerBreadIntersecting) {
// Hammer collected
activeHammer = hammer;
hammer.x = bread.x;
hammer.y = bread.y - 80;
LK.getSound('powerup').play();
}
hammer.lastY = hammer.y;
hammer.lastIntersecting = hammerBreadIntersecting;
}
// Move active hammer with bread
if (activeHammer !== null) {
activeHammer.x = bread.x;
activeHammer.y = bread.y - 80;
}
};
// Touch/drag controls
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Clamp bread position to game area
if (dragNode.x < 60) dragNode.x = 60;
if (dragNode.x > 2048 - 60) dragNode.x = 2048 - 60;
if (dragNode.y < 60) dragNode.y = 60;
if (dragNode.y > 2732 - 60) dragNode.y = 2732 - 60;
}
};
game.down = function (x, y, obj) {
dragNode = bread;
game.move(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
activeHammer = null;
};
// Start music
LK.playMusic('bgmusic', {
loop: true
}); /****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
selectedSkin: 0
});
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bread = Container.expand(function () {
var self = Container.call(this);
var breadGraphics = self.attachAsset('bread', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Bread position is controlled by drag
};
return self;
});
var Glass = Container.expand(function () {
var self = Container.call(this);
var glassGraphics = self.attachAsset('glass', {
anchorX: 0.5,
anchorY: 0.5
});
self.alpha = 1;
self.update = function () {
// Glass does not move, it just fades out via tween
};
return self;
});
var Hammer = Container.expand(function () {
var self = Container.call(this);
var hammerGraphics = self.attachAsset('hammer', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.lastY = self.y;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Jam = Container.expand(function () {
var self = Container.call(this);
var jamGraphics = self.attachAsset('jam', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastY = self.y;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFFF8DC
});
/****
* Game Code
****/
// Game state variables
var bread = null;
var jams = [];
var hammers = [];
var score = 0;
var waveCount = 0;
var jamSpawnRate = 30;
var jamBaseSpeed = 3;
var dragNode = null;
var lastDodgeTime = 0;
var activeHammer = null;
// UI elements
var scoreText = new Text2('0', {
size: 140,
fill: '#8B4513'
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var waveText = new Text2('Wave: 1', {
size: 100,
fill: '#8B4513'
});
waveText.anchor.set(0.5, 0);
waveText.x = 1024;
LK.gui.top.addChild(waveText);
// Initialize bread at center bottom
bread = game.addChild(new Bread());
bread.x = 1024;
bread.y = 2400;
// Wave progression timer
var waveTimer = LK.setInterval(function () {
waveCount++;
jamSpawnRate = Math.max(15, 30 - waveCount * 2);
jamBaseSpeed = 3 + waveCount * 0.5;
waveText.setText('Wave: ' + waveCount);
}, 8000);
// Jam spawn system
var spawnCounter = 0;
var hammerSpawnCounter = 0;
function spawnJam() {
var newJam = new Jam();
newJam.x = Math.random() * 1900 + 50;
newJam.y = -80;
newJam.speed = jamBaseSpeed + (Math.random() * 1 - 0.5);
newJam.lastY = newJam.y;
newJam.lastIntersecting = false;
jams.push(newJam);
game.addChild(newJam);
}
function spawnHammer() {
var newHammer = new Hammer();
newHammer.x = Math.random() * 1900 + 50;
newHammer.y = -80;
newHammer.speed = 2.5;
newHammer.lastY = newHammer.y;
newHammer.lastIntersecting = false;
hammers.push(newHammer);
game.addChild(newHammer);
}
// Game loop
game.update = function () {
// Spawn jams based on current spawn rate
spawnCounter++;
if (spawnCounter >= jamSpawnRate) {
spawnJam();
spawnCounter = 0;
}
// Spawn hammers occasionally (every 200 ticks when no hammer is active)
hammerSpawnCounter++;
if (hammerSpawnCounter >= 200 && activeHammer === null) {
spawnHammer();
hammerSpawnCounter = 0;
}
// Update and check all jams
for (var i = jams.length - 1; i >= 0; i--) {
var jam = jams[i];
// Off-screen detection
if (jam.lastY <= 2832 && jam.y > 2832) {
jam.destroy();
jams.splice(i, 1);
continue;
}
// Glass effect when jam exits bottom edge
if (jam.lastY <= 2832 && jam.y > 2832) {
var glassEffect = game.addChild(new Glass());
glassEffect.x = jam.x;
glassEffect.y = jam.y;
tween(glassEffect, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
glassEffect.destroy();
}
});
}
// Intersection detection with hammer
var hammerIntersecting = activeHammer !== null && jam.intersects(activeHammer);
if (hammerIntersecting) {
// Create glass effect at jam position
var glassEffect = game.addChild(new Glass());
glassEffect.x = jam.x;
glassEffect.y = jam.y;
// Tween glass to fade out and disappear over 600ms
tween(glassEffect, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
glassEffect.destroy();
}
});
jam.destroy();
jams.splice(i, 1);
score += 5;
scoreText.setText(score);
LK.getSound('dodge').play();
continue;
}
// Intersection detection with bread
var currentIntersecting = jam.intersects(bread);
if (!jam.lastIntersecting && currentIntersecting) {
// Collision detected - game over
LK.effects.flashScreen(0xFF0000, 800);
LK.getSound('hit').play();
// Hide bread and display bread_dead sprite
bread.alpha = 0;
var breadDead = LK.getAsset('Bread_dead', {
anchorX: 0.5,
anchorY: 0.5,
x: bread.x,
y: bread.y
});
game.addChild(breadDead);
// Convert score to coins (1 point = 1 coin)
var coinsEarned = Math.floor(score / 10);
storage.coins = (storage.coins || 0) + coinsEarned;
LK.setScore(score);
LK.showGameOver();
}
// Dodge detection - when jam passes bread without collision
if (jam.lastY < bread.y && jam.y >= bread.y && !currentIntersecting) {
if (LK.ticks - lastDodgeTime > 10) {
score++;
scoreText.setText(score);
LK.getSound('dodge').play();
lastDodgeTime = LK.ticks;
}
}
jam.lastY = jam.y;
jam.lastIntersecting = currentIntersecting;
}
// Update and check all hammers
for (var h = hammers.length - 1; h >= 0; h--) {
var hammer = hammers[h];
// Off-screen detection
if (hammer.lastY >= -100 && hammer.y < -100) {
hammer.destroy();
hammers.splice(h, 1);
if (activeHammer === hammer) activeHammer = null;
continue;
}
// Intersection detection with bread
var hammerBreadIntersecting = hammer.intersects(bread);
if (!hammer.lastIntersecting && hammerBreadIntersecting) {
// Hammer collected
activeHammer = hammer;
hammer.x = bread.x;
hammer.y = bread.y - 80;
LK.getSound('powerup').play();
}
hammer.lastY = hammer.y;
hammer.lastIntersecting = hammerBreadIntersecting;
}
// Move active hammer with bread
if (activeHammer !== null) {
activeHammer.x = bread.x;
activeHammer.y = bread.y - 80;
}
};
// Touch/drag controls
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Clamp bread position to game area
if (dragNode.x < 60) dragNode.x = 60;
if (dragNode.x > 2048 - 60) dragNode.x = 2048 - 60;
if (dragNode.y < 60) dragNode.y = 60;
if (dragNode.y > 2732 - 60) dragNode.y = 2732 - 60;
}
};
game.down = function (x, y, obj) {
dragNode = bread;
game.move(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
activeHammer = null;
};
// Start music
LK.playMusic('bgmusic', {
loop: true
});
Jar of jam. In-Game asset. 2d. High contrast. No shadows
Hammer. In-Game asset. 2d. High contrast. No shadows
Bread with feet and hands with jam on top and it's dead. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
pieces of glass with spilled jam. In-Game asset. 2d. High contrast. No shadows