User prompt
A que cada 15 segundos aparezca el láser, el láser del boss.
User prompt
haz que láser dure 10 segundos y que vaya siguiendo al boss o sea que lo vaya acompañando de lado a lado ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el jefe de vez en cuando lance un rayo láser celeste que haga que el jugador pierda 50 de vida siempre y cuando se esté moviendo, si no se mueve no recibe daño ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz que la recarga del ataque final, también sea rojo.
User prompt
Es que cuando el jefe pierda 1000 de vida, cuando pierde 1000 de vida haga un ataque final que abarca todo el mapa. O sea, el ataque final abarca todo el mapa.
User prompt
Es que haz que el ataque final sea de color rojo.
User prompt
cuando el jefe pierda 1000 de vida a un ataque final donde abarca toda la zona y hace daño pero si el jugador le logra disparar aunque sea una vez en ese periodo el jefe no podrá usar ese ataque ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Es que cada 5 segundos el jefe se queda quieto por un segundo con un cuadradito amarillo y lance un ataque que quite 5 de vida si el jugador lo toca. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Vaya subiendo y bajando lentamente mientras se mueva. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Es que el jefe se mueve de lado a lado.
User prompt
frecuencia sea de 20 y que haga un poquito menos daño, la mitad.
User prompt
Que los ataques del jugador sean un poquito más frecuentes, o sea, que ataquen un poquito más rápido, o sea, tampoco para tanto.
User prompt
Haz que los ataques vayan en 0.5
User prompt
Haz que los ataques del jugador vayan más rápido.
User prompt
a que los ataques del jugador sean menos frecuentes y también que sean más chiquitos y largos. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
El ataque del jugador va a ser muy rápido.
User prompt
horas que el jugador ataque solo.
User prompt
Ah, elimina el botón de atacar.
User prompt
Los ataques del jugador pasan automático y elimina el botón de atacar.
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(attackButton, {' Line Number: 222 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: tween.create is not a function' in or related to this line: 'tween.create(attackButton).to({' Line Number: 222
User prompt
vuelve a intentar porque hubo un error en el código
User prompt
Boss Battle Arena
Initial prompt
haz un combate donde haya un jefe que tenga 10.000 de vida pero que también nos pueda atacar y el jugador que tenga un botón que haga que lance un ataque que haga 100 de daño
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 10000; self.health = 10000; self.attackCooldown = 0; self.attackInterval = 180; // 3 seconds at 60fps self.moveDirection = 1; // 1 for right, -1 for left self.moveSpeed = 2; self.leftBound = 200; self.rightBound = 1848; self.verticalDirection = 1; // 1 for down, -1 for up self.verticalSpeed = 1; self.topBound = 300; self.bottomBound = 500; self.specialAttackTimer = 0; self.specialAttackInterval = 300; // 5 seconds at 60fps self.isCharging = false; self.chargeTime = 0; self.maxChargeTime = 60; // 1 second at 60fps self.indicator = null; self.finalAttackTriggered = false; self.isFinalAttacking = false; self.finalAttackTime = 0; self.maxFinalAttackTime = 180; // 3 seconds at 60fps self.finalAttackCanceled = false; self.laserAttackTimer = 0; self.laserAttackInterval = 900; // 15 seconds at 60fps self.laserCooldown = 0; // Cooldown timer for laser attacks self.laserCooldownTime = 300; // 5 seconds cooldown at 60fps self.isChargingLaser = false; // New state for laser charging self.laserChargeTime = 0; // Timer for laser charging self.maxLaserChargeTime = 180; // 3 seconds at 60fps self.laserUsed = false; // Track if laser has been used (only once allowed) self.takeDamage = function (damage) { self.health -= damage; if (self.health < 0) self.health = 0; // Flash red when taking damage tween(bossGraphics, { tint: 0xff8888 }, { duration: 100, onFinish: function onFinish() { tween(bossGraphics, { tint: 0xffffff }, { duration: 100 }); } }); }; self.attack = function () { return { x: self.x, y: self.y + 100, damage: 1 }; }; self.specialAttack = function () { return { x: self.x, y: self.y + 100, damage: 1 }; }; self.startFinalAttack = function () { self.isFinalAttacking = true; self.finalAttackTime = 0; self.finalAttackCanceled = false; // Boss stops moving during final attack }; self.cancelFinalAttack = function () { self.finalAttackCanceled = true; self.isFinalAttacking = false; self.finalAttackTime = 0; }; self.finalAttack = function () { return { x: 1024, // Center of screen horizontally y: 1366, // Center vertically to cover entire map damage: 1 }; }; self.laserAttack = function () { return { x: self.x, y: 1366, // Center vertically to cover full screen damage: 1 }; }; self.update = function () { // Check for final attack trigger (when health drops to 1000 or below) if (self.health <= 1000 && !self.finalAttackTriggered && !self.isFinalAttacking) { self.finalAttackTriggered = true; self.startFinalAttack(); return "finalAttack"; } // Handle final attack if (self.isFinalAttacking && !self.finalAttackCanceled) { self.finalAttackTime++; if (self.finalAttackTime >= self.maxFinalAttackTime) { // Final attack completes - deal damage to entire screen self.isFinalAttacking = false; return "finalAttackComplete"; } return false; // Boss doesn't move during final attack } // Handle special attack timing if (!self.isFinalAttacking) { self.specialAttackTimer++; // Fast special attack mode when boss health drops to half or below var currentSpecialInterval = self.health <= self.maxHealth / 2 ? 100 : self.specialAttackInterval; // Much faster when health <= 5000 // Check if it's time for special attack if (self.specialAttackTimer >= currentSpecialInterval && !self.isCharging) { self.isCharging = true; self.chargeTime = 0; // Create indicator if (!self.indicator) { self.indicator = self.addChild(LK.getAsset('bossSpecialIndicator', { anchorX: 0.5, anchorY: 0.5 })); self.indicator.y = 80; // Position above boss } } // Handle laser attack timing - only in fast mode if (self.health <= self.maxHealth / 2) { self.laserAttackTimer++; // Update laser cooldown if (self.laserCooldown > 0) { self.laserCooldown--; } // Only allow laser attack once when entering fast mode if (self.laserAttackTimer >= 300 && self.laserCooldown <= 0 && !self.isChargingLaser && !self.laserUsed) { self.isChargingLaser = true; self.laserChargeTime = 0; self.laserAttackTimer = 0; } } } // Handle laser charging phase (boss stops moving) if (self.isChargingLaser) { self.laserChargeTime++; // Make boss flash to indicate laser charging tween.stop(bossGraphics, { tint: true }); if (self.laserChargeTime % 30 === 0) { // Flash every 0.5 seconds tween(bossGraphics, { tint: 0xffff00 }, { duration: 150 }); } if (self.laserChargeTime >= self.maxLaserChargeTime) { // End laser charging, launch laser attack self.isChargingLaser = false; self.laserChargeTime = 0; self.laserCooldown = self.laserCooldownTime; // Start cooldown self.laserUsed = true; // Mark laser as used tween(bossGraphics, { tint: 0xffffff }, { duration: 100 }); // Reset boss color return "laser"; } } else if (self.isCharging) { self.chargeTime++; // Make indicator blink if (self.indicator) { self.indicator.alpha = Math.sin(self.chargeTime * 0.3) * 0.5 + 0.5; } if (self.chargeTime >= self.maxChargeTime) { // End charging, launch special attack self.isCharging = false; self.specialAttackTimer = 0; // Remove indicator if (self.indicator) { self.indicator.destroy(); self.indicator = null; } return "special"; // Signal to create special attack } } else if (!self.isFinalAttacking) { // Normal movement only when not charging and not doing final attack // Handle horizontal movement self.x += self.moveSpeed * self.moveDirection; // Change direction when hitting bounds if (self.x <= self.leftBound) { self.moveDirection = 1; // Move right self.x = self.leftBound; } else if (self.x >= self.rightBound) { self.moveDirection = -1; // Move left self.x = self.rightBound; } // Handle vertical movement self.y += self.verticalSpeed * self.verticalDirection; // Change direction when hitting vertical bounds if (self.y <= self.topBound) { self.verticalDirection = 1; // Move down self.y = self.topBound; } else if (self.y >= self.bottomBound) { self.verticalDirection = -1; // Move up self.y = self.bottomBound; } } // Normal attacks (only when not charging, not charging laser and not doing final attack) if (!self.isCharging && !self.isChargingLaser && !self.isFinalAttacking) { self.attackCooldown++; // Fast attack mode when boss health drops to half or below var currentAttackInterval = self.health <= self.maxHealth / 2 ? 10 : self.attackInterval; // Super fast when health <= 5000 if (self.attackCooldown >= currentAttackInterval) { self.attackCooldown = 0; return true; // Signal to create attack } } return false; }; return self; }); var BossAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('bossAttack', { anchorX: 0.5, anchorY: 0.5 }); // Speed increases in fast mode when boss health is low self.speed = boss && boss.health <= boss.maxHealth / 2 ? 8 : 4; self.damage = 1; self.update = function () { self.y += self.speed; }; return self; }); var BossFinalAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('bossFinalAttack', { anchorX: 0.5, anchorY: 0.5 }); attackGraphics.alpha = 0.4; // Semi-transparent red overlay covering entire screen self.damage = 1; self.lifeTime = 0; self.maxLifeTime = 60; // 1 second visible self.update = function () { self.lifeTime++; // Pulsing effect for entire screen coverage attackGraphics.alpha = 0.4 + Math.sin(self.lifeTime * 0.3) * 0.3; }; return self; }); var BossLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('bossLaser', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 1; self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds visible self.update = function () { self.lifeTime++; // Follow boss position horizontally self.x = boss.x; // Fade out effect in the last 3 seconds (180 frames) if (self.lifeTime >= self.maxLifeTime - 180) { var fadeProgress = (self.lifeTime - (self.maxLifeTime - 180)) / 180; laserGraphics.alpha = 0.7 * (1 - fadeProgress); } else { // Pulsing effect laserGraphics.alpha = 0.7 + Math.sin(self.lifeTime * 0.4) * 0.3; } }; return self; }); var BossSpecialAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('bossSpecialAttack', { anchorX: 0.5, anchorY: 0.5 }); // Speed increases in fast mode when boss health is low self.speed = boss && boss.health <= boss.maxHealth / 2 ? 12 : 6; self.damage = 1; self.update = function () { self.y += self.speed; }; return self; }); // Game variables var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 1; self.health = 1; self.attackDamage = 50; self.takeDamage = function (damage) { self.health -= damage; if (self.health < 0) self.health = 0; // Flash red when taking damage tween(playerGraphics, { tint: 0xff8888 }, { duration: 100, onFinish: function onFinish() { tween(playerGraphics, { tint: 0xffffff }, { duration: 100 }); } }); }; self.attack = function () { return { x: self.x, y: self.y - 50, damage: self.attackDamage }; }; return self; }); var PlayerAttack = Container.expand(function () { var self = Container.call(this); var attackGraphics = self.attachAsset('playerAttack', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -24; self.damage = 50; self.update = function () { self.y += self.speed; }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.speed = Math.random() * 2 + 1; // Random speed between 1-3 self.twinkleTime = 0; self.update = function () { self.y += self.speed; // Enhanced twinkling effect with random timing self.twinkleTime++; var twinkleIntensity = 0.4 + Math.sin(self.twinkleTime * (0.05 + Math.random() * 0.1)) * 0.3; starGraphics.alpha = Math.max(0.2, twinkleIntensity); // Add occasional bright flash if (Math.random() < 0.002) { tween(starGraphics, { alpha: 1.0, scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(starGraphics, { alpha: twinkleIntensity, scaleX: 1.0, scaleY: 1.0 }, { duration: 300 }); } }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game variables // Game state var gameStarted = false; var startScreen = null; var startButton = null; var titleText = null; var instructionText = null; var explanationScreen = null; var showingExplanation = false; // Boss assets // Player assets // Attack button // Attack effects // Sounds var boss; var player; var playerAttacks = []; var bossAttacks = []; var bossSpecialAttacks = []; var bossFinalAttacks = []; var bossLasers = []; var stars = []; var startScreenStars = []; var dragNode = null; var playerLastX = 0; var playerLastY = 0; // Health bars var bossHealthBarBg, bossHealthBar; var playerHealthBarBg, playerHealthBar; // Health text var bossHealthText, playerHealthText; // Create start screen startScreen = game.addChild(new Container()); // Add immediate star burst effect for (var burstIndex = 0; burstIndex < 20; burstIndex++) { var burstStar = new Star(); burstStar.x = 1024 + (Math.random() - 0.5) * 400; burstStar.y = 1366 + (Math.random() - 0.5) * 400; burstStar.speed = Math.random() * 0.5 + 0.2; var burstGraphics = burstStar.children[0]; burstGraphics.alpha = 0; burstGraphics.scaleX = 2; burstGraphics.scaleY = 2; // Animate burst effect tween(burstGraphics, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800 + Math.random() * 600, easing: tween.easeOut, onFinish: function onFinish() { // Add extra twinkle after burst tween(burstGraphics, { alpha: 0.3, scaleX: 1.5, scaleY: 1.5 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(burstGraphics, { alpha: 0.7, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeInOut }); } }); } }); startScreenStars.push(burstStar); startScreen.addChild(burstStar); } // Create initial stars for start screen background for (var starIndex = 0; starIndex < 50; starIndex++) { var startStar = new Star(); startStar.x = Math.random() * 2048; startStar.y = Math.random() * 2732; startStar.speed = Math.random() * 1 + 0.5; // Slower speed for start screen // Add immediate twinkling effect with random timing startStar.twinkleTime = Math.random() * 100; // Add enhanced initial visibility with tween effect var starGraphics = startStar.children[0]; starGraphics.alpha = 0; tween(starGraphics, { alpha: 0.6 + Math.random() * 0.4, scaleX: 0.8 + Math.random() * 0.4, scaleY: 0.8 + Math.random() * 0.4 }, { duration: 500 + Math.random() * 1000, easing: tween.easeOut }); startScreenStars.push(startStar); startScreen.addChild(startStar); } // Create title text titleText = new Text2('Space Ranger', { size: 120, fill: 0xFFFF00 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; startScreen.addChild(titleText); // Create instruction text instructionText = new Text2('Arrastra para moverte\nDerrota al jefe para ganar\n¡Ten cuidado con sus ataques!', { size: 60, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 1200; startScreen.addChild(instructionText); // Create start button startButton = new Text2('JUGAR', { size: 100, fill: 0x00FF00 }); startButton.anchor.set(0.5, 0.5); startButton.x = 900; startButton.y = 1600; startScreen.addChild(startButton); // Create explanation button var explanationButton = new Text2('?', { size: 100, fill: 0x4A90E2 }); explanationButton.anchor.set(0.5, 0.5); explanationButton.x = 1148; explanationButton.y = 1600; startScreen.addChild(explanationButton); // Add enhanced pulsing effect to start button with color changes and rotation var _buttonPulse = function buttonPulse() { if (startButton && !gameStarted) { // First phase: scale up with color change to bright yellow and slight rotation tween(startButton, { scaleX: 1.4, scaleY: 1.4, tint: 0xFFFF00, rotation: 0.1 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { // Second phase: scale down with color change to bright green and rotation back tween(startButton, { scaleX: 1.0, scaleY: 1.0, tint: 0x00FF88, rotation: -0.05 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { // Third phase: final color pulse back to original green tween(startButton, { tint: 0x00FF00, rotation: 0 }, { duration: 300, easing: tween.easeInOut, onFinish: _buttonPulse }); } }); } }); } }; _buttonPulse(); // Add pulsing effect to explanation button var _explanationPulse = function explanationPulse() { if (explanationButton && !gameStarted && !showingExplanation) { tween(explanationButton, { scaleX: 1.3, scaleY: 1.3, tint: 0x87CEEB }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { tween(explanationButton, { scaleX: 1.0, scaleY: 1.0, tint: 0x4A90E2 }, { duration: 600, easing: tween.easeIn, onFinish: _explanationPulse }); } }); } }; _explanationPulse(); // Start button click handler startButton.down = function (x, y, obj) { if (!gameStarted && !showingExplanation) { gameStarted = true; // Clean up start screen stars for (var cleanupIndex = startScreenStars.length - 1; cleanupIndex >= 0; cleanupIndex--) { startScreenStars[cleanupIndex].destroy(); } startScreenStars = []; startScreen.destroy(); initializeGame(); } }; // Explanation button click handler explanationButton.down = function (x, y, obj) { if (!gameStarted && !showingExplanation) { showingExplanation = true; createExplanationScreen(); } }; // Function to create explanation screen function createExplanationScreen() { explanationScreen = game.addChild(new Container()); explanationScreen.alpha = 0; tween(explanationScreen, { alpha: 1 }, { duration: 300 }); // Semi-transparent background var overlay = explanationScreen.addChild(LK.getAsset('bossFinalAttack', { anchorX: 0.5, anchorY: 0.5 })); overlay.x = 1024; overlay.y = 1366; overlay.alpha = 0.8; overlay.tint = 0x000033; // Title var explanationTitle = new Text2('GUÍA DEL JUEGO', { size: 80, fill: 0xFFFF00 }); explanationTitle.anchor.set(0.5, 0.5); explanationTitle.x = 1024; explanationTitle.y = 400; explanationScreen.addChild(explanationTitle); // Game mechanics explanation var mechanicsText = new Text2('CONTROLES:\n• Arrastra para mover tu nave\n• Disparas automáticamente\n\nEL JEFE:\n• Tiene 10,000 puntos de vida\n• Se mueve por la pantalla\n• Tiene múltiples tipos de ataque', { size: 45, fill: 0xFFFFFF }); mechanicsText.anchor.set(0.5, 0.5); mechanicsText.x = 1024; mechanicsText.y = 800; explanationScreen.addChild(mechanicsText); // Boss attacks explanation var attacksText = new Text2('ATAQUES DEL JEFE:\n\n• ATAQUE NORMAL: Proyectiles rojos (1 daño)\n• ATAQUE ESPECIAL: Proyectiles pequeños rápidos (1 daño)\n• ATAQUE LÁSER: Rayo vertical que te sigue (1 daño)\n• ATAQUE FINAL: Pantalla roja completa (1 daño)', { size: 40, fill: 0xFF8888 }); attacksText.anchor.set(0.5, 0.5); attacksText.x = 1024; attacksText.y = 1200; explanationScreen.addChild(attacksText); // Special mechanics var specialText = new Text2('MECÁNICAS ESPECIALES:\n\n• Cuando el jefe tiene ≤5000 vida: MODO RÁPIDO\n - Ataques más frecuentes y rápidos\n - Puede usar el ataque láser\n\n• Cuando el jefe tiene ≤1000 vida:\n - Intenta el ATAQUE FINAL mortal\n - ¡Dispárale para cancelarlo!', { size: 38, fill: 0x88FF88 }); specialText.anchor.set(0.5, 0.5); specialText.x = 1024; specialText.y = 1650; explanationScreen.addChild(specialText); // Victory condition var victoryText = new Text2('OBJETIVO: Reduce la vida del jefe a 0 para ganar\nSOBREVIVE: Tienes solo 1 punto de vida', { size: 42, fill: 0xFFD700 }); victoryText.anchor.set(0.5, 0.5); victoryText.x = 1024; victoryText.y = 2000; explanationScreen.addChild(victoryText); // Back button var backButton = new Text2('VOLVER', { size: 70, fill: 0xFF6666 }); backButton.anchor.set(0.5, 0.5); backButton.x = 1024; backButton.y = 2300; explanationScreen.addChild(backButton); // Back button animation var _backPulse = function backPulse() { if (backButton && showingExplanation) { tween(backButton, { scaleX: 1.2, scaleY: 1.2, tint: 0xFF8888 }, { duration: 600, onFinish: function onFinish() { tween(backButton, { scaleX: 1.0, scaleY: 1.0, tint: 0xFF6666 }, { duration: 400, onFinish: _backPulse }); } }); } }; _backPulse(); // Back button click handler backButton.down = function (x, y, obj) { if (showingExplanation) { tween(explanationScreen, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { explanationScreen.destroy(); explanationScreen = null; showingExplanation = false; } }); } }; } // Function to initialize game elements function initializeGame() { // Initialize boss boss = game.addChild(new Boss()); boss.x = 1024; boss.y = 400; // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 2200; playerLastX = player.x; playerLastY = player.y; // Create boss health bar bossHealthBarBg = game.addChild(LK.getAsset('bossHealthBarBg', { anchorX: 0.5, anchorY: 0.5 })); bossHealthBarBg.x = 1024; bossHealthBarBg.y = 200; bossHealthBar = game.addChild(LK.getAsset('bossHealthBar', { anchorX: 0.5, anchorY: 0.5 })); bossHealthBar.x = 1024; bossHealthBar.y = 200; // Create player health bar playerHealthBarBg = game.addChild(LK.getAsset('playerHealthBarBg', { anchorX: 0.5, anchorY: 0.5 })); playerHealthBarBg.x = 1024; playerHealthBarBg.y = 2500; playerHealthBar = game.addChild(LK.getAsset('playerHealthBar', { anchorX: 0.5, anchorY: 0.5 })); playerHealthBar.x = 1024; playerHealthBar.y = 2500; // Create health text bossHealthText = new Text2('10000/10000', { size: 40, fill: 0xFFFFFF }); bossHealthText.anchor.set(0.5, 0.5); bossHealthText.x = 1024; bossHealthText.y = 160; game.addChild(bossHealthText); playerHealthText = new Text2('1/1', { size: 30, fill: 0xFFFFFF }); playerHealthText.anchor.set(0.5, 0.5); playerHealthText.x = 1024; playerHealthText.y = 2540; game.addChild(playerHealthText); } // Player movement game.move = function (x, y, obj) { if (gameStarted && dragNode) { dragNode.x = x; dragNode.y = y; // Keep player within bounds if (dragNode.x < 50) dragNode.x = 50; if (dragNode.x > 1998) dragNode.x = 1998; if (dragNode.y < 800) dragNode.y = 800; if (dragNode.y > 2600) dragNode.y = 2600; } }; game.down = function (x, y, obj) { if (gameStarted) { dragNode = player; game.move(x, y, obj); } }; game.up = function (x, y, obj) { if (gameStarted) { dragNode = null; } }; // Main game update loop game.update = function () { // Only run game logic if game has started if (!gameStarted) { // Update start screen stars for (var startStarIndex = startScreenStars.length - 1; startStarIndex >= 0; startStarIndex--) { var startStar = startScreenStars[startStarIndex]; // Remove if off screen if (startStar.y > 2780) { startStar.destroy(); startScreenStars.splice(startStarIndex, 1); } } // Spawn new stars for start screen more frequently and consistently if (LK.ticks % 15 == 0 && Math.random() < 0.9) { var newStartStar = new Star(); newStartStar.x = Math.random() * 2048; newStartStar.y = -10; newStartStar.speed = Math.random() * 1.5 + 0.8; // Slightly faster and more visible // Add immediate fade-in effect for new stars var newStarGraphics = newStartStar.children[0]; newStarGraphics.alpha = 0; tween(newStarGraphics, { alpha: 0.5 + Math.random() * 0.5 }, { duration: 300 + Math.random() * 500, easing: tween.easeOut }); startScreenStars.push(newStartStar); startScreen.addChild(newStartStar); } return; } // Update player attacks for (var i = playerAttacks.length - 1; i >= 0; i--) { var attack = playerAttacks[i]; // Check if attack hit boss if (attack.intersects(boss)) { boss.takeDamage(attack.damage); // Cancel final attack if boss is doing it if (boss.isFinalAttacking && !boss.finalAttackCanceled) { boss.cancelFinalAttack(); } attack.destroy(); playerAttacks.splice(i, 1); continue; } // Remove if off screen if (attack.y < -50) { attack.destroy(); playerAttacks.splice(i, 1); } } // Update boss attacks for (var j = bossAttacks.length - 1; j >= 0; j--) { var bossAttack = bossAttacks[j]; // Check if attack hit player if (bossAttack.intersects(player)) { player.takeDamage(bossAttack.damage); bossAttack.destroy(); bossAttacks.splice(j, 1); continue; } // Remove if off screen if (bossAttack.y > 2780) { bossAttack.destroy(); bossAttacks.splice(j, 1); } } // Update boss special attacks for (var k = bossSpecialAttacks.length - 1; k >= 0; k--) { var specialAttack = bossSpecialAttacks[k]; // Check if special attack hit player if (specialAttack.intersects(player)) { player.takeDamage(specialAttack.damage); specialAttack.destroy(); bossSpecialAttacks.splice(k, 1); continue; } // Remove if off screen if (specialAttack.y > 2780) { specialAttack.destroy(); bossSpecialAttacks.splice(k, 1); } } // Player automatic attack - fast mode when health is half or below var attackInterval = player.health <= player.maxHealth / 2 ? 3 : 20; // Super fast when health <= 0.5 if (LK.ticks % attackInterval == 0) { var attackData = player.attack(); var newPlayerAttack = new PlayerAttack(); newPlayerAttack.x = attackData.x; newPlayerAttack.y = attackData.y; playerAttacks.push(newPlayerAttack); game.addChild(newPlayerAttack); } // Update boss final attacks for (var l = bossFinalAttacks.length - 1; l >= 0; l--) { var finalAttack = bossFinalAttacks[l]; // Check if final attack hit player (covers entire screen) if (finalAttack.intersects(player)) { player.takeDamage(finalAttack.damage); } // Remove after lifetime expires if (finalAttack.lifeTime >= finalAttack.maxLifeTime) { finalAttack.destroy(); bossFinalAttacks.splice(l, 1); } } // Update boss laser attacks for (var m = bossLasers.length - 1; m >= 0; m--) { var laser = bossLasers[m]; // Check if laser hit player AND player is moving var playerIsMoving = player.x !== playerLastX || player.y !== playerLastY; if (laser.intersects(player) && playerIsMoving) { player.takeDamage(laser.damage); } // Remove after lifetime expires if (laser.lifeTime >= laser.maxLifeTime) { laser.destroy(); bossLasers.splice(m, 1); } } // Update and spawn stars for (var s = stars.length - 1; s >= 0; s--) { var star = stars[s]; // Remove if off screen if (star.y > 2780) { star.destroy(); stars.splice(s, 1); } } // Spawn new stars randomly if (LK.ticks % 15 == 0 && Math.random() < 0.7) { var newStar = new Star(); newStar.x = Math.random() * 2048; newStar.y = -10; stars.push(newStar); game.addChild(newStar); } // Update player movement tracking playerLastX = player.x; playerLastY = player.y; // Boss attack logic var bossUpdateResult = boss.update(); if (bossUpdateResult === true) { var attackData = boss.attack(); var newBossAttack = new BossAttack(); newBossAttack.x = attackData.x; newBossAttack.y = attackData.y; bossAttacks.push(newBossAttack); game.addChild(newBossAttack); } else if (bossUpdateResult === "special") { var specialAttackData = boss.specialAttack(); var newSpecialAttack = new BossSpecialAttack(); newSpecialAttack.x = specialAttackData.x; newSpecialAttack.y = specialAttackData.y; bossSpecialAttacks.push(newSpecialAttack); game.addChild(newSpecialAttack); } else if (bossUpdateResult === "finalAttack") { // Flash screen red to indicate final attack starting LK.effects.flashScreen(0xff0000, 500); } else if (bossUpdateResult === "finalAttackComplete") { // Create final attack that covers entire map/screen var finalAttackData = boss.finalAttack(); var newFinalAttack = new BossFinalAttack(); newFinalAttack.x = 1024; // Center horizontally to cover entire map width newFinalAttack.y = 1366; // Center vertically to cover entire map height bossFinalAttacks.push(newFinalAttack); game.addChild(newFinalAttack); } else if (bossUpdateResult === "laser") { // Create laser attack var laserAttackData = boss.laserAttack(); var newLaser = new BossLaser(); newLaser.x = laserAttackData.x; newLaser.y = laserAttackData.y; bossLasers.push(newLaser); game.addChild(newLaser); } // Update health bars var bossHealthPercent = boss.health / boss.maxHealth; bossHealthBar.scaleX = bossHealthPercent; var playerHealthPercent = player.health / player.maxHealth; playerHealthBar.scaleX = playerHealthPercent; // Update health text bossHealthText.setText(boss.health + '/' + boss.maxHealth); playerHealthText.setText(player.health + '/' + player.maxHealth); // Check win condition if (boss.health <= 0) { LK.showYouWin(); } // Check lose condition if (player.health <= 0) { LK.showGameOver(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 10000;
self.health = 10000;
self.attackCooldown = 0;
self.attackInterval = 180; // 3 seconds at 60fps
self.moveDirection = 1; // 1 for right, -1 for left
self.moveSpeed = 2;
self.leftBound = 200;
self.rightBound = 1848;
self.verticalDirection = 1; // 1 for down, -1 for up
self.verticalSpeed = 1;
self.topBound = 300;
self.bottomBound = 500;
self.specialAttackTimer = 0;
self.specialAttackInterval = 300; // 5 seconds at 60fps
self.isCharging = false;
self.chargeTime = 0;
self.maxChargeTime = 60; // 1 second at 60fps
self.indicator = null;
self.finalAttackTriggered = false;
self.isFinalAttacking = false;
self.finalAttackTime = 0;
self.maxFinalAttackTime = 180; // 3 seconds at 60fps
self.finalAttackCanceled = false;
self.laserAttackTimer = 0;
self.laserAttackInterval = 900; // 15 seconds at 60fps
self.laserCooldown = 0; // Cooldown timer for laser attacks
self.laserCooldownTime = 300; // 5 seconds cooldown at 60fps
self.isChargingLaser = false; // New state for laser charging
self.laserChargeTime = 0; // Timer for laser charging
self.maxLaserChargeTime = 180; // 3 seconds at 60fps
self.laserUsed = false; // Track if laser has been used (only once allowed)
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health < 0) self.health = 0;
// Flash red when taking damage
tween(bossGraphics, {
tint: 0xff8888
}, {
duration: 100,
onFinish: function onFinish() {
tween(bossGraphics, {
tint: 0xffffff
}, {
duration: 100
});
}
});
};
self.attack = function () {
return {
x: self.x,
y: self.y + 100,
damage: 1
};
};
self.specialAttack = function () {
return {
x: self.x,
y: self.y + 100,
damage: 1
};
};
self.startFinalAttack = function () {
self.isFinalAttacking = true;
self.finalAttackTime = 0;
self.finalAttackCanceled = false;
// Boss stops moving during final attack
};
self.cancelFinalAttack = function () {
self.finalAttackCanceled = true;
self.isFinalAttacking = false;
self.finalAttackTime = 0;
};
self.finalAttack = function () {
return {
x: 1024,
// Center of screen horizontally
y: 1366,
// Center vertically to cover entire map
damage: 1
};
};
self.laserAttack = function () {
return {
x: self.x,
y: 1366,
// Center vertically to cover full screen
damage: 1
};
};
self.update = function () {
// Check for final attack trigger (when health drops to 1000 or below)
if (self.health <= 1000 && !self.finalAttackTriggered && !self.isFinalAttacking) {
self.finalAttackTriggered = true;
self.startFinalAttack();
return "finalAttack";
}
// Handle final attack
if (self.isFinalAttacking && !self.finalAttackCanceled) {
self.finalAttackTime++;
if (self.finalAttackTime >= self.maxFinalAttackTime) {
// Final attack completes - deal damage to entire screen
self.isFinalAttacking = false;
return "finalAttackComplete";
}
return false; // Boss doesn't move during final attack
}
// Handle special attack timing
if (!self.isFinalAttacking) {
self.specialAttackTimer++;
// Fast special attack mode when boss health drops to half or below
var currentSpecialInterval = self.health <= self.maxHealth / 2 ? 100 : self.specialAttackInterval; // Much faster when health <= 5000
// Check if it's time for special attack
if (self.specialAttackTimer >= currentSpecialInterval && !self.isCharging) {
self.isCharging = true;
self.chargeTime = 0;
// Create indicator
if (!self.indicator) {
self.indicator = self.addChild(LK.getAsset('bossSpecialIndicator', {
anchorX: 0.5,
anchorY: 0.5
}));
self.indicator.y = 80; // Position above boss
}
}
// Handle laser attack timing - only in fast mode
if (self.health <= self.maxHealth / 2) {
self.laserAttackTimer++;
// Update laser cooldown
if (self.laserCooldown > 0) {
self.laserCooldown--;
}
// Only allow laser attack once when entering fast mode
if (self.laserAttackTimer >= 300 && self.laserCooldown <= 0 && !self.isChargingLaser && !self.laserUsed) {
self.isChargingLaser = true;
self.laserChargeTime = 0;
self.laserAttackTimer = 0;
}
}
}
// Handle laser charging phase (boss stops moving)
if (self.isChargingLaser) {
self.laserChargeTime++;
// Make boss flash to indicate laser charging
tween.stop(bossGraphics, {
tint: true
});
if (self.laserChargeTime % 30 === 0) {
// Flash every 0.5 seconds
tween(bossGraphics, {
tint: 0xffff00
}, {
duration: 150
});
}
if (self.laserChargeTime >= self.maxLaserChargeTime) {
// End laser charging, launch laser attack
self.isChargingLaser = false;
self.laserChargeTime = 0;
self.laserCooldown = self.laserCooldownTime; // Start cooldown
self.laserUsed = true; // Mark laser as used
tween(bossGraphics, {
tint: 0xffffff
}, {
duration: 100
}); // Reset boss color
return "laser";
}
} else if (self.isCharging) {
self.chargeTime++;
// Make indicator blink
if (self.indicator) {
self.indicator.alpha = Math.sin(self.chargeTime * 0.3) * 0.5 + 0.5;
}
if (self.chargeTime >= self.maxChargeTime) {
// End charging, launch special attack
self.isCharging = false;
self.specialAttackTimer = 0;
// Remove indicator
if (self.indicator) {
self.indicator.destroy();
self.indicator = null;
}
return "special"; // Signal to create special attack
}
} else if (!self.isFinalAttacking) {
// Normal movement only when not charging and not doing final attack
// Handle horizontal movement
self.x += self.moveSpeed * self.moveDirection;
// Change direction when hitting bounds
if (self.x <= self.leftBound) {
self.moveDirection = 1; // Move right
self.x = self.leftBound;
} else if (self.x >= self.rightBound) {
self.moveDirection = -1; // Move left
self.x = self.rightBound;
}
// Handle vertical movement
self.y += self.verticalSpeed * self.verticalDirection;
// Change direction when hitting vertical bounds
if (self.y <= self.topBound) {
self.verticalDirection = 1; // Move down
self.y = self.topBound;
} else if (self.y >= self.bottomBound) {
self.verticalDirection = -1; // Move up
self.y = self.bottomBound;
}
}
// Normal attacks (only when not charging, not charging laser and not doing final attack)
if (!self.isCharging && !self.isChargingLaser && !self.isFinalAttacking) {
self.attackCooldown++;
// Fast attack mode when boss health drops to half or below
var currentAttackInterval = self.health <= self.maxHealth / 2 ? 10 : self.attackInterval; // Super fast when health <= 5000
if (self.attackCooldown >= currentAttackInterval) {
self.attackCooldown = 0;
return true; // Signal to create attack
}
}
return false;
};
return self;
});
var BossAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('bossAttack', {
anchorX: 0.5,
anchorY: 0.5
});
// Speed increases in fast mode when boss health is low
self.speed = boss && boss.health <= boss.maxHealth / 2 ? 8 : 4;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var BossFinalAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('bossFinalAttack', {
anchorX: 0.5,
anchorY: 0.5
});
attackGraphics.alpha = 0.4; // Semi-transparent red overlay covering entire screen
self.damage = 1;
self.lifeTime = 0;
self.maxLifeTime = 60; // 1 second visible
self.update = function () {
self.lifeTime++;
// Pulsing effect for entire screen coverage
attackGraphics.alpha = 0.4 + Math.sin(self.lifeTime * 0.3) * 0.3;
};
return self;
});
var BossLaser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('bossLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 1;
self.lifeTime = 0;
self.maxLifeTime = 600; // 10 seconds visible
self.update = function () {
self.lifeTime++;
// Follow boss position horizontally
self.x = boss.x;
// Fade out effect in the last 3 seconds (180 frames)
if (self.lifeTime >= self.maxLifeTime - 180) {
var fadeProgress = (self.lifeTime - (self.maxLifeTime - 180)) / 180;
laserGraphics.alpha = 0.7 * (1 - fadeProgress);
} else {
// Pulsing effect
laserGraphics.alpha = 0.7 + Math.sin(self.lifeTime * 0.4) * 0.3;
}
};
return self;
});
var BossSpecialAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('bossSpecialAttack', {
anchorX: 0.5,
anchorY: 0.5
});
// Speed increases in fast mode when boss health is low
self.speed = boss && boss.health <= boss.maxHealth / 2 ? 12 : 6;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Game variables
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 1;
self.health = 1;
self.attackDamage = 50;
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health < 0) self.health = 0;
// Flash red when taking damage
tween(playerGraphics, {
tint: 0xff8888
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerGraphics, {
tint: 0xffffff
}, {
duration: 100
});
}
});
};
self.attack = function () {
return {
x: self.x,
y: self.y - 50,
damage: self.attackDamage
};
};
return self;
});
var PlayerAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('playerAttack', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -24;
self.damage = 50;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 2 + 1; // Random speed between 1-3
self.twinkleTime = 0;
self.update = function () {
self.y += self.speed;
// Enhanced twinkling effect with random timing
self.twinkleTime++;
var twinkleIntensity = 0.4 + Math.sin(self.twinkleTime * (0.05 + Math.random() * 0.1)) * 0.3;
starGraphics.alpha = Math.max(0.2, twinkleIntensity);
// Add occasional bright flash
if (Math.random() < 0.002) {
tween(starGraphics, {
alpha: 1.0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(starGraphics, {
alpha: twinkleIntensity,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
// Game state
var gameStarted = false;
var startScreen = null;
var startButton = null;
var titleText = null;
var instructionText = null;
var explanationScreen = null;
var showingExplanation = false;
// Boss assets
// Player assets
// Attack button
// Attack effects
// Sounds
var boss;
var player;
var playerAttacks = [];
var bossAttacks = [];
var bossSpecialAttacks = [];
var bossFinalAttacks = [];
var bossLasers = [];
var stars = [];
var startScreenStars = [];
var dragNode = null;
var playerLastX = 0;
var playerLastY = 0;
// Health bars
var bossHealthBarBg, bossHealthBar;
var playerHealthBarBg, playerHealthBar;
// Health text
var bossHealthText, playerHealthText;
// Create start screen
startScreen = game.addChild(new Container());
// Add immediate star burst effect
for (var burstIndex = 0; burstIndex < 20; burstIndex++) {
var burstStar = new Star();
burstStar.x = 1024 + (Math.random() - 0.5) * 400;
burstStar.y = 1366 + (Math.random() - 0.5) * 400;
burstStar.speed = Math.random() * 0.5 + 0.2;
var burstGraphics = burstStar.children[0];
burstGraphics.alpha = 0;
burstGraphics.scaleX = 2;
burstGraphics.scaleY = 2;
// Animate burst effect
tween(burstGraphics, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800 + Math.random() * 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Add extra twinkle after burst
tween(burstGraphics, {
alpha: 0.3,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(burstGraphics, {
alpha: 0.7,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
});
startScreenStars.push(burstStar);
startScreen.addChild(burstStar);
}
// Create initial stars for start screen background
for (var starIndex = 0; starIndex < 50; starIndex++) {
var startStar = new Star();
startStar.x = Math.random() * 2048;
startStar.y = Math.random() * 2732;
startStar.speed = Math.random() * 1 + 0.5; // Slower speed for start screen
// Add immediate twinkling effect with random timing
startStar.twinkleTime = Math.random() * 100;
// Add enhanced initial visibility with tween effect
var starGraphics = startStar.children[0];
starGraphics.alpha = 0;
tween(starGraphics, {
alpha: 0.6 + Math.random() * 0.4,
scaleX: 0.8 + Math.random() * 0.4,
scaleY: 0.8 + Math.random() * 0.4
}, {
duration: 500 + Math.random() * 1000,
easing: tween.easeOut
});
startScreenStars.push(startStar);
startScreen.addChild(startStar);
}
// Create title text
titleText = new Text2('Space Ranger', {
size: 120,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
startScreen.addChild(titleText);
// Create instruction text
instructionText = new Text2('Arrastra para moverte\nDerrota al jefe para ganar\n¡Ten cuidado con sus ataques!', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1200;
startScreen.addChild(instructionText);
// Create start button
startButton = new Text2('JUGAR', {
size: 100,
fill: 0x00FF00
});
startButton.anchor.set(0.5, 0.5);
startButton.x = 900;
startButton.y = 1600;
startScreen.addChild(startButton);
// Create explanation button
var explanationButton = new Text2('?', {
size: 100,
fill: 0x4A90E2
});
explanationButton.anchor.set(0.5, 0.5);
explanationButton.x = 1148;
explanationButton.y = 1600;
startScreen.addChild(explanationButton);
// Add enhanced pulsing effect to start button with color changes and rotation
var _buttonPulse = function buttonPulse() {
if (startButton && !gameStarted) {
// First phase: scale up with color change to bright yellow and slight rotation
tween(startButton, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0xFFFF00,
rotation: 0.1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second phase: scale down with color change to bright green and rotation back
tween(startButton, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0x00FF88,
rotation: -0.05
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
// Third phase: final color pulse back to original green
tween(startButton, {
tint: 0x00FF00,
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: _buttonPulse
});
}
});
}
});
}
};
_buttonPulse();
// Add pulsing effect to explanation button
var _explanationPulse = function explanationPulse() {
if (explanationButton && !gameStarted && !showingExplanation) {
tween(explanationButton, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0x87CEEB
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(explanationButton, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0x4A90E2
}, {
duration: 600,
easing: tween.easeIn,
onFinish: _explanationPulse
});
}
});
}
};
_explanationPulse();
// Start button click handler
startButton.down = function (x, y, obj) {
if (!gameStarted && !showingExplanation) {
gameStarted = true;
// Clean up start screen stars
for (var cleanupIndex = startScreenStars.length - 1; cleanupIndex >= 0; cleanupIndex--) {
startScreenStars[cleanupIndex].destroy();
}
startScreenStars = [];
startScreen.destroy();
initializeGame();
}
};
// Explanation button click handler
explanationButton.down = function (x, y, obj) {
if (!gameStarted && !showingExplanation) {
showingExplanation = true;
createExplanationScreen();
}
};
// Function to create explanation screen
function createExplanationScreen() {
explanationScreen = game.addChild(new Container());
explanationScreen.alpha = 0;
tween(explanationScreen, {
alpha: 1
}, {
duration: 300
});
// Semi-transparent background
var overlay = explanationScreen.addChild(LK.getAsset('bossFinalAttack', {
anchorX: 0.5,
anchorY: 0.5
}));
overlay.x = 1024;
overlay.y = 1366;
overlay.alpha = 0.8;
overlay.tint = 0x000033;
// Title
var explanationTitle = new Text2('GUÍA DEL JUEGO', {
size: 80,
fill: 0xFFFF00
});
explanationTitle.anchor.set(0.5, 0.5);
explanationTitle.x = 1024;
explanationTitle.y = 400;
explanationScreen.addChild(explanationTitle);
// Game mechanics explanation
var mechanicsText = new Text2('CONTROLES:\n• Arrastra para mover tu nave\n• Disparas automáticamente\n\nEL JEFE:\n• Tiene 10,000 puntos de vida\n• Se mueve por la pantalla\n• Tiene múltiples tipos de ataque', {
size: 45,
fill: 0xFFFFFF
});
mechanicsText.anchor.set(0.5, 0.5);
mechanicsText.x = 1024;
mechanicsText.y = 800;
explanationScreen.addChild(mechanicsText);
// Boss attacks explanation
var attacksText = new Text2('ATAQUES DEL JEFE:\n\n• ATAQUE NORMAL: Proyectiles rojos (1 daño)\n• ATAQUE ESPECIAL: Proyectiles pequeños rápidos (1 daño)\n• ATAQUE LÁSER: Rayo vertical que te sigue (1 daño)\n• ATAQUE FINAL: Pantalla roja completa (1 daño)', {
size: 40,
fill: 0xFF8888
});
attacksText.anchor.set(0.5, 0.5);
attacksText.x = 1024;
attacksText.y = 1200;
explanationScreen.addChild(attacksText);
// Special mechanics
var specialText = new Text2('MECÁNICAS ESPECIALES:\n\n• Cuando el jefe tiene ≤5000 vida: MODO RÁPIDO\n - Ataques más frecuentes y rápidos\n - Puede usar el ataque láser\n\n• Cuando el jefe tiene ≤1000 vida:\n - Intenta el ATAQUE FINAL mortal\n - ¡Dispárale para cancelarlo!', {
size: 38,
fill: 0x88FF88
});
specialText.anchor.set(0.5, 0.5);
specialText.x = 1024;
specialText.y = 1650;
explanationScreen.addChild(specialText);
// Victory condition
var victoryText = new Text2('OBJETIVO: Reduce la vida del jefe a 0 para ganar\nSOBREVIVE: Tienes solo 1 punto de vida', {
size: 42,
fill: 0xFFD700
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = 1024;
victoryText.y = 2000;
explanationScreen.addChild(victoryText);
// Back button
var backButton = new Text2('VOLVER', {
size: 70,
fill: 0xFF6666
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 1024;
backButton.y = 2300;
explanationScreen.addChild(backButton);
// Back button animation
var _backPulse = function backPulse() {
if (backButton && showingExplanation) {
tween(backButton, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFF8888
}, {
duration: 600,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF6666
}, {
duration: 400,
onFinish: _backPulse
});
}
});
}
};
_backPulse();
// Back button click handler
backButton.down = function (x, y, obj) {
if (showingExplanation) {
tween(explanationScreen, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
explanationScreen.destroy();
explanationScreen = null;
showingExplanation = false;
}
});
}
};
}
// Function to initialize game elements
function initializeGame() {
// Initialize boss
boss = game.addChild(new Boss());
boss.x = 1024;
boss.y = 400;
// Initialize player
player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
playerLastX = player.x;
playerLastY = player.y;
// Create boss health bar
bossHealthBarBg = game.addChild(LK.getAsset('bossHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5
}));
bossHealthBarBg.x = 1024;
bossHealthBarBg.y = 200;
bossHealthBar = game.addChild(LK.getAsset('bossHealthBar', {
anchorX: 0.5,
anchorY: 0.5
}));
bossHealthBar.x = 1024;
bossHealthBar.y = 200;
// Create player health bar
playerHealthBarBg = game.addChild(LK.getAsset('playerHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5
}));
playerHealthBarBg.x = 1024;
playerHealthBarBg.y = 2500;
playerHealthBar = game.addChild(LK.getAsset('playerHealthBar', {
anchorX: 0.5,
anchorY: 0.5
}));
playerHealthBar.x = 1024;
playerHealthBar.y = 2500;
// Create health text
bossHealthText = new Text2('10000/10000', {
size: 40,
fill: 0xFFFFFF
});
bossHealthText.anchor.set(0.5, 0.5);
bossHealthText.x = 1024;
bossHealthText.y = 160;
game.addChild(bossHealthText);
playerHealthText = new Text2('1/1', {
size: 30,
fill: 0xFFFFFF
});
playerHealthText.anchor.set(0.5, 0.5);
playerHealthText.x = 1024;
playerHealthText.y = 2540;
game.addChild(playerHealthText);
}
// Player movement
game.move = function (x, y, obj) {
if (gameStarted && dragNode) {
dragNode.x = x;
dragNode.y = y;
// Keep player within bounds
if (dragNode.x < 50) dragNode.x = 50;
if (dragNode.x > 1998) dragNode.x = 1998;
if (dragNode.y < 800) dragNode.y = 800;
if (dragNode.y > 2600) dragNode.y = 2600;
}
};
game.down = function (x, y, obj) {
if (gameStarted) {
dragNode = player;
game.move(x, y, obj);
}
};
game.up = function (x, y, obj) {
if (gameStarted) {
dragNode = null;
}
};
// Main game update loop
game.update = function () {
// Only run game logic if game has started
if (!gameStarted) {
// Update start screen stars
for (var startStarIndex = startScreenStars.length - 1; startStarIndex >= 0; startStarIndex--) {
var startStar = startScreenStars[startStarIndex];
// Remove if off screen
if (startStar.y > 2780) {
startStar.destroy();
startScreenStars.splice(startStarIndex, 1);
}
}
// Spawn new stars for start screen more frequently and consistently
if (LK.ticks % 15 == 0 && Math.random() < 0.9) {
var newStartStar = new Star();
newStartStar.x = Math.random() * 2048;
newStartStar.y = -10;
newStartStar.speed = Math.random() * 1.5 + 0.8; // Slightly faster and more visible
// Add immediate fade-in effect for new stars
var newStarGraphics = newStartStar.children[0];
newStarGraphics.alpha = 0;
tween(newStarGraphics, {
alpha: 0.5 + Math.random() * 0.5
}, {
duration: 300 + Math.random() * 500,
easing: tween.easeOut
});
startScreenStars.push(newStartStar);
startScreen.addChild(newStartStar);
}
return;
}
// Update player attacks
for (var i = playerAttacks.length - 1; i >= 0; i--) {
var attack = playerAttacks[i];
// Check if attack hit boss
if (attack.intersects(boss)) {
boss.takeDamage(attack.damage);
// Cancel final attack if boss is doing it
if (boss.isFinalAttacking && !boss.finalAttackCanceled) {
boss.cancelFinalAttack();
}
attack.destroy();
playerAttacks.splice(i, 1);
continue;
}
// Remove if off screen
if (attack.y < -50) {
attack.destroy();
playerAttacks.splice(i, 1);
}
}
// Update boss attacks
for (var j = bossAttacks.length - 1; j >= 0; j--) {
var bossAttack = bossAttacks[j];
// Check if attack hit player
if (bossAttack.intersects(player)) {
player.takeDamage(bossAttack.damage);
bossAttack.destroy();
bossAttacks.splice(j, 1);
continue;
}
// Remove if off screen
if (bossAttack.y > 2780) {
bossAttack.destroy();
bossAttacks.splice(j, 1);
}
}
// Update boss special attacks
for (var k = bossSpecialAttacks.length - 1; k >= 0; k--) {
var specialAttack = bossSpecialAttacks[k];
// Check if special attack hit player
if (specialAttack.intersects(player)) {
player.takeDamage(specialAttack.damage);
specialAttack.destroy();
bossSpecialAttacks.splice(k, 1);
continue;
}
// Remove if off screen
if (specialAttack.y > 2780) {
specialAttack.destroy();
bossSpecialAttacks.splice(k, 1);
}
}
// Player automatic attack - fast mode when health is half or below
var attackInterval = player.health <= player.maxHealth / 2 ? 3 : 20; // Super fast when health <= 0.5
if (LK.ticks % attackInterval == 0) {
var attackData = player.attack();
var newPlayerAttack = new PlayerAttack();
newPlayerAttack.x = attackData.x;
newPlayerAttack.y = attackData.y;
playerAttacks.push(newPlayerAttack);
game.addChild(newPlayerAttack);
}
// Update boss final attacks
for (var l = bossFinalAttacks.length - 1; l >= 0; l--) {
var finalAttack = bossFinalAttacks[l];
// Check if final attack hit player (covers entire screen)
if (finalAttack.intersects(player)) {
player.takeDamage(finalAttack.damage);
}
// Remove after lifetime expires
if (finalAttack.lifeTime >= finalAttack.maxLifeTime) {
finalAttack.destroy();
bossFinalAttacks.splice(l, 1);
}
}
// Update boss laser attacks
for (var m = bossLasers.length - 1; m >= 0; m--) {
var laser = bossLasers[m];
// Check if laser hit player AND player is moving
var playerIsMoving = player.x !== playerLastX || player.y !== playerLastY;
if (laser.intersects(player) && playerIsMoving) {
player.takeDamage(laser.damage);
}
// Remove after lifetime expires
if (laser.lifeTime >= laser.maxLifeTime) {
laser.destroy();
bossLasers.splice(m, 1);
}
}
// Update and spawn stars
for (var s = stars.length - 1; s >= 0; s--) {
var star = stars[s];
// Remove if off screen
if (star.y > 2780) {
star.destroy();
stars.splice(s, 1);
}
}
// Spawn new stars randomly
if (LK.ticks % 15 == 0 && Math.random() < 0.7) {
var newStar = new Star();
newStar.x = Math.random() * 2048;
newStar.y = -10;
stars.push(newStar);
game.addChild(newStar);
}
// Update player movement tracking
playerLastX = player.x;
playerLastY = player.y;
// Boss attack logic
var bossUpdateResult = boss.update();
if (bossUpdateResult === true) {
var attackData = boss.attack();
var newBossAttack = new BossAttack();
newBossAttack.x = attackData.x;
newBossAttack.y = attackData.y;
bossAttacks.push(newBossAttack);
game.addChild(newBossAttack);
} else if (bossUpdateResult === "special") {
var specialAttackData = boss.specialAttack();
var newSpecialAttack = new BossSpecialAttack();
newSpecialAttack.x = specialAttackData.x;
newSpecialAttack.y = specialAttackData.y;
bossSpecialAttacks.push(newSpecialAttack);
game.addChild(newSpecialAttack);
} else if (bossUpdateResult === "finalAttack") {
// Flash screen red to indicate final attack starting
LK.effects.flashScreen(0xff0000, 500);
} else if (bossUpdateResult === "finalAttackComplete") {
// Create final attack that covers entire map/screen
var finalAttackData = boss.finalAttack();
var newFinalAttack = new BossFinalAttack();
newFinalAttack.x = 1024; // Center horizontally to cover entire map width
newFinalAttack.y = 1366; // Center vertically to cover entire map height
bossFinalAttacks.push(newFinalAttack);
game.addChild(newFinalAttack);
} else if (bossUpdateResult === "laser") {
// Create laser attack
var laserAttackData = boss.laserAttack();
var newLaser = new BossLaser();
newLaser.x = laserAttackData.x;
newLaser.y = laserAttackData.y;
bossLasers.push(newLaser);
game.addChild(newLaser);
}
// Update health bars
var bossHealthPercent = boss.health / boss.maxHealth;
bossHealthBar.scaleX = bossHealthPercent;
var playerHealthPercent = player.health / player.maxHealth;
playerHealthBar.scaleX = playerHealthPercent;
// Update health text
bossHealthText.setText(boss.health + '/' + boss.maxHealth);
playerHealthText.setText(player.health + '/' + player.maxHealth);
// Check win condition
if (boss.health <= 0) {
LK.showYouWin();
}
// Check lose condition
if (player.health <= 0) {
LK.showGameOver();
}
};
Una nave espacial futurista mirada desde arriba en pixel art. In-Game asset. 2d. High contrast. No shadows
Un mounstro gigante con alas mirado desde arriba en pixel art. In-Game asset. 2d. High contrast. No shadows
Fuego amarillo en pixel art. In-Game asset. 2d. High contrast. No shadows
Una barra de jefe final en juego pixel art. In-Game asset. 2d. High contrast. No shadows
Ráfaga de fuego roja en pixel art. In-Game asset. 2d. High contrast. No shadows
Estrella blanca en pixel art. In-Game asset. 2d. High contrast. No shadows