/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0,
anchorY: 0.5
});
weaponGraphics.x = 35;
weaponGraphics.y = 5;
self.velocity = 0;
self.gravity = 0.8;
self.flapStrength = -15;
self.health = 500;
self.maxHealth = 500;
self.invulnerable = false;
self.invulnerableTime = 0;
self.lastShotTime = 0;
self.flap = function () {
if (self.health > 0) {
self.velocity = self.flapStrength;
LK.getSound('flap').play();
}
};
self.update = function () {
if (self.health > 0) {
self.velocity += self.gravity;
self.y += self.velocity;
// Rotate bird based on velocity
birdGraphics.rotation = Math.max(-0.5, Math.min(0.5, self.velocity * 0.05));
// Handle invulnerability
if (self.invulnerable) {
self.invulnerableTime--;
birdGraphics.alpha = self.invulnerableTime % 10 < 5 ? 0.5 : 1.0;
if (self.invulnerableTime <= 0) {
self.invulnerable = false;
birdGraphics.alpha = 1.0;
}
}
// Auto-shoot at eagles when they get close
for (var i = 0; i < eagles.length; i++) {
var eagle = eagles[i];
var distance = Math.sqrt(Math.pow(eagle.x - self.x, 2) + Math.pow(eagle.y - self.y, 2));
// If eagle is within 400 pixels and in front of bird, shoot
if (distance < 400 && eagle.x > self.x) {
// Check if we haven't shot recently (every 30 frames = 0.5 seconds)
if (!self.lastShotTime || LK.ticks - self.lastShotTime > 30) {
self.shoot();
self.lastShotTime = LK.ticks;
break; // Only shoot at one eagle per frame
}
}
}
// Auto-shoot at monsters when they get close
for (var j = 0; j < monsters.length; j++) {
var monster = monsters[j];
var distance = Math.sqrt(Math.pow(monster.x - self.x, 2) + Math.pow(monster.y - self.y, 2));
// If monster is within 500 pixels and in front of bird, shoot
if (distance < 500 && monster.x > self.x) {
// Check if we haven't shot recently (every 25 frames = slightly faster than eagles)
if (!self.lastShotTime || LK.ticks - self.lastShotTime > 25) {
self.shoot();
self.lastShotTime = LK.ticks;
break; // Only shoot at one monster per frame
}
}
}
// Keep bird on screen vertically
if (self.y < 30) {
self.y = 30;
self.velocity = 0;
}
if (self.y > 2732 - 30) {
self.y = 2732 - 30;
self.velocity = 0;
}
}
};
self.shoot = function () {
if (self.health > 0) {
var newBullet = new Bullet();
newBullet.x = self.x + 40;
newBullet.y = self.y;
bullets.push(newBullet);
game.addChild(newBullet);
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
if (!self.invulnerable && self.health > 0) {
self.health -= 25; // Reduce health by 25 points
if (self.health > 0) {
self.invulnerable = true;
self.invulnerableTime = 120; // 2 seconds at 60fps
LK.effects.flashObject(self, 0xFF0000, 500);
}
LK.getSound('hit').play();
return true;
}
return false;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.scaleX = 0.5;
bulletGraphics.scaleY = 0.5;
bulletGraphics.tint = 0xFFFF00;
self.speed = 12;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinGraphics.tint = 0xFFD700; // Bright golden coins in sky
self.speed = 4;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Simple floating animation
coinGraphics.y = Math.sin(LK.ticks * 0.1 + self.x * 0.01) * 10;
coinGraphics.rotation += 0.05;
};
return self;
});
var Column = Container.expand(function () {
var self = Container.call(this);
self.gapSize = 300;
self.speed = 4;
self.scored = false;
self.init = function (gapY) {
// Top column
var topColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 1.0
});
topColumn.y = gapY - self.gapSize / 2;
topColumn.tint = 0x4682B4; // Steel blue for sky pillars
// Bottom column
var bottomColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 0.0
});
bottomColumn.y = gapY + self.gapSize / 2;
bottomColumn.tint = 0x4682B4; // Steel blue for sky pillars
self.topColumn = topColumn;
self.bottomColumn = bottomColumn;
};
self.initSolid = function () {
// Create a solid column that spans the entire height
var solidColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 0.5
});
solidColumn.y = 2732 / 2; // Center vertically
solidColumn.height = 2732; // Full screen height
solidColumn.tint = 0x4682B4; // Steel blue for sky pillars
self.topColumn = solidColumn;
self.bottomColumn = null; // No bottom column for solid
};
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Diamond = Container.expand(function () {
var self = Container.call(this);
var diamondGraphics = self.attachAsset('diamond', {
anchorX: 0.5,
anchorY: 0.5
});
diamondGraphics.tint = 0x00FFFF; // Cyan diamond color
self.speed = 4;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Sparkle animation
diamondGraphics.rotation += 0.1;
diamondGraphics.scaleX = 1.0 + Math.sin(LK.ticks * 0.15) * 0.2;
diamondGraphics.scaleY = 1.0 + Math.sin(LK.ticks * 0.15) * 0.2;
};
return self;
});
var Eagle = Container.expand(function () {
var self = Container.call(this);
var eagleGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
eagleGraphics.tint = 0x8B4513; // Brown color for eagle
eagleGraphics.scaleX = -1.2; // Negative scale to flip horizontally (face left)
eagleGraphics.scaleY = 1.2;
self.speed = 6;
self.update = function () {
self.x -= self.speed;
// Track bird position and move towards it
if (bird && bird.health > 0) {
var dx = bird.x - self.x;
var dy = bird.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards bird
var moveSpeed = 2;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
}
// Simple wing flapping animation
eagleGraphics.rotation = Math.sin(LK.ticks * 0.3) * 0.1;
};
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
monsterGraphics.tint = 0x8B0000; // Dark red color for monster
monsterGraphics.scaleX = -2.0; // Negative scale to flip horizontally (face left), bigger than eagle
monsterGraphics.scaleY = 2.0;
self.speed = 5;
self.health = 3; // Takes 3 bullets to kill
self.maxHealth = 3;
// Create small health bar above monster
var healthBarBg = self.attachAsset('column', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.tint = 0x333333;
healthBarBg.x = 0;
healthBarBg.y = -60;
var healthBarFill = self.attachAsset('column', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.tint = 0x00FF00;
healthBarFill.x = 0;
healthBarFill.y = -60;
self.healthBarFill = healthBarFill;
self.update = function () {
self.x -= self.speed;
// Track bird position and move towards it more aggressively
if (bird && bird.health > 0) {
var dx = bird.x - self.x;
var dy = bird.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards bird faster than eagles
var moveSpeed = 3;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
}
// Menacing animation with health-based tint
var healthRatio = self.health / self.maxHealth;
monsterGraphics.tint = healthRatio > 0.66 ? 0x8B0000 : healthRatio > 0.33 ? 0xFF4500 : 0xFF0000;
monsterGraphics.rotation = Math.sin(LK.ticks * 0.4) * 0.2;
};
self.takeDamage = function () {
self.health--;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
self.healthBarFill.width = 60 * healthPercent;
if (healthPercent > 0.66) {
self.healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.33) {
self.healthBarFill.tint = 0xFFFF00; // Yellow
} else {
self.healthBarFill.tint = 0xFF0000; // Red
}
tween(self, {
scaleX: -2.2,
scaleY: 2.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: -2.0,
scaleY: 2.0
}, {
duration: 100
});
}
});
return self.health <= 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue color
});
/****
* Game Code
****/
var bird = new Bird();
bird.x = 400;
bird.y = 2732 / 2;
game.addChild(bird);
var columns = [];
var coins = [];
var diamonds = [];
var eagles = [];
var monsters = [];
var bullets = [];
var columnSpawnTimer = 0;
var columnSpawnInterval = 90; // 1.5 seconds at 60fps
var eagleSpawnTimer = 0;
var eagleSpawnInterval = 180; // 3 seconds at 60fps
var monsterSpawnTimer = 0;
var monsterSpawnInterval = 300; // 5 seconds at 60fps
var gameSpeed = 4;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var healthBarBg = LK.getAsset('column', {
width: 400,
height: 30,
anchorX: 1,
anchorY: 0
});
healthBarBg.tint = 0x333333;
healthBarBg.x = -20;
healthBarBg.y = 50;
LK.gui.topRight.addChild(healthBarBg);
var healthBarFill = LK.getAsset('column', {
width: 400,
height: 30,
anchorX: 0,
anchorY: 0
});
healthBarFill.tint = 0x00FF00;
healthBarFill.x = -420;
healthBarFill.y = 50;
LK.gui.topRight.addChild(healthBarFill);
// Touch controls
game.down = function (x, y, obj) {
if (obj.event && obj.event.button === 2) {
// Right click - shoot
bird.shoot();
} else {
// Left click or touch - flap
bird.flap();
}
};
game.update = function () {
// Cloudless sky - no particles needed
if (bird.health <= 0) {
LK.showGameOver();
return;
}
// Spawn columns
columnSpawnTimer++;
if (columnSpawnTimer >= columnSpawnInterval) {
columnSpawnTimer = 0;
var gapY = 400 + Math.random() * (2732 - 800); // Random gap position
var hasCollectible = false;
// Check if we should spawn a coin (always spawn)
var newCoin = new Coin();
newCoin.x = 2048 + 60;
newCoin.y = gapY;
newCoin.speed = gameSpeed;
coins.push(newCoin);
game.addChild(newCoin);
hasCollectible = true;
// Check if we should spawn a diamond (20% chance)
if (Math.random() < 0.2) {
var newDiamond = new Diamond();
newDiamond.x = 2048 + 60;
newDiamond.y = gapY + (Math.random() - 0.5) * 100; // Slight vertical offset
newDiamond.speed = gameSpeed;
diamonds.push(newDiamond);
game.addChild(newDiamond);
hasCollectible = true;
}
// Only create gap in column if there are collectibles
var newColumn = new Column();
newColumn.x = 2048 + 60;
if (hasCollectible) {
newColumn.init(gapY); // Create column with gap
} else {
newColumn.initSolid(); // Create solid column without gap
}
newColumn.speed = gameSpeed;
columns.push(newColumn);
game.addChild(newColumn);
}
// Spawn eagles
eagleSpawnTimer++;
if (eagleSpawnTimer >= eagleSpawnInterval) {
eagleSpawnTimer = 0;
var newEagle = new Eagle();
newEagle.x = 2048 + 100;
newEagle.y = 300 + Math.random() * (2732 - 600); // Random height position
newEagle.speed = gameSpeed + 2; // Eagles fly faster than columns
eagles.push(newEagle);
game.addChild(newEagle);
}
// Spawn monsters after score 150
if (LK.getScore() >= 150) {
monsterSpawnTimer++;
if (monsterSpawnTimer >= monsterSpawnInterval) {
monsterSpawnTimer = 0;
var newMonster = new Monster();
newMonster.x = 2048 + 150;
newMonster.y = 400 + Math.random() * (2732 - 800); // Random height position
newMonster.speed = gameSpeed + 1; // Monsters fly slightly faster than columns
monsters.push(newMonster);
game.addChild(newMonster);
}
}
// Update and check columns
for (var i = columns.length - 1; i >= 0; i--) {
var column = columns[i];
// Remove off-screen columns
if (column.x < -100) {
column.destroy();
columns.splice(i, 1);
continue;
}
// Check for scoring
if (!column.scored && column.x < bird.x) {
column.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('score').play();
}
// Collision detection with bird - only when hitting solid column parts
if (!bird.invulnerable && bird.health > 0) {
var birdBounds = {
left: bird.x - 30,
right: bird.x + 30,
top: bird.y - 30,
bottom: bird.y + 30
};
// Check if bird is horizontally overlapping with column
var columnBounds = {
left: column.x - 60,
right: column.x + 60
};
if (birdBounds.right > columnBounds.left && birdBounds.left < columnBounds.right) {
var hittingColumn = false;
// Check for solid column (no gap)
if (!column.bottomColumn) {
// This is a solid column, bird hits it anywhere
hittingColumn = true;
} else {
// This is a gapped column, check top and bottom parts
var columnGapBounds = {
topBottom: column.topColumn.y,
bottomTop: column.bottomColumn.y
};
// Check if bird is hitting the solid top column (above the gap)
var hittingTopColumn = birdBounds.top <= columnGapBounds.topBottom;
// Check if bird is hitting the solid bottom column (below the gap)
var hittingBottomColumn = birdBounds.bottom >= columnGapBounds.bottomTop;
hittingColumn = hittingTopColumn || hittingBottomColumn;
}
if (hittingColumn) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
}
}
// Update and check coins
for (var k = coins.length - 1; k >= 0; k--) {
var coin = coins[k];
// Remove off-screen coins
if (coin.x < -100) {
coin.destroy();
coins.splice(k, 1);
continue;
}
// Check coin collection
if (!coin.collected && bird.intersects(coin)) {
coin.collected = true;
LK.setScore(LK.getScore() + 2); // Coins give 2 points
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('coin').play();
coin.destroy();
coins.splice(k, 1);
}
}
// Update and check diamonds
for (var d = diamonds.length - 1; d >= 0; d--) {
var diamond = diamonds[d];
// Remove off-screen diamonds
if (diamond.x < -100) {
diamond.destroy();
diamonds.splice(d, 1);
continue;
}
// Check diamond collection
if (!diamond.collected && bird.intersects(diamond)) {
diamond.collected = true;
LK.setScore(LK.getScore() + 10); // Diamonds give 10 points
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('coin').play(); // Use coin sound for now
diamond.destroy();
diamonds.splice(d, 1);
}
}
// Update and check eagles
for (var m = eagles.length - 1; m >= 0; m--) {
var eagle = eagles[m];
// Remove off-screen eagles
if (eagle.x < -150) {
eagle.destroy();
eagles.splice(m, 1);
continue;
}
// Check eagle collision with bird
if (!bird.invulnerable && bird.health > 0 && bird.intersects(eagle)) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
// Update and check monsters
for (var mo = monsters.length - 1; mo >= 0; mo--) {
var monster = monsters[mo];
// Remove off-screen monsters
if (monster.x < -200) {
monster.destroy();
monsters.splice(mo, 1);
continue;
}
// Check monster collision with bird
if (!bird.invulnerable && bird.health > 0 && bird.intersects(monster)) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
// Update and check bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
// Remove off-screen bullets
if (bullet.x > 2200) {
bullet.destroy();
bullets.splice(b, 1);
continue;
}
// Check bullet collision with eagles
for (var e = eagles.length - 1; e >= 0; e--) {
var eagle = eagles[e];
if (bullet.intersects(eagle)) {
// Eagle hit by bullet
tween(eagle, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
onFinish: function onFinish() {
eagle.destroy();
}
});
eagles.splice(e, 1);
bullet.destroy();
bullets.splice(b, 1);
LK.setScore(LK.getScore() + 5); // 5 points for killing eagle
scoreTxt.setText('Score: ' + LK.getScore());
break;
}
}
// Check bullet collision with monsters
for (var mo = monsters.length - 1; mo >= 0; mo--) {
var monster = monsters[mo];
if (bullet.intersects(monster)) {
// Monster hit by bullet
bullet.destroy();
bullets.splice(b, 1);
if (monster.takeDamage()) {
// Monster destroyed after taking enough damage
tween(monster, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
onFinish: function onFinish() {
monster.destroy();
}
});
monsters.splice(mo, 1);
LK.setScore(LK.getScore() + 15); // 15 points for killing monster
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
}
// Check for finish line at score 400
if (LK.getScore() >= 400) {
LK.showYouWin();
return;
}
// Increase difficulty over time
if (LK.getScore() > 0 && LK.getScore() % 10 == 0) {
if (gameSpeed < 8) {
gameSpeed = 4 + LK.getScore() / 10 * 0.5;
for (var j = 0; j < columns.length; j++) {
columns[j].speed = gameSpeed;
}
for (var l = 0; l < coins.length; l++) {
coins[l].speed = gameSpeed;
}
for (var p = 0; p < diamonds.length; p++) {
diamonds[p].speed = gameSpeed;
}
for (var n = 0; n < eagles.length; n++) {
eagles[n].speed = gameSpeed + 2;
}
for (var mo = 0; mo < monsters.length; mo++) {
monsters[mo].speed = gameSpeed + 1;
}
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0,
anchorY: 0.5
});
weaponGraphics.x = 35;
weaponGraphics.y = 5;
self.velocity = 0;
self.gravity = 0.8;
self.flapStrength = -15;
self.health = 500;
self.maxHealth = 500;
self.invulnerable = false;
self.invulnerableTime = 0;
self.lastShotTime = 0;
self.flap = function () {
if (self.health > 0) {
self.velocity = self.flapStrength;
LK.getSound('flap').play();
}
};
self.update = function () {
if (self.health > 0) {
self.velocity += self.gravity;
self.y += self.velocity;
// Rotate bird based on velocity
birdGraphics.rotation = Math.max(-0.5, Math.min(0.5, self.velocity * 0.05));
// Handle invulnerability
if (self.invulnerable) {
self.invulnerableTime--;
birdGraphics.alpha = self.invulnerableTime % 10 < 5 ? 0.5 : 1.0;
if (self.invulnerableTime <= 0) {
self.invulnerable = false;
birdGraphics.alpha = 1.0;
}
}
// Auto-shoot at eagles when they get close
for (var i = 0; i < eagles.length; i++) {
var eagle = eagles[i];
var distance = Math.sqrt(Math.pow(eagle.x - self.x, 2) + Math.pow(eagle.y - self.y, 2));
// If eagle is within 400 pixels and in front of bird, shoot
if (distance < 400 && eagle.x > self.x) {
// Check if we haven't shot recently (every 30 frames = 0.5 seconds)
if (!self.lastShotTime || LK.ticks - self.lastShotTime > 30) {
self.shoot();
self.lastShotTime = LK.ticks;
break; // Only shoot at one eagle per frame
}
}
}
// Auto-shoot at monsters when they get close
for (var j = 0; j < monsters.length; j++) {
var monster = monsters[j];
var distance = Math.sqrt(Math.pow(monster.x - self.x, 2) + Math.pow(monster.y - self.y, 2));
// If monster is within 500 pixels and in front of bird, shoot
if (distance < 500 && monster.x > self.x) {
// Check if we haven't shot recently (every 25 frames = slightly faster than eagles)
if (!self.lastShotTime || LK.ticks - self.lastShotTime > 25) {
self.shoot();
self.lastShotTime = LK.ticks;
break; // Only shoot at one monster per frame
}
}
}
// Keep bird on screen vertically
if (self.y < 30) {
self.y = 30;
self.velocity = 0;
}
if (self.y > 2732 - 30) {
self.y = 2732 - 30;
self.velocity = 0;
}
}
};
self.shoot = function () {
if (self.health > 0) {
var newBullet = new Bullet();
newBullet.x = self.x + 40;
newBullet.y = self.y;
bullets.push(newBullet);
game.addChild(newBullet);
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
if (!self.invulnerable && self.health > 0) {
self.health -= 25; // Reduce health by 25 points
if (self.health > 0) {
self.invulnerable = true;
self.invulnerableTime = 120; // 2 seconds at 60fps
LK.effects.flashObject(self, 0xFF0000, 500);
}
LK.getSound('hit').play();
return true;
}
return false;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.scaleX = 0.5;
bulletGraphics.scaleY = 0.5;
bulletGraphics.tint = 0xFFFF00;
self.speed = 12;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinGraphics.tint = 0xFFD700; // Bright golden coins in sky
self.speed = 4;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Simple floating animation
coinGraphics.y = Math.sin(LK.ticks * 0.1 + self.x * 0.01) * 10;
coinGraphics.rotation += 0.05;
};
return self;
});
var Column = Container.expand(function () {
var self = Container.call(this);
self.gapSize = 300;
self.speed = 4;
self.scored = false;
self.init = function (gapY) {
// Top column
var topColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 1.0
});
topColumn.y = gapY - self.gapSize / 2;
topColumn.tint = 0x4682B4; // Steel blue for sky pillars
// Bottom column
var bottomColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 0.0
});
bottomColumn.y = gapY + self.gapSize / 2;
bottomColumn.tint = 0x4682B4; // Steel blue for sky pillars
self.topColumn = topColumn;
self.bottomColumn = bottomColumn;
};
self.initSolid = function () {
// Create a solid column that spans the entire height
var solidColumn = self.attachAsset('column', {
anchorX: 0.5,
anchorY: 0.5
});
solidColumn.y = 2732 / 2; // Center vertically
solidColumn.height = 2732; // Full screen height
solidColumn.tint = 0x4682B4; // Steel blue for sky pillars
self.topColumn = solidColumn;
self.bottomColumn = null; // No bottom column for solid
};
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Diamond = Container.expand(function () {
var self = Container.call(this);
var diamondGraphics = self.attachAsset('diamond', {
anchorX: 0.5,
anchorY: 0.5
});
diamondGraphics.tint = 0x00FFFF; // Cyan diamond color
self.speed = 4;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Sparkle animation
diamondGraphics.rotation += 0.1;
diamondGraphics.scaleX = 1.0 + Math.sin(LK.ticks * 0.15) * 0.2;
diamondGraphics.scaleY = 1.0 + Math.sin(LK.ticks * 0.15) * 0.2;
};
return self;
});
var Eagle = Container.expand(function () {
var self = Container.call(this);
var eagleGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
eagleGraphics.tint = 0x8B4513; // Brown color for eagle
eagleGraphics.scaleX = -1.2; // Negative scale to flip horizontally (face left)
eagleGraphics.scaleY = 1.2;
self.speed = 6;
self.update = function () {
self.x -= self.speed;
// Track bird position and move towards it
if (bird && bird.health > 0) {
var dx = bird.x - self.x;
var dy = bird.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards bird
var moveSpeed = 2;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
}
// Simple wing flapping animation
eagleGraphics.rotation = Math.sin(LK.ticks * 0.3) * 0.1;
};
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
monsterGraphics.tint = 0x8B0000; // Dark red color for monster
monsterGraphics.scaleX = -2.0; // Negative scale to flip horizontally (face left), bigger than eagle
monsterGraphics.scaleY = 2.0;
self.speed = 5;
self.health = 3; // Takes 3 bullets to kill
self.maxHealth = 3;
// Create small health bar above monster
var healthBarBg = self.attachAsset('column', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.tint = 0x333333;
healthBarBg.x = 0;
healthBarBg.y = -60;
var healthBarFill = self.attachAsset('column', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.tint = 0x00FF00;
healthBarFill.x = 0;
healthBarFill.y = -60;
self.healthBarFill = healthBarFill;
self.update = function () {
self.x -= self.speed;
// Track bird position and move towards it more aggressively
if (bird && bird.health > 0) {
var dx = bird.x - self.x;
var dy = bird.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards bird faster than eagles
var moveSpeed = 3;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
}
// Menacing animation with health-based tint
var healthRatio = self.health / self.maxHealth;
monsterGraphics.tint = healthRatio > 0.66 ? 0x8B0000 : healthRatio > 0.33 ? 0xFF4500 : 0xFF0000;
monsterGraphics.rotation = Math.sin(LK.ticks * 0.4) * 0.2;
};
self.takeDamage = function () {
self.health--;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
self.healthBarFill.width = 60 * healthPercent;
if (healthPercent > 0.66) {
self.healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.33) {
self.healthBarFill.tint = 0xFFFF00; // Yellow
} else {
self.healthBarFill.tint = 0xFF0000; // Red
}
tween(self, {
scaleX: -2.2,
scaleY: 2.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: -2.0,
scaleY: 2.0
}, {
duration: 100
});
}
});
return self.health <= 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue color
});
/****
* Game Code
****/
var bird = new Bird();
bird.x = 400;
bird.y = 2732 / 2;
game.addChild(bird);
var columns = [];
var coins = [];
var diamonds = [];
var eagles = [];
var monsters = [];
var bullets = [];
var columnSpawnTimer = 0;
var columnSpawnInterval = 90; // 1.5 seconds at 60fps
var eagleSpawnTimer = 0;
var eagleSpawnInterval = 180; // 3 seconds at 60fps
var monsterSpawnTimer = 0;
var monsterSpawnInterval = 300; // 5 seconds at 60fps
var gameSpeed = 4;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var healthBarBg = LK.getAsset('column', {
width: 400,
height: 30,
anchorX: 1,
anchorY: 0
});
healthBarBg.tint = 0x333333;
healthBarBg.x = -20;
healthBarBg.y = 50;
LK.gui.topRight.addChild(healthBarBg);
var healthBarFill = LK.getAsset('column', {
width: 400,
height: 30,
anchorX: 0,
anchorY: 0
});
healthBarFill.tint = 0x00FF00;
healthBarFill.x = -420;
healthBarFill.y = 50;
LK.gui.topRight.addChild(healthBarFill);
// Touch controls
game.down = function (x, y, obj) {
if (obj.event && obj.event.button === 2) {
// Right click - shoot
bird.shoot();
} else {
// Left click or touch - flap
bird.flap();
}
};
game.update = function () {
// Cloudless sky - no particles needed
if (bird.health <= 0) {
LK.showGameOver();
return;
}
// Spawn columns
columnSpawnTimer++;
if (columnSpawnTimer >= columnSpawnInterval) {
columnSpawnTimer = 0;
var gapY = 400 + Math.random() * (2732 - 800); // Random gap position
var hasCollectible = false;
// Check if we should spawn a coin (always spawn)
var newCoin = new Coin();
newCoin.x = 2048 + 60;
newCoin.y = gapY;
newCoin.speed = gameSpeed;
coins.push(newCoin);
game.addChild(newCoin);
hasCollectible = true;
// Check if we should spawn a diamond (20% chance)
if (Math.random() < 0.2) {
var newDiamond = new Diamond();
newDiamond.x = 2048 + 60;
newDiamond.y = gapY + (Math.random() - 0.5) * 100; // Slight vertical offset
newDiamond.speed = gameSpeed;
diamonds.push(newDiamond);
game.addChild(newDiamond);
hasCollectible = true;
}
// Only create gap in column if there are collectibles
var newColumn = new Column();
newColumn.x = 2048 + 60;
if (hasCollectible) {
newColumn.init(gapY); // Create column with gap
} else {
newColumn.initSolid(); // Create solid column without gap
}
newColumn.speed = gameSpeed;
columns.push(newColumn);
game.addChild(newColumn);
}
// Spawn eagles
eagleSpawnTimer++;
if (eagleSpawnTimer >= eagleSpawnInterval) {
eagleSpawnTimer = 0;
var newEagle = new Eagle();
newEagle.x = 2048 + 100;
newEagle.y = 300 + Math.random() * (2732 - 600); // Random height position
newEagle.speed = gameSpeed + 2; // Eagles fly faster than columns
eagles.push(newEagle);
game.addChild(newEagle);
}
// Spawn monsters after score 150
if (LK.getScore() >= 150) {
monsterSpawnTimer++;
if (monsterSpawnTimer >= monsterSpawnInterval) {
monsterSpawnTimer = 0;
var newMonster = new Monster();
newMonster.x = 2048 + 150;
newMonster.y = 400 + Math.random() * (2732 - 800); // Random height position
newMonster.speed = gameSpeed + 1; // Monsters fly slightly faster than columns
monsters.push(newMonster);
game.addChild(newMonster);
}
}
// Update and check columns
for (var i = columns.length - 1; i >= 0; i--) {
var column = columns[i];
// Remove off-screen columns
if (column.x < -100) {
column.destroy();
columns.splice(i, 1);
continue;
}
// Check for scoring
if (!column.scored && column.x < bird.x) {
column.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('score').play();
}
// Collision detection with bird - only when hitting solid column parts
if (!bird.invulnerable && bird.health > 0) {
var birdBounds = {
left: bird.x - 30,
right: bird.x + 30,
top: bird.y - 30,
bottom: bird.y + 30
};
// Check if bird is horizontally overlapping with column
var columnBounds = {
left: column.x - 60,
right: column.x + 60
};
if (birdBounds.right > columnBounds.left && birdBounds.left < columnBounds.right) {
var hittingColumn = false;
// Check for solid column (no gap)
if (!column.bottomColumn) {
// This is a solid column, bird hits it anywhere
hittingColumn = true;
} else {
// This is a gapped column, check top and bottom parts
var columnGapBounds = {
topBottom: column.topColumn.y,
bottomTop: column.bottomColumn.y
};
// Check if bird is hitting the solid top column (above the gap)
var hittingTopColumn = birdBounds.top <= columnGapBounds.topBottom;
// Check if bird is hitting the solid bottom column (below the gap)
var hittingBottomColumn = birdBounds.bottom >= columnGapBounds.bottomTop;
hittingColumn = hittingTopColumn || hittingBottomColumn;
}
if (hittingColumn) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
}
}
// Update and check coins
for (var k = coins.length - 1; k >= 0; k--) {
var coin = coins[k];
// Remove off-screen coins
if (coin.x < -100) {
coin.destroy();
coins.splice(k, 1);
continue;
}
// Check coin collection
if (!coin.collected && bird.intersects(coin)) {
coin.collected = true;
LK.setScore(LK.getScore() + 2); // Coins give 2 points
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('coin').play();
coin.destroy();
coins.splice(k, 1);
}
}
// Update and check diamonds
for (var d = diamonds.length - 1; d >= 0; d--) {
var diamond = diamonds[d];
// Remove off-screen diamonds
if (diamond.x < -100) {
diamond.destroy();
diamonds.splice(d, 1);
continue;
}
// Check diamond collection
if (!diamond.collected && bird.intersects(diamond)) {
diamond.collected = true;
LK.setScore(LK.getScore() + 10); // Diamonds give 10 points
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('coin').play(); // Use coin sound for now
diamond.destroy();
diamonds.splice(d, 1);
}
}
// Update and check eagles
for (var m = eagles.length - 1; m >= 0; m--) {
var eagle = eagles[m];
// Remove off-screen eagles
if (eagle.x < -150) {
eagle.destroy();
eagles.splice(m, 1);
continue;
}
// Check eagle collision with bird
if (!bird.invulnerable && bird.health > 0 && bird.intersects(eagle)) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
// Update and check monsters
for (var mo = monsters.length - 1; mo >= 0; mo--) {
var monster = monsters[mo];
// Remove off-screen monsters
if (monster.x < -200) {
monster.destroy();
monsters.splice(mo, 1);
continue;
}
// Check monster collision with bird
if (!bird.invulnerable && bird.health > 0 && bird.intersects(monster)) {
if (bird.takeDamage()) {
var healthPercent = Math.max(0, bird.health / bird.maxHealth);
healthBarFill.width = 400 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
}
}
}
// Update and check bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
// Remove off-screen bullets
if (bullet.x > 2200) {
bullet.destroy();
bullets.splice(b, 1);
continue;
}
// Check bullet collision with eagles
for (var e = eagles.length - 1; e >= 0; e--) {
var eagle = eagles[e];
if (bullet.intersects(eagle)) {
// Eagle hit by bullet
tween(eagle, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
onFinish: function onFinish() {
eagle.destroy();
}
});
eagles.splice(e, 1);
bullet.destroy();
bullets.splice(b, 1);
LK.setScore(LK.getScore() + 5); // 5 points for killing eagle
scoreTxt.setText('Score: ' + LK.getScore());
break;
}
}
// Check bullet collision with monsters
for (var mo = monsters.length - 1; mo >= 0; mo--) {
var monster = monsters[mo];
if (bullet.intersects(monster)) {
// Monster hit by bullet
bullet.destroy();
bullets.splice(b, 1);
if (monster.takeDamage()) {
// Monster destroyed after taking enough damage
tween(monster, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
onFinish: function onFinish() {
monster.destroy();
}
});
monsters.splice(mo, 1);
LK.setScore(LK.getScore() + 15); // 15 points for killing monster
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
}
// Check for finish line at score 400
if (LK.getScore() >= 400) {
LK.showYouWin();
return;
}
// Increase difficulty over time
if (LK.getScore() > 0 && LK.getScore() % 10 == 0) {
if (gameSpeed < 8) {
gameSpeed = 4 + LK.getScore() / 10 * 0.5;
for (var j = 0; j < columns.length; j++) {
columns[j].speed = gameSpeed;
}
for (var l = 0; l < coins.length; l++) {
coins[l].speed = gameSpeed;
}
for (var p = 0; p < diamonds.length; p++) {
diamonds[p].speed = gameSpeed;
}
for (var n = 0; n < eagles.length; n++) {
eagles[n].speed = gameSpeed + 2;
}
for (var mo = 0; mo < monsters.length; mo++) {
monsters[mo].speed = gameSpeed + 1;
}
}
}
};