User prompt
the bomb does not show up when leveling up
User prompt
make a new bomb weapon explosive and slow. needs upgrade to unlock. star 1 + 25% explosion radius. star 2 + 50% firing speed. star 3 + 50% bomb speed. star 4 + 75% damage. star 5 + 50% explosion radius ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
change price of unlock evolution to 250
User prompt
add a extra upgrades button with a unlock evolution upgrade
User prompt
make so if all upgrades are picked the choose upgrade does not appear when leveling up
User prompt
make xp needed to level up 1.15x
User prompt
have 20 waves on arctic and a boss with 60000hp
User prompt
reduce the xp needed to level up to 1.1x
User prompt
add a 1.1x coins on desert and a 1.2x on arctic
User prompt
make desert have 15 waves and a 15000hp boss
User prompt
make desert map have 1.25x enemy hp per wave and arctic 1.3x and forest 1.2x
User prompt
make boss have 5x hp
User prompt
make a boss fight on wave 10 on forest map
User prompt
Remove the maps button and remove the standard gameplay text on the maps
User prompt
make all maps same difficulty
User prompt
make it so when you click play the map selection shows
User prompt
add a map selection
User prompt
rename speed upgrade and perma upgrade to walkspeed
User prompt
add a new shooting speed perma upgrade ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
make base money 1000 divided by time
User prompt
make perma upgrades more expensive ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
I only have 2 permanent levels on bow but I start with 5 levels
User prompt
add space between the permanent upgrades and the stars on them
User prompt
add little space between the stars on the permanent upgrades
User prompt
add levels 1-5 of every upgrade to permanent upgardes ↪💡 Consider importing and using the following plugins: @upit/storage.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.damage = baseArrowDamage;
self.directionX = 0;
self.directionY = 0;
self.lastEnemyCollisions = [];
self.isSeeking = false;
self.setDirection = function (dx, dy) {
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
self.rotation = Math.atan2(dy, dx);
}
};
self.update = function () {
var actualSpeed = self.speed * arrowSpeedMultiplier;
// Seeking behavior if bow evolution is active
if (self.isSeeking && enemies.length > 0) {
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
if (nearestEnemy) {
var dx = nearestEnemy.x - self.x;
var dy = nearestEnemy.y - self.y;
self.setDirection(dx, dy);
}
}
self.x += self.directionX * actualSpeed;
self.y += self.directionY * actualSpeed;
// Check collisions with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var currentCollision = self.intersects(enemy);
var lastCollision = self.lastEnemyCollisions[i] || false;
if (!lastCollision && currentCollision) {
// Hit enemy
LK.getSound('enemyHit').play();
LK.effects.flashObject(enemy, 0xFFFFFF, 200);
// Damage enemy
var isDead = enemy.takeDamage(self.damage);
if (isDead) {
// Remove enemy
enemies.splice(i, 1);
enemy.destroy();
}
// Remove arrow
if (arrows.indexOf(self) !== -1) {
arrows.splice(arrows.indexOf(self), 1);
self.destroy();
}
return;
}
self.lastEnemyCollisions[i] = currentCollision;
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5;
self.damage = 10;
self.targetX = 0;
self.targetY = 0;
self.lastPlayerCollision = false;
self.maxHealth = 30;
self.health = self.maxHealth;
// Create health bar background
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.3
});
healthBarBg.y = -40;
// Create health bar
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.3
});
healthBar.y = -40;
self.healthBar = healthBar;
self.healthBarBg = healthBarBg;
self.update = function () {
// Don't move when game is paused for upgrades
if (gamePaused) return;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
self.health = 0;
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
// Add tween animation for orb spawn
tween(xpOrb, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(xpOrb, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
return true; // Enemy is dead
}
return false; // Enemy is still alive
};
self.updateHealthBar = function () {
var healthPercentage = self.health / self.maxHealth;
self.healthBar.scaleX = 0.15 * healthPercentage;
if (healthPercentage > 0.6) {
self.healthBar.tint = 0x4CAF50;
} else if (healthPercentage > 0.3) {
self.healthBar.tint = 0xFFEB3B;
} else {
self.healthBar.tint = 0xFF5722;
}
};
return self;
});
var FastEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3.0;
self.damage = 10;
self.targetX = 0;
self.targetY = 0;
self.lastPlayerCollision = false;
self.maxHealth = 24;
self.health = self.maxHealth;
// Create health bar background
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.12,
scaleY: 0.25
});
healthBarBg.y = -35;
// Create health bar
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.12,
scaleY: 0.25
});
healthBar.y = -35;
self.healthBar = healthBar;
self.healthBarBg = healthBarBg;
self.update = function () {
// Don't move when game is paused for upgrades
if (gamePaused) return;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
self.health = 0;
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
// Add tween animation for orb spawn
tween(xpOrb, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(xpOrb, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
return true; // Enemy is dead
}
return false; // Enemy is still alive
};
self.updateHealthBar = function () {
var healthPercentage = self.health / self.maxHealth;
self.healthBar.scaleX = 0.12 * healthPercentage;
if (healthPercentage > 0.6) {
self.healthBar.tint = 0x4CAF50;
} else if (healthPercentage > 0.3) {
self.healthBar.tint = 0xFFEB3B;
} else {
self.healthBar.tint = 0xFF5722;
}
};
return self;
});
var HeavyEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('heavyEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.9; // Slower than regular enemies
self.damage = 15;
self.targetX = 0;
self.targetY = 0;
self.lastPlayerCollision = false;
self.maxHealth = 80; // More HP than regular enemies
self.health = self.maxHealth;
// Create health bar background
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.35
});
healthBarBg.y = -50;
// Create health bar
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.35
});
healthBar.y = -50;
self.healthBar = healthBar;
self.healthBarBg = healthBarBg;
self.update = function () {
// Don't move when game is paused for upgrades
if (gamePaused) return;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
self.health = 0;
// Drop Yellow XP orb worth 3x normal XP
var xpOrb = new YellowXPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
// Add tween animation for orb spawn
tween(xpOrb, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(xpOrb, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
return true; // Enemy is dead
}
return false; // Enemy is still alive
};
self.updateHealthBar = function () {
var healthPercentage = self.health / self.maxHealth;
self.healthBar.scaleX = 0.2 * healthPercentage;
if (healthPercentage > 0.6) {
self.healthBar.tint = 0x4CAF50;
} else if (healthPercentage > 0.3) {
self.healthBar.tint = 0xFFEB3B;
} else {
self.healthBar.tint = 0xFF5722;
}
};
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 = 100;
self.maxHealth = 100;
// Create player health bar background
var playerHealthBarBg = self.attachAsset('playerHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
playerHealthBarBg.y = -50;
// Create player health bar
var playerHealthBar = self.attachAsset('playerHealthBar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
playerHealthBar.y = -50;
self.playerHealthBar = playerHealthBar;
self.playerHealthBarBg = playerHealthBarBg;
self.speed = 1;
self.invulnerable = false;
self.invulnerableTime = 0;
self.takeDamage = function (damage) {
if (self.invulnerable) {
return;
}
self.health -= damage;
self.updatePlayerHealthBar();
self.invulnerable = true;
self.invulnerableTime = 60; // 1 second of invulnerability
LK.getSound('playerDamage').play();
LK.effects.flashObject(self, 0xFF0000, 500);
if (self.health <= 0) {
self.health = 0;
gameOver = true;
}
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
self.updatePlayerHealthBar();
};
self.updatePlayerHealthBar = function () {
var healthPercentage = self.health / self.maxHealth;
self.playerHealthBar.scaleX = 0.6 * healthPercentage;
if (healthPercentage > 0.6) {
self.playerHealthBar.tint = 0x4CAF50;
} else if (healthPercentage > 0.3) {
self.playerHealthBar.tint = 0xFFEB3B;
} else {
self.playerHealthBar.tint = 0xFF5722;
}
};
self.update = function () {
if (self.invulnerable) {
self.invulnerableTime--;
if (self.invulnerableTime <= 0) {
self.invulnerable = false;
}
}
};
return self;
});
var XPOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('xpOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.xpValue = 10;
self.attractDistance = baseMagnetRange;
self.attractSpeed = baseMagnetSpeed;
self.lastPlayerCollision = false;
self.update = function () {
// Don't attract when game is paused for upgrades
if (gamePaused) return;
// Check distance to player for attraction
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Attract to player if within range
if (distance < self.attractDistance && distance > 0) {
var moveSpeed = Math.min(self.attractSpeed, distance);
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
// Check collision with player
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
// Collect XP
playerXP += self.xpValue;
checkLevelUp();
LK.getSound('xpCollect').play();
// Remove orb
if (xpOrbs.indexOf(self) !== -1) {
xpOrbs.splice(xpOrbs.indexOf(self), 1);
self.destroy();
}
}
self.lastPlayerCollision = currentCollision;
};
return self;
});
var YellowXPOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('yellowXpOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.xpValue = 30; // 3x the normal XP value (normal is 10)
self.attractDistance = baseMagnetRange;
self.attractSpeed = baseMagnetSpeed;
self.lastPlayerCollision = false;
self.update = function () {
// Don't attract when game is paused for upgrades
if (gamePaused) return;
// Check distance to player for attraction
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Yellow orbs need magnet evolution to be pulled at long range
// If player has magnet evolution (level 6+), use full attract distance
// Otherwise, use base magnet range (50) for yellow orbs
var effectiveAttractDistance = self.attractDistance;
if (upgradeLevels[5] < 6) {
// No magnet evolution - use base range for yellow orbs
effectiveAttractDistance = 50;
}
// Attract to player if within range
if (distance < effectiveAttractDistance && distance > 0) {
var moveSpeed = Math.min(self.attractSpeed, distance);
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
}
// Check collision with player
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
// Collect XP
playerXP += self.xpValue;
checkLevelUp();
LK.getSound('xpCollect').play();
// Remove orb
if (xpOrbs.indexOf(self) !== -1) {
xpOrbs.splice(xpOrbs.indexOf(self), 1);
self.destroy();
}
}
self.lastPlayerCollision = currentCollision;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game state variables
var gameStarted = false;
var startScreen = null;
var playButton = null;
var upgradesScreen = null;
var upgradesScreenActive = false;
var upgradesScreenButtons = [];
// Create start screen
function createStartScreen() {
// Black background covering entire screen
startScreen = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0,
scaleX: 12,
scaleY: 20
});
startScreen.x = 0;
startScreen.y = 0;
startScreen.tint = 0x000000;
game.addChild(startScreen);
// Play button
playButton = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 2
});
playButton.x = 1024;
playButton.y = 2200;
playButton.tint = 0x4CAF50;
game.addChild(playButton);
// Play button text
var playButtonText = new Text2('PLAY', {
size: 100,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.x = 1024;
playButtonText.y = 2200;
game.addChild(playButtonText);
// Store reference to text for cleanup
playButton.buttonText = playButtonText;
// Permanent upgrades button
var upgradesButton = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 1.5
});
upgradesButton.x = 1024;
upgradesButton.y = 2350;
upgradesButton.tint = 0xFF9800;
game.addChild(upgradesButton);
// Permanent upgrades button text
var upgradesButtonText = new Text2('UPGRADES', {
size: 60,
fill: 0xFFFFFF
});
upgradesButtonText.anchor.set(0.5, 0.5);
upgradesButtonText.x = 1024;
upgradesButtonText.y = 2350;
game.addChild(upgradesButtonText);
// Store references for cleanup
playButton.upgradesButton = upgradesButton;
playButton.upgradesButtonText = upgradesButtonText;
}
// Remove start screen and begin game
function startGame() {
if (startScreen) {
startScreen.destroy();
startScreen = null;
}
if (playButton) {
playButton.buttonText.destroy();
if (playButton.upgradesButton) {
playButton.upgradesButton.destroy();
playButton.upgradesButtonText.destroy();
}
playButton.destroy();
playButton = null;
}
// Apply permanent upgrades
if (permanentUpgrades.bow > 0) {
// Apply bow upgrades based on permanent level
for (var bowLevel = 0; bowLevel < permanentUpgrades.bow; bowLevel++) {
applyBowUpgrade();
upgradeLevels[6]++;
}
}
if (permanentUpgrades.magnet > 0) {
baseMagnetRange = 50 * Math.pow(1.5, permanentUpgrades.magnet); // +50% range per level
upgradeLevels[5] = permanentUpgrades.magnet; // Set magnet upgrade level
baseMagnetSpeed = 8 + permanentUpgrades.magnet * 2; // +2 speed per level
}
if (permanentUpgrades.speed > 0) {
player.speed = 1 + permanentUpgrades.speed * 0.3; // +30% speed per level
}
player.updatePlayerHealthBar();
// Show UI elements and player
healthBarBg.visible = true;
healthBar.visible = true;
waveText.visible = true;
timeText.visible = true;
levelText.visible = true;
xpText.visible = true;
player.visible = true;
gameStarted = true;
}
// Permanent upgrades system
var permanentUpgrades = {
bow: storage.permanentBow || 0,
magnet: storage.permanentMagnet || 0,
speed: storage.permanentSpeed || 0,
coins: storage.coins || 0
};
function showUpgradesScreen() {
upgradesScreenActive = true;
// Clear existing buttons
clearUpgradesScreen();
// Black background
upgradesScreen = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0,
scaleX: 12,
scaleY: 20
});
upgradesScreen.x = 0;
upgradesScreen.y = 0;
upgradesScreen.tint = 0x000000;
game.addChild(upgradesScreen);
upgradesScreenButtons.push(upgradesScreen);
// Title
var titleText = new Text2('PERMANENT UPGRADES', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
upgradesScreenButtons.push(titleText);
// Coins display
var coinsText = new Text2('Coins: ' + permanentUpgrades.coins, {
size: 60,
fill: 0xFFFFFF
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 500;
game.addChild(coinsText);
upgradesScreenButtons.push(coinsText);
// Upgrade buttons - show all upgrades with their levels
var upgradeData = [{
name: 'Bow',
current: permanentUpgrades.bow,
cost: 100 + permanentUpgrades.bow * 50,
key: 'bow'
}, {
name: 'Magnet',
current: permanentUpgrades.magnet,
cost: 150 + permanentUpgrades.magnet * 60,
key: 'magnet'
}, {
name: 'Speed',
current: permanentUpgrades.speed,
cost: 200 + permanentUpgrades.speed * 70,
key: 'speed'
}];
for (var i = 0; i < upgradeData.length; i++) {
var upgrade = upgradeData[i];
var buttonY = 700 + i * 300;
var canAfford = permanentUpgrades.coins >= upgrade.cost && upgrade.current < 5;
var isMaxLevel = upgrade.current >= 5;
// Upgrade button
var upgradeButton = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 12,
scaleY: 3
});
upgradeButton.x = 1024;
upgradeButton.y = buttonY;
if (isMaxLevel) {
upgradeButton.tint = 0x333333;
} else {
upgradeButton.tint = canAfford ? 0x4CAF50 : 0x666666;
}
upgradeButton.upgradeKey = upgrade.key;
upgradeButton.upgradeCost = upgrade.cost;
upgradeButton.isMaxLevel = isMaxLevel;
game.addChild(upgradeButton);
upgradesScreenButtons.push(upgradeButton);
// Upgrade text
var upgradeText = new Text2(upgrade.name + ' Lv.' + upgrade.current, {
size: 100,
fill: 0xFFFFFF
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 1024;
upgradeText.y = buttonY - 40;
game.addChild(upgradeText);
upgradesScreenButtons.push(upgradeText);
// Cost text
var costText = new Text2(isMaxLevel ? 'MAX LEVEL' : 'Cost: ' + upgrade.cost, {
size: 70,
fill: isMaxLevel ? 0x999999 : canAfford ? 0xFFFFFF : 0x999999
});
costText.anchor.set(0.5, 0.5);
costText.x = 1024;
costText.y = buttonY + 40;
game.addChild(costText);
upgradesScreenButtons.push(costText);
// Add 5 stars below the button
var starY = buttonY + 130;
for (var s = 0; s < 5; s++) {
var star;
if (s < upgrade.current) {
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
} else {
star = LK.getAsset('starDark', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
}
star.x = 1024 - 100 + s * 70;
star.y = starY;
game.addChild(star);
upgradesScreenButtons.push(star);
}
}
// Back button
var backButton = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 1.5
});
backButton.x = 1024;
backButton.y = 2200;
backButton.tint = 0xFF5722;
backButton.isBackButton = true;
game.addChild(backButton);
upgradesScreenButtons.push(backButton);
var backButtonText = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 2200;
game.addChild(backButtonText);
upgradesScreenButtons.push(backButtonText);
}
function clearUpgradesScreen() {
for (var i = 0; i < upgradesScreenButtons.length; i++) {
upgradesScreenButtons[i].destroy();
}
upgradesScreenButtons = [];
}
function purchaseUpgrade(key, cost) {
if (permanentUpgrades.coins >= cost && permanentUpgrades[key] < 5) {
permanentUpgrades.coins -= cost;
permanentUpgrades[key]++; // Increase level by 1
// Save to storage
storage.coins = permanentUpgrades.coins;
if (key === 'bow') {
storage.permanentBow = permanentUpgrades[key];
} else if (key === 'magnet') {
storage.permanentMagnet = permanentUpgrades[key];
} else if (key === 'speed') {
storage.permanentSpeed = permanentUpgrades[key];
}
// Refresh screen
showUpgradesScreen();
}
}
// Initialize start screen
createStartScreen();
var player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
player.visible = false;
player.updatePlayerHealthBar();
var enemies = [];
var arrows = [];
var xpOrbs = [];
var gameOver = false;
var lastShootTime = 0;
var shootCooldown = 90; // 50% slower shooting rate
var waveNumber = 1;
var enemiesSpawned = 0;
var enemiesPerWave = 5;
var spawnTimer = 0;
var survivalTime = 0;
var dragNode = null;
var playerXP = 0;
var playerLevel = 1;
var xpToNextLevel = 10;
var healthRegenTimer = 0;
var healthRegenCooldown = 60; // 60 ticks = 1 second at 60 FPS
var gamePaused = false;
var upgradeChoices = [];
var upgradeButtons = [];
var upgradeLevels = [0, 0, 0, 0, 0, 0, 0]; // Track levels for each upgrade type
// Base arrow damage that will be used for all new arrows
var baseArrowDamage = 15;
// Base magnet range that will be used for all new XP orbs
var baseMagnetRange = 50;
// Base magnet speed that will be used for all new XP orbs
var baseMagnetSpeed = 8;
// Bow upgrade variables
var arrowsPerBurst = 1;
var arrowSpeedMultiplier = 1.0;
var bowEvolutionActive = false;
// Keyboard input state
var keys = {
w: false,
a: false,
s: false,
d: false
};
// UI Elements
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0
});
var healthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0
});
healthBarBg.visible = false;
healthBar.visible = false;
LK.gui.top.addChild(healthBarBg);
LK.gui.top.addChild(healthBar);
var waveText = new Text2('Wave: 1', {
size: 80,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
waveText.visible = false;
LK.gui.top.addChild(waveText);
var timeText = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeText.anchor.set(1, 0);
timeText.visible = false;
LK.gui.topRight.addChild(timeText);
var levelText = new Text2('Level: 1', {
size: 70,
fill: 0xFFD700
});
levelText.anchor.set(0, 0);
levelText.visible = false;
LK.gui.topLeft.addChild(levelText);
var xpText = new Text2('XP: 0/10', {
size: 50,
fill: 0x00BCD4
});
xpText.anchor.set(0, 0);
xpText.visible = false;
LK.gui.topLeft.addChild(xpText);
// Position UI elements
healthBarBg.y = 120;
healthBar.y = 120;
waveText.y = 200;
timeText.y = 280;
timeText.x = -20;
levelText.x = 120;
levelText.y = 20;
xpText.x = 120;
xpText.y = 100;
function checkLevelUp() {
if (playerXP >= xpToNextLevel) {
playerLevel++;
playerXP -= xpToNextLevel;
xpToNextLevel = Math.floor(xpToNextLevel * 1.2);
// Level up effects
LK.effects.flashScreen(0xFFD700, 800);
player.heal(20);
// Pause game and show upgrade choices
gamePaused = true;
showUpgradeChoices();
}
}
function showUpgradeChoices() {
// Clear any existing upgrade choices
clearUpgradeChoices();
// Create upgrade background
var upgradeBackground = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 10
});
upgradeBackground.x = 1024;
upgradeBackground.y = 1366;
upgradeBackground.alpha = 0.9;
game.addChild(upgradeBackground);
upgradeButtons.push(upgradeBackground);
// Create title
var titleText = new Text2('LEVEL UP!', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1100;
game.addChild(titleText);
upgradeButtons.push(titleText);
// Define possible upgrades
var allUpgrades = [{
name: 'Health Boost',
description: '+20 Max Health',
index: 0,
effect: function effect() {
player.maxHealth += 20;
player.heal(20);
upgradeLevels[0]++;
}
}, {
name: 'Faster Shooting',
description: 'Shoot 25% Faster',
index: 1,
effect: function effect() {
shootCooldown = Math.max(30, shootCooldown - 15);
upgradeLevels[1]++;
}
}, {
name: 'More Damage',
description: '+50% Arrow Damage',
index: 2,
effect: function effect() {
baseArrowDamage = Math.floor(baseArrowDamage * 1.5);
upgradeLevels[2]++;
}
}, {
name: 'Speed Boost',
description: 'Move 20% Faster',
index: 3,
effect: function effect() {
player.speed += 0.2;
upgradeLevels[3]++;
}
}, {
name: 'Health Regen',
description: 'Heal 2HP per second',
index: 4,
effect: function effect() {
healthRegenCooldown = Math.max(20, healthRegenCooldown - 10);
upgradeLevels[4]++;
}
}, {
name: upgradeLevels[5] === 5 ? 'Magnet Evolution I' : 'Magnet',
description: getMagnetUpgradeDescription(),
index: 5,
effect: function effect() {
applyMagnetUpgrade();
upgradeLevels[5]++;
}
}, {
name: upgradeLevels[6] === 5 ? 'Bow Evolution I' : 'Bow Upgrade',
description: getBowUpgradeDescription(),
index: 6,
effect: function effect() {
applyBowUpgrade();
upgradeLevels[6]++;
}
}];
// Select 3 random upgrades, excluding those with 5 stars
upgradeChoices = [];
var availableUpgrades = [];
// Filter out upgrades that have reached maximum level (11 levels for magnet and bow, 5 for others)
for (var u = 0; u < allUpgrades.length; u++) {
var upgrade = allUpgrades[u];
var maxLevel = upgrade.index === 5 || upgrade.index === 6 ? 11 : 5; // Magnet and bow have 11 levels (6 + 5 evolution), others have 5
if (upgradeLevels[upgrade.index] < maxLevel) {
availableUpgrades.push(upgrade);
}
}
// If we have available upgrades, select up to 3 random ones
var upgradeCount = Math.min(3, availableUpgrades.length);
for (var i = 0; i < upgradeCount; i++) {
var randomIndex = Math.floor(Math.random() * availableUpgrades.length);
upgradeChoices.push(availableUpgrades[randomIndex]);
availableUpgrades.splice(randomIndex, 1);
}
// Create upgrade buttons
for (var i = 0; i < upgradeChoices.length; i++) {
var upgrade = upgradeChoices[i];
var buttonX = 350 + i * 700; // Horizontal spacing from left to right
var buttonY = 1330;
// Button background
var buttonBg = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 3
});
buttonBg.x = buttonX;
buttonBg.y = buttonY;
// Make button red if it's magnet or bow evolution level 5 (evolution I)
if (upgrade.index === 5 && upgradeLevels[5] === 5 || upgrade.index === 6 && upgradeLevels[6] === 5) {
buttonBg.tint = 0xCC0000;
buttonBg.alpha = 0.7; // Make evolution upgrade box darker
} else {
buttonBg.tint = 0x4CAF50;
}
buttonBg.upgradeIndex = i;
game.addChild(buttonBg);
upgradeButtons.push(buttonBg);
// Button text
var buttonText = new Text2(upgrade.name, {
size: 80,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = buttonX;
buttonText.y = buttonY - 30;
game.addChild(buttonText);
upgradeButtons.push(buttonText);
// Description text
var descText = new Text2(upgrade.description, {
size: 60,
fill: 0xCCCCCC
});
descText.anchor.set(0.5, 0.5);
descText.x = buttonX;
descText.y = buttonY + 30;
game.addChild(descText);
upgradeButtons.push(descText);
// Add stars below button
var upgradeLevel = upgradeLevels[upgrade.index];
var starY = buttonY + 100;
var maxStars = upgrade.index === 5 || upgrade.index === 6 ? 6 : 5; // Magnet and bow have 6 stars, others have 5
var starsToShow = maxStars;
// For magnet and bow upgrades, calculate display stars based on evolution
var displayStars = upgradeLevel;
if (upgrade.index === 5 || upgrade.index === 6) {
// For evolution upgrades: levels 7+ show as stars 1-5, but with 6th star visible
if (upgradeLevel >= 7) {
displayStars = upgradeLevel - 6; // Convert level 7+ to display stars 1-5 (level 7 = 1 star, level 8 = 2 stars, etc.)
starsToShow = 6; // Show 6 stars when in post-evolution (5 regular + 1 red)
} else if (upgradeLevel <= 5) {
starsToShow = 5; // Only show 5 stars before evolution
} else if (upgradeLevel === 6) {
displayStars = 0; // Evolution level shows as 0 stars filled
starsToShow = 6; // Show 6 stars including red one
}
}
for (var s = 0; s < starsToShow; s++) {
var star;
// Special handling for magnet and bow evolution (level 6 and above)
if ((upgrade.index === 5 || upgrade.index === 6) && upgradeLevel >= 6) {
// When evolution is active, the 6th star should always be red
if (s === 5) {
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
star.tint = 0xFF0000; // Red color for evolution I
} else if (s < displayStars) {
// Show filled stars for current evolution level
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
// Show dark stars for unfilled evolution levels
star = LK.getAsset('starDark', {
anchorX: 0.5,
anchorY: 0.5
});
}
} else if ((upgrade.index === 5 || upgrade.index === 6) && (upgradeLevel === 5 || upgradeLevel === 6)) {
// Special case for evolution being available or just picked - don't show red star for level 5, show it for level 6
if (s === 5) {
if (upgradeLevel === 6) {
// Show red star for level 6
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
star.tint = 0xFF0000; // Red color for evolution I
} else {
// Don't show red star for level 5
star = LK.getAsset('starDark', {
anchorX: 0.5,
anchorY: 0.5
});
}
} else if (s < displayStars) {
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
star = LK.getAsset('starDark', {
anchorX: 0.5,
anchorY: 0.5
});
}
} else {
// Normal star display logic for all other cases
if (s < displayStars) {
star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
star = LK.getAsset('starDark', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Position stars - for magnet and bow (6 stars), put 6th star below first star
if ((upgrade.index === 5 || upgrade.index === 6) && s === 5) {
// 6th star for magnet/bow - position below the first star (star 0)
star.x = buttonX - 100 + 0 * 50; // Same x as first star
star.y = starY + 60; // Below the other stars
} else {
// Normal positioning for first 5 stars with increased spacing
star.x = buttonX - 100 + s * 50;
star.y = starY;
}
game.addChild(star);
upgradeButtons.push(star);
}
}
}
function getMagnetUpgradeDescription() {
var magnetLevel = upgradeLevels[5];
switch (magnetLevel) {
case 0:
case 1:
case 2:
case 3:
case 4:
return '+100% Magnet Range';
case 5:
return 'can pull yellow xp orbs';
case 6:
case 7:
case 8:
case 9:
case 10:
return '+25% Magnet Range';
case 11:
case 12:
case 13:
case 14:
return '+20% Pull Speed';
default:
return 'Max Level';
}
}
function getBowUpgradeDescription() {
var bowLevel = upgradeLevels[6];
switch (bowLevel) {
case 0:
return '+1 Arrow (Burst)';
case 1:
return '+100% Arrow Speed';
case 2:
return '+50% Arrow Damage';
case 3:
return '+25% Arrow Speed';
case 4:
return '+1 Arrow (Burst)';
case 5:
return 'seeking arrows';
case 6:
return '+25% Shoot Speed';
case 7:
return '+20% Arrow Speed';
case 8:
return '+1 Arrow';
case 9:
return '+50% Arrow Damage';
case 10:
return '+1 Arrow';
default:
return 'Max Level';
}
}
function applyMagnetUpgrade() {
var magnetLevel = upgradeLevels[5];
switch (magnetLevel) {
case 0:
case 1:
case 2:
case 3:
case 4:
// Levels 1-5: Double magnet range for all existing and future XP orbs
for (var o = 0; o < xpOrbs.length; o++) {
xpOrbs[o].attractDistance *= 2;
}
// Double base magnet range for new orbs
baseMagnetRange *= 2;
break;
case 5:
// Evolution: Double magnet pulling speed for all existing and future XP orbs
for (var o = 0; o < xpOrbs.length; o++) {
xpOrbs[o].attractSpeed *= 2;
}
// Double base magnet speed for new orbs
baseMagnetSpeed *= 2;
// Don't increment level for evolution - it stays at 5 until next upgrade
break;
case 6:
case 7:
case 8:
case 9:
case 10:
// Evolution level 6-10: +25% magnet range for all existing and future XP orbs
for (var o = 0; o < xpOrbs.length; o++) {
xpOrbs[o].attractDistance *= 1.25;
}
// +25% base magnet range for new orbs
baseMagnetRange *= 1.25;
break;
case 11:
case 12:
case 13:
case 14:
// Evolution levels 11-14: +20% pull speed for all existing and future XP orbs
for (var o = 0; o < xpOrbs.length; o++) {
xpOrbs[o].attractSpeed *= 1.2;
}
// +20% base magnet speed for new orbs
baseMagnetSpeed *= 1.2;
break;
}
}
function applyBowUpgrade() {
var bowLevel = upgradeLevels[6];
switch (bowLevel) {
case 0:
// Level 1: +1 arrow (burst)
arrowsPerBurst = 2;
break;
case 1:
// Level 2: +100% arrow speed
arrowSpeedMultiplier *= 2.0;
break;
case 2:
// Level 3: +50% arrow damage
baseArrowDamage = Math.floor(baseArrowDamage * 1.5);
break;
case 3:
// Level 4: +25% arrow speed
arrowSpeedMultiplier *= 1.25;
break;
case 4:
// Level 5: +1 arrow (burst)
arrowsPerBurst = 3;
break;
case 5:
// Evolution: seeking arrows
bowEvolutionActive = true;
break;
case 6:
// Evolution level 1: +25% shoot speed
shootCooldown = Math.floor(shootCooldown * 0.75);
break;
case 7:
// Evolution level 2: +20% arrow speed
arrowSpeedMultiplier *= 1.2;
break;
case 8:
// Evolution level 3: +1 arrow
arrowsPerBurst++;
break;
case 9:
// Evolution level 4: +50% arrow damage
baseArrowDamage = Math.floor(baseArrowDamage * 1.5);
break;
case 10:
// Evolution level 5: +1 arrow
arrowsPerBurst++;
break;
}
}
function clearUpgradeChoices() {
for (var i = 0; i < upgradeButtons.length; i++) {
upgradeButtons[i].destroy();
}
upgradeButtons = [];
upgradeChoices = [];
}
function selectUpgrade(index) {
if (index >= 0 && index < upgradeChoices.length) {
// Apply upgrade effect
upgradeChoices[index].effect();
// Clear upgrade UI
clearUpgradeChoices();
// Resume game
gamePaused = false;
}
}
function spawnEnemy() {
var enemy;
if (waveNumber >= 5 && Math.random() < 0.15) {
enemy = new HeavyEnemy();
} else if (waveNumber >= 3 && Math.random() < 0.3) {
enemy = new FastEnemy();
} else {
enemy = new Enemy();
}
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
enemy.targetX = player.x;
enemy.targetY = player.y;
enemy.speed += Math.floor(waveNumber / 3) * 0.5;
// Scale enemy health by 1.3x per wave
var healthMultiplier = Math.pow(1.3, waveNumber - 1);
enemy.maxHealth = Math.floor(enemy.maxHealth * healthMultiplier);
enemy.health = enemy.maxHealth;
enemy.updateHealthBar();
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
function updateHealthBar() {
var healthPercentage = player.health / player.maxHealth;
healthBar.width = 400 * healthPercentage;
if (healthPercentage > 0.6) {
healthBar.tint = 0x4CAF50;
} else if (healthPercentage > 0.3) {
healthBar.tint = 0xFFEB3B;
} else {
healthBar.tint = 0xFF5722;
}
}
function handleMove(x, y, obj) {
if (dragNode && !gameOver) {
var newX = Math.max(40, Math.min(2008, x));
var newY = Math.max(40, Math.min(2692, y));
var dx = newX - dragNode.x;
var dy = newY - dragNode.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var moveDistance = Math.min(distance, 8 * dragNode.speed);
dragNode.x += dx / distance * moveDistance;
dragNode.y += dy / distance * moveDistance;
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (!gameStarted) {
if (upgradesScreenActive) {
// Handle upgrades screen clicks
for (var i = 0; i < upgradesScreenButtons.length; i++) {
var button = upgradesScreenButtons[i];
if (button.isBackButton) {
// Back button - return to main menu
var buttonWidth = 60 * 3;
var buttonHeight = 60 * 1.5;
var buttonLeft = button.x - buttonWidth / 2;
var buttonRight = button.x + buttonWidth / 2;
var buttonTop = button.y - buttonHeight / 2;
var buttonBottom = button.y + buttonHeight / 2;
if (x >= buttonLeft && x <= buttonRight && y >= buttonTop && y <= buttonBottom) {
upgradesScreenActive = false;
clearUpgradesScreen();
createStartScreen();
return;
}
} else if (button.upgradeKey) {
// Upgrade button
var buttonWidth = 60 * 12;
var buttonHeight = 60 * 3;
var buttonLeft = button.x - buttonWidth / 2;
var buttonRight = button.x + buttonWidth / 2;
var buttonTop = button.y - buttonHeight / 2;
var buttonBottom = button.y + buttonHeight / 2;
if (x >= buttonLeft && x <= buttonRight && y >= buttonTop && y <= buttonBottom && !button.isMaxLevel) {
purchaseUpgrade(button.upgradeKey, button.upgradeCost);
return;
}
}
}
return;
}
// Check if play button was clicked
if (playButton) {
var buttonWidth = 60 * 4; // 240
var buttonHeight = 60 * 2; // 120
var buttonLeft = playButton.x - buttonWidth / 2;
var buttonRight = playButton.x + buttonWidth / 2;
var buttonTop = playButton.y - buttonHeight / 2;
var buttonBottom = playButton.y + buttonHeight / 2;
if (x >= buttonLeft && x <= buttonRight && y >= buttonTop && y <= buttonBottom) {
startGame();
return;
}
// Check if upgrades button was clicked
if (playButton.upgradesButton) {
var upgradesButtonWidth = 60 * 3;
var upgradesButtonHeight = 60 * 1.5;
var upgradesButtonLeft = playButton.upgradesButton.x - upgradesButtonWidth / 2;
var upgradesButtonRight = playButton.upgradesButton.x + upgradesButtonWidth / 2;
var upgradesButtonTop = playButton.upgradesButton.y - upgradesButtonHeight / 2;
var upgradesButtonBottom = playButton.upgradesButton.y + upgradesButtonHeight / 2;
if (x >= upgradesButtonLeft && x <= upgradesButtonRight && y >= upgradesButtonTop && y <= upgradesButtonBottom) {
// Hide start screen and show upgrades screen
if (startScreen) {
startScreen.destroy();
startScreen = null;
}
playButton.buttonText.destroy();
playButton.upgradesButton.destroy();
playButton.upgradesButtonText.destroy();
playButton.destroy();
playButton = null;
showUpgradesScreen();
return;
}
}
}
return;
}
if (!gameOver) {
// Check if we're in upgrade selection mode
if (gamePaused && upgradeButtons.length > 0) {
// Check if clicked on an upgrade button
for (var i = 0; i < upgradeButtons.length; i++) {
var button = upgradeButtons[i];
if (button.upgradeIndex !== undefined) {
// Check if click position is within button bounds
// Button is scaled 6x horizontally and 3x vertically from base enemy size (60x60)
var buttonWidth = 60 * 6; // 360
var buttonHeight = 60 * 3; // 180
var buttonLeft = button.x - buttonWidth / 2;
var buttonRight = button.x + buttonWidth / 2;
var buttonTop = button.y - buttonHeight / 2;
var buttonBottom = button.y + buttonHeight / 2;
if (x >= buttonLeft && x <= buttonRight && y >= buttonTop && y <= buttonBottom) {
selectUpgrade(button.upgradeIndex);
return;
}
}
}
} else {
dragNode = player;
handleMove(x, y, obj);
}
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Keyboard event listeners
LK.on('keydown', function (event) {
switch (event.key.toLowerCase()) {
case 'w':
keys.w = true;
break;
case 'a':
keys.a = true;
break;
case 's':
keys.s = true;
break;
case 'd':
keys.d = true;
break;
}
});
LK.on('keyup', function (event) {
switch (event.key.toLowerCase()) {
case 'w':
keys.w = false;
break;
case 'a':
keys.a = false;
break;
case 's':
keys.s = false;
break;
case 'd':
keys.d = false;
break;
}
});
game.update = function () {
if (!gameStarted || gameOver) return;
// Check pause state before any updates
if (gamePaused) return;
survivalTime++;
// Handle WASD movement
var moveSpeed = 5;
if (keys.w) {
player.y = Math.max(40, player.y - moveSpeed);
}
if (keys.s) {
player.y = Math.min(2692, player.y + moveSpeed);
}
if (keys.a) {
player.x = Math.max(40, player.x - moveSpeed);
}
if (keys.d) {
player.x = Math.min(2008, player.x + moveSpeed);
}
// Health regeneration
healthRegenTimer++;
if (healthRegenTimer >= healthRegenCooldown && player.health < player.maxHealth) {
player.heal(1);
healthRegenTimer = 0;
}
// Update UI
updateHealthBar();
waveText.setText('Wave: ' + waveNumber);
timeText.setText('Time: ' + Math.floor(survivalTime / 60) + 's');
levelText.setText('Level: ' + playerLevel);
xpText.setText('XP: ' + playerXP + '/' + xpToNextLevel);
// Enemy spawning
spawnTimer++;
var spawnRate = Math.max(15, 60 - waveNumber * 3);
if (spawnTimer >= spawnRate && enemiesSpawned < enemiesPerWave) {
spawnEnemy();
spawnTimer = 0;
}
// Auto-shoot arrows at nearest enemy
lastShootTime++;
if (lastShootTime >= shootCooldown && enemies.length > 0) {
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
var dx = enemy.x - player.x;
var dy = enemy.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
if (nearestEnemy) {
var baseDx = nearestEnemy.x - player.x;
var baseDy = nearestEnemy.y - player.y;
// Fire multiple arrows in a burst
for (var b = 0; b < arrowsPerBurst; b++) {
// Add delay for burst arrows so they fire sequentially
if (b > 0) {
LK.setTimeout(function (burstIndex) {
return function () {
var arrow = new Arrow();
arrow.x = player.x;
arrow.y = player.y;
var dx = baseDx;
var dy = baseDy;
// All arrows fire in same direction
arrow.setDirection(dx, dy);
// Enable seeking if bow evolution is active
arrow.isSeeking = bowEvolutionActive;
arrows.push(arrow);
game.addChild(arrow);
};
}(b), b * 100); // 100ms delay between each arrow
} else {
// Fire first arrow immediately
var arrow = new Arrow();
arrow.x = player.x;
arrow.y = player.y;
var dx = baseDx;
var dy = baseDy;
// All arrows fire in same direction
arrow.setDirection(dx, dy);
// Enable seeking if bow evolution is active
arrow.isSeeking = bowEvolutionActive;
arrows.push(arrow);
game.addChild(arrow);
}
}
LK.getSound('arrowShoot').play();
lastShootTime = 0;
}
}
// Update arrows
for (var a = arrows.length - 1; a >= 0; a--) {
var arrow = arrows[a];
// Remove arrows that are off screen
if (arrow.x < -100 || arrow.x > 2148 || arrow.y < -100 || arrow.y > 2832) {
arrows.splice(a, 1);
arrow.destroy();
}
}
// Update XP orbs
for (var x = xpOrbs.length - 1; x >= 0; x--) {
var xpOrb = xpOrbs[x];
// Remove orbs that are too far off screen
if (xpOrb.x < -200 || xpOrb.x > 2248 || xpOrb.y < -200 || xpOrb.y > 2932) {
xpOrbs.splice(x, 1);
xpOrb.destroy();
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.targetX = player.x;
enemy.targetY = player.y;
// Remove enemies that are too far off screen
if (enemy.x < -200 || enemy.x > 2248 || enemy.y < -200 || enemy.y > 2932) {
enemies.splice(i, 1);
enemy.destroy();
}
}
// Check wave completion
if (enemiesSpawned >= enemiesPerWave && enemies.length === 0) {
waveNumber++;
enemiesSpawned = 0;
enemiesPerWave = Math.min(20, 5 + waveNumber * 2);
// Bonus health for completing wave
player.heal(10);
LK.effects.flashScreen(0x4CAF50, 500);
// Check if player completed all 10 waves
if (waveNumber > 10) {
gameOver = true;
// Save best survival time
var bestTime = storage.bestTime || 0;
if (survivalTime > bestTime) {
storage.bestTime = survivalTime;
}
// Save total waves completed
var totalWaves = storage.totalWaves || 0;
storage.totalWaves = totalWaves + 10; // Completed all 10 waves
// Award bonus coins for completing all waves
var coinsEarned = Math.floor(survivalTime / 60) + 10 * 5 + 50; // Extra 50 coins for victory
permanentUpgrades.coins += coinsEarned;
storage.coins = permanentUpgrades.coins;
LK.setScore(Math.floor(survivalTime / 60) + 10 * 10);
LK.effects.flashScreen(0xFFD700, 1000);
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
}
}
// Game over check
if (player.health <= 0) {
gameOver = true;
// Save best survival time
var bestTime = storage.bestTime || 0;
if (survivalTime > bestTime) {
storage.bestTime = survivalTime;
}
// Save total waves completed
var totalWaves = storage.totalWaves || 0;
storage.totalWaves = totalWaves + (waveNumber - 1);
// Award coins based on performance
var coinsEarned = Math.floor(survivalTime / 60) + (waveNumber - 1) * 5;
permanentUpgrades.coins += coinsEarned;
storage.coins = permanentUpgrades.coins;
LK.setScore(Math.floor(survivalTime / 60) + (waveNumber - 1) * 10);
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
}; ===================================================================
--- original.js
+++ change.js
@@ -677,19 +677,19 @@
// Upgrade buttons - show all upgrades with their levels
var upgradeData = [{
name: 'Bow',
current: permanentUpgrades.bow,
- cost: 50 + permanentUpgrades.bow * 25,
+ cost: 100 + permanentUpgrades.bow * 50,
key: 'bow'
}, {
name: 'Magnet',
current: permanentUpgrades.magnet,
- cost: 75 + permanentUpgrades.magnet * 30,
+ cost: 150 + permanentUpgrades.magnet * 60,
key: 'magnet'
}, {
name: 'Speed',
current: permanentUpgrades.speed,
- cost: 100 + permanentUpgrades.speed * 35,
+ cost: 200 + permanentUpgrades.speed * 70,
key: 'speed'
}];
for (var i = 0; i < upgradeData.length; i++) {
var upgrade = upgradeData[i];