/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BossShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); shipGraphics.scaleX = 5; shipGraphics.scaleY = 5; shipGraphics.tint = 0xFF0000; self.health = 10; self.maxHealth = 10; self.shootCooldown = 0; self.attackPattern = 0; self.update = function () { // Boss stays stationary - no movement // New attack pattern - orange and cyan attacks if (self.shootCooldown <= 0) { if (self.attackPattern % 2 === 0) { // Orange attack pattern - 3 orange attacks tracking player var playerDx = player.x - self.x; var playerDy = player.y - self.y; var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy); var playerDirX = playerDx / playerDistance; var playerDirY = playerDy / playerDistance; for (var i = 0; i < 3; i++) { var orangeAttack = new OrangeAttack(); orangeAttack.x = self.x + (i - 1) * 120; // Spread attacks orangeAttack.y = self.y + 100; // Set tracking direction with spread var spreadAngle = (i - 1) * 0.2; orangeAttack.dirX = playerDirX * Math.cos(spreadAngle) - playerDirY * Math.sin(spreadAngle); orangeAttack.dirY = playerDirX * Math.sin(spreadAngle) + playerDirY * Math.cos(spreadAngle); game.addChild(orangeAttack); orangeAttacks.push(orangeAttack); } self.shootCooldown = 80; } else { // Cyan attack pattern - 2 cyan attacks tracking player var playerDx = player.x - self.x; var playerDy = player.y - self.y; var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy); var playerDirX = playerDx / playerDistance; var playerDirY = playerDy / playerDistance; for (var i = 0; i < 2; i++) { var cyanAttack = new CyanAttack(); cyanAttack.x = self.x + (i === 0 ? -100 : 100); cyanAttack.y = self.y + 100; // Set tracking direction cyanAttack.dirX = playerDirX; cyanAttack.dirY = playerDirY; game.addChild(cyanAttack); cyanAttacks.push(cyanAttack); } self.shootCooldown = 90; } self.attackPattern++; } if (self.shootCooldown > 0) { self.shootCooldown--; } // Pulsing effect based on health var healthRatio = self.health / self.maxHealth; var pulseScale = 5 + Math.sin(LK.ticks * 0.1) * 0.5 * (1 - healthRatio); shipGraphics.scaleX = pulseScale; shipGraphics.scaleY = pulseScale; }; self.takeDamage = function (damage, isChargedAttack) { // Boss is immune to charged attacks if (isChargedAttack) { return; } self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { LK.setScore(LK.getScore() + 10); LK.getSound('enemyDestroy').play(); self.destroy(); bossActive = false; boss = null; gameLevel++; // Increment level when boss is defeated levelResetFlag = true; // Flag to show level indicator LK.showGameOver(); } }; return self; }); var BossWideLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('bossWideLaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 3; self.update = function () { // Move towards player if direction is set, otherwise move straight down if (self.dirX !== undefined && self.dirY !== undefined) { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; } else { self.y += self.speed; } }; return self; }); var ChargedPlayerLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('chargedPlayerLaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -10; self.damage = 3; self.update = function () { self.y += self.speed; }; return self; }); var CyanAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('cyanAttack', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 2; self.checkTimer = 0; self.update = function () { // Move towards player if direction is set, otherwise move straight down if (self.dirX !== undefined && self.dirY !== undefined) { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; } else { self.y += self.speed; } // Add pulsing cyan effect var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.3; attackGraphics.scaleX = pulse; attackGraphics.scaleY = pulse; }; return self; }); var EnemyProjectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('enemyProjectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.update = function () { self.y += self.speed; }; return self; }); var EnemyShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.health = 3; self.shootCooldown = Math.random() * 60 + 30; // Random initial cooldown self.update = function () { self.y += self.speed; // Enemy shooting if (self.shootCooldown <= 0) { var projectile = new EnemyProjectile(); projectile.x = self.x; projectile.y = self.y + 40; game.addChild(projectile); enemyProjectiles.push(projectile); self.shootCooldown = Math.random() * 90 + 60; // Random cooldown between shots } if (self.shootCooldown > 0) { self.shootCooldown--; } }; return self; }); var Level2EnemyShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); // Level 2 enemies are larger and have different color shipGraphics.scaleX = 1.5; shipGraphics.scaleY = 1.5; shipGraphics.tint = 0xFF6600; // Orange tint for level 2 self.speed = 10; // Faster than regular enemies self.health = 5; // More health than regular enemies self.shootCooldown = Math.random() * 40 + 20; // Shoots more frequently self.zigzagTimer = 0; self.zigzagDirection = Math.random() > 0.5 ? 1 : -1; self.update = function () { self.y += self.speed; // Zigzag movement pattern self.zigzagTimer++; if (self.zigzagTimer % 30 === 0) { self.zigzagDirection *= -1; } self.x += self.zigzagDirection * 3; // Keep within screen bounds if (self.x < 100) { self.x = 100; self.zigzagDirection = 1; } if (self.x > 1948) { self.x = 1948; self.zigzagDirection = -1; } // Enhanced shooting - shoots 2 projectiles if (self.shootCooldown <= 0) { for (var i = 0; i < 2; i++) { var projectile = new EnemyProjectile(); projectile.x = self.x + (i === 0 ? -20 : 20); projectile.y = self.y + 40; projectile.speed = 8; // Faster projectiles game.addChild(projectile); enemyProjectiles.push(projectile); } self.shootCooldown = Math.random() * 60 + 40; } if (self.shootCooldown > 0) { self.shootCooldown--; } }; return self; }); var OrangeAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('orangeAttack', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 2; self.checkTimer = 0; self.update = function () { // Move towards player if direction is set, otherwise move straight down if (self.dirX !== undefined && self.dirY !== undefined) { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; } else { self.y += self.speed; } // Add pulsing orange effect var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.3; attackGraphics.scaleX = pulse; attackGraphics.scaleY = pulse; }; return self; }); var PlayerLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('playerLaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -8; self.damage = 1; self.update = function () { self.y += self.speed; }; return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); var chargeIndicator = self.attachAsset('chargeIndicator', { anchorX: 0.5, anchorY: 0.5 }); chargeIndicator.x = 0; chargeIndicator.y = -80; chargeIndicator.visible = false; self.health = 3; self.shootCooldown = 0; self.chargeAttackTime = 0; self.isCharging = false; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.isCharging) { self.chargeAttackTime++; // Create pulsing animation while charging var pulseIntensity = Math.min(self.chargeAttackTime / 60, 1); // 0 to 1 var pulseScale = 1 + Math.sin(LK.ticks * 0.3) * 0.15 * pulseIntensity; self.scaleX = pulseScale; self.scaleY = pulseScale; // Add color tint that gets stronger as charge builds var tintIntensity = Math.floor(pulseIntensity * 100); self.tint = 0xFFFFFF + (tintIntensity << 8); // Add green tint // When fully charged, show green square indicator if (self.chargeAttackTime >= 60) { var readyPulse = 1.2 + Math.sin(LK.ticks * 0.5) * 0.3; self.scaleX = readyPulse; self.scaleY = readyPulse; self.tint = 0x00FF00; // Bright green when ready chargeIndicator.visible = true; } } else { // Reset scale and tint when not charging self.scaleX = 1; self.scaleY = 1; self.tint = 0xFFFFFF; chargeIndicator.visible = false; } }; self.shoot = function () { if (self.shootCooldown <= 0) { var laser; // Create charged laser if charge time is sufficient if (self.chargeAttackTime >= 60) { laser = new ChargedPlayerLaser(); // Add spawn animation for charged laser laser.scaleX = 0.3; laser.scaleY = 0.3; tween(laser, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); // Add tint effect laser.tint = 0x00FF00; tween(laser, { tint: 0xFFFFFF }, { duration: 300 }); } else { laser = new PlayerLaser(); } laser.x = self.x; laser.y = self.y - 60; game.addChild(laser); playerLasers.push(laser); self.shootCooldown = 10; LK.getSound('shoot').play(); } }; self.takeDamage = function () { self.health--; LK.getSound('playerHit').play(); LK.effects.flashObject(self, 0xff0000, 500); if (self.health <= 0) { LK.showGameOver(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000011 }); /**** * Game Code ****/ var player = new PlayerShip(); player.x = 2048 / 2; player.y = 2732 - 200; game.addChild(player); var enemies = []; var playerLasers = []; var enemyProjectiles = []; var spawnTimer = 0; var gameSpeed = 1; var playerShootCooldown = 0; var isFireButtonPressed = false; var bossActive = false; var boss = null; var bossProjectiles = []; var bossLasers = []; var bossWideLasers = []; var orangeAttacks = []; var cyanAttacks = []; var playerLastX = 0; var playerLastY = 0; var playerIsMoving = false; var gameLevel = 1; var levelResetFlag = false; var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var healthTxt = new Text2('Health: 3', { size: 60, fill: 0xFF4444 }); healthTxt.anchor.set(0, 0); healthTxt.x = 150; healthTxt.y = 50; LK.gui.topLeft.addChild(healthTxt); var fireButton = new Text2('FIRE', { size: 120, fill: 0x00FF00 }); fireButton.anchor.set(1, 0); LK.gui.topRight.addChild(fireButton); var levelTxt = new Text2('Level: 1', { size: 60, fill: 0xFFFF00 }); levelTxt.anchor.set(0.5, 0); levelTxt.x = 0; levelTxt.y = 150; LK.gui.top.addChild(levelTxt); var dragNode = null; fireButton.down = function (x, y, obj) { isFireButtonPressed = true; player.isCharging = true; player.chargeAttackTime = 0; if (playerShootCooldown <= 0) { player.shoot(); playerShootCooldown = 20; } }; fireButton.up = function (x, y, obj) { isFireButtonPressed = false; // Shoot charged laser if player was charging if (player.isCharging && player.chargeAttackTime >= 60) { if (playerShootCooldown <= 0) { player.shoot(); playerShootCooldown = 20; } } player.isCharging = false; player.chargeAttackTime = 0; }; game.down = function (x, y, obj) { dragNode = player; player.isCharging = true; player.chargeAttackTime = 0; if (playerShootCooldown <= 0) { player.shoot(); playerShootCooldown = 20; } }; game.move = function (x, y, obj) { if (dragNode) { dragNode.x = Math.max(100, Math.min(1948, x)); } }; game.up = function (x, y, obj) { dragNode = null; // Shoot charged laser if player was charging if (player.isCharging && player.chargeAttackTime >= 60) { if (playerShootCooldown <= 0) { player.shoot(); playerShootCooldown = 20; } } player.isCharging = false; player.chargeAttackTime = 0; }; game.update = function () { // Update cooldown if (playerShootCooldown > 0) { playerShootCooldown--; } // Track player movement var currentPlayerMoving = Math.abs(player.x - playerLastX) > 1 || Math.abs(player.y - playerLastY) > 1; playerIsMoving = currentPlayerMoving; playerLastX = player.x; playerLastY = player.y; // Update UI scoreTxt.setText('Score: ' + LK.getScore()); healthTxt.setText('Health: ' + player.health); levelTxt.setText('Level: ' + gameLevel); // Show level indicator when level changes if (levelResetFlag) { LK.effects.flashScreen(0x00FF00, 800); // Green flash for level up levelResetFlag = false; } // Boss spawn when player reaches score threshold based on level var bossSpawnThreshold = 100 * gameLevel; if (LK.getScore() >= bossSpawnThreshold && !bossActive) { boss = new BossShip(); boss.x = 2048 / 2; boss.y = 200; // Scale boss health with level boss.health = 10 + (gameLevel - 1) * 5; boss.maxHealth = boss.health; game.addChild(boss); bossActive = true; } // Spawn regular enemies (only when boss is not active) if (!bossActive) { spawnTimer++; var spawnRate = Math.max(120 - Math.floor(LK.getScore() / 10) * 10, 60); if (spawnTimer >= spawnRate) { var enemy; // Spawn level 2 enemies if we're on level 2 or higher if (gameLevel >= 2) { // Mix of regular and level 2 enemies, with more level 2 enemies on higher levels if (Math.random() < 0.7) { enemy = new Level2EnemyShip(); } else { enemy = new EnemyShip(); } } else { enemy = new EnemyShip(); } enemy.x = Math.random() * 1848 + 100; enemy.y = -50; if (enemy.speed === undefined) { enemy.speed = 6 + Math.floor(LK.getScore() / 15) * 1.5; } enemies.push(enemy); game.addChild(enemy); spawnTimer = 0; } } // Update and check player lasers for (var i = playerLasers.length - 1; i >= 0; i--) { var laser = playerLasers[i]; if (laser.lastY === undefined) laser.lastY = laser.y; // Remove lasers that go off screen if (laser.lastY >= -50 && laser.y < -50) { laser.destroy(); playerLasers.splice(i, 1); continue; } // Check collision with enemies var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (laser.intersects(enemy)) { enemy.health -= laser.damage; laser.destroy(); playerLasers.splice(i, 1); hitEnemy = true; if (enemy.health <= 0) { LK.setScore(LK.getScore() + 10); LK.getSound('enemyDestroy').play(); enemy.destroy(); enemies.splice(j, 1); } break; } } // Check collision with boss if (bossActive && boss && laser.intersects(boss)) { var isChargedAttack = laser.damage > 1; boss.takeDamage(laser.damage, isChargedAttack); laser.destroy(); playerLasers.splice(i, 1); hitEnemy = true; } if (!hitEnemy) { laser.lastY = laser.y; } } // Update and check enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.lastY === undefined) enemy.lastY = enemy.y; // Remove enemies that reach bottom if (enemy.lastY <= 2732 && enemy.y > 2732) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check collision with player if (enemy.intersects(player)) { enemy.destroy(); enemies.splice(i, 1); player.takeDamage(); continue; } enemy.lastY = enemy.y; } // Check boss collision with player if (bossActive && boss && boss.intersects(player)) { player.takeDamage(); player.takeDamage(); // Boss does double damage } // Update and check enemy projectiles for (var i = enemyProjectiles.length - 1; i >= 0; i--) { var projectile = enemyProjectiles[i]; if (projectile.lastY === undefined) projectile.lastY = projectile.y; // Remove projectiles that go off screen if (projectile.lastY <= 2732 && projectile.y > 2732) { projectile.destroy(); enemyProjectiles.splice(i, 1); continue; } // Check collision with player if (projectile.intersects(player)) { projectile.destroy(); enemyProjectiles.splice(i, 1); // Enemy projectiles no longer cause damage - just destroy on contact // Enhanced damage for boss projectiles if (projectile.damage && projectile.damage > 1) { // player.takeDamage(); // player.takeDamage(); } else { // player.takeDamage(); } continue; } projectile.lastY = projectile.y; } // Update and check boss projectiles for (var i = bossProjectiles.length - 1; i >= 0; i--) { var projectile = bossProjectiles[i]; // Remove projectiles if boss is dead or projectiles go too far var shouldRemove = false; if (!boss) { shouldRemove = true; } else { var distanceFromBoss = Math.sqrt(Math.pow(projectile.x - boss.x, 2) + Math.pow(projectile.y - boss.y, 2)); shouldRemove = distanceFromBoss > 800; } if (shouldRemove || projectile.y > 2732 || projectile.y < -100 || projectile.x < -100 || projectile.x > 2148) { projectile.destroy(); bossProjectiles.splice(i, 1); continue; } // Check collision with player if (projectile.intersects(player)) { projectile.destroy(); bossProjectiles.splice(i, 1); // Giant projectiles do massive damage player.takeDamage(); player.takeDamage(); player.takeDamage(); continue; } } // Update and check boss lasers for (var i = bossLasers.length - 1; i >= 0; i--) { var laser = bossLasers[i]; if (laser.lastY === undefined) laser.lastY = laser.y; // Remove lasers that go off screen if (laser.lastY <= 2732 && laser.y > 2732) { laser.destroy(); bossLasers.splice(i, 1); continue; } // Check collision with player if (laser.intersects(player)) { laser.destroy(); bossLasers.splice(i, 1); player.takeDamage(); player.takeDamage(); // Boss lasers do double damage continue; } laser.lastY = laser.y; } // Update and check boss wide lasers for (var i = bossWideLasers.length - 1; i >= 0; i--) { var laser = bossWideLasers[i]; if (laser.lastY === undefined) laser.lastY = laser.y; // Remove lasers that go off screen if (laser.lastY <= 2732 && laser.y > 2732) { laser.destroy(); bossWideLasers.splice(i, 1); continue; } // Check collision with player if (laser.intersects(player)) { laser.destroy(); bossWideLasers.splice(i, 1); // Wide lasers do massive damage player.takeDamage(); player.takeDamage(); player.takeDamage(); continue; } laser.lastY = laser.y; } // Update and check orange attacks for (var i = orangeAttacks.length - 1; i >= 0; i--) { var attack = orangeAttacks[i]; if (attack.lastY === undefined) attack.lastY = attack.y; // Remove attacks that go off screen if (attack.lastY <= 2732 && attack.y > 2732) { attack.destroy(); orangeAttacks.splice(i, 1); continue; } // Check collision with player - damage only when player is NOT moving if (attack.intersects(player)) { attack.destroy(); orangeAttacks.splice(i, 1); // Orange attacks damage player when NOT moving if (!playerIsMoving) { player.takeDamage(); } continue; } attack.lastY = attack.y; } // Update and check cyan attacks for (var i = cyanAttacks.length - 1; i >= 0; i--) { var attack = cyanAttacks[i]; if (attack.lastY === undefined) attack.lastY = attack.y; // Remove attacks that go off screen if (attack.lastY <= 2732 && attack.y > 2732) { attack.destroy(); cyanAttacks.splice(i, 1); continue; } // Check collision with player - damage only when player IS moving if (attack.intersects(player)) { attack.destroy(); cyanAttacks.splice(i, 1); // Cyan attacks damage player when moving if (playerIsMoving) { player.takeDamage(); } continue; } attack.lastY = attack.y; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
shipGraphics.scaleX = 5;
shipGraphics.scaleY = 5;
shipGraphics.tint = 0xFF0000;
self.health = 10;
self.maxHealth = 10;
self.shootCooldown = 0;
self.attackPattern = 0;
self.update = function () {
// Boss stays stationary - no movement
// New attack pattern - orange and cyan attacks
if (self.shootCooldown <= 0) {
if (self.attackPattern % 2 === 0) {
// Orange attack pattern - 3 orange attacks tracking player
var playerDx = player.x - self.x;
var playerDy = player.y - self.y;
var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy);
var playerDirX = playerDx / playerDistance;
var playerDirY = playerDy / playerDistance;
for (var i = 0; i < 3; i++) {
var orangeAttack = new OrangeAttack();
orangeAttack.x = self.x + (i - 1) * 120; // Spread attacks
orangeAttack.y = self.y + 100;
// Set tracking direction with spread
var spreadAngle = (i - 1) * 0.2;
orangeAttack.dirX = playerDirX * Math.cos(spreadAngle) - playerDirY * Math.sin(spreadAngle);
orangeAttack.dirY = playerDirX * Math.sin(spreadAngle) + playerDirY * Math.cos(spreadAngle);
game.addChild(orangeAttack);
orangeAttacks.push(orangeAttack);
}
self.shootCooldown = 80;
} else {
// Cyan attack pattern - 2 cyan attacks tracking player
var playerDx = player.x - self.x;
var playerDy = player.y - self.y;
var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy);
var playerDirX = playerDx / playerDistance;
var playerDirY = playerDy / playerDistance;
for (var i = 0; i < 2; i++) {
var cyanAttack = new CyanAttack();
cyanAttack.x = self.x + (i === 0 ? -100 : 100);
cyanAttack.y = self.y + 100;
// Set tracking direction
cyanAttack.dirX = playerDirX;
cyanAttack.dirY = playerDirY;
game.addChild(cyanAttack);
cyanAttacks.push(cyanAttack);
}
self.shootCooldown = 90;
}
self.attackPattern++;
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Pulsing effect based on health
var healthRatio = self.health / self.maxHealth;
var pulseScale = 5 + Math.sin(LK.ticks * 0.1) * 0.5 * (1 - healthRatio);
shipGraphics.scaleX = pulseScale;
shipGraphics.scaleY = pulseScale;
};
self.takeDamage = function (damage, isChargedAttack) {
// Boss is immune to charged attacks
if (isChargedAttack) {
return;
}
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
LK.setScore(LK.getScore() + 10);
LK.getSound('enemyDestroy').play();
self.destroy();
bossActive = false;
boss = null;
gameLevel++; // Increment level when boss is defeated
levelResetFlag = true; // Flag to show level indicator
LK.showGameOver();
}
};
return self;
});
var BossWideLaser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('bossWideLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 3;
self.update = function () {
// Move towards player if direction is set, otherwise move straight down
if (self.dirX !== undefined && self.dirY !== undefined) {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
} else {
self.y += self.speed;
}
};
return self;
});
var ChargedPlayerLaser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('chargedPlayerLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -10;
self.damage = 3;
self.update = function () {
self.y += self.speed;
};
return self;
});
var CyanAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('cyanAttack', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 2;
self.checkTimer = 0;
self.update = function () {
// Move towards player if direction is set, otherwise move straight down
if (self.dirX !== undefined && self.dirY !== undefined) {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
} else {
self.y += self.speed;
}
// Add pulsing cyan effect
var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
attackGraphics.scaleX = pulse;
attackGraphics.scaleY = pulse;
};
return self;
});
var EnemyProjectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('enemyProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.health = 3;
self.shootCooldown = Math.random() * 60 + 30; // Random initial cooldown
self.update = function () {
self.y += self.speed;
// Enemy shooting
if (self.shootCooldown <= 0) {
var projectile = new EnemyProjectile();
projectile.x = self.x;
projectile.y = self.y + 40;
game.addChild(projectile);
enemyProjectiles.push(projectile);
self.shootCooldown = Math.random() * 90 + 60; // Random cooldown between shots
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var Level2EnemyShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Level 2 enemies are larger and have different color
shipGraphics.scaleX = 1.5;
shipGraphics.scaleY = 1.5;
shipGraphics.tint = 0xFF6600; // Orange tint for level 2
self.speed = 10; // Faster than regular enemies
self.health = 5; // More health than regular enemies
self.shootCooldown = Math.random() * 40 + 20; // Shoots more frequently
self.zigzagTimer = 0;
self.zigzagDirection = Math.random() > 0.5 ? 1 : -1;
self.update = function () {
self.y += self.speed;
// Zigzag movement pattern
self.zigzagTimer++;
if (self.zigzagTimer % 30 === 0) {
self.zigzagDirection *= -1;
}
self.x += self.zigzagDirection * 3;
// Keep within screen bounds
if (self.x < 100) {
self.x = 100;
self.zigzagDirection = 1;
}
if (self.x > 1948) {
self.x = 1948;
self.zigzagDirection = -1;
}
// Enhanced shooting - shoots 2 projectiles
if (self.shootCooldown <= 0) {
for (var i = 0; i < 2; i++) {
var projectile = new EnemyProjectile();
projectile.x = self.x + (i === 0 ? -20 : 20);
projectile.y = self.y + 40;
projectile.speed = 8; // Faster projectiles
game.addChild(projectile);
enemyProjectiles.push(projectile);
}
self.shootCooldown = Math.random() * 60 + 40;
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var OrangeAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('orangeAttack', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 2;
self.checkTimer = 0;
self.update = function () {
// Move towards player if direction is set, otherwise move straight down
if (self.dirX !== undefined && self.dirY !== undefined) {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
} else {
self.y += self.speed;
}
// Add pulsing orange effect
var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
attackGraphics.scaleX = pulse;
attackGraphics.scaleY = pulse;
};
return self;
});
var PlayerLaser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('playerLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
var chargeIndicator = self.attachAsset('chargeIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
chargeIndicator.x = 0;
chargeIndicator.y = -80;
chargeIndicator.visible = false;
self.health = 3;
self.shootCooldown = 0;
self.chargeAttackTime = 0;
self.isCharging = false;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.isCharging) {
self.chargeAttackTime++;
// Create pulsing animation while charging
var pulseIntensity = Math.min(self.chargeAttackTime / 60, 1); // 0 to 1
var pulseScale = 1 + Math.sin(LK.ticks * 0.3) * 0.15 * pulseIntensity;
self.scaleX = pulseScale;
self.scaleY = pulseScale;
// Add color tint that gets stronger as charge builds
var tintIntensity = Math.floor(pulseIntensity * 100);
self.tint = 0xFFFFFF + (tintIntensity << 8); // Add green tint
// When fully charged, show green square indicator
if (self.chargeAttackTime >= 60) {
var readyPulse = 1.2 + Math.sin(LK.ticks * 0.5) * 0.3;
self.scaleX = readyPulse;
self.scaleY = readyPulse;
self.tint = 0x00FF00; // Bright green when ready
chargeIndicator.visible = true;
}
} else {
// Reset scale and tint when not charging
self.scaleX = 1;
self.scaleY = 1;
self.tint = 0xFFFFFF;
chargeIndicator.visible = false;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
var laser;
// Create charged laser if charge time is sufficient
if (self.chargeAttackTime >= 60) {
laser = new ChargedPlayerLaser();
// Add spawn animation for charged laser
laser.scaleX = 0.3;
laser.scaleY = 0.3;
tween(laser, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
// Add tint effect
laser.tint = 0x00FF00;
tween(laser, {
tint: 0xFFFFFF
}, {
duration: 300
});
} else {
laser = new PlayerLaser();
}
laser.x = self.x;
laser.y = self.y - 60;
game.addChild(laser);
playerLasers.push(laser);
self.shootCooldown = 10;
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
self.health--;
LK.getSound('playerHit').play();
LK.effects.flashObject(self, 0xff0000, 500);
if (self.health <= 0) {
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
var player = new PlayerShip();
player.x = 2048 / 2;
player.y = 2732 - 200;
game.addChild(player);
var enemies = [];
var playerLasers = [];
var enemyProjectiles = [];
var spawnTimer = 0;
var gameSpeed = 1;
var playerShootCooldown = 0;
var isFireButtonPressed = false;
var bossActive = false;
var boss = null;
var bossProjectiles = [];
var bossLasers = [];
var bossWideLasers = [];
var orangeAttacks = [];
var cyanAttacks = [];
var playerLastX = 0;
var playerLastY = 0;
var playerIsMoving = false;
var gameLevel = 1;
var levelResetFlag = false;
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var healthTxt = new Text2('Health: 3', {
size: 60,
fill: 0xFF4444
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 150;
healthTxt.y = 50;
LK.gui.topLeft.addChild(healthTxt);
var fireButton = new Text2('FIRE', {
size: 120,
fill: 0x00FF00
});
fireButton.anchor.set(1, 0);
LK.gui.topRight.addChild(fireButton);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFF00
});
levelTxt.anchor.set(0.5, 0);
levelTxt.x = 0;
levelTxt.y = 150;
LK.gui.top.addChild(levelTxt);
var dragNode = null;
fireButton.down = function (x, y, obj) {
isFireButtonPressed = true;
player.isCharging = true;
player.chargeAttackTime = 0;
if (playerShootCooldown <= 0) {
player.shoot();
playerShootCooldown = 20;
}
};
fireButton.up = function (x, y, obj) {
isFireButtonPressed = false;
// Shoot charged laser if player was charging
if (player.isCharging && player.chargeAttackTime >= 60) {
if (playerShootCooldown <= 0) {
player.shoot();
playerShootCooldown = 20;
}
}
player.isCharging = false;
player.chargeAttackTime = 0;
};
game.down = function (x, y, obj) {
dragNode = player;
player.isCharging = true;
player.chargeAttackTime = 0;
if (playerShootCooldown <= 0) {
player.shoot();
playerShootCooldown = 20;
}
};
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(100, Math.min(1948, x));
}
};
game.up = function (x, y, obj) {
dragNode = null;
// Shoot charged laser if player was charging
if (player.isCharging && player.chargeAttackTime >= 60) {
if (playerShootCooldown <= 0) {
player.shoot();
playerShootCooldown = 20;
}
}
player.isCharging = false;
player.chargeAttackTime = 0;
};
game.update = function () {
// Update cooldown
if (playerShootCooldown > 0) {
playerShootCooldown--;
}
// Track player movement
var currentPlayerMoving = Math.abs(player.x - playerLastX) > 1 || Math.abs(player.y - playerLastY) > 1;
playerIsMoving = currentPlayerMoving;
playerLastX = player.x;
playerLastY = player.y;
// Update UI
scoreTxt.setText('Score: ' + LK.getScore());
healthTxt.setText('Health: ' + player.health);
levelTxt.setText('Level: ' + gameLevel);
// Show level indicator when level changes
if (levelResetFlag) {
LK.effects.flashScreen(0x00FF00, 800); // Green flash for level up
levelResetFlag = false;
}
// Boss spawn when player reaches score threshold based on level
var bossSpawnThreshold = 100 * gameLevel;
if (LK.getScore() >= bossSpawnThreshold && !bossActive) {
boss = new BossShip();
boss.x = 2048 / 2;
boss.y = 200;
// Scale boss health with level
boss.health = 10 + (gameLevel - 1) * 5;
boss.maxHealth = boss.health;
game.addChild(boss);
bossActive = true;
}
// Spawn regular enemies (only when boss is not active)
if (!bossActive) {
spawnTimer++;
var spawnRate = Math.max(120 - Math.floor(LK.getScore() / 10) * 10, 60);
if (spawnTimer >= spawnRate) {
var enemy;
// Spawn level 2 enemies if we're on level 2 or higher
if (gameLevel >= 2) {
// Mix of regular and level 2 enemies, with more level 2 enemies on higher levels
if (Math.random() < 0.7) {
enemy = new Level2EnemyShip();
} else {
enemy = new EnemyShip();
}
} else {
enemy = new EnemyShip();
}
enemy.x = Math.random() * 1848 + 100;
enemy.y = -50;
if (enemy.speed === undefined) {
enemy.speed = 6 + Math.floor(LK.getScore() / 15) * 1.5;
}
enemies.push(enemy);
game.addChild(enemy);
spawnTimer = 0;
}
}
// Update and check player lasers
for (var i = playerLasers.length - 1; i >= 0; i--) {
var laser = playerLasers[i];
if (laser.lastY === undefined) laser.lastY = laser.y;
// Remove lasers that go off screen
if (laser.lastY >= -50 && laser.y < -50) {
laser.destroy();
playerLasers.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
enemy.health -= laser.damage;
laser.destroy();
playerLasers.splice(i, 1);
hitEnemy = true;
if (enemy.health <= 0) {
LK.setScore(LK.getScore() + 10);
LK.getSound('enemyDestroy').play();
enemy.destroy();
enemies.splice(j, 1);
}
break;
}
}
// Check collision with boss
if (bossActive && boss && laser.intersects(boss)) {
var isChargedAttack = laser.damage > 1;
boss.takeDamage(laser.damage, isChargedAttack);
laser.destroy();
playerLasers.splice(i, 1);
hitEnemy = true;
}
if (!hitEnemy) {
laser.lastY = laser.y;
}
}
// Update and check enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that reach bottom
if (enemy.lastY <= 2732 && enemy.y > 2732) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
enemy.destroy();
enemies.splice(i, 1);
player.takeDamage();
continue;
}
enemy.lastY = enemy.y;
}
// Check boss collision with player
if (bossActive && boss && boss.intersects(player)) {
player.takeDamage();
player.takeDamage(); // Boss does double damage
}
// Update and check enemy projectiles
for (var i = enemyProjectiles.length - 1; i >= 0; i--) {
var projectile = enemyProjectiles[i];
if (projectile.lastY === undefined) projectile.lastY = projectile.y;
// Remove projectiles that go off screen
if (projectile.lastY <= 2732 && projectile.y > 2732) {
projectile.destroy();
enemyProjectiles.splice(i, 1);
continue;
}
// Check collision with player
if (projectile.intersects(player)) {
projectile.destroy();
enemyProjectiles.splice(i, 1);
// Enemy projectiles no longer cause damage - just destroy on contact
// Enhanced damage for boss projectiles
if (projectile.damage && projectile.damage > 1) {
// player.takeDamage();
// player.takeDamage();
} else {
// player.takeDamage();
}
continue;
}
projectile.lastY = projectile.y;
}
// Update and check boss projectiles
for (var i = bossProjectiles.length - 1; i >= 0; i--) {
var projectile = bossProjectiles[i];
// Remove projectiles if boss is dead or projectiles go too far
var shouldRemove = false;
if (!boss) {
shouldRemove = true;
} else {
var distanceFromBoss = Math.sqrt(Math.pow(projectile.x - boss.x, 2) + Math.pow(projectile.y - boss.y, 2));
shouldRemove = distanceFromBoss > 800;
}
if (shouldRemove || projectile.y > 2732 || projectile.y < -100 || projectile.x < -100 || projectile.x > 2148) {
projectile.destroy();
bossProjectiles.splice(i, 1);
continue;
}
// Check collision with player
if (projectile.intersects(player)) {
projectile.destroy();
bossProjectiles.splice(i, 1);
// Giant projectiles do massive damage
player.takeDamage();
player.takeDamage();
player.takeDamage();
continue;
}
}
// Update and check boss lasers
for (var i = bossLasers.length - 1; i >= 0; i--) {
var laser = bossLasers[i];
if (laser.lastY === undefined) laser.lastY = laser.y;
// Remove lasers that go off screen
if (laser.lastY <= 2732 && laser.y > 2732) {
laser.destroy();
bossLasers.splice(i, 1);
continue;
}
// Check collision with player
if (laser.intersects(player)) {
laser.destroy();
bossLasers.splice(i, 1);
player.takeDamage();
player.takeDamage(); // Boss lasers do double damage
continue;
}
laser.lastY = laser.y;
}
// Update and check boss wide lasers
for (var i = bossWideLasers.length - 1; i >= 0; i--) {
var laser = bossWideLasers[i];
if (laser.lastY === undefined) laser.lastY = laser.y;
// Remove lasers that go off screen
if (laser.lastY <= 2732 && laser.y > 2732) {
laser.destroy();
bossWideLasers.splice(i, 1);
continue;
}
// Check collision with player
if (laser.intersects(player)) {
laser.destroy();
bossWideLasers.splice(i, 1);
// Wide lasers do massive damage
player.takeDamage();
player.takeDamage();
player.takeDamage();
continue;
}
laser.lastY = laser.y;
}
// Update and check orange attacks
for (var i = orangeAttacks.length - 1; i >= 0; i--) {
var attack = orangeAttacks[i];
if (attack.lastY === undefined) attack.lastY = attack.y;
// Remove attacks that go off screen
if (attack.lastY <= 2732 && attack.y > 2732) {
attack.destroy();
orangeAttacks.splice(i, 1);
continue;
}
// Check collision with player - damage only when player is NOT moving
if (attack.intersects(player)) {
attack.destroy();
orangeAttacks.splice(i, 1);
// Orange attacks damage player when NOT moving
if (!playerIsMoving) {
player.takeDamage();
}
continue;
}
attack.lastY = attack.y;
}
// Update and check cyan attacks
for (var i = cyanAttacks.length - 1; i >= 0; i--) {
var attack = cyanAttacks[i];
if (attack.lastY === undefined) attack.lastY = attack.y;
// Remove attacks that go off screen
if (attack.lastY <= 2732 && attack.y > 2732) {
attack.destroy();
cyanAttacks.splice(i, 1);
continue;
}
// Check collision with player - damage only when player IS moving
if (attack.intersects(player)) {
attack.destroy();
cyanAttacks.splice(i, 1);
// Cyan attacks damage player when moving
if (playerIsMoving) {
player.takeDamage();
}
continue;
}
attack.lastY = attack.y;
}
};
Una nave de Star wars mirada desde arriba. In-Game asset. 2d. High contrast. No shadows
Ataque verde de Star wars mirada desde arriba llendo para adelante. In-Game asset. 2d. High contrast. No shadows
Meteorito llendo hacia abajo con el fuego arriba. In-Game asset. 2d. High contrast. No shadows
Explosión verde. In-Game asset. 2d. High contrast. No shadows
Star wars la estrella de la muerte. In-Game asset. 2d. High contrast. No shadows