/**** * 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 BalancedShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 3; self.fireRate = 20; self.speed = 10; self.update = function () { // Custom update logic for BalancedShip }; 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; }); var SpeedyShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 2; self.fireRate = 15; self.speed = 15; self.update = function () { // Custom update logic for SpeedyShip }; return self; }); var TankShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 5; self.fireRate = 25; self.speed = 5; self.update = function () { // Custom update logic for TankShip }; 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 // Choose a spaceship class to initialize the player player = new SpeedyShip(); // Options: SpeedyShip, TankShip, BalancedShip 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
@@ -23,8 +23,22 @@
self.rotation += self.rotationSpeed;
};
return self;
});
+var BalancedShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 3;
+ self.fireRate = 20;
+ self.speed = 10;
+ self.update = function () {
+ // Custom update logic for BalancedShip
+ };
+ return self;
+});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
@@ -235,8 +249,36 @@
powerupGraphics.scale.set(scale, scale);
};
return self;
});
+var SpeedyShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 2;
+ self.fireRate = 15;
+ self.speed = 15;
+ self.update = function () {
+ // Custom update logic for SpeedyShip
+ };
+ return self;
+});
+var TankShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 5;
+ self.fireRate = 25;
+ self.speed = 5;
+ self.update = function () {
+ // Custom update logic for TankShip
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -321,9 +363,10 @@
boss.destroy();
boss = null;
}
// Create player
- player = new Player();
+ // Choose a spaceship class to initialize the player
+ player = new SpeedyShip(); // Options: SpeedyShip, TankShip, BalancedShip
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT - 200;
game.addChild(player);
// Update UI