/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Jahia (the bee) class var Jahia = Container.expand(function () { var self = Container.call(this); // Attach bee asset (yellow ellipse with black stripes) var beeBody = self.attachAsset('jahiaBody', { anchorX: 0.5, anchorY: 0.5 }); // Add stripes as separate shapes var stripe1 = self.attachAsset('jahiaStripe1', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -20 }); var stripe2 = self.attachAsset('jahiaStripe2', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); var stripe3 = self.attachAsset('jahiaStripe3', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 20 }); // Add wings var wingL = self.attachAsset('jahiaWingL', { anchorX: 0.5, anchorY: 0.5, x: -40, y: -30 }); var wingR = self.attachAsset('jahiaWingR', { anchorX: 0.5, anchorY: 0.5, x: 40, y: -30 }); self.vy = 0; // vertical speed self.gravity = 1.5; // gravity self.flapStrength = -32; // upward velocity on tap self.alive = true; self.update = function () { if (!self.alive) return; self.vy += self.gravity; self.y += self.vy; // Clamp rotation based on vy self.rotation = Math.max(-0.5, Math.min(1.0, self.vy / 40)); // Prevent bee from going off the top if (self.y < beeMinY) { self.y = beeMinY; self.vy = 0; } // If bee falls below screen, trigger game over if (self.y > beeMaxY) { self.y = beeMaxY; self.vy = 0; self.die(); } }; self.flap = function () { if (!self.alive) return; self.vy = self.flapStrength; // Animate wings tween(wingL, { rotation: -0.7 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(wingL, { rotation: 0 }, { duration: 120, easing: tween.cubicIn }); } }); tween(wingR, { rotation: 0.7 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(wingR, { rotation: 0 }, { duration: 120, easing: tween.cubicIn }); } }); }; self.die = function () { if (!self.alive) return; self.alive = false; LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); }; return self; }); // Pesticide enemy class var Pesticide = Container.expand(function () { var self = Container.call(this); var pestBody = self.attachAsset('pestBody', { anchorX: 0.5, anchorY: 0.5 }); var pestSpray = self.attachAsset('pestSpray', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 40 }); self.vx = -pestSpeed; self.vy = Math.random() > 0.5 ? 2 : -2; self.update = function () { self.x += self.vx; self.y += self.vy; // Bounce off top/bottom if (self.y < beeMinY + 80 || self.y > beeMaxY - 80) { self.vy *= -1; } }; return self; }); // Pipe class (top or bottom) var Pipe = Container.expand(function () { var self = Container.call(this); // Attach pipe asset (pink box with flower) var pipeBody = self.attachAsset('pipeBody', { anchorX: 0.5, anchorY: 0.0 }); var flower = self.attachAsset('pipeFlower', { anchorX: 0.5, anchorY: 0.0, y: -40 }); self.passed = false; // Has bee passed this pipe pair? self.update = function () { self.x -= pipeSpeed; }; return self; }); // Wasp enemy class var Wasp = Container.expand(function () { var self = Container.call(this); var waspBody = self.attachAsset('waspBody', { anchorX: 0.5, anchorY: 0.5 }); var waspWingL = self.attachAsset('waspWingL', { anchorX: 0.5, anchorY: 0.5, x: -30, y: -20 }); var waspWingR = self.attachAsset('waspWingR', { anchorX: 0.5, anchorY: 0.5, x: 30, y: -20 }); self.vx = -waspSpeed; self.amp = 60 + Math.random() * 40; self.phase = Math.random() * Math.PI * 2; self.update = function () { self.x += self.vx; self.y += Math.sin(LK.ticks / 20 + self.phase) * 2; // Animate wings waspWingL.rotation = Math.sin(LK.ticks / 3) * 0.5; waspWingR.rotation = -Math.sin(LK.ticks / 3) * 0.5; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xbee6e0 // Soft blue-green for forest sky }); /**** * Game Code ****/ // Custom forest background asset (replace 'your_forest_asset_id' with your actual asset id) // Game constants var beeStartX = 500; var beeStartY = 1366; var beeMinY = 120; var beeMaxY = 2732 - 120; var pipeGap = 420; var pipeMinY = 350; var pipeMaxY = 2732 - 350 - pipeGap; var pipeSpeed = 16; var waspSpeed = 18; var pestSpeed = 20; var pipeInterval = 120; // frames between pipes var pipes = []; var wasps = []; var pests = []; var nextPipeTick = 0; var nextWaspTick = 0; var nextPestTick = 0; var score = 0; var level = 1; var pipesToNextLevel = 3; var pipesPassedThisLevel = 0; var gameStarted = false; // Add forest background image behind all gameplay elements var forestBg = LK.getAsset('forestBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChild(forestBg); // Create bee var jahia = new Jahia(); game.addChild(jahia); jahia.x = beeStartX; jahia.y = beeStartY; // Play looping background music LK.playMusic('bgmusic'); // GUI: Score, Level, Pipes to next level var scoreTxt = new Text2('0', { size: 120, fill: 0xFFF000 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var levelTxt = new Text2('Niveau 1', { size: 70, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); levelTxt.y = 130; var nextLevelTxt = new Text2('Tuyaux avant niveau suivant: 3', { size: 60, fill: 0xFFFFFF }); nextLevelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(nextLevelTxt); nextLevelTxt.y = 220; // Helper: create a pipe pair (top and bottom) function createPipePair() { var gapY = pipeMinY + Math.random() * (pipeMaxY - pipeMinY); // Top pipe var topPipe = new Pipe(); topPipe.x = 2048 + 120; topPipe.y = gapY - pipeGap / 2 - 600; // pipe height is 600 topPipe.isTop = true; game.addChild(topPipe); pipes.push(topPipe); // Bottom pipe var bottomPipe = new Pipe(); bottomPipe.x = 2048 + 120; bottomPipe.y = gapY + pipeGap / 2; bottomPipe.isTop = false; game.addChild(bottomPipe); pipes.push(bottomPipe); } // Helper: create a wasp function createWasp() { var y = beeMinY + 100 + Math.random() * (beeMaxY - beeMinY - 200); var wasp = new Wasp(); wasp.x = 2048 + 120; wasp.y = y; game.addChild(wasp); wasps.push(wasp); } // Helper: create a pesticide function createPesticide() { var y = beeMinY + 100 + Math.random() * (beeMaxY - beeMinY - 200); var pest = new Pesticide(); pest.x = 2048 + 120; pest.y = y; game.addChild(pest); pests.push(pest); } // Start game on first tap function startGame() { if (gameStarted) return; gameStarted = true; jahia.flap(); } // Tap to flap game.down = function (x, y, obj) { if (!jahia.alive) return; if (!gameStarted) { startGame(); return; } jahia.flap(); }; // Main update loop game.update = function () { if (!jahia.alive) return; // Only start spawning pipes after first tap if (!gameStarted) return; // Update bee jahia.update(); // Spawn pipes if (LK.ticks >= nextPipeTick) { createPipePair(); nextPipeTick = LK.ticks + pipeInterval; } // Update pipes for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; pipe.update(); // Remove pipes off screen if (pipe.x < -200) { pipe.destroy(); pipes.splice(i, 1); continue; } // Collision with bee if (jahia.intersects(pipe)) { jahia.die(); return; } // Score: only on bottom pipe, once per pair if (!pipe.passed && !pipe.isTop && pipe.x + 80 < jahia.x) { pipe.passed = true; score += 1; pipesPassedThisLevel += 1; LK.setScore(score); scoreTxt.setText(score); // Level up if (pipesPassedThisLevel >= pipesToNextLevel) { level += 1; pipesPassedThisLevel = 0; levelTxt.setText('Niveau ' + level); // Double the number of pipes needed for next level, starting from 3 for level 1 if (level === 1) { pipesToNextLevel = 3; } else { pipesToNextLevel = pipesToNextLevel * 2; } // Increase difficulty if (level < 10) { pipeSpeed += 1; } else if (level < 20) { pipeSpeed += 0.5; } // More frequent pipes if (pipeInterval > 70) { pipeInterval -= 4; } } nextLevelTxt.setText('Tuyaux avant niveau suivant: ' + (pipesToNextLevel - pipesPassedThisLevel)); } } // Spawn wasps from level 5 if (level >= 5 && LK.ticks >= nextWaspTick) { createWasp(); nextWaspTick = LK.ticks + Math.max(90, 300 - level * 10); } // Update wasps for (var i = wasps.length - 1; i >= 0; i--) { var wasp = wasps[i]; wasp.update(); if (wasp.x < -200) { wasp.destroy(); wasps.splice(i, 1); continue; } if (jahia.intersects(wasp)) { jahia.die(); return; } } // Spawn pesticides from level 20 if (level >= 20 && LK.ticks >= nextPestTick) { createPesticide(); nextPestTick = LK.ticks + Math.max(120, 400 - (level - 20) * 8); } // Update pesticides for (var i = pests.length - 1; i >= 0; i--) { var pest = pests[i]; pest.update(); if (pest.x < -200) { pest.destroy(); pests.splice(i, 1); continue; } if (jahia.intersects(pest)) { jahia.die(); return; } } }; // Reset game state on game over (handled by LK, but clear arrays for safety) game.onDestroy = function () { pipes = []; wasps = []; pests = []; score = 0; level = 1; pipesPassedThisLevel = 0; pipesToNextLevel = 3; pipeSpeed = 16; pipeInterval = 120; gameStarted = false; }; /**** * Asset Definitions (for LK static analysis) ****/ // Bee body (yellow ellipse) // Bee stripes (black boxes) // Bee wings (white ellipses) // Pipe body (pink box) // Pipe flower (small yellow ellipse) // Wasp body (black/yellow ellipse) // Pesticide (green box with white spray)
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Jahia (the bee) class
var Jahia = Container.expand(function () {
var self = Container.call(this);
// Attach bee asset (yellow ellipse with black stripes)
var beeBody = self.attachAsset('jahiaBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Add stripes as separate shapes
var stripe1 = self.attachAsset('jahiaStripe1', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -20
});
var stripe2 = self.attachAsset('jahiaStripe2', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
var stripe3 = self.attachAsset('jahiaStripe3', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 20
});
// Add wings
var wingL = self.attachAsset('jahiaWingL', {
anchorX: 0.5,
anchorY: 0.5,
x: -40,
y: -30
});
var wingR = self.attachAsset('jahiaWingR', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: -30
});
self.vy = 0; // vertical speed
self.gravity = 1.5; // gravity
self.flapStrength = -32; // upward velocity on tap
self.alive = true;
self.update = function () {
if (!self.alive) return;
self.vy += self.gravity;
self.y += self.vy;
// Clamp rotation based on vy
self.rotation = Math.max(-0.5, Math.min(1.0, self.vy / 40));
// Prevent bee from going off the top
if (self.y < beeMinY) {
self.y = beeMinY;
self.vy = 0;
}
// If bee falls below screen, trigger game over
if (self.y > beeMaxY) {
self.y = beeMaxY;
self.vy = 0;
self.die();
}
};
self.flap = function () {
if (!self.alive) return;
self.vy = self.flapStrength;
// Animate wings
tween(wingL, {
rotation: -0.7
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(wingL, {
rotation: 0
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
tween(wingR, {
rotation: 0.7
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(wingR, {
rotation: 0
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
};
self.die = function () {
if (!self.alive) return;
self.alive = false;
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
};
return self;
});
// Pesticide enemy class
var Pesticide = Container.expand(function () {
var self = Container.call(this);
var pestBody = self.attachAsset('pestBody', {
anchorX: 0.5,
anchorY: 0.5
});
var pestSpray = self.attachAsset('pestSpray', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 40
});
self.vx = -pestSpeed;
self.vy = Math.random() > 0.5 ? 2 : -2;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// Bounce off top/bottom
if (self.y < beeMinY + 80 || self.y > beeMaxY - 80) {
self.vy *= -1;
}
};
return self;
});
// Pipe class (top or bottom)
var Pipe = Container.expand(function () {
var self = Container.call(this);
// Attach pipe asset (pink box with flower)
var pipeBody = self.attachAsset('pipeBody', {
anchorX: 0.5,
anchorY: 0.0
});
var flower = self.attachAsset('pipeFlower', {
anchorX: 0.5,
anchorY: 0.0,
y: -40
});
self.passed = false; // Has bee passed this pipe pair?
self.update = function () {
self.x -= pipeSpeed;
};
return self;
});
// Wasp enemy class
var Wasp = Container.expand(function () {
var self = Container.call(this);
var waspBody = self.attachAsset('waspBody', {
anchorX: 0.5,
anchorY: 0.5
});
var waspWingL = self.attachAsset('waspWingL', {
anchorX: 0.5,
anchorY: 0.5,
x: -30,
y: -20
});
var waspWingR = self.attachAsset('waspWingR', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -20
});
self.vx = -waspSpeed;
self.amp = 60 + Math.random() * 40;
self.phase = Math.random() * Math.PI * 2;
self.update = function () {
self.x += self.vx;
self.y += Math.sin(LK.ticks / 20 + self.phase) * 2;
// Animate wings
waspWingL.rotation = Math.sin(LK.ticks / 3) * 0.5;
waspWingR.rotation = -Math.sin(LK.ticks / 3) * 0.5;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xbee6e0 // Soft blue-green for forest sky
});
/****
* Game Code
****/
// Custom forest background asset (replace 'your_forest_asset_id' with your actual asset id)
// Game constants
var beeStartX = 500;
var beeStartY = 1366;
var beeMinY = 120;
var beeMaxY = 2732 - 120;
var pipeGap = 420;
var pipeMinY = 350;
var pipeMaxY = 2732 - 350 - pipeGap;
var pipeSpeed = 16;
var waspSpeed = 18;
var pestSpeed = 20;
var pipeInterval = 120; // frames between pipes
var pipes = [];
var wasps = [];
var pests = [];
var nextPipeTick = 0;
var nextWaspTick = 0;
var nextPestTick = 0;
var score = 0;
var level = 1;
var pipesToNextLevel = 3;
var pipesPassedThisLevel = 0;
var gameStarted = false;
// Add forest background image behind all gameplay elements
var forestBg = LK.getAsset('forestBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(forestBg);
// Create bee
var jahia = new Jahia();
game.addChild(jahia);
jahia.x = beeStartX;
jahia.y = beeStartY;
// Play looping background music
LK.playMusic('bgmusic');
// GUI: Score, Level, Pipes to next level
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFF000
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Niveau 1', {
size: 70,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 130;
var nextLevelTxt = new Text2('Tuyaux avant niveau suivant: 3', {
size: 60,
fill: 0xFFFFFF
});
nextLevelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(nextLevelTxt);
nextLevelTxt.y = 220;
// Helper: create a pipe pair (top and bottom)
function createPipePair() {
var gapY = pipeMinY + Math.random() * (pipeMaxY - pipeMinY);
// Top pipe
var topPipe = new Pipe();
topPipe.x = 2048 + 120;
topPipe.y = gapY - pipeGap / 2 - 600; // pipe height is 600
topPipe.isTop = true;
game.addChild(topPipe);
pipes.push(topPipe);
// Bottom pipe
var bottomPipe = new Pipe();
bottomPipe.x = 2048 + 120;
bottomPipe.y = gapY + pipeGap / 2;
bottomPipe.isTop = false;
game.addChild(bottomPipe);
pipes.push(bottomPipe);
}
// Helper: create a wasp
function createWasp() {
var y = beeMinY + 100 + Math.random() * (beeMaxY - beeMinY - 200);
var wasp = new Wasp();
wasp.x = 2048 + 120;
wasp.y = y;
game.addChild(wasp);
wasps.push(wasp);
}
// Helper: create a pesticide
function createPesticide() {
var y = beeMinY + 100 + Math.random() * (beeMaxY - beeMinY - 200);
var pest = new Pesticide();
pest.x = 2048 + 120;
pest.y = y;
game.addChild(pest);
pests.push(pest);
}
// Start game on first tap
function startGame() {
if (gameStarted) return;
gameStarted = true;
jahia.flap();
}
// Tap to flap
game.down = function (x, y, obj) {
if (!jahia.alive) return;
if (!gameStarted) {
startGame();
return;
}
jahia.flap();
};
// Main update loop
game.update = function () {
if (!jahia.alive) return;
// Only start spawning pipes after first tap
if (!gameStarted) return;
// Update bee
jahia.update();
// Spawn pipes
if (LK.ticks >= nextPipeTick) {
createPipePair();
nextPipeTick = LK.ticks + pipeInterval;
}
// Update pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
pipe.update();
// Remove pipes off screen
if (pipe.x < -200) {
pipe.destroy();
pipes.splice(i, 1);
continue;
}
// Collision with bee
if (jahia.intersects(pipe)) {
jahia.die();
return;
}
// Score: only on bottom pipe, once per pair
if (!pipe.passed && !pipe.isTop && pipe.x + 80 < jahia.x) {
pipe.passed = true;
score += 1;
pipesPassedThisLevel += 1;
LK.setScore(score);
scoreTxt.setText(score);
// Level up
if (pipesPassedThisLevel >= pipesToNextLevel) {
level += 1;
pipesPassedThisLevel = 0;
levelTxt.setText('Niveau ' + level);
// Double the number of pipes needed for next level, starting from 3 for level 1
if (level === 1) {
pipesToNextLevel = 3;
} else {
pipesToNextLevel = pipesToNextLevel * 2;
}
// Increase difficulty
if (level < 10) {
pipeSpeed += 1;
} else if (level < 20) {
pipeSpeed += 0.5;
}
// More frequent pipes
if (pipeInterval > 70) {
pipeInterval -= 4;
}
}
nextLevelTxt.setText('Tuyaux avant niveau suivant: ' + (pipesToNextLevel - pipesPassedThisLevel));
}
}
// Spawn wasps from level 5
if (level >= 5 && LK.ticks >= nextWaspTick) {
createWasp();
nextWaspTick = LK.ticks + Math.max(90, 300 - level * 10);
}
// Update wasps
for (var i = wasps.length - 1; i >= 0; i--) {
var wasp = wasps[i];
wasp.update();
if (wasp.x < -200) {
wasp.destroy();
wasps.splice(i, 1);
continue;
}
if (jahia.intersects(wasp)) {
jahia.die();
return;
}
}
// Spawn pesticides from level 20
if (level >= 20 && LK.ticks >= nextPestTick) {
createPesticide();
nextPestTick = LK.ticks + Math.max(120, 400 - (level - 20) * 8);
}
// Update pesticides
for (var i = pests.length - 1; i >= 0; i--) {
var pest = pests[i];
pest.update();
if (pest.x < -200) {
pest.destroy();
pests.splice(i, 1);
continue;
}
if (jahia.intersects(pest)) {
jahia.die();
return;
}
}
};
// Reset game state on game over (handled by LK, but clear arrays for safety)
game.onDestroy = function () {
pipes = [];
wasps = [];
pests = [];
score = 0;
level = 1;
pipesPassedThisLevel = 0;
pipesToNextLevel = 3;
pipeSpeed = 16;
pipeInterval = 120;
gameStarted = false;
};
/****
* Asset Definitions (for LK static analysis)
****/
// Bee body (yellow ellipse)
// Bee stripes (black boxes)
// Bee wings (white ellipses)
// Pipe body (pink box)
// Pipe flower (small yellow ellipse)
// Wasp body (black/yellow ellipse)
// Pesticide (green box with white spray)