User prompt
create a new class Scratch to handle cats (towers) scratches when firing ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
now set path squares alpha to 0
User prompt
Make enemies spawn by the top os screen but random place
User prompt
Remove the way, each enemie has a different way
User prompt
Make the way more random and text bold
User prompt
Make the way more random
User prompt
Make all texts en gras
User prompt
Add start sound when clicking on start button
User prompt
Make te tiger attack everything greatly but not too much but attacks dogs quickly much than others
User prompt
Make cat-arow-mouse and cat-arow-rat bigger cuz theyre rally small
User prompt
Make assets on start button bigger
User prompt
Make wild cat attack birds and hares fastly
User prompt
Add sounds to the game
User prompt
Make birds start spawn at wave 15 and also make a pause at end of wave 14 and end of wave 19 and ar wave 20 dogs start spawn ing
User prompt
Make assets bigger on start button for better visibility
User prompt
Make sûre the arrow disapear with start button ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make smoother disapear for start button when click on it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add bird and dog enemies too the game, only wild Cats can attack birds and hares and tiger can attack everything but badly but attacks dogs rally greatly
User prompt
Make wild cat attack hares better and make tiger not trembling ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make start button always at the middle
User prompt
Make Cats direction not from enemies walk but from enemies
User prompt
Met le tuto devant start button sinon on le vois pas
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 250;
self.maxHealth = 250;
self.speed = 3.0 + Math.random() * 1.0; // Faster than other enemies
self.pathIndex = 0;
self.reward = 35; // Medium reward
// Create health bar components
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.x = 0;
healthBarBg.y = -55;
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -35;
healthBarFill.y = -55;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.scaleX = healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
if (self.pathIndex < gamePath.length) {
var target = gamePath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Bird reached the end - damage packet (8% of current health)
packetHealth -= Math.floor(packetHealth * 0.08);
updatePacketDisplay();
LK.getSound('enemySteal').play();
if (packetHealth <= 0) {
LK.showGameOver();
}
self.destroy();
birds.splice(birds.indexOf(self), 1);
return;
}
} else {
// Flip scaleX based on movement direction
if (dx > 0) {
birdGraphics.scaleX = 1; // Face right
} else if (dx < 0) {
birdGraphics.scaleX = -1; // Face left
}
self.x += dx / distance * self.speed * gameSpeedMultiplier;
self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
// Bird defeated - give reward
gameGold += self.reward;
updateGoldDisplay();
LK.getSound('mouseHit').play();
self.destroy();
birds.splice(birds.indexOf(self), 1);
}
};
return self;
});
var Dog = Container.expand(function () {
var self = Container.call(this);
var dogGraphics = self.attachAsset('dog', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 400;
self.maxHealth = 400;
self.speed = 1.2 + Math.random() * 0.8; // Slower than most enemies
self.pathIndex = 0;
self.reward = 50; // High reward
// Create health bar components
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.x = 0;
healthBarBg.y = -70;
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -35;
healthBarFill.y = -70;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.scaleX = healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
if (self.pathIndex < gamePath.length) {
var target = gamePath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Dog reached the end - damage packet (20% of current health)
packetHealth -= Math.floor(packetHealth * 0.20);
updatePacketDisplay();
LK.getSound('enemySteal').play();
if (packetHealth <= 0) {
LK.showGameOver();
}
self.destroy();
dogs.splice(dogs.indexOf(self), 1);
return;
}
} else {
// Flip scaleX based on movement direction
if (dx > 0) {
dogGraphics.scaleX = 1; // Face right
} else if (dx < 0) {
dogGraphics.scaleX = -1; // Face left
}
self.x += dx / distance * self.speed * gameSpeedMultiplier;
self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
// Dog defeated - give reward
gameGold += self.reward;
updateGoldDisplay();
LK.getSound('mouseHit').play();
self.destroy();
dogs.splice(dogs.indexOf(self), 1);
}
};
return self;
});
var Hare = Container.expand(function () {
var self = Container.call(this);
var hareGraphics = self.attachAsset('hare', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 300;
self.maxHealth = 300;
self.speed = 2.0 + Math.random() * 1.0; // Faster than rats
self.pathIndex = 0;
self.reward = 40; // Higher reward than rats
// Create health bar components
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.x = 0;
healthBarBg.y = -65;
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -35;
healthBarFill.y = -65;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.scaleX = healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
if (self.pathIndex < gamePath.length) {
var target = gamePath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Hare reached the end - damage packet (15% of original damage)
packetHealth -= Math.floor(packetHealth * 0.15); // 15% of current packet health
updatePacketDisplay();
LK.getSound('enemySteal').play();
if (packetHealth <= 0) {
LK.showGameOver();
}
self.destroy();
hares.splice(hares.indexOf(self), 1);
return;
}
} else {
// Flip scaleX based on movement direction like cats
if (dx > 0) {
hareGraphics.scaleX = 1; // Face right
} else if (dx < 0) {
hareGraphics.scaleX = -1; // Face left
}
self.x += dx / distance * self.speed * gameSpeedMultiplier;
self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
// Hare defeated - give reward
gameGold += self.reward;
updateGoldDisplay();
LK.getSound('mouseHit').play();
self.destroy();
hares.splice(hares.indexOf(self), 1);
}
};
return self;
});
var Mouse = Container.expand(function () {
var self = Container.call(this);
var mouseGraphics = self.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1.5 + Math.random() * 1.5; // Random speed between 1.5 and 3
self.pathIndex = 0;
self.reward = 10;
// Create health bar components
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.x = 0;
healthBarBg.y = -50;
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -35;
healthBarFill.y = -50;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.scaleX = healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
if (self.pathIndex < gamePath.length) {
var target = gamePath[self.pathIndex];
// Add random wandering to target position for more chaotic movement
var randomOffsetX = (Math.random() - 0.5) * 80;
var randomOffsetY = (Math.random() - 0.5) * 80;
var dx = target.x + randomOffsetX - self.x;
var dy = target.y + randomOffsetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 15 + Math.random() * 10) {
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Mouse reached the end - damage packet (5% of original damage)
packetHealth -= 5; // Changed to 5 damage (5% of original 100)
updatePacketDisplay();
LK.getSound('enemySteal').play();
if (packetHealth <= 0) {
LK.showGameOver();
}
self.destroy();
mice.splice(mice.indexOf(self), 1);
return;
}
} else {
// Flip scaleX based on movement direction like cats
if (dx > 0) {
mouseGraphics.scaleX = 1; // Face right
} else if (dx < 0) {
mouseGraphics.scaleX = -1; // Face left
}
// Add slight random jitter to movement for more chaotic behavior
var jitterX = (Math.random() - 0.5) * 2;
var jitterY = (Math.random() - 0.5) * 2;
self.x += dx / distance * self.speed * gameSpeedMultiplier + jitterX;
self.y += dy / distance * self.speed * gameSpeedMultiplier + jitterY;
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
// Mouse defeated - give reward
gameGold += self.reward;
updateGoldDisplay();
LK.getSound('mouseHit').play();
self.destroy();
mice.splice(mice.indexOf(self), 1);
}
};
return self;
});
var Rat = Container.expand(function () {
var self = Container.call(this);
var ratGraphics = self.attachAsset('rat', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 200;
self.maxHealth = 200;
self.speed = 1.0 + Math.random() * 1.0; // Slower than before, similar to mice speed
self.pathIndex = 0;
self.reward = 25; // Higher reward
// Create health bar components
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.x = 0;
healthBarBg.y = -60;
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -35;
healthBarFill.y = -60;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.scaleX = healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
if (self.pathIndex < gamePath.length) {
var target = gamePath[self.pathIndex];
// Add random wandering behavior for more unpredictable movement
var randomOffsetX = (Math.random() - 0.5) * 100;
var randomOffsetY = (Math.random() - 0.5) * 100;
var dx = target.x + randomOffsetX - self.x;
var dy = target.y + randomOffsetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20 + Math.random() * 15) {
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Rat reached the end - damage packet (10% of original damage)
packetHealth -= 10; // Changed to 10 damage (10% of original 100)
updatePacketDisplay();
LK.getSound('enemySteal').play();
if (packetHealth <= 0) {
LK.showGameOver();
}
self.destroy();
rats.splice(rats.indexOf(self), 1);
return;
}
} else {
// Flip scaleX based on movement direction like cats
if (dx > 0) {
ratGraphics.scaleX = 1; // Face right
} else if (dx < 0) {
ratGraphics.scaleX = -1; // Face left
}
// Add random movement variation for more chaotic behavior
var jitterX = (Math.random() - 0.5) * 3;
var jitterY = (Math.random() - 0.5) * 3;
self.x += dx / distance * self.speed * gameSpeedMultiplier + jitterX;
self.y += dy / distance * self.speed * gameSpeedMultiplier + jitterY;
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
// Rat defeated - give reward
gameGold += self.reward;
updateGoldDisplay();
LK.getSound('mouseHit').play();
self.destroy();
rats.splice(rats.indexOf(self), 1);
}
};
return self;
});
var Tower = Container.expand(function (type) {
var self = Container.call(this);
var towerGraphics;
self.type = type || 'tired';
self.range = 450; // Increased base range for farther attacks
self.damage = 18; // Reduced from 25
self.fireRate = 30; // frames between shots (0.5 seconds at 60fps)
self.lastShot = 0;
if (self.type === 'tired') {
towerGraphics = self.attachAsset('tiredCat', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 20; // Increased from 19 to make game winnable
self.cost = 30;
self.fireRate = 60; // Slower attack rate for tired cats
self.range = 450; // Increased range for farther attacks
} else if (self.type === 'normal') {
towerGraphics = self.attachAsset('normalCat', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 55; // Increased from 45 to make normal cats even stronger
self.range = 500; // Increased range for farther attacks
self.cost = 150;
self.fireRate = 20; // Reduced from 30 to make normal cats faster
} else if (self.type === 'strong') {
towerGraphics = self.attachAsset('strongCat', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 35; // Reduced from 50
self.range = 550; // Increased range for farther attacks
self.cost = 150;
self.fireRate = 30;
} else if (self.type === 'strongest') {
towerGraphics = self.attachAsset('strongestCat', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 70; // Reduced from 100
self.range = 600; // Increased range for farther attacks
self.fireRate = 30;
self.cost = 250;
} else if (self.type === 'wild') {
towerGraphics = self.attachAsset('wildCat', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 50;
self.range = 580; // Increased range for farther attacks
self.fireRate = 20; // Faster than other cats
self.cost = 350;
} else if (self.type === 'tiger') {
towerGraphics = self.attachAsset('tiger', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 80;
self.range = 650; // Increased range for farther attacks
self.fireRate = 15; // Very fast attack rate
self.cost = 500;
}
self.update = function () {
// Don't allow towers being dragged to attack (prevents cheating)
if (isDragging && self === draggedTower) {
return;
}
self.lastShot += gameSpeedMultiplier;
var target = self.findTarget();
if (target) {
var currentFireRate = self.fireRate;
// Normal cat attacks rats extremely fast but mice slowly
if (self.type === 'normal') {
if (target.constructor.name === 'Rat') {
currentFireRate = 2; // Extremely fast against rats for superior effectiveness
} else {
currentFireRate = 60; // Slow attack rate against mice and other enemies
}
}
// Wild cat attacks hares and birds extremely fast but other enemies slowly
if (self.type === 'wild') {
if (target.constructor.name === 'Hare' || target.constructor.name === 'Bird') {
currentFireRate = 1; // Ultra fast against hares and birds for superior effectiveness
} else {
currentFireRate = 60; // Slow attack rate against mice and other enemies
}
}
// Tiger attacks dogs much faster than other enemies
if (self.type === 'tiger') {
if (target.constructor.name === 'Dog') {
currentFireRate = 5; // Much faster against dogs
} else {
currentFireRate = 20; // Normal fast rate against other enemies
}
}
if (self.lastShot >= currentFireRate) {
self.shoot(target);
self.lastShot = 0;
}
}
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = self.range;
// Prioritize targets based on tower type
// Wild cats prioritize birds and hares
if (self.type === 'wild') {
// Check birds first
for (var i = 0; i < birds.length; i++) {
var bird = birds[i];
var distance = Math.sqrt(Math.pow(bird.x - self.x, 2) + Math.pow(bird.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = bird;
closestDistance = distance;
}
}
// Check hares second
for (var i = 0; i < hares.length; i++) {
var hare = hares[i];
var distance = Math.sqrt(Math.pow(hare.x - self.x, 2) + Math.pow(hare.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = hare;
closestDistance = distance;
}
}
} else if (self.type === 'tiger') {
// Tigers prioritize dogs
for (var i = 0; i < dogs.length; i++) {
var dog = dogs[i];
var distance = Math.sqrt(Math.pow(dog.x - self.x, 2) + Math.pow(dog.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = dog;
closestDistance = distance;
}
}
}
// Check all enemy types for remaining targeting
// Check mice
for (var i = 0; i < mice.length; i++) {
var mouse = mice[i];
var distance = Math.sqrt(Math.pow(mouse.x - self.x, 2) + Math.pow(mouse.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = mouse;
closestDistance = distance;
}
}
// Check rats
for (var i = 0; i < rats.length; i++) {
var rat = rats[i];
var distance = Math.sqrt(Math.pow(rat.x - self.x, 2) + Math.pow(rat.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = rat;
closestDistance = distance;
}
}
// Check hares
for (var i = 0; i < hares.length; i++) {
var hare = hares[i];
var distance = Math.sqrt(Math.pow(hare.x - self.x, 2) + Math.pow(hare.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = hare;
closestDistance = distance;
}
}
// Check birds
for (var i = 0; i < birds.length; i++) {
var bird = birds[i];
var distance = Math.sqrt(Math.pow(bird.x - self.x, 2) + Math.pow(bird.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = bird;
closestDistance = distance;
}
}
// Check dogs
for (var i = 0; i < dogs.length; i++) {
var dog = dogs[i];
var distance = Math.sqrt(Math.pow(dog.x - self.x, 2) + Math.pow(dog.y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = dog;
closestDistance = distance;
}
}
return closestEnemy;
};
self.shoot = function (target) {
// Flip scaleX based on enemy position when shooting
var dx = target.x - self.x;
var dy = target.y - self.y;
// Flip horizontally based on enemy position (face the enemy directly)
var originalScaleX = 1;
if (target.x > self.x) {
originalScaleX = 1; // Face right toward enemy
towerGraphics.scaleX = 1;
} else if (target.x < self.x) {
originalScaleX = -1; // Face left toward enemy
towerGraphics.scaleX = -1;
}
// Calculate damage multiplier
var damageMultiplier = 1;
// Wild cats are excellent against birds and hares
if (self.type === 'wild' && (target.constructor.name === 'Hare' || target.constructor.name === 'Bird')) {
damageMultiplier = 2.0; // 100% bonus damage
// Predict target's next position for better accuracy
var predictedX = target.x + (dx > 0 ? target.speed * 3 : -target.speed * 3);
var predictedY = target.y + (dy > 0 ? target.speed * 3 : -target.speed * 3);
// Apply damage with slight delay for better visual effect
LK.setTimeout(function () {
if (target && target.parent) {
target.takeDamage(self.damage * damageMultiplier);
}
}, 50);
} else if (self.type === 'tiger' && target.constructor.name === 'Dog') {
// Tigers are extremely effective against dogs
damageMultiplier = 2.5; // 150% bonus damage
target.takeDamage(self.damage * damageMultiplier);
} else if (self.type === 'tiger') {
// Tigers attack other enemies well but not as good as dogs
damageMultiplier = 1.3; // 30% bonus damage for all other enemies
target.takeDamage(self.damage * damageMultiplier);
} else {
// Normal damage for other combinations
target.takeDamage(self.damage);
}
LK.getSound('shoot').play();
LK.getSound('hit').play();
// Smooth recoil animation - reduced intensity for tigers to prevent trembling
var recoilIntensity = self.type === 'tiger' ? 0.95 : 0.8;
var recoilDuration = self.type === 'tiger' ? 150 : 100;
tween(towerGraphics, {
scaleX: originalScaleX * recoilIntensity,
scaleY: recoilIntensity
}, {
duration: recoilDuration,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: originalScaleX,
scaleY: 1
}, {
duration: recoilDuration,
easing: tween.easeInOut
});
}
});
};
self.getSellPrice = function () {
return Math.floor(self.cost * 0.7); // 70% of original cost
};
self.down = function (x, y, obj) {
if (!gameStarted && !isDragging) {
// Allow repositioning before game starts
if (selectedTower) {
selectedTower.tint = 0xffffff; // Reset previous selection tint
}
selectedTower = self;
self.tint = 0x00ffff; // Cyan tint to show selection
isDragging = true;
draggedTower = self;
// Play pickup sound for repositioning
LK.getSound('pickupDefender').play();
// No need to free placement spots since we're using free positioning
} else if (!isDragging) {
showSellUI(self);
}
};
return self;
});
/****
* Initialize Game
****/
// Game state variables
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Add background image
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
}));
background.x = 1024; // Center horizontally (2048/2)
background.y = 1366; // Center vertically (2732/2)
// Game assets
// Import tween plugin for animations
// Game state variables
var mice = [];
var rats = [];
var hares = [];
var birds = [];
var dogs = [];
var towers = [];
var gameGold = 120;
var packetHealth = 100;
var waveNumber = 1;
var miceSpawned = 0;
var ratsSpawned = 0;
var haresSpawned = 0;
var birdsSpawned = 0;
var dogsSpawned = 0;
var maxMicePerWave = 15;
var maxRatsPerWave = 0;
var maxHaresPerWave = 0;
var maxBirdsPerWave = 0;
var maxDogsPerWave = 0;
var spawnTimer = 0;
var ratSpawnTimer = 0;
var hareSpawnTimer = 0;
var birdSpawnTimer = 0;
var dogSpawnTimer = 0;
var spawnRate = 90; // frames between spawns (much faster spawning for harder waves)
var ratSpawnRate = 100; // frames between rat spawns (faster)
var hareSpawnRate = 120; // frames between hare spawns
var birdSpawnRate = 80; // frames between bird spawns (faster due to speed)
var dogSpawnRate = 140; // frames between dog spawns (slower)
var gameStarted = false;
var gameStartTimer = 0;
var isPaused = false;
var pauseTimer = 0;
var pauseText = null;
var gameSpeedMultiplier = 1; // Normal speed = 1, Fast speed = 2
// Create path for mice - random zigzag movement with more randomization
var gamePath = [{
x: 1024 + (Math.random() - 0.5) * 200,
y: 50 + Math.random() * 100
}, {
x: 600 + (Math.random() - 0.5) * 400,
y: 300 + (Math.random() - 0.5) * 200
}, {
x: 1400 + (Math.random() - 0.5) * 400,
y: 600 + (Math.random() - 0.5) * 200
}, {
x: 400 + (Math.random() - 0.5) * 300,
y: 900 + (Math.random() - 0.5) * 200
}, {
x: 1600 + (Math.random() - 0.5) * 300,
y: 1200 + (Math.random() - 0.5) * 200
}, {
x: 800 + (Math.random() - 0.5) * 400,
y: 1500 + (Math.random() - 0.5) * 200
}, {
x: 1200 + (Math.random() - 0.5) * 400,
y: 1800 + (Math.random() - 0.5) * 200
}, {
x: 500 + (Math.random() - 0.5) * 300,
y: 2100 + (Math.random() - 0.5) * 200
}, {
x: 1500 + (Math.random() - 0.5) * 300,
y: 2400 + (Math.random() - 0.5) * 200
}, {
x: 1024 + (Math.random() - 0.5) * 200,
y: 2700 + Math.random() * 100
}];
// Draw path
for (var i = 0; i < gamePath.length; i++) {
var pathSegment = game.addChild(LK.getAsset('path', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}));
pathSegment.x = gamePath[i].x;
pathSegment.y = gamePath[i].y;
}
// Create packet of treats at the end
var packet = game.addChild(LK.getAsset('packetTreats', {
anchorX: 0.5,
anchorY: 0.5
}));
packet.x = gamePath[gamePath.length - 1].x;
packet.y = gamePath[gamePath.length - 1].y - 200;
// Create placement system - cats can be placed anywhere near the path
var placementSpots = []; // Keep for compatibility but will be used differently
var maxDistanceFromPath = 300; // Maximum distance cats can be placed from path
// Helper function to check if a position is valid for tower placement
function isValidPlacementPosition(x, y) {
// Check if position is within game bounds
if (x < 100 || x > 1948 || y < 100 || y > 2632) {
return false;
}
// Check if position is too close to existing towers
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 120) {
// Minimum distance between towers
return false;
}
}
return true;
}
// UI Elements
var goldText = new Text2('Gold: ' + gameGold, {
size: 60,
fill: 0xFFD700,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
goldText.anchor.set(0, 0);
goldText.x = 50;
goldText.y = 50;
LK.gui.topLeft.addChild(goldText);
var healthText = new Text2('Packet Health: ' + packetHealth, {
size: 60,
fill: 0xFF0000,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
healthText.anchor.set(0.5, 0);
healthText.x = 0;
healthText.y = 50;
LK.gui.top.addChild(healthText);
var waveText = new Text2('Wave: ' + waveNumber, {
size: 60,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
waveText.anchor.set(1, 0);
waveText.x = 0;
waveText.y = 50;
LK.gui.topRight.addChild(waveText);
// Create start button square
var startButton = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3,
alpha: 0
});
startButton.x = 0;
startButton.y = 0;
startButton.interactive = false;
LK.gui.center.addChild(startButton);
// Add tutorial images in front of start button
var tutorialCat = LK.getAsset('tiredCat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
});
tutorialCat.x = -120;
tutorialCat.y = -20;
LK.gui.center.addChild(tutorialCat);
// Add arrow image pointing from cat to mouse
var tutorialArrow = new Text2('→', {
size: 180,
fill: 0xFFFF00,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
tutorialArrow.anchor.set(0.5, 0.5);
tutorialArrow.x = 0;
tutorialArrow.y = -20;
tutorialArrow.alpha = 0;
LK.gui.center.addChild(tutorialArrow);
// Add mouse image
var tutorialMouse = LK.getAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
alpha: 0
});
tutorialMouse.x = 120;
tutorialMouse.y = -20;
LK.gui.center.addChild(tutorialMouse);
// Add wave 5 waiting state
var waitingForWave5Start = false;
// Add click handler to start button
startButton.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
// Play start sound
LK.getSound('start').play();
// Smoothly fade out start button and tutorial elements together
tween(startButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
startButton.interactive = false;
// Smoothly fade out tutorial images at the same time
tween(tutorialCat, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(tutorialArrow, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(tutorialMouse, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
} else if (waitingForWave5Start) {
// Wave 5 start button clicked
waitingForWave5Start = false;
isPaused = false;
pauseTimer = 0;
// Play start sound
LK.getSound('start').play();
// Smoothly fade out start button and tutorial elements together
tween(startButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
startButton.interactive = false;
// Smoothly fade out tutorial images at the same time
tween(tutorialCat, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(tutorialArrow, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(tutorialMouse, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
};
// Show start button after 10 seconds
LK.setTimeout(function () {
if (!gameStarted) {
tween(startButton, {
alpha: 1
}, {
duration: 500
});
// Show tutorial images
tween(tutorialCat, {
alpha: 1
}, {
duration: 500
});
tween(tutorialArrow, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
// Add pulsing effect to make arrow more visible
tween(tutorialArrow, {
alpha: 0.3
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(tutorialArrow, {
alpha: 1
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
});
tween(tutorialMouse, {
alpha: 1
}, {
duration: 500
});
startButton.interactive = true;
}
}, 10000);
// Tower selection UI
var selectedTowerType = 'normal';
// Create bottom menu background
var menuBackground = LK.getAsset('placementGrid', {
anchorX: 0.5,
anchorY: 1,
scaleX: 20,
scaleY: 2,
alpha: 0.8
});
menuBackground.x = 0;
menuBackground.y = 0;
LK.gui.bottom.addChild(menuBackground);
// Create tired cat button with asset
var tiredCatButton = LK.getAsset('tiredCat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
tiredCatButton.x = -200;
tiredCatButton.y = -80;
LK.gui.bottom.addChild(tiredCatButton);
// Create price text for tired cat
var tiredCatPrice = new Text2('30g', {
size: 40,
fill: 0xFFD700,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
tiredCatPrice.anchor.set(0.5, 0);
tiredCatPrice.x = -200;
tiredCatPrice.y = -40;
LK.gui.bottom.addChild(tiredCatPrice);
// Create normal cat button with asset
var normalCatButton = LK.getAsset('normalCat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
normalCatButton.x = 200;
normalCatButton.y = -80;
LK.gui.bottom.addChild(normalCatButton);
// Create price text for normal cat
var normalCatPrice = new Text2('150g', {
size: 40,
fill: 0xFFD700,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
normalCatPrice.anchor.set(0.5, 0);
normalCatPrice.x = 200;
normalCatPrice.y = -40;
LK.gui.bottom.addChild(normalCatPrice);
// Create wild cat button with asset
var wildCatButton = LK.getAsset('wildCat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
wildCatButton.x = 400;
wildCatButton.y = -80;
LK.gui.bottom.addChild(wildCatButton);
// Create price text for wild cat
var wildCatPrice = new Text2('350g', {
size: 40,
fill: 0xFFD700,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
wildCatPrice.anchor.set(0.5, 0);
wildCatPrice.x = 400;
wildCatPrice.y = -40;
LK.gui.bottom.addChild(wildCatPrice);
// Create tiger button with asset
var tigerButton = LK.getAsset('tiger', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
tigerButton.x = 600;
tigerButton.y = -80;
LK.gui.bottom.addChild(tigerButton);
// Create price text for tiger
var tigerPrice = new Text2('500g', {
size: 40,
fill: 0xFFD700,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
tigerPrice.anchor.set(0.5, 0);
tigerPrice.x = 600;
tigerPrice.y = -40;
LK.gui.bottom.addChild(tigerPrice);
// Create speed control buttons
var fastForwardButton = new Text2('⏩', {
size: 80,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
fastForwardButton.anchor.set(1, 0);
fastForwardButton.x = -20;
fastForwardButton.y = 120;
LK.gui.topRight.addChild(fastForwardButton);
var normalSpeedButton = new Text2('▶️', {
size: 80,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
normalSpeedButton.anchor.set(1, 0);
normalSpeedButton.x = -20;
normalSpeedButton.y = 220;
fastForwardButton.alpha = 1; // Start opaque since fast speed is not selected
normalSpeedButton.alpha = 0.5; // Start transparent since normal speed is selected
LK.gui.topRight.addChild(normalSpeedButton);
// Initialize button transparency
updateTiredCatButtonAlpha();
updateNormalCatButtonAlpha();
updateWildCatButtonAlpha();
updateTigerButtonAlpha();
// Speed control button handlers
fastForwardButton.down = function (x, y, obj) {
gameSpeedMultiplier = 2;
// Make fast button transparent and normal button opaque (clicked option is transparent)
tween(fastForwardButton, {
alpha: 0.5
}, {
duration: 200
});
tween(normalSpeedButton, {
alpha: 1
}, {
duration: 200
});
};
normalSpeedButton.down = function (x, y, obj) {
gameSpeedMultiplier = 1;
// Make normal button transparent and fast button opaque (clicked option is transparent)
tween(fastForwardButton, {
alpha: 1
}, {
duration: 200
});
tween(normalSpeedButton, {
alpha: 0.5
}, {
duration: 200
});
};
// Dragging variables
var isDragging = false;
var draggedTower = null;
var dragOffset = {
x: 0,
y: 0
};
// Sell UI variables
var sellUI = null;
var sellUITower = null;
// Tower selection for repositioning
var selectedTower = null;
function updateGoldDisplay() {
goldText.setText('Gold: ' + gameGold);
updateTiredCatButtonAlpha();
updateNormalCatButtonAlpha();
updateWildCatButtonAlpha();
updateTigerButtonAlpha();
}
function updatePacketDisplay() {
healthText.setText('Packet Health: ' + packetHealth);
}
function updateWaveDisplay() {
waveText.setText('Wave: ' + waveNumber);
}
function showSellUI(tower) {
// Remove existing sell UI
if (sellUI) {
sellUI.destroy();
sellUI = null;
}
sellUITower = tower;
sellUI = new Container();
game.addChild(sellUI);
// Position sell UI above tower
sellUI.x = tower.x;
sellUI.y = tower.y - 100;
// Create sell button
var sellButton = sellUI.attachAsset('sellButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Create sell price text
var sellPrice = tower.getSellPrice();
var sellText = new Text2('SELL\n' + sellPrice + 'g', {
size: 24,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fontWeight: 'bold'
});
sellText.anchor.set(0.5, 0.5);
sellText.x = 0;
sellText.y = 0;
sellUI.addChild(sellText);
// Sell button click handler
sellButton.down = function (x, y, obj) {
sellTower(sellUITower);
};
// Auto-hide sell UI after 3 seconds
LK.setTimeout(function () {
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
}, 3000);
}
function sellTower(tower) {
// Give back gold (70% of original cost)
var sellPrice = tower.getSellPrice();
gameGold += sellPrice;
updateGoldDisplay();
LK.getSound('mouseHit').play();
// No need to free placement spots since we're using free positioning
// Remove tower from towers array
var towerIndex = towers.indexOf(tower);
if (towerIndex > -1) {
towers.splice(towerIndex, 1);
}
// Destroy tower
tower.destroy();
// Hide sell UI
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
}
// Tired cat button drag functionality
tiredCatButton.down = function (x, y, obj) {
if (gameGold >= 30) {
// Hide sell UI when starting to drag
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
isDragging = true;
selectedTowerType = 'tired';
// Create dragged tower preview
draggedTower = new Tower('tired');
draggedTower.alpha = 0.8;
draggedTower.scaleX = 1.2;
draggedTower.scaleY = 1.2;
game.addChild(draggedTower);
// Convert button position to game coordinates
var buttonPos = game.toLocal(tiredCatButton.parent.toGlobal(tiredCatButton.position));
draggedTower.x = buttonPos.x;
draggedTower.y = buttonPos.y;
dragOffset.x = x;
dragOffset.y = y;
// Play pickup sound
LK.getSound('pickupDefender').play();
// Button feedback
tween(tiredCatButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(tiredCatButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
}
});
}
};
function updateTiredCatButtonAlpha() {
if (gameGold >= 30) {
tiredCatButton.alpha = 1;
tiredCatPrice.alpha = 1;
} else {
tiredCatButton.alpha = 0.5;
tiredCatPrice.alpha = 0.5;
}
}
// Add move handler to tired cat button for drag support
tiredCatButton.move = function (x, y, obj) {
if (isDragging && draggedTower && selectedTowerType === 'tired') {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Apply the offset from button position
var buttonPos = game.toLocal(tiredCatButton.parent.toGlobal(tiredCatButton.position));
draggedTower.x = gamePos.x + (buttonPos.x - dragOffset.x);
draggedTower.y = gamePos.y + (buttonPos.y - dragOffset.y);
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
// Tint tower based on placement validity
if (isValidPosition) {
draggedTower.tint = 0x00ff00; // Green tint for valid placement
} else {
draggedTower.tint = 0xff0000; // Red tint for invalid placement
}
}
};
// Normal cat button drag functionality
normalCatButton.down = function (x, y, obj) {
if (gameGold >= 150) {
// Hide sell UI when starting to drag
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
isDragging = true;
selectedTowerType = 'normal';
// Create dragged tower preview
draggedTower = new Tower('normal');
draggedTower.alpha = 0.8;
draggedTower.scaleX = 1.2;
draggedTower.scaleY = 1.2;
game.addChild(draggedTower);
// Convert button position to game coordinates
var buttonPos = game.toLocal(normalCatButton.parent.toGlobal(normalCatButton.position));
draggedTower.x = buttonPos.x;
draggedTower.y = buttonPos.y;
dragOffset.x = x;
dragOffset.y = y;
// Play pickup sound
LK.getSound('pickupDefender').play();
// Button feedback
tween(normalCatButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100,
onFinish: function onFinish() {
tween(normalCatButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100
});
}
});
}
};
function updateNormalCatButtonAlpha() {
if (gameGold >= 150) {
normalCatButton.alpha = 1;
normalCatPrice.alpha = 1;
} else {
normalCatButton.alpha = 0.5;
normalCatPrice.alpha = 0.5;
}
}
// Add move handler to normal cat button for drag support
normalCatButton.move = function (x, y, obj) {
if (isDragging && draggedTower && selectedTowerType === 'normal') {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Apply the offset from button position
var buttonPos = game.toLocal(normalCatButton.parent.toGlobal(normalCatButton.position));
draggedTower.x = gamePos.x + (buttonPos.x - dragOffset.x);
draggedTower.y = gamePos.y + (buttonPos.y - dragOffset.y);
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
// Tint tower based on placement validity
if (isValidPosition) {
draggedTower.tint = 0x00ff00; // Green tint for valid placement
} else {
draggedTower.tint = 0xff0000; // Red tint for invalid placement
}
}
};
// Wild cat button drag functionality
wildCatButton.down = function (x, y, obj) {
if (gameGold >= 350) {
// Hide sell UI when starting to drag
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
isDragging = true;
selectedTowerType = 'wild';
// Create dragged tower preview
draggedTower = new Tower('wild');
draggedTower.alpha = 0.8;
draggedTower.scaleX = 1.2;
draggedTower.scaleY = 1.2;
game.addChild(draggedTower);
// Convert button position to game coordinates
var buttonPos = game.toLocal(wildCatButton.parent.toGlobal(wildCatButton.position));
draggedTower.x = buttonPos.x;
draggedTower.y = buttonPos.y;
dragOffset.x = x;
dragOffset.y = y;
// Play pickup sound
LK.getSound('pickupDefender').play();
// Button feedback
tween(wildCatButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(wildCatButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100
});
}
});
}
};
function updateWildCatButtonAlpha() {
if (gameGold >= 350) {
wildCatButton.alpha = 1;
wildCatPrice.alpha = 1;
} else {
wildCatButton.alpha = 0.5;
wildCatPrice.alpha = 0.5;
}
}
// Add move handler to wild cat button for drag support
wildCatButton.move = function (x, y, obj) {
if (isDragging && draggedTower && selectedTowerType === 'wild') {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Apply the offset from button position
var buttonPos = game.toLocal(wildCatButton.parent.toGlobal(wildCatButton.position));
draggedTower.x = gamePos.x + (buttonPos.x - dragOffset.x);
draggedTower.y = gamePos.y + (buttonPos.y - dragOffset.y);
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
// Tint tower based on placement validity
if (isValidPosition) {
draggedTower.tint = 0x00ff00; // Green tint for valid placement
} else {
draggedTower.tint = 0xff0000; // Red tint for invalid placement
}
}
};
// Tiger button drag functionality
tigerButton.down = function (x, y, obj) {
if (gameGold >= 500) {
// Hide sell UI when starting to drag
if (sellUI) {
sellUI.destroy();
sellUI = null;
sellUITower = null;
}
isDragging = true;
selectedTowerType = 'tiger';
// Create dragged tower preview
draggedTower = new Tower('tiger');
draggedTower.alpha = 0.8;
draggedTower.scaleX = 1.2;
draggedTower.scaleY = 1.2;
game.addChild(draggedTower);
// Convert button position to game coordinates
var buttonPos = game.toLocal(tigerButton.parent.toGlobal(tigerButton.position));
draggedTower.x = buttonPos.x;
draggedTower.y = buttonPos.y;
dragOffset.x = x;
dragOffset.y = y;
// Play pickup sound
LK.getSound('pickupDefender').play();
// Button feedback
tween(tigerButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
tween(tigerButton, {
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 100
});
}
});
}
};
function updateTigerButtonAlpha() {
if (gameGold >= 500) {
tigerButton.alpha = 1;
tigerPrice.alpha = 1;
} else {
tigerButton.alpha = 0.5;
tigerPrice.alpha = 0.5;
}
}
// Add move handler to tiger button for drag support
tigerButton.move = function (x, y, obj) {
if (isDragging && draggedTower && selectedTowerType === 'tiger') {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Apply the offset from button position
var buttonPos = game.toLocal(tigerButton.parent.toGlobal(tigerButton.position));
draggedTower.x = gamePos.x + (buttonPos.x - dragOffset.x);
draggedTower.y = gamePos.y + (buttonPos.y - dragOffset.y);
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
// Tint tower based on placement validity
if (isValidPosition) {
draggedTower.tint = 0x00ff00; // Green tint for valid placement
} else {
draggedTower.tint = 0xff0000; // Red tint for invalid placement
}
}
};
// Add up handlers to all tower buttons
tiredCatButton.up = function (x, y, obj) {
if (isDragging && draggedTower) {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Check if current position is valid for placement using dragged tower's position
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
var towerCost = draggedTower.cost;
if (isValidPosition && gameGold >= towerCost) {
// Place tower at dragged position (tower already positioned correctly)
gameGold -= towerCost;
updateGoldDisplay();
towers.push(draggedTower);
draggedTower.alpha = 1;
draggedTower.tint = 0xffffff; // Reset tint
LK.getSound('placeDefender').play();
} else {
// Remove dragged tower if placement failed
draggedTower.destroy();
}
// Reset dragging state
isDragging = false;
draggedTower = null;
}
};
normalCatButton.up = function (x, y, obj) {
if (isDragging && draggedTower) {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Check if current position is valid for placement using dragged tower's position
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
var towerCost = draggedTower.cost;
if (isValidPosition && gameGold >= towerCost) {
// Place tower at dragged position (tower already positioned correctly)
gameGold -= towerCost;
updateGoldDisplay();
towers.push(draggedTower);
draggedTower.alpha = 1;
draggedTower.tint = 0xffffff; // Reset tint
LK.getSound('placeDefender').play();
} else {
// Remove dragged tower if placement failed
draggedTower.destroy();
}
// Reset dragging state
isDragging = false;
draggedTower = null;
}
};
wildCatButton.up = function (x, y, obj) {
if (isDragging && draggedTower) {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Check if current position is valid for placement using dragged tower's position
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
var towerCost = draggedTower.cost;
if (isValidPosition && gameGold >= towerCost) {
// Place tower at dragged position (tower already positioned correctly)
gameGold -= towerCost;
updateGoldDisplay();
towers.push(draggedTower);
draggedTower.alpha = 1;
draggedTower.tint = 0xffffff; // Reset tint
LK.getSound('placeDefender').play();
} else {
// Remove dragged tower if placement failed
draggedTower.destroy();
}
// Reset dragging state
isDragging = false;
draggedTower = null;
}
};
tigerButton.up = function (x, y, obj) {
if (isDragging && draggedTower) {
var gamePos = obj.parent ? game.toLocal(obj.parent.toGlobal({
x: x,
y: y
})) : {
x: x,
y: y
};
// Check if current position is valid for placement using dragged tower's position
var isValidPosition = isValidPlacementPosition(draggedTower.x, draggedTower.y);
var towerCost = draggedTower.cost;
if (isValidPosition && gameGold >= towerCost) {
// Place tower at dragged position (tower already positioned correctly)
gameGold -= towerCost;
updateGoldDisplay();
towers.push(draggedTower);
draggedTower.alpha = 1;
draggedTower.tint = 0xffffff; // Reset tint
LK.getSound('placeDefender').play();
} else {
// Remove dragged tower if placement failed
draggedTower.destroy();
}
// Reset dragging state
isDragging = false;
draggedTower = null;
}
};
// Game move handler for dragging
game.move = function (x, y, obj) {
if (isDragging && draggedTower) {
draggedTower.x = x;
draggedTower.y = y;
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(x, y);
// Tint tower based on placement validity
if (isValidPosition) {
draggedTower.tint = 0x00ff00; // Green tint for valid placement
} else if (selectedTower === draggedTower) {
draggedTower.tint = 0x00ffff; // Keep cyan tint for selected tower being repositioned
} else {
draggedTower.tint = 0xff0000; // Red tint for invalid placement
}
}
};
// Game up handler for tower placement
game.up = function (x, y, obj) {
if (isDragging && draggedTower) {
// Check if current position is valid for placement
var isValidPosition = isValidPlacementPosition(x, y);
// Check if this is a repositioning of an existing tower
var isRepositioning = selectedTower === draggedTower;
var towerCost = isRepositioning ? 0 : draggedTower.cost;
if (isValidPosition && gameGold >= towerCost) {
// Place or reposition tower at current position
if (!isRepositioning) {
gameGold -= towerCost;
updateGoldDisplay();
towers.push(draggedTower);
}
// Keep tower at current dragged position
draggedTower.alpha = 1;
draggedTower.tint = 0xffffff; // Reset tint
if (!isRepositioning) {
LK.getSound('placeDefender').play();
}
} else if (isRepositioning) {
// If repositioning failed, keep tower at its current position but remove selection
draggedTower.tint = 0xffffff;
} else {
// Remove dragged tower if placement failed
draggedTower.destroy();
}
// Reset dragging and selection state
isDragging = false;
draggedTower = null;
if (selectedTower) {
selectedTower = null;
}
}
};
// Start background music
LK.playMusic('bgMusic');
game.update = function () {
// Don't spawn mice until game starts (start button clicked)
if (!gameStarted) {
return; // Don't spawn mice until game starts
}
// Handle pause after wave 4 (changed from wave 3) or waiting for wave 5 start
if (isPaused || waitingForWave5Start) {
if (isPaused) {
pauseTimer += gameSpeedMultiplier;
if (pauseTimer >= 600) {
// 10 seconds at 60fps
isPaused = false;
// Remove pause text
if (pauseText) {
pauseText.destroy();
pauseText = null;
}
// Show start button with normal cat, arrow, rat after wave 4
if (waveNumber === 5) {
// Wave number increments before pause check
// Set waiting state for wave 5
waitingForWave5Start = true;
// Show start button
startButton.alpha = 1;
startButton.interactive = true;
// Change tutorial images for wave 4 completion
tutorialCat.destroy();
tutorialCat = LK.getAsset('normalCat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
alpha: 1
});
tutorialCat.x = -120;
tutorialCat.y = -20;
LK.gui.center.addChild(tutorialCat);
tutorialArrow.alpha = 1;
// Change mouse to rat
tutorialMouse.destroy();
tutorialMouse = LK.getAsset('rat', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 1
});
tutorialMouse.x = 120;
tutorialMouse.y = -20;
LK.gui.center.addChild(tutorialMouse);
}
}
}
return; // Don't spawn enemies during pause or while waiting for wave 5 start
}
// Spawn mice with much more random timing variation
spawnTimer += gameSpeedMultiplier;
var randomSpawnDelay = Math.random() * 60 + Math.random() * 30; // Much more random delay
if (spawnTimer >= spawnRate + randomSpawnDelay && miceSpawned < maxMicePerWave) {
var mouse = new Mouse();
// Much more random spawn positions with larger variation
mouse.x = gamePath[0].x + (Math.random() - 0.5) * 600 + Math.random() * 200;
mouse.y = gamePath[0].y + (Math.random() - 0.5) * 400 + Math.random() * 150;
// More random health variation (±40%)
var baseHealth = 180 + waveNumber * 50;
mouse.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.8;
mouse.maxHealth = mouse.health;
// Much more random speed variation (±50%)
mouse.speed = mouse.speed * (0.5 + Math.random() * 1.0);
mouse.updateHealthBar();
mice.push(mouse);
game.addChild(mouse);
miceSpawned++;
spawnTimer = Math.random() * 20; // Random reset for more chaos
}
// Spawn rats (only after wave 5) with random variations
if (waveNumber >= 5) {
ratSpawnTimer += gameSpeedMultiplier;
var randomRatDelay = Math.random() * 40;
if (ratSpawnTimer >= ratSpawnRate + randomRatDelay && ratsSpawned < maxRatsPerWave) {
var rat = new Rat();
rat.x = gamePath[0].x + (Math.random() - 0.5) * 500;
rat.y = gamePath[0].y + (Math.random() - 0.5) * 250;
// Random health variation (±25%)
var baseHealth = 500 + waveNumber * 120;
rat.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.5;
rat.maxHealth = rat.health;
// Random speed variation (±40%)
rat.speed = rat.speed * (0.6 + Math.random() * 0.8);
rat.updateHealthBar();
rats.push(rat);
game.addChild(rat);
ratsSpawned++;
ratSpawnTimer = 0;
}
}
// Spawn hares (only after wave 10) with random variations
if (waveNumber >= 10) {
hareSpawnTimer += gameSpeedMultiplier;
var randomHareDelay = Math.random() * 50;
if (hareSpawnTimer >= hareSpawnRate + randomHareDelay && haresSpawned < maxHaresPerWave) {
var hare = new Hare();
hare.x = gamePath[0].x + (Math.random() - 0.5) * 600;
hare.y = gamePath[0].y + (Math.random() - 0.5) * 300;
// Random health variation (±30%)
var baseHealth = 700 + waveNumber * 150;
hare.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.6;
hare.maxHealth = hare.health;
// Random speed variation (±35%)
hare.speed = hare.speed * (0.65 + Math.random() * 0.7);
hare.updateHealthBar();
hares.push(hare);
game.addChild(hare);
haresSpawned++;
hareSpawnTimer = 0;
}
}
// Spawn birds (only after wave 15) with random variations
if (waveNumber >= 15) {
birdSpawnTimer += gameSpeedMultiplier;
var randomBirdDelay = Math.random() * 35;
if (birdSpawnTimer >= birdSpawnRate + randomBirdDelay && birdsSpawned < maxBirdsPerWave) {
var bird = new Bird();
bird.x = gamePath[0].x + (Math.random() - 0.5) * 450;
bird.y = gamePath[0].y + (Math.random() - 0.5) * 200;
// Random health variation (±25%)
var baseHealth = 400 + waveNumber * 100;
bird.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.5;
bird.maxHealth = bird.health;
// Random speed variation (±30%)
bird.speed = bird.speed * (0.7 + Math.random() * 0.6);
bird.updateHealthBar();
birds.push(bird);
game.addChild(bird);
birdsSpawned++;
birdSpawnTimer = 0;
}
}
// Spawn dogs (only after wave 20) with random variations
if (waveNumber >= 20) {
dogSpawnTimer += gameSpeedMultiplier;
var randomDogDelay = Math.random() * 60;
if (dogSpawnTimer >= dogSpawnRate + randomDogDelay && dogsSpawned < maxDogsPerWave) {
var dog = new Dog();
dog.x = gamePath[0].x + (Math.random() - 0.5) * 400;
dog.y = gamePath[0].y + (Math.random() - 0.5) * 200;
// Random health variation (±35%)
var baseHealth = 800 + waveNumber * 200;
dog.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.7;
dog.maxHealth = dog.health;
// Random speed variation (±25%)
dog.speed = dog.speed * (0.75 + Math.random() * 0.5);
dog.updateHealthBar();
dogs.push(dog);
game.addChild(dog);
dogsSpawned++;
dogSpawnTimer = 0;
}
}
// Check if wave is complete
if (miceSpawned >= maxMicePerWave && ratsSpawned >= maxRatsPerWave && haresSpawned >= maxHaresPerWave && birdsSpawned >= maxBirdsPerWave && dogsSpawned >= maxDogsPerWave && mice.length === 0 && rats.length === 0 && hares.length === 0 && birds.length === 0 && dogs.length === 0) {
// Check if wave 4, 14, or 19 just completed
if (waveNumber === 4 || waveNumber === 14 || waveNumber === 19) {
isPaused = true;
pauseTimer = 0;
}
waveNumber++;
miceSpawned = 0;
ratsSpawned = 0;
haresSpawned = 0;
birdsSpawned = 0;
dogsSpawned = 0;
// Random variation in mice count per wave (±30%)
var baseMiceIncrease = waveNumber <= 3 ? 2 : 1;
maxMicePerWave += Math.floor(baseMiceIncrease * (0.7 + Math.random() * 0.6));
// Start spawning rats after wave 5 with random counts
if (waveNumber >= 5) {
var baseRats = Math.max(1, waveNumber - 4);
maxRatsPerWave = Math.floor(baseRats * (0.8 + Math.random() * 0.4));
}
// Start spawning birds after wave 15 with random counts
if (waveNumber >= 15) {
var baseBirds = Math.max(1, waveNumber - 14);
maxBirdsPerWave = Math.floor(baseBirds * (0.7 + Math.random() * 0.6));
}
// Start spawning hares after wave 10 with random counts
if (waveNumber >= 10) {
var baseHares = Math.max(1, waveNumber - 9);
maxHaresPerWave = Math.floor(baseHares * (0.8 + Math.random() * 0.4));
}
// Start spawning dogs after wave 20 with random counts
if (waveNumber >= 20) {
var baseDogs = Math.max(1, waveNumber - 19);
maxDogsPerWave = Math.floor(baseDogs * (0.6 + Math.random() * 0.8));
}
// Random spawn rate variations
var baseSpawnDecrease = waveNumber <= 3 ? 8 : 12;
spawnRate = Math.max(40, spawnRate - Math.floor(baseSpawnDecrease * (0.8 + Math.random() * 0.4)));
ratSpawnRate = Math.max(90, ratSpawnRate - Math.floor(15 * (0.7 + Math.random() * 0.6)));
hareSpawnRate = Math.max(100, hareSpawnRate - Math.floor(10 * (0.8 + Math.random() * 0.4)));
birdSpawnRate = Math.max(70, birdSpawnRate - Math.floor(10 * (0.9 + Math.random() * 0.2)));
dogSpawnRate = Math.max(120, dogSpawnRate - Math.floor(10 * (0.7 + Math.random() * 0.6)));
updateWaveDisplay();
}
// Update all game objects
for (var i = mice.length - 1; i >= 0; i--) {
if (mice[i].parent) {
mice[i].update();
}
}
for (var i = rats.length - 1; i >= 0; i--) {
if (rats[i].parent) {
rats[i].update();
}
}
for (var i = hares.length - 1; i >= 0; i--) {
if (hares[i].parent) {
hares[i].update();
}
}
for (var i = birds.length - 1; i >= 0; i--) {
if (birds[i].parent) {
birds[i].update();
}
}
for (var i = dogs.length - 1; i >= 0; i--) {
if (dogs[i].parent) {
dogs[i].update();
}
}
for (var i = towers.length - 1; i >= 0; i--) {
if (towers[i].parent) {
towers[i].update();
// Check if tower is touching menu area (bottom 200px of screen)
var isTouchingMenu = towers[i].y > 2532; // Menu area starts around y=2532
if (isTouchingMenu && !isDragging) {
// Check if tower is very close to the path (excluding treatpacket position)
var minDistanceFromPath = Infinity;
for (var p = 0; p < gamePath.length - 1; p++) {
var dx = gamePath[p].x - towers[i].x;
var dy = gamePath[p].y - towers[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < minDistanceFromPath) {
minDistanceFromPath = distance;
}
}
// If not very close to path (more than 120px away), turn red
if (minDistanceFromPath > 120) {
towers[i].tint = 0xff0000; // Red tint
} else {
towers[i].tint = 0xffffff; // Reset to normal
}
} else if (!isDragging && towers[i] !== selectedTower) {
// Reset tint if not touching menu and not being dragged/selected
towers[i].tint = 0xffffff;
}
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -42,39 +42,37 @@
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
- // Initialize swoop variables if not set
- if (self.swoopPhase === undefined) self.swoopPhase = Math.random() * Math.PI * 2;
- if (self.swoopSpeed === undefined) self.swoopSpeed = 0.06 + Math.random() * 0.03;
- // Move in swooping flight pattern towards packet
- var dx = packet.x - self.x;
- var dy = packet.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // Create swooping flight pattern unique to birds
- var swoopX = Math.sin(LK.ticks * self.swoopSpeed + self.swoopPhase) * 50;
- var swoopY = Math.cos(LK.ticks * 0.04) * 30;
- if (distance < 50) {
- // Bird reached the packet - damage it
- packetHealth -= Math.floor(packetHealth * 0.08);
- updatePacketDisplay();
- LK.getSound('enemySteal').play();
- if (packetHealth <= 0) {
- LK.showGameOver();
+ if (self.pathIndex < gamePath.length) {
+ var target = gamePath[self.pathIndex];
+ var dx = target.x - self.x;
+ var dy = target.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 10) {
+ self.pathIndex++;
+ if (self.pathIndex >= gamePath.length) {
+ // Bird reached the end - damage packet (8% of current health)
+ packetHealth -= Math.floor(packetHealth * 0.08);
+ updatePacketDisplay();
+ LK.getSound('enemySteal').play();
+ if (packetHealth <= 0) {
+ LK.showGameOver();
+ }
+ self.destroy();
+ birds.splice(birds.indexOf(self), 1);
+ return;
+ }
+ } else {
+ // Flip scaleX based on movement direction
+ if (dx > 0) {
+ birdGraphics.scaleX = 1; // Face right
+ } else if (dx < 0) {
+ birdGraphics.scaleX = -1; // Face left
+ }
+ self.x += dx / distance * self.speed * gameSpeedMultiplier;
+ self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
- self.destroy();
- birds.splice(birds.indexOf(self), 1);
- return;
- } else {
- // Flip scaleX based on movement direction
- if (dx > 0) {
- birdGraphics.scaleX = 1; // Face right
- } else if (dx < 0) {
- birdGraphics.scaleX = -1; // Face left
- }
- // Move with swooping pattern
- self.x += (dx / distance * self.speed + swoopX * 0.02) * gameSpeedMultiplier;
- self.y += (dy / distance * self.speed + swoopY * 0.02) * gameSpeedMultiplier;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
@@ -126,34 +124,37 @@
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
- // Move in straight charging line towards packet
- var dx = packet.x - self.x;
- var dy = packet.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < 50) {
- // Dog reached the packet - damage it heavily
- packetHealth -= Math.floor(packetHealth * 0.20);
- updatePacketDisplay();
- LK.getSound('enemySteal').play();
- if (packetHealth <= 0) {
- LK.showGameOver();
+ if (self.pathIndex < gamePath.length) {
+ var target = gamePath[self.pathIndex];
+ var dx = target.x - self.x;
+ var dy = target.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 10) {
+ self.pathIndex++;
+ if (self.pathIndex >= gamePath.length) {
+ // Dog reached the end - damage packet (20% of current health)
+ packetHealth -= Math.floor(packetHealth * 0.20);
+ updatePacketDisplay();
+ LK.getSound('enemySteal').play();
+ if (packetHealth <= 0) {
+ LK.showGameOver();
+ }
+ self.destroy();
+ dogs.splice(dogs.indexOf(self), 1);
+ return;
+ }
+ } else {
+ // Flip scaleX based on movement direction
+ if (dx > 0) {
+ dogGraphics.scaleX = 1; // Face right
+ } else if (dx < 0) {
+ dogGraphics.scaleX = -1; // Face left
+ }
+ self.x += dx / distance * self.speed * gameSpeedMultiplier;
+ self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
- self.destroy();
- dogs.splice(dogs.indexOf(self), 1);
- return;
- } else {
- // Flip scaleX based on movement direction
- if (dx > 0) {
- dogGraphics.scaleX = 1; // Face right
- } else if (dx < 0) {
- dogGraphics.scaleX = -1; // Face left
- }
- // Charge straight at packet with slight random deviation
- var deviation = (Math.random() - 0.5) * 2;
- self.x += (dx / distance * self.speed + deviation) * gameSpeedMultiplier;
- self.y += (dy / distance * self.speed + deviation) * gameSpeedMultiplier;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
@@ -205,39 +206,37 @@
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
- // Initialize bounce variables if not set
- if (self.bouncePhase === undefined) self.bouncePhase = Math.random() * Math.PI * 2;
- if (self.bounceSpeed === undefined) self.bounceSpeed = 0.08 + Math.random() * 0.04;
- // Move in bouncing pattern towards packet
- var dx = packet.x - self.x;
- var dy = packet.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // Create bouncing movement unique to hares
- var bounceHeight = 40 + Math.sin(LK.ticks * self.bounceSpeed + self.bouncePhase) * 25;
- var bounceY = Math.sin(LK.ticks * 0.12) * bounceHeight;
- if (distance < 50) {
- // Hare reached the packet - damage it
- packetHealth -= Math.floor(packetHealth * 0.15); // 15% of current packet health
- updatePacketDisplay();
- LK.getSound('enemySteal').play();
- if (packetHealth <= 0) {
- LK.showGameOver();
+ if (self.pathIndex < gamePath.length) {
+ var target = gamePath[self.pathIndex];
+ var dx = target.x - self.x;
+ var dy = target.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 10) {
+ self.pathIndex++;
+ if (self.pathIndex >= gamePath.length) {
+ // Hare reached the end - damage packet (15% of original damage)
+ packetHealth -= Math.floor(packetHealth * 0.15); // 15% of current packet health
+ updatePacketDisplay();
+ LK.getSound('enemySteal').play();
+ if (packetHealth <= 0) {
+ LK.showGameOver();
+ }
+ self.destroy();
+ hares.splice(hares.indexOf(self), 1);
+ return;
+ }
+ } else {
+ // Flip scaleX based on movement direction like cats
+ if (dx > 0) {
+ hareGraphics.scaleX = 1; // Face right
+ } else if (dx < 0) {
+ hareGraphics.scaleX = -1; // Face left
+ }
+ self.x += dx / distance * self.speed * gameSpeedMultiplier;
+ self.y += dy / distance * self.speed * gameSpeedMultiplier;
}
- self.destroy();
- hares.splice(hares.indexOf(self), 1);
- return;
- } else {
- // Flip scaleX based on movement direction
- if (dx > 0) {
- hareGraphics.scaleX = 1; // Face right
- } else if (dx < 0) {
- hareGraphics.scaleX = -1; // Face left
- }
- // Move with bouncing pattern
- self.x += dx / distance * self.speed * gameSpeedMultiplier;
- self.y += (dy / distance * self.speed + bounceY * 0.1) * gameSpeedMultiplier;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
@@ -289,38 +288,43 @@
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
- // Move directly towards packet with random zigzag pattern
- var dx = packet.x - self.x;
- var dy = packet.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // Add random zigzag movement unique to mice
- var zigzagX = Math.sin(LK.ticks * 0.1 + self.x * 0.01) * 30;
- var zigzagY = Math.cos(LK.ticks * 0.08 + self.y * 0.01) * 20;
- if (distance < 50) {
- // Mouse reached the packet - damage it
- packetHealth -= 5; // 5% damage
- updatePacketDisplay();
- LK.getSound('enemySteal').play();
- if (packetHealth <= 0) {
- LK.showGameOver();
+ if (self.pathIndex < gamePath.length) {
+ var target = gamePath[self.pathIndex];
+ // Add random wandering to target position for more chaotic movement
+ var randomOffsetX = (Math.random() - 0.5) * 80;
+ var randomOffsetY = (Math.random() - 0.5) * 80;
+ var dx = target.x + randomOffsetX - self.x;
+ var dy = target.y + randomOffsetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 15 + Math.random() * 10) {
+ self.pathIndex++;
+ if (self.pathIndex >= gamePath.length) {
+ // Mouse reached the end - damage packet (5% of original damage)
+ packetHealth -= 5; // Changed to 5 damage (5% of original 100)
+ updatePacketDisplay();
+ LK.getSound('enemySteal').play();
+ if (packetHealth <= 0) {
+ LK.showGameOver();
+ }
+ self.destroy();
+ mice.splice(mice.indexOf(self), 1);
+ return;
+ }
+ } else {
+ // Flip scaleX based on movement direction like cats
+ if (dx > 0) {
+ mouseGraphics.scaleX = 1; // Face right
+ } else if (dx < 0) {
+ mouseGraphics.scaleX = -1; // Face left
+ }
+ // Add slight random jitter to movement for more chaotic behavior
+ var jitterX = (Math.random() - 0.5) * 2;
+ var jitterY = (Math.random() - 0.5) * 2;
+ self.x += dx / distance * self.speed * gameSpeedMultiplier + jitterX;
+ self.y += dy / distance * self.speed * gameSpeedMultiplier + jitterY;
}
- self.destroy();
- mice.splice(mice.indexOf(self), 1);
- return;
- } else {
- // Flip scaleX based on movement direction
- if (dx > 0) {
- mouseGraphics.scaleX = 1; // Face right
- } else if (dx < 0) {
- mouseGraphics.scaleX = -1; // Face left
- }
- // Move with zigzag pattern and random jitter
- var jitterX = (Math.random() - 0.5) * 3;
- var jitterY = (Math.random() - 0.5) * 3;
- self.x += (dx / distance * self.speed + zigzagX * 0.1) * gameSpeedMultiplier + jitterX;
- self.y += (dy / distance * self.speed + zigzagY * 0.1) * gameSpeedMultiplier + jitterY;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
@@ -372,40 +376,43 @@
healthBarFill.tint = 0xff0000; // Red
}
};
self.update = function () {
- // Move in spiral pattern towards packet
- var dx = packet.x - self.x;
- var dy = packet.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // Create spiral movement unique to rats
- var spiralRadius = Math.min(distance * 0.3, 80);
- var spiralAngle = LK.ticks * 0.05 + self.x * 0.005;
- var spiralX = Math.cos(spiralAngle) * spiralRadius;
- var spiralY = Math.sin(spiralAngle) * spiralRadius;
- if (distance < 50) {
- // Rat reached the packet - damage it
- packetHealth -= 10; // 10% damage
- updatePacketDisplay();
- LK.getSound('enemySteal').play();
- if (packetHealth <= 0) {
- LK.showGameOver();
+ if (self.pathIndex < gamePath.length) {
+ var target = gamePath[self.pathIndex];
+ // Add random wandering behavior for more unpredictable movement
+ var randomOffsetX = (Math.random() - 0.5) * 100;
+ var randomOffsetY = (Math.random() - 0.5) * 100;
+ var dx = target.x + randomOffsetX - self.x;
+ var dy = target.y + randomOffsetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 20 + Math.random() * 15) {
+ self.pathIndex++;
+ if (self.pathIndex >= gamePath.length) {
+ // Rat reached the end - damage packet (10% of original damage)
+ packetHealth -= 10; // Changed to 10 damage (10% of original 100)
+ updatePacketDisplay();
+ LK.getSound('enemySteal').play();
+ if (packetHealth <= 0) {
+ LK.showGameOver();
+ }
+ self.destroy();
+ rats.splice(rats.indexOf(self), 1);
+ return;
+ }
+ } else {
+ // Flip scaleX based on movement direction like cats
+ if (dx > 0) {
+ ratGraphics.scaleX = 1; // Face right
+ } else if (dx < 0) {
+ ratGraphics.scaleX = -1; // Face left
+ }
+ // Add random movement variation for more chaotic behavior
+ var jitterX = (Math.random() - 0.5) * 3;
+ var jitterY = (Math.random() - 0.5) * 3;
+ self.x += dx / distance * self.speed * gameSpeedMultiplier + jitterX;
+ self.y += dy / distance * self.speed * gameSpeedMultiplier + jitterY;
}
- self.destroy();
- rats.splice(rats.indexOf(self), 1);
- return;
- } else {
- // Flip scaleX based on movement direction
- if (dx > 0) {
- ratGraphics.scaleX = 1; // Face right
- } else if (dx < 0) {
- ratGraphics.scaleX = -1; // Face left
- }
- // Move with spiral pattern and random variation
- var jitterX = (Math.random() - 0.5) * 4;
- var jitterY = (Math.random() - 0.5) * 4;
- self.x += (dx / distance * self.speed + spiralX * 0.02) * gameSpeedMultiplier + jitterX;
- self.y += (dy / distance * self.speed + spiralY * 0.02) * gameSpeedMultiplier + jitterY;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
@@ -745,15 +752,57 @@
var isPaused = false;
var pauseTimer = 0;
var pauseText = null;
var gameSpeedMultiplier = 1; // Normal speed = 1, Fast speed = 2
-// Create packet of treats at the bottom center
+// Create path for mice - random zigzag movement with more randomization
+var gamePath = [{
+ x: 1024 + (Math.random() - 0.5) * 200,
+ y: 50 + Math.random() * 100
+}, {
+ x: 600 + (Math.random() - 0.5) * 400,
+ y: 300 + (Math.random() - 0.5) * 200
+}, {
+ x: 1400 + (Math.random() - 0.5) * 400,
+ y: 600 + (Math.random() - 0.5) * 200
+}, {
+ x: 400 + (Math.random() - 0.5) * 300,
+ y: 900 + (Math.random() - 0.5) * 200
+}, {
+ x: 1600 + (Math.random() - 0.5) * 300,
+ y: 1200 + (Math.random() - 0.5) * 200
+}, {
+ x: 800 + (Math.random() - 0.5) * 400,
+ y: 1500 + (Math.random() - 0.5) * 200
+}, {
+ x: 1200 + (Math.random() - 0.5) * 400,
+ y: 1800 + (Math.random() - 0.5) * 200
+}, {
+ x: 500 + (Math.random() - 0.5) * 300,
+ y: 2100 + (Math.random() - 0.5) * 200
+}, {
+ x: 1500 + (Math.random() - 0.5) * 300,
+ y: 2400 + (Math.random() - 0.5) * 200
+}, {
+ x: 1024 + (Math.random() - 0.5) * 200,
+ y: 2700 + Math.random() * 100
+}];
+// Draw path
+for (var i = 0; i < gamePath.length; i++) {
+ var pathSegment = game.addChild(LK.getAsset('path', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0
+ }));
+ pathSegment.x = gamePath[i].x;
+ pathSegment.y = gamePath[i].y;
+}
+// Create packet of treats at the end
var packet = game.addChild(LK.getAsset('packetTreats', {
anchorX: 0.5,
anchorY: 0.5
}));
-packet.x = 1024;
-packet.y = 2500;
+packet.x = gamePath[gamePath.length - 1].x;
+packet.y = gamePath[gamePath.length - 1].y - 200;
// Create placement system - cats can be placed anywhere near the path
var placementSpots = []; // Keep for compatibility but will be used differently
var maxDistanceFromPath = 300; // Maximum distance cats can be placed from path
// Helper function to check if a position is valid for tower placement
@@ -1740,11 +1789,11 @@
spawnTimer += gameSpeedMultiplier;
var randomSpawnDelay = Math.random() * 60 + Math.random() * 30; // Much more random delay
if (spawnTimer >= spawnRate + randomSpawnDelay && miceSpawned < maxMicePerWave) {
var mouse = new Mouse();
- // Spawn from top of screen at random X position
- mouse.x = Math.random() * 2048;
- mouse.y = -50;
+ // Much more random spawn positions with larger variation
+ mouse.x = gamePath[0].x + (Math.random() - 0.5) * 600 + Math.random() * 200;
+ mouse.y = gamePath[0].y + (Math.random() - 0.5) * 400 + Math.random() * 150;
// More random health variation (±40%)
var baseHealth = 180 + waveNumber * 50;
mouse.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.8;
mouse.maxHealth = mouse.health;
@@ -1761,11 +1810,10 @@
ratSpawnTimer += gameSpeedMultiplier;
var randomRatDelay = Math.random() * 40;
if (ratSpawnTimer >= ratSpawnRate + randomRatDelay && ratsSpawned < maxRatsPerWave) {
var rat = new Rat();
- // Spawn from top of screen at random X position
- rat.x = Math.random() * 2048;
- rat.y = -50;
+ rat.x = gamePath[0].x + (Math.random() - 0.5) * 500;
+ rat.y = gamePath[0].y + (Math.random() - 0.5) * 250;
// Random health variation (±25%)
var baseHealth = 500 + waveNumber * 120;
rat.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.5;
rat.maxHealth = rat.health;
@@ -1783,11 +1831,10 @@
hareSpawnTimer += gameSpeedMultiplier;
var randomHareDelay = Math.random() * 50;
if (hareSpawnTimer >= hareSpawnRate + randomHareDelay && haresSpawned < maxHaresPerWave) {
var hare = new Hare();
- // Spawn from top of screen at random X position
- hare.x = Math.random() * 2048;
- hare.y = -50;
+ hare.x = gamePath[0].x + (Math.random() - 0.5) * 600;
+ hare.y = gamePath[0].y + (Math.random() - 0.5) * 300;
// Random health variation (±30%)
var baseHealth = 700 + waveNumber * 150;
hare.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.6;
hare.maxHealth = hare.health;
@@ -1805,11 +1852,10 @@
birdSpawnTimer += gameSpeedMultiplier;
var randomBirdDelay = Math.random() * 35;
if (birdSpawnTimer >= birdSpawnRate + randomBirdDelay && birdsSpawned < maxBirdsPerWave) {
var bird = new Bird();
- // Spawn from top of screen at random X position
- bird.x = Math.random() * 2048;
- bird.y = -50;
+ bird.x = gamePath[0].x + (Math.random() - 0.5) * 450;
+ bird.y = gamePath[0].y + (Math.random() - 0.5) * 200;
// Random health variation (±25%)
var baseHealth = 400 + waveNumber * 100;
bird.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.5;
bird.maxHealth = bird.health;
@@ -1827,11 +1873,10 @@
dogSpawnTimer += gameSpeedMultiplier;
var randomDogDelay = Math.random() * 60;
if (dogSpawnTimer >= dogSpawnRate + randomDogDelay && dogsSpawned < maxDogsPerWave) {
var dog = new Dog();
- // Spawn from top of screen at random X position
- dog.x = Math.random() * 2048;
- dog.y = -50;
+ dog.x = gamePath[0].x + (Math.random() - 0.5) * 400;
+ dog.y = gamePath[0].y + (Math.random() - 0.5) * 200;
// Random health variation (±35%)
var baseHealth = 800 + waveNumber * 200;
dog.health = baseHealth + (Math.random() - 0.5) * baseHealth * 0.7;
dog.maxHealth = dog.health;
@@ -1920,9 +1965,24 @@
towers[i].update();
// Check if tower is touching menu area (bottom 200px of screen)
var isTouchingMenu = towers[i].y > 2532; // Menu area starts around y=2532
if (isTouchingMenu && !isDragging) {
- towers[i].tint = 0xff0000; // Red tint for towers in menu area
+ // Check if tower is very close to the path (excluding treatpacket position)
+ var minDistanceFromPath = Infinity;
+ for (var p = 0; p < gamePath.length - 1; p++) {
+ var dx = gamePath[p].x - towers[i].x;
+ var dy = gamePath[p].y - towers[i].y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < minDistanceFromPath) {
+ minDistanceFromPath = distance;
+ }
+ }
+ // If not very close to path (more than 120px away), turn red
+ if (minDistanceFromPath > 120) {
+ towers[i].tint = 0xff0000; // Red tint
+ } else {
+ towers[i].tint = 0xffffff; // Reset to normal
+ }
} else if (!isDragging && towers[i] !== selectedTower) {
// Reset tint if not touching menu and not being dragged/selected
towers[i].tint = 0xffffff;
}
Un emignone souris cartoon style sur ses quatres pattes. In-Game asset. 2d. High contrast. No shadows
Cute tired cat manga cartoon style. In-Game asset. 2d. High contrast. No shadows
A cute manga style cat. In-Game asset. 2d. High contrast. No shadows
An angry but cute wild cat manga cartoon style. In-Game asset. 2d. High contrast. No shadows
A big angry cute tiger. In-Game asset. 2d. High contrast. No shadows
A pretty air view grass plain. In-Game asset. 2d. High contrast. No shadows
A red rectangular button. In-Game asset. 2d. High contrast. No shadows
A cute hare running on 4 paws. In-Game asset. 2d. High contrast. No shadows
cute lil bird flying cartoon style
Make more manga style and cutter with cut colors
a cute angry dog manga style. In-Game asset. 2d. High contrast. No shadows