User prompt
Ok make it 30% after 25 wave
User prompt
Ok then: After the extra special weathers activate every wave ther change will increase by %5 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Do the same weather text thing for extra special weathers but extra special weathers will be golden and text like: Extra Bloody Rain ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When the special weather change become %100. Add Extra special weather. Every weather has %30 change to be a extra special weather. Extra special weathers are same as special weathers but double effect. Like Bloody Rain = 4 times hp for all zombies ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove the descrpition when the text goes to bottom middle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When the weather text at middle appear, also write what does that weather do too ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the weather text go to bottom middle instead of bottom left corner ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Lets add this: After the 10. wave, every wave there is a %5 change to have a special weather, like : Windy = All zombies are %50 faster Blood Smell = Double amouth of zombies Blood Rain = Every zombie has double hp Unlucky Clouds = There is %20 change to your gun dont shoot BLOOD MOON = ALL OF THEM The weather will written at the middle of the screen at the start for 3 second then it will shrink and move to left bottom corner. Weathers last for 1 wave. Blood Moon is very rare the other ones is all have equal change to happen. The special weather change increas by %2.5 every wave until its %100 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Lets try monster behavior Improments
User prompt
They are still coming too close they can throw from more far away
User prompt
Make them die with 1 hit, they are coming too close to throw a rock they can throw from more far, make then shake a bit when throwing the rock so they look like realy throwing ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Lets add a zombie that when it comes near enough its start throwing rock at me its has %10 change to replace a normal zombie after wave 25 rock will deal 5 damage and it will keep throwing rock until it dies. Make a texture for it and rock. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
more pls
User prompt
İts working now but it can be less close to center
User prompt
it still cant damage me. can we make it deal damage to me when he is close to center of screen ?
User prompt
They still cant deal damage to me
User prompt
they still cant deal damage to me
User prompt
Crayz zombies cant deal damage to me
User prompt
make a asset for splitter zombie and make its minis green
User prompt
Splitter zombie is cool! Lets make it appear after wave 18. Its has %15 change to replace a tough zombie
User prompt
make it 25
User prompt
TWİCE THE SPEED
User prompt
faster
User prompt
a bit more faster pls ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İts working! Just make them a bit faster
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BloodSplat = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('blood', { anchorX: 0.5, anchorY: 0.5 }); self.lifetime = 300; // 5 seconds at 60fps self.fadeStartTime = 0; self.isFading = false; self.update = function () { self.lifetime--; // Start fading after 10 seconds if (self.lifetime <= 0 && !self.isFading) { self.isFading = true; tween(graphics, { alpha: 0 }, { duration: 3000, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 20; self.dx = 0; self.dy = 0; self.active = true; self.bounced = false; self.bounceCount = 0; // Track number of bounces performed self.update = function () { if (!self.active) return; self.x += self.dx; self.y += self.dy; if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.active = false; } }; self.setDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.dx = dx / distance * self.speed; self.dy = dy / distance * self.speed; // Rotate bullet to face direction of travel graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } }; self.bounce = function (hitMonster) { // Increment bounce count first self.bounceCount++; // Check if we've reached the bounce limit if (self.bounceCount >= bouncyBulletCount) { self.active = false; return; } // Find nearest monster regardless of distance var nearestMonster = null; var nearestDistance = Infinity; // No distance limit for (var i = 0; i < monsters.length; i++) { var monster = monsters[i]; if (!monster.active || monster === hitMonster) continue; var dx = monster.x - self.x; var dy = monster.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestMonster = monster; } } if (nearestMonster) { self.bounced = true; self.bounceTarget = nearestMonster; // Store the target self.setDirection(nearestMonster.x, nearestMonster.y); } else { // No target found, deactivate bullet self.active = false; } }; return self; }); var Card = Container.expand(function (powerType) { var self = Container.call(this); // Card background var cardBg = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5 }); cardBg.tint = 0x2c3e50; self.addChild(cardBg); // Card title text var titleText = new Text2(getPowerTitle(powerType), { size: 50, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -40; self.addChild(titleText); // Card description text var descText = new Text2(getPowerDescription(powerType), { size: 30, fill: 0xECF0F1 }); descText.anchor.set(0.5, 0.5); descText.y = 20; self.addChild(descText); self.powerType = powerType; // Card selection handler self.down = function (x, y, obj) { selectCard(self.powerType); }; return self; }); var CrayzZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('crayzZombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 25; // Even faster speed for maximum challenge self.health = 1; self.damage = 12; self.active = true; self.lastPlayerDistance = 0; self.spiralAngle = 0; // Angle for spiral movement self.crazyTimer = 0; // Timer for random direction changes self.suddenChangeX = 0; // Sudden movement offset X self.suddenChangeY = 0; // Sudden movement offset Y self.isChangingDirection = false; // Flag for direction change animation // Start with a random crazy movement pattern immediately self.startCrazyMovement = function () { if (self.isChangingDirection) return; self.isChangingDirection = true; // Random sudden movement direction var randomAngle = Math.random() * Math.PI * 2; var randomDistance = 100 + Math.random() * 200; var targetX = Math.cos(randomAngle) * randomDistance; var targetY = Math.sin(randomAngle) * randomDistance; // Animate sudden direction change tween(self, { suddenChangeX: targetX, suddenChangeY: targetY }, { duration: 300 + Math.random() * 400, easing: tween.easeInOut, onFinish: function onFinish() { // Reset and prepare for next crazy movement self.suddenChangeX = 0; self.suddenChangeY = 0; self.isChangingDirection = false; } }); }; self.update = function () { if (!self.active) return; // Screen center coordinates var screenCenterX = 1024; // Half of 2048 var screenCenterY = 1366; // Half of 2732 // Calculate distance from screen center var dxToCenter = screenCenterX - self.x; var dyToCenter = screenCenterY - self.y; var distanceToCenter = Math.sqrt(dxToCenter * dxToCenter + dyToCenter * dyToCenter); // Calculate distance to player for damage detection var dxToPlayer = player.x - self.x; var dyToPlayer = player.y - self.y; var distanceToPlayer = Math.sqrt(dxToPlayer * dxToPlayer + dyToPlayer * dyToPlayer); // Spiral movement around screen center self.spiralAngle += 0.1; // Spiral rotation speed // Calculate current position relative to screen center var currentAngle = Math.atan2(self.y - screenCenterY, self.x - screenCenterX); var currentRadius = distanceToCenter; // Gradually decrease radius to spiral inward var targetRadius = Math.max(50, currentRadius - 1); // Minimum radius of 50 pixels // Calculate new position on the spiral var newAngle = currentAngle + 0.1; // Spiral by rotating around center var newX = screenCenterX + Math.cos(newAngle) * targetRadius; var newY = screenCenterY + Math.sin(newAngle) * targetRadius; // Move toward the new spiral position var dx = newX - self.x; var dy = newY - 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; // Rotate zombie to face movement direction graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distanceToPlayer; // CrayzZombie can deal damage when getting close to screen center if (distanceToCenter <= 250) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = distanceToPlayer; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion with spreading effect for (var i = 0; i < 15; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.2; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 150 + Math.random() * 300; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 15); // Score between normal and fast zombie LK.getSound('hit').play(); return true; } return false; }; return self; }); var FastZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('fastZombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; // Faster than normal zombie (2) self.health = 1; self.damage = 10; self.active = true; self.lastPlayerDistance = 0; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - 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; // Rotate monster to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distance; if (self.lastPlayerDistance > 50 && currentDistance <= 50) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = currentDistance; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion with spreading effect for (var i = 0; i < 15; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.2; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 150 + Math.random() * 300; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 10); LK.getSound('hit').play(); return true; } return false; }; return self; }); var MiniZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); // Scale down to make it smaller graphics.scaleX = 0.5; graphics.scaleY = 0.5; // Tint it green to distinguish from normal zombies graphics.tint = 0x44aa44; self.speed = 5; // Fast movement self.health = 1; self.damage = 8; self.active = true; self.lastPlayerDistance = 0; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - 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; // Rotate monster to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distance; if (self.lastPlayerDistance > 50 && currentDistance <= 50) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = currentDistance; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create smaller blood explosion for (var i = 0; i < 8; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.2 + Math.random() * 0.8; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 80 + Math.random() * 150; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 200 + Math.random() * 300; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 5); // Lower score for mini zombie LK.getSound('hit').play(); return true; } return false; }; return self; }); var Monster = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.health = 1; self.damage = 10; self.active = true; self.lastPlayerDistance = 0; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - 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; // Rotate monster to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distance; if (self.lastPlayerDistance > 50 && currentDistance <= 50) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = currentDistance; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion with spreading effect for (var i = 0; i < 15; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.2; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 150 + Math.random() * 300; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 10); LK.getSound('hit').play(); return true; } return false; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.fireRate = 30; // Slower initial fire rate self.fireTimer = 0; self.update = function () { if (self.fireTimer > 0) { self.fireTimer--; } }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xff0000, 300); }; self.canFire = function () { return self.fireTimer <= 0; }; self.fire = function () { if (self.canFire()) { self.fireTimer = self.fireRate; return true; } return false; }; return self; }); var Rock = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('rock', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.dx = 0; self.dy = 0; self.active = true; self.damage = 5; self.update = function () { if (!self.active) return; self.x += self.dx; self.y += self.dy; // Remove rock if it goes off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.active = false; } // Check collision with player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 85) { // Player radius + rock radius player.takeDamage(self.damage); self.active = false; } }; self.setDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.dx = dx / distance * self.speed; self.dy = dy / distance * self.speed; // Rotate rock to face direction of travel graphics.rotation = Math.atan2(dy, dx); } }; return self; }); var RockThrowerZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('rockThrowerZombie', { anchorX: 0.5, anchorY: 0.5 }); graphics.rotation = Math.PI; // Face downward like other zombies self.speed = 1; // Slower movement speed self.health = 1; self.damage = 0; // Doesn't deal contact damage self.active = true; self.lastPlayerDistance = 0; self.throwCooldown = 0; self.throwRange = 900; // Range to start throwing rocks self.isInRange = false; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Move toward player but stop at throwing range if (distance > self.throwRange) { if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; // Rotate zombie to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } self.isInRange = false; } else { // In range - stop moving and start throwing self.isInRange = true; // Face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } // Throw rocks when in range if (self.isInRange && self.throwCooldown <= 0) { self.throwRock(); self.throwCooldown = 120; // 2 seconds between throws } if (self.throwCooldown > 0) { self.throwCooldown--; } self.lastPlayerDistance = distance; }; self.throwRock = function () { var rock = new Rock(); rock.x = self.x; rock.y = self.y; rock.setDirection(player.x, player.y); rocks.push(rock); game.addChild(rock); // Shake animation when throwing var originalX = self.x; var originalY = self.y; tween(self, { x: originalX + 15, y: originalY + 10 }, { duration: 80, onFinish: function onFinish() { tween(self, { x: originalX - 10, y: originalY - 8 }, { duration: 80, onFinish: function onFinish() { tween(self, { x: originalX, y: originalY }, { duration: 80 }); } }); } }); }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion for (var i = 0; i < 12; i++) { var bloodSplat = new BloodSplat(); bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.0; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; var angle = Math.random() * Math.PI * 2; var distance = 120 + Math.random() * 250; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 18); // Score between tough and splitter LK.getSound('hit').play(); return true; } return false; }; return self; }); var SplitterZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('splitterZombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; // Medium speed self.health = 2; // Same as tough zombie self.damage = 12; // Medium damage self.active = true; self.lastPlayerDistance = 0; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - 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; // Rotate monster to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distance; if (self.lastPlayerDistance > 50 && currentDistance <= 50) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = currentDistance; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion for (var i = 0; i < 12; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.0; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 120 + Math.random() * 250; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } // Spawn 2-3 mini zombies var miniCount = 2 + Math.floor(Math.random() * 2); // 2 or 3 mini zombies for (var m = 0; m < miniCount; m++) { var miniZombie = new MiniZombie(); // Position mini zombies around the original position var spawnAngle = Math.PI * 2 / miniCount * m + Math.random() * 0.5; var spawnDistance = 80 + Math.random() * 40; miniZombie.x = self.x + Math.cos(spawnAngle) * spawnDistance; miniZombie.y = self.y + Math.sin(spawnAngle) * spawnDistance; // Keep within bounds miniZombie.x = Math.max(125, Math.min(1923, miniZombie.x)); miniZombie.y = Math.max(125, Math.min(2607, miniZombie.y)); monsters.push(miniZombie); game.addChild(miniZombie); } LK.setScore(LK.getScore() + 25); // Higher score for splitter zombie LK.getSound('hit').play(); return true; } return false; }; return self; }); var ToughZombie = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('toughZombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.5; // Slower than normal zombie self.health = 2; // Much tougher self.damage = 15; // Higher damage self.active = true; self.lastPlayerDistance = 0; self.update = function () { if (!self.active) return; var dx = player.x - self.x; var dy = player.y - 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; // Rotate monster to face the player graphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; } var currentDistance = distance; if (self.lastPlayerDistance > 50 && currentDistance <= 50) { player.takeDamage(self.damage); self.active = false; } self.lastPlayerDistance = currentDistance; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.active = false; // Create blood explosion with spreading effect for (var i = 0; i < 15; i++) { var bloodSplat = new BloodSplat(); // Start at monster position bloodSplat.x = self.x; bloodSplat.y = self.y; bloodSplat.graphics = bloodSplat.children[0]; var scale = 0.3 + Math.random() * 1.2; bloodSplat.graphics.scaleX = scale; bloodSplat.graphics.scaleY = scale; // Calculate random spread destination var angle = Math.random() * Math.PI * 2; var distance = 150 + Math.random() * 300; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; // Keep within game bounds targetX = Math.max(50, Math.min(1998, targetX)); targetY = Math.max(50, Math.min(2682, targetY)); // Animate spreading with random delay and duration var delay = Math.random() * 200; var duration = 300 + Math.random() * 400; tween(bloodSplat, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); bloodSplats.push(bloodSplat); game.addChild(bloodSplat); } LK.setScore(LK.getScore() + 20); // Higher score for tough zombie LK.getSound('hit').play(); return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ var player = null; var bullets = []; var monsters = []; var bloodSplats = []; var rocks = []; var waveNumber = 1; var monstersInWave = 5; var monstersSpawned = 0; var monstersKilled = 0; var spawnTimer = 0; var waveDelay = 180; var bulletCooldown = 30; // Start with cooldown to prevent immediate shooting // Secret wave skip variables (hidden from normal players) var secretTapCount = 0; var secretTapTimer = 0; var secretZone = { x: 1900, y: 2600, width: 148, height: 132 }; // Bottom-right corner // Fast zombie spawn chance (starts at 10%, increases 1% per wave, max 80%) var fastZombieChance = 10; // Tough zombie spawn chance (starts at 5% after wave 5, increases 1% per wave, max 90%) var toughZombieChance = 5; // Crayz zombie spawn chance (10% after wave 15 to replace fast zombies) var crayzZombieChance = 10; // Splitter zombie spawn chance (15% after wave 18 to replace tough zombies) var splitterZombieChance = 15; // Rock thrower zombie spawn chance (10% after wave 25 to replace normal zombies) var rockThrowerZombieChance = 10; // Weather system variables var currentWeather = null; var weatherActive = false; var weatherChance = 5; // Starting at 5% after wave 10 var weatherText = null; var weatherTypes = ['windy', 'bloodSmell', 'bloodRain', 'unluckyClouds']; var weatherEffects = { windy: false, bloodSmell: false, bloodRain: false, unluckyClouds: false, bloodMoon: false }; // Weather utility functions function getWeatherName(weather) { switch (weather) { case 'windy': return 'WINDY'; case 'bloodSmell': return 'BLOOD SMELL'; case 'bloodRain': return 'BLOOD RAIN'; case 'unluckyClouds': return 'UNLUCKY CLOUDS'; case 'bloodMoon': return 'BLOOD MOON'; default: return ''; } } function getWeatherDescription(weather) { switch (weather) { case 'windy': return 'All zombies are 50% faster'; case 'bloodSmell': return 'Double amount of zombies'; case 'bloodRain': return 'Every zombie has double HP'; case 'unluckyClouds': return '20% chance your gun won\'t shoot'; case 'bloodMoon': return 'ALL EFFECTS COMBINED!'; default: return ''; } } function applyWeatherEffects(weather) { // Reset all weather effects first weatherEffects.windy = false; weatherEffects.bloodSmell = false; weatherEffects.bloodRain = false; weatherEffects.unluckyClouds = false; weatherEffects.bloodMoon = false; if (weather === 'bloodMoon') { // Blood moon activates all effects weatherEffects.windy = true; weatherEffects.bloodSmell = true; weatherEffects.bloodRain = true; weatherEffects.unluckyClouds = true; weatherEffects.bloodMoon = true; } else if (weather) { weatherEffects[weather] = true; } } function showWeatherAnnouncement(weather) { var weatherName = getWeatherName(weather); var weatherDescription = getWeatherDescription(weather); // Create weather text at center of screen weatherText = new Text2(weatherName + '\n' + weatherDescription, { size: 120, fill: weather === 'bloodMoon' ? 0xFF0000 : 0xFFFFFF }); weatherText.anchor.set(0.5, 0.5); weatherText.x = 1024; weatherText.y = 1366; if (weather === 'bloodMoon') { weatherText.tint = 0xFF0000; } game.addChild(weatherText); // After 3 seconds, shrink and move to bottom left LK.setTimeout(function () { if (weatherText) { tween(weatherText, { scaleX: 0.3, scaleY: 0.3, x: 1024, y: 2650 }, { duration: 1000, easing: tween.easeInOut }); } }, 3000); } function checkForWeather() { // Only check for weather after wave 10 if (waveNumber < 10) return; // Calculate current weather chance (5% + 2.5% per wave, max 100%) var currentWeatherChance = Math.min(5 + (waveNumber - 10) * 2.5, 100); if (Math.random() * 100 < currentWeatherChance) { var selectedWeather; // Very small chance for blood moon (1% of weather events) if (Math.random() * 100 < 1) { selectedWeather = 'bloodMoon'; } else { // Equal chance for other weather types selectedWeather = weatherTypes[Math.floor(Math.random() * weatherTypes.length)]; } currentWeather = selectedWeather; weatherActive = true; applyWeatherEffects(selectedWeather); showWeatherAnnouncement(selectedWeather); } } function clearWeather() { currentWeather = null; weatherActive = false; applyWeatherEffects(null); // Remove weather text if it exists if (weatherText) { weatherText.destroy(); weatherText = null; } } // Card system variables var isCardSelectionActive = false; var cardContainer = null; var selectedPower = null; var availablePowers = ['bouncy', 'rapidfire', 'multishot']; var activePowers = []; var bouncyBulletCount = 1; // Number of bounces for bouncy bullets var multishotBulletCount = 1; // Number of bullets to fire for multishot var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var healthText = new Text2('Health: 100', { size: 50, fill: 0xFF4444 }); healthText.anchor.set(0, 0); healthText.x = 120; healthText.y = 20; LK.gui.topLeft.addChild(healthText); var waveText = new Text2('Wave: 1', { size: 50, fill: 0x4A90E2 }); waveText.anchor.set(1, 0); LK.gui.topRight.addChild(waveText); // Power utility functions function getPowerTitle(powerType) { switch (powerType) { case 'bouncy': return 'Bouncy Bullets'; case 'rapidfire': return 'Rapid Fire'; case 'multishot': return 'Multi Shot'; default: return 'Unknown Power'; } } function getPowerDescription(powerType) { switch (powerType) { case 'bouncy': return 'Bullets bounce to nearby enemies'; case 'rapidfire': return 'Faster shooting speed'; case 'multishot': return 'Shoot 3 bullets at once'; default: return 'Unknown effect'; } } function showCardSelection() { isCardSelectionActive = true; // Create card container cardContainer = new Container(); game.addChild(cardContainer); // Create dark overlay var overlay = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.8 }); overlay.tint = 0x000000; cardContainer.addChild(overlay); // Select 3 random powers var shuffledPowers = availablePowers.slice(); for (var i = shuffledPowers.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = shuffledPowers[i]; shuffledPowers[i] = shuffledPowers[j]; shuffledPowers[j] = temp; } var selectedPowers = shuffledPowers.slice(0, 3); // Create cards for (var i = 0; i < 3; i++) { var card = new Card(selectedPowers[i]); card.x = 512 + i * 512; card.y = 1366; cardContainer.addChild(card); // Animate cards in tween(card, { y: 1000 }, { duration: 500, easing: tween.easeOut }); } // Add title text var titleText = new Text2('Choose Your Power!', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; cardContainer.addChild(titleText); } function selectCard(powerType) { if (!isCardSelectionActive) return; // Add power to active powers activePowers.push(powerType); // Apply power effect applyPowerEffect(powerType); // Animate cards out and clean up if (cardContainer) { tween(cardContainer, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (cardContainer) { cardContainer.destroy(); } cardContainer = null; isCardSelectionActive = false; } }); } } function applyPowerEffect(powerType) { switch (powerType) { case 'rapidfire': player.fireRate = Math.max(1, Math.floor(player.fireRate / 2)); break; case 'multishot': // Increase bullet count for multishot multishotBulletCount++; break; case 'bouncy': // Increase bounce count for all future bullets bouncyBulletCount++; break; } } var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); player = game.addChild(new Player()); player.x = 1024; player.y = 1366; function spawnMonster() { if (monstersSpawned >= monstersInWave) return; // Spawn multiple monsters at once based on wave number - more balanced progression var monstersToSpawn = 1; if (waveNumber >= 3) monstersToSpawn = 2; if (waveNumber >= 6) monstersToSpawn = 3; if (waveNumber >= 10) monstersToSpawn = Math.min(4, Math.floor(waveNumber / 3)); var actualSpawn = Math.min(monstersToSpawn, monstersInWave - monstersSpawned); for (var spawnIndex = 0; spawnIndex < actualSpawn; spawnIndex++) { // Calculate current tough zombie chance (5% base + 1% per wave after wave 10, max 90%) var currentToughZombieChance = waveNumber >= 10 ? Math.min(5 + (waveNumber - 10), 90) : 0; // Determine zombie type with priority: splitter > tough > crayz > fast > rockthrower > normal var randomChance = Math.random() * 100; var monster; if (waveNumber >= 10 && randomChance < currentToughZombieChance) { // 15% chance to spawn splitter zombie instead of tough zombie after wave 18 if (waveNumber >= 18 && Math.random() * 100 < splitterZombieChance) { monster = new SplitterZombie(); } else { monster = new ToughZombie(); } } else if (waveNumber >= 15 && randomChance < currentToughZombieChance + crayzZombieChance) { // 10% chance to spawn crayz zombie instead of fast zombie after wave 15 monster = new CrayzZombie(); } else if (waveNumber >= 5 && randomChance < currentToughZombieChance + crayzZombieChance + fastZombieChance) { monster = new FastZombie(); } else if (waveNumber >= 25 && randomChance < currentToughZombieChance + crayzZombieChance + fastZombieChance + rockThrowerZombieChance) { // 10% chance to spawn rock thrower zombie after wave 25 monster = new RockThrowerZombie(); } else { monster = new Monster(); } var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top monster.x = Math.random() * 2048; monster.y = -30; break; case 1: // Right monster.x = 2078; monster.y = Math.random() * 2732; break; case 2: // Bottom monster.x = Math.random() * 2048; monster.y = 2762; break; case 3: // Left monster.x = -30; monster.y = Math.random() * 2732; break; } // Apply weather effects to monster if (weatherEffects.windy) { monster.speed *= 1.5; // 50% faster } if (weatherEffects.bloodRain) { monster.health *= 2; // Double HP } monsters.push(monster); game.addChild(monster); monstersSpawned++; } } function cleanupBullets() { for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (!bullet.active) { bullet.destroy(); bullets.splice(i, 1); } } } function cleanupMonsters() { for (var i = monsters.length - 1; i >= 0; i--) { var monster = monsters[i]; if (!monster.active) { monster.destroy(); monsters.splice(i, 1); monstersKilled++; } } } function cleanupBloodSplats() { for (var i = bloodSplats.length - 1; i >= 0; i--) { var bloodSplat = bloodSplats[i]; if (!bloodSplat.parent) { bloodSplats.splice(i, 1); } } } function cleanupRocks() { for (var i = rocks.length - 1; i >= 0; i--) { var rock = rocks[i]; if (!rock.active) { rock.destroy(); rocks.splice(i, 1); } } } function checkBulletCollisions() { for (var i = 0; i < bullets.length; i++) { var bullet = bullets[i]; if (!bullet.active) continue; for (var j = 0; j < monsters.length; j++) { var monster = monsters[j]; if (!monster.active) continue; if (bullet.intersects(monster)) { monster.takeDamage(1); // Try to bounce bullet if bouncy power is active and bullet hasn't exceeded bounce limit if (bullet.bounceCount < bouncyBulletCount && activePowers.indexOf('bouncy') !== -1) { bullet.bounce(monster); // If bounce was successful (found a target), keep bullet active if (bullet.bounced) { break; // Stop checking other monsters for this bullet this frame } } // Only deactivate bullet if it reached bounce limit or bouncy power is not active if (bullet.bounceCount >= bouncyBulletCount || activePowers.indexOf('bouncy') === -1) { bullet.active = false; } break; } } } } function nextWave() { waveNumber++; // Check for card selection every 5 waves if (waveNumber % 5 === 0 && waveNumber > 0) { showCardSelection(); return; // Don't start next wave until card is selected } // More balanced wave size progression: slower growth after wave 10 if (waveNumber <= 10) { monstersInWave = 3 + waveNumber * 2; } else { monstersInWave = 23 + Math.floor((waveNumber - 10) / 2); } // Apply blood smell weather effect (double monsters) if (weatherEffects.bloodSmell) { monstersInWave *= 2; } monstersSpawned = 0; monstersKilled = 0; spawnTimer = 0; waveDelay = 180; // Increase fast zombie chance by 1% each wave, max 80% fastZombieChance = Math.min(10 + waveNumber, 80); waveText.setText('Wave: ' + waveNumber); // Clear previous weather and check for new weather clearWeather(); checkForWeather(); } game.down = function (x, y, obj) { // Secret wave skip check (bottom-right corner taps) if (x >= secretZone.x && x <= secretZone.x + secretZone.width && y >= secretZone.y && y <= secretZone.y + secretZone.height) { secretTapCount++; secretTapTimer = 120; // 2 seconds to complete sequence if (secretTapCount >= 5) { // Skip 3 waves var skipAmount = 3; // Skip waves instantly for (var skipCount = 0; skipCount < skipAmount; skipCount++) { waveNumber++; } // Calculate wave size using balanced progression if (waveNumber <= 10) { monstersInWave = 3 + waveNumber * 2; } else { monstersInWave = 23 + Math.floor((waveNumber - 10) / 2); } // Update fast zombie chance for the new wave fastZombieChance = Math.min(10 + waveNumber, 80); monstersSpawned = 0; monstersKilled = monstersInWave; // Clear all current monsters for (var i = 0; i < monsters.length; i++) { if (monsters[i].active) { monsters[i].active = false; } } secretTapCount = 0; waveText.setText('Wave: ' + waveNumber); // Visual feedback (brief flash) LK.effects.flashScreen(0x00ff00, 200); } return; } // Check unlucky clouds weather effect (20% chance gun doesn't shoot) var gunJammed = weatherEffects.unluckyClouds && Math.random() * 100 < 20; if (bulletCooldown <= 0 && player.fire() && !gunJammed) { // Check if multishot is active var shotCount = activePowers.indexOf('multishot') !== -1 ? multishotBulletCount : 1; for (var shotIndex = 0; shotIndex < shotCount; shotIndex++) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y; if (shotCount === 1) { // Single shot - aim directly at target bullet.setDirection(x, y); } else { // Multishot - spread bullets var baseAngle = Math.atan2(y - player.y, x - player.x); var spreadAngle = (shotIndex - (shotCount - 1) / 2) * 0.3; // Center the spread var finalAngle = baseAngle + spreadAngle; var targetX = player.x + Math.cos(finalAngle) * 500; var targetY = player.y + Math.sin(finalAngle) * 500; bullet.setDirection(targetX, targetY); } bullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); bulletCooldown = player.fireRate; } }; LK.playMusic('bgmusic'); game.update = function () { // Pause game during card selection if (isCardSelectionActive) { return; } // Secret wave skip timer if (secretTapTimer > 0) { secretTapTimer--; if (secretTapTimer <= 0) { secretTapCount = 0; // Reset if too slow } } if (bulletCooldown > 0) { bulletCooldown--; } if (waveDelay > 0) { waveDelay--; return; } spawnTimer++; if (spawnTimer >= 60 && monstersSpawned < monstersInWave) { spawnMonster(); spawnTimer = 0; } checkBulletCollisions(); cleanupBullets(); cleanupMonsters(); cleanupBloodSplats(); cleanupRocks(); if (monstersKilled >= monstersInWave && monsters.length === 0) { nextWave(); } scoreText.setText('Score: ' + LK.getScore()); healthText.setText('Health: ' + player.health); };
===================================================================
--- original.js
+++ change.js
@@ -899,8 +899,24 @@
default:
return '';
}
}
+function getWeatherDescription(weather) {
+ switch (weather) {
+ case 'windy':
+ return 'All zombies are 50% faster';
+ case 'bloodSmell':
+ return 'Double amount of zombies';
+ case 'bloodRain':
+ return 'Every zombie has double HP';
+ case 'unluckyClouds':
+ return '20% chance your gun won\'t shoot';
+ case 'bloodMoon':
+ return 'ALL EFFECTS COMBINED!';
+ default:
+ return '';
+ }
+}
function applyWeatherEffects(weather) {
// Reset all weather effects first
weatherEffects.windy = false;
weatherEffects.bloodSmell = false;
@@ -919,10 +935,11 @@
}
}
function showWeatherAnnouncement(weather) {
var weatherName = getWeatherName(weather);
+ var weatherDescription = getWeatherDescription(weather);
// Create weather text at center of screen
- weatherText = new Text2(weatherName, {
+ weatherText = new Text2(weatherName + '\n' + weatherDescription, {
size: 120,
fill: weather === 'bloodMoon' ? 0xFF0000 : 0xFFFFFF
});
weatherText.anchor.set(0.5, 0.5);
Bullet. In-Game asset. 2d. High contrast. No shadows
A extremly basic zombie look from top. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A round drop of blood. In-Game asset. 2d. High contrast. No shadows
Make it simple no blood or object
Make its skin blue and make it smile
A happier version of this zombie but its will be purple
Make it green
small rock. In-Game asset. 2d. High contrast. No shadows
Yellow version of it
make it white
Explosion!. In-Game asset. 2d. High contrast. No shadows
Lightning. In-Game asset. 2d. High contrast. No shadows
Make it rainbow and extremly happy
A cowboy hat from top. In-Game asset. 2d. High contrast. No shadows
Hake his skin red and add horns
A card. In-Game asset. 2d. High contrast. No shadows