User prompt
quiero tener un aliado ia que se mueva por el mapa que no lo boten los enemigos sino que este ahi y que aparezca uno nuevocada oleada que dispare y mate enemigos y tenga 20 de vida si sobrevive aparece otro cada oleado incluso si no sobrevive siempre llega uno mas y se acumulan
User prompt
no aprecio en la oleada uno que aparezca el aliado que dispara
User prompt
que el amigo pulpo pistola aparezca desde el principio del juego
User prompt
que el pulpo con pistola aparezca en la oleada 3
User prompt
creame los aset para hacerle sus imagenes
User prompt
desde la oleada 8 empieza aparecer otro poder que sueltan los enemigos que si golpeo la esfera que sueltan aparece un amigo pulpo con pistola que tiene 20 de vida que se mueve por el mapa y los enemigos tambien le pueden disparar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que el dirijido igual se convine con el triple si estan los dos activos
User prompt
que los poderes se puedan convinar que si tengo un ataque triple activo y pulpo se multipliquen los pulpos, si tengo fuego rapido que los pulpos vayan mas rapido si estan los pulpos igual y que si esta el ataque rapido y el dirijido vayan mas rapido y aparte que el dirijido busque botiquines igual
User prompt
que el ataque rapido dure 5 segudos
User prompt
que los pulpos se mantenga por 20 segudos
User prompt
si pesco un poder del pulpo que se acumule y que no desaparezca el anterior
User prompt
que el sketch ya no tenga animacion y que el inicio este denuevo al principio ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que esta imagen palpite con animacion ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que el cañon tenga una respiracion ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
pon animacion de palpitar a la la imagen del sketch 2 y 3 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que las imagenes de los eketch tenga un palpitar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
por alguna razon no suena la musica de sketch
User prompt
con su respectiva musica
User prompt
la historia de los sketch este primero que el inicio y lo de play
User prompt
que empiece las musica apenas inicia el juego
User prompt
la musica de inicio debe terminar cuando apreto play luego sale la de sketch y luego empieza la otra del juego
User prompt
la musica no se escucha corrije eso
User prompt
el toca para continuar del sketch este en ingles
User prompt
creame dos aset mas para hacer dos imagenes mas que sigan despues del primer sketch sin que cambie el fondo de sketch hasta que empiece el juego
User prompt
y que haya un aset para la musica que sonara mientra haya un sketch
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); self.shipType = 'boss'; self.speed = 0.5; // Very slow base speed self.points = 500; // High points for boss self.graphics = null; self.healthBar = null; self.healthBarBg = null; self.isDying = false; self.init = function (wave) { self.shipType = 'boss'; self.graphics = self.attachAsset('bossShip', { anchorX: 0.5, anchorY: 0.5 }); // Make boss larger and more intimidating self.graphics.scaleX = 1.5; self.graphics.scaleY = 1.5; // Slow speed that slightly increases with wave self.speed = 0.5 + (wave - 4) * 0.1; self.points = 500 + (wave - 4) * 100; // Scaling points self.health = 40; self.maxHealth = 40; // Create larger health bar for boss var healthBarWidth = 300; self.healthBarBg = LK.getAsset('healthBarBg', { width: healthBarWidth, height: 20, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.healthBarBg.y = -self.graphics.height / 2 - 40; self.addChild(self.healthBarBg); self.healthBar = LK.getAsset('healthBar', { width: healthBarWidth - 4, height: 16, color: 0xFF0000, // Red health bar for boss shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.healthBar.y = -self.graphics.height / 2 - 40; self.addChild(self.healthBar); // Boss shoots more frequently self.lastShotTime = 0; self.shotDelay = 90; // 1.5 seconds }; self.updateHealthBar = function () { if (self.healthBar && self.maxHealth > 1) { var healthPercent = self.health / self.maxHealth; self.healthBar.scaleX = healthPercent; if (healthPercent > 0.6) { self.healthBar.tint = 0xFF4444; // Dark red } else if (healthPercent > 0.3) { self.healthBar.tint = 0xFF0000; // Red } else { self.healthBar.tint = 0x880000; // Dark red } } }; self.update = function () { self.x += self.speed; if (self.graphics) { self.graphics.visible = true; } }; self.canShoot = function () { return LK.ticks - self.lastShotTime >= self.shotDelay; }; self.shootAtCannon = function (cannonX, cannonY) { if (!self.canShoot()) return null; self.lastShotTime = LK.ticks; var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var dx = cannonX - self.x; var dy = cannonY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / distance * bullet.speed; bullet.velocityY = dy / distance * bullet.speed; bullet.damage = 2; // Boss bullets do more damage return bullet; }; return self; }); var Cannon = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 0.5 }); self.targetX = 0; self.targetY = 0; self.lastFireTime = 0; self.fireDelay = 300; self.health = 10; self.maxHealth = 10; self.isShielded = false; self.shieldTimer = 0; self.aimAt = function (x, y) { self.targetX = x; self.targetY = y; var dx = x - self.x; var dy = y - self.y; var angle = Math.atan2(dy, dx); self.graphics.rotation = angle; }; self.canFire = function () { var currentFireDelay = rapidFire ? self.fireDelay / 3 : self.fireDelay; return LK.ticks * 16.67 - self.lastFireTime >= currentFireDelay; }; self.fire = function () { if (!self.canFire()) return null; self.lastFireTime = LK.ticks * 16.67; var cannonballs = []; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var baseAngle = Math.atan2(dy, dx); if (guidedShot) { // Fire guided projectile var guidedProjectile = new GuidedProjectile(); guidedProjectile.x = self.x - 45; guidedProjectile.y = self.y - 40; guidedProjectile.targetX = self.targetX; guidedProjectile.targetY = self.targetY; guidedProjectile.lastTargetUpdateTime = LK.ticks; guidedProjectile.creationTime = LK.ticks; // Set creation time guidedProjectiles.push(guidedProjectile); game.addChild(guidedProjectile); } else if (tripleShot) { // Fire three cannonballs with slight angle differences for (var i = 0; i < 3; i++) { var cannonball = new Cannonball(); cannonball.x = self.x - 45; cannonball.y = self.y - 40; var angleOffset = (i - 1) * 0.2; // -0.2, 0, 0.2 radians var adjustedAngle = baseAngle + angleOffset; cannonball.velocityX = Math.cos(adjustedAngle) * cannonball.speed; cannonball.velocityY = Math.sin(adjustedAngle) * cannonball.speed; cannonballs.push(cannonball); } } else { // Fire single cannonball var cannonball = new Cannonball(); cannonball.x = self.x - 45; cannonball.y = self.y - 40; cannonball.velocityX = dx / distance * cannonball.speed; cannonball.velocityY = dy / distance * cannonball.speed; cannonballs.push(cannonball); } LK.getSound('shoot').play(); return cannonballs; }; self.takeDamage = function (damage) { if (self.isShielded) { damage = Math.floor(damage / 2); // Shield reduces damage by half } self.health -= damage; if (self.health < 0) self.health = 0; // Flash red when taking damage tween(self.graphics, { tint: 0xff0000 }, { duration: 100, onFinish: function onFinish() { tween(self.graphics, { tint: 0xffffff }, { duration: 100 }); } }); }; self.heal = function (amount) { self.health += amount; if (self.health > self.maxHealth) self.health = self.maxHealth; // Flash green when healing tween(self.graphics, { tint: 0x00ff00 }, { duration: 200, onFinish: function onFinish() { tween(self.graphics, { tint: 0xffffff }, { duration: 200 }); } }); }; self.activateShield = function () { self.isShielded = true; self.shieldTimer = 900; // 15 seconds at 60fps self.graphics.tint = 0x88ccff; // Blue tint for shield }; return self; }); var Cannonball = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('cannonball', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.speed = 16; self.damage = 1; // Base damage, will be multiplied by cannonDamage when hitting self.update = function () { self.x += self.velocityX; self.y += self.velocityY; }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.speed = 8; self.damage = 1; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; }; return self; }); var GuidedProjectile = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('guidedProjectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 16; self.damage = 3; // Base damage for guided projectiles (will be enhanced by cannonDamage) self.targetX = 0; self.targetY = 0; self.lastTargetUpdateTime = 0; self.targetUpdateDelay = 30; // Update target every 0.5 seconds self.creationTime = 0; // Track when the projectile was created self.lifetime = 120; // 2 seconds at 60fps (2 * 60) self.update = function () { // Update target position periodically if (LK.ticks - self.lastTargetUpdateTime >= self.targetUpdateDelay) { // Find nearest enemy ship var nearestShip = null; var nearestDistance = Infinity; for (var i = 0; i < ships.length; i++) { var ship = ships[i]; if (ship && ship.graphics && ship.graphics.visible && !ship.isDying) { var dx = ship.x - self.x; var dy = ship.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestShip = ship; } } } // If we found a ship, target it if (nearestShip) { self.targetX = nearestShip.x; self.targetY = nearestShip.y; } self.lastTargetUpdateTime = LK.ticks; } // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Add slight rotation for visual effect graphics.rotation += 0.1; }; return self; }); var GuidedShotPowerUp = Container.expand(function () { var self = Container.call(this); self.speed = 2; var graphics = self.attachAsset('guidedShotPowerUp', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.speed; }; return self; }); var HealthKit = Container.expand(function () { var self = Container.call(this); self.speed = 2; self.healAmount = 2; var graphics = self.attachAsset('healthKit', { anchorX: 0.5, anchorY: 0.5 }); // Add a cross symbol var crossV = LK.getAsset('healthKit', { width: 20, height: 60, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); var crossH = LK.getAsset('healthKit', { width: 60, height: 20, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.addChild(crossV); self.addChild(crossH); self.update = function () { self.x += self.speed; }; return self; }); var Octopus = Container.expand(function () { var self = Container.call(this); self.speed = 4; self.targetShip = null; self.state = 'seeking'; // seeking, grabbing, sinking self.sinkTimer = 0; self.sinkDuration = 120; // 2 seconds at 60fps var graphics = self.attachAsset('smallShip', { anchorX: 0.5, anchorY: 0.5, color: 0x800080, // Purple color for octopus shape: 'ellipse' }); graphics.scaleX = 0.8; graphics.scaleY = 0.8; graphics.tint = 0x800080; self.init = function () { // Find nearest ship to grab var nearestShip = null; var nearestDistance = Infinity; for (var i = 0; i < ships.length; i++) { var ship = ships[i]; if (ship && ship.graphics && ship.graphics.visible && !ship.isDying && ship.shipType !== 'boss') { var dx = ship.x - self.x; var dy = ship.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestShip = ship; } } } self.targetShip = nearestShip; }; self.update = function () { if (self.state === 'seeking' && self.targetShip && self.targetShip.parent) { // Move towards target ship var dx = self.targetShip.x - self.x; var dy = self.targetShip.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Check if reached the ship if (distance < 50) { self.state = 'grabbing'; self.targetShip.isDying = true; // Start sinking animation tween(self.targetShip, { y: self.targetShip.y + 100, scaleX: 0.8, scaleY: 0.8, alpha: 0.5 }, { duration: 2000, easing: tween.easeIn, onFinish: function onFinish() { if (self.targetShip && self.targetShip.parent) { self.targetShip.destroy(); // Remove from ships array for (var i = ships.length - 1; i >= 0; i--) { if (ships[i] === self.targetShip) { ships.splice(i, 1); break; } } } } }); self.state = 'sinking'; } } else if (self.state === 'sinking') { self.sinkTimer++; if (self.sinkTimer >= self.sinkDuration) { // Octopus disappears self.destroy(); } } }; return self; }); var OctopusArm = Container.expand(function () { var self = Container.call(this); self.speed = 28; self.targetShip = null; self.state = 'emerging'; // emerging, seeking, grabbing, sinking, retreating self.stateTimer = 0; self.grabCount = 0; self.maxGrabs = 5; var graphics = self.attachAsset('octopusArm', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x4B0082; // Deep purple color for octopus arm self.init = function () { self.x = 1024; // Start from center bottom self.y = 2600; // Start from bottom of screen self.alpha = 0.8; self.scaleX = 0.5; self.scaleY = 0.5; self.state = 'emerging'; self.stateTimer = 60; // 1 second emergence time self.grabCount = 0; // Emergence animation tween(self, { y: 2200, scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }, { duration: 1000, easing: tween.easeOut }); }; self.findNearestShip = function () { var nearestShip = null; var nearestDistance = Infinity; for (var i = 0; i < ships.length; i++) { var ship = ships[i]; if (ship && ship.graphics && ship.graphics.visible && !ship.isDying) { var dx = ship.x - self.x; var dy = ship.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestShip = ship; } } } return nearestShip; }; self.update = function () { self.stateTimer--; if (self.state === 'emerging') { if (self.stateTimer <= 0) { self.state = 'seeking'; self.targetShip = self.findNearestShip(); } } else if (self.state === 'seeking') { if (self.targetShip && self.targetShip.parent && !self.targetShip.isDying) { // Move towards target ship var dx = self.targetShip.x - self.x; var dy = self.targetShip.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Check if reached the ship if (distance < 80) { self.state = 'grabbing'; self.stateTimer = 30; // Half second grab time // Special handling for bosses - damage instead of instant kill if (self.targetShip.shipType === 'boss') { self.targetShip.health -= 15; self.targetShip.updateHealthBar(); LK.effects.flashObject(self.targetShip, 0xff0000, 500); if (self.targetShip.health <= 0) { self.targetShip.isDying = true; // Count this as an octopus kill since boss died from octopus damage self.grabCount++; // Grab animation - ship gets pulled towards octopus tween(self.targetShip, { x: self.x, y: self.y + 50, scaleX: 0.6, scaleY: 0.6, alpha: 0.7 }, { duration: 500, easing: tween.easeIn }); } else { // Boss survives, octopus retreats after damaging but doesn't count as kill self.state = 'retreating'; self.stateTimer = 60; } } else { self.targetShip.isDying = true; // Count this kill immediately when octopus grabs the ship self.grabCount++; // Grab animation - ship gets pulled towards octopus tween(self.targetShip, { x: self.x, y: self.y + 50, scaleX: 0.6, scaleY: 0.6, alpha: 0.7 }, { duration: 500, easing: tween.easeIn }); } } } else { // Find new target if current one is gone self.targetShip = self.findNearestShip(); if (!self.targetShip) { self.state = 'retreating'; self.stateTimer = 60; } } } else if (self.state === 'grabbing') { if (self.stateTimer <= 0) { self.state = 'sinking'; self.stateTimer = 90; // 1.5 second sink time // Sinking animation - ship disappears into the depths if (self.targetShip && self.targetShip.parent) { tween(self.targetShip, { y: self.targetShip.y + 200, scaleX: 0.2, scaleY: 0.2, alpha: 0.0, rotation: Math.PI }, { duration: 1500, easing: tween.easeIn, onFinish: function onFinish() { if (self.targetShip && self.targetShip.parent) { // Award points and remove ship LK.setScore(LK.getScore() + self.targetShip.points); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('shipDestroyed').play(); self.targetShip.destroy(); // Remove from ships array for (var i = ships.length - 1; i >= 0; i--) { if (ships[i] === self.targetShip) { ships.splice(i, 1); break; } } } } }); } } } else if (self.state === 'sinking') { if (self.stateTimer <= 0) { // Only retreat when octopus has made 5 successful kills by itself if (self.grabCount >= self.maxGrabs) { self.state = 'retreating'; self.stateTimer = 60; } else { self.state = 'seeking'; self.targetShip = self.findNearestShip(); } } } else if (self.state === 'retreating') { // Retreat animation self.y += 4; self.alpha -= 0.02; self.scaleX -= 0.02; self.scaleY -= 0.02; if (self.stateTimer <= 0 || self.alpha <= 0) { self.destroy(); } } }; return self; }); var OctopusPowerUp = Container.expand(function () { var self = Container.call(this); self.speed = 2; var graphics = self.attachAsset('octopusPowerUpSphere', { anchorX: 0.5, anchorY: 0.5 }); // Add "P" text on the sphere var pText = new Text2('P', { size: 120, fill: 0xFFFFFF }); pText.anchor.set(0.5, 0.5); self.addChild(pText); self.update = function () { self.x += self.speed; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.powerType = 'tripleShot'; self.speed = 2; self.graphics = null; self.init = function (type) { self.powerType = type; if (type === 'tripleShot') { self.graphics = self.attachAsset('tripleShotPowerUp', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'rapidFire') { self.graphics = self.attachAsset('rapidFirePowerUp', { anchorX: 0.5, anchorY: 0.5 }); } }; self.update = function () { self.x += self.speed; }; return self; }); var ShieldPowerUp = Container.expand(function () { var self = Container.call(this); self.speed = 2; var graphics = self.attachAsset('shieldPowerUp', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.speed; }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); self.shipType = 'small'; self.speed = 2; self.points = 10; self.graphics = null; self.healthBar = null; self.healthBarBg = null; self.isDying = false; // Flag to prevent damage during death animation self.init = function (type) { self.shipType = type; if (type === 'small') { self.graphics = self.attachAsset('smallShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; // Small ships: 100 points in waves 1-2, then scale with wave if (currentWave <= 2) { self.points = 100; } else { self.points = 10 + (currentWave - 2) * 5; // Gradual increase after wave 2 } self.health = 1; self.maxHealth = 1; } else if (type === 'medium') { self.graphics = self.attachAsset('mediumShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; // Medium ships: 100 points when first appearing (waves 3-4), then scale if (currentWave <= 4) { self.points = 100; } else { self.points = 25 + (currentWave - 4) * 10; // Gradual increase after wave 4 } self.health = 3; self.maxHealth = 3; } else if (type === 'large') { self.graphics = self.attachAsset('largeShip', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.5; // Large ships: 100 points when first appearing (waves 5-6), then scale if (currentWave <= 6) { self.points = 100; } else { self.points = 50 + (currentWave - 6) * 15; // Gradual increase after wave 6 } self.health = 5; self.maxHealth = 5; } // Create health bar background - wider for better visibility var healthBarWidth = Math.max(120, self.graphics.width * 1.2); self.healthBarBg = LK.getAsset('healthBarBg', { width: healthBarWidth, height: 12, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.healthBarBg.y = -self.graphics.height / 2 - 20; self.addChild(self.healthBarBg); // Create health bar foreground - wider for better visibility self.healthBar = LK.getAsset('healthBar', { width: healthBarWidth - 4, height: 8, color: 0x00FF00, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.healthBar.y = -self.graphics.height / 2 - 20; self.addChild(self.healthBar); // Show health bar for all ships now - no hiding for small ships // Set shooting properties based on ship type self.lastShotTime = 0; if (type === 'small') { self.shotDelay = 180; // 3 seconds } else if (type === 'medium') { self.shotDelay = 150; // 2.5 seconds } else if (type === 'large') { self.shotDelay = 120; // 2 seconds } }; self.updateHealthBar = function () { if (self.healthBar && self.maxHealth >= 1) { var healthPercent = Math.max(0, self.health / self.maxHealth); self.healthBar.scaleX = healthPercent; if (healthPercent > 0.6) { self.healthBar.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { self.healthBar.tint = 0xFFFF00; // Yellow } else { self.healthBar.tint = 0xFF0000; // Red } // Ensure health bar visibility for all ship types self.healthBar.visible = true; self.healthBarBg.visible = true; } }; self.update = function () { self.x += self.speed; // Ensure collision detection remains active if (self.graphics) { self.graphics.visible = true; } }; self.canShoot = function () { return LK.ticks - self.lastShotTime >= self.shotDelay; }; self.shootAtCannon = function (cannonX, cannonY) { if (!self.canShoot()) return null; self.lastShotTime = LK.ticks; var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var dx = cannonX - self.x; var dy = cannonY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / distance * bullet.speed; bullet.velocityY = dy / distance * bullet.speed; return bullet; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001122 }); /**** * Game Code ****/ var oceanBackground = LK.getAsset('oceanBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); oceanBackground.visible = false; // Start hidden since we show sketches first game.addChild(oceanBackground); // Game background - will replace ocean background when game starts var gameBackground = LK.getAsset('gameBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); gameBackground.visible = true; // Start visible for sketches game.addChild(gameBackground); // Start menu variables var gameStarted = false; var sketchShown = true; // Start with sketches visible var menuShown = false; // Track if menu has been shown var currentSketchIndex = 0; var totalSketches = 3; var startMenu = new Container(); game.addChild(startMenu); startMenu.visible = false; // Start with menu hidden // Sketch menu container var sketchMenu = new Container(); game.addChild(sketchMenu); sketchMenu.visible = true; // Start with sketches visible // Sketch background - only visible during sketch var sketchBackgroundImage = sketchMenu.attachAsset('sketchBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); // Sketch images var sketchImage = sketchMenu.attachAsset('sketch', { anchorX: 0.5, anchorY: 0.5 }); sketchImage.x = 1024; sketchImage.y = 1366; var sketchImage2 = sketchMenu.attachAsset('sketch2', { anchorX: 0.5, anchorY: 0.5 }); sketchImage2.x = 1024; sketchImage2.y = 1366; sketchImage2.visible = false; var sketchImage3 = sketchMenu.attachAsset('sketch3', { anchorX: 0.5, anchorY: 0.5 }); sketchImage3.x = 1024; sketchImage3.y = 1366; sketchImage3.visible = false; // Add pulsating animation to sketch images function pulseSketchImage(sketchImg) { if (sketchImg.visible && sketchImg.parent) { tween(sketchImg, { scaleX: 1.05, scaleY: 1.05, alpha: 0.9 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (sketchImg.visible && sketchImg.parent) { tween(sketchImg, { scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { pulseSketchImage(sketchImg); } }); } } }); } } // Start pulsating animations for all sketch images pulseSketchImage(sketchImage); pulseSketchImage(sketchImage2); pulseSketchImage(sketchImage3); // Continue button text var continueText = new Text2('Tap to continue', { size: 60, fill: 0xFFFFFF }); continueText.anchor.set(0.5, 0.5); continueText.x = 1024; continueText.y = 2400; sketchMenu.addChild(continueText); // Add pulsating animation to continue text function pulseContinueText() { tween(continueText, { alpha: 0.5, scaleX: 0.9, scaleY: 0.9 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(continueText, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 1000, easing: tween.easeInOut, onFinish: pulseContinueText }); } }); } // Start continue text animation immediately since sketches are shown first pulseContinueText(); // Ocean title image var oceanTitleImage = startMenu.attachAsset('oceanTitle', { anchorX: 0.5, anchorY: 0.5 }); oceanTitleImage.x = 1024; oceanTitleImage.y = 750; // Defender title image var defenderTitleImage = startMenu.attachAsset('defenderTitle', { anchorX: 0.5, anchorY: 0.5 }); defenderTitleImage.x = 1024; defenderTitleImage.y = 1600; // Play button image var playButtonImage = startMenu.attachAsset('playButtonImage', { anchorX: 0.5, anchorY: 0.5 }); playButtonImage.x = 1024; playButtonImage.y = 2300; // Add pulsating animation to ocean title function pulseOceanTitle() { tween(oceanTitleImage, { scaleX: 1.1, scaleY: 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(oceanTitleImage, { scaleX: 1.0, scaleY: 1.0 }, { duration: 1000, easing: tween.easeInOut, onFinish: pulseOceanTitle }); } }); } pulseOceanTitle(); // Add pulsating animation to defender title function pulseDefenderTitle() { tween(defenderTitleImage, { scaleX: 1.1, scaleY: 1.1 }, { duration: 1200, easing: tween.easeInOut, onFinish: function onFinish() { tween(defenderTitleImage, { scaleX: 1.0, scaleY: 1.0 }, { duration: 1200, easing: tween.easeInOut, onFinish: pulseDefenderTitle }); } }); } pulseDefenderTitle(); // Add pulsating animation to play button function pulsePlayButton() { tween(playButtonImage, { scaleX: 1.15, scaleY: 1.15 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(playButtonImage, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: pulsePlayButton }); } }); } pulsePlayButton(); // Creator name image var creatorNameImage = startMenu.attachAsset('creatorNameImage', { anchorX: 0.5, anchorY: 0.5 }); creatorNameImage.x = 1024; creatorNameImage.y = 2500; // Add subtle glow animation to creator image function pulseCreatorName() { tween(creatorNameImage, { alpha: 0.7, scaleX: 0.95, scaleY: 0.95 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { tween(creatorNameImage, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 1500, easing: tween.easeInOut, onFinish: pulseCreatorName }); } }); } pulseCreatorName(); // Start playing the sketch music immediately when game starts LK.playMusic('sketchMusic', { loop: true, fade: { start: 0, end: 0.5, duration: 500 } }); function checkWaveCompletion() { // Simple wave completion based on enemies killed var requiredKills = enemiesRequiredPerWave + (currentWave - 1) * 5; if (enemiesKilledThisWave >= requiredKills && !waveCompleted) { waveCompleted = true; enemiesKilledThisWave = 0; waveCompleted = false; } } var cannon = game.addChild(new Cannon()); cannon.x = 1024; cannon.y = 2600; cannon.visible = false; cannon.baseFireDelay = 300; // Store original fire delay // Shield effect visual var shieldEffect = LK.getAsset('shieldEffect', { anchorX: 0.5, anchorY: 0.5 }); shieldEffect.x = cannon.x; shieldEffect.y = cannon.y; shieldEffect.visible = false; shieldEffect.alpha = 0.6; shieldEffect.scaleX = 0.3; shieldEffect.scaleY = 0.3; game.addChild(shieldEffect); var ships = []; var cannonballs = []; var shipSpawnTimer = 0; var shipSpawnDelay = 120; var difficultyTimer = 0; var shipsEscaped = 0; var maxEscapedShips = 10; // Escaped ships counter UI var escapedShipsTxt = new Text2('Escaped: 0/10', { size: 50, fill: 0xFFFFFF }); escapedShipsTxt.anchor.set(0.5, 0); escapedShipsTxt.y = 60; escapedShipsTxt.visible = false; LK.gui.top.addChild(escapedShipsTxt); // Wave number display UI var waveNumberTxt = new Text2('Wave: 1', { size: 50, fill: 0xFFFFFF }); waveNumberTxt.anchor.set(0.5, 0); waveNumberTxt.y = 120; waveNumberTxt.visible = false; LK.gui.top.addChild(waveNumberTxt); var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.visible = false; LK.gui.top.addChild(scoreTxt); var powerUps = []; var tripleShot = false; var tripleShotTimer = 0; var rapidFire = false; var rapidFireTimer = 0; var powerUpDuration = 180; // 3 seconds at 60fps // Power-up timer UI var powerUpTimerTxt = new Text2('', { size: 70, fill: 0xFFFFFF }); powerUpTimerTxt.anchor.set(0.5, 0.5); powerUpTimerTxt.x = 0; powerUpTimerTxt.y = 100; LK.gui.center.addChild(powerUpTimerTxt); var activePowerUpType = ''; var activePowerUpTimer = 0; var isShooting = false; var shootingTimer = 0; // Wave system var currentWave = 1; var lastWaveScore = 0; var waveMessage = null; var waveMessageTimer = 0; var waveCompleted = false; // Wave completion tracking var enemiesKilledThisWave = 0; var enemiesRequiredPerWave = 15; // Base number of enemies to kill per wave // Cannon health system var enemyBullets = []; var healthKits = []; var shieldPowerUps = []; var guidedShotPowerUps = []; var guidedProjectiles = []; var octopusPowerUps = []; var octopuses = []; var guidedShot = false; var guidedShotTimer = 0; var guidedShotDuration = 420; // 7 seconds at 60fps // Cannon health UI - positioned next to cannon var cannonHealthBarBg = LK.getAsset('cannonHealthBarBg', { width: 400, height: 20, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); cannonHealthBarBg.x = cannon.x; cannonHealthBarBg.y = cannon.y - 150; cannonHealthBarBg.visible = false; game.addChild(cannonHealthBarBg); var cannonHealthBar = LK.getAsset('cannonHealthBar', { width: 396, height: 16, color: 0x00ff00, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); cannonHealthBar.x = cannon.x; cannonHealthBar.y = cannon.y - 150; cannonHealthBar.visible = false; game.addChild(cannonHealthBar); var healthText = new Text2('Health: 10/10', { size: 40, fill: 0xFFFFFF }); healthText.anchor.set(0.5, 0.5); healthText.x = cannon.x; healthText.y = cannon.y - 100; healthText.visible = false; game.addChild(healthText); // Wave message text var waveMessageTxt = new Text2('', { size: 100, fill: 0xFFFF00 }); waveMessageTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(waveMessageTxt); waveMessageTxt.visible = false; // Track if boss has been spawned this wave var bossSpawnedThisWave = false; function spawnShip() { // Check if it's a boss wave (every 4 waves) and boss hasn't been spawned yet if (currentWave % 4 === 0 && currentWave >= 4 && !bossSpawnedThisWave) { // Check if there's already a boss in the ships array var bossExists = false; for (var i = 0; i < ships.length; i++) { if (ships[i].shipType === 'boss') { bossExists = true; break; } } // Only spawn boss if none exists if (!bossExists) { var boss = new Boss(); boss.init(currentWave); boss.x = -300; // Start further left due to larger size boss.y = 1366; // Center vertically boss.zIndex = 10; // Highest priority for rendering ships.push(boss); game.addChild(boss); game.children.sort(function (a, b) { return (a.zIndex || 0) - (b.zIndex || 0); }); bossSpawnedThisWave = true; } } // Regular ship spawning for all waves (including boss waves) var ship = new Ship(); var shipType; // Wave-based enemy spawning if (currentWave <= 2) { // Waves 1-2: Only small ships shipType = 'small'; } else if (currentWave <= 4) { // Waves 3-4: Small and medium ships var types = ['small', 'small', 'medium']; shipType = types[Math.floor(Math.random() * types.length)]; } else if (currentWave <= 6) { // Waves 5-6: Medium and some large ships var types = ['small', 'medium', 'medium', 'large']; shipType = types[Math.floor(Math.random() * types.length)]; } else { // Wave 7+: All ship types with more large ships var types = ['small', 'medium', 'large', 'large']; shipType = types[Math.floor(Math.random() * types.length)]; } ship.init(shipType); ship.x = -150; ship.y = 1000 + Math.random() * 1200; // Apply wave-based speed multiplier var speedMultiplier = 1 + (currentWave - 1) * 0.3; // If it's a boss wave, apply slower speed to all enemies if (currentWave % 4 === 0 && currentWave >= 4) { speedMultiplier = speedMultiplier * 0.5; // Make all enemies slower on boss waves } ship.speed = ship.speed * speedMultiplier; // Set zIndex based on ship type for proper layering if (ship.shipType === 'large') { ship.zIndex = 3; } else if (ship.shipType === 'medium') { ship.zIndex = 2; } else { ship.zIndex = 1; } game.children.sort(function (a, b) { return (a.zIndex || 0) - (b.zIndex || 0); }); ships.push(ship); game.addChild(ship); } function updateDifficulty() { difficultyTimer++; if (difficultyTimer % 1800 === 0) { shipSpawnDelay = Math.max(60, shipSpawnDelay - 10); } } function checkWaveTransition() { var currentScore = LK.getScore(); var newWave = Math.floor(currentScore / 1000) + 1; if (newWave > currentWave) { currentWave = newWave; lastWaveScore = Math.floor(currentScore / 1000) * 1000; // Reset boss spawning flag for new wave bossSpawnedThisWave = false; // Reset escaped ships counter for new wave shipsEscaped = 0; escapedShipsTxt.setText('Escaped: 0/10'); // Update wave number display waveNumberTxt.setText('Wave: ' + currentWave); // Increase max health by 2 each wave cannon.maxHealth += 2; cannon.health = cannon.maxHealth; // Restore to full health // Keep base fire rate constant across waves cannon.fireDelay = cannon.baseFireDelay; // Show wave message if (currentWave === 2) { waveMessageTxt.setText('Segunda Oleada'); } else if (currentWave === 3) { waveMessageTxt.setText('Tercera Oleada'); } else if (currentWave === 4) { waveMessageTxt.setText('¡JEFE! - Oleada 4'); } else if (currentWave === 5) { waveMessageTxt.setText('Quinta Oleada'); } else if (currentWave % 4 === 0) { waveMessageTxt.setText('¡JEFE! - Oleada ' + currentWave); } else { waveMessageTxt.setText('Oleada ' + currentWave); } waveMessageTxt.visible = true; waveMessageTimer = 180; // Show for 3 seconds // Increase difficulty shipSpawnDelay = Math.max(30, 120 - (currentWave - 1) * 15); // Increase ship speeds for (var i = 0; i < ships.length; i++) { var ship = ships[i]; var speedMultiplier = 1 + (currentWave - 1) * 0.3; ship.speed = ship.speed * speedMultiplier; } } } // Touch/click handlers game.down = function (x, y, obj) { if (!gameStarted) return; cannon.aimAt(x, y); isShooting = true; shootingTimer = 0; // Fire immediately on first click var newCannonballs = cannon.fire(); if (newCannonballs) { for (var c = 0; c < newCannonballs.length; c++) { cannonballs.push(newCannonballs[c]); game.addChild(newCannonballs[c]); } } }; game.up = function (x, y, obj) { if (!gameStarted) return; isShooting = false; }; // Play button event handler playButtonImage.down = function (x, y, obj) { if (!gameStarted && menuShown) { // Start the game directly gameStarted = true; startMenu.visible = false; // Change background to game background oceanBackground.visible = false; gameBackground.visible = true; // Stop button animations tween.stop(oceanTitleImage); tween.stop(defenderTitleImage); tween.stop(playButtonImage); tween.stop(creatorNameImage); // Stop menu music completely before starting game music LK.stopMusic(); // Start game music immediately after stopping menu music LK.playMusic('calmSeaMelody', { loop: true }); // Show game UI cannon.visible = true; cannonHealthBarBg.visible = true; cannonHealthBar.visible = true; healthText.visible = true; scoreTxt.visible = true; escapedShipsTxt.visible = true; waveNumberTxt.visible = true; } }; // Sketch menu click handler to cycle through sketches and show menu sketchMenu.down = function (x, y, obj) { if (sketchShown && !menuShown) { currentSketchIndex++; if (currentSketchIndex < totalSketches) { // Hide current sketch and show next one if (currentSketchIndex === 1) { sketchImage.visible = false; sketchImage2.visible = true; } else if (currentSketchIndex === 2) { sketchImage2.visible = false; sketchImage3.visible = true; } } else { // All sketches shown, show the menu menuShown = true; sketchMenu.visible = false; startMenu.visible = true; // Change background to ocean background gameBackground.visible = false; oceanBackground.visible = true; // Stop continue text animation tween.stop(continueText); // Stop sketch music completely before starting menu music LK.stopMusic(); // Start menu music immediately after stopping sketch music LK.playMusic('menuMusic', { loop: true }); // Start menu animations pulseOceanTitle(); pulseDefenderTitle(); pulsePlayButton(); pulseCreatorName(); } } }; game.update = function () { if (!gameStarted) return; // Handle continuous shooting if (isShooting) { shootingTimer++; var currentFireDelay = rapidFire ? cannon.fireDelay / 3 : cannon.fireDelay; var fireDelayInTicks = currentFireDelay / 16.67; // Convert ms to ticks if (shootingTimer >= fireDelayInTicks) { var newCannonballs = cannon.fire(); if (newCannonballs) { for (var c = 0; c < newCannonballs.length; c++) { cannonballs.push(newCannonballs[c]); game.addChild(newCannonballs[c]); } } shootingTimer = 0; } } updateDifficulty(); checkWaveTransition(); // Update wave message timer if (waveMessageTimer > 0) { waveMessageTimer--; if (waveMessageTimer <= 0) { waveMessageTxt.visible = false; } } shipSpawnTimer++; if (shipSpawnTimer >= shipSpawnDelay) { spawnShip(); shipSpawnTimer = 0; } for (var i = ships.length - 1; i >= 0; i--) { var ship = ships[i]; if (ship.lastX === undefined) ship.lastX = ship.x; if (ship.lastX <= 2048 && ship.x > 2048) { shipsEscaped++; escapedShipsTxt.setText('Escaped: ' + shipsEscaped + '/10'); LK.getSound('shipEscape').play(); ship.destroy(); ships.splice(i, 1); // Check if too many ships escaped if (shipsEscaped >= maxEscapedShips) { // Show final score and wave reached var finalScore = LK.getScore(); var finalWave = currentWave; LK.showGameOver('Puntaje: ' + finalScore + '\nOleada alcanzada: ' + finalWave); return; } continue; } // Ships shoot at cannon if (ship.x > 200 && ship.x < 1800) { // Only shoot when in range var newBullet = ship.shootAtCannon(cannon.x, cannon.y); if (newBullet) { enemyBullets.push(newBullet); game.addChild(newBullet); } } ship.lastX = ship.x; } for (var j = cannonballs.length - 1; j >= 0; j--) { var cannonball = cannonballs[j]; if (cannonball.lastX === undefined) cannonball.lastX = cannonball.x; if (cannonball.lastY === undefined) cannonball.lastY = cannonball.y; if (cannonball.lastX >= 0 && cannonball.x < 0 || cannonball.lastX <= 2048 && cannonball.x > 2048 || cannonball.lastY >= 0 && cannonball.y < 0 || cannonball.lastY <= 2732 && cannonball.y > 2732) { cannonball.destroy(); cannonballs.splice(j, 1); continue; } // Auto-selection is now used - no upgrade button collision detection needed for (var k = ships.length - 1; k >= 0; k--) { var ship = ships[k]; // Ensure ship is valid and has proper collision detection, and not dying if (ship && ship.graphics && ship.graphics.visible && !ship.isDying && cannonball.intersects(ship)) { ship.health -= cannonball.damage; ship.updateHealthBar(); LK.effects.flashObject(ship, 0xff0000, 200); LK.getSound('hit').play(); cannonball.destroy(); cannonballs.splice(j, 1); if (ship.health <= 0) { enemiesKilledThisWave++; // Track kills for wave completion ship.isDying = true; // Mark as dying to prevent further damage LK.setScore(LK.getScore() + ship.points); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('shipDestroyed').play(); // Add small jump death animation var originalY = ship.y; var deadShip = ship; // Store reference to avoid closure issues tween(ship, { y: originalY - 30, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(deadShip, { y: originalY + 10, scaleX: 0.8, scaleY: 0.8 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { // Random chance to spawn different power-ups (45% total chance) var spawnChance = Math.random(); if (spawnChance < 0.15) { // 15% chance for weapon power-ups var powerUp = new PowerUp(); var powerTypes = ['tripleShot', 'rapidFire']; var randomPowerType = powerTypes[Math.floor(Math.random() * powerTypes.length)]; powerUp.init(randomPowerType); powerUp.x = deadShip.x; powerUp.y = deadShip.y; powerUps.push(powerUp); game.addChild(powerUp); // Add brilliant glowing animation to power-up powerUp.graphics.tint = 0xffffff; tween(powerUp.graphics, { tint: 0xffff00, scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(powerUp.graphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { // Continue pulsing glow function continuePulse() { if (powerUp.parent) { tween(powerUp.graphics, { tint: 0xffff00, scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { if (powerUp.parent) { tween(powerUp.graphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeInOut, onFinish: continuePulse }); } } }); } } continuePulse(); } }); } }); } else if (spawnChance < 0.25) { // 10% chance for health kit var healthKit = new HealthKit(); healthKit.x = deadShip.x; healthKit.y = deadShip.y; healthKits.push(healthKit); game.addChild(healthKit); // Add brilliant glowing animation to health kit healthKit.tint = 0xffffff; tween(healthKit, { tint: 0x00ff00, scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(healthKit, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { // Continue pulsing glow function continuePulse() { if (healthKit.parent) { tween(healthKit, { tint: 0x00ff00, scaleX: 1.15, scaleY: 1.15 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { if (healthKit.parent) { tween(healthKit, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: continuePulse }); } } }); } } continuePulse(); } }); } }); } else if (spawnChance < 0.35) { // 15% chance for guided shot var guidedShotPowerUp = new GuidedShotPowerUp(); guidedShotPowerUp.x = deadShip.x; guidedShotPowerUp.y = deadShip.y; guidedShotPowerUps.push(guidedShotPowerUp); game.addChild(guidedShotPowerUp); // Add brilliant glowing animation to guided shot power-up guidedShotPowerUp.tint = 0xffffff; tween(guidedShotPowerUp, { tint: 0xff6600, scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(guidedShotPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { // Continue pulsing glow function continuePulse() { if (guidedShotPowerUp.parent) { tween(guidedShotPowerUp, { tint: 0xff6600, scaleX: 1.2, scaleY: 1.2 }, { duration: 700, easing: tween.easeInOut, onFinish: function onFinish() { if (guidedShotPowerUp.parent) { tween(guidedShotPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 700, easing: tween.easeInOut, onFinish: continuePulse }); } } }); } } continuePulse(); } }); } }); } else if (spawnChance < 0.40) { // 5% chance for octopus power - same as other special powers var octopusPowerUp = new OctopusPowerUp(); octopusPowerUp.x = deadShip.x; octopusPowerUp.y = deadShip.y; octopusPowerUps.push(octopusPowerUp); game.addChild(octopusPowerUp); // Add brilliant glowing animation octopusPowerUp.tint = 0xffffff; tween(octopusPowerUp, { tint: 0x800080, scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(octopusPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { function continuePulse() { if (octopusPowerUp.parent) { tween(octopusPowerUp, { tint: 0x800080, scaleX: 1.2, scaleY: 1.2 }, { duration: 700, easing: tween.easeInOut, onFinish: function onFinish() { if (octopusPowerUp.parent) { tween(octopusPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 700, easing: tween.easeInOut, onFinish: continuePulse }); } } }); } } continuePulse(); } }); } }); } else if (spawnChance < 0.45) { // 5% chance for shield var shieldPowerUp = new ShieldPowerUp(); shieldPowerUp.x = deadShip.x; shieldPowerUp.y = deadShip.y; shieldPowerUps.push(shieldPowerUp); game.addChild(shieldPowerUp); // Add brilliant glowing animation to shield power-up shieldPowerUp.tint = 0xffffff; tween(shieldPowerUp, { tint: 0x0099ff, scaleX: 1.3, scaleY: 1.3 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(shieldPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { // Continue pulsing glow function continuePulse() { if (shieldPowerUp.parent) { tween(shieldPowerUp, { tint: 0x0099ff, scaleX: 1.2, scaleY: 1.2 }, { duration: 700, easing: tween.easeInOut, onFinish: function onFinish() { if (shieldPowerUp.parent) { tween(shieldPowerUp, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 700, easing: tween.easeInOut, onFinish: continuePulse }); } } }); } } continuePulse(); } }); } }); } if (deadShip.parent) { deadShip.destroy(); } // Remove from ships array by finding the ship for (var removeIndex = ships.length - 1; removeIndex >= 0; removeIndex--) { if (ships[removeIndex] === deadShip) { ships.splice(removeIndex, 1); break; } } } }); } }); } break; } } if (cannonballs[j]) { cannonball.lastX = cannonball.x; cannonball.lastY = cannonball.y; } } // Update power-ups for (var p = powerUps.length - 1; p >= 0; p--) { var powerUp = powerUps[p]; if (powerUp.lastX === undefined) powerUp.lastX = powerUp.x; // Remove power-up if it goes off screen if (powerUp.lastX <= 2048 && powerUp.x > 2048) { powerUp.destroy(); powerUps.splice(p, 1); continue; } // Check collision with cannonballs for collection for (var cb = cannonballs.length - 1; cb >= 0; cb--) { var cannonball = cannonballs[cb]; if (cannonball.intersects(powerUp)) { // Collect power-up LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0x00ff00, 300); // Clear any existing power-up to prevent accumulation tripleShot = false; rapidFire = false; activePowerUpTimer = 0; // Reset timer to prevent accumulation // Activate new power-up if (powerUp.powerType === 'tripleShot') { tripleShot = true; activePowerUpType = 'Triple Shot'; activePowerUpTimer = powerUpDuration; } else if (powerUp.powerType === 'rapidFire') { rapidFire = true; activePowerUpType = 'Rapid Fire'; activePowerUpTimer = powerUpDuration; } powerUp.destroy(); powerUps.splice(p, 1); break; } } if (powerUps[p]) { powerUp.lastX = powerUp.x; } } // Update enemy bullets for (var eb = enemyBullets.length - 1; eb >= 0; eb--) { var enemyBullet = enemyBullets[eb]; if (enemyBullet.lastY === undefined) enemyBullet.lastY = enemyBullet.y; // Remove if off screen if (enemyBullet.lastY <= 2732 && enemyBullet.y > 2732) { enemyBullet.destroy(); enemyBullets.splice(eb, 1); continue; } // Check collision with cannon if (enemyBullet.intersects(cannon)) { cannon.takeDamage(enemyBullet.damage); enemyBullet.destroy(); enemyBullets.splice(eb, 1); // Update health UI var healthPercent = cannon.health / cannon.maxHealth; cannonHealthBar.scaleX = healthPercent; if (healthPercent > 0.6) { cannonHealthBar.tint = 0x00FF00; } else if (healthPercent > 0.3) { cannonHealthBar.tint = 0xFFFF00; } else { cannonHealthBar.tint = 0xFF0000; } healthText.setText('Health: ' + cannon.health + '/' + cannon.maxHealth); // Check game over if (cannon.health <= 0) { // Show final score and wave reached var finalScore = LK.getScore(); var finalWave = currentWave; LK.showGameOver('Puntaje: ' + finalScore + '\nOleada alcanzada: ' + finalWave); return; } continue; } if (enemyBullets[eb]) { enemyBullet.lastY = enemyBullet.y; } } // Update health kits for (var hk = healthKits.length - 1; hk >= 0; hk--) { var healthKit = healthKits[hk]; if (healthKit.lastX === undefined) healthKit.lastX = healthKit.x; // Remove if off screen if (healthKit.lastX <= 2048 && healthKit.x > 2048) { healthKit.destroy(); healthKits.splice(hk, 1); continue; } // Check collection by cannonball for (var cb = cannonballs.length - 1; cb >= 0; cb--) { var cannonball = cannonballs[cb]; if (cannonball.intersects(healthKit)) { cannon.heal(healthKit.healAmount); LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0x00ff00, 200); // Update health UI var healthPercent = cannon.health / cannon.maxHealth; cannonHealthBar.scaleX = healthPercent; if (healthPercent > 0.6) { cannonHealthBar.tint = 0x00FF00; } else if (healthPercent > 0.3) { cannonHealthBar.tint = 0xFFFF00; } else { cannonHealthBar.tint = 0xFF0000; } healthText.setText('Health: ' + cannon.health + '/' + cannon.maxHealth); healthKit.destroy(); healthKits.splice(hk, 1); break; } } // Check collection by guided projectiles for (var gp = guidedProjectiles.length - 1; gp >= 0; gp--) { var guidedProjectile = guidedProjectiles[gp]; if (guidedProjectile.intersects(healthKit)) { cannon.heal(healthKit.healAmount); LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0x00ff00, 200); // Update health UI var healthPercent = cannon.health / cannon.maxHealth; cannonHealthBar.scaleX = healthPercent; if (healthPercent > 0.6) { cannonHealthBar.tint = 0x00FF00; } else if (healthPercent > 0.3) { cannonHealthBar.tint = 0xFFFF00; } else { cannonHealthBar.tint = 0xFF0000; } healthText.setText('Health: ' + cannon.health + '/' + cannon.maxHealth); healthKit.destroy(); healthKits.splice(hk, 1); break; } } if (healthKits[hk]) { healthKit.lastX = healthKit.x; } } // Update shield power-ups for (var sp = shieldPowerUps.length - 1; sp >= 0; sp--) { var shieldPowerUp = shieldPowerUps[sp]; if (shieldPowerUp.lastX === undefined) shieldPowerUp.lastX = shieldPowerUp.x; // Remove if off screen if (shieldPowerUp.lastX <= 2048 && shieldPowerUp.x > 2048) { shieldPowerUp.destroy(); shieldPowerUps.splice(sp, 1); continue; } // Check collection by cannonball for (var cb = cannonballs.length - 1; cb >= 0; cb--) { var cannonball = cannonballs[cb]; if (cannonball.intersects(shieldPowerUp)) { cannon.activateShield(); LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0x0099ff, 300); // Add brilliant glowing animation to cannon when shield is collected tween(cannon.graphics, { tint: 0x88ccff, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(cannon.graphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeInOut }); } }); shieldPowerUp.destroy(); shieldPowerUps.splice(sp, 1); break; } } if (shieldPowerUps[sp]) { shieldPowerUp.lastX = shieldPowerUp.x; } } // Update guided shot power-ups for (var gsp = guidedShotPowerUps.length - 1; gsp >= 0; gsp--) { var guidedShotPowerUp = guidedShotPowerUps[gsp]; if (guidedShotPowerUp.lastX === undefined) guidedShotPowerUp.lastX = guidedShotPowerUp.x; // Remove if off screen if (guidedShotPowerUp.lastX <= 2048 && guidedShotPowerUp.x > 2048) { guidedShotPowerUp.destroy(); guidedShotPowerUps.splice(gsp, 1); continue; } // Check collection by cannonball for (var cb = cannonballs.length - 1; cb >= 0; cb--) { var cannonball = cannonballs[cb]; if (cannonball.intersects(guidedShotPowerUp)) { // Clear existing power-ups tripleShot = false; rapidFire = false; guidedShot = true; activePowerUpType = 'Guided Shot'; activePowerUpTimer = guidedShotDuration; LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0xff6600, 300); guidedShotPowerUp.destroy(); guidedShotPowerUps.splice(gsp, 1); break; } } if (guidedShotPowerUps[gsp]) { guidedShotPowerUp.lastX = guidedShotPowerUp.x; } } // Update octopus power-ups for (var op = octopusPowerUps.length - 1; op >= 0; op--) { var octopusPowerUp = octopusPowerUps[op]; if (octopusPowerUp.lastX === undefined) octopusPowerUp.lastX = octopusPowerUp.x; // Remove if off screen if (octopusPowerUp.lastX <= 2048 && octopusPowerUp.x > 2048) { octopusPowerUp.destroy(); octopusPowerUps.splice(op, 1); continue; } // Check collection by cannonball for (var cb = cannonballs.length - 1; cb >= 0; cb--) { var cannonball = cannonballs[cb]; if (cannonball.intersects(octopusPowerUp)) { // Spawn octopus arm helper var octopusArm = new OctopusArm(); octopusArm.init(); octopuses.push(octopusArm); game.addChild(octopusArm); // Destroy the cannonball that collected the power-up cannonball.destroy(); cannonballs.splice(cb, 1); LK.getSound('powerUpCollect').play(); LK.effects.flashScreen(0x800080, 300); // Show power activation message var powerMessage = new Text2('¡Brazo de Pulpo Invocado!', { size: 80, fill: 0x800080 }); powerMessage.anchor.set(0.5, 0.5); LK.gui.center.addChild(powerMessage); // Animate and remove message tween(powerMessage, { y: -100, alpha: 0 }, { duration: 2000, easing: tween.easeOut, onFinish: function onFinish() { if (powerMessage.parent) { powerMessage.destroy(); } } }); octopusPowerUp.destroy(); octopusPowerUps.splice(op, 1); break; } } if (octopusPowerUps[op]) { octopusPowerUp.lastX = octopusPowerUp.x; } } // Update octopuses for (var oc = octopuses.length - 1; oc >= 0; oc--) { var octopus = octopuses[oc]; // Remove if octopus is destroyed or off screen if (!octopus.parent || octopus.x > 2300 || octopus.y > 2900) { if (octopus.parent) { octopus.destroy(); } octopuses.splice(oc, 1); } } // Update guided projectiles for (var gp = guidedProjectiles.length - 1; gp >= 0; gp--) { var guidedProjectile = guidedProjectiles[gp]; // Check if projectile has exceeded its lifetime (4 seconds) if (LK.ticks - guidedProjectile.creationTime >= guidedProjectile.lifetime) { guidedProjectile.destroy(); guidedProjectiles.splice(gp, 1); continue; } // Check collision with enemy ships var hitShip = false; for (var k = ships.length - 1; k >= 0; k--) { var ship = ships[k]; // Ensure ship is valid and has proper collision detection, and not dying if (ship && ship.graphics && ship.graphics.visible && !ship.isDying && guidedProjectile.intersects(ship)) { ship.health -= guidedProjectile.damage; ship.updateHealthBar(); LK.effects.flashObject(ship, 0xff0000, 200); LK.getSound('hit').play(); guidedProjectile.destroy(); guidedProjectiles.splice(gp, 1); hitShip = true; if (ship.health <= 0) { enemiesKilledThisWave++; // Track kills for wave completion ship.isDying = true; // Mark as dying to prevent further damage LK.setScore(LK.getScore() + ship.points); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('shipDestroyed').play(); // Add small jump death animation var originalY = ship.y; var deadShip = ship; // Store reference to avoid closure issues tween(ship, { y: originalY - 30, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(deadShip, { y: originalY + 10, scaleX: 0.8, scaleY: 0.8 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { if (deadShip.parent) { deadShip.destroy(); } // Remove from ships array by finding the ship for (var removeIndex = ships.length - 1; removeIndex >= 0; removeIndex--) { if (ships[removeIndex] === deadShip) { ships.splice(removeIndex, 1); break; } } } }); } }); } break; } } if (hitShip) continue; // Remove if too far off screen if (guidedProjectile.x < -200 || guidedProjectile.x > 2248 || guidedProjectile.y < -200 || guidedProjectile.y > 2932) { guidedProjectile.destroy(); guidedProjectiles.splice(gp, 1); } } // Update cannon shield if (cannon.isShielded && cannon.shieldTimer > 0) { cannon.shieldTimer--; // Show shield effect when active if (!shieldEffect.visible) { shieldEffect.visible = true; shieldEffect.x = cannon.x; shieldEffect.y = cannon.y; } if (cannon.shieldTimer <= 0) { cannon.isShielded = false; shieldEffect.visible = false; tween(cannon.graphics, { tint: 0xffffff }, { duration: 500 }); } } else { shieldEffect.visible = false; } // Update power-up timer if (activePowerUpTimer > 0) { activePowerUpTimer--; // Update timer display var timeLeft = Math.ceil(activePowerUpTimer / 60); var timerText = activePowerUpType + ': ' + timeLeft + 's'; if (cannon.isShielded) { var shieldTimeLeft = Math.ceil(cannon.shieldTimer / 60); timerText += ' | Shield: ' + shieldTimeLeft + 's'; } powerUpTimerTxt.setText(timerText); // Check if power-up expired if (activePowerUpTimer <= 0) { tripleShot = false; rapidFire = false; guidedShot = false; activePowerUpType = ''; if (cannon.isShielded) { var shieldTimeLeft = Math.ceil(cannon.shieldTimer / 60); powerUpTimerTxt.setText('Shield: ' + shieldTimeLeft + 's'); } else { powerUpTimerTxt.setText(''); } } } else { // No active weapon power-up, but maybe shield if (cannon.isShielded) { var shieldTimeLeft = Math.ceil(cannon.shieldTimer / 60); powerUpTimerTxt.setText('Shield: ' + shieldTimeLeft + 's'); } else { powerUpTimerTxt.setText(''); } } // Check for wave completion at end of update loop checkWaveCompletion(); };
===================================================================
--- original.js
+++ change.js
@@ -849,8 +849,40 @@
});
sketchImage3.x = 1024;
sketchImage3.y = 1366;
sketchImage3.visible = false;
+// Add pulsating animation to sketch images
+function pulseSketchImage(sketchImg) {
+ if (sketchImg.visible && sketchImg.parent) {
+ tween(sketchImg, {
+ scaleX: 1.05,
+ scaleY: 1.05,
+ alpha: 0.9
+ }, {
+ duration: 1500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ if (sketchImg.visible && sketchImg.parent) {
+ tween(sketchImg, {
+ scaleX: 1.0,
+ scaleY: 1.0,
+ alpha: 1.0
+ }, {
+ duration: 1500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ pulseSketchImage(sketchImg);
+ }
+ });
+ }
+ }
+ });
+ }
+}
+// Start pulsating animations for all sketch images
+pulseSketchImage(sketchImage);
+pulseSketchImage(sketchImage2);
+pulseSketchImage(sketchImage3);
// Continue button text
var continueText = new Text2('Tap to continue', {
size: 60,
fill: 0xFFFFFF
The small warship is fast and agile, designed for quick attacks and evading enemy fire. It has light armor and carries a few small cannons. Its compact size makes it harder to hit but less durable.. In-Game asset. 2d. High contrast. No shadows
The medium warship balances speed and firepower. It is equipped with multiple cannons and moderate armor. It moves steadily and can withstand more hits than smaller ships, making it a tougher target.. In-Game asset. 2d. High contrast. No shadows
boton de play pero que sea con tematica oceanica y que tenga una cocha al lado. In-Game asset. 2d. High contrast. No shadows
un barco gigante de guerra. In-Game asset. 2d. High contrast. No shadows
escudo celestial. In-Game asset. 2d. High contrast. No shadows
mas velocidad pero escrito en ingles. In-Game asset. 2d. High contrast. No shadows
mas vida pero escrito en ingles. In-Game asset. 2d. High contrast. No shadows
mas daño pero escrito en ingles. In-Game asset. 2d. High contrast. No shadows
un mar con un fondo a lo lejos. In-Game asset. 2d. High contrast. No shadows
unas letras que digan : creado por ZURI HARDAWAY. In-Game asset. 2d. High contrast. No shadows
que un pulpo este sentado en un cañon. In-Game asset. 2d. High contrast. No shadows
crea un titulo que diga oceanic defence con un pulplo detras de las letras que esta sentado en un cañon negro. In-Game asset. 2d. High contrast. No shadows
crea una imagen de un barco estallando. In-Game asset. 2d. High contrast. No shadows
un pulpo naranja viendo que barcos de guerra vienen a atacar su hogar marino. In-Game asset. 2d. High contrast. No shadows
una sola viñeta en blanco de comic de manera rectangular horizontal en el centro de la pantalla, que el back ground este adornado con un fondo marino y brazos de pulpos. In-Game asset. 2d. High contrast. No shadows, que los tentaculos no toquen la viñeta q
un pulpo naranja abriendo un cofre del tesoro donde encuentra en el fondo marino dentro de ese cofre un cañon nergro donde. In-Game asset. 2d. High contrast. No shadows
un pulpo naranja frenetico disparandole a buques de guerras encima de un cañon negro. que se vea el fondo del cielo y el mar pero que no este enojado sino calmado
bala de cañon. In-Game asset. 2d. High contrast. No shadows
bala de cañon. In-Game asset. 2d. High contrast. No shadows
ojo de pulpo. In-Game asset. 2d. High contrast. No shadows
botiquin con un pulpo rodeandolo. In-Game asset. 2d. High contrast. No shadows
una esfera con una letra r dentro y un pulpo rodeando la esfera. In-Game asset. 2d. High contrast. No shadows
una letra t dentro de una esfera y un pulpo que la rodea. In-Game asset. 2d. High contrast. No shadows
una p dentro de una esfera con un brazo de un pulpo rojo rodeandola. In-Game asset. 2d. High contrast. No shadows
guerra de pulpos con cañones, que sean de diferentes colores los pulpos de diferentes, tipo dibujo contra buques de guerra