/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BigFox = Container.expand(function () { var self = Container.call(this); var bigFoxGraphics = self.attachAsset('bigFox', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.health = 5; self.maxHealth = 5; self.lastY = 0; self.moveDirection = 'straight'; self.update = function () { // Move towards the egg if (egg) { var dx = egg.x - self.x; var dy = egg.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Normalize direction and apply speed self.x += dx / distance * self.speed * 0.7; // Slightly slower horizontal movement self.y += dy / distance * self.speed; } else { // Fallback to moving down if somehow at same position self.y += self.speed; } } else { // Fallback to moving down if egg doesn't exist self.y += self.speed; } // Health tracking without color changes var healthRatio = self.health / self.maxHealth; }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xFF0000, 200); if (self.health <= 0) { return true; // BigFox is dead } return false; }; return self; }); var BlackChicken = Container.expand(function () { var self = Container.call(this); var chickenGraphics = self.attachAsset('blackChicken', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1; self.shootTimer = 0; self.shootCooldown = 60; // 1 second at 60fps self.target = null; self.lastTarget = null; self.damage = 4; // 4x stronger than regular chicken self.update = function () { // Find nearest fox var nearestFox = null; var nearestDistance = Infinity; for (var i = 0; i < foxes.length; i++) { var fox = foxes[i]; var distance = Math.sqrt(Math.pow(fox.x - self.x, 2) + Math.pow(fox.y - self.y, 2)); if (distance < nearestDistance && distance < 300) { nearestDistance = distance; nearestFox = fox; } } // Check big foxes too for (var i = 0; i < bigFoxes.length; i++) { var bigFox = bigFoxes[i]; var distance = Math.sqrt(Math.pow(bigFox.x - self.x, 2) + Math.pow(bigFox.y - self.y, 2)); if (distance < nearestDistance && distance < 300) { nearestDistance = distance; nearestFox = bigFox; } } self.target = nearestFox; // Move towards target if (self.target) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } // Shoot at target self.shootTimer++; if (self.shootTimer >= self.shootCooldown && self.target) { self.shootTimer = 0; self.shoot(); } }; self.shoot = function () { if (self.target) { // Fire 3 shots for black chicken with slight spread var angles = [-0.3, 0, 0.3]; // Left, center, right spread for (var shotIndex = 0; shotIndex < 3; shotIndex++) { var newBullet = new Bullet(); newBullet.x = self.x; newBullet.y = self.y; // Add angle spread to target position var angle = Math.atan2(self.target.y - self.y, self.target.x - self.x) + angles[shotIndex]; var distance = 500; // Arbitrary distance for target calculation newBullet.targetX = self.x + Math.cos(angle) * distance; newBullet.targetY = self.y + Math.sin(angle) * distance; newBullet.damage = self.damage; // Use black chicken's damage bullets.push(newBullet); game.addChild(newBullet); } LK.getSound('shoot').play(); } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.targetX = 0; self.targetY = 0; self.directionX = 0; self.directionY = 0; self.damage = 1; // Calculate direction on creation self.calculateDirection = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.directionX = dx / distance; self.directionY = dy / distance; } }; self.update = function () { if (self.directionX === 0 && self.directionY === 0) { self.calculateDirection(); } self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); var Chicken = Container.expand(function () { var self = Container.call(this); var chickenGraphics = self.attachAsset('chicken', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1; self.shootTimer = 0; self.shootCooldown = 60; // 1 second at 60fps self.target = null; self.lastTarget = null; self.update = function () { // Find nearest fox var nearestFox = null; var nearestDistance = Infinity; for (var i = 0; i < foxes.length; i++) { var fox = foxes[i]; var distance = Math.sqrt(Math.pow(fox.x - self.x, 2) + Math.pow(fox.y - self.y, 2)); if (distance < nearestDistance && distance < 300) { nearestDistance = distance; nearestFox = fox; } } // Check big foxes too for (var i = 0; i < bigFoxes.length; i++) { var bigFox = bigFoxes[i]; var distance = Math.sqrt(Math.pow(bigFox.x - self.x, 2) + Math.pow(bigFox.y - self.y, 2)); if (distance < nearestDistance && distance < 300) { nearestDistance = distance; nearestFox = bigFox; } } self.target = nearestFox; // Move towards target if (self.target) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } // Shoot at target self.shootTimer++; if (self.shootTimer >= self.shootCooldown && self.target) { self.shootTimer = 0; self.shoot(); } }; self.shoot = function () { if (self.target) { var newBullet = new Bullet(); newBullet.x = self.x; newBullet.y = self.y; newBullet.targetX = self.target.x; newBullet.targetY = self.target.y; bullets.push(newBullet); game.addChild(newBullet); LK.getSound('shoot').play(); } }; return self; }); var Egg = Container.expand(function () { var self = Container.call(this); var eggGraphics = self.attachAsset('egg', { anchorX: 0.5, anchorY: 0.5 }); self.health = 10; self.maxHealth = 10; self.hatchChance = 0.025; // 2.5% chance self.blackChickenChance = 0.005; // 0.5% chance self.lastHealth = self.health; self.down = function (x, y, obj) { self.tryHatch(); }; self.tryHatch = function () { touchCount++; // Check if we've reached guaranteed spawn threshold if (touchCount >= guaranteedSpawnTouches) { // Guaranteed spawn - reset counter and spawn chicken touchCount = 0; self.spawnChicken(); LK.getSound('hatch').play(); LK.effects.flashObject(self, 0xFFD700, 300); return; } // Regular random spawn logic var randomValue = Math.random(); if (randomValue < self.blackChickenChance) { // Spawn black chicken (0.5% chance) self.spawnBlackChicken(); LK.getSound('hatch').play(); LK.effects.flashObject(self, 0x000000, 300); // Reset touch counter since we got a spawn touchCount = 0; } else if (randomValue < self.hatchChance) { // Spawn regular chicken (remaining 2% to reach 2.5% total) self.spawnChicken(); LK.getSound('hatch').play(); LK.effects.flashObject(self, 0xFFD700, 300); // Reset touch counter since we got a spawn touchCount = 0; } else { // Failed hatch visual feedback tween(self, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } }; self.spawnChicken = function () { var newChicken = new Chicken(); // Spawn on top of the egg with random horizontal offset newChicken.x = self.x + (Math.random() - 0.5) * 200; // Random offset between -100 and +100 newChicken.y = self.y - 400; chickens.push(newChicken); game.addChild(newChicken); chickenCount++; chickenTxt.setText('Chickens: ' + chickens.length); }; self.spawnBlackChicken = function () { var newBlackChicken = new BlackChicken(); // Spawn on top of the egg with random horizontal offset newBlackChicken.x = self.x + (Math.random() - 0.5) * 200; // Random offset between -100 and +100 newBlackChicken.y = self.y - 400; chickens.push(newBlackChicken); game.addChild(newBlackChicken); chickenCount++; chickenTxt.setText('Chickens: ' + chickens.length); }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xFF0000, 500); // Update egg color based on health var healthRatio = self.health / self.maxHealth; if (healthRatio > 0.6) { eggGraphics.tint = 0xFFF8DC; // Beige } else if (healthRatio > 0.3) { eggGraphics.tint = 0xFFD700; // Yellow } else { eggGraphics.tint = 0xFF4500; // Red } if (self.health <= 0) { return true; // Egg is destroyed } return false; }; return self; }); var Fox = Container.expand(function () { var self = Container.call(this); var foxGraphics = self.attachAsset('fox', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; self.health = 3; self.maxHealth = 3; self.lastY = 0; self.moveDirection = 'straight'; // Default movement direction self.update = function () { // Move towards the egg if (egg) { var dx = egg.x - self.x; var dy = egg.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Normalize direction and apply speed self.x += dx / distance * self.speed * 0.7; // Slightly slower horizontal movement self.y += dy / distance * self.speed; } else { // Fallback to moving down if somehow at same position self.y += self.speed; } } else { // Fallback to moving down if egg doesn't exist self.y += self.speed; } // Health tracking without color changes var healthRatio = self.health / self.maxHealth; }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xFF0000, 200); if (self.health <= 0) { return true; // Fox is dead } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var egg = null; var foxes = []; var bigFoxes = []; var chickens = []; var bullets = []; var foxSpawnTimer = 0; var foxSpawnRate = 120; // 2 seconds at 60fps var waveNumber = 1; var foxesKilled = 0; var foxesSpawned = 0; var gameStartTime = Date.now(); var chickenCount = 0; var lastFoxMultiplierTrigger = 0; var touchCount = 0; var guaranteedSpawnTouches = 50; // Create UI elements var healthTxt = new Text2('Egg Health: 10', { size: 60, fill: 0xFFFFFF }); healthTxt.anchor.set(0.5, 0); LK.gui.top.addChild(healthTxt); var chickenTxt = new Text2('Chickens: 0', { size: 50, fill: 0xFFFFFF }); chickenTxt.anchor.set(1, 0); chickenTxt.x = -50; chickenTxt.y = 50; LK.gui.topRight.addChild(chickenTxt); // Create egg at bottom center egg = new Egg(); egg.x = 2048 / 2; egg.y = 2732 - 200; game.addChild(egg); function spawnFox() { var newFox = new Fox(); newFox.x = Math.random() * (2048 - 160) + 80; newFox.y = -50; newFox.speed = 1 + Math.random() * 2 + waveNumber * 0.5; newFox.lastY = newFox.y; // Set diagonal movement based on spawn position var screenCenter = 2048 / 2; if (newFox.x < screenCenter - 300) { // Left side - move diagonally right newFox.moveDirection = 'diagonal-right'; } else if (newFox.x > screenCenter + 300) { // Right side - move diagonally left newFox.moveDirection = 'diagonal-left'; } else { // Center - move straight down newFox.moveDirection = 'straight'; } foxes.push(newFox); game.addChild(newFox); foxesSpawned++; } function spawnBigFox() { var newBigFox = new BigFox(); newBigFox.x = Math.random() * (2048 - 320) + 160; newBigFox.y = -100; newBigFox.speed = 1 + waveNumber * 0.3; newBigFox.lastY = newBigFox.y; newBigFox.moveDirection = 'straight'; bigFoxes.push(newBigFox); game.addChild(newBigFox); } function updateDifficulty() { var currentTime = Date.now(); var elapsedTime = (currentTime - gameStartTime) / 1000; // Increase wave every 30 seconds var newWave = Math.floor(elapsedTime / 30) + 1; if (newWave > waveNumber) { waveNumber = newWave; chickenTxt.setText('Chickens: ' + chickens.length); // Increase spawn rate foxSpawnRate = Math.max(30, 120 - waveNumber * 10); } } game.update = function () { updateDifficulty(); // Spawn foxes foxSpawnTimer++; if (foxSpawnTimer >= foxSpawnRate) { foxSpawnTimer = 0; // Check if we need to spawn 2x foxes (every 5 chickens) var foxesToSpawn = 1; var currentFoxMultiplierTrigger = Math.floor(chickenCount / 5); if (currentFoxMultiplierTrigger > lastFoxMultiplierTrigger) { foxesToSpawn = 2; lastFoxMultiplierTrigger = currentFoxMultiplierTrigger; } // Spawn the calculated number of foxes for (var spawnIndex = 0; spawnIndex < foxesToSpawn; spawnIndex++) { spawnFox(); // Spawn big fox every 20 foxes if (foxesSpawned % 20 === 0) { spawnBigFox(); } } } // Update foxes for (var i = foxes.length - 1; i >= 0; i--) { var fox = foxes[i]; // Check if fox reached egg if (fox.lastY < egg.y && fox.y >= egg.y && Math.abs(fox.x - egg.x) < 100) { // Fox attacks egg if (egg.takeDamage(1)) { // Egg is destroyed - game over LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); return; } healthTxt.setText('Egg Health: ' + egg.health); // Remove fox after attack fox.destroy(); foxes.splice(i, 1); continue; } // Remove foxes that go off screen if (fox.y > 2732 + 100) { fox.destroy(); foxes.splice(i, 1); continue; } fox.lastY = fox.y; } // Update big foxes for (var i = bigFoxes.length - 1; i >= 0; i--) { var bigFox = bigFoxes[i]; // Check if big fox reached egg if (bigFox.lastY < egg.y && bigFox.y >= egg.y && Math.abs(bigFox.x - egg.x) < 150) { // Big fox attacks egg for 3 damage if (egg.takeDamage(3)) { // Egg is destroyed - game over LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); return; } healthTxt.setText('Egg Health: ' + egg.health); // Remove big fox after attack bigFox.destroy(); bigFoxes.splice(i, 1); continue; } // Remove big foxes that go off screen if (bigFox.y > 2732 + 100) { bigFox.destroy(); bigFoxes.splice(i, 1); continue; } bigFox.lastY = bigFox.y; } // Update bullets for (var j = bullets.length - 1; j >= 0; j--) { var bullet = bullets[j]; // Check bullet-fox collisions var hit = false; for (var k = foxes.length - 1; k >= 0; k--) { var fox = foxes[k]; if (bullet.intersects(fox)) { // Bullet hits fox - kill immediately with one hit LK.getSound('foxHit').play(); foxesKilled++; LK.setScore(foxesKilled * 10); chickenTxt.setText('Chickens: ' + chickens.length); fox.destroy(); foxes.splice(k, 1); bullet.destroy(); bullets.splice(j, 1); hit = true; break; } } // Check bullet-big fox collisions if (!hit) { for (var k = bigFoxes.length - 1; k >= 0; k--) { var bigFox = bigFoxes[k]; if (bullet.intersects(bigFox)) { // Bullet hits big fox - takes 5 bullets to kill LK.getSound('foxHit').play(); if (bigFox.takeDamage(bullet.damage)) { // Big fox is dead foxesKilled++; LK.setScore(foxesKilled * 50); // Big fox worth 50 points chickenTxt.setText('Chickens: ' + chickens.length); bigFox.destroy(); bigFoxes.splice(k, 1); } bullet.destroy(); bullets.splice(j, 1); hit = true; break; } } } // Remove bullets that go off screen if (!hit && (bullet.x < -50 || bullet.x > 2048 + 50 || bullet.y < -50 || bullet.y > 2732 + 50)) { bullet.destroy(); bullets.splice(j, 1); } } // Update chickens for (var l = chickens.length - 1; l >= 0; l--) { var chicken = chickens[l]; // Check if chicken is still alive (no health system for chickens yet) // Could add zombie attacks on chickens in future versions // Check fox-chicken collisions var chickenHit = false; // Check regular foxes for (var m = foxes.length - 1; m >= 0; m--) { var fox = foxes[m]; if (chicken.intersects(fox)) { // Fox kills chicken chicken.destroy(); chickens.splice(l, 1); chickenHit = true; break; } } // Check big foxes if chicken not already hit if (!chickenHit) { for (var m = bigFoxes.length - 1; m >= 0; m--) { var bigFox = bigFoxes[m]; if (chicken.intersects(bigFox)) { // Big fox kills chicken chicken.destroy(); chickens.splice(l, 1); chickenHit = true; break; } } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigFox = Container.expand(function () {
var self = Container.call(this);
var bigFoxGraphics = self.attachAsset('bigFox', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.health = 5;
self.maxHealth = 5;
self.lastY = 0;
self.moveDirection = 'straight';
self.update = function () {
// Move towards the egg
if (egg) {
var dx = egg.x - self.x;
var dy = egg.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize direction and apply speed
self.x += dx / distance * self.speed * 0.7; // Slightly slower horizontal movement
self.y += dy / distance * self.speed;
} else {
// Fallback to moving down if somehow at same position
self.y += self.speed;
}
} else {
// Fallback to moving down if egg doesn't exist
self.y += self.speed;
}
// Health tracking without color changes
var healthRatio = self.health / self.maxHealth;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
return true; // BigFox is dead
}
return false;
};
return self;
});
var BlackChicken = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('blackChicken', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.shootTimer = 0;
self.shootCooldown = 60; // 1 second at 60fps
self.target = null;
self.lastTarget = null;
self.damage = 4; // 4x stronger than regular chicken
self.update = function () {
// Find nearest fox
var nearestFox = null;
var nearestDistance = Infinity;
for (var i = 0; i < foxes.length; i++) {
var fox = foxes[i];
var distance = Math.sqrt(Math.pow(fox.x - self.x, 2) + Math.pow(fox.y - self.y, 2));
if (distance < nearestDistance && distance < 300) {
nearestDistance = distance;
nearestFox = fox;
}
}
// Check big foxes too
for (var i = 0; i < bigFoxes.length; i++) {
var bigFox = bigFoxes[i];
var distance = Math.sqrt(Math.pow(bigFox.x - self.x, 2) + Math.pow(bigFox.y - self.y, 2));
if (distance < nearestDistance && distance < 300) {
nearestDistance = distance;
nearestFox = bigFox;
}
}
self.target = nearestFox;
// Move towards target
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Shoot at target
self.shootTimer++;
if (self.shootTimer >= self.shootCooldown && self.target) {
self.shootTimer = 0;
self.shoot();
}
};
self.shoot = function () {
if (self.target) {
// Fire 3 shots for black chicken with slight spread
var angles = [-0.3, 0, 0.3]; // Left, center, right spread
for (var shotIndex = 0; shotIndex < 3; shotIndex++) {
var newBullet = new Bullet();
newBullet.x = self.x;
newBullet.y = self.y;
// Add angle spread to target position
var angle = Math.atan2(self.target.y - self.y, self.target.x - self.x) + angles[shotIndex];
var distance = 500; // Arbitrary distance for target calculation
newBullet.targetX = self.x + Math.cos(angle) * distance;
newBullet.targetY = self.y + Math.sin(angle) * distance;
newBullet.damage = self.damage; // Use black chicken's damage
bullets.push(newBullet);
game.addChild(newBullet);
}
LK.getSound('shoot').play();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.targetX = 0;
self.targetY = 0;
self.directionX = 0;
self.directionY = 0;
self.damage = 1;
// Calculate direction on creation
self.calculateDirection = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
};
self.update = function () {
if (self.directionX === 0 && self.directionY === 0) {
self.calculateDirection();
}
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var Chicken = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('chicken', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.shootTimer = 0;
self.shootCooldown = 60; // 1 second at 60fps
self.target = null;
self.lastTarget = null;
self.update = function () {
// Find nearest fox
var nearestFox = null;
var nearestDistance = Infinity;
for (var i = 0; i < foxes.length; i++) {
var fox = foxes[i];
var distance = Math.sqrt(Math.pow(fox.x - self.x, 2) + Math.pow(fox.y - self.y, 2));
if (distance < nearestDistance && distance < 300) {
nearestDistance = distance;
nearestFox = fox;
}
}
// Check big foxes too
for (var i = 0; i < bigFoxes.length; i++) {
var bigFox = bigFoxes[i];
var distance = Math.sqrt(Math.pow(bigFox.x - self.x, 2) + Math.pow(bigFox.y - self.y, 2));
if (distance < nearestDistance && distance < 300) {
nearestDistance = distance;
nearestFox = bigFox;
}
}
self.target = nearestFox;
// Move towards target
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Shoot at target
self.shootTimer++;
if (self.shootTimer >= self.shootCooldown && self.target) {
self.shootTimer = 0;
self.shoot();
}
};
self.shoot = function () {
if (self.target) {
var newBullet = new Bullet();
newBullet.x = self.x;
newBullet.y = self.y;
newBullet.targetX = self.target.x;
newBullet.targetY = self.target.y;
bullets.push(newBullet);
game.addChild(newBullet);
LK.getSound('shoot').play();
}
};
return self;
});
var Egg = Container.expand(function () {
var self = Container.call(this);
var eggGraphics = self.attachAsset('egg', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.maxHealth = 10;
self.hatchChance = 0.025; // 2.5% chance
self.blackChickenChance = 0.005; // 0.5% chance
self.lastHealth = self.health;
self.down = function (x, y, obj) {
self.tryHatch();
};
self.tryHatch = function () {
touchCount++;
// Check if we've reached guaranteed spawn threshold
if (touchCount >= guaranteedSpawnTouches) {
// Guaranteed spawn - reset counter and spawn chicken
touchCount = 0;
self.spawnChicken();
LK.getSound('hatch').play();
LK.effects.flashObject(self, 0xFFD700, 300);
return;
}
// Regular random spawn logic
var randomValue = Math.random();
if (randomValue < self.blackChickenChance) {
// Spawn black chicken (0.5% chance)
self.spawnBlackChicken();
LK.getSound('hatch').play();
LK.effects.flashObject(self, 0x000000, 300);
// Reset touch counter since we got a spawn
touchCount = 0;
} else if (randomValue < self.hatchChance) {
// Spawn regular chicken (remaining 2% to reach 2.5% total)
self.spawnChicken();
LK.getSound('hatch').play();
LK.effects.flashObject(self, 0xFFD700, 300);
// Reset touch counter since we got a spawn
touchCount = 0;
} else {
// Failed hatch visual feedback
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
};
self.spawnChicken = function () {
var newChicken = new Chicken();
// Spawn on top of the egg with random horizontal offset
newChicken.x = self.x + (Math.random() - 0.5) * 200; // Random offset between -100 and +100
newChicken.y = self.y - 400;
chickens.push(newChicken);
game.addChild(newChicken);
chickenCount++;
chickenTxt.setText('Chickens: ' + chickens.length);
};
self.spawnBlackChicken = function () {
var newBlackChicken = new BlackChicken();
// Spawn on top of the egg with random horizontal offset
newBlackChicken.x = self.x + (Math.random() - 0.5) * 200; // Random offset between -100 and +100
newBlackChicken.y = self.y - 400;
chickens.push(newBlackChicken);
game.addChild(newBlackChicken);
chickenCount++;
chickenTxt.setText('Chickens: ' + chickens.length);
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 500);
// Update egg color based on health
var healthRatio = self.health / self.maxHealth;
if (healthRatio > 0.6) {
eggGraphics.tint = 0xFFF8DC; // Beige
} else if (healthRatio > 0.3) {
eggGraphics.tint = 0xFFD700; // Yellow
} else {
eggGraphics.tint = 0xFF4500; // Red
}
if (self.health <= 0) {
return true; // Egg is destroyed
}
return false;
};
return self;
});
var Fox = Container.expand(function () {
var self = Container.call(this);
var foxGraphics = self.attachAsset('fox', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.health = 3;
self.maxHealth = 3;
self.lastY = 0;
self.moveDirection = 'straight'; // Default movement direction
self.update = function () {
// Move towards the egg
if (egg) {
var dx = egg.x - self.x;
var dy = egg.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize direction and apply speed
self.x += dx / distance * self.speed * 0.7; // Slightly slower horizontal movement
self.y += dy / distance * self.speed;
} else {
// Fallback to moving down if somehow at same position
self.y += self.speed;
}
} else {
// Fallback to moving down if egg doesn't exist
self.y += self.speed;
}
// Health tracking without color changes
var healthRatio = self.health / self.maxHealth;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
return true; // Fox is dead
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var egg = null;
var foxes = [];
var bigFoxes = [];
var chickens = [];
var bullets = [];
var foxSpawnTimer = 0;
var foxSpawnRate = 120; // 2 seconds at 60fps
var waveNumber = 1;
var foxesKilled = 0;
var foxesSpawned = 0;
var gameStartTime = Date.now();
var chickenCount = 0;
var lastFoxMultiplierTrigger = 0;
var touchCount = 0;
var guaranteedSpawnTouches = 50;
// Create UI elements
var healthTxt = new Text2('Egg Health: 10', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
var chickenTxt = new Text2('Chickens: 0', {
size: 50,
fill: 0xFFFFFF
});
chickenTxt.anchor.set(1, 0);
chickenTxt.x = -50;
chickenTxt.y = 50;
LK.gui.topRight.addChild(chickenTxt);
// Create egg at bottom center
egg = new Egg();
egg.x = 2048 / 2;
egg.y = 2732 - 200;
game.addChild(egg);
function spawnFox() {
var newFox = new Fox();
newFox.x = Math.random() * (2048 - 160) + 80;
newFox.y = -50;
newFox.speed = 1 + Math.random() * 2 + waveNumber * 0.5;
newFox.lastY = newFox.y;
// Set diagonal movement based on spawn position
var screenCenter = 2048 / 2;
if (newFox.x < screenCenter - 300) {
// Left side - move diagonally right
newFox.moveDirection = 'diagonal-right';
} else if (newFox.x > screenCenter + 300) {
// Right side - move diagonally left
newFox.moveDirection = 'diagonal-left';
} else {
// Center - move straight down
newFox.moveDirection = 'straight';
}
foxes.push(newFox);
game.addChild(newFox);
foxesSpawned++;
}
function spawnBigFox() {
var newBigFox = new BigFox();
newBigFox.x = Math.random() * (2048 - 320) + 160;
newBigFox.y = -100;
newBigFox.speed = 1 + waveNumber * 0.3;
newBigFox.lastY = newBigFox.y;
newBigFox.moveDirection = 'straight';
bigFoxes.push(newBigFox);
game.addChild(newBigFox);
}
function updateDifficulty() {
var currentTime = Date.now();
var elapsedTime = (currentTime - gameStartTime) / 1000;
// Increase wave every 30 seconds
var newWave = Math.floor(elapsedTime / 30) + 1;
if (newWave > waveNumber) {
waveNumber = newWave;
chickenTxt.setText('Chickens: ' + chickens.length);
// Increase spawn rate
foxSpawnRate = Math.max(30, 120 - waveNumber * 10);
}
}
game.update = function () {
updateDifficulty();
// Spawn foxes
foxSpawnTimer++;
if (foxSpawnTimer >= foxSpawnRate) {
foxSpawnTimer = 0;
// Check if we need to spawn 2x foxes (every 5 chickens)
var foxesToSpawn = 1;
var currentFoxMultiplierTrigger = Math.floor(chickenCount / 5);
if (currentFoxMultiplierTrigger > lastFoxMultiplierTrigger) {
foxesToSpawn = 2;
lastFoxMultiplierTrigger = currentFoxMultiplierTrigger;
}
// Spawn the calculated number of foxes
for (var spawnIndex = 0; spawnIndex < foxesToSpawn; spawnIndex++) {
spawnFox();
// Spawn big fox every 20 foxes
if (foxesSpawned % 20 === 0) {
spawnBigFox();
}
}
}
// Update foxes
for (var i = foxes.length - 1; i >= 0; i--) {
var fox = foxes[i];
// Check if fox reached egg
if (fox.lastY < egg.y && fox.y >= egg.y && Math.abs(fox.x - egg.x) < 100) {
// Fox attacks egg
if (egg.takeDamage(1)) {
// Egg is destroyed - game over
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
healthTxt.setText('Egg Health: ' + egg.health);
// Remove fox after attack
fox.destroy();
foxes.splice(i, 1);
continue;
}
// Remove foxes that go off screen
if (fox.y > 2732 + 100) {
fox.destroy();
foxes.splice(i, 1);
continue;
}
fox.lastY = fox.y;
}
// Update big foxes
for (var i = bigFoxes.length - 1; i >= 0; i--) {
var bigFox = bigFoxes[i];
// Check if big fox reached egg
if (bigFox.lastY < egg.y && bigFox.y >= egg.y && Math.abs(bigFox.x - egg.x) < 150) {
// Big fox attacks egg for 3 damage
if (egg.takeDamage(3)) {
// Egg is destroyed - game over
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
healthTxt.setText('Egg Health: ' + egg.health);
// Remove big fox after attack
bigFox.destroy();
bigFoxes.splice(i, 1);
continue;
}
// Remove big foxes that go off screen
if (bigFox.y > 2732 + 100) {
bigFox.destroy();
bigFoxes.splice(i, 1);
continue;
}
bigFox.lastY = bigFox.y;
}
// Update bullets
for (var j = bullets.length - 1; j >= 0; j--) {
var bullet = bullets[j];
// Check bullet-fox collisions
var hit = false;
for (var k = foxes.length - 1; k >= 0; k--) {
var fox = foxes[k];
if (bullet.intersects(fox)) {
// Bullet hits fox - kill immediately with one hit
LK.getSound('foxHit').play();
foxesKilled++;
LK.setScore(foxesKilled * 10);
chickenTxt.setText('Chickens: ' + chickens.length);
fox.destroy();
foxes.splice(k, 1);
bullet.destroy();
bullets.splice(j, 1);
hit = true;
break;
}
}
// Check bullet-big fox collisions
if (!hit) {
for (var k = bigFoxes.length - 1; k >= 0; k--) {
var bigFox = bigFoxes[k];
if (bullet.intersects(bigFox)) {
// Bullet hits big fox - takes 5 bullets to kill
LK.getSound('foxHit').play();
if (bigFox.takeDamage(bullet.damage)) {
// Big fox is dead
foxesKilled++;
LK.setScore(foxesKilled * 50); // Big fox worth 50 points
chickenTxt.setText('Chickens: ' + chickens.length);
bigFox.destroy();
bigFoxes.splice(k, 1);
}
bullet.destroy();
bullets.splice(j, 1);
hit = true;
break;
}
}
}
// Remove bullets that go off screen
if (!hit && (bullet.x < -50 || bullet.x > 2048 + 50 || bullet.y < -50 || bullet.y > 2732 + 50)) {
bullet.destroy();
bullets.splice(j, 1);
}
}
// Update chickens
for (var l = chickens.length - 1; l >= 0; l--) {
var chicken = chickens[l];
// Check if chicken is still alive (no health system for chickens yet)
// Could add zombie attacks on chickens in future versions
// Check fox-chicken collisions
var chickenHit = false;
// Check regular foxes
for (var m = foxes.length - 1; m >= 0; m--) {
var fox = foxes[m];
if (chicken.intersects(fox)) {
// Fox kills chicken
chicken.destroy();
chickens.splice(l, 1);
chickenHit = true;
break;
}
}
// Check big foxes if chicken not already hit
if (!chickenHit) {
for (var m = bigFoxes.length - 1; m >= 0; m--) {
var bigFox = bigFoxes[m];
if (chicken.intersects(bigFox)) {
// Big fox kills chicken
chicken.destroy();
chickens.splice(l, 1);
chickenHit = true;
break;
}
}
}
}
};