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