/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
var size = 0.5 + Math.random() * 1.5; // Random size between 0.5 and 2
var asteroidGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size,
scaleY: size
});
self.speed = 1 + Math.random() * 4; // Random speed
self.rotationSpeed = (Math.random() - 0.5) * 0.05; // Random rotation
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.maxHealth = 30;
self.speed = 3;
self.points = 500;
self.phase = 1;
self.moveDirection = 1;
self.fireRate = 60;
self.lastFired = 0;
self.patternTimer = 0;
self.currentPattern = 'move';
self.update = function () {
self.patternTimer++;
// Change patterns every few seconds
if (self.patternTimer >= 180) {
self.patternTimer = 0;
self.currentPattern = self.currentPattern === 'move' ? 'attack' : 'move';
}
// Movement pattern
if (self.currentPattern === 'move') {
self.x += self.speed * self.moveDirection;
// Reverse direction if approaching screen edge
if (self.x < 300 || self.x > 2048 - 300) {
self.moveDirection *= -1;
}
}
// Attack pattern
if (self.currentPattern === 'attack') {
self.lastFired++;
if (self.lastFired >= self.fireRate) {
self.lastFired = 0;
return true; // Signal to create bullets
}
}
// Change phase based on health
if (self.health <= self.maxHealth * 0.6 && self.phase === 1) {
self.phase = 2;
self.speed = 4;
self.fireRate = 45;
} else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
self.speed = 5;
self.fireRate = 30;
}
return false;
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash boss red when hit
LK.effects.flashObject(self, 0xff0000, 300);
return self.health <= 0;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15; // Negative because bullets move upward
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.speed = 2;
self.points = 10;
self.canShoot = false;
self.fireRate = 120; // Frames between shots
self.lastFired = Math.floor(Math.random() * 60); // Randomize initial fire time
self.movePattern = 'straight'; // Default pattern
self.amplitude = 100; // For wave pattern
self.frequency = 0.02; // For wave pattern
self.startX = 0; // Store initial X position for wave pattern
self.direction = 1; // For zigzag pattern
self.update = function () {
// Basic movement
if (self.movePattern === 'straight') {
self.y += self.speed;
} else if (self.movePattern === 'wave') {
self.y += self.speed;
self.x = self.startX + Math.sin(self.y * self.frequency) * self.amplitude;
} else if (self.movePattern === 'zigzag') {
self.y += self.speed;
self.x += self.speed * self.direction;
// Reverse direction if approaching screen edge
if (self.x < 100 || self.x > 2048 - 100) {
self.direction *= -1;
}
}
// Enemy shooting logic
if (self.canShoot) {
self.lastFired++;
if (self.lastFired >= self.fireRate) {
self.lastFired = 0;
return true; // Signal to create a bullet
}
}
return false;
};
self.takeDamage = function (amount) {
self.health -= amount;
return self.health <= 0;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.fireRate = 20;
self.lastFired = 0;
self.speed = 10;
self.powerupTimer = 0;
self.hasPowerup = false;
self.takeDamage = function () {
if (self.invulnerable) {
return;
}
self.health--;
LK.getSound('playerHit').play();
// Flash player to indicate damage
self.invulnerable = true;
// Blink effect to show invulnerability
var blinkCount = 0;
var blinkInterval = LK.setInterval(function () {
playerGraphics.alpha = playerGraphics.alpha === 1 ? 0.2 : 1;
blinkCount++;
if (blinkCount >= 10) {
LK.clearInterval(blinkInterval);
playerGraphics.alpha = 1;
self.invulnerable = false;
}
}, 150);
};
self.activatePowerup = function (type) {
LK.getSound('powerupCollected').play();
self.hasPowerup = true;
self.powerupTimer = 300; // 5 seconds at 60fps
if (type === 'fire') {
self.fireRate = 10; // Faster fire rate
playerGraphics.tint = 0xff0000;
} else if (type === 'shield') {
self.invulnerable = true;
playerGraphics.tint = 0x00ffff;
}
};
self.update = function () {
// Handle powerup duration
if (self.hasPowerup) {
self.powerupTimer--;
if (self.powerupTimer <= 0) {
self.hasPowerup = false;
self.fireRate = 20; // Reset to normal
self.invulnerable = false;
playerGraphics.tint = 0xffffff; // Reset tint
}
}
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() < 0.5 ? 'fire' : 'shield';
self.speed = 3;
// Set color based on type
if (self.type === 'fire') {
powerupGraphics.tint = 0xff0000; // Red for fire rate
} else {
powerupGraphics.tint = 0x00ffff; // Cyan for shield
}
self.update = function () {
self.y += self.speed;
// Slight pulsing effect
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
powerupGraphics.scale.set(scale, scale);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Game state variables
var gameState = "playing"; // playing, paused, over
var level = 1;
var waveTimer = 0;
var nextWaveTime = 180; // 3 seconds at 60fps
var wave = 0;
var spawnRate = 60; // frames between enemy spawns
var lastSpawn = 0;
var bossActive = false;
var bossDefeated = false;
var bossSpawnWave = 5;
// Game elements
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var asteroids = [];
var powerups = [];
var boss = null;
// Track dragging
var dragging = false;
var lastX = 0;
var lastY = 0;
// Score display
var scoreText = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -350; // Position from right edge
// Wave display
var waveText = new Text2('WAVE: 1', {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topRight.addChild(waveText);
waveText.x = -350;
waveText.y = 70;
// Health display
var healthText = new Text2('HEALTH: 3', {
size: 60,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120; // Avoid the top-left corner as requested
healthText.y = 0;
// Initialize game elements
function initGame() {
// Reset game state
gameState = "playing";
level = 1;
waveTimer = 0;
nextWaveTime = 180;
wave = 0;
spawnRate = 60;
lastSpawn = 0;
bossActive = false;
bossDefeated = false;
// Clear all game elements
playerBullets = [];
enemies = [];
enemyBullets = [];
asteroids = [];
powerups = [];
if (boss) {
boss.destroy();
boss = null;
}
// Create player
player = new Player();
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT - 200;
game.addChild(player);
// Update UI
LK.setScore(0);
updateUI();
// Start background music
LK.playMusic('gameMusic');
}
// Update UI elements
function updateUI() {
scoreText.setText('SCORE: ' + LK.getScore());
waveText.setText('WAVE: ' + wave);
healthText.setText('HEALTH: ' + player.health);
}
// Spawn enemies for the current wave
function spawnWave() {
wave++;
waveText.setText('WAVE: ' + wave);
// Boss wave
if (wave % bossSpawnWave === 0) {
spawnBoss();
return;
}
// Increase difficulty with each wave
spawnRate = Math.max(30, 60 - wave * 5);
// Spawn some initial enemies
var initialEnemies = 3 + Math.min(7, Math.floor(wave / 2));
for (var i = 0; i < initialEnemies; i++) {
spawnEnemy();
}
// Also spawn some asteroids
for (var j = 0; j < Math.min(5, wave); j++) {
spawnAsteroid();
}
}
// Spawn a single enemy
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = 200 + Math.random() * (GAME_WIDTH - 400);
enemy.y = -100;
// Increase health and speed with level
enemy.health = 1 + Math.floor(wave / 3);
enemy.speed = 2 + Math.min(3, wave * 0.5);
enemy.points = 10 * (1 + Math.floor(wave / 2));
// Different enemy types based on wave
if (wave > 1) {
// Some enemies can shoot
enemy.canShoot = Math.random() < 0.3;
// Different movement patterns
var patterns = ['straight', 'wave', 'zigzag'];
enemy.movePattern = patterns[Math.floor(Math.random() * Math.min(patterns.length, 1 + wave / 2))];
enemy.startX = enemy.x;
}
game.addChild(enemy);
enemies.push(enemy);
}
// Spawn boss
function spawnBoss() {
LK.getSound('bossAppear').play();
boss = new Boss();
boss.x = GAME_WIDTH / 2;
boss.y = 300;
// Scale boss difficulty with wave
var waveMultiplier = Math.floor(wave / bossSpawnWave);
boss.health = boss.maxHealth = 30 + waveMultiplier * 20;
boss.points = 500 + waveMultiplier * 200;
bossActive = true;
game.addChild(boss);
// Add warning text
var warningText = new Text2('BOSS INCOMING!', {
size: 120,
fill: 0xFF0000
});
warningText.anchor.set(0.5, 0.5);
warningText.x = GAME_WIDTH / 2;
warningText.y = GAME_HEIGHT / 2;
game.addChild(warningText);
// Remove warning after 2 seconds
LK.setTimeout(function () {
warningText.destroy();
}, 2000);
}
// Spawn asteroid
function spawnAsteroid() {
var asteroid = new Asteroid();
asteroid.x = Math.random() * GAME_WIDTH;
asteroid.y = -100;
game.addChild(asteroid);
asteroids.push(asteroid);
}
// Spawn powerup
function spawnPowerup(x, y) {
if (Math.random() < 0.2) {
// 20% chance to spawn a powerup
var powerup = new Powerup();
powerup.x = x;
powerup.y = y;
game.addChild(powerup);
powerups.push(powerup);
}
}
// Player shoots a bullet
function playerShoot() {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
LK.getSound('playerShoot').play();
}
// Enemy shoots a bullet
function enemyShoot(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 30;
game.addChild(bullet);
enemyBullets.push(bullet);
}
// Boss shoots bullets
function bossShoot() {
// Different attack patterns based on phase
if (boss.phase === 1) {
// Single bullet
var bullet = new EnemyBullet();
bullet.x = boss.x;
bullet.y = boss.y + 75;
game.addChild(bullet);
enemyBullets.push(bullet);
} else if (boss.phase === 2) {
// Three bullets in spread
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x + i * 50;
bullet.y = boss.y + 75;
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else {
// Circle of bullets
var bulletCount = 8;
for (var i = 0; i < bulletCount; i++) {
var angle = i / bulletCount * Math.PI * 2;
var bullet = new EnemyBullet();
bullet.x = boss.x;
bullet.y = boss.y + 75;
bullet.speed = 6;
// Add velocity components
bullet.vx = Math.sin(angle) * bullet.speed;
bullet.vy = Math.cos(angle) * bullet.speed;
// Override update method for this bullet
bullet.update = function () {
this.x += this.vx;
this.y += this.vy;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
}
}
// Check if an object is off screen
function isOffScreen(obj) {
return obj.y < -100 || obj.y > GAME_HEIGHT + 100 || obj.x < -100 || obj.x > GAME_WIDTH + 100;
}
// Handle game over
function handleGameOver() {
if (player.health <= 0) {
gameState = "over";
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
// Handle input events
game.down = function (x, y, obj) {
dragging = true;
lastX = x;
lastY = y;
};
game.up = function (x, y, obj) {
dragging = false;
};
game.move = function (x, y, obj) {
if (dragging && player) {
// Calculate movement
var dx = x - lastX;
var dy = y - lastY;
// Update player position with boundaries
player.x = Math.max(50, Math.min(GAME_WIDTH - 50, player.x + dx));
player.y = Math.max(50, Math.min(GAME_HEIGHT - 50, player.y + dy));
// Update last position
lastX = x;
lastY = y;
}
};
// Initialize the game
initGame();
// Main game loop
game.update = function () {
if (gameState !== "playing") {
return;
}
// Update player
if (player) {
player.update();
// Player shooting
player.lastFired++;
if (player.lastFired >= player.fireRate) {
player.lastFired = 0;
playerShoot();
}
}
// Wave management
if (!bossActive) {
waveTimer++;
if (waveTimer >= nextWaveTime && enemies.length === 0) {
waveTimer = 0;
spawnWave();
}
// Periodic enemy spawning during wave
lastSpawn++;
if (lastSpawn >= spawnRate && wave > 0 && !bossActive && enemies.length < 10 + wave) {
lastSpawn = 0;
spawnEnemy();
}
}
// Update bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
bullet.update();
// Remove off-screen bullets
if (isOffScreen(bullet)) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
var destroyed = enemy.takeDamage(bullet.damage);
if (destroyed) {
LK.getSound('enemyDestroyed').play();
LK.setScore(LK.getScore() + enemy.points);
updateUI();
// Chance to spawn powerup
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(j, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
// Check collision with boss
if (boss && bullet.intersects(boss)) {
var bossDestroyed = boss.takeDamage(bullet.damage);
if (bossDestroyed) {
LK.getSound('enemyDestroyed').play();
LK.setScore(LK.getScore() + boss.points);
updateUI();
// Multiple powerups when boss is defeated
for (var k = 0; k < 3; k++) {
spawnPowerup(boss.x + (Math.random() - 0.5) * 100, boss.y + (Math.random() - 0.5) * 100);
}
boss.destroy();
boss = null;
bossActive = false;
bossDefeated = true;
// Next wave after boss defeat
waveTimer = nextWaveTime;
}
bullet.destroy();
playerBullets.splice(i, 1);
}
// Check collision with asteroids
for (var j = asteroids.length - 1; j >= 0; j--) {
var asteroid = asteroids[j];
if (bullet.intersects(asteroid)) {
asteroid.destroy();
asteroids.splice(j, 1);
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
bullet.update();
// Remove off-screen bullets
if (isOffScreen(bullet)) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (player && bullet.intersects(player)) {
player.takeDamage();
updateUI();
bullet.destroy();
enemyBullets.splice(i, 1);
handleGameOver();
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var shouldShoot = enemy.update();
// Enemy shooting
if (shouldShoot) {
enemyShoot(enemy);
}
// Remove off-screen enemies
if (enemy.y > GAME_HEIGHT + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (player && enemy.intersects(player)) {
player.takeDamage();
updateUI();
enemy.destroy();
enemies.splice(i, 1);
handleGameOver();
}
}
// Update boss
if (boss) {
var shouldShoot = boss.update();
if (shouldShoot) {
bossShoot();
}
// Check collision with player
if (player && boss.intersects(player)) {
player.takeDamage();
updateUI();
handleGameOver();
}
}
// Update asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
asteroid.update();
// Remove off-screen asteroids
if (asteroid.y > GAME_HEIGHT + 100) {
asteroid.destroy();
asteroids.splice(i, 1);
continue;
}
// Check collision with player
if (player && asteroid.intersects(player)) {
player.takeDamage();
updateUI();
asteroid.destroy();
asteroids.splice(i, 1);
handleGameOver();
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
powerup.update();
// Remove off-screen powerups
if (powerup.y > GAME_HEIGHT + 100) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (player && powerup.intersects(player)) {
player.activatePowerup(powerup.type);
powerup.destroy();
powerups.splice(i, 1);
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,704 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var Asteroid = Container.expand(function () {
+ var self = Container.call(this);
+ var size = 0.5 + Math.random() * 1.5; // Random size between 0.5 and 2
+ var asteroidGraphics = self.attachAsset('asteroid', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: size,
+ scaleY: size
+ });
+ self.speed = 1 + Math.random() * 4; // Random speed
+ self.rotationSpeed = (Math.random() - 0.5) * 0.05; // Random rotation
+ self.update = function () {
+ self.y += self.speed;
+ self.rotation += self.rotationSpeed;
+ };
+ return self;
+});
+var Boss = Container.expand(function () {
+ var self = Container.call(this);
+ var bossGraphics = self.attachAsset('boss', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 30;
+ self.maxHealth = 30;
+ self.speed = 3;
+ self.points = 500;
+ self.phase = 1;
+ self.moveDirection = 1;
+ self.fireRate = 60;
+ self.lastFired = 0;
+ self.patternTimer = 0;
+ self.currentPattern = 'move';
+ self.update = function () {
+ self.patternTimer++;
+ // Change patterns every few seconds
+ if (self.patternTimer >= 180) {
+ self.patternTimer = 0;
+ self.currentPattern = self.currentPattern === 'move' ? 'attack' : 'move';
+ }
+ // Movement pattern
+ if (self.currentPattern === 'move') {
+ self.x += self.speed * self.moveDirection;
+ // Reverse direction if approaching screen edge
+ if (self.x < 300 || self.x > 2048 - 300) {
+ self.moveDirection *= -1;
+ }
+ }
+ // Attack pattern
+ if (self.currentPattern === 'attack') {
+ self.lastFired++;
+ if (self.lastFired >= self.fireRate) {
+ self.lastFired = 0;
+ return true; // Signal to create bullets
+ }
+ }
+ // Change phase based on health
+ if (self.health <= self.maxHealth * 0.6 && self.phase === 1) {
+ self.phase = 2;
+ self.speed = 4;
+ self.fireRate = 45;
+ } else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
+ self.phase = 3;
+ self.speed = 5;
+ self.fireRate = 30;
+ }
+ return false;
+ };
+ self.takeDamage = function (amount) {
+ self.health -= amount;
+ // Flash boss red when hit
+ LK.effects.flashObject(self, 0xff0000, 300);
+ return self.health <= 0;
+ };
+ return self;
+});
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -15; // Negative because bullets move upward
+ self.damage = 1;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemyGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 1;
+ self.speed = 2;
+ self.points = 10;
+ self.canShoot = false;
+ self.fireRate = 120; // Frames between shots
+ self.lastFired = Math.floor(Math.random() * 60); // Randomize initial fire time
+ self.movePattern = 'straight'; // Default pattern
+ self.amplitude = 100; // For wave pattern
+ self.frequency = 0.02; // For wave pattern
+ self.startX = 0; // Store initial X position for wave pattern
+ self.direction = 1; // For zigzag pattern
+ self.update = function () {
+ // Basic movement
+ if (self.movePattern === 'straight') {
+ self.y += self.speed;
+ } else if (self.movePattern === 'wave') {
+ self.y += self.speed;
+ self.x = self.startX + Math.sin(self.y * self.frequency) * self.amplitude;
+ } else if (self.movePattern === 'zigzag') {
+ self.y += self.speed;
+ self.x += self.speed * self.direction;
+ // Reverse direction if approaching screen edge
+ if (self.x < 100 || self.x > 2048 - 100) {
+ self.direction *= -1;
+ }
+ }
+ // Enemy shooting logic
+ if (self.canShoot) {
+ self.lastFired++;
+ if (self.lastFired >= self.fireRate) {
+ self.lastFired = 0;
+ return true; // Signal to create a bullet
+ }
+ }
+ return false;
+ };
+ self.takeDamage = function (amount) {
+ self.health -= amount;
+ return self.health <= 0;
+ };
+ return self;
+});
+var EnemyBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('enemyBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 8;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 3;
+ self.fireRate = 20;
+ self.lastFired = 0;
+ self.speed = 10;
+ self.powerupTimer = 0;
+ self.hasPowerup = false;
+ self.takeDamage = function () {
+ if (self.invulnerable) {
+ return;
+ }
+ self.health--;
+ LK.getSound('playerHit').play();
+ // Flash player to indicate damage
+ self.invulnerable = true;
+ // Blink effect to show invulnerability
+ var blinkCount = 0;
+ var blinkInterval = LK.setInterval(function () {
+ playerGraphics.alpha = playerGraphics.alpha === 1 ? 0.2 : 1;
+ blinkCount++;
+ if (blinkCount >= 10) {
+ LK.clearInterval(blinkInterval);
+ playerGraphics.alpha = 1;
+ self.invulnerable = false;
+ }
+ }, 150);
+ };
+ self.activatePowerup = function (type) {
+ LK.getSound('powerupCollected').play();
+ self.hasPowerup = true;
+ self.powerupTimer = 300; // 5 seconds at 60fps
+ if (type === 'fire') {
+ self.fireRate = 10; // Faster fire rate
+ playerGraphics.tint = 0xff0000;
+ } else if (type === 'shield') {
+ self.invulnerable = true;
+ playerGraphics.tint = 0x00ffff;
+ }
+ };
+ self.update = function () {
+ // Handle powerup duration
+ if (self.hasPowerup) {
+ self.powerupTimer--;
+ if (self.powerupTimer <= 0) {
+ self.hasPowerup = false;
+ self.fireRate = 20; // Reset to normal
+ self.invulnerable = false;
+ playerGraphics.tint = 0xffffff; // Reset tint
+ }
+ }
+ };
+ return self;
+});
+var Powerup = Container.expand(function () {
+ var self = Container.call(this);
+ var powerupGraphics = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.type = Math.random() < 0.5 ? 'fire' : 'shield';
+ self.speed = 3;
+ // Set color based on type
+ if (self.type === 'fire') {
+ powerupGraphics.tint = 0xff0000; // Red for fire rate
+ } else {
+ powerupGraphics.tint = 0x00ffff; // Cyan for shield
+ }
+ self.update = function () {
+ self.y += self.speed;
+ // Slight pulsing effect
+ var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
+ powerupGraphics.scale.set(scale, scale);
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
backgroundColor: 0x000000
-});
\ No newline at end of file
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+// Game state variables
+var gameState = "playing"; // playing, paused, over
+var level = 1;
+var waveTimer = 0;
+var nextWaveTime = 180; // 3 seconds at 60fps
+var wave = 0;
+var spawnRate = 60; // frames between enemy spawns
+var lastSpawn = 0;
+var bossActive = false;
+var bossDefeated = false;
+var bossSpawnWave = 5;
+// Game elements
+var player;
+var playerBullets = [];
+var enemies = [];
+var enemyBullets = [];
+var asteroids = [];
+var powerups = [];
+var boss = null;
+// Track dragging
+var dragging = false;
+var lastX = 0;
+var lastY = 0;
+// Score display
+var scoreText = new Text2('SCORE: 0', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0, 0);
+LK.gui.topRight.addChild(scoreText);
+scoreText.x = -350; // Position from right edge
+// Wave display
+var waveText = new Text2('WAVE: 1', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+waveText.anchor.set(0, 0);
+LK.gui.topRight.addChild(waveText);
+waveText.x = -350;
+waveText.y = 70;
+// Health display
+var healthText = new Text2('HEALTH: 3', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+healthText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(healthText);
+healthText.x = 120; // Avoid the top-left corner as requested
+healthText.y = 0;
+// Initialize game elements
+function initGame() {
+ // Reset game state
+ gameState = "playing";
+ level = 1;
+ waveTimer = 0;
+ nextWaveTime = 180;
+ wave = 0;
+ spawnRate = 60;
+ lastSpawn = 0;
+ bossActive = false;
+ bossDefeated = false;
+ // Clear all game elements
+ playerBullets = [];
+ enemies = [];
+ enemyBullets = [];
+ asteroids = [];
+ powerups = [];
+ if (boss) {
+ boss.destroy();
+ boss = null;
+ }
+ // Create player
+ player = new Player();
+ player.x = GAME_WIDTH / 2;
+ player.y = GAME_HEIGHT - 200;
+ game.addChild(player);
+ // Update UI
+ LK.setScore(0);
+ updateUI();
+ // Start background music
+ LK.playMusic('gameMusic');
+}
+// Update UI elements
+function updateUI() {
+ scoreText.setText('SCORE: ' + LK.getScore());
+ waveText.setText('WAVE: ' + wave);
+ healthText.setText('HEALTH: ' + player.health);
+}
+// Spawn enemies for the current wave
+function spawnWave() {
+ wave++;
+ waveText.setText('WAVE: ' + wave);
+ // Boss wave
+ if (wave % bossSpawnWave === 0) {
+ spawnBoss();
+ return;
+ }
+ // Increase difficulty with each wave
+ spawnRate = Math.max(30, 60 - wave * 5);
+ // Spawn some initial enemies
+ var initialEnemies = 3 + Math.min(7, Math.floor(wave / 2));
+ for (var i = 0; i < initialEnemies; i++) {
+ spawnEnemy();
+ }
+ // Also spawn some asteroids
+ for (var j = 0; j < Math.min(5, wave); j++) {
+ spawnAsteroid();
+ }
+}
+// Spawn a single enemy
+function spawnEnemy() {
+ var enemy = new Enemy();
+ enemy.x = 200 + Math.random() * (GAME_WIDTH - 400);
+ enemy.y = -100;
+ // Increase health and speed with level
+ enemy.health = 1 + Math.floor(wave / 3);
+ enemy.speed = 2 + Math.min(3, wave * 0.5);
+ enemy.points = 10 * (1 + Math.floor(wave / 2));
+ // Different enemy types based on wave
+ if (wave > 1) {
+ // Some enemies can shoot
+ enemy.canShoot = Math.random() < 0.3;
+ // Different movement patterns
+ var patterns = ['straight', 'wave', 'zigzag'];
+ enemy.movePattern = patterns[Math.floor(Math.random() * Math.min(patterns.length, 1 + wave / 2))];
+ enemy.startX = enemy.x;
+ }
+ game.addChild(enemy);
+ enemies.push(enemy);
+}
+// Spawn boss
+function spawnBoss() {
+ LK.getSound('bossAppear').play();
+ boss = new Boss();
+ boss.x = GAME_WIDTH / 2;
+ boss.y = 300;
+ // Scale boss difficulty with wave
+ var waveMultiplier = Math.floor(wave / bossSpawnWave);
+ boss.health = boss.maxHealth = 30 + waveMultiplier * 20;
+ boss.points = 500 + waveMultiplier * 200;
+ bossActive = true;
+ game.addChild(boss);
+ // Add warning text
+ var warningText = new Text2('BOSS INCOMING!', {
+ size: 120,
+ fill: 0xFF0000
+ });
+ warningText.anchor.set(0.5, 0.5);
+ warningText.x = GAME_WIDTH / 2;
+ warningText.y = GAME_HEIGHT / 2;
+ game.addChild(warningText);
+ // Remove warning after 2 seconds
+ LK.setTimeout(function () {
+ warningText.destroy();
+ }, 2000);
+}
+// Spawn asteroid
+function spawnAsteroid() {
+ var asteroid = new Asteroid();
+ asteroid.x = Math.random() * GAME_WIDTH;
+ asteroid.y = -100;
+ game.addChild(asteroid);
+ asteroids.push(asteroid);
+}
+// Spawn powerup
+function spawnPowerup(x, y) {
+ if (Math.random() < 0.2) {
+ // 20% chance to spawn a powerup
+ var powerup = new Powerup();
+ powerup.x = x;
+ powerup.y = y;
+ game.addChild(powerup);
+ powerups.push(powerup);
+ }
+}
+// Player shoots a bullet
+function playerShoot() {
+ var bullet = new Bullet();
+ bullet.x = player.x;
+ bullet.y = player.y - 40;
+ game.addChild(bullet);
+ playerBullets.push(bullet);
+ LK.getSound('playerShoot').play();
+}
+// Enemy shoots a bullet
+function enemyShoot(enemy) {
+ var bullet = new EnemyBullet();
+ bullet.x = enemy.x;
+ bullet.y = enemy.y + 30;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+}
+// Boss shoots bullets
+function bossShoot() {
+ // Different attack patterns based on phase
+ if (boss.phase === 1) {
+ // Single bullet
+ var bullet = new EnemyBullet();
+ bullet.x = boss.x;
+ bullet.y = boss.y + 75;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ } else if (boss.phase === 2) {
+ // Three bullets in spread
+ for (var i = -1; i <= 1; i++) {
+ var bullet = new EnemyBullet();
+ bullet.x = boss.x + i * 50;
+ bullet.y = boss.y + 75;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ }
+ } else {
+ // Circle of bullets
+ var bulletCount = 8;
+ for (var i = 0; i < bulletCount; i++) {
+ var angle = i / bulletCount * Math.PI * 2;
+ var bullet = new EnemyBullet();
+ bullet.x = boss.x;
+ bullet.y = boss.y + 75;
+ bullet.speed = 6;
+ // Add velocity components
+ bullet.vx = Math.sin(angle) * bullet.speed;
+ bullet.vy = Math.cos(angle) * bullet.speed;
+ // Override update method for this bullet
+ bullet.update = function () {
+ this.x += this.vx;
+ this.y += this.vy;
+ };
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ }
+ }
+}
+// Check if an object is off screen
+function isOffScreen(obj) {
+ return obj.y < -100 || obj.y > GAME_HEIGHT + 100 || obj.x < -100 || obj.x > GAME_WIDTH + 100;
+}
+// Handle game over
+function handleGameOver() {
+ if (player.health <= 0) {
+ gameState = "over";
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ }
+}
+// Handle input events
+game.down = function (x, y, obj) {
+ dragging = true;
+ lastX = x;
+ lastY = y;
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+};
+game.move = function (x, y, obj) {
+ if (dragging && player) {
+ // Calculate movement
+ var dx = x - lastX;
+ var dy = y - lastY;
+ // Update player position with boundaries
+ player.x = Math.max(50, Math.min(GAME_WIDTH - 50, player.x + dx));
+ player.y = Math.max(50, Math.min(GAME_HEIGHT - 50, player.y + dy));
+ // Update last position
+ lastX = x;
+ lastY = y;
+ }
+};
+// Initialize the game
+initGame();
+// Main game loop
+game.update = function () {
+ if (gameState !== "playing") {
+ return;
+ }
+ // Update player
+ if (player) {
+ player.update();
+ // Player shooting
+ player.lastFired++;
+ if (player.lastFired >= player.fireRate) {
+ player.lastFired = 0;
+ playerShoot();
+ }
+ }
+ // Wave management
+ if (!bossActive) {
+ waveTimer++;
+ if (waveTimer >= nextWaveTime && enemies.length === 0) {
+ waveTimer = 0;
+ spawnWave();
+ }
+ // Periodic enemy spawning during wave
+ lastSpawn++;
+ if (lastSpawn >= spawnRate && wave > 0 && !bossActive && enemies.length < 10 + wave) {
+ lastSpawn = 0;
+ spawnEnemy();
+ }
+ }
+ // Update bullets
+ for (var i = playerBullets.length - 1; i >= 0; i--) {
+ var bullet = playerBullets[i];
+ bullet.update();
+ // Remove off-screen bullets
+ if (isOffScreen(bullet)) {
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ continue;
+ }
+ // Check collision with enemies
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (bullet.intersects(enemy)) {
+ var destroyed = enemy.takeDamage(bullet.damage);
+ if (destroyed) {
+ LK.getSound('enemyDestroyed').play();
+ LK.setScore(LK.getScore() + enemy.points);
+ updateUI();
+ // Chance to spawn powerup
+ spawnPowerup(enemy.x, enemy.y);
+ enemy.destroy();
+ enemies.splice(j, 1);
+ }
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ break;
+ }
+ }
+ // Check collision with boss
+ if (boss && bullet.intersects(boss)) {
+ var bossDestroyed = boss.takeDamage(bullet.damage);
+ if (bossDestroyed) {
+ LK.getSound('enemyDestroyed').play();
+ LK.setScore(LK.getScore() + boss.points);
+ updateUI();
+ // Multiple powerups when boss is defeated
+ for (var k = 0; k < 3; k++) {
+ spawnPowerup(boss.x + (Math.random() - 0.5) * 100, boss.y + (Math.random() - 0.5) * 100);
+ }
+ boss.destroy();
+ boss = null;
+ bossActive = false;
+ bossDefeated = true;
+ // Next wave after boss defeat
+ waveTimer = nextWaveTime;
+ }
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ }
+ // Check collision with asteroids
+ for (var j = asteroids.length - 1; j >= 0; j--) {
+ var asteroid = asteroids[j];
+ if (bullet.intersects(asteroid)) {
+ asteroid.destroy();
+ asteroids.splice(j, 1);
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ break;
+ }
+ }
+ }
+ // Update enemy bullets
+ for (var i = enemyBullets.length - 1; i >= 0; i--) {
+ var bullet = enemyBullets[i];
+ bullet.update();
+ // Remove off-screen bullets
+ if (isOffScreen(bullet)) {
+ bullet.destroy();
+ enemyBullets.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player && bullet.intersects(player)) {
+ player.takeDamage();
+ updateUI();
+ bullet.destroy();
+ enemyBullets.splice(i, 1);
+ handleGameOver();
+ }
+ }
+ // Update enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ var shouldShoot = enemy.update();
+ // Enemy shooting
+ if (shouldShoot) {
+ enemyShoot(enemy);
+ }
+ // Remove off-screen enemies
+ if (enemy.y > GAME_HEIGHT + 100) {
+ enemy.destroy();
+ enemies.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player && enemy.intersects(player)) {
+ player.takeDamage();
+ updateUI();
+ enemy.destroy();
+ enemies.splice(i, 1);
+ handleGameOver();
+ }
+ }
+ // Update boss
+ if (boss) {
+ var shouldShoot = boss.update();
+ if (shouldShoot) {
+ bossShoot();
+ }
+ // Check collision with player
+ if (player && boss.intersects(player)) {
+ player.takeDamage();
+ updateUI();
+ handleGameOver();
+ }
+ }
+ // Update asteroids
+ for (var i = asteroids.length - 1; i >= 0; i--) {
+ var asteroid = asteroids[i];
+ asteroid.update();
+ // Remove off-screen asteroids
+ if (asteroid.y > GAME_HEIGHT + 100) {
+ asteroid.destroy();
+ asteroids.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player && asteroid.intersects(player)) {
+ player.takeDamage();
+ updateUI();
+ asteroid.destroy();
+ asteroids.splice(i, 1);
+ handleGameOver();
+ }
+ }
+ // Update powerups
+ for (var i = powerups.length - 1; i >= 0; i--) {
+ var powerup = powerups[i];
+ powerup.update();
+ // Remove off-screen powerups
+ if (powerup.y > GAME_HEIGHT + 100) {
+ powerup.destroy();
+ powerups.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player && powerup.intersects(player)) {
+ player.activatePowerup(powerup.type);
+ powerup.destroy();
+ powerups.splice(i, 1);
+ }
+ }
+};
\ No newline at end of file