User prompt
Rotate vertical line 6 5° left ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move vertical line 3 right 100
User prompt
Rotate vertical line 3 right 5° ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move vertical line 2 left 25
User prompt
Move vertical line 2 right 150
User prompt
Rotate vertical line2 7° right ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move vertical line 1 right 150
User prompt
Move vertical line 1 right 200
User prompt
Rotate vertical line 1 right 7° ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move vertical line 1 right 150
User prompt
Rotate vertical line 1 right 15° ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move vertical line 3 left 80
User prompt
Move vertical line 7 right 120
User prompt
Move vertical line 2 left 120
User prompt
Move vertical line 8 right 150
User prompt
Move vertical line 1 left 150
User prompt
Move vertical line left 100
User prompt
Rotate vertical line 1 right 45° ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Create 8 vertical guidelines same size as the other ones
User prompt
When fan goes into cool down mode it stops rotating for 10 seconds leaving it vulnerable to be attacked and destroyed by enemies ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move all lines down 50
User prompt
Move blade down 25
User prompt
Move blades down 25
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'rotation')' in or related to this line: 'tween(tower.blades, {' Line Number: 436 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When enemy collides with fan blades blow them back 400 pixels and inflict damage to enemy ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Button class var Button = Container.expand(function () { var self = Container.call(this); // Button properties self.text = ''; self.backgroundColor = 0x333333; self.textColor = 0xffffff; self.width = 200; self.height = 80; self.fontSize = 40; self.isPressed = false; // Create button background self.background = self.attachAsset('notification', { anchorX: 0.5, anchorY: 0.5, tint: self.backgroundColor }); // Create button text self.buttonText = new Text2(self.text, { size: self.fontSize, fill: self.textColor }); self.buttonText.anchor.set(0.5, 0.5); self.buttonText.x = 0; self.buttonText.y = 0; self.addChild(self.buttonText); // Method to set button properties self.setup = function (options) { if (options.text !== undefined) { self.text = options.text; self.buttonText.setText(self.text); } if (options.backgroundColor !== undefined) { self.backgroundColor = options.backgroundColor; self.background.tint = self.backgroundColor; } if (options.textColor !== undefined) { self.textColor = options.textColor; // Recreate text with new color since Text2 doesn't have a modifiable style property self.removeChild(self.buttonText); self.buttonText = new Text2(self.text, { size: self.fontSize, fill: self.textColor }); self.buttonText.anchor.set(0.5, 0.5); self.buttonText.x = 0; self.buttonText.y = 0; self.addChild(self.buttonText); } if (options.width !== undefined) { self.width = options.width; self.background.width = self.width; } if (options.height !== undefined) { self.height = options.height; self.background.height = self.height; } if (options.fontSize !== undefined) { self.fontSize = options.fontSize; // Recreate text with new font size since Text2 doesn't have a modifiable style property self.removeChild(self.buttonText); self.buttonText = new Text2(self.text, { size: self.fontSize, fill: self.textColor }); self.buttonText.anchor.set(0.5, 0.5); self.buttonText.x = 0; self.buttonText.y = 0; self.addChild(self.buttonText); } }; // Touch down event self.down = function (x, y, obj) { self.isPressed = true; // Visual feedback - darken button self.background.alpha = 0.7; // Call custom down handler if defined if (self.onDown) { self.onDown(x, y, obj); } }; // Touch up event self.up = function (x, y, obj) { if (self.isPressed) { self.isPressed = false; // Reset visual state self.background.alpha = 1.0; // Call custom up handler if defined if (self.onUp) { self.onUp(x, y, obj); } // Call click handler if defined if (self.onClick) { self.onClick(x, y, obj); } } }; return self; }); // Defense class var Defense = Container.expand(function () { var self = Container.call(this); var defenseGraphics = self.attachAsset('defense', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Defense logic goes here }; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); // Attach probedroid as the main enemy graphic var enemyGraphics = self.attachAsset('Probedroid', { anchorX: 0.5, anchorY: 0.5 }); // Add flashing lights to probe droid var light1 = self.attachAsset('rangeCircle', { anchorX: 0.5, anchorY: 0.5, x: -25, y: -85, scaleX: 0.03, scaleY: 0.03, tint: 0xff0000, alpha: 0.5 }); var light2 = self.attachAsset('rangeCircle', { anchorX: 0.5, anchorY: 0.5, x: 55, y: -85, scaleX: 0.03, scaleY: 0.03, tint: 0x00ff00, alpha: 0.5 }); var light3 = self.attachAsset('rangeCircle', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -100, scaleX: 0.02, scaleY: 0.02, tint: 0x0000ff, alpha: 0.5 }); // Start flashing animations for the lights function startLightFlashing() { // Red light flashing tween(light1, { alpha: 0.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(light1, { alpha: 0.6 }, { duration: 800, easing: tween.easeInOut, onFinish: startLightFlashing }); } }); // Green light flashing (offset timing) LK.setTimeout(function () { tween(light2, { alpha: 0.1 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(light2, { alpha: 0.6 }, { duration: 600, easing: tween.easeInOut }); } }); }, 300); // Blue light flashing (different timing) LK.setTimeout(function () { tween(light3, { alpha: 0.15 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(light3, { alpha: 0.6 }, { duration: 1000, easing: tween.easeInOut }); } }); }, 600); } // Start the flashing animation startLightFlashing(); // Initialize enemy properties self.speed = -2; // Default movement speed self.health = 100; // Default health self.maxHealth = 100; // Default max health self.pathLine = 1; // Default path line self.lastX = undefined; // Track last X position // Add number text self.numberText = new Text2('1', { size: 60, fill: 0x000000 }); self.numberText.anchor.set(0.5, 0.5); self.numberText.x = 0; self.numberText.y = 0; self.addChild(self.numberText); // Add health bar var healthBarOutline = self.attachAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -150 }); var healthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -150, tint: 0x00ff00 }); self.updateHealthBar = function () { var healthPercentage = self.health / self.maxHealth; healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { healthBar.tint = 0xffff00; // Yellow } else { healthBar.tint = 0xff0000; // Red } }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; } self.updateHealthBar(); }; self.update = function () { // Initialize lastX if not set if (self.lastX === undefined) self.lastX = self.x; // Update health bar self.updateHealthBar(); }; return self; }); // Assets will be automatically created and loaded by the LK engine // Tower class var Tower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('tower', { anchorX: 0.5, anchorY: 0.5 }); // Initialize tower health self.health = 100; self.maxHealth = 100; self.isBeingDamaged = false; self.lastDamageTime = 0; // Method to take damage self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; } }; self.update = function () { // Tower logic goes here }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 //Init game with black background }); /**** * Game Code ****/ // Game update loop game.update = function () { if (!gameStarted) return; // Spawn enemies enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnInterval) { spawnEnemy(); enemySpawnTimer = 0; } // Update fan tower cooldowns for (var i = 0; i < towers.length; i++) { var tower = towers[i]; // Check if this is a fan tower if (tower.blades) { tower.cooldownTimer++; // Check if cooldown should start if (tower.isRunning && tower.cooldownTimer >= tower.cooldownDuration) { // Start cooldown - stop fan tower.cooldownActive = true; tower.isRunning = false; tower.cooldownTimer = 0; // Stop blade spinning if (tower.blades) { tween.stop(tower.blades); } // Flash fan red to indicate cooldown LK.effects.flashObject(tower, 0xff0000, 1000); } // Check if cooldown should end (10 seconds cooldown) if (tower.cooldownActive && tower.cooldownTimer >= 10 * 60) { // End cooldown - restart fan tower.cooldownActive = false; tower.isRunning = true; tower.cooldownTimer = 0; // Resume blade spinning var _spinBlades2 = function spinBlades() { if (tower.blades) { tween(tower.blades, { rotation: tower.blades.rotation + Math.PI * 2 }, { duration: 500, easing: tween.linear, onFinish: _spinBlades2 }); } }; _spinBlades2(); // Flash fan green to indicate restart LK.effects.flashObject(tower, 0x00ff00, 500); } } } // Update enemies updateEnemies(); // Check win condition if (enemiesSpawned >= maxEnemiesInWave && enemies.length === 0) { LK.showYouWin(); } }; // Mouse move handler for tower preview game.move = function (x, y, obj) { if (isPlacingTower && towerPreview) { towerPreview.x = x; // Snap preview to nearest guideline Y position var snappedY = getNearestGuidelineY(y); towerPreview.y = snappedY; // Update blades position if fan preview has blades if (towerPreview.blades) { towerPreview.blades.x = towerPreview.x + 50; towerPreview.blades.y = towerPreview.y - 40 - 100 + 25 + 25; } } }; var enemies = []; var towers = []; var gameStarted = false; var enemySpawnTimer = 0; var enemySpawnInterval = 600; // Spawn every 10 seconds at 60fps var enemiesSpawned = 0; var maxEnemiesInWave = 10; // Wave 1 has exactly 10 enemies var playerCash = 200; // Player starts with $200 var playerLives = 3; // Player starts with 3 lives var isPlacingTower = false; var selectedTowerType = null; var towerPreview = null; var guidelines = []; var cashText = null; var confirmButton = null; var enemyNumber = 1; // Track enemy numbers for display // Define path positions for different lines var pathPositions = { line6: 2732 / 7 * 6 - 310 + 50, // Line 6 position line2: 2732 / 7 * 2 + 320 + 50, // Line 2 position line3: 2732 / 7 * 3 + 150 + 50, // Line 3 position line4: 2732 / 7 * 4 + 10 + 50, // Line 4 position line5: 2732 / 7 * 5 - 150 + 50, // Line 5 position line1: 2732 / 7 * 1 + 480 + 50 // Line 1 position }; // Helper function to get nearest guideline Y position function getNearestGuidelineY(y) { var nearestY = y; var minDistance = Infinity; for (var i = 0; i < guidelines.length; i++) { var guideline = guidelines[i]; var distance = Math.abs(guideline.y - y); if (distance < minDistance) { minDistance = distance; nearestY = guideline.y; } } return nearestY; } // Tower defense functions function startTowerDefenseWave1() { gameStarted = true; enemySpawnTimer = 0; enemiesSpawned = 0; // Add score display to top of screen var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 50; game.addChild(scoreText); // Add cash display to top of screen cashText = new Text2('Cash: $' + playerCash, { size: 80, fill: 0xFFD700 }); cashText.anchor.set(0.5, 0); cashText.x = 2048 / 2 + 300 + 200; cashText.y = 50; game.addChild(cashText); // Add lives display to top of screen var livesText = new Text2('Lives: ' + playerLives, { size: 80, fill: 0xFF4444 }); livesText.anchor.set(0.5, 0); livesText.x = 2048 / 2 - 300 - 200; livesText.y = 50; game.addChild(livesText); // Add skip wave button to top of screen var skipWaveButton = new Text2('SKIP WAVE', { size: 60, fill: 0xFFFFFF }); skipWaveButton.anchor.set(0.5, 0); skipWaveButton.x = 2048 / 2; skipWaveButton.y = 150; game.addChild(skipWaveButton); // Add touch event to skip wave button skipWaveButton.down = function (x, y, obj) { // Skip to end of wave - destroy all enemies and show you win for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } enemies = []; enemiesSpawned = maxEnemiesInWave; LK.showYouWin(); }; // Add Gasbutton to bottom of game scene var gasButton = game.addChild(LK.getAsset('Gasbutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 50, y: 2732 - 350 })); // Add Waterbutton to bottom left of game scene var waterButton = game.addChild(LK.getAsset('Waterbutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 50, y: 2732 - 350 })); // Water button click handler waterButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 10) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'water'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Tower1', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Tower1', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); newTower._assetId = 'Tower1'; // Mark this as a water tower newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; newTower.lastFireTime = 0; // Initialize fire rate tracking // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 120 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 120, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Check for enemies in range immediately after placing for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Check if enemy is on the same horizontal line as the tower (within 50 pixels tolerance) if (Math.abs(enemy.y - newTower.y) < 50) { // Check if enemy is to the right of the tower and within range of 700 pixels if (enemy.x > newTower.x && enemy.x - newTower.x < 700) { // Fire immediately by setting lastFireTime in the past newTower.lastFireTime = LK.ticks - 30; break; // Found an enemy in range } } } // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); } // Deduct cost and update display playerCash -= 10; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Gas button click handler gasButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 20) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'gas'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Dog', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Dog', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); newTower._assetId = 'Dog'; // Mark this as a gas tower newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; newTower.lastFireTime = 0; // Initialize fire rate tracking // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 120 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 120, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Check for enemies in range immediately after placing for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Check if enemy is on the same horizontal line as the tower (within 50 pixels tolerance) if (Math.abs(enemy.y - newTower.y) < 50) { // Check if enemy is to the right of the tower and within range of 600 pixels if (enemy.x > newTower.x && enemy.x - newTower.x < 600) { // Fire immediately by setting lastFireTime in the past newTower.lastFireTime = LK.ticks - 45; break; // Found an enemy in range } } } // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); } // Deduct cost and update display playerCash -= 20; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Add Airbutton to the right side of gasbutton var airButton = game.addChild(LK.getAsset('Airbutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 420 + 50 + 50, y: 2732 - 350 })); // Air button click handler airButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 30) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'air'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Fan', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Add blades to fan preview var previewBlades = game.addChild(LK.getAsset('Blades', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x + 50, y: towerPreview.y - 40 - 100 + 25 + 25, alpha: 0.5 })); // Store blades reference in tower preview towerPreview.blades = previewBlades; // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Create spinning animation for blades var _spinBlades = function spinBlades() { tween(blades, { rotation: blades.rotation + Math.PI * 2 }, { duration: 500, easing: tween.linear, onFinish: _spinBlades }); }; // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Fan', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); // Add blades asset to fan tower var blades = game.addChild(LK.getAsset('Blades', { anchorX: 0.5, anchorY: 0.5, x: newTower.x + 50, y: newTower.y - 40 - 100 + 25 + 25 })); _spinBlades(); // Store blades reference in tower newTower.blades = blades; newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; // Add cooldown properties for fan newTower.cooldownTimer = 0; newTower.cooldownDuration = 20 * 60; // 20 seconds at 60fps newTower.cooldownActive = false; newTower.isRunning = true; // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 170 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 170, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); // Re-add blades if this tower has them to ensure they render in front if (towers[i].blades) { game.removeChild(towers[i].blades); game.addChild(towers[i].blades); } } // Deduct cost and update display playerCash -= 30; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; // Destroy preview blades if they exist if (towerPreview.blades) { towerPreview.blades.destroy(); } towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Add Firebutton to the right side of airbutton var fireButton = game.addChild(LK.getAsset('Firebutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 420 + 50 + 426 + 50 + 50, y: 2732 - 350 })); // Fire button click handler fireButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 40) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'fire'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Fireworks', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Fireworks', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 210 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 210, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); } // Deduct cost and update display playerCash -= 40; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Add mystery button under air button var mysteryButton1 = game.addChild(LK.getAsset('Mysterybutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 420 + 50 + 50, y: 2732 - 350 + 200 + 20 })); // Add Electricbutton to bottom of screen under water button var electricButton = game.addChild(LK.getAsset('Electricbutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 50, y: 2732 - 350 + 200 + 20 })); // Electric button click handler electricButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 50) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'electric'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Bugzapper', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Bugzapper', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 210 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 210, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); } // Deduct cost and update display playerCash -= 50; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Add Plasmabutton to bottom of screen under gas button var plasmaButton = game.addChild(LK.getAsset('Plasmabutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 50, y: 2732 - 350 + 200 + 20 })); // Plasma button click handler plasmaButton.down = function (x, y, obj) { // Check if player has enough cash if (playerCash >= 60) { // Start tower placement mode isPlacingTower = true; selectedTowerType = 'plasma'; // Create tower preview if (towerPreview) { towerPreview.destroy(); } towerPreview = game.addChild(LK.getAsset('Plasmaball', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 })); // Create green tick button for confirming placement if (confirmButton) { confirmButton.destroy(); } confirmButton = game.addChild(new Button()); confirmButton.setup({ text: '✓', backgroundColor: 0x00FF00, textColor: 0xFFFFFF, width: 120, height: 120, fontSize: 80 }); confirmButton.x = 2048 - 150; confirmButton.y = 2732 / 2; confirmButton.onClick = function () { // Place tower at current preview position if (towerPreview) { // Align tower Y position to nearest guideline var alignedY = getNearestGuidelineY(towerPreview.y); var newTower = game.addChild(LK.getAsset('Plasmaball', { anchorX: 0.5, anchorY: 0.5, x: towerPreview.x, y: alignedY, alpha: 1 })); newTower.health = 100; newTower.maxHealth = 100; newTower.isBeingDamaged = false; newTower.lastDamageTime = 0; // Add health bar to tower var healthBarOutline = game.addChild(LK.getAsset('healthBarOutline', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 150 })); var healthBar = game.addChild(LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: newTower.x, y: newTower.y - 150, tint: 0x00ff00 })); newTower.healthBarOutline = healthBarOutline; newTower.healthBar = healthBar; newTower.takeDamage = function (damage) { newTower.health -= damage; if (newTower.health <= 0) { newTower.health = 0; } // Update health bar var healthPercentage = newTower.health / newTower.maxHealth; newTower.healthBar.scaleX = healthPercentage; // Change color based on health if (healthPercentage > 0.6) { newTower.healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { newTower.healthBar.tint = 0xffff00; // Yellow } else { newTower.healthBar.tint = 0xff0000; // Red } }; towers.push(newTower); // Sort all towers by Y position (higher Y values should be in front) towers.sort(function (a, b) { return a.y - b.y; }); // Re-add towers to game in sorted order for (var i = 0; i < towers.length; i++) { game.removeChild(towers[i]); game.addChild(towers[i]); } // Deduct cost and update display playerCash -= 60; cashText.setText('Cash: $' + playerCash); // Clean up placement mode isPlacingTower = false; selectedTowerType = null; towerPreview.destroy(); towerPreview = null; confirmButton.destroy(); confirmButton = null; } }; } }; // Add mystery button under fire button var mysteryButton2 = game.addChild(LK.getAsset('Mysterybutton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 4 - 250 + 426.67 + 50 + 420 + 50 + 426 + 50 + 50, y: 2732 - 350 + 200 + 20 })); } function spawnEnemy() { if (enemiesSpawned >= maxEnemiesInWave) return; var enemy = game.addChild(new Enemy()); // Position enemy at the right side of the screen enemy.x = 2048 - 50; // Start from right side // Randomly assign path from all 6 available lines var availableLines = [1, 2, 3, 4, 5, 6]; var randomLineIndex = Math.floor(Math.random() * availableLines.length); var selectedLine = availableLines[randomLineIndex]; // Set enemy position based on randomly selected line if (selectedLine === 1) { enemy.y = pathPositions.line1; enemy.pathLine = 1; } else if (selectedLine === 2) { enemy.y = pathPositions.line2; enemy.pathLine = 2; } else if (selectedLine === 3) { enemy.y = pathPositions.line3; enemy.pathLine = 3; } else if (selectedLine === 4) { enemy.y = pathPositions.line4; enemy.pathLine = 4; } else if (selectedLine === 5) { enemy.y = pathPositions.line5; enemy.pathLine = 5; } else if (selectedLine === 6) { enemy.y = pathPositions.line6; enemy.pathLine = 6; } enemy.health = 100; enemy.maxHealth = 100; enemy.speed = -2; // Negative speed to move left enemy.pathIndex = 0; enemy.lastPathIndex = -1; // Set enemy number enemy.numberText.setText(enemyNumber.toString()); enemies.push(enemy); enemiesSpawned++; } function updateEnemies() { for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // Move enemy using its speed (negative for left movement) enemy.x += enemy.speed; // Check if enemy reached the left side of the screen if (enemy.lastX >= 0 && enemy.x < 0) { // Enemy reached the left side - remove it enemy.destroy(); enemies.splice(i, 1); continue; } // Check for water towers on the same line for (var j = 0; j < towers.length; j++) { var tower = towers[j]; // Check if tower is a water tower (Tower1 asset) by checking the asset's id if (tower._assetId === 'Tower1') { // Check if enemy is on the same horizontal line as the tower (within 50 pixels tolerance) if (Math.abs(enemy.y - tower.y) < 50) { // Check if enemy is to the right of the tower and within range of 700 pixels if (enemy.x > tower.x && enemy.x - tower.x < 700) { // Initialize fire rate tracking for this tower if (!tower.lastFireTime) { tower.lastFireTime = 0; } // Fire every 30 ticks (0.5 seconds at 60fps) if (LK.ticks - tower.lastFireTime >= 30) { tower.lastFireTime = LK.ticks; // Create water squirt visual var waterSquirt = game.addChild(LK.getAsset('Water', { anchorX: 0, anchorY: 0.5, x: tower.x, y: tower.y, scaleX: 0.3, scaleY: 0.1, alpha: 0.7, tint: 0x4169E1 })); // Animate water squirt tween(waterSquirt, { scaleX: 0.35, alpha: 0.3 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { waterSquirt.destroy(); } }); // Deal damage to enemy enemy.takeDamage(10); // Check if enemy is destroyed if (enemy.health <= 0) { enemy.destroy(); enemies.splice(i, 1); // Give player money for destroying enemy playerCash += 5; cashText.setText('Cash: $' + playerCash); i--; // Adjust index since we removed an enemy break; // Exit tower loop for this enemy } } } } } // Check if tower is a gas tower (Dog asset) else if (tower._assetId === 'Dog') { // Check if enemy is on the same horizontal line as the tower (within 50 pixels tolerance) if (Math.abs(enemy.y - tower.y) < 50) { // Check if enemy is to the right of the tower and within range of 600 pixels if (enemy.x > tower.x && enemy.x - tower.x < 600) { // Initialize fire rate tracking for this tower if (!tower.lastFireTime) { tower.lastFireTime = 0; } // Fire every 45 ticks (0.75 seconds at 60fps) if (LK.ticks - tower.lastFireTime >= 45) { tower.lastFireTime = LK.ticks; // Switch dog asset to dog1 for fart animation tower.destroy(); var fartingDog = game.addChild(LK.getAsset('Dog1', { anchorX: 0.5, anchorY: 0.5, x: tower.x, y: tower.y, alpha: 1 })); // Copy tower properties to the new farting dog fartingDog._assetId = 'Dog'; fartingDog.health = tower.health; fartingDog.maxHealth = tower.maxHealth; fartingDog.isBeingDamaged = tower.isBeingDamaged; fartingDog.lastDamageTime = tower.lastDamageTime; fartingDog.lastFireTime = tower.lastFireTime; fartingDog.healthBarOutline = tower.healthBarOutline; fartingDog.healthBar = tower.healthBar; fartingDog.takeDamage = tower.takeDamage; // Replace tower in towers array for (var towerIndex = 0; towerIndex < towers.length; towerIndex++) { if (towers[towerIndex] === tower) { towers[towerIndex] = fartingDog; break; } } // Create gas cloud visual var gasCloud = game.addChild(LK.getAsset('GasCloud', { anchorX: 0.5, anchorY: 0.5, x: tower.x + 150, // Position gas cloud 100 pixels further left when dog farts y: tower.y, scaleX: 1.5, scaleY: 1.5, alpha: 0.6, tint: 0x90EE90 })); // Animate gas cloud expanding and fading tween(gasCloud, { scaleX: 2.5, scaleY: 2.5, alpha: 0.2 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { gasCloud.destroy(); } }); // Switch back to normal dog after 500ms LK.setTimeout(function () { fartingDog.destroy(); var normalDog = game.addChild(LK.getAsset('Dog', { anchorX: 0.5, anchorY: 0.5, x: fartingDog.x, y: fartingDog.y, alpha: 1 })); // Copy properties back to normal dog normalDog._assetId = 'Dog'; normalDog.health = fartingDog.health; normalDog.maxHealth = fartingDog.maxHealth; normalDog.isBeingDamaged = fartingDog.isBeingDamaged; normalDog.lastDamageTime = fartingDog.lastDamageTime; normalDog.lastFireTime = fartingDog.lastFireTime; normalDog.healthBarOutline = fartingDog.healthBarOutline; normalDog.healthBar = fartingDog.healthBar; normalDog.takeDamage = fartingDog.takeDamage; // Replace in towers array for (var towerIndex = 0; towerIndex < towers.length; towerIndex++) { if (towers[towerIndex] === fartingDog) { towers[towerIndex] = normalDog; break; } } }, 500); // Deal damage to enemy enemy.takeDamage(15); // Check if enemy is destroyed if (enemy.health <= 0) { enemy.destroy(); enemies.splice(i, 1); // Give player money for destroying enemy playerCash += 5; cashText.setText('Cash: $' + playerCash); i--; // Adjust index since we removed an enemy break; // Exit tower loop for this enemy } } } } } } // Check collision with fan blades first (before tower collision) for (var k = 0; k < towers.length; k++) { var tower = towers[k]; // Check if this tower has blades (fan tower) and is running (not in cooldown) if (tower.blades && tower.isRunning && !tower.cooldownActive) { // Initialize blade collision tracking for this enemy-tower pair if (!enemy.collidingBlades) { enemy.collidingBlades = {}; } // Check if enemy intersects with fan blades var enemyWidth = 150; // Half width of probedroid var enemyHeight = 183; // Half height of probedroid var bladeWidth = 75; // Half width of blades var bladeHeight = 75; // Half height of blades var isCollidingWithBlades = Math.abs(enemy.x - tower.blades.x) < (enemyWidth + bladeWidth) / 2 && Math.abs(enemy.y - tower.blades.y) < (enemyHeight + bladeHeight) / 2; // Track blade collision state transitions var wasCollidingWithBlades = enemy.collidingBlades[k] || false; // Handle blade collision start if (!wasCollidingWithBlades && isCollidingWithBlades) { // Collision with blades just started enemy.collidingBlades[k] = true; // Push enemy back 400 pixels to the right var pushbackDistance = 400; var targetX = enemy.x + pushbackDistance; // Make sure enemy doesn't go off screen if (targetX > 2048 - 50) { targetX = 2048 - 50; } // Animate pushback using tween tween(enemy, { x: targetX }, { duration: 500, easing: tween.easeOut }); // Inflict damage to enemy enemy.takeDamage(25); // Flash enemy to show damage LK.effects.flashObject(enemy, 0x0088ff, 300); // Check if enemy is destroyed if (enemy.health <= 0) { enemy.destroy(); enemies.splice(i, 1); // Give player money for destroying enemy playerCash += 5; cashText.setText('Cash: $' + playerCash); i--; // Adjust index since we removed an enemy break; // Exit tower loop for this enemy } } else if (!isCollidingWithBlades && wasCollidingWithBlades) { // Collision with blades just ended enemy.collidingBlades[k] = false; } } } // Check if enemy is colliding with any tower for (var k = 0; k < towers.length; k++) { var tower = towers[k]; // Initialize collision tracking for this enemy-tower pair if (!enemy.collidingTowers) { enemy.collidingTowers = {}; } // Check if enemy intersects with tower (use proper collision detection) var enemyWidth = 150; // Half width of probedroid var enemyHeight = 183; // Half height of probedroid var towerWidth = 100; // Half width of tower var towerHeight = 100; // Half height of tower var isColliding = Math.abs(enemy.x - tower.x) < (enemyWidth + towerWidth) / 2 && Math.abs(enemy.y - tower.y) < (enemyHeight + towerHeight) / 2; // Track collision state transitions var wasColliding = enemy.collidingTowers[k] || false; // Handle collision start if (!wasColliding && isColliding) { // Collision just started enemy.collidingTowers[k] = true; // Stop enemy movement enemy.speed = 0; // Mark tower as being damaged tower.isBeingDamaged = true; tower.lastDamageTime = LK.ticks; // Flash both objects to show collision LK.effects.flashObject(enemy, 0xffff00, 200); LK.effects.flashObject(tower, 0xff0000, 200); } // Handle ongoing collision if (isColliding) { // Deal damage every 30 ticks (0.5 seconds at 60fps) if (tower.isBeingDamaged && LK.ticks - tower.lastDamageTime >= 30) { // Flash tower red to show damage LK.effects.flashObject(tower, 0xff0000, 300); // Deal damage to tower tower.takeDamage(10); tower.lastDamageTime = LK.ticks; // Check if tower is destroyed if (tower.health <= 0) { // Remove health bar components if (tower.healthBarOutline) { tower.healthBarOutline.destroy(); } if (tower.healthBar) { tower.healthBar.destroy(); } // Remove blades if this is a fan tower if (tower.blades) { tower.blades.destroy(); } // Remove tower from the game tower.destroy(); towers.splice(k, 1); k--; // Adjust index since we removed a tower // Resume enemy movement after destroying tower enemy.speed = -2; // Clear collision tracking for this tower delete enemy.collidingTowers[k]; // Flash enemy green to show it can continue LK.effects.flashObject(enemy, 0x00ff00, 500); } } } else { // No longer colliding if (wasColliding) { // Collision just ended enemy.collidingTowers[k] = false; tower.isBeingDamaged = false; // Resume enemy movement if not colliding with any towers var stillColliding = false; for (var key in enemy.collidingTowers) { if (enemy.collidingTowers[key]) { stillColliding = true; break; } } if (!stillColliding) { enemy.speed = -2; } } } } // Update last position for next frame enemy.lastX = enemy.x; } } // Display the title - They Came For Our WiFi // Import tween plugin var titleImage = game.addChild(LK.getAsset('Title', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 1400 })); // Add skip intro button to top of title screen var skipButton = new Text2('SKIP INTRO', { size: 60, fill: 0xFFFFFF }); skipButton.anchor.set(0.5, 0); skipButton.x = 2048 / 2; skipButton.y = 150; game.addChild(skipButton); // Function to skip directly to backdrop scene function skipToBackdrop() { // Stop all tweens tween.stop(titleImage); tween.stop(flybyImage); // Remove title and flyby titleImage.destroy(); flybyImage.destroy(); skipButton.destroy(); // Add backdrop asset to game var backdropAsset = game.addChild(LK.getAsset('backdrop', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 1, scaleX: 0.5, scaleY: 0.5 })); // Add flyby asset to backdrop var backdropFlyby = game.addChild(LK.getAsset('Flyby', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 800, alpha: 1, scaleX: 0.1, scaleY: 0.1 })); // Zoom in flyby to final size tween(backdropFlyby, { scaleX: 0.8, scaleY: 0.8 }, { duration: 2000, easing: tween.easeInOut }); // Store the original Y position for backdrop flyby var backdropFlybyOriginalY = backdropFlyby.y; // Make flyby move off the right side of backdrop scene tween(backdropFlyby, { x: 2048 + 375 }, { duration: 6000, easing: tween.linear, onFinish: function onFinish() { // After flyby has left the backdrop scene, fade in wave1 asset var wave1Asset = game.addChild(LK.getAsset('Wave1', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave1 asset tween(wave1Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Keep wave1 visible for 3 seconds then fade out LK.setTimeout(function () { tween(wave1Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { wave1Asset.destroy(); // Start first wave of tower defense game startTowerDefenseWave1(); } }); }, 3000); } }); } }); // Add 6 horizontal guide lines immediately var lineSpacing = 2732 / 7; for (var i = 1; i <= 6; i++) { var yPosition = lineSpacing * i; if (i === 1) { yPosition += 480 + 50; // Move guideline 1 down by 480 pixels } else if (i === 2) { yPosition += 320 + 50; // Move guideline 2 down by 320 pixels } else if (i === 3) { yPosition += 150 + 50; // Move guideline 3 down by 150 pixels } else if (i === 4) { yPosition += 10 + 50; // Move guideline 4 down by 10 pixels } else if (i === 5) { yPosition -= 150 - 50; // Move guideline 5 up by 150 pixels } else if (i === 6) { yPosition -= 310 - 50; // Move guideline 6 up by 310 pixels } var guideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPosition, alpha: 0.5 })); // Store guideline reference and add click handler guidelines.push(guideLine); guideLine.lineNumber = i; guideLine.down = function (x, y, obj) { if (isPlacingTower && towerPreview) { // Move tower preview to clicked position on guideline // x and y are already in the local coordinate space of the guideline towerPreview.x = x; towerPreview.y = this.y; // Use the guideline's Y position } }; } // Add 8 vertical guidelines with same size as horizontal ones var verticalSpacing = 2048 / 9; // Divide screen width by 9 to get 8 lines with margins for (var j = 1; j <= 8; j++) { var xPosition = verticalSpacing * j; var rotationAngle = Math.PI / 2; // Default 90 degrees for vertical if (j === 1) { xPosition += 0; // Move vertical line 1 right 150 pixels rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 1 } else if (j === 2) { xPosition += 5; // Move vertical line 2 right 5 pixels (was 30, now +5 = -25 total) rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 2 } else if (j === 3) { xPosition += 20; // Move vertical line 3 right 20 pixels rotationAngle = Math.PI / 2 + 5 * Math.PI / 180; // Add 5 degrees to vertical line 3 } else if (j === 6) { rotationAngle = Math.PI / 2 - 5 * Math.PI / 180; // Subtract 5 degrees from vertical line 6 } else if (j === 7) { xPosition += 120; // Move vertical line 7 right 120 pixels } else if (j === 8) { xPosition += 150; // Move vertical line 8 right 150 pixels } var verticalGuideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: xPosition, y: 2732 / 2, alpha: 0.5, rotation: rotationAngle })); } } // Add touch event to skip button skipButton.down = function (x, y, obj) { skipToBackdrop(); }; // Add flyby asset to title - start at right side of screen var flybyImage = game.addChild(LK.getAsset('Flyby', { anchorX: 0.5, anchorY: 0.5, x: 2048 + 375, y: 2732 / 2 + 1400 - 500 })); // Store the original Y position for flyby var flybyOriginalY = flybyImage.y; // Create hover animation function function startFlybyHover() { // Tween up 50 pixels over 2 seconds tween(flybyImage, { y: flybyOriginalY - 50 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Tween down 50 pixels over 2 seconds tween(flybyImage, { y: flybyOriginalY + 50 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Start the cycle again startFlybyHover(); } }); } }); } // Start the hover animation startFlybyHover(); // Start flyby movement from right to left tween(flybyImage, { x: -375 }, { duration: 8000, easing: tween.linear, onFinish: function onFinish() { // After flyby has left the screen, slowly scroll title up tween(titleImage, { y: titleImage.y - titleImage.height }, { duration: 20000, easing: tween.easeOut }); // Stop the title scrolling after 5 seconds LK.setTimeout(function () { tween.stop(titleImage, { y: true }); // Fade in intro asset in the middle of the screen var introAsset = game.addChild(LK.getAsset('intro', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Tween alpha from 0 to 1 for fade-in effect tween(introAsset, { alpha: 1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // After intro has faded in, make flyby move from left to right flybyImage.x = -375; // Reset flyby to left side flybyImage.y = 2732 / 2; // Center vertically tween(flybyImage, { x: 2048 + 375 }, { duration: 6000, easing: tween.linear, onFinish: function onFinish() { // After flyby has left the screen, fade out intro and fade in backdrop tween(introAsset, { alpha: 0 }, { duration: 2000, easing: tween.easeInOut }); // Add backdrop asset to game var backdropAsset = game.addChild(LK.getAsset('backdrop', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0, scaleX: 0.5, scaleY: 0.5 })); // Add flyby asset to backdrop var backdropFlyby = game.addChild(LK.getAsset('Flyby', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 800, alpha: 1, scaleX: 0.1, scaleY: 0.1 })); // Store the original Y position for backdrop flyby var backdropFlybyOriginalY = backdropFlyby.y; // Make flyby move off the right side of backdrop scene function startBackdropFlybyHover() { tween(backdropFlyby, { x: 2048 + 375 }, { duration: 6000, easing: tween.linear, onFinish: function onFinish() { // After flyby has left the backdrop scene, fade in wave1 asset var wave1Asset = game.addChild(LK.getAsset('Wave1', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave1 asset tween(wave1Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Keep wave1 visible for 3 seconds then fade out LK.setTimeout(function () { tween(wave1Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { wave1Asset.destroy(); // Start first wave of tower defense game startTowerDefenseWave1(); } }); }, 3000); } }); } }); } // Fade in backdrop tween(backdropAsset, { alpha: 1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Zoom in backdrop flyby tween(backdropFlyby, { scaleX: 0.8, scaleY: 0.8 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Start flyby movement to right side after zoom in startBackdropFlybyHover(); } }); // Add 6 horizontal guide lines after backdrop fades in var lineSpacing = 2732 / 7; // Divide screen height by 7 to get 6 lines with margins for (var i = 1; i <= 6; i++) { var yPosition = lineSpacing * i; if (i === 1) { yPosition += 480 + 50; // Move guideline 1 down by 480 pixels } else if (i === 2) { yPosition += 320 + 50; // Move guideline 2 down by 320 pixels } else if (i === 3) { yPosition += 150 + 50; // Move guideline 3 down by 150 pixels } else if (i === 4) { yPosition += 10 + 50; // Move guideline 4 down by 10 pixels } else if (i === 5) { yPosition -= 150 - 50; // Move guideline 5 up by 150 pixels } else if (i === 6) { yPosition -= 310 - 50; // Move guideline 6 up by 310 pixels } var guideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPosition, alpha: 0.5 })); } // Add 8 vertical guidelines with same size as horizontal ones var verticalSpacing = 2048 / 9; // Divide screen width by 9 to get 8 lines with margins for (var j = 1; j <= 8; j++) { var xPosition = verticalSpacing * j; var rotationAngle = Math.PI / 2; // Default 90 degrees for vertical if (j === 1) { xPosition += 0; // Move vertical line 1 right 150 pixels rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 1 } else if (j === 2) { xPosition += 5; // Move vertical line 2 right 5 pixels (was 30, now +5 = -25 total) rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 2 } else if (j === 3) { xPosition += 20; // Move vertical line 3 right 20 pixels rotationAngle = Math.PI / 2 + 5 * Math.PI / 180; // Add 5 degrees to vertical line 3 } else if (j === 6) { rotationAngle = Math.PI / 2 - 5 * Math.PI / 180; // Subtract 5 degrees from vertical line 6 } else if (j === 7) { xPosition += 120; // Move vertical line 7 right 120 pixels } else if (j === 8) { xPosition += 150; // Move vertical line 8 right 150 pixels } var verticalGuideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: xPosition, y: 2732 / 2, alpha: 0.5, rotation: rotationAngle })); } } }); } }); } }); }, 5000); } }); ;
===================================================================
--- original.js
+++ change.js
@@ -1735,8 +1735,10 @@
rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 2
} else if (j === 3) {
xPosition += 20; // Move vertical line 3 right 20 pixels
rotationAngle = Math.PI / 2 + 5 * Math.PI / 180; // Add 5 degrees to vertical line 3
+ } else if (j === 6) {
+ rotationAngle = Math.PI / 2 - 5 * Math.PI / 180; // Subtract 5 degrees from vertical line 6
} else if (j === 7) {
xPosition += 120; // Move vertical line 7 right 120 pixels
} else if (j === 8) {
xPosition += 150; // Move vertical line 8 right 150 pixels
@@ -1960,8 +1962,10 @@
rotationAngle = Math.PI / 2 + 7 * Math.PI / 180; // Add 7 degrees to vertical line 2
} else if (j === 3) {
xPosition += 20; // Move vertical line 3 right 20 pixels
rotationAngle = Math.PI / 2 + 5 * Math.PI / 180; // Add 5 degrees to vertical line 3
+ } else if (j === 6) {
+ rotationAngle = Math.PI / 2 - 5 * Math.PI / 180; // Subtract 5 degrees from vertical line 6
} else if (j === 7) {
xPosition += 120; // Move vertical line 7 right 120 pixels
} else if (j === 8) {
xPosition += 150; // Move vertical line 8 right 150 pixels
White circle with two eyes, seen from above.. In-Game asset. 2d. High contrast. No shadows
White simple circular enemy seen from above, black outline. Black eyes, with a single shield in-font of it. Black and white only. Blue background.
White circle with black outline. Blue background.. In-Game asset. 2d. High contrast. No shadows
Fire hydrant. In-Game asset. 2d. High contrast. No shadows
Water spraying forward In-Game asset. 2d. High contrast. No shadows
Fan blades symmetrical. In-Game asset. 2d. High contrast. No shadows
Plasma ball. In-Game asset. 2d. High contrast. No shadows
Make picture transparent
Bug zapper on a pole. In-Game asset. 2d. High contrast. No shadows
Probe droid. In-Game asset. 2d. High contrast. No shadows
Space drone. In-Game asset. 2d. High contrast. No shadows
Remove propellers and make them symmetrical
Add more rows to gris
Make this picture with more night sky above the city skyline
Change text to say wave 1
Make button grey and say ??????
Make it say Wave 2
Make it say wave 3
Make it say wave 4
WiFi symbol. In-Game asset. 2d. High contrast. No shadows
explosion effect In-Game asset. 2d. High contrast. No shadows
Make it say wave 5
Remove laser beam
Make button hot pink and say 'Reflect $20'
Make button blue and change text to say 'Water $10' in a retro style font
Make button green and change test to say 'Gas $20'
Make button orange and change test to say 'Fire $40'
Make button very light blue and change test to say 'Air $30'
Make button gold and change text to say 'Electric $50'
Make button purple and change test to say 'Plasma $60'
Make button Teal and change test to say 'Slingshot $100'
Make button silver and change test to say 'WiFi $150'
Remove little kick so it's just a smooth oval shape
Make grid 6x8
Hand should be holding the gun by the Handle
Place laser cannon in both hands holding it like a shotgun
Make it stand still
Remove the words 5g
Make sure spelling in speech bubble is correct "We have found the earthlings weakness"
Fix the spelling of the word Planet
Slingshot. In-Game asset. 2d. High contrast. No shadows
Red button with a 'X' on it. In-Game asset. 2d. High contrast. No shadows
Green button with a tick on it
Fix the spelling of word saw
Display icon that says score sci fi comic style font. In-Game asset. 2d. High contrast. No shadows
Display icon that says cash sci fi comic style font. In-Game asset. 2d. High contrast. No shadows
Display icon that says X2 speed sci fi comic style font. In-Game asset. 2d. High contrast. No shadows
Make it say x1 speed and make the x1 blue
Canvasser
Sound effect
Alien1
Sound effect
Alien2
Sound effect
Alien3
Sound effect
Intro
Music
Probedroid
Sound effect
Probedroid2
Sound effect
Towerselect
Sound effect
Water
Sound effect
Explosion
Sound effect
Confirm
Sound effect
Fart
Sound effect
Electric
Sound effect
Fireball
Sound effect