/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, shipColor: 3447003 }); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); // Type: 0 = basic, 1 = shooter, 2 = fast self.type = 0; self.health = 1; self.points = 100; self.moveSpeed = 2; self.shotFrequency = 120; // frames between shots self.shotCounter = Math.floor(Math.random() * 60); // Random initial delay self.init = function (type) { self.type = type || 0; if (self.type === 0) { // Basic enemy enemyGraphics.tint = 0xe74c3c; self.health = 1; self.points = 100; self.moveSpeed = 2; self.shotFrequency = 0; // Doesn't shoot } else if (self.type === 1) { // Shooter enemy enemyGraphics.tint = 0xf39c12; self.health = 2; self.points = 200; self.moveSpeed = 1; self.shotFrequency = 120; } else if (self.type === 2) { // Fast enemy enemyGraphics.tint = 0x9b59b6; self.health = 1; self.points = 150; self.moveSpeed = 4; self.shotFrequency = 0; } return self; }; self.movePattern = function () { // Default movement pattern self.y += self.moveSpeed; if (self.type === 2) { // Fast enemy zigzags self.x += Math.sin(LK.ticks / 10) * 5; } }; self.tryShoot = function () { if (self.shotFrequency === 0) { return null; } self.shotCounter++; if (self.shotCounter >= self.shotFrequency) { self.shotCounter = 0; return true; } return false; }; self.takeDamage = function (amount) { self.health -= amount; // Flash red when hit tween(enemyGraphics, { tint: 0xff0000 }, { duration: 100, onFinish: function onFinish() { if (self.type === 0) { tween(enemyGraphics, { tint: 0xe74c3c }, { duration: 100 }); } else if (self.type === 1) { tween(enemyGraphics, { tint: 0xf39c12 }, { duration: 100 }); } else if (self.type === 2) { tween(enemyGraphics, { tint: 0x9b59b6 }, { duration: 100 }); } } }); return self.health <= 0; }; self.update = function () { self.movePattern(); }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.power = 1; self.update = function () { self.y += self.speed; }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphics = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); self.lifespan = 30; // frames self.update = function () { self.lifespan--; if (self.lifespan <= 0) { self.destroy(); return; } // Gradually fade out and expand explosionGraphics.alpha = self.lifespan / 30; explosionGraphics.scale.x = 1 + (1 - self.lifespan / 30) * 2; explosionGraphics.scale.y = 1 + (1 - self.lifespan / 30) * 2; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); // Set the ship color from storage if available playerGraphics.tint = storage.shipColor || 0x3498db; self.lives = 3; self.score = 0; self.fireRate = 15; // frames between shots self.fireCounter = 0; self.doubleFire = false; self.doubleFireduration = 0; self.shield = false; self.shieldDuration = 0; self.invulnerable = false; self.invulnerableDuration = 0; // Shield visual var shieldGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5, alpha: 0, tint: 0x3498db, scaleX: 1.5, scaleY: 1.5 }); self.canFire = function () { self.fireCounter++; if (self.fireCounter >= self.fireRate) { self.fireCounter = 0; return true; } return false; }; self.takeDamage = function () { if (self.invulnerable || self.shield) { if (self.shield) { // Remove shield instead of taking damage self.shield = false; shieldGraphics.alpha = 0; // Flash effect LK.effects.flashObject(self, 0x3498db, 500); } return false; } self.lives--; // Become temporarily invulnerable self.invulnerable = true; self.invulnerableDuration = 90; // 1.5 seconds // Flash effect LK.effects.flashObject(self, 0xff0000, 500); return self.lives <= 0; }; self.applyPowerUp = function (type) { if (type === 0) { // Double fire self.doubleFire = true; self.doubleFireduration = 300; // 5 seconds } else if (type === 1) { // Shield self.shield = true; shieldGraphics.alpha = 0.7; self.shieldDuration = 300; // 5 seconds } else if (type === 2) { // Extra life self.lives++; } }; self.update = function () { // Update power-ups durations if (self.doubleFire) { self.doubleFireduration--; if (self.doubleFireduration <= 0) { self.doubleFire = false; } } if (self.shield) { self.shieldDuration--; if (self.shieldDuration <= 0) { self.shield = false; shieldGraphics.alpha = 0; } else { // Pulsate shield shieldGraphics.alpha = 0.5 + Math.sin(LK.ticks / 10) * 0.2; } } if (self.invulnerable) { self.invulnerableDuration--; if (self.invulnerableDuration <= 0) { self.invulnerable = false; } // Blink when invulnerable self.alpha = Math.floor(LK.ticks / 5) % 2 ? 0.5 : 1; } else { self.alpha = 1; } }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.power = 1; self.update = function () { self.y += self.speed; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); // PowerUp types: 0 = double fire, 1 = shield, 2 = extra life self.type = Math.floor(Math.random() * 3); // Set color based on type if (self.type === 0) { powerUpGraphics.tint = 0xff5500; // orange for double fire } else if (self.type === 1) { powerUpGraphics.tint = 0x3498db; // blue for shield } else { powerUpGraphics.tint = 0x2ecc71; // green for extra life } self.speed = 3; self.update = function () { self.y += self.speed; // Pulsate effect if (LK.ticks % 10 === 0) { tween(powerUpGraphics.scale, { x: 1.1, y: 1.1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(powerUpGraphics.scale, { x: 1, y: 1 }, { duration: 500, easing: tween.easeInOut }); } }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Set the game's background game.setBackgroundColor(0x0a0a2a); // Deep space blue // Game state variables var player; var enemies = []; var playerBullets = []; var enemyBullets = []; var powerUps = []; var explosions = []; var score = 0; var level = 1; var enemySpawnRate = 60; // frames between enemy spawns var enemySpawnCounter = 0; var powerUpChance = 0.1; // 10% chance on enemy death var gameActive = true; var dragNode = null; var isPaused = false; // UI elements var scoreText = new Text2('SCORE: 0', { size: 70, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topRight.addChild(scoreText); scoreText.y = 20; scoreText.x = -scoreText.width - 20; var livesText = new Text2('LIVES: 3', { size: 70, fill: 0xFFFFFF }); livesText.anchor.set(1, 0); LK.gui.topLeft.addChild(livesText); livesText.y = 20; livesText.x = 120; // Keep away from top-left corner menu icon var levelText = new Text2('LEVEL: 1', { size: 70, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 20; // Initialize the player player = new Player(); player.x = 2048 / 2; player.y = 2732 - 300; game.addChild(player); // Create stars for background var stars = []; function createStars() { for (var i = 0; i < 100; i++) { var star = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3 + Math.random() * 0.7, scaleY: 0.3 + Math.random() * 0.7, alpha: 0.3 + Math.random() * 0.7, tint: 0xffffff }); star.x = Math.random() * 2048; star.y = Math.random() * 2732; star.speed = 0.5 + Math.random() * 2; stars.push(star); game.addChild(star); } } createStars(); // Start background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Spawn a new enemy function spawnEnemy() { // Choose enemy type based on level var typeChances = [0.7, 0.2, 0.1]; // Default chances // Adjust chances based on level if (level >= 3) { typeChances = [0.5, 0.3, 0.2]; } if (level >= 5) { typeChances = [0.4, 0.3, 0.3]; } if (level >= 8) { typeChances = [0.3, 0.4, 0.3]; } // Determine enemy type var rand = Math.random(); var enemyType = 0; if (rand > typeChances[0]) { enemyType = rand > typeChances[0] + typeChances[1] ? 2 : 1; } var enemy = new Enemy().init(enemyType); enemy.x = 200 + Math.random() * (2048 - 400); enemy.y = -100; enemies.push(enemy); game.addChild(enemy); } // Fire a bullet from the player function firePlayerBullet(offsetX) { offsetX = offsetX || 0; var bullet = new PlayerBullet(); bullet.x = player.x + offsetX; bullet.y = player.y - 50; playerBullets.push(bullet); game.addChild(bullet); LK.getSound('playerShoot').play(); } // Fire a bullet from an enemy function fireEnemyBullet(enemy) { var bullet = new EnemyBullet(); bullet.x = enemy.x; bullet.y = enemy.y + 50; enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('enemyShoot').play(); } // Create an explosion function createExplosion(x, y, size) { var explosion = new Explosion(); explosion.x = x; explosion.y = y; explosion.scale.set(size || 1); explosions.push(explosion); game.addChild(explosion); LK.getSound('explosion').play(); } // Spawn a power-up function spawnPowerUp(x, y) { var powerUp = new PowerUp(); powerUp.x = x; powerUp.y = y; powerUps.push(powerUp); game.addChild(powerUp); } // Update score display function updateScore(newScore) { score = newScore; scoreText.setText("SCORE: " + score); // Check for level up (every 1000 points) var newLevel = Math.floor(score / 1000) + 1; if (newLevel > level) { level = newLevel; levelText.setText("LEVEL: " + level); // Increase difficulty with level enemySpawnRate = Math.max(20, 60 - (level - 1) * 5); } // Set score in LK system LK.setScore(score); // Update high score if needed if (score > storage.highScore) { storage.highScore = score; } } // Update lives display function updateLives() { livesText.setText("LIVES: " + player.lives); } // Handle player and enemy movement function handleGameInput(x, y) { if (dragNode && gameActive && !isPaused) { dragNode.x = Math.max(dragNode.width / 2, Math.min(2048 - dragNode.width / 2, x)); // Restrict vertical movement to bottom third of screen dragNode.y = Math.max(2732 / 3 * 2, Math.min(2732 - dragNode.height / 2, y)); } } // Mouse or touch down on the game game.down = function (x, y, obj) { if (!gameActive || isPaused) { return; } // Set drag node to player if within bounds if (Math.abs(x - player.x) < 100 && Math.abs(y - player.y) < 100) { dragNode = player; } else { // Fire when tapping elsewhere if (player.canFire()) { if (player.doubleFire) { firePlayerBullet(-30); firePlayerBullet(30); } else { firePlayerBullet(0); } } } // Call move handler for immediate response handleGameInput(x, y); }; // Mouse or touch move on the game game.move = function (x, y, obj) { handleGameInput(x, y); }; // Mouse or touch up on the game game.up = function (x, y, obj) { dragNode = null; }; // Main game update loop game.update = function () { if (!gameActive || isPaused) { return; } // Update stars (background) for (var i = 0; i < stars.length; i++) { stars[i].y += stars[i].speed; if (stars[i].y > 2732) { stars[i].y = 0; stars[i].x = Math.random() * 2048; } } // Spawn enemies enemySpawnCounter++; if (enemySpawnCounter >= enemySpawnRate) { enemySpawnCounter = 0; spawnEnemy(); } // Auto-fire for player (if holding down) if (dragNode === player && player.canFire()) { if (player.doubleFire) { firePlayerBullet(-30); firePlayerBullet(30); } else { firePlayerBullet(0); } } // Update player player.update(); // Update bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; // Check if bullet is off screen if (bullet.y < -50) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check for collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { // Handle enemy hit if (enemy.takeDamage(bullet.power)) { // Enemy destroyed createExplosion(enemy.x, enemy.y, 1); updateScore(score + enemy.points); // Chance to spawn power-up if (Math.random() < powerUpChance) { spawnPowerUp(enemy.x, enemy.y); } enemy.destroy(); enemies.splice(j, 1); } // Remove bullet bullet.destroy(); playerBullets.splice(i, 1); break; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; // Check if bullet is off screen if (bullet.y > 2732 + 50) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check for collision with player if (bullet.intersects(player)) { // Handle player hit if (player.takeDamage()) { // Game over gameActive = false; createExplosion(player.x, player.y, 2); LK.setTimeout(function () { LK.showGameOver(); }, 1500); } updateLives(); // Remove bullet bullet.destroy(); enemyBullets.splice(i, 1); } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // Check if enemy is off screen if (enemy.y > 2732 + 100) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check for collision with player if (enemy.intersects(player)) { // Handle player collision with enemy if (player.takeDamage()) { // Game over gameActive = false; createExplosion(player.x, player.y, 2); LK.setTimeout(function () { LK.showGameOver(); }, 1500); } updateLives(); // Destroy enemy createExplosion(enemy.x, enemy.y, 1); enemy.destroy(); enemies.splice(i, 1); continue; } // Enemy shooting if (enemy.tryShoot()) { fireEnemyBullet(enemy); } // Update enemy enemy.update(); } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; // Check if power-up is off screen if (powerUp.y > 2732 + 50) { powerUp.destroy(); powerUps.splice(i, 1); continue; } // Check for collision with player if (powerUp.intersects(player)) { // Apply power-up effect player.applyPowerUp(powerUp.type); // Play sound and add points LK.getSound('powerUp').play(); updateScore(score + 50); // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); continue; } // Update power-up powerUp.update(); } // Update explosions for (var i = explosions.length - 1; i >= 0; i--) { explosions[i].update(); if (explosions[i].lifespan <= 0) { explosions.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
shipColor: 3447003
});
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Type: 0 = basic, 1 = shooter, 2 = fast
self.type = 0;
self.health = 1;
self.points = 100;
self.moveSpeed = 2;
self.shotFrequency = 120; // frames between shots
self.shotCounter = Math.floor(Math.random() * 60); // Random initial delay
self.init = function (type) {
self.type = type || 0;
if (self.type === 0) {
// Basic enemy
enemyGraphics.tint = 0xe74c3c;
self.health = 1;
self.points = 100;
self.moveSpeed = 2;
self.shotFrequency = 0; // Doesn't shoot
} else if (self.type === 1) {
// Shooter enemy
enemyGraphics.tint = 0xf39c12;
self.health = 2;
self.points = 200;
self.moveSpeed = 1;
self.shotFrequency = 120;
} else if (self.type === 2) {
// Fast enemy
enemyGraphics.tint = 0x9b59b6;
self.health = 1;
self.points = 150;
self.moveSpeed = 4;
self.shotFrequency = 0;
}
return self;
};
self.movePattern = function () {
// Default movement pattern
self.y += self.moveSpeed;
if (self.type === 2) {
// Fast enemy zigzags
self.x += Math.sin(LK.ticks / 10) * 5;
}
};
self.tryShoot = function () {
if (self.shotFrequency === 0) {
return null;
}
self.shotCounter++;
if (self.shotCounter >= self.shotFrequency) {
self.shotCounter = 0;
return true;
}
return false;
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xff0000
}, {
duration: 100,
onFinish: function onFinish() {
if (self.type === 0) {
tween(enemyGraphics, {
tint: 0xe74c3c
}, {
duration: 100
});
} else if (self.type === 1) {
tween(enemyGraphics, {
tint: 0xf39c12
}, {
duration: 100
});
} else if (self.type === 2) {
tween(enemyGraphics, {
tint: 0x9b59b6
}, {
duration: 100
});
}
}
});
return self.health <= 0;
};
self.update = function () {
self.movePattern();
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.power = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifespan = 30; // frames
self.update = function () {
self.lifespan--;
if (self.lifespan <= 0) {
self.destroy();
return;
}
// Gradually fade out and expand
explosionGraphics.alpha = self.lifespan / 30;
explosionGraphics.scale.x = 1 + (1 - self.lifespan / 30) * 2;
explosionGraphics.scale.y = 1 + (1 - self.lifespan / 30) * 2;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set the ship color from storage if available
playerGraphics.tint = storage.shipColor || 0x3498db;
self.lives = 3;
self.score = 0;
self.fireRate = 15; // frames between shots
self.fireCounter = 0;
self.doubleFire = false;
self.doubleFireduration = 0;
self.shield = false;
self.shieldDuration = 0;
self.invulnerable = false;
self.invulnerableDuration = 0;
// Shield visual
var shieldGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
tint: 0x3498db,
scaleX: 1.5,
scaleY: 1.5
});
self.canFire = function () {
self.fireCounter++;
if (self.fireCounter >= self.fireRate) {
self.fireCounter = 0;
return true;
}
return false;
};
self.takeDamage = function () {
if (self.invulnerable || self.shield) {
if (self.shield) {
// Remove shield instead of taking damage
self.shield = false;
shieldGraphics.alpha = 0;
// Flash effect
LK.effects.flashObject(self, 0x3498db, 500);
}
return false;
}
self.lives--;
// Become temporarily invulnerable
self.invulnerable = true;
self.invulnerableDuration = 90; // 1.5 seconds
// Flash effect
LK.effects.flashObject(self, 0xff0000, 500);
return self.lives <= 0;
};
self.applyPowerUp = function (type) {
if (type === 0) {
// Double fire
self.doubleFire = true;
self.doubleFireduration = 300; // 5 seconds
} else if (type === 1) {
// Shield
self.shield = true;
shieldGraphics.alpha = 0.7;
self.shieldDuration = 300; // 5 seconds
} else if (type === 2) {
// Extra life
self.lives++;
}
};
self.update = function () {
// Update power-ups durations
if (self.doubleFire) {
self.doubleFireduration--;
if (self.doubleFireduration <= 0) {
self.doubleFire = false;
}
}
if (self.shield) {
self.shieldDuration--;
if (self.shieldDuration <= 0) {
self.shield = false;
shieldGraphics.alpha = 0;
} else {
// Pulsate shield
shieldGraphics.alpha = 0.5 + Math.sin(LK.ticks / 10) * 0.2;
}
}
if (self.invulnerable) {
self.invulnerableDuration--;
if (self.invulnerableDuration <= 0) {
self.invulnerable = false;
}
// Blink when invulnerable
self.alpha = Math.floor(LK.ticks / 5) % 2 ? 0.5 : 1;
} else {
self.alpha = 1;
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.power = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// PowerUp types: 0 = double fire, 1 = shield, 2 = extra life
self.type = Math.floor(Math.random() * 3);
// Set color based on type
if (self.type === 0) {
powerUpGraphics.tint = 0xff5500; // orange for double fire
} else if (self.type === 1) {
powerUpGraphics.tint = 0x3498db; // blue for shield
} else {
powerUpGraphics.tint = 0x2ecc71; // green for extra life
}
self.speed = 3;
self.update = function () {
self.y += self.speed;
// Pulsate effect
if (LK.ticks % 10 === 0) {
tween(powerUpGraphics.scale, {
x: 1.1,
y: 1.1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(powerUpGraphics.scale, {
x: 1,
y: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Set the game's background
game.setBackgroundColor(0x0a0a2a); // Deep space blue
// Game state variables
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var powerUps = [];
var explosions = [];
var score = 0;
var level = 1;
var enemySpawnRate = 60; // frames between enemy spawns
var enemySpawnCounter = 0;
var powerUpChance = 0.1; // 10% chance on enemy death
var gameActive = true;
var dragNode = null;
var isPaused = false;
// UI elements
var scoreText = new Text2('SCORE: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.y = 20;
scoreText.x = -scoreText.width - 20;
var livesText = new Text2('LIVES: 3', {
size: 70,
fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
LK.gui.topLeft.addChild(livesText);
livesText.y = 20;
livesText.x = 120; // Keep away from top-left corner menu icon
var levelText = new Text2('LEVEL: 1', {
size: 70,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 20;
// Initialize the player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Create stars for background
var stars = [];
function createStars() {
for (var i = 0; i < 100; i++) {
var star = LK.getAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + Math.random() * 0.7,
scaleY: 0.3 + Math.random() * 0.7,
alpha: 0.3 + Math.random() * 0.7,
tint: 0xffffff
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.speed = 0.5 + Math.random() * 2;
stars.push(star);
game.addChild(star);
}
}
createStars();
// Start background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Spawn a new enemy
function spawnEnemy() {
// Choose enemy type based on level
var typeChances = [0.7, 0.2, 0.1]; // Default chances
// Adjust chances based on level
if (level >= 3) {
typeChances = [0.5, 0.3, 0.2];
}
if (level >= 5) {
typeChances = [0.4, 0.3, 0.3];
}
if (level >= 8) {
typeChances = [0.3, 0.4, 0.3];
}
// Determine enemy type
var rand = Math.random();
var enemyType = 0;
if (rand > typeChances[0]) {
enemyType = rand > typeChances[0] + typeChances[1] ? 2 : 1;
}
var enemy = new Enemy().init(enemyType);
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -100;
enemies.push(enemy);
game.addChild(enemy);
}
// Fire a bullet from the player
function firePlayerBullet(offsetX) {
offsetX = offsetX || 0;
var bullet = new PlayerBullet();
bullet.x = player.x + offsetX;
bullet.y = player.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('playerShoot').play();
}
// Fire a bullet from an enemy
function fireEnemyBullet(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 50;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
// Create an explosion
function createExplosion(x, y, size) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
explosion.scale.set(size || 1);
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('explosion').play();
}
// Spawn a power-up
function spawnPowerUp(x, y) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Update score display
function updateScore(newScore) {
score = newScore;
scoreText.setText("SCORE: " + score);
// Check for level up (every 1000 points)
var newLevel = Math.floor(score / 1000) + 1;
if (newLevel > level) {
level = newLevel;
levelText.setText("LEVEL: " + level);
// Increase difficulty with level
enemySpawnRate = Math.max(20, 60 - (level - 1) * 5);
}
// Set score in LK system
LK.setScore(score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
}
// Update lives display
function updateLives() {
livesText.setText("LIVES: " + player.lives);
}
// Handle player and enemy movement
function handleGameInput(x, y) {
if (dragNode && gameActive && !isPaused) {
dragNode.x = Math.max(dragNode.width / 2, Math.min(2048 - dragNode.width / 2, x));
// Restrict vertical movement to bottom third of screen
dragNode.y = Math.max(2732 / 3 * 2, Math.min(2732 - dragNode.height / 2, y));
}
}
// Mouse or touch down on the game
game.down = function (x, y, obj) {
if (!gameActive || isPaused) {
return;
}
// Set drag node to player if within bounds
if (Math.abs(x - player.x) < 100 && Math.abs(y - player.y) < 100) {
dragNode = player;
} else {
// Fire when tapping elsewhere
if (player.canFire()) {
if (player.doubleFire) {
firePlayerBullet(-30);
firePlayerBullet(30);
} else {
firePlayerBullet(0);
}
}
}
// Call move handler for immediate response
handleGameInput(x, y);
};
// Mouse or touch move on the game
game.move = function (x, y, obj) {
handleGameInput(x, y);
};
// Mouse or touch up on the game
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
if (!gameActive || isPaused) {
return;
}
// Update stars (background)
for (var i = 0; i < stars.length; i++) {
stars[i].y += stars[i].speed;
if (stars[i].y > 2732) {
stars[i].y = 0;
stars[i].x = Math.random() * 2048;
}
}
// Spawn enemies
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnRate) {
enemySpawnCounter = 0;
spawnEnemy();
}
// Auto-fire for player (if holding down)
if (dragNode === player && player.canFire()) {
if (player.doubleFire) {
firePlayerBullet(-30);
firePlayerBullet(30);
} else {
firePlayerBullet(0);
}
}
// Update player
player.update();
// Update bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Check if bullet is off screen
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check for collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Handle enemy hit
if (enemy.takeDamage(bullet.power)) {
// Enemy destroyed
createExplosion(enemy.x, enemy.y, 1);
updateScore(score + enemy.points);
// Chance to spawn power-up
if (Math.random() < powerUpChance) {
spawnPowerUp(enemy.x, enemy.y);
}
enemy.destroy();
enemies.splice(j, 1);
}
// Remove bullet
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is off screen
if (bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check for collision with player
if (bullet.intersects(player)) {
// Handle player hit
if (player.takeDamage()) {
// Game over
gameActive = false;
createExplosion(player.x, player.y, 2);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
updateLives();
// Remove bullet
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Check if enemy is off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check for collision with player
if (enemy.intersects(player)) {
// Handle player collision with enemy
if (player.takeDamage()) {
// Game over
gameActive = false;
createExplosion(player.x, player.y, 2);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
updateLives();
// Destroy enemy
createExplosion(enemy.x, enemy.y, 1);
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shooting
if (enemy.tryShoot()) {
fireEnemyBullet(enemy);
}
// Update enemy
enemy.update();
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
// Check if power-up is off screen
if (powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check for collision with player
if (powerUp.intersects(player)) {
// Apply power-up effect
player.applyPowerUp(powerUp.type);
// Play sound and add points
LK.getSound('powerUp').play();
updateScore(score + 50);
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Update power-up
powerUp.update();
}
// Update explosions
for (var i = explosions.length - 1; i >= 0; i--) {
explosions[i].update();
if (explosions[i].lifespan <= 0) {
explosions.splice(i, 1);
}
}
};