/****
* 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