/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Chick class: bounces, must be caught in nest or by Jason/Vixen var Chick = Container.expand(function () { var self = Container.call(this); var chickSprite = self.attachAsset('chick', { anchorX: 0.5, anchorY: 0.5 }); self.vy = -12 - Math.random() * 4; // initial pop self.vx = (Math.random() - 0.5) * 8; self.isSafe = false; self.update = function () { if (!self.isSafe) { self.vy += 0.7; // gravity self.x += self.vx; self.y += self.vy; self.vx *= 0.98; } // Check if in nest if (!self.isSafe && self.intersects(nest)) { self.isSafe = true; self.vx = 0; self.vy = 0; // Snap to nest self.y = nest.y - nest.height / 2 + self.height / 2 + 10 + Math.random() * 20; // Animate happy bounce tween(self, { y: self.y - 30 }, { duration: 180, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { y: self.y + 30 }, { duration: 180, easing: tween.easeIn }); } }); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); } // If falls off screen if (self.y > 2732 + 100) { // Game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } }; return self; }); // Egg class: can be juggled, hatches into chick after timer var Egg = Container.expand(function () { var self = Container.call(this); var eggSprite = self.attachAsset('egg', { anchorX: 0.5, anchorY: 0.5 }); self.vy = 0; self.vx = 0; self.hatchTime = 180 + Math.floor(Math.random() * 120); // 3-5 seconds self.age = 0; self.isHeld = false; self.isHatched = false; self.update = function () { if (!self.isHeld) { self.vy += 0.7; // gravity self.x += self.vx; self.y += self.vy; // friction self.vx *= 0.98; } self.age++; if (!self.isHatched && self.age > self.hatchTime) { self.hatch(); } }; self.hatch = function () { if (self.isHatched) return; self.isHatched = true; // Spawn chick at this position var chick = new Chick(); chick.x = self.x; chick.y = self.y; chicks.push(chick); game.addChild(chick); // Animate egg fade out tween(self, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { self.destroy(); eggs.splice(eggs.indexOf(self), 1); } }); }; return self; }); // Fire class: moves horizontally, burns eggs/chicks var Fire = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('fire', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 12 + Math.random() * 8; self.life = 90; self.update = function () { self.x += self.vx; self.life--; // Burn eggs for (var i = eggs.length - 1; i >= 0; i--) { var egg = eggs[i]; if (self.intersects(egg)) { // Burn egg tween(egg, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { egg.destroy(); eggs.splice(eggs.indexOf(egg), 1); } }); } } // Burn chicks for (var i = chicks.length - 1; i >= 0; i--) { var chick = chicks[i]; if (!chick.isSafe && self.intersects(chick)) { // Burn chick tween(chick, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { chick.destroy(); chicks.splice(chicks.indexOf(chick), 1); } }); // Game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } } if (self.life <= 0 || self.x > 2048 + 100) { self.destroy(); fires.splice(fires.indexOf(self), 1); } }; return self; }); // Jason class: draggable, can catch eggs/chicks var Jason = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('jason', { anchorX: 0.5, anchorY: 0.5 }); self.isDragging = false; self.down = function (x, y, obj) { self.isDragging = true; }; self.up = function (x, y, obj) { self.isDragging = false; }; return self; }); // Nest class: static, eggs/chicks must land here var Nest = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('nest', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Vixen class: draggable, sometimes emits fire var Vixen = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('vixen', { anchorX: 0.5, anchorY: 0.5 }); self.isDragging = false; self.fireTimer = 0; self.down = function (x, y, obj) { self.isDragging = true; }; self.up = function (x, y, obj) { self.isDragging = false; }; self.update = function () { // Randomly emit fire every 3-6 seconds self.fireTimer++; if (self.fireTimer > 180 + Math.floor(Math.random() * 180)) { self.fireTimer = 0; self.emitFire(); } }; self.emitFire = function () { var fire = new Fire(); fire.x = self.x + 80; fire.y = self.y; fires.push(fire); game.addChild(fire); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf7e7b6 }); /**** * Game Code ****/ // Jason the Crow (gray box), Vixen the Phoenix (orange ellipse), Egg (white ellipse), Chick (yellow ellipse), Nest (brown ellipse), Fire (red ellipse) // Main arrays var eggs = []; var chicks = []; var fires = []; // Create nest at bottom center var nest = new Nest(); nest.x = 2048 / 2; nest.y = 2732 - 220; game.addChild(nest); // Create Jason and Vixen var jason = new Jason(); jason.x = 2048 / 2 - 220; jason.y = nest.y - 180; game.addChild(jason); var vixen = new Vixen(); vixen.x = 2048 / 2 + 220; vixen.y = nest.y - 180; game.addChild(vixen); // Score display var scoreTxt = new Text2('0', { size: 120, fill: "#222" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Spawn initial eggs function spawnEgg() { var egg = new Egg(); // Place above nest, random offset egg.x = nest.x + (Math.random() - 0.5) * 220; egg.y = nest.y - 220 - Math.random() * 80; eggs.push(egg); game.addChild(egg); } for (var i = 0; i < 3; i++) spawnEgg(); // Dragging logic var dragNode = null; function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; } } game.move = handleMove; game.down = function (x, y, obj) { // Check if Jason or Vixen pressed var localJason = jason.toLocal(game.toGlobal({ x: x, y: y })); if (Math.abs(localJason.x) < jason.width / 2 && Math.abs(localJason.y) < jason.height / 2) { dragNode = jason; jason.isDragging = true; return; } var localVixen = vixen.toLocal(game.toGlobal({ x: x, y: y })); if (Math.abs(localVixen.x) < vixen.width / 2 && Math.abs(localVixen.y) < vixen.height / 2) { dragNode = vixen; vixen.isDragging = true; return; } // Check for eggs for (var i = eggs.length - 1; i >= 0; i--) { var egg = eggs[i]; var localEgg = egg.toLocal(game.toGlobal({ x: x, y: y })); if (Math.abs(localEgg.x) < egg.width / 2 && Math.abs(localEgg.y) < egg.height / 2) { dragNode = egg; egg.isHeld = true; egg.vx = 0; egg.vy = 0; return; } } // Check for chicks for (var i = chicks.length - 1; i >= 0; i--) { var chick = chicks[i]; if (chick.isSafe) continue; var localChick = chick.toLocal(game.toGlobal({ x: x, y: y })); if (Math.abs(localChick.x) < chick.width / 2 && Math.abs(localChick.y) < chick.height / 2) { dragNode = chick; chick.vx = 0; chick.vy = 0; return; } } }; game.up = function (x, y, obj) { if (dragNode) { // If egg or chick, throw with velocity if (eggs.indexOf(dragNode) >= 0) { var egg = dragNode; egg.isHeld = false; egg.vx = (Math.random() - 0.5) * 8; egg.vy = -8 - Math.random() * 4; } if (chicks.indexOf(dragNode) >= 0) { var chick = dragNode; chick.vx = (Math.random() - 0.5) * 8; chick.vy = -8 - Math.random() * 4; } if (dragNode == jason) jason.isDragging = false; if (dragNode == vixen) vixen.isDragging = false; dragNode = null; } }; // Game update var eggSpawnTimer = 0; game.update = function () { // Update eggs for (var i = eggs.length - 1; i >= 0; i--) { eggs[i].update(); // If egg falls off screen if (eggs[i].y > 2732 + 100) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } // If egg lands in nest, stop movement if (!eggs[i].isHeld && eggs[i].vy > 0 && eggs[i].intersects(nest)) { eggs[i].y = nest.y - nest.height / 2 + eggs[i].height / 2 + 10 + Math.random() * 20; eggs[i].vx = 0; eggs[i].vy = 0; } // If egg lands on Jason or Vixen, stop movement if (!eggs[i].isHeld && (eggs[i].intersects(jason) || eggs[i].intersects(vixen))) { eggs[i].vx = 0; eggs[i].vy = 0; } } // Update chicks for (var i = chicks.length - 1; i >= 0; i--) { chicks[i].update(); // If chick lands on Jason or Vixen, bounce up if (!chicks[i].isSafe && (chicks[i].intersects(jason) || chicks[i].intersects(vixen))) { chicks[i].vy = -10 - Math.random() * 4; chicks[i].vx = (Math.random() - 0.5) * 8; } } // Update fires for (var i = fires.length - 1; i >= 0; i--) { fires[i].update(); } // Update Vixen vixen.update && vixen.update(); // Egg spawn logic: spawn new egg every 3-5 seconds, max 5 eggs eggSpawnTimer++; if (eggSpawnTimer > 180 + Math.floor(Math.random() * 120) && eggs.length < 5) { eggSpawnTimer = 0; spawnEgg(); } // Win condition: 10 chicks safe var safeChicks = 0; for (var i = 0; i < chicks.length; i++) if (chicks[i].isSafe) safeChicks++; if (safeChicks >= 10) { LK.showYouWin(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Chick class: bounces, must be caught in nest or by Jason/Vixen
var Chick = Container.expand(function () {
var self = Container.call(this);
var chickSprite = self.attachAsset('chick', {
anchorX: 0.5,
anchorY: 0.5
});
self.vy = -12 - Math.random() * 4; // initial pop
self.vx = (Math.random() - 0.5) * 8;
self.isSafe = false;
self.update = function () {
if (!self.isSafe) {
self.vy += 0.7; // gravity
self.x += self.vx;
self.y += self.vy;
self.vx *= 0.98;
}
// Check if in nest
if (!self.isSafe && self.intersects(nest)) {
self.isSafe = true;
self.vx = 0;
self.vy = 0;
// Snap to nest
self.y = nest.y - nest.height / 2 + self.height / 2 + 10 + Math.random() * 20;
// Animate happy bounce
tween(self, {
y: self.y - 30
}, {
duration: 180,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 30
}, {
duration: 180,
easing: tween.easeIn
});
}
});
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
}
// If falls off screen
if (self.y > 2732 + 100) {
// Game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
};
return self;
});
// Egg class: can be juggled, hatches into chick after timer
var Egg = Container.expand(function () {
var self = Container.call(this);
var eggSprite = self.attachAsset('egg', {
anchorX: 0.5,
anchorY: 0.5
});
self.vy = 0;
self.vx = 0;
self.hatchTime = 180 + Math.floor(Math.random() * 120); // 3-5 seconds
self.age = 0;
self.isHeld = false;
self.isHatched = false;
self.update = function () {
if (!self.isHeld) {
self.vy += 0.7; // gravity
self.x += self.vx;
self.y += self.vy;
// friction
self.vx *= 0.98;
}
self.age++;
if (!self.isHatched && self.age > self.hatchTime) {
self.hatch();
}
};
self.hatch = function () {
if (self.isHatched) return;
self.isHatched = true;
// Spawn chick at this position
var chick = new Chick();
chick.x = self.x;
chick.y = self.y;
chicks.push(chick);
game.addChild(chick);
// Animate egg fade out
tween(self, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
self.destroy();
eggs.splice(eggs.indexOf(self), 1);
}
});
};
return self;
});
// Fire class: moves horizontally, burns eggs/chicks
var Fire = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('fire', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 12 + Math.random() * 8;
self.life = 90;
self.update = function () {
self.x += self.vx;
self.life--;
// Burn eggs
for (var i = eggs.length - 1; i >= 0; i--) {
var egg = eggs[i];
if (self.intersects(egg)) {
// Burn egg
tween(egg, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
egg.destroy();
eggs.splice(eggs.indexOf(egg), 1);
}
});
}
}
// Burn chicks
for (var i = chicks.length - 1; i >= 0; i--) {
var chick = chicks[i];
if (!chick.isSafe && self.intersects(chick)) {
// Burn chick
tween(chick, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
chick.destroy();
chicks.splice(chicks.indexOf(chick), 1);
}
});
// Game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
}
if (self.life <= 0 || self.x > 2048 + 100) {
self.destroy();
fires.splice(fires.indexOf(self), 1);
}
};
return self;
});
// Jason class: draggable, can catch eggs/chicks
var Jason = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('jason', {
anchorX: 0.5,
anchorY: 0.5
});
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
return self;
});
// Nest class: static, eggs/chicks must land here
var Nest = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('nest', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Vixen class: draggable, sometimes emits fire
var Vixen = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('vixen', {
anchorX: 0.5,
anchorY: 0.5
});
self.isDragging = false;
self.fireTimer = 0;
self.down = function (x, y, obj) {
self.isDragging = true;
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.update = function () {
// Randomly emit fire every 3-6 seconds
self.fireTimer++;
if (self.fireTimer > 180 + Math.floor(Math.random() * 180)) {
self.fireTimer = 0;
self.emitFire();
}
};
self.emitFire = function () {
var fire = new Fire();
fire.x = self.x + 80;
fire.y = self.y;
fires.push(fire);
game.addChild(fire);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf7e7b6
});
/****
* Game Code
****/
// Jason the Crow (gray box), Vixen the Phoenix (orange ellipse), Egg (white ellipse), Chick (yellow ellipse), Nest (brown ellipse), Fire (red ellipse)
// Main arrays
var eggs = [];
var chicks = [];
var fires = [];
// Create nest at bottom center
var nest = new Nest();
nest.x = 2048 / 2;
nest.y = 2732 - 220;
game.addChild(nest);
// Create Jason and Vixen
var jason = new Jason();
jason.x = 2048 / 2 - 220;
jason.y = nest.y - 180;
game.addChild(jason);
var vixen = new Vixen();
vixen.x = 2048 / 2 + 220;
vixen.y = nest.y - 180;
game.addChild(vixen);
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Spawn initial eggs
function spawnEgg() {
var egg = new Egg();
// Place above nest, random offset
egg.x = nest.x + (Math.random() - 0.5) * 220;
egg.y = nest.y - 220 - Math.random() * 80;
eggs.push(egg);
game.addChild(egg);
}
for (var i = 0; i < 3; i++) spawnEgg();
// Dragging logic
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Check if Jason or Vixen pressed
var localJason = jason.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(localJason.x) < jason.width / 2 && Math.abs(localJason.y) < jason.height / 2) {
dragNode = jason;
jason.isDragging = true;
return;
}
var localVixen = vixen.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(localVixen.x) < vixen.width / 2 && Math.abs(localVixen.y) < vixen.height / 2) {
dragNode = vixen;
vixen.isDragging = true;
return;
}
// Check for eggs
for (var i = eggs.length - 1; i >= 0; i--) {
var egg = eggs[i];
var localEgg = egg.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(localEgg.x) < egg.width / 2 && Math.abs(localEgg.y) < egg.height / 2) {
dragNode = egg;
egg.isHeld = true;
egg.vx = 0;
egg.vy = 0;
return;
}
}
// Check for chicks
for (var i = chicks.length - 1; i >= 0; i--) {
var chick = chicks[i];
if (chick.isSafe) continue;
var localChick = chick.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(localChick.x) < chick.width / 2 && Math.abs(localChick.y) < chick.height / 2) {
dragNode = chick;
chick.vx = 0;
chick.vy = 0;
return;
}
}
};
game.up = function (x, y, obj) {
if (dragNode) {
// If egg or chick, throw with velocity
if (eggs.indexOf(dragNode) >= 0) {
var egg = dragNode;
egg.isHeld = false;
egg.vx = (Math.random() - 0.5) * 8;
egg.vy = -8 - Math.random() * 4;
}
if (chicks.indexOf(dragNode) >= 0) {
var chick = dragNode;
chick.vx = (Math.random() - 0.5) * 8;
chick.vy = -8 - Math.random() * 4;
}
if (dragNode == jason) jason.isDragging = false;
if (dragNode == vixen) vixen.isDragging = false;
dragNode = null;
}
};
// Game update
var eggSpawnTimer = 0;
game.update = function () {
// Update eggs
for (var i = eggs.length - 1; i >= 0; i--) {
eggs[i].update();
// If egg falls off screen
if (eggs[i].y > 2732 + 100) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
// If egg lands in nest, stop movement
if (!eggs[i].isHeld && eggs[i].vy > 0 && eggs[i].intersects(nest)) {
eggs[i].y = nest.y - nest.height / 2 + eggs[i].height / 2 + 10 + Math.random() * 20;
eggs[i].vx = 0;
eggs[i].vy = 0;
}
// If egg lands on Jason or Vixen, stop movement
if (!eggs[i].isHeld && (eggs[i].intersects(jason) || eggs[i].intersects(vixen))) {
eggs[i].vx = 0;
eggs[i].vy = 0;
}
}
// Update chicks
for (var i = chicks.length - 1; i >= 0; i--) {
chicks[i].update();
// If chick lands on Jason or Vixen, bounce up
if (!chicks[i].isSafe && (chicks[i].intersects(jason) || chicks[i].intersects(vixen))) {
chicks[i].vy = -10 - Math.random() * 4;
chicks[i].vx = (Math.random() - 0.5) * 8;
}
}
// Update fires
for (var i = fires.length - 1; i >= 0; i--) {
fires[i].update();
}
// Update Vixen
vixen.update && vixen.update();
// Egg spawn logic: spawn new egg every 3-5 seconds, max 5 eggs
eggSpawnTimer++;
if (eggSpawnTimer > 180 + Math.floor(Math.random() * 120) && eggs.length < 5) {
eggSpawnTimer = 0;
spawnEgg();
}
// Win condition: 10 chicks safe
var safeChicks = 0;
for (var i = 0; i < chicks.length; i++) if (chicks[i].isSafe) safeChicks++;
if (safeChicks >= 10) {
LK.showYouWin();
}
};