/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
lastScore: 0
});
/****
* Classes
****/
var AlienShip = Container.expand(function () {
var self = Container.call(this);
self.shipGraphics = self.attachAsset('alienShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = -3;
self.speedY = 2;
self.health = 8;
self.score = 300;
self.shootTimer = 0;
self.shootInterval = 90; // 1.5 seconds at 60fps
self.directionChangeTimer = 0;
self.directionChangeInterval = 120; // 2 seconds
self.lastY = 0;
self.lastPlayerIntersecting = false;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Change direction periodically
self.directionChangeTimer++;
if (self.directionChangeTimer >= self.directionChangeInterval) {
self.speedY = -self.speedY;
self.directionChangeTimer = 0;
}
// Boundary checking
if (self.y <= 200) {
self.speedY = Math.abs(self.speedY);
} else if (self.y >= 2500) {
self.speedY = -Math.abs(self.speedY);
}
// Shooting logic - aim at player
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shootAtPlayer();
}
// Auto destroy when off screen
if (self.x < -150) {
self.destroy();
}
};
self.shootAtPlayer = function () {
if (!game || !game.player) {
return;
}
var speed = 12;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0x00ff00; // Green alien bullets
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
// Explosion effect
LK.getSound('explosion').play();
LK.effects.flashObject(self, 0xffffff, 300);
// Add score
game.increaseScore(self.score);
// Potentially drop powerup (25% chance)
if (Math.random() < 0.25) {
game.spawnPowerup(self.x, self.y);
}
self.destroy();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 20;
self.damage = 1;
self.isPlayerBullet = true;
self.update = function () {
self.x += self.speed;
// Auto destroy when off screen
if (self.x > 2148) {
self.destroy();
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = -5;
self.speedY = 0;
self.health = 5;
self.score = 100;
self.canShoot = false;
self.shootTimer = 0;
self.shootInterval = 120; // 2 seconds at 60fps
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Simple movement pattern
if (self.movePattern === 'sine') {
self.y += Math.sin(LK.ticks * 0.05) * 2;
} else if (self.movePattern === 'zigzag') {
if (LK.ticks % 60 === 0) {
self.speedY = -self.speedY || (Math.random() > 0.5 ? 3 : -3);
}
}
// Shooting logic
if (self.canShoot) {
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shoot();
}
}
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
self.shoot = function () {
if (!game) {
return;
}
var speed = 12;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0xff0000; // Red enemy bullets
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
// Explosion effect
LK.getSound('explosion').play();
LK.effects.flashObject(self, 0xffffff, 300);
// Add score
game.increaseScore(self.score);
// Potentially drop powerup (20% chance)
if (Math.random() < 0.2) {
game.spawnPowerup(self.x, self.y);
}
self.destroy();
}
};
return self;
});
var Boss = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with boss graphic
self.enemyGraphics.destroy();
self.enemyGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 75;
self.score = 2000;
self.speedX = -2;
self.canShoot = true;
self.shootInterval = 60; // 1 second at 60fps
self.phase = 1;
self.phaseTimer = 0;
self.isBoss = true;
// Override update function
self.update = function () {
self.phaseTimer++;
// Boss movement based on phases
if (self.phase === 1) {
// Enter the screen
if (self.x > 1600) {
self.x += self.speedX;
} else {
self.phase = 2;
self.phaseTimer = 0;
}
} else if (self.phase === 2) {
// Move up and down
self.y += Math.sin(self.phaseTimer * 0.03) * 4;
// Shooting pattern
if (self.phaseTimer % 20 === 0) {
self.shoot();
}
// Phase transition
if (self.phaseTimer > 300) {
self.phase = 3;
self.phaseTimer = 0;
}
} else if (self.phase === 3) {
// Charge at player
if (self.phaseTimer < 60) {
// Prepare
self.speedX = 0;
} else if (self.phaseTimer < 120) {
// Charge
self.x -= 15;
} else {
// Return to position
if (self.x < 1600) {
self.x += 5;
} else {
self.phase = 2;
self.phaseTimer = 0;
}
}
}
// Health-based phase changes
if (self.health < 25 && self.shootInterval > 40) {
self.shootInterval = 40; // Shoot faster when at low health
}
};
// Override shoot function for more complex patterns
self.shoot = function () {
if (!game) {
return;
}
var speed = 15;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x - 50;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0xff0000;
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
self.obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.update = function () {
self.x += self.speed;
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
self.playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.shield = 0;
self.weaponLevel = 1;
self.specialMeter = 0;
self.specialMax = 100;
self.shootCooldown = 0;
self.invulnerable = 0;
self.update = function () {
// Shooting cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Invulnerability frames
if (self.invulnerable > 0) {
self.invulnerable--;
// Flash effect during invulnerability
if (LK.ticks % 5 === 0) {
self.playerGraphics.alpha = self.playerGraphics.alpha === 1 ? 0.5 : 1;
}
} else {
self.playerGraphics.alpha = 1;
}
// Gentle hover effect
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
};
self.shoot = function () {
if (self.shootCooldown > 0) {
return;
}
LK.getSound('shoot').play();
var speed = 20;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: speed,
speedY: 0
},
// Right
{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
} // Left
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = true;
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.playerBullets.push(bullet);
}
self.shootCooldown = 10;
// Increase special meter slightly with each shot
self.specialMeter = Math.min(self.specialMeter + 1, self.specialMax);
game.updateSpecialMeter();
};
self.activateSpecial = function () {
if (self.specialMeter < self.specialMax) {
return;
}
LK.getSound('special').play();
// Create special attack
var special = new SpecialAttack();
special.x = self.x;
special.y = self.y;
game.addChild(special);
game.specialAttacks.push(special);
// Make player briefly invulnerable
self.invulnerable = 60;
// Reset special meter
self.specialMeter = 0;
game.updateSpecialMeter();
};
self.takeDamage = function () {
if (self.invulnerable > 0) {
return;
}
// Shield absorbs damage first
if (self.shield > 0) {
self.shield--;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0x3498db, 300); // Blue flash for shield hit
} else {
self.health--;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xff0000, 300); // Red flash for health hit
// Set invulnerability frames
self.invulnerable = 60;
// Game over check
if (self.health <= 0) {
// Store score
storage.lastScore = game.score;
if (game.score > storage.highScore) {
storage.highScore = game.score;
}
LK.showGameOver();
}
}
game.updateHealthDisplay();
};
self.collectPowerup = function (powerup) {
LK.getSound('powerup').play();
if (powerup.type === 'health') {
self.health = Math.min(self.health + 1, self.maxHealth);
} else if (powerup.type === 'shield') {
self.shield = Math.min(self.shield + 2, 3); // Max 3 shield points
} else if (powerup.type === 'weapon') {
self.weaponLevel = Math.min(self.weaponLevel + 1, 3);
} else if (powerup.type === 'special') {
self.specialMeter = self.specialMax; // Fill special meter
}
game.updateHealthDisplay();
game.updateSpecialMeter();
// Visual effect
LK.effects.flashObject(self, 0xffffff, 300);
};
// Touch/mouse controls
self.down = function (x, y, obj) {
game.isDragging = true;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -3;
self.type = 'health'; // Default power-up type
// Set color based on type
if (self.type === 'health') {
self.powerupGraphics.tint = 0x2ecc71; // Green
} else if (self.type === 'shield') {
self.powerupGraphics.tint = 0x3498db; // Blue
} else if (self.type === 'weapon') {
self.powerupGraphics.tint = 0xf1c40f; // Yellow
} else if (self.type === 'special') {
self.powerupGraphics.tint = 0x9b59b6; // Purple
}
self.update = function () {
self.x += self.speed;
// Gentle floating effect
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
return self;
});
var SpecialAttack = Container.expand(function () {
var self = Container.call(this);
self.attackGraphics = self.attachAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.duration = 60; // 1 second at 60fps
self.counter = 0;
self.damage = 5;
self.update = function () {
self.counter++;
self.x += 10;
// Flash effect
if (self.counter % 5 === 0) {
self.attackGraphics.alpha = self.attackGraphics.alpha === 0.7 ? 0.9 : 0.7;
}
// Auto destroy when duration ends
if (self.counter >= self.duration) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0e0e2a
});
/****
* Game Code
****/
// Game variables
game.score = 0;
game.level = 1;
game.waveTimer = 0;
game.bossActive = false;
game.spawnRate = 120; // Enemy spawn rate (frames)
game.isDragging = false;
game.autoShoot = true;
game.autoShootTimer = 0;
// Array containers for game objects
game.playerBullets = [];
game.enemyBullets = [];
game.enemies = [];
game.alienShips = [];
game.powerups = [];
game.obstacles = [];
game.specialAttacks = [];
// Create background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Create player
game.player = new Player();
game.player.x = 300;
game.player.y = 1366; // Center vertically
game.addChild(game.player);
// Create UI
// Score display
var scoreTxt = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create touch screen buttons for movement
var leftBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var rightBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var upBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 250,
y: 2400,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var downBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 250,
y: 2600,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
// Button event handlers
leftBtn.down = function () {
game.player.x = Math.max(85, game.player.x - 10);
};
rightBtn.down = function () {
game.player.x = Math.min(1963, game.player.x + 10);
};
upBtn.down = function () {
game.player.y = Math.max(85, game.player.y - 10);
};
downBtn.down = function () {
game.player.y = Math.min(2647, game.player.y + 10);
};
// Health display
var healthTxt = new Text2('HEALTH: 5', {
size: 60,
fill: 0x2ECC71
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 100;
LK.gui.addChild(healthTxt);
// Shield display
var shieldTxt = new Text2('SHIELD: 0', {
size: 60,
fill: 0x3498DB
});
shieldTxt.anchor.set(0, 0);
shieldTxt.x = 120;
shieldTxt.y = 170;
LK.gui.addChild(shieldTxt);
// Special meter
var specialTxt = new Text2('SPECIAL: 0%', {
size: 60,
fill: 0x9B59B6
});
specialTxt.anchor.set(0, 0);
specialTxt.x = 120;
specialTxt.y = 240;
LK.gui.addChild(specialTxt);
// Level display
var levelTxt = new Text2('LEVEL 1', {
size: 60,
fill: 0xF1C40F
});
levelTxt.anchor.set(1, 0);
levelTxt.x = -120;
levelTxt.y = 100;
LK.gui.right.addChild(levelTxt);
// Special attack button
var specialBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x9b59b6
}));
// Update UI functions
game.updateScoreDisplay = function () {
scoreTxt.setText('SCORE: ' + game.score);
};
game.updateHealthDisplay = function () {
healthTxt.setText('HEALTH: ' + game.player.health);
shieldTxt.setText('SHIELD: ' + game.player.shield);
};
game.updateSpecialMeter = function () {
var percentage = Math.floor(game.player.specialMeter / game.player.specialMax * 100);
specialTxt.setText('SPECIAL: ' + percentage + '%');
// Visual indication of special readiness
if (percentage >= 100) {
specialTxt.setStyle({
fill: 0xFFFFFF
});
tween(specialTxt, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(specialTxt, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
} else {
specialTxt.setStyle({
fill: 0x9B59B6
});
specialTxt.alpha = 1;
}
};
game.updateLevelDisplay = function () {
levelTxt.setText('LEVEL ' + game.level);
};
// Spawn functions
game.spawnEnemy = function (type) {
var enemy = new Enemy();
enemy.x = 2148; // Just off-screen to the right
enemy.y = 500 + Math.random() * 1400; // Random y position
// Configure enemy type
if (type === 'basic') {
enemy.movePattern = 'none';
enemy.canShoot = true; // Enable shooting for basic enemies
} else if (type === 'shooter') {
enemy.movePattern = 'none';
enemy.canShoot = true;
enemy.enemyGraphics.tint = 0xe67e22; // Orange
} else if (type === 'fast') {
enemy.movePattern = 'zigzag';
enemy.speedX = -10;
enemy.health = 2;
enemy.canShoot = true; // Enable shooting for fast enemies
enemy.enemyGraphics.tint = 0xe74c3c; // Red
} else if (type === 'tank') {
enemy.movePattern = 'sine';
enemy.speedX = -3;
enemy.health = 12;
enemy.score = 250;
enemy.canShoot = true; // Enable shooting for tank enemies
enemy.enemyGraphics.scaleX = 1.5;
enemy.enemyGraphics.scaleY = 1.5;
enemy.enemyGraphics.tint = 0x7f8c8d; // Gray
}
game.addChild(enemy);
game.enemies.push(enemy);
return enemy;
};
game.spawnBoss = function () {
// Only one boss at a time
if (game.bossActive) {
return;
}
game.bossActive = true;
var boss = new Boss();
boss.x = 2300; // Start off-screen
boss.y = 1366; // Center vertically
game.addChild(boss);
game.enemies.push(boss);
return boss;
};
game.spawnObstacle = function () {
var obstacle = new Obstacle();
obstacle.x = 2148; // Just off-screen to the right
obstacle.y = 400 + Math.random() * 1600; // Random y position
game.addChild(obstacle);
game.obstacles.push(obstacle);
return obstacle;
};
game.spawnAlienShip = function () {
var alienShip = new AlienShip();
alienShip.x = 2148; // Just off-screen to the right
alienShip.y = 300 + Math.random() * 1800; // Random y position
alienShip.lastY = alienShip.y;
alienShip.lastPlayerIntersecting = false;
game.addChild(alienShip);
game.alienShips.push(alienShip);
return alienShip;
};
game.spawnPowerup = function (x, y) {
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
// Random powerup type
var types = ['health', 'shield', 'weapon', 'special'];
var weights = [0.3, 0.3, 0.2, 0.2]; // Higher chance for health/shield
var total = 0;
var random = Math.random();
for (var i = 0; i < types.length; i++) {
total += weights[i];
if (random <= total) {
powerup.type = types[i];
break;
}
}
// Set color based on type
if (powerup.type === 'health') {
powerup.powerupGraphics.tint = 0x2ecc71; // Green
} else if (powerup.type === 'shield') {
powerup.powerupGraphics.tint = 0x3498db; // Blue
} else if (powerup.type === 'weapon') {
powerup.powerupGraphics.tint = 0xf1c40f; // Yellow
} else if (powerup.type === 'special') {
powerup.powerupGraphics.tint = 0x9b59b6; // Purple
}
game.addChild(powerup);
game.powerups.push(powerup);
return powerup;
};
// Score function
game.increaseScore = function (amount) {
game.score += amount;
game.updateScoreDisplay();
// Level up every 5000 points
if (game.score > 0 && game.score % 5000 === 0) {
game.levelUp();
}
};
game.levelUp = function () {
game.level++;
game.updateLevelDisplay();
// Spawn boss every 3 levels
if (game.level % 3 === 0) {
game.spawnBoss();
}
// Increase difficulty
game.spawnRate = Math.max(60, game.spawnRate - 10);
// Flash screen
LK.effects.flashScreen(0xf1c40f, 500); // Yellow flash
};
// Event handlers
game.down = function (x, y, obj) {
// Special button handling
if (obj === specialBtn && game.player.specialMeter >= game.player.specialMax) {
game.player.activateSpecial();
return;
}
// Player shooting
game.player.shoot();
// Start dragging
game.isDragging = true;
};
game.up = function (x, y, obj) {
game.isDragging = false;
};
game.move = function (x, y, obj) {
if (game.isDragging) {
// Calculate movement based on touchpad input
var deltaX = x - game.player.x;
var deltaY = y - game.player.y;
// Apply movement with a sensitivity factor
game.player.x += deltaX * 0.1;
game.player.y += deltaY * 0.1;
// Ensure player stays within screen bounds
game.player.x = Math.max(85, Math.min(game.player.x, 1963));
game.player.y = Math.max(85, Math.min(game.player.y, 2647));
}
};
// Main game update loop
game.update = function () {
// Auto-shooting
if (game.autoShoot) {
game.autoShootTimer++;
if (game.autoShootTimer >= 15) {
// Every 15 frames (4 times per second)
game.player.shoot();
game.autoShootTimer = 0;
}
}
// Spawn enemies based on timer
game.waveTimer++;
if (!game.bossActive && game.waveTimer >= game.spawnRate) {
game.waveTimer = 0;
// Different enemy types based on level
var types = ['basic'];
if (game.level >= 2) {
types.push('shooter');
}
if (game.level >= 3) {
types.push('fast');
}
if (game.level >= 5) {
types.push('tank');
}
// Spawn random enemy type
var type = types[Math.floor(Math.random() * types.length)];
game.spawnEnemy(type);
// Spawn alien ships (15% chance after level 4)
if (game.level >= 4 && Math.random() < 0.15) {
game.spawnAlienShip();
}
// Occasionally spawn obstacles (10% chance)
if (Math.random() < 0.1) {
game.spawnObstacle();
}
}
// Check boss status
if (game.bossActive) {
var bossStillActive = false;
for (var i = 0; i < game.enemies.length; i++) {
if (game.enemies[i].isBoss) {
bossStillActive = true;
break;
}
}
game.bossActive = bossStillActive;
}
// Check collisions
// Player bullets vs enemies
for (var i = game.playerBullets.length - 1; i >= 0; i--) {
var bullet = game.playerBullets[i];
// Skip destroyed bullets
if (!bullet.parent) {
game.playerBullets.splice(i, 1);
continue;
}
for (var j = game.enemies.length - 1; j >= 0; j--) {
var enemy = game.enemies[j];
// Skip destroyed enemies
if (!enemy.parent) {
game.enemies.splice(j, 1);
continue;
}
if (bullet.intersects(enemy)) {
enemy.takeDamage(bullet.damage);
bullet.destroy();
game.playerBullets.splice(i, 1);
break;
}
}
// Check alien ships
for (var j = game.alienShips.length - 1; j >= 0; j--) {
var alienShip = game.alienShips[j];
// Skip destroyed alien ships
if (!alienShip.parent) {
game.alienShips.splice(j, 1);
continue;
}
if (bullet.intersects(alienShip)) {
alienShip.takeDamage(bullet.damage);
bullet.destroy();
game.playerBullets.splice(i, 1);
break;
}
}
}
// Special attacks vs enemies
for (var i = game.specialAttacks.length - 1; i >= 0; i--) {
var special = game.specialAttacks[i];
// Skip destroyed specials
if (!special.parent) {
game.specialAttacks.splice(i, 1);
continue;
}
for (var j = game.enemies.length - 1; j >= 0; j--) {
var enemy = game.enemies[j];
// Skip destroyed enemies
if (!enemy.parent) {
game.enemies.splice(j, 1);
continue;
}
if (special.intersects(enemy)) {
enemy.takeDamage(special.damage);
}
}
// Special vs alien ships
for (var j = game.alienShips.length - 1; j >= 0; j--) {
var alienShip = game.alienShips[j];
// Skip destroyed alien ships
if (!alienShip.parent) {
game.alienShips.splice(j, 1);
continue;
}
if (special.intersects(alienShip)) {
alienShip.takeDamage(special.damage);
}
}
// Special clears enemy bullets too
for (var j = game.enemyBullets.length - 1; j >= 0; j--) {
var bullet = game.enemyBullets[j];
// Skip destroyed bullets
if (!bullet.parent) {
game.enemyBullets.splice(j, 1);
continue;
}
if (special.intersects(bullet)) {
bullet.destroy();
game.enemyBullets.splice(j, 1);
}
}
}
// Enemy bullets vs player
for (var i = game.enemyBullets.length - 1; i >= 0; i--) {
var bullet = game.enemyBullets[i];
// Skip destroyed bullets
if (!bullet.parent) {
game.enemyBullets.splice(i, 1);
continue;
}
if (bullet.intersects(game.player)) {
game.player.takeDamage();
bullet.destroy();
game.enemyBullets.splice(i, 1);
}
}
// Obstacles vs player
for (var i = game.obstacles.length - 1; i >= 0; i--) {
var obstacle = game.obstacles[i];
// Skip destroyed obstacles
if (!obstacle.parent) {
game.obstacles.splice(i, 1);
continue;
}
if (obstacle.intersects(game.player)) {
game.player.takeDamage();
obstacle.destroy();
game.obstacles.splice(i, 1);
}
}
// Powerups vs player
for (var i = game.powerups.length - 1; i >= 0; i--) {
var powerup = game.powerups[i];
// Skip destroyed powerups
if (!powerup.parent) {
game.powerups.splice(i, 1);
continue;
}
if (powerup.intersects(game.player)) {
game.player.collectPowerup(powerup);
powerup.destroy();
game.powerups.splice(i, 1);
}
}
// Remove destroyed enemies from array
for (var i = game.enemies.length - 1; i >= 0; i--) {
if (!game.enemies[i].parent) {
game.enemies.splice(i, 1);
}
}
// Update arrays of objects that might be removed
game.playerBullets = game.playerBullets.filter(function (bullet) {
return bullet.parent !== null;
});
game.enemyBullets = game.enemyBullets.filter(function (bullet) {
return bullet.parent !== null;
});
game.obstacles = game.obstacles.filter(function (obstacle) {
return obstacle.parent !== null;
});
game.powerups = game.powerups.filter(function (powerup) {
return powerup.parent !== null;
});
game.specialAttacks = game.specialAttacks.filter(function (special) {
return special.parent !== null;
});
game.alienShips = game.alienShips.filter(function (alienShip) {
return alienShip.parent !== null;
});
// Static background - no scrolling
};
// Initialize displays
game.updateScoreDisplay();
game.updateHealthDisplay();
game.updateSpecialMeter();
game.updateLevelDisplay();
// Start background music
LK.playMusic('bgm'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
lastScore: 0
});
/****
* Classes
****/
var AlienShip = Container.expand(function () {
var self = Container.call(this);
self.shipGraphics = self.attachAsset('alienShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = -3;
self.speedY = 2;
self.health = 8;
self.score = 300;
self.shootTimer = 0;
self.shootInterval = 90; // 1.5 seconds at 60fps
self.directionChangeTimer = 0;
self.directionChangeInterval = 120; // 2 seconds
self.lastY = 0;
self.lastPlayerIntersecting = false;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Change direction periodically
self.directionChangeTimer++;
if (self.directionChangeTimer >= self.directionChangeInterval) {
self.speedY = -self.speedY;
self.directionChangeTimer = 0;
}
// Boundary checking
if (self.y <= 200) {
self.speedY = Math.abs(self.speedY);
} else if (self.y >= 2500) {
self.speedY = -Math.abs(self.speedY);
}
// Shooting logic - aim at player
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shootAtPlayer();
}
// Auto destroy when off screen
if (self.x < -150) {
self.destroy();
}
};
self.shootAtPlayer = function () {
if (!game || !game.player) {
return;
}
var speed = 12;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0x00ff00; // Green alien bullets
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
// Explosion effect
LK.getSound('explosion').play();
LK.effects.flashObject(self, 0xffffff, 300);
// Add score
game.increaseScore(self.score);
// Potentially drop powerup (25% chance)
if (Math.random() < 0.25) {
game.spawnPowerup(self.x, self.y);
}
self.destroy();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 20;
self.damage = 1;
self.isPlayerBullet = true;
self.update = function () {
self.x += self.speed;
// Auto destroy when off screen
if (self.x > 2148) {
self.destroy();
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = -5;
self.speedY = 0;
self.health = 5;
self.score = 100;
self.canShoot = false;
self.shootTimer = 0;
self.shootInterval = 120; // 2 seconds at 60fps
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Simple movement pattern
if (self.movePattern === 'sine') {
self.y += Math.sin(LK.ticks * 0.05) * 2;
} else if (self.movePattern === 'zigzag') {
if (LK.ticks % 60 === 0) {
self.speedY = -self.speedY || (Math.random() > 0.5 ? 3 : -3);
}
}
// Shooting logic
if (self.canShoot) {
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shoot();
}
}
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
self.shoot = function () {
if (!game) {
return;
}
var speed = 12;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0xff0000; // Red enemy bullets
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
// Explosion effect
LK.getSound('explosion').play();
LK.effects.flashObject(self, 0xffffff, 300);
// Add score
game.increaseScore(self.score);
// Potentially drop powerup (20% chance)
if (Math.random() < 0.2) {
game.spawnPowerup(self.x, self.y);
}
self.destroy();
}
};
return self;
});
var Boss = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with boss graphic
self.enemyGraphics.destroy();
self.enemyGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 75;
self.score = 2000;
self.speedX = -2;
self.canShoot = true;
self.shootInterval = 60; // 1 second at 60fps
self.phase = 1;
self.phaseTimer = 0;
self.isBoss = true;
// Override update function
self.update = function () {
self.phaseTimer++;
// Boss movement based on phases
if (self.phase === 1) {
// Enter the screen
if (self.x > 1600) {
self.x += self.speedX;
} else {
self.phase = 2;
self.phaseTimer = 0;
}
} else if (self.phase === 2) {
// Move up and down
self.y += Math.sin(self.phaseTimer * 0.03) * 4;
// Shooting pattern
if (self.phaseTimer % 20 === 0) {
self.shoot();
}
// Phase transition
if (self.phaseTimer > 300) {
self.phase = 3;
self.phaseTimer = 0;
}
} else if (self.phase === 3) {
// Charge at player
if (self.phaseTimer < 60) {
// Prepare
self.speedX = 0;
} else if (self.phaseTimer < 120) {
// Charge
self.x -= 15;
} else {
// Return to position
if (self.x < 1600) {
self.x += 5;
} else {
self.phase = 2;
self.phaseTimer = 0;
}
}
}
// Health-based phase changes
if (self.health < 25 && self.shootInterval > 40) {
self.shootInterval = 40; // Shoot faster when at low health
}
};
// Override shoot function for more complex patterns
self.shoot = function () {
if (!game) {
return;
}
var speed = 15;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
},
// Left
{
speedX: speed,
speedY: 0
} // Right
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x - 50;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = false;
bullet.bulletGraphics.tint = 0xff0000;
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.enemyBullets.push(bullet);
}
LK.getSound('shoot').play();
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
self.obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.update = function () {
self.x += self.speed;
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
self.playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.shield = 0;
self.weaponLevel = 1;
self.specialMeter = 0;
self.specialMax = 100;
self.shootCooldown = 0;
self.invulnerable = 0;
self.update = function () {
// Shooting cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Invulnerability frames
if (self.invulnerable > 0) {
self.invulnerable--;
// Flash effect during invulnerability
if (LK.ticks % 5 === 0) {
self.playerGraphics.alpha = self.playerGraphics.alpha === 1 ? 0.5 : 1;
}
} else {
self.playerGraphics.alpha = 1;
}
// Gentle hover effect
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
};
self.shoot = function () {
if (self.shootCooldown > 0) {
return;
}
LK.getSound('shoot').play();
var speed = 20;
// Create bullets in four directions: up, down, left, right
var directions = [{
speedX: speed,
speedY: 0
},
// Right
{
speedX: 0,
speedY: -speed
},
// Up
{
speedX: 0,
speedY: speed
},
// Down
{
speedX: -speed,
speedY: 0
} // Left
];
for (var i = 0; i < directions.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = directions[i].speedX;
bullet.speedY = directions[i].speedY;
bullet.isPlayerBullet = true;
// Custom update for four-directional movement
bullet.update = function () {
this.x += this.speed;
this.y += this.speedY;
// Off screen check
if (this.x < -100 || this.y < -100 || this.y > 2832 || this.x > 2148) {
this.destroy();
}
};
game.addChild(bullet);
game.playerBullets.push(bullet);
}
self.shootCooldown = 10;
// Increase special meter slightly with each shot
self.specialMeter = Math.min(self.specialMeter + 1, self.specialMax);
game.updateSpecialMeter();
};
self.activateSpecial = function () {
if (self.specialMeter < self.specialMax) {
return;
}
LK.getSound('special').play();
// Create special attack
var special = new SpecialAttack();
special.x = self.x;
special.y = self.y;
game.addChild(special);
game.specialAttacks.push(special);
// Make player briefly invulnerable
self.invulnerable = 60;
// Reset special meter
self.specialMeter = 0;
game.updateSpecialMeter();
};
self.takeDamage = function () {
if (self.invulnerable > 0) {
return;
}
// Shield absorbs damage first
if (self.shield > 0) {
self.shield--;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0x3498db, 300); // Blue flash for shield hit
} else {
self.health--;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xff0000, 300); // Red flash for health hit
// Set invulnerability frames
self.invulnerable = 60;
// Game over check
if (self.health <= 0) {
// Store score
storage.lastScore = game.score;
if (game.score > storage.highScore) {
storage.highScore = game.score;
}
LK.showGameOver();
}
}
game.updateHealthDisplay();
};
self.collectPowerup = function (powerup) {
LK.getSound('powerup').play();
if (powerup.type === 'health') {
self.health = Math.min(self.health + 1, self.maxHealth);
} else if (powerup.type === 'shield') {
self.shield = Math.min(self.shield + 2, 3); // Max 3 shield points
} else if (powerup.type === 'weapon') {
self.weaponLevel = Math.min(self.weaponLevel + 1, 3);
} else if (powerup.type === 'special') {
self.specialMeter = self.specialMax; // Fill special meter
}
game.updateHealthDisplay();
game.updateSpecialMeter();
// Visual effect
LK.effects.flashObject(self, 0xffffff, 300);
};
// Touch/mouse controls
self.down = function (x, y, obj) {
game.isDragging = true;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -3;
self.type = 'health'; // Default power-up type
// Set color based on type
if (self.type === 'health') {
self.powerupGraphics.tint = 0x2ecc71; // Green
} else if (self.type === 'shield') {
self.powerupGraphics.tint = 0x3498db; // Blue
} else if (self.type === 'weapon') {
self.powerupGraphics.tint = 0xf1c40f; // Yellow
} else if (self.type === 'special') {
self.powerupGraphics.tint = 0x9b59b6; // Purple
}
self.update = function () {
self.x += self.speed;
// Gentle floating effect
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Auto destroy when off screen
if (self.x < -100) {
self.destroy();
}
};
return self;
});
var SpecialAttack = Container.expand(function () {
var self = Container.call(this);
self.attackGraphics = self.attachAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.duration = 60; // 1 second at 60fps
self.counter = 0;
self.damage = 5;
self.update = function () {
self.counter++;
self.x += 10;
// Flash effect
if (self.counter % 5 === 0) {
self.attackGraphics.alpha = self.attackGraphics.alpha === 0.7 ? 0.9 : 0.7;
}
// Auto destroy when duration ends
if (self.counter >= self.duration) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0e0e2a
});
/****
* Game Code
****/
// Game variables
game.score = 0;
game.level = 1;
game.waveTimer = 0;
game.bossActive = false;
game.spawnRate = 120; // Enemy spawn rate (frames)
game.isDragging = false;
game.autoShoot = true;
game.autoShootTimer = 0;
// Array containers for game objects
game.playerBullets = [];
game.enemyBullets = [];
game.enemies = [];
game.alienShips = [];
game.powerups = [];
game.obstacles = [];
game.specialAttacks = [];
// Create background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Create player
game.player = new Player();
game.player.x = 300;
game.player.y = 1366; // Center vertically
game.addChild(game.player);
// Create UI
// Score display
var scoreTxt = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create touch screen buttons for movement
var leftBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var rightBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var upBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 250,
y: 2400,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
var downBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 250,
y: 2600,
scaleX: 2,
scaleY: 2,
tint: 0x3498db
}));
// Button event handlers
leftBtn.down = function () {
game.player.x = Math.max(85, game.player.x - 10);
};
rightBtn.down = function () {
game.player.x = Math.min(1963, game.player.x + 10);
};
upBtn.down = function () {
game.player.y = Math.max(85, game.player.y - 10);
};
downBtn.down = function () {
game.player.y = Math.min(2647, game.player.y + 10);
};
// Health display
var healthTxt = new Text2('HEALTH: 5', {
size: 60,
fill: 0x2ECC71
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 100;
LK.gui.addChild(healthTxt);
// Shield display
var shieldTxt = new Text2('SHIELD: 0', {
size: 60,
fill: 0x3498DB
});
shieldTxt.anchor.set(0, 0);
shieldTxt.x = 120;
shieldTxt.y = 170;
LK.gui.addChild(shieldTxt);
// Special meter
var specialTxt = new Text2('SPECIAL: 0%', {
size: 60,
fill: 0x9B59B6
});
specialTxt.anchor.set(0, 0);
specialTxt.x = 120;
specialTxt.y = 240;
LK.gui.addChild(specialTxt);
// Level display
var levelTxt = new Text2('LEVEL 1', {
size: 60,
fill: 0xF1C40F
});
levelTxt.anchor.set(1, 0);
levelTxt.x = -120;
levelTxt.y = 100;
LK.gui.right.addChild(levelTxt);
// Special attack button
var specialBtn = game.addChild(LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 2500,
scaleX: 2,
scaleY: 2,
tint: 0x9b59b6
}));
// Update UI functions
game.updateScoreDisplay = function () {
scoreTxt.setText('SCORE: ' + game.score);
};
game.updateHealthDisplay = function () {
healthTxt.setText('HEALTH: ' + game.player.health);
shieldTxt.setText('SHIELD: ' + game.player.shield);
};
game.updateSpecialMeter = function () {
var percentage = Math.floor(game.player.specialMeter / game.player.specialMax * 100);
specialTxt.setText('SPECIAL: ' + percentage + '%');
// Visual indication of special readiness
if (percentage >= 100) {
specialTxt.setStyle({
fill: 0xFFFFFF
});
tween(specialTxt, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(specialTxt, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
} else {
specialTxt.setStyle({
fill: 0x9B59B6
});
specialTxt.alpha = 1;
}
};
game.updateLevelDisplay = function () {
levelTxt.setText('LEVEL ' + game.level);
};
// Spawn functions
game.spawnEnemy = function (type) {
var enemy = new Enemy();
enemy.x = 2148; // Just off-screen to the right
enemy.y = 500 + Math.random() * 1400; // Random y position
// Configure enemy type
if (type === 'basic') {
enemy.movePattern = 'none';
enemy.canShoot = true; // Enable shooting for basic enemies
} else if (type === 'shooter') {
enemy.movePattern = 'none';
enemy.canShoot = true;
enemy.enemyGraphics.tint = 0xe67e22; // Orange
} else if (type === 'fast') {
enemy.movePattern = 'zigzag';
enemy.speedX = -10;
enemy.health = 2;
enemy.canShoot = true; // Enable shooting for fast enemies
enemy.enemyGraphics.tint = 0xe74c3c; // Red
} else if (type === 'tank') {
enemy.movePattern = 'sine';
enemy.speedX = -3;
enemy.health = 12;
enemy.score = 250;
enemy.canShoot = true; // Enable shooting for tank enemies
enemy.enemyGraphics.scaleX = 1.5;
enemy.enemyGraphics.scaleY = 1.5;
enemy.enemyGraphics.tint = 0x7f8c8d; // Gray
}
game.addChild(enemy);
game.enemies.push(enemy);
return enemy;
};
game.spawnBoss = function () {
// Only one boss at a time
if (game.bossActive) {
return;
}
game.bossActive = true;
var boss = new Boss();
boss.x = 2300; // Start off-screen
boss.y = 1366; // Center vertically
game.addChild(boss);
game.enemies.push(boss);
return boss;
};
game.spawnObstacle = function () {
var obstacle = new Obstacle();
obstacle.x = 2148; // Just off-screen to the right
obstacle.y = 400 + Math.random() * 1600; // Random y position
game.addChild(obstacle);
game.obstacles.push(obstacle);
return obstacle;
};
game.spawnAlienShip = function () {
var alienShip = new AlienShip();
alienShip.x = 2148; // Just off-screen to the right
alienShip.y = 300 + Math.random() * 1800; // Random y position
alienShip.lastY = alienShip.y;
alienShip.lastPlayerIntersecting = false;
game.addChild(alienShip);
game.alienShips.push(alienShip);
return alienShip;
};
game.spawnPowerup = function (x, y) {
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
// Random powerup type
var types = ['health', 'shield', 'weapon', 'special'];
var weights = [0.3, 0.3, 0.2, 0.2]; // Higher chance for health/shield
var total = 0;
var random = Math.random();
for (var i = 0; i < types.length; i++) {
total += weights[i];
if (random <= total) {
powerup.type = types[i];
break;
}
}
// Set color based on type
if (powerup.type === 'health') {
powerup.powerupGraphics.tint = 0x2ecc71; // Green
} else if (powerup.type === 'shield') {
powerup.powerupGraphics.tint = 0x3498db; // Blue
} else if (powerup.type === 'weapon') {
powerup.powerupGraphics.tint = 0xf1c40f; // Yellow
} else if (powerup.type === 'special') {
powerup.powerupGraphics.tint = 0x9b59b6; // Purple
}
game.addChild(powerup);
game.powerups.push(powerup);
return powerup;
};
// Score function
game.increaseScore = function (amount) {
game.score += amount;
game.updateScoreDisplay();
// Level up every 5000 points
if (game.score > 0 && game.score % 5000 === 0) {
game.levelUp();
}
};
game.levelUp = function () {
game.level++;
game.updateLevelDisplay();
// Spawn boss every 3 levels
if (game.level % 3 === 0) {
game.spawnBoss();
}
// Increase difficulty
game.spawnRate = Math.max(60, game.spawnRate - 10);
// Flash screen
LK.effects.flashScreen(0xf1c40f, 500); // Yellow flash
};
// Event handlers
game.down = function (x, y, obj) {
// Special button handling
if (obj === specialBtn && game.player.specialMeter >= game.player.specialMax) {
game.player.activateSpecial();
return;
}
// Player shooting
game.player.shoot();
// Start dragging
game.isDragging = true;
};
game.up = function (x, y, obj) {
game.isDragging = false;
};
game.move = function (x, y, obj) {
if (game.isDragging) {
// Calculate movement based on touchpad input
var deltaX = x - game.player.x;
var deltaY = y - game.player.y;
// Apply movement with a sensitivity factor
game.player.x += deltaX * 0.1;
game.player.y += deltaY * 0.1;
// Ensure player stays within screen bounds
game.player.x = Math.max(85, Math.min(game.player.x, 1963));
game.player.y = Math.max(85, Math.min(game.player.y, 2647));
}
};
// Main game update loop
game.update = function () {
// Auto-shooting
if (game.autoShoot) {
game.autoShootTimer++;
if (game.autoShootTimer >= 15) {
// Every 15 frames (4 times per second)
game.player.shoot();
game.autoShootTimer = 0;
}
}
// Spawn enemies based on timer
game.waveTimer++;
if (!game.bossActive && game.waveTimer >= game.spawnRate) {
game.waveTimer = 0;
// Different enemy types based on level
var types = ['basic'];
if (game.level >= 2) {
types.push('shooter');
}
if (game.level >= 3) {
types.push('fast');
}
if (game.level >= 5) {
types.push('tank');
}
// Spawn random enemy type
var type = types[Math.floor(Math.random() * types.length)];
game.spawnEnemy(type);
// Spawn alien ships (15% chance after level 4)
if (game.level >= 4 && Math.random() < 0.15) {
game.spawnAlienShip();
}
// Occasionally spawn obstacles (10% chance)
if (Math.random() < 0.1) {
game.spawnObstacle();
}
}
// Check boss status
if (game.bossActive) {
var bossStillActive = false;
for (var i = 0; i < game.enemies.length; i++) {
if (game.enemies[i].isBoss) {
bossStillActive = true;
break;
}
}
game.bossActive = bossStillActive;
}
// Check collisions
// Player bullets vs enemies
for (var i = game.playerBullets.length - 1; i >= 0; i--) {
var bullet = game.playerBullets[i];
// Skip destroyed bullets
if (!bullet.parent) {
game.playerBullets.splice(i, 1);
continue;
}
for (var j = game.enemies.length - 1; j >= 0; j--) {
var enemy = game.enemies[j];
// Skip destroyed enemies
if (!enemy.parent) {
game.enemies.splice(j, 1);
continue;
}
if (bullet.intersects(enemy)) {
enemy.takeDamage(bullet.damage);
bullet.destroy();
game.playerBullets.splice(i, 1);
break;
}
}
// Check alien ships
for (var j = game.alienShips.length - 1; j >= 0; j--) {
var alienShip = game.alienShips[j];
// Skip destroyed alien ships
if (!alienShip.parent) {
game.alienShips.splice(j, 1);
continue;
}
if (bullet.intersects(alienShip)) {
alienShip.takeDamage(bullet.damage);
bullet.destroy();
game.playerBullets.splice(i, 1);
break;
}
}
}
// Special attacks vs enemies
for (var i = game.specialAttacks.length - 1; i >= 0; i--) {
var special = game.specialAttacks[i];
// Skip destroyed specials
if (!special.parent) {
game.specialAttacks.splice(i, 1);
continue;
}
for (var j = game.enemies.length - 1; j >= 0; j--) {
var enemy = game.enemies[j];
// Skip destroyed enemies
if (!enemy.parent) {
game.enemies.splice(j, 1);
continue;
}
if (special.intersects(enemy)) {
enemy.takeDamage(special.damage);
}
}
// Special vs alien ships
for (var j = game.alienShips.length - 1; j >= 0; j--) {
var alienShip = game.alienShips[j];
// Skip destroyed alien ships
if (!alienShip.parent) {
game.alienShips.splice(j, 1);
continue;
}
if (special.intersects(alienShip)) {
alienShip.takeDamage(special.damage);
}
}
// Special clears enemy bullets too
for (var j = game.enemyBullets.length - 1; j >= 0; j--) {
var bullet = game.enemyBullets[j];
// Skip destroyed bullets
if (!bullet.parent) {
game.enemyBullets.splice(j, 1);
continue;
}
if (special.intersects(bullet)) {
bullet.destroy();
game.enemyBullets.splice(j, 1);
}
}
}
// Enemy bullets vs player
for (var i = game.enemyBullets.length - 1; i >= 0; i--) {
var bullet = game.enemyBullets[i];
// Skip destroyed bullets
if (!bullet.parent) {
game.enemyBullets.splice(i, 1);
continue;
}
if (bullet.intersects(game.player)) {
game.player.takeDamage();
bullet.destroy();
game.enemyBullets.splice(i, 1);
}
}
// Obstacles vs player
for (var i = game.obstacles.length - 1; i >= 0; i--) {
var obstacle = game.obstacles[i];
// Skip destroyed obstacles
if (!obstacle.parent) {
game.obstacles.splice(i, 1);
continue;
}
if (obstacle.intersects(game.player)) {
game.player.takeDamage();
obstacle.destroy();
game.obstacles.splice(i, 1);
}
}
// Powerups vs player
for (var i = game.powerups.length - 1; i >= 0; i--) {
var powerup = game.powerups[i];
// Skip destroyed powerups
if (!powerup.parent) {
game.powerups.splice(i, 1);
continue;
}
if (powerup.intersects(game.player)) {
game.player.collectPowerup(powerup);
powerup.destroy();
game.powerups.splice(i, 1);
}
}
// Remove destroyed enemies from array
for (var i = game.enemies.length - 1; i >= 0; i--) {
if (!game.enemies[i].parent) {
game.enemies.splice(i, 1);
}
}
// Update arrays of objects that might be removed
game.playerBullets = game.playerBullets.filter(function (bullet) {
return bullet.parent !== null;
});
game.enemyBullets = game.enemyBullets.filter(function (bullet) {
return bullet.parent !== null;
});
game.obstacles = game.obstacles.filter(function (obstacle) {
return obstacle.parent !== null;
});
game.powerups = game.powerups.filter(function (powerup) {
return powerup.parent !== null;
});
game.specialAttacks = game.specialAttacks.filter(function (special) {
return special.parent !== null;
});
game.alienShips = game.alienShips.filter(function (alienShip) {
return alienShip.parent !== null;
});
// Static background - no scrolling
};
// Initialize displays
game.updateScoreDisplay();
game.updateHealthDisplay();
game.updateSpecialMeter();
game.updateLevelDisplay();
// Start background music
LK.playMusic('bgm');
red robot look like gundam shoot enemy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
amazing gold stone. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
horizontal branch of red light thunder anime style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
black hole with evil face. anime style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
green crab style alien ship. side scroller image. In-Game asset. 2d. High contrast. No shadows
panorame wied gambar hutan tropis pegunungan dan langit biru cerah gaya anime vinland saga
bio green living asteroid. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
ancient flyng red slime with talasophobia texture