/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Egg (Projectile) class
var Egg = Container.expand(function () {
var self = Container.call(this);
// Attach egg asset (ellipse, white)
var egg = self.attachAsset('egg', {
width: 40,
height: 60,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Movement speed (upwards)
self.speed = -18;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
// Update method for movement
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Chicken class
var EnemyChicken = Container.expand(function () {
var self = Container.call(this);
// Attach enemy chicken asset (box, light brown)
var enemy = self.attachAsset('enemyChicken', {
width: 160,
height: 160,
color: 0xf5d6b4,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Add a dark red comb
var comb = self.attachAsset('enemyComb', {
width: 50,
height: 30,
color: 0xaa2222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -80
});
// Add a beak
var beak = self.attachAsset('enemyBeak', {
width: 25,
height: 25,
color: 0xffc300,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 60
});
// Add an eye
var eye = self.attachAsset('enemyEye', {
width: 15,
height: 15,
color: 0x111111,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -25
});
// Movement speed (downwards)
self.speed = 6 + Math.random() * 3;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
// Update method for movement
self.update = function () {
self.y += self.speed;
};
return self;
});
// Hero Chicken class
var HeroChicken = Container.expand(function () {
var self = Container.call(this);
// Attach hero chicken asset (box, white)
var hero = self.attachAsset('heroChicken', {
width: 180,
height: 180,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Add a red "comb" on top
var comb = self.attachAsset('heroComb', {
width: 60,
height: 40,
color: 0xff2222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90
});
// Add a yellow beak
var beak = self.attachAsset('heroBeak', {
width: 30,
height: 30,
color: 0xffe066,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 70
});
// Add a small black eye
var eye = self.attachAsset('heroEye', {
width: 20,
height: 20,
color: 0x222222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: -30
});
// For drag logic
self.down = function (x, y, obj) {};
self.up = function (x, y, obj) {};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Light blue sky
});
/****
* Game Code
****/
// Tween plugin for animations
// Game constants
var HERO_START_X = 2048 / 2;
var HERO_START_Y = 2732 - 350;
var ENEMY_SPAWN_INTERVAL = 60; // frames
var WIN_SCORE = 20;
// Game state
var hero = new HeroChicken();
game.addChild(hero);
hero.x = HERO_START_X;
hero.y = HERO_START_Y;
var eggs = [];
var enemies = [];
var dragNode = null;
var canShoot = true;
var shootCooldown = 18; // frames between shots
var shootTimer = 0;
var lastGameOver = false;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn an enemy at random X at the top
function spawnEnemy() {
var enemy = new EnemyChicken();
enemy.x = 180 + Math.random() * (2048 - 360);
enemy.y = -100;
enemy.lastY = enemy.y;
enemy.lastIntersecting = false;
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: shoot an egg
function shootEgg() {
if (!canShoot) return;
var egg = new Egg();
egg.x = hero.x;
egg.y = hero.y - 100;
egg.lastY = egg.y;
egg.lastIntersecting = false;
eggs.push(egg);
game.addChild(egg);
canShoot = false;
shootTimer = shootCooldown;
// Optional: flash hero for feedback
LK.effects.flashObject(hero, 0xffff99, 200);
}
// Drag logic
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp hero inside game area (with margin)
var margin = 100;
var minX = margin;
var maxX = 2048 - margin;
var minY = 800;
var maxY = 2732 - margin;
dragNode.x = Math.max(minX, Math.min(maxX, x));
dragNode.y = Math.max(minY, Math.min(maxY, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is on hero
if (x >= hero.x - 90 && x <= hero.x + 90 && y >= hero.y - 90 && y <= hero.y + 90) {
dragNode = hero;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Handle shooting cooldown
if (!canShoot) {
shootTimer--;
if (shootTimer <= 0) {
canShoot = true;
}
}
// Auto-shoot egg if possible (one at a time, when not cooling down)
if (canShoot && !lastGameOver) {
shootEgg();
}
// Spawn enemies
if (LK.ticks % ENEMY_SPAWN_INTERVAL === 0) {
spawnEnemy();
}
// Update eggs
for (var i = eggs.length - 1; i >= 0; i--) {
var egg = eggs[i];
if (egg.lastY === undefined) egg.lastY = egg.y;
if (egg.lastIntersecting === undefined) egg.lastIntersecting = false;
egg.update();
// Remove egg if off screen
if (egg.lastY >= -80 && egg.y < -80) {
egg.destroy();
eggs.splice(i, 1);
continue;
}
// Check collision with enemies
var hit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
var isect = egg.intersects(enemy);
if (!egg.lastIntersecting && isect) {
// Hit!
hit = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Flash enemy
LK.effects.flashObject(enemy, 0xff0000, 200);
// Remove both
enemy.destroy();
enemies.splice(j, 1);
break;
}
}
if (hit) {
egg.destroy();
eggs.splice(i, 1);
continue;
}
egg.lastY = egg.y;
egg.lastIntersecting = hit;
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
enemy.update();
// Remove enemy if off screen (bottom)
if (enemy.lastY <= 2732 + 100 && enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(k, 1);
continue;
}
// Check collision with hero
var isectHero = enemy.intersects(hero);
if (!enemy.lastIntersecting && isectHero) {
// Game over
if (!lastGameOver) {
LK.effects.flashScreen(0xff0000, 800);
lastGameOver = true;
LK.showGameOver();
}
}
enemy.lastY = enemy.y;
enemy.lastIntersecting = isectHero;
}
// Win condition
if (LK.getScore() >= WIN_SCORE && !lastGameOver) {
lastGameOver = true;
LK.showYouWin();
}
};
// Set initial score
LK.setScore(0);
scoreTxt.setText('0'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Egg (Projectile) class
var Egg = Container.expand(function () {
var self = Container.call(this);
// Attach egg asset (ellipse, white)
var egg = self.attachAsset('egg', {
width: 40,
height: 60,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Movement speed (upwards)
self.speed = -18;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
// Update method for movement
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Chicken class
var EnemyChicken = Container.expand(function () {
var self = Container.call(this);
// Attach enemy chicken asset (box, light brown)
var enemy = self.attachAsset('enemyChicken', {
width: 160,
height: 160,
color: 0xf5d6b4,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Add a dark red comb
var comb = self.attachAsset('enemyComb', {
width: 50,
height: 30,
color: 0xaa2222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -80
});
// Add a beak
var beak = self.attachAsset('enemyBeak', {
width: 25,
height: 25,
color: 0xffc300,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 60
});
// Add an eye
var eye = self.attachAsset('enemyEye', {
width: 15,
height: 15,
color: 0x111111,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -25
});
// Movement speed (downwards)
self.speed = 6 + Math.random() * 3;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
// Update method for movement
self.update = function () {
self.y += self.speed;
};
return self;
});
// Hero Chicken class
var HeroChicken = Container.expand(function () {
var self = Container.call(this);
// Attach hero chicken asset (box, white)
var hero = self.attachAsset('heroChicken', {
width: 180,
height: 180,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Add a red "comb" on top
var comb = self.attachAsset('heroComb', {
width: 60,
height: 40,
color: 0xff2222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90
});
// Add a yellow beak
var beak = self.attachAsset('heroBeak', {
width: 30,
height: 30,
color: 0xffe066,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 70
});
// Add a small black eye
var eye = self.attachAsset('heroEye', {
width: 20,
height: 20,
color: 0x222222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: 35,
y: -30
});
// For drag logic
self.down = function (x, y, obj) {};
self.up = function (x, y, obj) {};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Light blue sky
});
/****
* Game Code
****/
// Tween plugin for animations
// Game constants
var HERO_START_X = 2048 / 2;
var HERO_START_Y = 2732 - 350;
var ENEMY_SPAWN_INTERVAL = 60; // frames
var WIN_SCORE = 20;
// Game state
var hero = new HeroChicken();
game.addChild(hero);
hero.x = HERO_START_X;
hero.y = HERO_START_Y;
var eggs = [];
var enemies = [];
var dragNode = null;
var canShoot = true;
var shootCooldown = 18; // frames between shots
var shootTimer = 0;
var lastGameOver = false;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn an enemy at random X at the top
function spawnEnemy() {
var enemy = new EnemyChicken();
enemy.x = 180 + Math.random() * (2048 - 360);
enemy.y = -100;
enemy.lastY = enemy.y;
enemy.lastIntersecting = false;
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: shoot an egg
function shootEgg() {
if (!canShoot) return;
var egg = new Egg();
egg.x = hero.x;
egg.y = hero.y - 100;
egg.lastY = egg.y;
egg.lastIntersecting = false;
eggs.push(egg);
game.addChild(egg);
canShoot = false;
shootTimer = shootCooldown;
// Optional: flash hero for feedback
LK.effects.flashObject(hero, 0xffff99, 200);
}
// Drag logic
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp hero inside game area (with margin)
var margin = 100;
var minX = margin;
var maxX = 2048 - margin;
var minY = 800;
var maxY = 2732 - margin;
dragNode.x = Math.max(minX, Math.min(maxX, x));
dragNode.y = Math.max(minY, Math.min(maxY, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is on hero
if (x >= hero.x - 90 && x <= hero.x + 90 && y >= hero.y - 90 && y <= hero.y + 90) {
dragNode = hero;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Handle shooting cooldown
if (!canShoot) {
shootTimer--;
if (shootTimer <= 0) {
canShoot = true;
}
}
// Auto-shoot egg if possible (one at a time, when not cooling down)
if (canShoot && !lastGameOver) {
shootEgg();
}
// Spawn enemies
if (LK.ticks % ENEMY_SPAWN_INTERVAL === 0) {
spawnEnemy();
}
// Update eggs
for (var i = eggs.length - 1; i >= 0; i--) {
var egg = eggs[i];
if (egg.lastY === undefined) egg.lastY = egg.y;
if (egg.lastIntersecting === undefined) egg.lastIntersecting = false;
egg.update();
// Remove egg if off screen
if (egg.lastY >= -80 && egg.y < -80) {
egg.destroy();
eggs.splice(i, 1);
continue;
}
// Check collision with enemies
var hit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
var isect = egg.intersects(enemy);
if (!egg.lastIntersecting && isect) {
// Hit!
hit = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Flash enemy
LK.effects.flashObject(enemy, 0xff0000, 200);
// Remove both
enemy.destroy();
enemies.splice(j, 1);
break;
}
}
if (hit) {
egg.destroy();
eggs.splice(i, 1);
continue;
}
egg.lastY = egg.y;
egg.lastIntersecting = hit;
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
enemy.update();
// Remove enemy if off screen (bottom)
if (enemy.lastY <= 2732 + 100 && enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(k, 1);
continue;
}
// Check collision with hero
var isectHero = enemy.intersects(hero);
if (!enemy.lastIntersecting && isectHero) {
// Game over
if (!lastGameOver) {
LK.effects.flashScreen(0xff0000, 800);
lastGameOver = true;
LK.showGameOver();
}
}
enemy.lastY = enemy.y;
enemy.lastIntersecting = isectHero;
}
// Win condition
if (LK.getScore() >= WIN_SCORE && !lastGameOver) {
lastGameOver = true;
LK.showYouWin();
}
};
// Set initial score
LK.setScore(0);
scoreTxt.setText('0');