/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, unlockedWeapons: [0] }); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphic = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 30; self.maxHealth = 30; self.speed = 2; self.damage = 10; self.attackCooldown = 60; // frames self.attackTimer = 0; self.scoreValue = 10; self.healthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, y: -80 }); self.healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, y: -80 }); self.healthBar.width = self.health / self.maxHealth * 100; self.takeDamage = function (amount) { self.health -= amount; self.healthBar.width = self.health / self.maxHealth * 100; // Flash red when hit tween(enemyGraphic, { alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(enemyGraphic, { alpha: 1 }, { duration: 100 }); } }); if (self.health <= 0) { LK.getSound('enemyDeath').play(); var randomChance = Math.random(); if (randomChance < 0.2) { // 20% chance to drop powerup var powerup = new PowerUp(); powerup.x = self.x; powerup.y = self.y; game.addChild(powerup); powerups.push(powerup); } self.readyToRemove = true; return true; } return false; }; self.moveTowards = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.update = function () { if (self.attackTimer > 0) { self.attackTimer--; } }; return self; }); var BossEnemy = Enemy.expand(function () { var self = Enemy.call(this); // Replace the enemy graphic with a boss graphic self.removeChild(self.children[0]); // Remove regular enemy graphic var bossGraphic = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.health = 150; self.maxHealth = 150; self.speed = 1.5; self.damage = 20; self.attackCooldown = 120; self.scoreValue = 50; // Update health bar position and size for boss self.healthBar.y = -120; self.healthBarBg.y = -120; self.healthBar.width = 200; self.healthBarBg.width = 200; // Special boss attack pattern var attackPhase = 0; self.update = function () { Enemy.prototype.update.call(self); // Call the parent update method if (self.attackTimer === 0) { // Boss can fire projectiles attackPhase = (attackPhase + 1) % 3; switch (attackPhase) { case 0: // Fire in cardinal directions for (var angle = 0; angle < Math.PI * 2; angle += Math.PI / 2) { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.setDirection(Math.cos(angle), Math.sin(angle)); projectile.damage = 15; projectile.isEnemyProjectile = true; game.addChild(projectile); enemyProjectiles.push(projectile); } break; case 1: // Fire at player if (warrior) { var dx = warrior.x - self.x; var dy = warrior.y - self.y; var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.setDirection(dx, dy); projectile.damage = 15; projectile.isEnemyProjectile = true; game.addChild(projectile); enemyProjectiles.push(projectile); } break; case 2: // Spawn minions var minion = new Enemy(); minion.x = self.x + (Math.random() * 200 - 100); minion.y = self.y + (Math.random() * 200 - 100); minion.health = 15; minion.maxHealth = 15; minion.speed = 3; game.addChild(minion); enemies.push(minion); break; } self.attackTimer = self.attackCooldown; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphic = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.floor(Math.random() * 3); // 0: health, 1: speed, 2: damage // Different colors for different powerup types switch (self.type) { case 0: // Health powerupGraphic.tint = 0x33cc33; // Green break; case 1: // Speed powerupGraphic.tint = 0x3366ff; // Blue break; case 2: // Damage powerupGraphic.tint = 0xff3333; // Red break; } self.lifespan = 300; // frames the powerup will stay self.age = 0; // Pulsing animation self.update = function () { self.age++; var scale = 1 + 0.1 * Math.sin(self.age * 0.1); powerupGraphic.scale.set(scale, scale); if (self.age >= self.lifespan) { self.readyToRemove = true; } }; self.applyEffect = function (warrior) { LK.getSound('powerupCollect').play(); switch (self.type) { case 0: // Health warrior.health = Math.min(warrior.health + 30, warrior.maxHealth); warrior.updateHealthBar(); break; case 1: // Speed warrior.speedBoost = 300; // Number of frames for speed boost break; case 2: // Damage warrior.damageBoost = 300; // Number of frames for damage boost break; } }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphic = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.damage = 10; self.direction = { x: 0, y: 0 }; self.lifespan = 120; // frames the projectile will live self.age = 0; self.setDirection = function (dirX, dirY) { // Normalize direction vector var length = Math.sqrt(dirX * dirX + dirY * dirY); if (length > 0) { self.direction.x = dirX / length; self.direction.y = dirY / length; } }; self.update = function () { self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; self.age++; if (self.age >= self.lifespan) { self.readyToRemove = true; } }; return self; }); var Warrior = Container.expand(function () { var self = Container.call(this); var warriorGraphic = self.attachAsset('warrior', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.speed = 5; self.damage = 20; self.attackCooldown = 20; // frames self.attackTimer = 0; self.invulnerable = false; self.invulnerableTime = 0; self.speedBoost = 0; self.damageBoost = 0; // Health bar displayed at the top of the screen self.healthBar = null; self.healthBarBg = null; self.initializeHealthBar = function () { self.healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 30 }); self.healthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, width: 300, height: 30 }); LK.gui.top.addChild(self.healthBarBg); self.healthBarBg.y = 50; LK.gui.top.addChild(self.healthBar); self.healthBar.y = 50; self.healthBar.x = self.healthBarBg.x - self.healthBarBg.width / 2; self.updateHealthBar(); }; self.updateHealthBar = function () { if (self.healthBar) { self.healthBar.width = self.health / self.maxHealth * 300; } }; self.takeDamage = function (amount) { if (self.invulnerable) { return false; } self.health -= amount; self.updateHealthBar(); LK.getSound('playerHit').play(); // Flash and set invulnerable briefly self.invulnerable = true; self.invulnerableTime = 60; // 1 second of invulnerability tween(warriorGraphic, { alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(warriorGraphic, { alpha: 1 }, { duration: 100 }); } }); if (self.health <= 0) { LK.getSound('gameOver').play(); LK.showGameOver(); return true; } return false; }; self.fire = function (dirX, dirY) { if (self.attackTimer === 0) { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.setDirection(dirX, dirY); // Apply damage boost if active if (self.damageBoost > 0) { projectile.damage = self.damage * 1.5; projectile.tint = 0xff0000; // Red tint for boosted projectiles } else { projectile.damage = self.damage; } game.addChild(projectile); playerProjectiles.push(projectile); self.attackTimer = self.attackCooldown; } }; self.update = function () { if (self.attackTimer > 0) { self.attackTimer--; } if (self.invulnerable) { self.invulnerableTime--; warriorGraphic.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.2); if (self.invulnerableTime <= 0) { self.invulnerable = false; warriorGraphic.alpha = 1; } } // Handle boosts if (self.speedBoost > 0) { self.speedBoost--; warriorGraphic.tint = 0x3366ff; // Blue tint during speed boost } else { warriorGraphic.tint = 0xffffff; // Reset tint } if (self.damageBoost > 0) { self.damageBoost--; if (!self.speedBoost) { // Only tint red if not speed boosted warriorGraphic.tint = 0xff3333; // Red tint during damage boost } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game state variables var warrior = null; var enemies = []; var playerProjectiles = []; var enemyProjectiles = []; var powerups = []; var waveNumber = 1; var enemiesPerWave = 5; var score = 0; var waveClearTimeBonus = 5000; // Base time bonus for clearing waves var waveStartTime = 0; var gameActive = false; var arena = null; var arenaSize = 1800; var waveText = null; var scoreText = null; var dragging = false; var lastMoveX = 0; var lastMoveY = 0; // Initialize the game function initGame() { // Reset game state warrior = null; enemies = []; playerProjectiles = []; enemyProjectiles = []; powerups = []; waveNumber = 1; enemiesPerWave = 5; score = 0; gameActive = true; // Set score for LK LK.setScore(score); // Create arena arena = LK.getAsset('arena', { anchorX: 0.5, anchorY: 0.5 }); game.addChild(arena); arena.x = 2048 / 2; arena.y = 2732 / 2; arena.alpha = 0.5; // Create warrior warrior = new Warrior(); warrior.x = 2048 / 2; warrior.y = 2732 / 2; game.addChild(warrior); warrior.initializeHealthBar(); // Create UI elements createUI(); // Start first wave startWave(); // Play background music LK.playMusic('battleMusic'); } function createUI() { // Score text scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); scoreText.x = -20; scoreText.y = 20; // Wave text waveText = new Text2('Wave 1', { size: 60, fill: 0xFFFFFF }); waveText.anchor.set(0, 0); LK.gui.topRight.addChild(waveText); waveText.x = -20; waveText.y = 80; } function updateUI() { scoreText.setText('Score: ' + score); waveText.setText('Wave ' + waveNumber); } function startWave() { waveStartTime = Date.now(); // Create enemies for this wave var enemiesToSpawn = enemiesPerWave + waveNumber; // Every 3rd wave has a boss if (waveNumber % 3 === 0) { var boss = new BossEnemy(); placeEnemyOutsideArena(boss); game.addChild(boss); enemies.push(boss); enemiesToSpawn -= 3; // Boss counts as 3 regular enemies } for (var i = 0; i < enemiesToSpawn; i++) { var enemy = new Enemy(); // Scale difficulty with wave number enemy.health = 30 + waveNumber * 5; enemy.maxHealth = enemy.health; enemy.speed = 2 + waveNumber * 0.1; enemy.damage = 10 + waveNumber * 2; placeEnemyOutsideArena(enemy); game.addChild(enemy); enemies.push(enemy); } updateUI(); } function placeEnemyOutsideArena(enemy) { var angle = Math.random() * Math.PI * 2; var distance = arenaSize / 2 + 100 + Math.random() * 300; // Spawn outside arena enemy.x = 2048 / 2 + Math.cos(angle) * distance; enemy.y = 2732 / 2 + Math.sin(angle) * distance; } function waveCompleted() { // Calculate time bonus var timeElapsed = Date.now() - waveStartTime; var timeBonus = Math.max(0, waveClearTimeBonus - Math.floor(timeElapsed / 100)); score += timeBonus; LK.setScore(score); // Update high score if (score > storage.highScore) { storage.highScore = score; } // Play victory sound LK.getSound('waveComplete').play(); // Flash screen LK.effects.flashScreen(0x33cc33, 500); // Next wave waveNumber++; enemiesPerWave += 2; // Brief delay before next wave LK.setTimeout(function () { startWave(); }, 2000); } // Game update function game.update = function () { if (!gameActive) { return; } // Update warrior if (warrior) { warrior.update(); // Move warrior if dragging if (dragging) { // Calculate actual speed based on speed boost var actualSpeed = warrior.speed; if (warrior.speedBoost > 0) { actualSpeed *= 1.5; } // Calculate direction to move var dx = lastMoveX - warrior.x; var dy = lastMoveY - warrior.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > actualSpeed) { warrior.x += dx / distance * actualSpeed; warrior.y += dy / distance * actualSpeed; } else { warrior.x = lastMoveX; warrior.y = lastMoveY; } // Keep warrior inside the arena var arenaRadius = arenaSize / 2; var centerX = 2048 / 2; var centerY = 2732 / 2; var dx = warrior.x - centerX; var dy = warrior.y - centerY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > arenaRadius) { warrior.x = centerX + dx / distance * arenaRadius; warrior.y = centerY + dy / distance * arenaRadius; } } // Check for powerup collisions for (var i = powerups.length - 1; i >= 0; i--) { if (warrior.intersects(powerups[i])) { powerups[i].applyEffect(warrior); powerups[i].destroy(); powerups.splice(i, 1); } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Move towards warrior if (warrior) { enemy.moveTowards(warrior.x, warrior.y); // Check for collision with warrior if (warrior.intersects(enemy) && enemy.attackTimer === 0) { warrior.takeDamage(enemy.damage); enemy.attackTimer = enemy.attackCooldown; } } // Remove dead enemies if (enemy.readyToRemove) { score += enemy.scoreValue; LK.setScore(score); enemy.destroy(); enemies.splice(i, 1); } } // Update player projectiles for (var i = playerProjectiles.length - 1; i >= 0; i--) { var proj = playerProjectiles[i]; proj.update(); // Check for enemy hits for (var j = enemies.length - 1; j >= 0; j--) { if (proj.intersects(enemies[j])) { LK.getSound('hit').play(); var killed = enemies[j].takeDamage(proj.damage); if (killed) { score += enemies[j].scoreValue; LK.setScore(score); } proj.readyToRemove = true; break; } } // Remove projectiles that are off-screen or have hit something if (proj.readyToRemove || proj.x < 0 || proj.x > 2048 || proj.y < 0 || proj.y > 2732) { proj.destroy(); playerProjectiles.splice(i, 1); } } // Update enemy projectiles for (var i = enemyProjectiles.length - 1; i >= 0; i--) { var proj = enemyProjectiles[i]; proj.update(); // Check for warrior hit if (warrior && proj.intersects(warrior)) { warrior.takeDamage(proj.damage); proj.readyToRemove = true; } // Remove projectiles that are off-screen or have hit something if (proj.readyToRemove || proj.x < 0 || proj.x > 2048 || proj.y < 0 || proj.y > 2732) { proj.destroy(); enemyProjectiles.splice(i, 1); } } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].update(); if (powerups[i].readyToRemove) { powerups[i].destroy(); powerups.splice(i, 1); } } // Check if wave is completed if (enemies.length === 0) { waveCompleted(); } // Update UI updateUI(); }; // Input handling function handleMove(x, y, obj) { if (dragging && warrior) { lastMoveX = x; lastMoveY = y; } } game.move = handleMove; game.down = function (x, y, obj) { if (warrior) { dragging = true; lastMoveX = x; lastMoveY = y; // Fire in the direction opposite to the touch var dx = x - warrior.x; var dy = y - warrior.y; warrior.fire(dx, dy); } }; game.up = function (x, y, obj) { dragging = false; }; // Initialize game when script loads initGame();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,649 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ unlockedWeapons: [0]
+});
+
+/****
+* Classes
+****/
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemyGraphic = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 30;
+ self.maxHealth = 30;
+ self.speed = 2;
+ self.damage = 10;
+ self.attackCooldown = 60; // frames
+ self.attackTimer = 0;
+ self.scoreValue = 10;
+ self.healthBar = self.attachAsset('healthBar', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -80
+ });
+ self.healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -80
+ });
+ self.healthBar.width = self.health / self.maxHealth * 100;
+ self.takeDamage = function (amount) {
+ self.health -= amount;
+ self.healthBar.width = self.health / self.maxHealth * 100;
+ // Flash red when hit
+ tween(enemyGraphic, {
+ alpha: 0.5
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(enemyGraphic, {
+ alpha: 1
+ }, {
+ duration: 100
+ });
+ }
+ });
+ if (self.health <= 0) {
+ LK.getSound('enemyDeath').play();
+ var randomChance = Math.random();
+ if (randomChance < 0.2) {
+ // 20% chance to drop powerup
+ var powerup = new PowerUp();
+ powerup.x = self.x;
+ powerup.y = self.y;
+ game.addChild(powerup);
+ powerups.push(powerup);
+ }
+ self.readyToRemove = true;
+ return true;
+ }
+ return false;
+ };
+ self.moveTowards = function (targetX, targetY) {
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 5) {
+ self.x += dx / distance * self.speed;
+ self.y += dy / distance * self.speed;
+ }
+ };
+ self.update = function () {
+ if (self.attackTimer > 0) {
+ self.attackTimer--;
+ }
+ };
+ return self;
+});
+var BossEnemy = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace the enemy graphic with a boss graphic
+ self.removeChild(self.children[0]); // Remove regular enemy graphic
+ var bossGraphic = self.attachAsset('boss', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 150;
+ self.maxHealth = 150;
+ self.speed = 1.5;
+ self.damage = 20;
+ self.attackCooldown = 120;
+ self.scoreValue = 50;
+ // Update health bar position and size for boss
+ self.healthBar.y = -120;
+ self.healthBarBg.y = -120;
+ self.healthBar.width = 200;
+ self.healthBarBg.width = 200;
+ // Special boss attack pattern
+ var attackPhase = 0;
+ self.update = function () {
+ Enemy.prototype.update.call(self); // Call the parent update method
+ if (self.attackTimer === 0) {
+ // Boss can fire projectiles
+ attackPhase = (attackPhase + 1) % 3;
+ switch (attackPhase) {
+ case 0:
+ // Fire in cardinal directions
+ for (var angle = 0; angle < Math.PI * 2; angle += Math.PI / 2) {
+ var projectile = new Projectile();
+ projectile.x = self.x;
+ projectile.y = self.y;
+ projectile.setDirection(Math.cos(angle), Math.sin(angle));
+ projectile.damage = 15;
+ projectile.isEnemyProjectile = true;
+ game.addChild(projectile);
+ enemyProjectiles.push(projectile);
+ }
+ break;
+ case 1:
+ // Fire at player
+ if (warrior) {
+ var dx = warrior.x - self.x;
+ var dy = warrior.y - self.y;
+ var projectile = new Projectile();
+ projectile.x = self.x;
+ projectile.y = self.y;
+ projectile.setDirection(dx, dy);
+ projectile.damage = 15;
+ projectile.isEnemyProjectile = true;
+ game.addChild(projectile);
+ enemyProjectiles.push(projectile);
+ }
+ break;
+ case 2:
+ // Spawn minions
+ var minion = new Enemy();
+ minion.x = self.x + (Math.random() * 200 - 100);
+ minion.y = self.y + (Math.random() * 200 - 100);
+ minion.health = 15;
+ minion.maxHealth = 15;
+ minion.speed = 3;
+ game.addChild(minion);
+ enemies.push(minion);
+ break;
+ }
+ self.attackTimer = self.attackCooldown;
+ }
+ };
+ return self;
+});
+var PowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ var powerupGraphic = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.type = Math.floor(Math.random() * 3); // 0: health, 1: speed, 2: damage
+ // Different colors for different powerup types
+ switch (self.type) {
+ case 0:
+ // Health
+ powerupGraphic.tint = 0x33cc33; // Green
+ break;
+ case 1:
+ // Speed
+ powerupGraphic.tint = 0x3366ff; // Blue
+ break;
+ case 2:
+ // Damage
+ powerupGraphic.tint = 0xff3333; // Red
+ break;
+ }
+ self.lifespan = 300; // frames the powerup will stay
+ self.age = 0;
+ // Pulsing animation
+ self.update = function () {
+ self.age++;
+ var scale = 1 + 0.1 * Math.sin(self.age * 0.1);
+ powerupGraphic.scale.set(scale, scale);
+ if (self.age >= self.lifespan) {
+ self.readyToRemove = true;
+ }
+ };
+ self.applyEffect = function (warrior) {
+ LK.getSound('powerupCollect').play();
+ switch (self.type) {
+ case 0:
+ // Health
+ warrior.health = Math.min(warrior.health + 30, warrior.maxHealth);
+ warrior.updateHealthBar();
+ break;
+ case 1:
+ // Speed
+ warrior.speedBoost = 300; // Number of frames for speed boost
+ break;
+ case 2:
+ // Damage
+ warrior.damageBoost = 300; // Number of frames for damage boost
+ break;
+ }
+ };
+ return self;
+});
+var Projectile = Container.expand(function () {
+ var self = Container.call(this);
+ var projectileGraphic = self.attachAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 10;
+ self.damage = 10;
+ self.direction = {
+ x: 0,
+ y: 0
+ };
+ self.lifespan = 120; // frames the projectile will live
+ self.age = 0;
+ self.setDirection = function (dirX, dirY) {
+ // Normalize direction vector
+ var length = Math.sqrt(dirX * dirX + dirY * dirY);
+ if (length > 0) {
+ self.direction.x = dirX / length;
+ self.direction.y = dirY / length;
+ }
+ };
+ self.update = function () {
+ self.x += self.direction.x * self.speed;
+ self.y += self.direction.y * self.speed;
+ self.age++;
+ if (self.age >= self.lifespan) {
+ self.readyToRemove = true;
+ }
+ };
+ return self;
+});
+var Warrior = Container.expand(function () {
+ var self = Container.call(this);
+ var warriorGraphic = self.attachAsset('warrior', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 100;
+ self.maxHealth = 100;
+ self.speed = 5;
+ self.damage = 20;
+ self.attackCooldown = 20; // frames
+ self.attackTimer = 0;
+ self.invulnerable = false;
+ self.invulnerableTime = 0;
+ self.speedBoost = 0;
+ self.damageBoost = 0;
+ // Health bar displayed at the top of the screen
+ self.healthBar = null;
+ self.healthBarBg = null;
+ self.initializeHealthBar = function () {
+ self.healthBarBg = LK.getAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 300,
+ height: 30
+ });
+ self.healthBar = LK.getAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0.5,
+ width: 300,
+ height: 30
+ });
+ LK.gui.top.addChild(self.healthBarBg);
+ self.healthBarBg.y = 50;
+ LK.gui.top.addChild(self.healthBar);
+ self.healthBar.y = 50;
+ self.healthBar.x = self.healthBarBg.x - self.healthBarBg.width / 2;
+ self.updateHealthBar();
+ };
+ self.updateHealthBar = function () {
+ if (self.healthBar) {
+ self.healthBar.width = self.health / self.maxHealth * 300;
+ }
+ };
+ self.takeDamage = function (amount) {
+ if (self.invulnerable) {
+ return false;
+ }
+ self.health -= amount;
+ self.updateHealthBar();
+ LK.getSound('playerHit').play();
+ // Flash and set invulnerable briefly
+ self.invulnerable = true;
+ self.invulnerableTime = 60; // 1 second of invulnerability
+ tween(warriorGraphic, {
+ alpha: 0.5
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(warriorGraphic, {
+ alpha: 1
+ }, {
+ duration: 100
+ });
+ }
+ });
+ if (self.health <= 0) {
+ LK.getSound('gameOver').play();
+ LK.showGameOver();
+ return true;
+ }
+ return false;
+ };
+ self.fire = function (dirX, dirY) {
+ if (self.attackTimer === 0) {
+ var projectile = new Projectile();
+ projectile.x = self.x;
+ projectile.y = self.y;
+ projectile.setDirection(dirX, dirY);
+ // Apply damage boost if active
+ if (self.damageBoost > 0) {
+ projectile.damage = self.damage * 1.5;
+ projectile.tint = 0xff0000; // Red tint for boosted projectiles
+ } else {
+ projectile.damage = self.damage;
+ }
+ game.addChild(projectile);
+ playerProjectiles.push(projectile);
+ self.attackTimer = self.attackCooldown;
+ }
+ };
+ self.update = function () {
+ if (self.attackTimer > 0) {
+ self.attackTimer--;
+ }
+ if (self.invulnerable) {
+ self.invulnerableTime--;
+ warriorGraphic.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.2);
+ if (self.invulnerableTime <= 0) {
+ self.invulnerable = false;
+ warriorGraphic.alpha = 1;
+ }
+ }
+ // Handle boosts
+ if (self.speedBoost > 0) {
+ self.speedBoost--;
+ warriorGraphic.tint = 0x3366ff; // Blue tint during speed boost
+ } else {
+ warriorGraphic.tint = 0xffffff; // Reset tint
+ }
+ if (self.damageBoost > 0) {
+ self.damageBoost--;
+ if (!self.speedBoost) {
+ // Only tint red if not speed boosted
+ warriorGraphic.tint = 0xff3333; // Red tint during damage boost
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var warrior = null;
+var enemies = [];
+var playerProjectiles = [];
+var enemyProjectiles = [];
+var powerups = [];
+var waveNumber = 1;
+var enemiesPerWave = 5;
+var score = 0;
+var waveClearTimeBonus = 5000; // Base time bonus for clearing waves
+var waveStartTime = 0;
+var gameActive = false;
+var arena = null;
+var arenaSize = 1800;
+var waveText = null;
+var scoreText = null;
+var dragging = false;
+var lastMoveX = 0;
+var lastMoveY = 0;
+// Initialize the game
+function initGame() {
+ // Reset game state
+ warrior = null;
+ enemies = [];
+ playerProjectiles = [];
+ enemyProjectiles = [];
+ powerups = [];
+ waveNumber = 1;
+ enemiesPerWave = 5;
+ score = 0;
+ gameActive = true;
+ // Set score for LK
+ LK.setScore(score);
+ // Create arena
+ arena = LK.getAsset('arena', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ game.addChild(arena);
+ arena.x = 2048 / 2;
+ arena.y = 2732 / 2;
+ arena.alpha = 0.5;
+ // Create warrior
+ warrior = new Warrior();
+ warrior.x = 2048 / 2;
+ warrior.y = 2732 / 2;
+ game.addChild(warrior);
+ warrior.initializeHealthBar();
+ // Create UI elements
+ createUI();
+ // Start first wave
+ startWave();
+ // Play background music
+ LK.playMusic('battleMusic');
+}
+function createUI() {
+ // Score text
+ scoreText = new Text2('Score: 0', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ scoreText.anchor.set(1, 0);
+ LK.gui.topRight.addChild(scoreText);
+ scoreText.x = -20;
+ scoreText.y = 20;
+ // Wave text
+ waveText = new Text2('Wave 1', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ waveText.anchor.set(0, 0);
+ LK.gui.topRight.addChild(waveText);
+ waveText.x = -20;
+ waveText.y = 80;
+}
+function updateUI() {
+ scoreText.setText('Score: ' + score);
+ waveText.setText('Wave ' + waveNumber);
+}
+function startWave() {
+ waveStartTime = Date.now();
+ // Create enemies for this wave
+ var enemiesToSpawn = enemiesPerWave + waveNumber;
+ // Every 3rd wave has a boss
+ if (waveNumber % 3 === 0) {
+ var boss = new BossEnemy();
+ placeEnemyOutsideArena(boss);
+ game.addChild(boss);
+ enemies.push(boss);
+ enemiesToSpawn -= 3; // Boss counts as 3 regular enemies
+ }
+ for (var i = 0; i < enemiesToSpawn; i++) {
+ var enemy = new Enemy();
+ // Scale difficulty with wave number
+ enemy.health = 30 + waveNumber * 5;
+ enemy.maxHealth = enemy.health;
+ enemy.speed = 2 + waveNumber * 0.1;
+ enemy.damage = 10 + waveNumber * 2;
+ placeEnemyOutsideArena(enemy);
+ game.addChild(enemy);
+ enemies.push(enemy);
+ }
+ updateUI();
+}
+function placeEnemyOutsideArena(enemy) {
+ var angle = Math.random() * Math.PI * 2;
+ var distance = arenaSize / 2 + 100 + Math.random() * 300; // Spawn outside arena
+ enemy.x = 2048 / 2 + Math.cos(angle) * distance;
+ enemy.y = 2732 / 2 + Math.sin(angle) * distance;
+}
+function waveCompleted() {
+ // Calculate time bonus
+ var timeElapsed = Date.now() - waveStartTime;
+ var timeBonus = Math.max(0, waveClearTimeBonus - Math.floor(timeElapsed / 100));
+ score += timeBonus;
+ LK.setScore(score);
+ // Update high score
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Play victory sound
+ LK.getSound('waveComplete').play();
+ // Flash screen
+ LK.effects.flashScreen(0x33cc33, 500);
+ // Next wave
+ waveNumber++;
+ enemiesPerWave += 2;
+ // Brief delay before next wave
+ LK.setTimeout(function () {
+ startWave();
+ }, 2000);
+}
+// Game update function
+game.update = function () {
+ if (!gameActive) {
+ return;
+ }
+ // Update warrior
+ if (warrior) {
+ warrior.update();
+ // Move warrior if dragging
+ if (dragging) {
+ // Calculate actual speed based on speed boost
+ var actualSpeed = warrior.speed;
+ if (warrior.speedBoost > 0) {
+ actualSpeed *= 1.5;
+ }
+ // Calculate direction to move
+ var dx = lastMoveX - warrior.x;
+ var dy = lastMoveY - warrior.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > actualSpeed) {
+ warrior.x += dx / distance * actualSpeed;
+ warrior.y += dy / distance * actualSpeed;
+ } else {
+ warrior.x = lastMoveX;
+ warrior.y = lastMoveY;
+ }
+ // Keep warrior inside the arena
+ var arenaRadius = arenaSize / 2;
+ var centerX = 2048 / 2;
+ var centerY = 2732 / 2;
+ var dx = warrior.x - centerX;
+ var dy = warrior.y - centerY;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > arenaRadius) {
+ warrior.x = centerX + dx / distance * arenaRadius;
+ warrior.y = centerY + dy / distance * arenaRadius;
+ }
+ }
+ // Check for powerup collisions
+ for (var i = powerups.length - 1; i >= 0; i--) {
+ if (warrior.intersects(powerups[i])) {
+ powerups[i].applyEffect(warrior);
+ powerups[i].destroy();
+ powerups.splice(i, 1);
+ }
+ }
+ }
+ // Update enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ enemy.update();
+ // Move towards warrior
+ if (warrior) {
+ enemy.moveTowards(warrior.x, warrior.y);
+ // Check for collision with warrior
+ if (warrior.intersects(enemy) && enemy.attackTimer === 0) {
+ warrior.takeDamage(enemy.damage);
+ enemy.attackTimer = enemy.attackCooldown;
+ }
+ }
+ // Remove dead enemies
+ if (enemy.readyToRemove) {
+ score += enemy.scoreValue;
+ LK.setScore(score);
+ enemy.destroy();
+ enemies.splice(i, 1);
+ }
+ }
+ // Update player projectiles
+ for (var i = playerProjectiles.length - 1; i >= 0; i--) {
+ var proj = playerProjectiles[i];
+ proj.update();
+ // Check for enemy hits
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ if (proj.intersects(enemies[j])) {
+ LK.getSound('hit').play();
+ var killed = enemies[j].takeDamage(proj.damage);
+ if (killed) {
+ score += enemies[j].scoreValue;
+ LK.setScore(score);
+ }
+ proj.readyToRemove = true;
+ break;
+ }
+ }
+ // Remove projectiles that are off-screen or have hit something
+ if (proj.readyToRemove || proj.x < 0 || proj.x > 2048 || proj.y < 0 || proj.y > 2732) {
+ proj.destroy();
+ playerProjectiles.splice(i, 1);
+ }
+ }
+ // Update enemy projectiles
+ for (var i = enemyProjectiles.length - 1; i >= 0; i--) {
+ var proj = enemyProjectiles[i];
+ proj.update();
+ // Check for warrior hit
+ if (warrior && proj.intersects(warrior)) {
+ warrior.takeDamage(proj.damage);
+ proj.readyToRemove = true;
+ }
+ // Remove projectiles that are off-screen or have hit something
+ if (proj.readyToRemove || proj.x < 0 || proj.x > 2048 || proj.y < 0 || proj.y > 2732) {
+ proj.destroy();
+ enemyProjectiles.splice(i, 1);
+ }
+ }
+ // Update powerups
+ for (var i = powerups.length - 1; i >= 0; i--) {
+ powerups[i].update();
+ if (powerups[i].readyToRemove) {
+ powerups[i].destroy();
+ powerups.splice(i, 1);
+ }
+ }
+ // Check if wave is completed
+ if (enemies.length === 0) {
+ waveCompleted();
+ }
+ // Update UI
+ updateUI();
+};
+// Input handling
+function handleMove(x, y, obj) {
+ if (dragging && warrior) {
+ lastMoveX = x;
+ lastMoveY = y;
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ if (warrior) {
+ dragging = true;
+ lastMoveX = x;
+ lastMoveY = y;
+ // Fire in the direction opposite to the touch
+ var dx = x - warrior.x;
+ var dy = y - warrior.y;
+ warrior.fire(dx, dy);
+ }
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+};
+// Initialize game when script loads
+initGame();
\ No newline at end of file