User prompt
When tower buttons a pressed play towerselect sound
User prompt
Fire tower will have a range of 800 straight ahead right and left fire tower bullets will be orange ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make blades on air tower rotate and when enemy gets within range of 200 right straight ahead it will blow enemy back 500 inflicting a small amount of damage ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add firework asset to screen by clicking fire button and dragging it into position then click a green tick to confirm position. Remove $40 from cash when positioned use firework asset as actual tower ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add fan asset to screen by clicking air button and dragging it into position then click a green tick to confirm position. Remove $30 from cash when positioned use fan and blade asset together as actual tower ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Play water sound when water tower shoots
User prompt
When wave1-5 fade in and out , make sure they are rendered shown visibly in front of tower and enemy assets ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Render wave1-5 assets in front of towers and enemies
User prompt
Play fart sound when dog tower shoots
User prompt
Move tower health bar down 50
User prompt
Please fix the bug: 'Uncaught TypeError: newTower.setAssetType is not a function' in or related to this line: 'newTower.setAssetType('Dog');' Line Number: 1575
User prompt
Add dog1 assets in same position as dog asset and swap visibility when firing ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Gas tower bullet should be green ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Gas tower range will be 600 straight ahead to the right
User prompt
add dog asset to screen by clicking gas button and dragging it into position then click a green tick to confirm position. Remove $20 from cash when positioned use dog asset as actual tower ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Towers and enemies below should be rendered in front of towers and enemies above
User prompt
Tower1 is water tower, make water tower projectile blue ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make UFO boss have 1000 health
User prompt
Make robots stronger than SpaceDrones
User prompt
Make SpaceDrones stronger than drones
User prompt
Make drones stronger than probedroids
User prompt
Make probedroids slightly stronger
User prompt
Add health bar to all enemies from different waves
User prompt
Add health bar to tower If enemy runs into tower tower will take damage ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Show health bar on enemies
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Cutscene class var Cutscene = Container.expand(function () { var self = Container.call(this); // Properties self.scenes = []; self.currentSceneIndex = 0; self.isPlaying = false; // Add a scene to the cutscene self.addScene = function (sceneData) { self.scenes.push(sceneData); }; // Start playing the cutscene self.play = function () { if (self.scenes.length === 0) return; self.isPlaying = true; self.currentSceneIndex = 0; self.playCurrentScene(); }; // Play the current scene self.playCurrentScene = function () { if (self.currentSceneIndex >= self.scenes.length) { self.finish(); return; } var scene = self.scenes[self.currentSceneIndex]; if (scene.onStart) { scene.onStart(); } // Auto-advance to next scene after duration if (scene.duration) { LK.setTimeout(function () { self.nextScene(); }, scene.duration); } }; // Move to next scene self.nextScene = function () { var scene = self.scenes[self.currentSceneIndex]; if (scene.onEnd) { scene.onEnd(); } self.currentSceneIndex++; self.playCurrentScene(); }; // Skip to specific scene self.skipToScene = function (index) { if (index >= 0 && index < self.scenes.length) { self.currentSceneIndex = index; self.playCurrentScene(); } }; // Finish cutscene self.finish = function () { self.isPlaying = false; if (self.onFinish) { self.onFinish(); } }; // Stop cutscene self.stop = function () { self.isPlaying = false; // Stop any running tweens or timeouts tween.stopAll(); }; 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 for tower defense var Enemy = Container.expand(function () { var self = Container.call(this); // Default to Probedroid, but can be changed self.assetType = 'Probedroid'; var enemyGraphics = self.attachAsset(self.assetType, { anchorX: 0.5, anchorY: 0.5 }); // Enemy properties self.health = 100; self.maxHealth = 100; self.speed = 2; self.targetX = -100; // Move to left side of screen self.lastX = self.x; // Health bar graphics self.healthBarBackground = self.attachAsset('healthBarBackground', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -40 }); self.healthBarForeground = self.attachAsset('healthBarForeground', { anchorX: 0, anchorY: 0.5, x: -30, y: -40 }); self.update = function () { // Store last position for collision detection self.lastX = self.x; // Move towards target (right to left) if (self.x > self.targetX) { self.x -= self.speed; } // Move towards the center of the assigned guideline if (self.baseY !== undefined) { var targetY = self.baseY; var yDifference = targetY - self.y; // Move towards guideline center with a fraction of movement speed if (Math.abs(yDifference) > 2) { self.y += yDifference * 0.1; // Adjust 0.1 to control how quickly enemies center on guidelines } } // Update health bar var healthPercentage = self.health / self.maxHealth; self.healthBarForeground.scaleX = healthPercentage; // Change health bar color based on health percentage if (healthPercentage > 0.6) { self.healthBarForeground.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { self.healthBarForeground.tint = 0xffff00; // Yellow } else { self.healthBarForeground.tint = 0xff0000; // Red } // Check if enemy reached the end if (self.lastX > 0 && self.x <= 0) { // Enemy reached the end - remove from game if (self.parent) { self.destroy(); // Remove from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } } } }; // Method to defeat this enemy self.defeat = function () { if (self.parent) { enemiesDefeated++; self.destroy(); // Remove from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } } }; self.setAssetType = function (assetType) { if (enemyGraphics && enemyGraphics.parent) { enemyGraphics.destroy(); } self.assetType = assetType; enemyGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); }; return self; }); // Tower class for tower defense var Tower = Container.expand(function () { var self = Container.call(this); // Tower properties self.towerType = 'basic'; self.level = 1; self.damage = 25; self.range = 300; self.fireRate = 60; // Frames between shots (60 = 1 second at 60fps) self.cost = 100; self.upgradeCost = 150; self.lastShotFrame = 0; self.target = null; self.rangeCircle = null; self.showingRange = false; // Tower1 specific properties self.tower1Range = 500; // Tower1 has 500 range straight ahead self.isTower1 = false; // Flag to identify Tower1 instances // Tower health properties self.health = 100; self.maxHealth = 100; self.lastCollidingEnemies = []; // Track which enemies were colliding last frame // Guideline tracking for same-line targeting self.guidelineIndex = -1; // Which guideline this tower is on // Create tower graphics var towerGraphics = self.attachAsset('tower', { anchorX: 0.5, anchorY: 0.5 }); // Create level indicator var levelIndicator = self.attachAsset('towerLevelIndicator', { anchorX: 0.5, anchorY: 0.5, x: 30, y: -30 }); // Method to show/hide range circle self.showRange = function () { if (!self.rangeCircle) { self.rangeCircle = self.addChild(LK.getAsset('rangeCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: self.range / 500, scaleY: self.range / 500, alpha: 0.3 })); } self.rangeCircle.alpha = 0.3; self.showingRange = true; }; self.hideRange = function () { if (self.rangeCircle) { self.rangeCircle.alpha = 0; } self.showingRange = false; }; // Method to find nearest enemy in range self.findTarget = function () { var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Only target enemies on the same guideline if (enemy.guidelineIndex !== self.guidelineIndex) { continue; // Skip enemies not on same line } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // For Tower1, target enemies 500 pixels both left and right if (self.isTower1) { // Check if enemy is within 500 range horizontally (both left and right) if (Math.abs(dx) <= self.tower1Range && Math.abs(dy) <= 50) { var straightDistance = Math.abs(dx); // Distance horizontally if (straightDistance < nearestDistance) { nearestDistance = straightDistance; nearestEnemy = enemy; } } } else { // Regular circular range for other towers if (distance <= self.range && distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } } return nearestEnemy; }; // Method to shoot at target self.shoot = function (target) { if (!target || !target.parent) return; // Create bullet/projectile effect var bullet = game.addChild(LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y })); // Calculate direction to target var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Animate bullet to target tween(bullet, { x: target.x, y: target.y }, { duration: distance / 2, // Speed based on distance easing: tween.linear, onFinish: function onFinish() { bullet.destroy(); // Deal damage to target if (target && target.parent) { target.health -= self.damage; if (target.health <= 0) { target.defeat(); playerScore += 10; playerCash += 25; } } } }); // Play shoot sound LK.getSound('Confirm').play(); }; // Method to upgrade tower self.upgrade = function () { if (playerCash >= self.upgradeCost && self.level < 3) { playerCash -= self.upgradeCost; self.level++; self.damage += 15; self.range += 50; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); // Update level indicator levelIndicator.destroy(); levelIndicator = self.attachAsset('towerLevelIndicator', { anchorX: 0.5, anchorY: 0.5, x: 30, y: -30, scaleX: self.level, scaleY: self.level }); // Update range circle if showing if (self.showingRange && self.rangeCircle) { self.rangeCircle.scaleX = self.range / 500; self.rangeCircle.scaleY = self.range / 500; } // Play upgrade sound LK.getSound('Towerselect').play(); return true; } return false; }; // Click handler for tower interaction self.down = function (x, y, obj) { if (self.showingRange) { self.hideRange(); } else { self.showRange(); } }; self.update = function () { // Only operate when wave is active if (!waveActive) return; // Check for enemy collisions and reduce tower health var currentCollidingEnemies = []; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Only collide with enemies on the same guideline if (enemy.guidelineIndex === self.guidelineIndex && self.intersects(enemy)) { currentCollidingEnemies.push(enemy); // Check if this enemy just started colliding (wasn't colliding last frame) var wasCollidingBefore = false; for (var j = 0; j < self.lastCollidingEnemies.length; j++) { if (self.lastCollidingEnemies[j] === enemy) { wasCollidingBefore = true; break; } } // If enemy just started colliding, reduce tower health if (!wasCollidingBefore) { self.health -= 10; // Reduce health by 10 per collision // Flash tower red to show damage tween(towerGraphics, { tint: 0xFF0000 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Check if tower is destroyed if (self.health <= 0) { // Remove tower from towers array for (var k = towers.length - 1; k >= 0; k--) { if (towers[k] === self) { towers.splice(k, 1); break; } } // Destroy tower self.destroy(); return; } } } } // Update last colliding enemies for next frame self.lastCollidingEnemies = currentCollidingEnemies; // Find target if we don't have one or current target is invalid if (!self.target || !self.target.parent) { self.target = self.findTarget(); } // Shoot at target if in range and fire rate allows if (self.target && self.target.parent) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Check if target is still in range if (distance <= self.range) { // Check if enough time has passed since last shot if (LK.ticks - self.lastShotFrame >= self.fireRate) { self.shoot(self.target); self.lastShotFrame = LK.ticks; } } else { // Target moved out of range self.target = null; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 //Init game with black background }); /**** * Game Code ****/ // Tower Defense Game Variables var enemies = []; var towers = []; var waveActive = false; var enemySpawnTimer = 0; var enemySpawnInterval = 420; // Spawn every 7 seconds at 60fps var enemiesSpawned = 0; var maxEnemiesInWave = 10; var guidelineYPositions = []; var firstEnemySpawned = false; var currentWave = 1; var enemiesDefeated = 0; var playerScore = 0; var playerLives = 10; var playerCash = 200; var scoreDisplay = null; var livesDisplay = null; var cashDisplay = null; var placingTower = false; var towerPreview = null; var confirmButton = null; var pendingTowerCost = 10; var verticalGuidelines = []; var snapPositions = []; // Create intro cutscene using intro2 asset var introCutscene = new Cutscene(); // Add intro2 scene introCutscene.addScene({ onStart: function onStart() { // Create intro2 asset var intro2Asset = game.addChild(LK.getAsset('Intro2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Create cell asset in middle of intro2 var cellAsset = game.addChild(LK.getAsset('cell', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Store references for cleanup introCutscene.intro2Asset = intro2Asset; introCutscene.cellAsset = cellAsset; // Fade in intro2 tween(intro2Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Fade in cell asset tween(cellAsset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add skip intro button var skipIntroButton = new Text2('SKIP INTRO', { size: 60, fill: 0xFFFFFF }); skipIntroButton.anchor.set(0.5, 0); skipIntroButton.x = 2048 / 2; skipIntroButton.y = 200; skipIntroButton.alpha = 0; game.addChild(skipIntroButton); // Store reference for cleanup introCutscene.skipIntroButton = skipIntroButton; // Fade in skip button tween(skipIntroButton, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add click event handler to skip button skipIntroButton.down = function (x, y, obj) { // Play intro music LK.playMusic('Intro', { loop: false }); // Clean up intro2 assets tween.stop(intro2Asset); tween.stop(cellAsset); tween.stop(skipIntroButton); intro2Asset.destroy(); cellAsset.destroy(); skipIntroButton.destroy(); // Skip directly to title screen showTitleScreen(); }; // Add click event handler to cell asset cellAsset.down = function (x, y, obj) { // Play intro music LK.playMusic('Intro', { loop: false }); // Transition to story1 scene var story1Asset = game.addChild(LK.getAsset('Story1', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade out current assets tween(intro2Asset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut }); tween(cellAsset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut }); // Fade in story1 asset tween(story1Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add click event handler to story1 asset to transition to story2 story1Asset.down = function (x, y, obj) { // Create story2 asset var story2Asset = game.addChild(LK.getAsset('Story2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade out story1 asset tween(story1Asset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { story1Asset.destroy(); } }); // Fade in story2 asset tween(story2Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add click event handler to story2 asset to transition to story3 story2Asset.down = function (x, y, obj) { // Create story3 asset var story3Asset = game.addChild(LK.getAsset('Story3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade out story2 asset tween(story2Asset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { story2Asset.destroy(); } }); // Fade in story3 asset tween(story3Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add click event handler to story3 asset to transition to story4 story3Asset.down = function (x, y, obj) { // Create story4 asset var story4Asset = game.addChild(LK.getAsset('Story4', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade out story3 asset tween(story3Asset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { story3Asset.destroy(); } }); // Fade in story4 asset tween(story4Asset, { alpha: 1 }, { duration: 1000, easing: tween.easeInOut }); // Add click event handler to story4 asset to transition to titlescreen story4Asset.down = function (x, y, obj) { // Fade out story4 asset tween(story4Asset, { alpha: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { story4Asset.destroy(); // Show title screen showTitleScreen(); } }); }; }; }; }; }; } }); // Set what happens when cutscene finishes introCutscene.onFinish = function () { // Cutscene finished - no automatic transition }; // Function to show title screen function showTitleScreen() { // Display the title // 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.2, scaleY: 0.2 })); // Zoom flyby to final size tween(backdropFlyby, { scaleX: 0.8, scaleY: 0.8 }, { duration: 1000, 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 2 seconds then fade out LK.setTimeout(function () { tween(wave1Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { wave1Asset.destroy(); // Start first tower defense wave startWave1(); } }); }, 2000); } }); } }); // 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 += 560; // Move guideline 1 down by 560 pixels (was 575) } else if (i === 2) { yPosition += 395; // Move guideline 2 down by 395 pixels (was 420) } else if (i === 3) { yPosition += 225; // Move guideline 3 down by 225 pixels (was 250) } else if (i === 4) { yPosition += 95; // Move guideline 4 down by 95 pixels (was 120) } else if (i === 5) { yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50) } else if (i === 6) { yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200) } var guideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPosition, alpha: 0.5 })); } } // 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: 0, scaleX: 0.2, scaleY: 0.2 })); // 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 2 seconds then fade out LK.setTimeout(function () { tween(wave1Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { wave1Asset.destroy(); // Start first tower defense wave startWave1(); } }); }, 2000); } }); } }); } // Fade in backdrop tween(backdropAsset, { alpha: 1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Fade in backdrop flyby and zoom to position tween(backdropFlyby, { alpha: 1, scaleX: 0.8, scaleY: 0.8 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Start flyby movement to right side after fade 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 += 560; // Move guideline 1 down by 560 pixels (was 575) } else if (i === 2) { yPosition += 395; // Move guideline 2 down by 395 pixels (was 420) } else if (i === 3) { yPosition += 225; // Move guideline 3 down by 225 pixels (was 250) } else if (i === 4) { yPosition += 95; // Move guideline 4 down by 95 pixels (was 120) } else if (i === 5) { yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50) } else if (i === 6) { yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200) } var guideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPosition, alpha: 0.5 })); } } }); } }); } }); }, 5000); } }); } // Calculate guideline Y positions for enemy spawning function calculateGuidelinePositions() { var lineSpacing = 2732 / 7; guidelineYPositions = []; for (var i = 1; i <= 6; i++) { var yPosition = lineSpacing * i; if (i === 1) { yPosition += 560; // Move guideline 1 down by 560 pixels (was 575) } else if (i === 2) { yPosition += 395; // Move guideline 2 down by 395 pixels (was 420) } else if (i === 3) { yPosition += 225; // Move guideline 3 down by 225 pixels (was 250) } else if (i === 4) { yPosition += 95; // Move guideline 4 down by 95 pixels (was 120) } else if (i === 5) { yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50) } else if (i === 6) { yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200) } guidelineYPositions.push(yPosition); } } // Calculate snap positions from guideline intersections function calculateSnapPositions() { snapPositions = []; // Create vertical guideline positions (8 columns across screen width) var verticalSpacing = 2048 / 9; var verticalXPositions = []; for (var i = 1; i <= 8; i++) { var xPosition = verticalSpacing * i; verticalXPositions.push(xPosition); } // Create snap positions at intersections of horizontal and vertical guidelines for (var h = 0; h < guidelineYPositions.length; h++) { for (var v = 0; v < verticalXPositions.length; v++) { snapPositions.push({ x: verticalXPositions[v], y: guidelineYPositions[h] }); } } } // Find nearest snap position to given coordinates function findNearestSnapPosition(x, y) { var nearestPosition = { x: x, y: y }; var nearestDistance = Infinity; for (var i = 0; i < snapPositions.length; i++) { var snap = snapPositions[i]; var dx = snap.x - x; var dy = snap.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestPosition = snap; } } return nearestPosition; } // Show vertical guidelines during tower placement function showVerticalGuidelines() { hideVerticalGuidelines(); // Clear any existing guidelines var verticalSpacing = 2048 / 9; for (var i = 1; i <= 8; i++) { var xPosition = verticalSpacing * i; var guideLine = game.addChild(LK.getAsset('verticalGuideLine', { anchorX: 0.5, anchorY: 0.5, x: xPosition, y: 2732 / 2, alpha: 0.3 })); verticalGuidelines.push(guideLine); } } // Hide vertical guidelines function hideVerticalGuidelines() { for (var i = 0; i < verticalGuidelines.length; i++) { verticalGuidelines[i].destroy(); } verticalGuidelines = []; } // Start first wave of tower defense function startWave1() { calculateGuidelinePositions(); waveActive = true; enemySpawnTimer = 0; enemiesSpawned = 0; currentWave = 1; enemiesDefeated = 0; // Add score display at top left var scoreDisplay = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreDisplay.anchor.set(0, 0); scoreDisplay.x = 400; scoreDisplay.y = 50; LK.gui.addChild(scoreDisplay); // Add lives display at top center var livesDisplay = new Text2('Lives: 10', { size: 60, fill: 0xFFFFFF }); livesDisplay.anchor.set(0.5, 0); livesDisplay.x = 1024; livesDisplay.y = 50; LK.gui.addChild(livesDisplay); // Add cash display under lives display cashDisplay = new Text2('Cash: $200', { size: 60, fill: 0xFFFFFF }); cashDisplay.anchor.set(0.5, 0); cashDisplay.x = 1024; cashDisplay.y = 120; LK.gui.addChild(cashDisplay); // Add skip wave button under score display var skipWaveButton = new Text2('SKIP WAVE', { size: 40, fill: 0xFFFF00 }); skipWaveButton.anchor.set(0, 0); skipWaveButton.x = 400; skipWaveButton.y = 120; LK.gui.addChild(skipWaveButton); // Add global click handler to cancel tower placement game.down = function (x, y, obj) { // Cancel tower placement if clicking on empty space if (placingTower && obj === game) { if (towerPreview) { towerPreview.destroy(); towerPreview = null; } if (confirmButton) { confirmButton.destroy(); confirmButton = null; } hideVerticalGuidelines(); placingTower = false; } }; // Add tower purchase buttons at bottom of screen var towerButtonY = 2400; // Position near bottom of screen var buttonSpacing = 50; // 50 pixel spacing between buttons var startX = 430; // Water Tower Button var waterTowerButton = game.addChild(LK.getAsset('Waterbutton', { anchorX: 0.5, anchorY: 0.5, x: startX, y: towerButtonY, scaleX: 0.8, scaleY: 0.8 })); // Gas Tower Button var gasTowerButton = game.addChild(LK.getAsset('Gasbutton', { anchorX: 0.5, anchorY: 0.5, x: startX + waterTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY, scaleX: 0.8, scaleY: 0.8 })); // Basic Tower Button var basicTowerButton = game.addChild(LK.getAsset('Firebutton', { anchorX: 0.5, anchorY: 0.5, x: startX + waterTowerButton.width * 0.8 + buttonSpacing + gasTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY, scaleX: 0.8, scaleY: 0.8 })); // Electric Tower Button var electricTowerButton = game.addChild(LK.getAsset('Electricbutton', { anchorX: 0.5, anchorY: 0.5, x: startX, y: towerButtonY + 150 + buttonSpacing, scaleX: 0.8, scaleY: 0.8 })); // Advanced Tower Button var advancedTowerButton = game.addChild(LK.getAsset('Plasmabutton', { anchorX: 0.5, anchorY: 0.5, x: startX + electricTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY + 150 + buttonSpacing, scaleX: 0.8, scaleY: 0.8 })); // Slingshot Tower Button var slingshotTowerButton = game.addChild(LK.getAsset('Slingshotbutton', { anchorX: 0.5, anchorY: 0.5, x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY + 150 + buttonSpacing, scaleX: 0.8, scaleY: 0.8 })); // Air Tower Button (above WiFi button) var airTowerButton = game.addChild(LK.getAsset('Airbutton', { anchorX: 0.5, anchorY: 0.5, x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing + slingshotTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY + 150 + buttonSpacing - 150 - buttonSpacing, scaleX: 0.8, scaleY: 0.8 })); // WiFi Tower Button var wifiTowerButton = game.addChild(LK.getAsset('Wifibutton', { anchorX: 0.5, anchorY: 0.5, x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing + slingshotTowerButton.width * 0.8 + buttonSpacing, y: towerButtonY + 150 + buttonSpacing, scaleX: 0.8, scaleY: 0.8 })); // Add click handlers for tower buttons basicTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for basic tower }; advancedTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for plasma tower }; electricTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for electric tower }; waterTowerButton.down = function (x, y, obj) { if (playerCash >= pendingTowerCost && !placingTower) { LK.getSound('Towerselect').play(); // Start tower placement mode placingTower = true; // Calculate snap positions and show guidelines calculateSnapPositions(); showVerticalGuidelines(); // Find initial snap position var snapPos = findNearestSnapPosition(x, y); // Create tower preview using Tower1 asset towerPreview = game.addChild(LK.getAsset('Tower1', { anchorX: 0.5, anchorY: 0.5, x: snapPos.x, y: snapPos.y, alpha: 0.7 })); // Create green tick confirmation button confirmButton = game.addChild(LK.getAsset('squareLight', { anchorX: 0.5, anchorY: 0.5, x: snapPos.x + 60, y: snapPos.y - 60, scaleX: 1.5, scaleY: 1.5 })); // Add click handler to confirm button confirmButton.down = function (cx, cy, cobj) { if (placingTower && towerPreview) { // Deduct cash playerCash -= pendingTowerCost; if (cashDisplay) { cashDisplay.setText('Cash: $' + playerCash); } // Create actual tower at preview position using Tower1 asset var newTower = new Tower(); var towerGraphics = newTower.attachAsset('Tower1', { anchorX: 0.5, anchorY: 0.5 }); newTower.x = towerPreview.x; newTower.y = towerPreview.y; newTower.cost = pendingTowerCost; newTower.isTower1 = true; // Mark as Tower1 newTower.range = newTower.tower1Range; // Set range to 500 // Assign tower to nearest guideline var nearestGuidelineIndex = 0; var nearestDistance = Infinity; for (var g = 0; g < guidelineYPositions.length; g++) { var distance = Math.abs(newTower.y - guidelineYPositions[g]); if (distance < nearestDistance) { nearestDistance = distance; nearestGuidelineIndex = g; } } newTower.guidelineIndex = nearestGuidelineIndex; game.addChild(newTower); towers.push(newTower); // Clean up placement mode towerPreview.destroy(); confirmButton.destroy(); towerPreview = null; confirmButton = null; hideVerticalGuidelines(); placingTower = false; // Play confirmation sound LK.getSound('Confirm').play(); } }; } }; gasTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for gas tower }; wifiTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for wifi tower }; slingshotTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for slingshot tower }; airTowerButton.down = function (x, y, obj) { LK.getSound('Towerselect').play(); // TODO: Start tower placement mode for air tower }; // Add click handler to skip wave button skipWaveButton.down = function (x, y, obj) { // Force wave completion by clearing all enemies and setting appropriate flags for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); enemies.splice(i, 1); } enemiesSpawned = maxEnemiesInWave; enemiesDefeated = maxEnemiesInWave; // Check which wave we're skipping and trigger appropriate transition if (currentWave === 1) { // Show wave2 asset with fade in/out var wave2Asset = game.addChild(LK.getAsset('Wave2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave2 asset tween(wave2Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave2 asset tween(wave2Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave2Asset.destroy(); // Start wave2 startWave2(); } }); } }); } else if (currentWave === 2) { // Show wave3 asset with fade in/out var wave3Asset = game.addChild(LK.getAsset('Wave3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave3 asset tween(wave3Asset, { alpha: 1 }, { duration: 750, easing: tween.easeInOut, onFinish: function onFinish() { // Keep wave3 visible for 1.5 seconds then fade out LK.setTimeout(function () { tween(wave3Asset, { alpha: 0 }, { duration: 750, easing: tween.easeInOut, onFinish: function onFinish() { wave3Asset.destroy(); // Start wave3 startWave3(); } }); }, 1500); } }); } else if (currentWave === 3) { // Show wave4 asset with fade in/out var wave4Asset = game.addChild(LK.getAsset('Wave4', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave4 asset tween(wave4Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave4 asset tween(wave4Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave4Asset.destroy(); // Start wave4 startWave4(); } }); } }); } else if (currentWave === 4) { // Show wave5 asset with fade in/out var wave5Asset = game.addChild(LK.getAsset('Wave5', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave5 asset tween(wave5Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave5 asset tween(wave5Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave5Asset.destroy(); // Start wave5 startWave5(); } }); } }); } else if (currentWave === 5) { // UFO boss defeated - transition to story5 cutscene var story5Asset = game.addChild(LK.getAsset('Story5', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in story5 asset tween(story5Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Add click handler to story5 to transition to level2 story5Asset.down = function (x, y, obj) { // Fade out story5 asset tween(story5Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { story5Asset.destroy(); // Start level2 with backdrop2 startLevel2(); } }); }; } }); } else { waveActive = false; } }; } // Start second wave of tower defense function startWave2() { calculateGuidelinePositions(); waveActive = true; enemySpawnTimer = 0; enemiesSpawned = 0; maxEnemiesInWave = 20; enemySpawnInterval = 300; // Spawn every 5 seconds at 60fps currentWave = 2; } // Start third wave of tower defense function startWave3() { calculateGuidelinePositions(); waveActive = true; enemySpawnTimer = 0; enemiesSpawned = 0; maxEnemiesInWave = 30; enemySpawnInterval = 300; // Spawn every 5 seconds at 60fps (300 frames = 5 seconds at 60fps) currentWave = 3; } // Start fourth wave of tower defense function startWave4() { calculateGuidelinePositions(); waveActive = true; enemySpawnTimer = 0; enemiesSpawned = 0; maxEnemiesInWave = 40; enemySpawnInterval = 180; // Spawn every 3 seconds at 60fps (180 frames = 3 seconds at 60fps) currentWave = 4; } // Start fifth wave of tower defense (boss stage) function startWave5() { calculateGuidelinePositions(); waveActive = true; enemySpawnTimer = 0; enemiesSpawned = 0; maxEnemiesInWave = 1; // Only 1 boss enemy enemySpawnInterval = 60; // Spawn immediately currentWave = 5; } // Spawn enemy on random guideline function spawnEnemy() { if (guidelineYPositions.length === 0) return; // Pick random guideline with better distribution var randomIndex = Math.floor(Math.random() * guidelineYPositions.length); var spawnY = guidelineYPositions[randomIndex]; // Add some vertical variation to make movement less predictable var verticalVariation = (Math.random() - 0.5) * 60; // +/- 30 pixels variation spawnY += verticalVariation; // Create new enemy var enemy = new Enemy(); // Set asset type based on current wave if (currentWave === 2) { enemy.setAssetType('Drone'); } else if (currentWave === 3) { enemy.setAssetType('SpaceDrone'); } else if (currentWave === 4) { enemy.setAssetType('Robot'); } else if (currentWave === 5) { enemy.setAssetType('UFO'); } enemy.x = 2048 + 100; // Start off right side of screen enemy.y = spawnY; // Store which guideline this enemy is following for reference enemy.guidelineIndex = randomIndex; enemy.baseY = guidelineYPositions[randomIndex]; enemies.push(enemy); game.addChild(enemy); // Play probedroid sound when first enemy appears if (!firstEnemySpawned) { LK.getSound('Probedroid').play(); firstEnemySpawned = true; } // Play probedroid2 sound when first robot appears in wave4 if (currentWave === 4 && enemiesSpawned === 0) { LK.getSound('Probedroid2').play(); } } // Add tower placement move handler game.move = function (x, y, obj) { if (placingTower && towerPreview) { // Find nearest snap position var snapPos = findNearestSnapPosition(x, y); towerPreview.x = snapPos.x; towerPreview.y = snapPos.y; if (confirmButton) { confirmButton.x = snapPos.x + 60; confirmButton.y = snapPos.y - 60; } } }; // Update tower defense game game.update = function () { // Only run tower defense logic when wave is active if (!waveActive) return; // Spawn enemies if (enemiesSpawned < maxEnemiesInWave) { enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnInterval) { spawnEnemy(); enemiesSpawned++; enemySpawnTimer = 0; } } // Check if wave is complete if (enemiesSpawned >= maxEnemiesInWave && enemies.length === 0) { waveActive = false; // Wave complete - transition to next wave if (currentWave === 1) { // Show wave2 asset with fade in/out var wave2Asset = game.addChild(LK.getAsset('Wave2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave2 asset tween(wave2Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave2 asset tween(wave2Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave2Asset.destroy(); // Start wave2 startWave2(); } }); } }); } else if (currentWave === 2) { // Show wave3 asset with fade in/out var wave3Asset = game.addChild(LK.getAsset('Wave3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave3 asset tween(wave3Asset, { alpha: 1 }, { duration: 750, easing: tween.easeInOut, onFinish: function onFinish() { // Keep wave3 visible for 1.5 seconds then fade out LK.setTimeout(function () { tween(wave3Asset, { alpha: 0 }, { duration: 750, easing: tween.easeInOut, onFinish: function onFinish() { wave3Asset.destroy(); // Start wave3 startWave3(); } }); }, 1500); } }); } else if (currentWave === 3) { // Show wave4 asset with fade in/out var wave4Asset = game.addChild(LK.getAsset('Wave4', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave4 asset tween(wave4Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave4 asset tween(wave4Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave4Asset.destroy(); // Start wave4 startWave4(); } }); } }); } else if (currentWave === 4) { // Show wave5 asset with fade in/out var wave5Asset = game.addChild(LK.getAsset('Wave5', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in wave5 asset tween(wave5Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Fade out wave5 asset tween(wave5Asset, { alpha: 0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { wave5Asset.destroy(); // Start wave5 startWave5(); } }); } }); } else if (currentWave === 5) { // UFO boss defeated - transition to story5 cutscene var story5Asset = game.addChild(LK.getAsset('Story5', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0 })); // Fade in story5 asset tween(story5Asset, { alpha: 1 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { // Add click handler to story5 to transition to level2 story5Asset.down = function (x, y, obj) { // Fade out story5 asset tween(story5Asset, { alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { story5Asset.destroy(); // Start level2 with backdrop2 startLevel2(); } }); }; } }); } } }; // Start the intro cutscene introCutscene.play(); ; ; // Start level2 with backdrop2 function startLevel2() { // Clear any existing game elements for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); enemies.splice(i, 1); } // Reset game variables for level2 waveActive = false; enemySpawnTimer = 0; enemiesSpawned = 0; maxEnemiesInWave = 10; enemySpawnInterval = 420; firstEnemySpawned = false; currentWave = 1; enemiesDefeated = 0; // Add backdrop2 asset as the new background var backdrop2Asset = game.addChild(LK.getAsset('Backdrop2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0, scaleX: 1.0, scaleY: 1.0 })); // Fade in backdrop2 tween(backdrop2Asset, { alpha: 1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Level2 is now ready - could start first wave or wait for player input // For now, level1 is officially over and level2 has begun with backdrop2 } }); // Recalculate guideline positions for level2 calculateGuidelinePositions(); // Add 6 horizontal guide lines for level2 var lineSpacing = 2732 / 7; for (var i = 1; i <= 6; i++) { var yPosition = lineSpacing * i; if (i === 1) { yPosition += 560; // Move guideline 1 down by 560 pixels (was 575) } else if (i === 2) { yPosition += 395; // Move guideline 2 down by 395 pixels (was 420) } else if (i === 3) { yPosition += 225; // Move guideline 3 down by 225 pixels (was 250) } else if (i === 4) { yPosition += 95; // Move guideline 4 down by 95 pixels (was 120) } else if (i === 5) { yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50) } else if (i === 6) { yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200) } var guideLine = game.addChild(LK.getAsset('guideLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPosition, alpha: 0.5 })); } }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Cutscene class
var Cutscene = Container.expand(function () {
var self = Container.call(this);
// Properties
self.scenes = [];
self.currentSceneIndex = 0;
self.isPlaying = false;
// Add a scene to the cutscene
self.addScene = function (sceneData) {
self.scenes.push(sceneData);
};
// Start playing the cutscene
self.play = function () {
if (self.scenes.length === 0) return;
self.isPlaying = true;
self.currentSceneIndex = 0;
self.playCurrentScene();
};
// Play the current scene
self.playCurrentScene = function () {
if (self.currentSceneIndex >= self.scenes.length) {
self.finish();
return;
}
var scene = self.scenes[self.currentSceneIndex];
if (scene.onStart) {
scene.onStart();
}
// Auto-advance to next scene after duration
if (scene.duration) {
LK.setTimeout(function () {
self.nextScene();
}, scene.duration);
}
};
// Move to next scene
self.nextScene = function () {
var scene = self.scenes[self.currentSceneIndex];
if (scene.onEnd) {
scene.onEnd();
}
self.currentSceneIndex++;
self.playCurrentScene();
};
// Skip to specific scene
self.skipToScene = function (index) {
if (index >= 0 && index < self.scenes.length) {
self.currentSceneIndex = index;
self.playCurrentScene();
}
};
// Finish cutscene
self.finish = function () {
self.isPlaying = false;
if (self.onFinish) {
self.onFinish();
}
};
// Stop cutscene
self.stop = function () {
self.isPlaying = false;
// Stop any running tweens or timeouts
tween.stopAll();
};
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 for tower defense
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Default to Probedroid, but can be changed
self.assetType = 'Probedroid';
var enemyGraphics = self.attachAsset(self.assetType, {
anchorX: 0.5,
anchorY: 0.5
});
// Enemy properties
self.health = 100;
self.maxHealth = 100;
self.speed = 2;
self.targetX = -100; // Move to left side of screen
self.lastX = self.x;
// Health bar graphics
self.healthBarBackground = self.attachAsset('healthBarBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -40
});
self.healthBarForeground = self.attachAsset('healthBarForeground', {
anchorX: 0,
anchorY: 0.5,
x: -30,
y: -40
});
self.update = function () {
// Store last position for collision detection
self.lastX = self.x;
// Move towards target (right to left)
if (self.x > self.targetX) {
self.x -= self.speed;
}
// Move towards the center of the assigned guideline
if (self.baseY !== undefined) {
var targetY = self.baseY;
var yDifference = targetY - self.y;
// Move towards guideline center with a fraction of movement speed
if (Math.abs(yDifference) > 2) {
self.y += yDifference * 0.1; // Adjust 0.1 to control how quickly enemies center on guidelines
}
}
// Update health bar
var healthPercentage = self.health / self.maxHealth;
self.healthBarForeground.scaleX = healthPercentage;
// Change health bar color based on health percentage
if (healthPercentage > 0.6) {
self.healthBarForeground.tint = 0x00ff00; // Green
} else if (healthPercentage > 0.3) {
self.healthBarForeground.tint = 0xffff00; // Yellow
} else {
self.healthBarForeground.tint = 0xff0000; // Red
}
// Check if enemy reached the end
if (self.lastX > 0 && self.x <= 0) {
// Enemy reached the end - remove from game
if (self.parent) {
self.destroy();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
}
};
// Method to defeat this enemy
self.defeat = function () {
if (self.parent) {
enemiesDefeated++;
self.destroy();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.setAssetType = function (assetType) {
if (enemyGraphics && enemyGraphics.parent) {
enemyGraphics.destroy();
}
self.assetType = assetType;
enemyGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
// Tower class for tower defense
var Tower = Container.expand(function () {
var self = Container.call(this);
// Tower properties
self.towerType = 'basic';
self.level = 1;
self.damage = 25;
self.range = 300;
self.fireRate = 60; // Frames between shots (60 = 1 second at 60fps)
self.cost = 100;
self.upgradeCost = 150;
self.lastShotFrame = 0;
self.target = null;
self.rangeCircle = null;
self.showingRange = false;
// Tower1 specific properties
self.tower1Range = 500; // Tower1 has 500 range straight ahead
self.isTower1 = false; // Flag to identify Tower1 instances
// Tower health properties
self.health = 100;
self.maxHealth = 100;
self.lastCollidingEnemies = []; // Track which enemies were colliding last frame
// Guideline tracking for same-line targeting
self.guidelineIndex = -1; // Which guideline this tower is on
// Create tower graphics
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
anchorY: 0.5
});
// Create level indicator
var levelIndicator = self.attachAsset('towerLevelIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -30
});
// Method to show/hide range circle
self.showRange = function () {
if (!self.rangeCircle) {
self.rangeCircle = self.addChild(LK.getAsset('rangeCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.range / 500,
scaleY: self.range / 500,
alpha: 0.3
}));
}
self.rangeCircle.alpha = 0.3;
self.showingRange = true;
};
self.hideRange = function () {
if (self.rangeCircle) {
self.rangeCircle.alpha = 0;
}
self.showingRange = false;
};
// Method to find nearest enemy in range
self.findTarget = function () {
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only target enemies on the same guideline
if (enemy.guidelineIndex !== self.guidelineIndex) {
continue; // Skip enemies not on same line
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// For Tower1, target enemies 500 pixels both left and right
if (self.isTower1) {
// Check if enemy is within 500 range horizontally (both left and right)
if (Math.abs(dx) <= self.tower1Range && Math.abs(dy) <= 50) {
var straightDistance = Math.abs(dx); // Distance horizontally
if (straightDistance < nearestDistance) {
nearestDistance = straightDistance;
nearestEnemy = enemy;
}
}
} else {
// Regular circular range for other towers
if (distance <= self.range && distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
}
return nearestEnemy;
};
// Method to shoot at target
self.shoot = function (target) {
if (!target || !target.parent) return;
// Create bullet/projectile effect
var bullet = game.addChild(LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Calculate direction to target
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Animate bullet to target
tween(bullet, {
x: target.x,
y: target.y
}, {
duration: distance / 2,
// Speed based on distance
easing: tween.linear,
onFinish: function onFinish() {
bullet.destroy();
// Deal damage to target
if (target && target.parent) {
target.health -= self.damage;
if (target.health <= 0) {
target.defeat();
playerScore += 10;
playerCash += 25;
}
}
}
});
// Play shoot sound
LK.getSound('Confirm').play();
};
// Method to upgrade tower
self.upgrade = function () {
if (playerCash >= self.upgradeCost && self.level < 3) {
playerCash -= self.upgradeCost;
self.level++;
self.damage += 15;
self.range += 50;
self.fireRate = Math.max(30, self.fireRate - 10);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
// Update level indicator
levelIndicator.destroy();
levelIndicator = self.attachAsset('towerLevelIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: -30,
scaleX: self.level,
scaleY: self.level
});
// Update range circle if showing
if (self.showingRange && self.rangeCircle) {
self.rangeCircle.scaleX = self.range / 500;
self.rangeCircle.scaleY = self.range / 500;
}
// Play upgrade sound
LK.getSound('Towerselect').play();
return true;
}
return false;
};
// Click handler for tower interaction
self.down = function (x, y, obj) {
if (self.showingRange) {
self.hideRange();
} else {
self.showRange();
}
};
self.update = function () {
// Only operate when wave is active
if (!waveActive) return;
// Check for enemy collisions and reduce tower health
var currentCollidingEnemies = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only collide with enemies on the same guideline
if (enemy.guidelineIndex === self.guidelineIndex && self.intersects(enemy)) {
currentCollidingEnemies.push(enemy);
// Check if this enemy just started colliding (wasn't colliding last frame)
var wasCollidingBefore = false;
for (var j = 0; j < self.lastCollidingEnemies.length; j++) {
if (self.lastCollidingEnemies[j] === enemy) {
wasCollidingBefore = true;
break;
}
}
// If enemy just started colliding, reduce tower health
if (!wasCollidingBefore) {
self.health -= 10; // Reduce health by 10 per collision
// Flash tower red to show damage
tween(towerGraphics, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Check if tower is destroyed
if (self.health <= 0) {
// Remove tower from towers array
for (var k = towers.length - 1; k >= 0; k--) {
if (towers[k] === self) {
towers.splice(k, 1);
break;
}
}
// Destroy tower
self.destroy();
return;
}
}
}
}
// Update last colliding enemies for next frame
self.lastCollidingEnemies = currentCollidingEnemies;
// Find target if we don't have one or current target is invalid
if (!self.target || !self.target.parent) {
self.target = self.findTarget();
}
// Shoot at target if in range and fire rate allows
if (self.target && self.target.parent) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if target is still in range
if (distance <= self.range) {
// Check if enough time has passed since last shot
if (LK.ticks - self.lastShotFrame >= self.fireRate) {
self.shoot(self.target);
self.lastShotFrame = LK.ticks;
}
} else {
// Target moved out of range
self.target = null;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
// Tower Defense Game Variables
var enemies = [];
var towers = [];
var waveActive = false;
var enemySpawnTimer = 0;
var enemySpawnInterval = 420; // Spawn every 7 seconds at 60fps
var enemiesSpawned = 0;
var maxEnemiesInWave = 10;
var guidelineYPositions = [];
var firstEnemySpawned = false;
var currentWave = 1;
var enemiesDefeated = 0;
var playerScore = 0;
var playerLives = 10;
var playerCash = 200;
var scoreDisplay = null;
var livesDisplay = null;
var cashDisplay = null;
var placingTower = false;
var towerPreview = null;
var confirmButton = null;
var pendingTowerCost = 10;
var verticalGuidelines = [];
var snapPositions = [];
// Create intro cutscene using intro2 asset
var introCutscene = new Cutscene();
// Add intro2 scene
introCutscene.addScene({
onStart: function onStart() {
// Create intro2 asset
var intro2Asset = game.addChild(LK.getAsset('Intro2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Create cell asset in middle of intro2
var cellAsset = game.addChild(LK.getAsset('cell', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Store references for cleanup
introCutscene.intro2Asset = intro2Asset;
introCutscene.cellAsset = cellAsset;
// Fade in intro2
tween(intro2Asset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Fade in cell asset
tween(cellAsset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add skip intro button
var skipIntroButton = new Text2('SKIP INTRO', {
size: 60,
fill: 0xFFFFFF
});
skipIntroButton.anchor.set(0.5, 0);
skipIntroButton.x = 2048 / 2;
skipIntroButton.y = 200;
skipIntroButton.alpha = 0;
game.addChild(skipIntroButton);
// Store reference for cleanup
introCutscene.skipIntroButton = skipIntroButton;
// Fade in skip button
tween(skipIntroButton, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add click event handler to skip button
skipIntroButton.down = function (x, y, obj) {
// Play intro music
LK.playMusic('Intro', {
loop: false
});
// Clean up intro2 assets
tween.stop(intro2Asset);
tween.stop(cellAsset);
tween.stop(skipIntroButton);
intro2Asset.destroy();
cellAsset.destroy();
skipIntroButton.destroy();
// Skip directly to title screen
showTitleScreen();
};
// Add click event handler to cell asset
cellAsset.down = function (x, y, obj) {
// Play intro music
LK.playMusic('Intro', {
loop: false
});
// Transition to story1 scene
var story1Asset = game.addChild(LK.getAsset('Story1', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade out current assets
tween(intro2Asset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut
});
tween(cellAsset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut
});
// Fade in story1 asset
tween(story1Asset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add click event handler to story1 asset to transition to story2
story1Asset.down = function (x, y, obj) {
// Create story2 asset
var story2Asset = game.addChild(LK.getAsset('Story2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade out story1 asset
tween(story1Asset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
story1Asset.destroy();
}
});
// Fade in story2 asset
tween(story2Asset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add click event handler to story2 asset to transition to story3
story2Asset.down = function (x, y, obj) {
// Create story3 asset
var story3Asset = game.addChild(LK.getAsset('Story3', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade out story2 asset
tween(story2Asset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
story2Asset.destroy();
}
});
// Fade in story3 asset
tween(story3Asset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add click event handler to story3 asset to transition to story4
story3Asset.down = function (x, y, obj) {
// Create story4 asset
var story4Asset = game.addChild(LK.getAsset('Story4', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade out story3 asset
tween(story3Asset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
story3Asset.destroy();
}
});
// Fade in story4 asset
tween(story4Asset, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeInOut
});
// Add click event handler to story4 asset to transition to titlescreen
story4Asset.down = function (x, y, obj) {
// Fade out story4 asset
tween(story4Asset, {
alpha: 0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
story4Asset.destroy();
// Show title screen
showTitleScreen();
}
});
};
};
};
};
};
}
});
// Set what happens when cutscene finishes
introCutscene.onFinish = function () {
// Cutscene finished - no automatic transition
};
// Function to show title screen
function showTitleScreen() {
// Display the title
// 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.2,
scaleY: 0.2
}));
// Zoom flyby to final size
tween(backdropFlyby, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 1000,
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 2 seconds then fade out
LK.setTimeout(function () {
tween(wave1Asset, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave1Asset.destroy();
// Start first tower defense wave
startWave1();
}
});
}, 2000);
}
});
}
});
// 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 += 560; // Move guideline 1 down by 560 pixels (was 575)
} else if (i === 2) {
yPosition += 395; // Move guideline 2 down by 395 pixels (was 420)
} else if (i === 3) {
yPosition += 225; // Move guideline 3 down by 225 pixels (was 250)
} else if (i === 4) {
yPosition += 95; // Move guideline 4 down by 95 pixels (was 120)
} else if (i === 5) {
yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50)
} else if (i === 6) {
yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200)
}
var guideLine = game.addChild(LK.getAsset('guideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: yPosition,
alpha: 0.5
}));
}
}
// 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: 0,
scaleX: 0.2,
scaleY: 0.2
}));
// 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 2 seconds then fade out
LK.setTimeout(function () {
tween(wave1Asset, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave1Asset.destroy();
// Start first tower defense wave
startWave1();
}
});
}, 2000);
}
});
}
});
}
// Fade in backdrop
tween(backdropAsset, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade in backdrop flyby and zoom to position
tween(backdropFlyby, {
alpha: 1,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Start flyby movement to right side after fade 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 += 560; // Move guideline 1 down by 560 pixels (was 575)
} else if (i === 2) {
yPosition += 395; // Move guideline 2 down by 395 pixels (was 420)
} else if (i === 3) {
yPosition += 225; // Move guideline 3 down by 225 pixels (was 250)
} else if (i === 4) {
yPosition += 95; // Move guideline 4 down by 95 pixels (was 120)
} else if (i === 5) {
yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50)
} else if (i === 6) {
yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200)
}
var guideLine = game.addChild(LK.getAsset('guideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: yPosition,
alpha: 0.5
}));
}
}
});
}
});
}
});
}, 5000);
}
});
}
// Calculate guideline Y positions for enemy spawning
function calculateGuidelinePositions() {
var lineSpacing = 2732 / 7;
guidelineYPositions = [];
for (var i = 1; i <= 6; i++) {
var yPosition = lineSpacing * i;
if (i === 1) {
yPosition += 560; // Move guideline 1 down by 560 pixels (was 575)
} else if (i === 2) {
yPosition += 395; // Move guideline 2 down by 395 pixels (was 420)
} else if (i === 3) {
yPosition += 225; // Move guideline 3 down by 225 pixels (was 250)
} else if (i === 4) {
yPosition += 95; // Move guideline 4 down by 95 pixels (was 120)
} else if (i === 5) {
yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50)
} else if (i === 6) {
yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200)
}
guidelineYPositions.push(yPosition);
}
}
// Calculate snap positions from guideline intersections
function calculateSnapPositions() {
snapPositions = [];
// Create vertical guideline positions (8 columns across screen width)
var verticalSpacing = 2048 / 9;
var verticalXPositions = [];
for (var i = 1; i <= 8; i++) {
var xPosition = verticalSpacing * i;
verticalXPositions.push(xPosition);
}
// Create snap positions at intersections of horizontal and vertical guidelines
for (var h = 0; h < guidelineYPositions.length; h++) {
for (var v = 0; v < verticalXPositions.length; v++) {
snapPositions.push({
x: verticalXPositions[v],
y: guidelineYPositions[h]
});
}
}
}
// Find nearest snap position to given coordinates
function findNearestSnapPosition(x, y) {
var nearestPosition = {
x: x,
y: y
};
var nearestDistance = Infinity;
for (var i = 0; i < snapPositions.length; i++) {
var snap = snapPositions[i];
var dx = snap.x - x;
var dy = snap.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestPosition = snap;
}
}
return nearestPosition;
}
// Show vertical guidelines during tower placement
function showVerticalGuidelines() {
hideVerticalGuidelines(); // Clear any existing guidelines
var verticalSpacing = 2048 / 9;
for (var i = 1; i <= 8; i++) {
var xPosition = verticalSpacing * i;
var guideLine = game.addChild(LK.getAsset('verticalGuideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: xPosition,
y: 2732 / 2,
alpha: 0.3
}));
verticalGuidelines.push(guideLine);
}
}
// Hide vertical guidelines
function hideVerticalGuidelines() {
for (var i = 0; i < verticalGuidelines.length; i++) {
verticalGuidelines[i].destroy();
}
verticalGuidelines = [];
}
// Start first wave of tower defense
function startWave1() {
calculateGuidelinePositions();
waveActive = true;
enemySpawnTimer = 0;
enemiesSpawned = 0;
currentWave = 1;
enemiesDefeated = 0;
// Add score display at top left
var scoreDisplay = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreDisplay.anchor.set(0, 0);
scoreDisplay.x = 400;
scoreDisplay.y = 50;
LK.gui.addChild(scoreDisplay);
// Add lives display at top center
var livesDisplay = new Text2('Lives: 10', {
size: 60,
fill: 0xFFFFFF
});
livesDisplay.anchor.set(0.5, 0);
livesDisplay.x = 1024;
livesDisplay.y = 50;
LK.gui.addChild(livesDisplay);
// Add cash display under lives display
cashDisplay = new Text2('Cash: $200', {
size: 60,
fill: 0xFFFFFF
});
cashDisplay.anchor.set(0.5, 0);
cashDisplay.x = 1024;
cashDisplay.y = 120;
LK.gui.addChild(cashDisplay);
// Add skip wave button under score display
var skipWaveButton = new Text2('SKIP WAVE', {
size: 40,
fill: 0xFFFF00
});
skipWaveButton.anchor.set(0, 0);
skipWaveButton.x = 400;
skipWaveButton.y = 120;
LK.gui.addChild(skipWaveButton);
// Add global click handler to cancel tower placement
game.down = function (x, y, obj) {
// Cancel tower placement if clicking on empty space
if (placingTower && obj === game) {
if (towerPreview) {
towerPreview.destroy();
towerPreview = null;
}
if (confirmButton) {
confirmButton.destroy();
confirmButton = null;
}
hideVerticalGuidelines();
placingTower = false;
}
};
// Add tower purchase buttons at bottom of screen
var towerButtonY = 2400; // Position near bottom of screen
var buttonSpacing = 50; // 50 pixel spacing between buttons
var startX = 430;
// Water Tower Button
var waterTowerButton = game.addChild(LK.getAsset('Waterbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX,
y: towerButtonY,
scaleX: 0.8,
scaleY: 0.8
}));
// Gas Tower Button
var gasTowerButton = game.addChild(LK.getAsset('Gasbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + waterTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY,
scaleX: 0.8,
scaleY: 0.8
}));
// Basic Tower Button
var basicTowerButton = game.addChild(LK.getAsset('Firebutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + waterTowerButton.width * 0.8 + buttonSpacing + gasTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY,
scaleX: 0.8,
scaleY: 0.8
}));
// Electric Tower Button
var electricTowerButton = game.addChild(LK.getAsset('Electricbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX,
y: towerButtonY + 150 + buttonSpacing,
scaleX: 0.8,
scaleY: 0.8
}));
// Advanced Tower Button
var advancedTowerButton = game.addChild(LK.getAsset('Plasmabutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + electricTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY + 150 + buttonSpacing,
scaleX: 0.8,
scaleY: 0.8
}));
// Slingshot Tower Button
var slingshotTowerButton = game.addChild(LK.getAsset('Slingshotbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY + 150 + buttonSpacing,
scaleX: 0.8,
scaleY: 0.8
}));
// Air Tower Button (above WiFi button)
var airTowerButton = game.addChild(LK.getAsset('Airbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing + slingshotTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY + 150 + buttonSpacing - 150 - buttonSpacing,
scaleX: 0.8,
scaleY: 0.8
}));
// WiFi Tower Button
var wifiTowerButton = game.addChild(LK.getAsset('Wifibutton', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + basicTowerButton.width * 0.8 + buttonSpacing + advancedTowerButton.width * 0.8 + buttonSpacing + slingshotTowerButton.width * 0.8 + buttonSpacing,
y: towerButtonY + 150 + buttonSpacing,
scaleX: 0.8,
scaleY: 0.8
}));
// Add click handlers for tower buttons
basicTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for basic tower
};
advancedTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for plasma tower
};
electricTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for electric tower
};
waterTowerButton.down = function (x, y, obj) {
if (playerCash >= pendingTowerCost && !placingTower) {
LK.getSound('Towerselect').play();
// Start tower placement mode
placingTower = true;
// Calculate snap positions and show guidelines
calculateSnapPositions();
showVerticalGuidelines();
// Find initial snap position
var snapPos = findNearestSnapPosition(x, y);
// Create tower preview using Tower1 asset
towerPreview = game.addChild(LK.getAsset('Tower1', {
anchorX: 0.5,
anchorY: 0.5,
x: snapPos.x,
y: snapPos.y,
alpha: 0.7
}));
// Create green tick confirmation button
confirmButton = game.addChild(LK.getAsset('squareLight', {
anchorX: 0.5,
anchorY: 0.5,
x: snapPos.x + 60,
y: snapPos.y - 60,
scaleX: 1.5,
scaleY: 1.5
}));
// Add click handler to confirm button
confirmButton.down = function (cx, cy, cobj) {
if (placingTower && towerPreview) {
// Deduct cash
playerCash -= pendingTowerCost;
if (cashDisplay) {
cashDisplay.setText('Cash: $' + playerCash);
}
// Create actual tower at preview position using Tower1 asset
var newTower = new Tower();
var towerGraphics = newTower.attachAsset('Tower1', {
anchorX: 0.5,
anchorY: 0.5
});
newTower.x = towerPreview.x;
newTower.y = towerPreview.y;
newTower.cost = pendingTowerCost;
newTower.isTower1 = true; // Mark as Tower1
newTower.range = newTower.tower1Range; // Set range to 500
// Assign tower to nearest guideline
var nearestGuidelineIndex = 0;
var nearestDistance = Infinity;
for (var g = 0; g < guidelineYPositions.length; g++) {
var distance = Math.abs(newTower.y - guidelineYPositions[g]);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestGuidelineIndex = g;
}
}
newTower.guidelineIndex = nearestGuidelineIndex;
game.addChild(newTower);
towers.push(newTower);
// Clean up placement mode
towerPreview.destroy();
confirmButton.destroy();
towerPreview = null;
confirmButton = null;
hideVerticalGuidelines();
placingTower = false;
// Play confirmation sound
LK.getSound('Confirm').play();
}
};
}
};
gasTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for gas tower
};
wifiTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for wifi tower
};
slingshotTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for slingshot tower
};
airTowerButton.down = function (x, y, obj) {
LK.getSound('Towerselect').play();
// TODO: Start tower placement mode for air tower
};
// Add click handler to skip wave button
skipWaveButton.down = function (x, y, obj) {
// Force wave completion by clearing all enemies and setting appropriate flags
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
enemiesSpawned = maxEnemiesInWave;
enemiesDefeated = maxEnemiesInWave;
// Check which wave we're skipping and trigger appropriate transition
if (currentWave === 1) {
// Show wave2 asset with fade in/out
var wave2Asset = game.addChild(LK.getAsset('Wave2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave2 asset
tween(wave2Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave2 asset
tween(wave2Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave2Asset.destroy();
// Start wave2
startWave2();
}
});
}
});
} else if (currentWave === 2) {
// Show wave3 asset with fade in/out
var wave3Asset = game.addChild(LK.getAsset('Wave3', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave3 asset
tween(wave3Asset, {
alpha: 1
}, {
duration: 750,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Keep wave3 visible for 1.5 seconds then fade out
LK.setTimeout(function () {
tween(wave3Asset, {
alpha: 0
}, {
duration: 750,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave3Asset.destroy();
// Start wave3
startWave3();
}
});
}, 1500);
}
});
} else if (currentWave === 3) {
// Show wave4 asset with fade in/out
var wave4Asset = game.addChild(LK.getAsset('Wave4', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave4 asset
tween(wave4Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave4 asset
tween(wave4Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave4Asset.destroy();
// Start wave4
startWave4();
}
});
}
});
} else if (currentWave === 4) {
// Show wave5 asset with fade in/out
var wave5Asset = game.addChild(LK.getAsset('Wave5', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave5 asset
tween(wave5Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave5 asset
tween(wave5Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave5Asset.destroy();
// Start wave5
startWave5();
}
});
}
});
} else if (currentWave === 5) {
// UFO boss defeated - transition to story5 cutscene
var story5Asset = game.addChild(LK.getAsset('Story5', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in story5 asset
tween(story5Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add click handler to story5 to transition to level2
story5Asset.down = function (x, y, obj) {
// Fade out story5 asset
tween(story5Asset, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
story5Asset.destroy();
// Start level2 with backdrop2
startLevel2();
}
});
};
}
});
} else {
waveActive = false;
}
};
}
// Start second wave of tower defense
function startWave2() {
calculateGuidelinePositions();
waveActive = true;
enemySpawnTimer = 0;
enemiesSpawned = 0;
maxEnemiesInWave = 20;
enemySpawnInterval = 300; // Spawn every 5 seconds at 60fps
currentWave = 2;
}
// Start third wave of tower defense
function startWave3() {
calculateGuidelinePositions();
waveActive = true;
enemySpawnTimer = 0;
enemiesSpawned = 0;
maxEnemiesInWave = 30;
enemySpawnInterval = 300; // Spawn every 5 seconds at 60fps (300 frames = 5 seconds at 60fps)
currentWave = 3;
}
// Start fourth wave of tower defense
function startWave4() {
calculateGuidelinePositions();
waveActive = true;
enemySpawnTimer = 0;
enemiesSpawned = 0;
maxEnemiesInWave = 40;
enemySpawnInterval = 180; // Spawn every 3 seconds at 60fps (180 frames = 3 seconds at 60fps)
currentWave = 4;
}
// Start fifth wave of tower defense (boss stage)
function startWave5() {
calculateGuidelinePositions();
waveActive = true;
enemySpawnTimer = 0;
enemiesSpawned = 0;
maxEnemiesInWave = 1; // Only 1 boss enemy
enemySpawnInterval = 60; // Spawn immediately
currentWave = 5;
}
// Spawn enemy on random guideline
function spawnEnemy() {
if (guidelineYPositions.length === 0) return;
// Pick random guideline with better distribution
var randomIndex = Math.floor(Math.random() * guidelineYPositions.length);
var spawnY = guidelineYPositions[randomIndex];
// Add some vertical variation to make movement less predictable
var verticalVariation = (Math.random() - 0.5) * 60; // +/- 30 pixels variation
spawnY += verticalVariation;
// Create new enemy
var enemy = new Enemy();
// Set asset type based on current wave
if (currentWave === 2) {
enemy.setAssetType('Drone');
} else if (currentWave === 3) {
enemy.setAssetType('SpaceDrone');
} else if (currentWave === 4) {
enemy.setAssetType('Robot');
} else if (currentWave === 5) {
enemy.setAssetType('UFO');
}
enemy.x = 2048 + 100; // Start off right side of screen
enemy.y = spawnY;
// Store which guideline this enemy is following for reference
enemy.guidelineIndex = randomIndex;
enemy.baseY = guidelineYPositions[randomIndex];
enemies.push(enemy);
game.addChild(enemy);
// Play probedroid sound when first enemy appears
if (!firstEnemySpawned) {
LK.getSound('Probedroid').play();
firstEnemySpawned = true;
}
// Play probedroid2 sound when first robot appears in wave4
if (currentWave === 4 && enemiesSpawned === 0) {
LK.getSound('Probedroid2').play();
}
}
// Add tower placement move handler
game.move = function (x, y, obj) {
if (placingTower && towerPreview) {
// Find nearest snap position
var snapPos = findNearestSnapPosition(x, y);
towerPreview.x = snapPos.x;
towerPreview.y = snapPos.y;
if (confirmButton) {
confirmButton.x = snapPos.x + 60;
confirmButton.y = snapPos.y - 60;
}
}
};
// Update tower defense game
game.update = function () {
// Only run tower defense logic when wave is active
if (!waveActive) return;
// Spawn enemies
if (enemiesSpawned < maxEnemiesInWave) {
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnInterval) {
spawnEnemy();
enemiesSpawned++;
enemySpawnTimer = 0;
}
}
// Check if wave is complete
if (enemiesSpawned >= maxEnemiesInWave && enemies.length === 0) {
waveActive = false;
// Wave complete - transition to next wave
if (currentWave === 1) {
// Show wave2 asset with fade in/out
var wave2Asset = game.addChild(LK.getAsset('Wave2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave2 asset
tween(wave2Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave2 asset
tween(wave2Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave2Asset.destroy();
// Start wave2
startWave2();
}
});
}
});
} else if (currentWave === 2) {
// Show wave3 asset with fade in/out
var wave3Asset = game.addChild(LK.getAsset('Wave3', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave3 asset
tween(wave3Asset, {
alpha: 1
}, {
duration: 750,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Keep wave3 visible for 1.5 seconds then fade out
LK.setTimeout(function () {
tween(wave3Asset, {
alpha: 0
}, {
duration: 750,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave3Asset.destroy();
// Start wave3
startWave3();
}
});
}, 1500);
}
});
} else if (currentWave === 3) {
// Show wave4 asset with fade in/out
var wave4Asset = game.addChild(LK.getAsset('Wave4', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave4 asset
tween(wave4Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave4 asset
tween(wave4Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave4Asset.destroy();
// Start wave4
startWave4();
}
});
}
});
} else if (currentWave === 4) {
// Show wave5 asset with fade in/out
var wave5Asset = game.addChild(LK.getAsset('Wave5', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in wave5 asset
tween(wave5Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out wave5 asset
tween(wave5Asset, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
wave5Asset.destroy();
// Start wave5
startWave5();
}
});
}
});
} else if (currentWave === 5) {
// UFO boss defeated - transition to story5 cutscene
var story5Asset = game.addChild(LK.getAsset('Story5', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0
}));
// Fade in story5 asset
tween(story5Asset, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add click handler to story5 to transition to level2
story5Asset.down = function (x, y, obj) {
// Fade out story5 asset
tween(story5Asset, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
story5Asset.destroy();
// Start level2 with backdrop2
startLevel2();
}
});
};
}
});
}
}
};
// Start the intro cutscene
introCutscene.play();
;
;
// Start level2 with backdrop2
function startLevel2() {
// Clear any existing game elements
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
// Reset game variables for level2
waveActive = false;
enemySpawnTimer = 0;
enemiesSpawned = 0;
maxEnemiesInWave = 10;
enemySpawnInterval = 420;
firstEnemySpawned = false;
currentWave = 1;
enemiesDefeated = 0;
// Add backdrop2 asset as the new background
var backdrop2Asset = game.addChild(LK.getAsset('Backdrop2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0,
scaleX: 1.0,
scaleY: 1.0
}));
// Fade in backdrop2
tween(backdrop2Asset, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Level2 is now ready - could start first wave or wait for player input
// For now, level1 is officially over and level2 has begun with backdrop2
}
});
// Recalculate guideline positions for level2
calculateGuidelinePositions();
// Add 6 horizontal guide lines for level2
var lineSpacing = 2732 / 7;
for (var i = 1; i <= 6; i++) {
var yPosition = lineSpacing * i;
if (i === 1) {
yPosition += 560; // Move guideline 1 down by 560 pixels (was 575)
} else if (i === 2) {
yPosition += 395; // Move guideline 2 down by 395 pixels (was 420)
} else if (i === 3) {
yPosition += 225; // Move guideline 3 down by 225 pixels (was 250)
} else if (i === 4) {
yPosition += 95; // Move guideline 4 down by 95 pixels (was 120)
} else if (i === 5) {
yPosition -= 75; // Move guideline 5 up by 75 pixels (was -50)
} else if (i === 6) {
yPosition -= 225; // Move guideline 6 up by 225 pixels (was -200)
}
var guideLine = game.addChild(LK.getAsset('guideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: yPosition,
alpha: 0.5
}));
}
}
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