/**** * 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;
}
}
}
};