/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BossShip = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('bossShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1; self.moveDirection = 1; self.shootTimer = 0; self.maxHealth = 50; self.health = self.maxHealth; self.shootPattern = 0; self.patternTimer = 0; // Create boss health bar background var healthBarBg = self.attachAsset('bossHealthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -140; // Create boss health bar fill var healthBarFill = self.attachAsset('bossHealthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -140; self.healthBarFill = healthBarFill; // Method to update health bar self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; self.healthBarFill.scaleX = healthPercent; if (healthPercent > 0.6) { self.healthBarFill.tint = 0xff0000; // Red } else if (healthPercent > 0.3) { self.healthBarFill.tint = 0xff6600; // Orange } else { self.healthBarFill.tint = 0xffff00; // Yellow } }; self.update = function () { self.y += self.speed; // Move side to side self.x += self.moveDirection * 2; if (self.x <= 100 || self.x >= 1948) { self.moveDirection *= -1; } // Handle shooting patterns self.shootTimer--; self.patternTimer++; if (self.patternTimer % 300 === 0) { self.shootPattern = (self.shootPattern + 1) % 3; } if (self.shootTimer <= 0) { self.shootTimer = 30; // Only shoot if not about to hit edges if (self.x > 150 && self.x < 1898) { self.shouldShoot = true; } } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; // Play shoot sound when enemy bullet is created LK.getSound('shoot').play(); self.update = function () { self.y += self.speed; }; return self; }); var EnemyShip = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.movePattern = Math.random() < 0.5 ? 'straight' : 'zigzag'; self.zigzagTimer = 0; self.zigzagDirection = Math.random() < 0.5 ? -1 : 1; self.shootTimer = Math.random() * 60 + 60; // Random initial shoot delay self.maxHealth = 3; self.health = self.maxHealth; // Create health bar background var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -50; // Create health bar fill var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -50; self.healthBarFill = healthBarFill; // Method to update health bar self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; self.healthBarFill.scaleX = healthPercent; if (healthPercent > 0.6) { self.healthBarFill.tint = 0x00ff00; // Green } else if (healthPercent > 0.3) { self.healthBarFill.tint = 0xffff00; // Yellow } else { self.healthBarFill.tint = 0xff0000; // Red } }; self.update = function () { self.y += self.speed; if (self.movePattern === 'zigzag') { self.zigzagTimer += 1; if (self.zigzagTimer % 60 === 0) { self.zigzagDirection *= -1; } self.x += self.zigzagDirection * 2; } // Keep enemy within screen bounds if (self.x < 50) self.x = 50; if (self.x > 1998) self.x = 1998; // Handle shooting self.shootTimer--; if (self.shootTimer <= 0) { self.shootTimer = Math.random() * 120 + 90; // Slower random shoot interval self.shouldShoot = true; } }; return self; }); var GunPowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('gunPowerUp', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.update = function () { self.y += self.speed; }; return self; }); var HealthPack = Container.expand(function () { var self = Container.call(this); var healthPackGraphics = self.attachAsset('healthPack', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.update = function () { self.y += self.speed; }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.angle = 0; // Angle in radians for bullet direction // Play shoot sound when bullet is created LK.getSound('shoot').play(); self.update = function () { self.y += self.speed * Math.cos(self.angle); self.x += self.speed * Math.sin(self.angle); }; return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 10; self.health = self.maxHealth; // Create health bar background var healthBarBg = self.attachAsset('playerHealthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -80; // Create health bar fill var healthBarFill = self.attachAsset('playerHealthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -80; self.healthBarFill = healthBarFill; // Method to update health bar self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; self.healthBarFill.scaleX = healthPercent; if (healthPercent > 0.6) { self.healthBarFill.tint = 0x00ff00; // Green } else if (healthPercent > 0.3) { self.healthBarFill.tint = 0xffff00; // Yellow } else { self.healthBarFill.tint = 0xff0000; // Red } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000011 }); /**** * Game Code ****/ // Game variables var playerShip; var playerBullets = []; var enemyBullets = []; var enemyShips = []; var bossShips = []; var difficultyLevel = 1; var enemySpawnRate = 120; // frames between spawns var bulletFireRate = 15; // frames between shots var dragNode = null; var lastBossScore = 0; var gunPowerUps = []; var gunPowerUpTimer = 0; var healthPacks = []; var healthPackTimer = 0; var playerFireRate = bulletFireRate; // Track player's current fire rate var hasTripleShot = false; // Track if player has triple shot upgrade var gunPowerUpEndTime = 0; // Track when gun power-up should end var isBossPresent = false; // Track if boss is currently on screen // UI Elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Initialize player ship playerShip = game.addChild(new PlayerShip()); playerShip.x = 1024; // Center horizontally playerShip.y = 2400; // Near bottom of screen // Update score display function updateScore() { scoreTxt.setText('Score: ' + LK.getScore()); } // Handle movement function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; // Keep player within screen bounds if (dragNode.x < 40) dragNode.x = 40; if (dragNode.x > 2008) dragNode.x = 2008; if (dragNode.y < 200) dragNode.y = 200; if (dragNode.y > 2600) dragNode.y = 2600; } } // Event handlers game.move = handleMove; game.down = function (x, y, obj) { dragNode = playerShip; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; }; // Main game update loop game.update = function () { // Fire player bullets if (LK.ticks % playerFireRate === 0) { if (hasTripleShot) { // Fire three bullets in different directions var angles = [-0.3, 0, 0.3]; // Left, center, right angles in radians for (var bulletIndex = 0; bulletIndex < 3; bulletIndex++) { var newBullet = new PlayerBullet(); newBullet.x = playerShip.x; newBullet.y = playerShip.y - 60; newBullet.angle = angles[bulletIndex]; newBullet.lastY = newBullet.y; playerBullets.push(newBullet); game.addChild(newBullet); } } else { // Fire single bullet var newBullet = new PlayerBullet(); newBullet.x = playerShip.x; newBullet.y = playerShip.y - 60; newBullet.lastY = newBullet.y; playerBullets.push(newBullet); game.addChild(newBullet); } } // Spawn gun power-up every 13 seconds (780 frames) gunPowerUpTimer++; if (gunPowerUpTimer >= 780) { var newGunPowerUp = new GunPowerUp(); newGunPowerUp.x = Math.random() * 1800 + 124; // Random x position within bounds newGunPowerUp.y = -50; newGunPowerUp.lastY = newGunPowerUp.y; newGunPowerUp.lastIntersecting = false; gunPowerUps.push(newGunPowerUp); game.addChild(newGunPowerUp); gunPowerUpTimer = 0; } // Spawn health pack every 30 seconds (1800 frames) healthPackTimer++; if (healthPackTimer >= 1800) { var newHealthPack = new HealthPack(); newHealthPack.x = Math.random() * 1800 + 124; // Random x position within bounds newHealthPack.y = -50; newHealthPack.lastY = newHealthPack.y; newHealthPack.lastIntersecting = false; healthPacks.push(newHealthPack); game.addChild(newHealthPack); healthPackTimer = 0; } // Spawn boss every 1000 points var currentScore = LK.getScore(); if (Math.floor(currentScore / 1000) > Math.floor(lastBossScore / 1000) && bossShips.length === 0) { var newBoss = new BossShip(); newBoss.x = 1024; // Center horizontally newBoss.y = -125; newBoss.lastY = newBoss.y; newBoss.lastIntersecting = false; bossShips.push(newBoss); game.addChild(newBoss); lastBossScore = currentScore; isBossPresent = true; } // Spawn enemies (only when no boss is present) if (!isBossPresent && LK.ticks % enemySpawnRate === 0) { var newEnemy = new EnemyShip(); newEnemy.x = Math.random() * 1800 + 124; // Random x position within bounds newEnemy.y = -50; newEnemy.lastY = newEnemy.y; newEnemy.lastIntersecting = false; enemyShips.push(newEnemy); game.addChild(newEnemy); } // Update and check player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; // Remove bullets that go off screen if (bullet.lastY >= -25 && bullet.y < -25) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check bullet-enemy collisions var bulletHit = false; for (var j = enemyShips.length - 1; j >= 0; j--) { var enemy = enemyShips[j]; if (bullet.intersects(enemy)) { // Damage enemy enemy.health--; enemy.updateHealthBar(); LK.setScore(LK.getScore() + 5); updateScore(); // Flash effect on enemy LK.effects.flashObject(enemy, 0xffffff, 200); bullet.destroy(); playerBullets.splice(i, 1); bulletHit = true; // Check if enemy is destroyed if (enemy.health <= 0) { LK.setScore(LK.getScore() + 5); // Bonus points for destroying enemy updateScore(); LK.getSound('enemyDestroy').play(); enemy.destroy(); enemyShips.splice(j, 1); } break; } } // Check bullet-boss collisions if (!bulletHit) { for (var b = bossShips.length - 1; b >= 0; b--) { var boss = bossShips[b]; if (bullet.intersects(boss)) { // Damage boss boss.health--; boss.updateHealthBar(); // Flash effect on boss LK.effects.flashObject(boss, 0xffffff, 200); bullet.destroy(); playerBullets.splice(i, 1); bulletHit = true; // Check if boss is destroyed if (boss.health <= 0) { LK.setScore(LK.getScore() + 500); // Big bonus for destroying boss updateScore(); LK.getSound('enemyDestroy').play(); boss.destroy(); bossShips.splice(b, 1); isBossPresent = false; // Allow enemies to spawn again } break; } } } if (!bulletHit) { bullet.lastY = bullet.y; } } // Update and check enemies for (var k = enemyShips.length - 1; k >= 0; k--) { var enemy = enemyShips[k]; // Create enemy bullet if enemy should shoot if (enemy.shouldShoot) { var newEnemyBullet = new EnemyBullet(); newEnemyBullet.x = enemy.x; newEnemyBullet.y = enemy.y + 40; newEnemyBullet.lastY = newEnemyBullet.y; newEnemyBullet.lastIntersecting = false; enemyBullets.push(newEnemyBullet); game.addChild(newEnemyBullet); enemy.shouldShoot = false; } // Check if enemy reached bottom edge - instant kill player if (enemy.lastY <= 2780 && enemy.y > 2780) { // Enemy reached bottom - instant kill player playerShip.health = 0; playerShip.updateHealthBar(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Check player-enemy collision var currentIntersecting = enemy.intersects(playerShip); if (!enemy.lastIntersecting && currentIntersecting) { // Damage player playerShip.health--; playerShip.updateHealthBar(); // Flash effect on player LK.effects.flashObject(playerShip, 0xff0000, 300); // Destroy enemy enemy.destroy(); enemyShips.splice(k, 1); continue; } enemy.lastY = enemy.y; enemy.lastIntersecting = currentIntersecting; } // Update and check bosses for (var n = bossShips.length - 1; n >= 0; n--) { var boss = bossShips[n]; // Create boss bullets with different patterns if (boss.shouldShoot) { if (boss.shootPattern === 0) { // Single shot at player var newBossBullet = new EnemyBullet(); newBossBullet.x = boss.x; newBossBullet.y = boss.y + 125; newBossBullet.lastY = newBossBullet.y; newBossBullet.lastIntersecting = false; enemyBullets.push(newBossBullet); game.addChild(newBossBullet); } else if (boss.shootPattern === 1) { // Triple shot for (var s = -1; s <= 1; s++) { var newBossBullet = new EnemyBullet(); newBossBullet.x = boss.x + s * 60; newBossBullet.y = boss.y + 125; newBossBullet.lastY = newBossBullet.y; newBossBullet.lastIntersecting = false; enemyBullets.push(newBossBullet); game.addChild(newBossBullet); } } else { // Spread shot (5 bullets) for (var s = -2; s <= 2; s++) { var newBossBullet = new EnemyBullet(); newBossBullet.x = boss.x + s * 40; newBossBullet.y = boss.y + 125; newBossBullet.lastY = newBossBullet.y; newBossBullet.lastIntersecting = false; enemyBullets.push(newBossBullet); game.addChild(newBossBullet); } } boss.shouldShoot = false; } // Check if boss reached bottom edge - instant kill player if (boss.lastY <= 2780 && boss.y > 2780) { playerShip.health = 0; playerShip.updateHealthBar(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Check player-boss collision var bossPlayerIntersecting = boss.intersects(playerShip); if (!boss.lastIntersecting && bossPlayerIntersecting) { // Damage player playerShip.health -= 1; // Boss does 1 damage like other sources playerShip.updateHealthBar(); // Flash effect on player LK.effects.flashObject(playerShip, 0xff0000, 300); } boss.lastY = boss.y; boss.lastIntersecting = bossPlayerIntersecting; } // Update and check enemy bullets for (var m = enemyBullets.length - 1; m >= 0; m--) { var enemyBullet = enemyBullets[m]; // Remove bullets that go off screen if (enemyBullet.lastY <= 2780 && enemyBullet.y > 2780) { enemyBullet.destroy(); enemyBullets.splice(m, 1); continue; } // Check enemy bullet-player collision var bulletPlayerIntersecting = enemyBullet.intersects(playerShip); if (!enemyBullet.lastIntersecting && bulletPlayerIntersecting) { // Damage player playerShip.health--; playerShip.updateHealthBar(); // Flash effect on player LK.effects.flashObject(playerShip, 0xff0000, 300); // Destroy bullet enemyBullet.destroy(); enemyBullets.splice(m, 1); continue; } enemyBullet.lastY = enemyBullet.y; enemyBullet.lastIntersecting = bulletPlayerIntersecting; } // Update and check gun power-ups for (var g = gunPowerUps.length - 1; g >= 0; g--) { var gunPowerUp = gunPowerUps[g]; // Remove gun power-ups that go off screen if (gunPowerUp.lastY <= 2780 && gunPowerUp.y > 2780) { gunPowerUp.destroy(); gunPowerUps.splice(g, 1); continue; } // Check gun power-up-player collision var gunPowerUpPlayerIntersecting = gunPowerUp.intersects(playerShip); if (!gunPowerUp.lastIntersecting && gunPowerUpPlayerIntersecting) { // Enable triple shot for 6 seconds (360 frames at 60fps) hasTripleShot = true; gunPowerUpEndTime = LK.ticks + 360; // Flash effect on player (blue for gun upgrade) LK.effects.flashObject(playerShip, 0x0099ff, 300); // Tint player ship blue to show power-up is active tween(playerShip, { tint: 0x4444ff }, { duration: 500 }); // Destroy gun power-up gunPowerUp.destroy(); gunPowerUps.splice(g, 1); continue; } gunPowerUp.lastY = gunPowerUp.y; gunPowerUp.lastIntersecting = gunPowerUpPlayerIntersecting; } // Update and check health packs for (var h = healthPacks.length - 1; h >= 0; h--) { var healthPack = healthPacks[h]; // Remove health packs that go off screen if (healthPack.lastY <= 2780 && healthPack.y > 2780) { healthPack.destroy(); healthPacks.splice(h, 1); continue; } // Check health pack-player collision var healthPackPlayerIntersecting = healthPack.intersects(playerShip); if (!healthPack.lastIntersecting && healthPackPlayerIntersecting) { // Heal player to max health if (playerShip.health < playerShip.maxHealth) { playerShip.health = playerShip.maxHealth; playerShip.updateHealthBar(); // Flash effect on player (magenta for health) LK.effects.flashObject(playerShip, 0xff00ff, 300); } // Destroy health pack healthPack.destroy(); healthPacks.splice(h, 1); continue; } healthPack.lastY = healthPack.y; healthPack.lastIntersecting = healthPackPlayerIntersecting; } // Check if gun power-up should expire if (hasTripleShot && LK.ticks >= gunPowerUpEndTime) { hasTripleShot = false; // Fade player ship back to normal color tween(playerShip, { tint: 0xffffff }, { duration: 500 }); // Flash effect to show power-up ended LK.effects.flashObject(playerShip, 0xffffff, 200); } // Check if player is dead if (playerShip.health <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Increase difficulty over time if (LK.ticks % 1800 === 0) { // Every 30 seconds difficultyLevel++; if (enemySpawnRate > 30) { enemySpawnRate -= 10; } if (bulletFireRate > 8 && difficultyLevel % 3 === 0) { bulletFireRate -= 1; } } }; // Start background music LK.playMusic('gameMusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossShip = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('bossShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.moveDirection = 1;
self.shootTimer = 0;
self.maxHealth = 50;
self.health = self.maxHealth;
self.shootPattern = 0;
self.patternTimer = 0;
// Create boss health bar background
var healthBarBg = self.attachAsset('bossHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -140;
// Create boss health bar fill
var healthBarFill = self.attachAsset('bossHealthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.y = -140;
self.healthBarFill = healthBarFill;
// Method to update health bar
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
self.healthBarFill.scaleX = healthPercent;
if (healthPercent > 0.6) {
self.healthBarFill.tint = 0xff0000; // Red
} else if (healthPercent > 0.3) {
self.healthBarFill.tint = 0xff6600; // Orange
} else {
self.healthBarFill.tint = 0xffff00; // Yellow
}
};
self.update = function () {
self.y += self.speed;
// Move side to side
self.x += self.moveDirection * 2;
if (self.x <= 100 || self.x >= 1948) {
self.moveDirection *= -1;
}
// Handle shooting patterns
self.shootTimer--;
self.patternTimer++;
if (self.patternTimer % 300 === 0) {
self.shootPattern = (self.shootPattern + 1) % 3;
}
if (self.shootTimer <= 0) {
self.shootTimer = 30;
// Only shoot if not about to hit edges
if (self.x > 150 && self.x < 1898) {
self.shouldShoot = true;
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
// Play shoot sound when enemy bullet is created
LK.getSound('shoot').play();
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.movePattern = Math.random() < 0.5 ? 'straight' : 'zigzag';
self.zigzagTimer = 0;
self.zigzagDirection = Math.random() < 0.5 ? -1 : 1;
self.shootTimer = Math.random() * 60 + 60; // Random initial shoot delay
self.maxHealth = 3;
self.health = self.maxHealth;
// Create health bar background
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -50;
// Create health bar fill
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.y = -50;
self.healthBarFill = healthBarFill;
// Method to update health bar
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
self.healthBarFill.scaleX = healthPercent;
if (healthPercent > 0.6) {
self.healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
self.healthBarFill.tint = 0xffff00; // Yellow
} else {
self.healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
self.y += self.speed;
if (self.movePattern === 'zigzag') {
self.zigzagTimer += 1;
if (self.zigzagTimer % 60 === 0) {
self.zigzagDirection *= -1;
}
self.x += self.zigzagDirection * 2;
}
// Keep enemy within screen bounds
if (self.x < 50) self.x = 50;
if (self.x > 1998) self.x = 1998;
// Handle shooting
self.shootTimer--;
if (self.shootTimer <= 0) {
self.shootTimer = Math.random() * 120 + 90; // Slower random shoot interval
self.shouldShoot = true;
}
};
return self;
});
var GunPowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('gunPowerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.update = function () {
self.y += self.speed;
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthPackGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.angle = 0; // Angle in radians for bullet direction
// Play shoot sound when bullet is created
LK.getSound('shoot').play();
self.update = function () {
self.y += self.speed * Math.cos(self.angle);
self.x += self.speed * Math.sin(self.angle);
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 10;
self.health = self.maxHealth;
// Create health bar background
var healthBarBg = self.attachAsset('playerHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -80;
// Create health bar fill
var healthBarFill = self.attachAsset('playerHealthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.y = -80;
self.healthBarFill = healthBarFill;
// Method to update health bar
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
self.healthBarFill.scaleX = healthPercent;
if (healthPercent > 0.6) {
self.healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
self.healthBarFill.tint = 0xffff00; // Yellow
} else {
self.healthBarFill.tint = 0xff0000; // Red
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Game variables
var playerShip;
var playerBullets = [];
var enemyBullets = [];
var enemyShips = [];
var bossShips = [];
var difficultyLevel = 1;
var enemySpawnRate = 120; // frames between spawns
var bulletFireRate = 15; // frames between shots
var dragNode = null;
var lastBossScore = 0;
var gunPowerUps = [];
var gunPowerUpTimer = 0;
var healthPacks = [];
var healthPackTimer = 0;
var playerFireRate = bulletFireRate; // Track player's current fire rate
var hasTripleShot = false; // Track if player has triple shot upgrade
var gunPowerUpEndTime = 0; // Track when gun power-up should end
var isBossPresent = false; // Track if boss is currently on screen
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize player ship
playerShip = game.addChild(new PlayerShip());
playerShip.x = 1024; // Center horizontally
playerShip.y = 2400; // Near bottom of screen
// Update score display
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
// Handle movement
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Keep player within screen bounds
if (dragNode.x < 40) dragNode.x = 40;
if (dragNode.x > 2008) dragNode.x = 2008;
if (dragNode.y < 200) dragNode.y = 200;
if (dragNode.y > 2600) dragNode.y = 2600;
}
}
// Event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = playerShip;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Fire player bullets
if (LK.ticks % playerFireRate === 0) {
if (hasTripleShot) {
// Fire three bullets in different directions
var angles = [-0.3, 0, 0.3]; // Left, center, right angles in radians
for (var bulletIndex = 0; bulletIndex < 3; bulletIndex++) {
var newBullet = new PlayerBullet();
newBullet.x = playerShip.x;
newBullet.y = playerShip.y - 60;
newBullet.angle = angles[bulletIndex];
newBullet.lastY = newBullet.y;
playerBullets.push(newBullet);
game.addChild(newBullet);
}
} else {
// Fire single bullet
var newBullet = new PlayerBullet();
newBullet.x = playerShip.x;
newBullet.y = playerShip.y - 60;
newBullet.lastY = newBullet.y;
playerBullets.push(newBullet);
game.addChild(newBullet);
}
}
// Spawn gun power-up every 13 seconds (780 frames)
gunPowerUpTimer++;
if (gunPowerUpTimer >= 780) {
var newGunPowerUp = new GunPowerUp();
newGunPowerUp.x = Math.random() * 1800 + 124; // Random x position within bounds
newGunPowerUp.y = -50;
newGunPowerUp.lastY = newGunPowerUp.y;
newGunPowerUp.lastIntersecting = false;
gunPowerUps.push(newGunPowerUp);
game.addChild(newGunPowerUp);
gunPowerUpTimer = 0;
}
// Spawn health pack every 30 seconds (1800 frames)
healthPackTimer++;
if (healthPackTimer >= 1800) {
var newHealthPack = new HealthPack();
newHealthPack.x = Math.random() * 1800 + 124; // Random x position within bounds
newHealthPack.y = -50;
newHealthPack.lastY = newHealthPack.y;
newHealthPack.lastIntersecting = false;
healthPacks.push(newHealthPack);
game.addChild(newHealthPack);
healthPackTimer = 0;
}
// Spawn boss every 1000 points
var currentScore = LK.getScore();
if (Math.floor(currentScore / 1000) > Math.floor(lastBossScore / 1000) && bossShips.length === 0) {
var newBoss = new BossShip();
newBoss.x = 1024; // Center horizontally
newBoss.y = -125;
newBoss.lastY = newBoss.y;
newBoss.lastIntersecting = false;
bossShips.push(newBoss);
game.addChild(newBoss);
lastBossScore = currentScore;
isBossPresent = true;
}
// Spawn enemies (only when no boss is present)
if (!isBossPresent && LK.ticks % enemySpawnRate === 0) {
var newEnemy = new EnemyShip();
newEnemy.x = Math.random() * 1800 + 124; // Random x position within bounds
newEnemy.y = -50;
newEnemy.lastY = newEnemy.y;
newEnemy.lastIntersecting = false;
enemyShips.push(newEnemy);
game.addChild(newEnemy);
}
// Update and check player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Remove bullets that go off screen
if (bullet.lastY >= -25 && bullet.y < -25) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
var bulletHit = false;
for (var j = enemyShips.length - 1; j >= 0; j--) {
var enemy = enemyShips[j];
if (bullet.intersects(enemy)) {
// Damage enemy
enemy.health--;
enemy.updateHealthBar();
LK.setScore(LK.getScore() + 5);
updateScore();
// Flash effect on enemy
LK.effects.flashObject(enemy, 0xffffff, 200);
bullet.destroy();
playerBullets.splice(i, 1);
bulletHit = true;
// Check if enemy is destroyed
if (enemy.health <= 0) {
LK.setScore(LK.getScore() + 5); // Bonus points for destroying enemy
updateScore();
LK.getSound('enemyDestroy').play();
enemy.destroy();
enemyShips.splice(j, 1);
}
break;
}
}
// Check bullet-boss collisions
if (!bulletHit) {
for (var b = bossShips.length - 1; b >= 0; b--) {
var boss = bossShips[b];
if (bullet.intersects(boss)) {
// Damage boss
boss.health--;
boss.updateHealthBar();
// Flash effect on boss
LK.effects.flashObject(boss, 0xffffff, 200);
bullet.destroy();
playerBullets.splice(i, 1);
bulletHit = true;
// Check if boss is destroyed
if (boss.health <= 0) {
LK.setScore(LK.getScore() + 500); // Big bonus for destroying boss
updateScore();
LK.getSound('enemyDestroy').play();
boss.destroy();
bossShips.splice(b, 1);
isBossPresent = false; // Allow enemies to spawn again
}
break;
}
}
}
if (!bulletHit) {
bullet.lastY = bullet.y;
}
}
// Update and check enemies
for (var k = enemyShips.length - 1; k >= 0; k--) {
var enemy = enemyShips[k];
// Create enemy bullet if enemy should shoot
if (enemy.shouldShoot) {
var newEnemyBullet = new EnemyBullet();
newEnemyBullet.x = enemy.x;
newEnemyBullet.y = enemy.y + 40;
newEnemyBullet.lastY = newEnemyBullet.y;
newEnemyBullet.lastIntersecting = false;
enemyBullets.push(newEnemyBullet);
game.addChild(newEnemyBullet);
enemy.shouldShoot = false;
}
// Check if enemy reached bottom edge - instant kill player
if (enemy.lastY <= 2780 && enemy.y > 2780) {
// Enemy reached bottom - instant kill player
playerShip.health = 0;
playerShip.updateHealthBar();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check player-enemy collision
var currentIntersecting = enemy.intersects(playerShip);
if (!enemy.lastIntersecting && currentIntersecting) {
// Damage player
playerShip.health--;
playerShip.updateHealthBar();
// Flash effect on player
LK.effects.flashObject(playerShip, 0xff0000, 300);
// Destroy enemy
enemy.destroy();
enemyShips.splice(k, 1);
continue;
}
enemy.lastY = enemy.y;
enemy.lastIntersecting = currentIntersecting;
}
// Update and check bosses
for (var n = bossShips.length - 1; n >= 0; n--) {
var boss = bossShips[n];
// Create boss bullets with different patterns
if (boss.shouldShoot) {
if (boss.shootPattern === 0) {
// Single shot at player
var newBossBullet = new EnemyBullet();
newBossBullet.x = boss.x;
newBossBullet.y = boss.y + 125;
newBossBullet.lastY = newBossBullet.y;
newBossBullet.lastIntersecting = false;
enemyBullets.push(newBossBullet);
game.addChild(newBossBullet);
} else if (boss.shootPattern === 1) {
// Triple shot
for (var s = -1; s <= 1; s++) {
var newBossBullet = new EnemyBullet();
newBossBullet.x = boss.x + s * 60;
newBossBullet.y = boss.y + 125;
newBossBullet.lastY = newBossBullet.y;
newBossBullet.lastIntersecting = false;
enemyBullets.push(newBossBullet);
game.addChild(newBossBullet);
}
} else {
// Spread shot (5 bullets)
for (var s = -2; s <= 2; s++) {
var newBossBullet = new EnemyBullet();
newBossBullet.x = boss.x + s * 40;
newBossBullet.y = boss.y + 125;
newBossBullet.lastY = newBossBullet.y;
newBossBullet.lastIntersecting = false;
enemyBullets.push(newBossBullet);
game.addChild(newBossBullet);
}
}
boss.shouldShoot = false;
}
// Check if boss reached bottom edge - instant kill player
if (boss.lastY <= 2780 && boss.y > 2780) {
playerShip.health = 0;
playerShip.updateHealthBar();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check player-boss collision
var bossPlayerIntersecting = boss.intersects(playerShip);
if (!boss.lastIntersecting && bossPlayerIntersecting) {
// Damage player
playerShip.health -= 1; // Boss does 1 damage like other sources
playerShip.updateHealthBar();
// Flash effect on player
LK.effects.flashObject(playerShip, 0xff0000, 300);
}
boss.lastY = boss.y;
boss.lastIntersecting = bossPlayerIntersecting;
}
// Update and check enemy bullets
for (var m = enemyBullets.length - 1; m >= 0; m--) {
var enemyBullet = enemyBullets[m];
// Remove bullets that go off screen
if (enemyBullet.lastY <= 2780 && enemyBullet.y > 2780) {
enemyBullet.destroy();
enemyBullets.splice(m, 1);
continue;
}
// Check enemy bullet-player collision
var bulletPlayerIntersecting = enemyBullet.intersects(playerShip);
if (!enemyBullet.lastIntersecting && bulletPlayerIntersecting) {
// Damage player
playerShip.health--;
playerShip.updateHealthBar();
// Flash effect on player
LK.effects.flashObject(playerShip, 0xff0000, 300);
// Destroy bullet
enemyBullet.destroy();
enemyBullets.splice(m, 1);
continue;
}
enemyBullet.lastY = enemyBullet.y;
enemyBullet.lastIntersecting = bulletPlayerIntersecting;
}
// Update and check gun power-ups
for (var g = gunPowerUps.length - 1; g >= 0; g--) {
var gunPowerUp = gunPowerUps[g];
// Remove gun power-ups that go off screen
if (gunPowerUp.lastY <= 2780 && gunPowerUp.y > 2780) {
gunPowerUp.destroy();
gunPowerUps.splice(g, 1);
continue;
}
// Check gun power-up-player collision
var gunPowerUpPlayerIntersecting = gunPowerUp.intersects(playerShip);
if (!gunPowerUp.lastIntersecting && gunPowerUpPlayerIntersecting) {
// Enable triple shot for 6 seconds (360 frames at 60fps)
hasTripleShot = true;
gunPowerUpEndTime = LK.ticks + 360;
// Flash effect on player (blue for gun upgrade)
LK.effects.flashObject(playerShip, 0x0099ff, 300);
// Tint player ship blue to show power-up is active
tween(playerShip, {
tint: 0x4444ff
}, {
duration: 500
});
// Destroy gun power-up
gunPowerUp.destroy();
gunPowerUps.splice(g, 1);
continue;
}
gunPowerUp.lastY = gunPowerUp.y;
gunPowerUp.lastIntersecting = gunPowerUpPlayerIntersecting;
}
// Update and check health packs
for (var h = healthPacks.length - 1; h >= 0; h--) {
var healthPack = healthPacks[h];
// Remove health packs that go off screen
if (healthPack.lastY <= 2780 && healthPack.y > 2780) {
healthPack.destroy();
healthPacks.splice(h, 1);
continue;
}
// Check health pack-player collision
var healthPackPlayerIntersecting = healthPack.intersects(playerShip);
if (!healthPack.lastIntersecting && healthPackPlayerIntersecting) {
// Heal player to max health
if (playerShip.health < playerShip.maxHealth) {
playerShip.health = playerShip.maxHealth;
playerShip.updateHealthBar();
// Flash effect on player (magenta for health)
LK.effects.flashObject(playerShip, 0xff00ff, 300);
}
// Destroy health pack
healthPack.destroy();
healthPacks.splice(h, 1);
continue;
}
healthPack.lastY = healthPack.y;
healthPack.lastIntersecting = healthPackPlayerIntersecting;
}
// Check if gun power-up should expire
if (hasTripleShot && LK.ticks >= gunPowerUpEndTime) {
hasTripleShot = false;
// Fade player ship back to normal color
tween(playerShip, {
tint: 0xffffff
}, {
duration: 500
});
// Flash effect to show power-up ended
LK.effects.flashObject(playerShip, 0xffffff, 200);
}
// Check if player is dead
if (playerShip.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Increase difficulty over time
if (LK.ticks % 1800 === 0) {
// Every 30 seconds
difficultyLevel++;
if (enemySpawnRate > 30) {
enemySpawnRate -= 10;
}
if (bulletFireRate > 8 && difficultyLevel % 3 === 0) {
bulletFireRate -= 1;
}
}
};
// Start background music
LK.playMusic('gameMusic');
boss enimey space ship. In-Game asset. 2d. High contrast. No shadows
enimy space ship. In-Game asset. 2d. High contrast. No shadows
player space ship. In-Game asset. 2d. High contrast. No shadows
bullet. In-Game asset. 2d. High contrast. No shadows
shot gun. In-Game asset. 2d. High contrast. No shadows
first aid kit. In-Game asset. 2d. High contrast. No shadows