User prompt
Puedes hacer una explosion en area para el guerrero4, para editar la iamgen porfavor
User prompt
el sonido de quemar se reproduce en bucle hasta que a no este quemado
User prompt
aumentalo a 80% y que haga un sonido de quemadura, si se pasa el quemado no se reproduce el audio y el color rojo desaparece ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cuando los enemigos estan quemados se ponene de color rojo un 50% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Auemntalo a 500 porfa =)
User prompt
reduzce el teimpo de spamear enemigos en 3
User prompt
mas grande a 48 con negrita, e igual agregale a los enemigos pero solo vida - daño
User prompt
haz mas grande la letra y baja la opacidad el modo fuego a un 20% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
puedes agregar debajo de los guerreso un texto asi 41-43-2.2-250-100 Que significan Vida, Daño, velocidad, alcanze, velocidad de ataque porfa
User prompt
hazlo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Los enemigos tienen 80 de vida
User prompt
fireWarrior; Vida 5 – Daño 6 – Velocidad 2.2 – Alcanze 250 – Velocidad de Ataque 100 fireWarrior 2; Vida 10 – Daño 6 – Velocidad 2.4 – Alcanze 250 – Velocidad de Ataque 50 fireWarrior 3; Vida 15 – Daño 18 – Velocidad 2.6 – Alcanze 250 – Velocidad de Ataque 100, quema los enemigos por 3s, cada segundo inflige 6 de daño si no son resistentes al fuego fireWarrior 4; Vida 20 – Daño 24 – Velocidad 2.8 – Alcanze 250 – Velocidad de Ataque 60, sus ataques son en área de 600 unidades, provocando una explosión que quema a los enemigos por 5s, cada segundo inflige 8 de daño si no son resistentes al fuego fireWarrior 5; Vida 25 – Daño 30 – Velocidad 3 – Alcanze 250 – Velocidad de Ataque 60 Activa el modo fuego, que hará que todos los enemigos reciban 6 de daño cada segundo, si no son resistentes al fuego ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Listo ahora vamos hacer los cinco guerros de agua, tierra, viento y enrgia, casi igual como hicimos a los de fuego =), las combinaciones identidas, ods notas de agua paralevel 2 de un guerrero de agua porfa
User prompt
Elimina el ajuste de sonido y los texto informativo porfa
User prompt
No funciono, ah zesto pon como control centralizado, de cambio inmediato y reemplazo total con el sonido del ajuste
User prompt
Corrige ese sonido usado esa investigacion
User prompt
hazlo con el sonido del bton de ajsutes
User prompt
replica el mismo procedimiento de la musica con el sonido del boton de asjutes, es decir analiza como esta puesto el cambio de musica e intenta replicalo con el boton, usnado el volumen del sonido, mejor dicho intenta que funcione, porque la musica si funciona
User prompt
1318 fue la linea de prueba si queires podemos volverlo a intentar
Code edit (1 edits merged)
Please save this source code
User prompt
Prueba el voumen dinamico, para ello vamos agregar un sonido cuando le damos clic al botn de asjutes y aste le aplciamos esta solucion porfa
User prompt
Corrige porfa
User prompt
ahora solo a la nota de fuego aplicale el procentaje de volumen del ajsute
User prompt
elimina todos los aumentos o reduciones de volumen por ajsute solo eja el ajsute
User prompt
corrige
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var ElementalNote = Container.expand(function (element, x, y) { var self = Container.call(this); var noteGraphics = self.attachAsset(element + 'Note', { anchorX: 0.5, anchorY: 0.5 }); self.element = element; self.x = x; self.y = y; var label = new Text2(element.toUpperCase(), { size: 30, fill: 0xFFFFFF }); label.anchor.set(0.5, 0.5); self.addChild(label); self.isDisabled = false; self.down = function (x, y, obj) { // Check if button is disabled if (self.isDisabled) { return; } // Disable button self.isDisabled = true; notePressed(self.element); // Play sound effect with controlled volume when pressed directly // Access current global soundValue instead of captured value var currentSoundValue = typeof soundValue !== 'undefined' ? soundValue : 0.8; if (self.element === 'fire') { var fireSound = LK.getSound('Nota_Fire'); fireSound.volume = currentSoundValue * 0.5; fireSound.play(); } else if (self.element === 'water') { var waterSound = LK.getSound('Nota_Water'); waterSound.volume = currentSoundValue; waterSound.play(); } else if (self.element === 'earth') { var earthSound = LK.getSound('Nota_Earth'); earthSound.volume = currentSoundValue; earthSound.play(); } else if (self.element === 'wind') { var windSound = LK.getSound('Nota_Wind'); windSound.volume = currentSoundValue; windSound.play(); } else if (self.element === 'light') { var lightSound = LK.getSound('Nota_Light'); lightSound.volume = currentSoundValue; lightSound.play(); } else { var summonSound = LK.getSound('summon'); summonSound.volume = currentSoundValue; summonSound.play(); } // Visual feedback - make smaller on press and change to green tween(noteGraphics, { scaleX: 0.8, scaleY: 0.8, tint: 0x00ff00 }, { duration: 100, onFinish: function onFinish() { // Return to normal size and restore color quickly tween(noteGraphics, { scaleX: 1.0, scaleY: 1.0, tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { // Only re-enable button if we have enough mana and haven't reached limit LK.setTimeout(function () { // Check if we still have enough mana and haven't reached the counter limit if (temporaryNoteCounter < currentMana) { self.isDisabled = false; } }, 0); // Re-enable conditionally after color animation } }); } }); }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemyUnit', { anchorX: 0.5, anchorY: 0.5, width: 280, height: 280 }); self.health = 5; self.maxHealth = 5; self.damage = 1; self.speed = 1.5; self.attackCooldown = 0; // Physics properties self.velocityY = 0; self.onGround = false; self.gravity = 0.5; // Beat effect properties self.baseY = 0; self.beatEffectTimer = 0; // Health bar var healthBar = LK.getAsset('healthBar', { width: 100, height: 12 }); healthBar.anchor.set(0.5, 0.5); healthBar.y = -80; self.addChild(healthBar); self.healthBar = healthBar; self.update = function () { // Set base Y position for beat effect if (self.baseY === 0) { self.baseY = 2186; // Ground level } // Apply beat effect if active if (self.beatEffectTimer > 0) { self.beatEffectTimer--; // Get current audio level and calculate rotation strength based on sensitivity difference var audioLevel = getGameMusicLevel(); var sensitivityDifference = Math.max(0, audioLevel - musicBeatThreshold); if (sensitivityDifference > 0) { var rotationAmount = Math.sin((120 - self.beatEffectTimer) * 0.3) * sensitivityDifference * 0.785; enemyGraphics.rotation = rotationAmount; } else { enemyGraphics.rotation = 0; // No rotation when no difference } } else { enemyGraphics.rotation = 0; // Reset rotation when effect ends // Apply gravity if (!self.onGround) { self.velocityY += self.gravity; self.y += self.velocityY; } // Ground collision var groundY = 2186; if (self.y >= groundY) { self.y = groundY; self.baseY = groundY; // Update base position self.velocityY = 0; self.onGround = true; } else { self.onGround = false; } } if (self.attackCooldown > 0) { self.attackCooldown--; } // Move towards player tower (speed is controlled by combat state) self.x -= self.speed; // Check for warriors to attack and combat engagement var inCombat = false; for (var i = 0; i < warriors.length; i++) { var warrior = warriors[i]; // Use half width for enemy and warrior colliders but keep full height var enemyColliderWidth = 280 * 0.5; // Half of enemy width var warriorColliderWidth = 288 * 0.5; // Half of warrior width var distance = Math.sqrt(Math.pow(self.x - warrior.x, 2) + Math.pow(self.y - warrior.y, 2)); if (distance < 250) { // Mark as in combat to stop movement inCombat = true; if (self.attackCooldown <= 0) { self.attack(warrior); // Play combat sound when fighting with warrior playRandomCombatSound(); // Attack animation - flash red and scale up tween(enemyGraphics, { tint: 0xff0000, scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(enemyGraphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); } break; } } // Check if enemy is at the tower x position - stop movement to focus on tower attack var atTowerPosition = Math.abs(self.x - enemyTower.x) <= 50; // Stop movement if in combat or at tower position, otherwise resume normal movement if (inCombat || atTowerPosition) { self.speed = 0; } else { self.speed = 1.5; } // Check collision with player tower and destroy enemy - use half width for enemy collider var towerColliderRadius = 700; // Fixed collider size, not scaled with tower var enemyColliderWidth = 280 * 0.5; // Half of enemy width var enemyColliderHeight = 280; // Full enemy height var towerDistance = Math.sqrt(Math.pow(self.x - playerTower.x, 2) + Math.pow(self.y - playerTower.y, 2)); if (towerDistance < towerColliderRadius) { if (self.attackCooldown <= 0) { self.attackPlayerTower(); } // Destroy enemy when it touches the tower self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } // Check if enemy is off-screen and destroy if (self.x < -500 || self.x > 4500 || self.y > 3500) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } return; // Exit update to prevent further execution } // Update health bar var healthPercent = self.health / self.maxHealth; self.healthBar.scaleX = healthPercent; }; self.attack = function (target) { self.attackCooldown = 80; if (target === playerTower) { self.attackPlayerTower(); } else { target.takeDamage(self.damage); } }; self.attackPlayerTower = function () { self.attackCooldown = 80; playerTowerHealth -= self.damage; // Play random tower damage sound var towerSounds = ['sonido_torre_1', 'sonido_torre_2', 'sonido_torre_3', 'sonido_torre_4']; var randomIndex = Math.floor(Math.random() * towerSounds.length); var sound = LK.getSound(towerSounds[randomIndex]); sound.volume = soundValue; sound.play(); // Create escombros particles when tower takes damage - quantity based on damage var particleCount = self.damage * 12; // Multiply particle count by damage for (var escombrosIndex = 0; escombrosIndex < particleCount; escombrosIndex++) { // 360-degree explosion pattern var angle = escombrosIndex / particleCount * Math.PI * 2; // Distribute evenly in 360 degrees var force = (200 + Math.random() * 300) * 4; // Quadruple the force var velocityX = Math.cos(angle) * force; var velocityY = Math.sin(angle) * force; var escombrosParticle = game.addChild(LK.getAsset('escombro_torre_jugador', { anchorX: 0.5, anchorY: 0.5, x: playerTower.x, y: playerTower.y - 800, width: (60 + Math.random() * 40) * 5, height: (60 + Math.random() * 40) * 5, rotation: Math.random() * Math.PI * 2 })); escombrosParticle.alpha = 0.9; escombrosParticle.tint = 0x8B4513; // Brown color for debris // Add gravity and physics properties escombrosParticle.velocityX = velocityX * 0.02; // Scale down for smooth movement escombrosParticle.velocityY = velocityY * 0.02; escombrosParticle.gravity = 0.8; // Gravity effect // Animate escombros particles with physics tween(escombrosParticle, { y: playerTower.y + 200 + escombrosParticle.velocityY * 100, x: playerTower.x + escombrosParticle.velocityX * 100, alpha: 0, rotation: escombrosParticle.rotation + Math.PI * 4, scaleX: 0.1, scaleY: 0.1 }, { duration: 2000 + Math.random() * 1000, easing: tween.easeOut, onFinish: function onFinish() { escombrosParticle.destroy(); } }); } if (playerTowerHealth <= 0) { LK.showGameOver(); } updateTowerHealthBars(); }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { // Play enemy death sound var sound = LK.getSound('enemy_death'); sound.volume = soundValue; sound.play(); // Death animation - fade out and scale down tween(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } LK.setScore(LK.getScore() + 10); scoreText.setText('Score: ' + LK.getScore()); // 50% chance to drop mana if not at max capacity if (Math.random() < 0.5 && currentMana < maxMana) { // Create mana drop at enemy position var manaDrop = game.addChild(LK.getAsset('manaOrb', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y })); // Visual effect - pulsing and floating up tween(manaDrop, { scaleX: 3.0, scaleY: 3.0, y: self.y - 100 }, { duration: 800, easing: tween.easeOut }); // Add mana after short delay and destroy drop LK.setTimeout(function () { currentMana = Math.min(currentMana + 1, maxMana); updateManaDisplay(); // Flash effect on collection tween(manaDrop, { alpha: 0, scaleX: 4, scaleY: 4 }, { duration: 300, onFinish: function onFinish() { manaDrop.destroy(); } }); }, 600); } } }; return self; }); var Nube = Container.expand(function () { var self = Container.call(this); // Create cloud with random uniform scale to maintain proportions var uniformScale = 0.5 + Math.random() * 1.5; // Random scale between 50% and 200% var cloudGraphics = self.attachAsset('shape', { anchorX: 0.5, anchorY: 0.5, scaleX: uniformScale, scaleY: uniformScale, alpha: 0.4 + Math.random() * 0.5 // Random opacity between 40% and 90% }); // Set cloud to white/light gray color cloudGraphics.tint = 0xF0F0F0; // Random cloud speed (slower clouds for depth) - will be adjusted by height layer self.speed = 0.5 + Math.random() * 1.0; // Speed between 0.5 and 1.5 // Adjust speed based on scale to simulate depth (smaller clouds move slower) self.baseSpeed = self.speed; // Store initial Y for floating animation self.initialY = 0; // Will be set when cloud is positioned // Method to start floating animation after positioning self.startFloating = function () { if (self.initialY === 0) { self.initialY = self.y; // Store the manually set position } var floatAmount = 20 + Math.random() * 30; var floatDuration = 3000 + Math.random() * 2000; tween(self, { y: self.initialY + floatAmount }, { duration: floatDuration, yoyo: true, repeat: -1, easing: tween.easeInOut }); }; self.update = function () { // Adjust speed based on scale for depth effect (smaller = slower, further away) self.speed = self.baseSpeed * (self.scaleX * 0.7 + 0.3); // Scale speed between 30% and 100% // Move cloud to the right self.x += self.speed; // Remove clouds that have moved off-screen to the right if (self.x > 4000 + cloudGraphics.width) { self.destroy(); var index = clouds.indexOf(self); if (index > -1) { clouds.splice(index, 1); } } }; return self; }); var Warrior = Container.expand(function (element, tier) { var self = Container.call(this); var assetName = element + 'Warrior'; if (element === 'fire') { assetName = 'fireWarrior_nivel_' + tier; } var warriorGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5, width: 288, height: 288 }); self.element = element; self.tier = tier; // Base stats - same as enemies var baseDamage = 1; var baseHealth = 5; // Set elemental-specific stats if (element === 'fire') { self.maxHealth = baseHealth; self.damage = baseDamage + 5; // +5 damage bonus self.speed = 2.2; } else if (element === 'water') { self.maxHealth = baseHealth; self.damage = baseDamage; self.speed = 1.8; self.canHeal = true; self.healCooldown = 0; self.isRanged = true; self.projectiles = []; } else if (element === 'earth') { self.maxHealth = baseHealth + 50; // +50 health bonus self.damage = baseDamage; self.speed = 1.5; } else if (element === 'light') { self.maxHealth = baseHealth; self.damage = baseDamage; self.speed = 2.5; self.isRanged = true; self.canAreaDamage = true; self.projectiles = []; } else if (element === 'wind') { self.maxHealth = baseHealth; self.damage = baseDamage; self.speed = 2.8; self.isFlying = true; self.isRanged = true; self.projectiles = []; } else { // Default stats for any other element self.maxHealth = baseHealth; self.damage = baseDamage; self.speed = 2; } self.health = self.maxHealth; self.attackCooldown = 0; self.target = null; self.isBeingDestroyed = false; // Flag to prevent multiple destruction attempts // Physics properties self.velocityY = 0; self.onGround = false; self.gravity = 0.5; // Beat effect properties self.baseY = 0; self.beatEffectTimer = 0; // Remove tier-based scaling to prevent size issues // Warriors maintain standard size regardless of tier // Health bar var healthBar = LK.getAsset('warriorHealthBar', { width: 120, height: 16 }); healthBar.anchor.set(0.5, 0.5); healthBar.y = -100; self.addChild(healthBar); self.healthBar = healthBar; self.update = function () { // Set base Y position for beat effect if (self.baseY === 0) { if (self.isFlying) { self.baseY = 1800; // Flying height } else { self.baseY = 2186; // Ground level } } // Apply beat effect if active if (self.beatEffectTimer > 0) { self.beatEffectTimer--; // Get current audio level and calculate rotation strength based on sensitivity difference var audioLevel = getGameMusicLevel(); var sensitivityDifference = Math.max(0, audioLevel - musicBeatThreshold); if (sensitivityDifference > 0) { var rotationAmount = Math.sin((120 - self.beatEffectTimer) * 0.3) * sensitivityDifference * 0.785; warriorGraphics.rotation = rotationAmount; } else { warriorGraphics.rotation = 0; // No rotation when no difference } } else { warriorGraphics.rotation = 0; // Reset rotation when effect ends // Apply gravity only to non-flying units if (!self.isFlying && !self.onGround) { self.velocityY += self.gravity; self.y += self.velocityY; } // Ground collision for non-flying units var groundY = 2186; if (!self.isFlying && self.y >= groundY) { self.y = groundY; self.baseY = groundY; // Update base position self.velocityY = 0; self.onGround = true; } else if (!self.isFlying) { self.onGround = false; } // Flying units hover at a specific height if (self.isFlying) { self.y = 1800; // Fly above ground level self.baseY = 1800; // Update base position } } // Move towards enemy tower (speed is controlled by combat state) if (!self.target) { self.x += self.speed; } // Attack logic if (self.attackCooldown > 0) { self.attackCooldown--; } // Update heal cooldown for water warriors if (self.canHeal && self.healCooldown > 0) { self.healCooldown--; } // Water warriors heal nearby allies only (not themselves) if (self.canHeal && self.healCooldown <= 0) { self.healCooldown = 120; // 2 seconds // Heal nearby warriors for (var j = 0; j < warriors.length; j++) { var ally = warriors[j]; if (ally !== self) { var allyDistance = Math.sqrt(Math.pow(self.x - ally.x, 2) + Math.pow(self.y - ally.y, 2)); if (allyDistance < 300 && ally.health < ally.maxHealth) { ally.health = Math.min(ally.health + 1, ally.maxHealth); // Healing effect tween(ally.children[0], { tint: 0x00ff88 }, { duration: 200, onFinish: function onFinish() { tween(ally.children[0], { tint: 0xffffff }, { duration: 200 }); } }); // Create healing particles for (var particleIndex = 0; particleIndex < 8; particleIndex++) { var particle = game.addChild(LK.getAsset('particulas_curacion', { anchorX: 0.5, anchorY: 0.5, x: ally.x + (Math.random() - 0.5) * 100, y: ally.y + (Math.random() - 0.5) * 100, width: 140 + Math.random() * 100, height: 140 + Math.random() * 100 })); particle.alpha = 0.8; // Animate particles upward and fade out tween(particle, { y: ally.y - 150 - Math.random() * 50, x: ally.x + (Math.random() - 0.5) * 200, alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 800 + Math.random() * 400, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } } } } } // Check for enemies to attack and combat engagement var inCombat = false; var attackRange = self.isRanged ? 600 : 250; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Use half width for warrior and enemy colliders but keep full height var warriorColliderWidth = 288 * 0.5; // Half of warrior width var enemyColliderWidth = 280 * 0.5; // Half of enemy width var distance = Math.sqrt(Math.pow(self.x - enemy.x, 2) + Math.pow(self.y - enemy.y, 2)); if (distance < attackRange) { // Mark as in combat to stop movement for both melee and ranged units inCombat = true; if (self.attackCooldown <= 0) { self.attack(enemy); // Play combat sound only for melee warriors to avoid double sounds if (!self.isRanged) { playRandomCombatSound(); } // Attack animation - flash blue and scale up tween(warriorGraphics, { tint: 0x00ffff, scaleX: 1.4, scaleY: 1.4 }, { duration: 300, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 300 }); } }); } if (!self.isRanged) { break; } } } // Check if warrior is at the tower x position - stop movement to focus on tower attack var atTowerPosition = Math.abs(self.x - playerTower.x) <= 50; // Update projectiles for ranged units if (self.isRanged) { for (var p = self.projectiles.length - 1; p >= 0; p--) { var proj = self.projectiles[p]; proj.x += proj.speedX; proj.y += proj.speedY; var projectileDestroyed = false; // Water warrior projectiles can heal allies if (self.element === 'water') { // Check collision with allies first for (var w = 0; w < warriors.length; w++) { var ally = warriors[w]; if (ally !== self) { // Use half width for ally collider but keep full height var allyColliderWidth = 288 * 0.5; // Half of ally width var allyDistance = Math.sqrt(Math.pow(proj.x - ally.x, 2) + Math.pow(proj.y - ally.y, 2)); if (allyDistance < 50) { // Hit ally if (ally.health < ally.maxHealth) { // Heal ally if not at full health ally.health = Math.min(ally.health + 1, ally.maxHealth); // Healing effect tween(ally.children[0], { tint: 0x00ff88 }, { duration: 200, onFinish: function onFinish() { tween(ally.children[0], { tint: 0xffffff }, { duration: 200 }); } }); // Create healing particles for (var particleIndex = 0; particleIndex < 8; particleIndex++) { var particle = game.addChild(LK.getAsset('particulas_curacion', { anchorX: 0.5, anchorY: 0.5, x: ally.x + (Math.random() - 0.5) * 100, y: ally.y + (Math.random() - 0.5) * 100, width: 140 + Math.random() * 100, height: 140 + Math.random() * 100 })); particle.alpha = 0.8; // Animate particles upward and fade out tween(particle, { y: ally.y - 150 - Math.random() * 50, x: ally.x + (Math.random() - 0.5) * 200, alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 800 + Math.random() * 400, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } proj.destroy(); self.projectiles.splice(p, 1); projectileDestroyed = true; break; } // If ally is at full health, projectile passes through } } } } // Check collision with enemies only if projectile wasn't destroyed by healing if (!projectileDestroyed) { for (var e = 0; e < enemies.length; e++) { var enemy = enemies[e]; // Use half width for enemy collider but keep full height var enemyColliderWidth = 280 * 0.5; // Half of enemy width var projDistance = Math.sqrt(Math.pow(proj.x - enemy.x, 2) + Math.pow(proj.y - enemy.y, 2)); if (projDistance < 80) { // Increased collision radius for better detection // Hit enemy if (self.canAreaDamage) { // Create lightning explosion visual effect at projectile impact point var explosion = game.addChild(LK.getAsset('efecto_electricidad', { anchorX: 0.5, anchorY: 0.5, x: proj.x, y: proj.y, width: 80, height: 80 })); explosion.alpha = 0.9; // Animate explosion - scale up and fade out tween(explosion, { scaleX: 3.0, scaleY: 3.0, alpha: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { explosion.destroy(); } }); // Create electric particles expanding from explosion center for (var particleIndex = 0; particleIndex < 12; particleIndex++) { var angle = particleIndex / 12 * Math.PI * 2; // Distribute evenly in circle var distance = 150 + Math.random() * 100; var particleEndX = proj.x + Math.cos(angle) * distance; var particleEndY = proj.y + Math.sin(angle) * distance; var electricParticle = game.addChild(LK.getAsset('efecto_electricidad', { anchorX: 0.5, anchorY: 0.5, x: proj.x, y: proj.y, width: 20 + Math.random() * 20, height: 20 + Math.random() * 20 })); electricParticle.alpha = 0.8; // Animate particles expanding outward and fading tween(electricParticle, { x: particleEndX, y: particleEndY, alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 300 + Math.random() * 200, easing: tween.easeOut, onFinish: function onFinish() { electricParticle.destroy(); } }); } // Lightning area damage - increased damage for area effect for (var ae = 0; ae < enemies.length; ae++) { var areaEnemy = enemies[ae]; var areaDistance = Math.sqrt(Math.pow(proj.x - areaEnemy.x, 2) + Math.pow(proj.y - areaEnemy.y, 2)); if (areaDistance < 600) { areaEnemy.takeDamage(1); // Set damage to 1 for area effect } } } else { // Single target damage for water and wind warriors enemy.takeDamage(self.damage); } proj.destroy(); self.projectiles.splice(p, 1); projectileDestroyed = true; break; } } } // Remove projectiles that go off screen only if not already destroyed if (!projectileDestroyed && (proj.x > 4500 || proj.x < -500 || proj.y > 3500 || proj.y < -500)) { proj.destroy(); self.projectiles.splice(p, 1); } } } // Stop movement if in combat or at tower position, otherwise resume normal movement // Exception: wind warriors (aerial units) continue moving while attacking if ((inCombat || atTowerPosition) && self.element !== 'wind') { self.speed = 0; } else { if (self.element === 'fire') { self.speed = 2.2; } else if (self.element === 'water') { self.speed = 1.8; } else if (self.element === 'earth') { self.speed = 1.5; } else if (self.element === 'light') { self.speed = 2.5; } else if (self.element === 'wind') { self.speed = 2.8; } else { self.speed = 2; } } // Check collision with enemy tower - use separate x and y collision detection for flying units var towerColliderRadius = 700; // Fixed collider size, not scaled with tower var warriorColliderWidth = 288 * 0.5; // Half of warrior width var warriorColliderHeight = 288; // Full warrior height var towerDistance = Math.sqrt(Math.pow(self.x - enemyTower.x, 2) + Math.pow(self.y - enemyTower.y, 2)); var xDistance = Math.abs(self.x - enemyTower.x); var yDistance = Math.abs(self.y - enemyTower.y); // Debug collision for wind warriors if (self.element === 'wind') { collisionDebugText.setText('Wind Warrior - XDist: ' + Math.round(xDistance) + ' YDist: ' + Math.round(yDistance) + ' Pos: (' + Math.round(self.x) + ',' + Math.round(self.y) + ')'); } // Use different collision detection for flying units vs ground units var collisionDetected = false; if (self.isFlying) { // For flying units, use x-distance only (ignore y difference) collisionDetected = xDistance < towerColliderRadius; } else { // For ground units, use traditional distance-based collision collisionDetected = towerDistance < towerColliderRadius; } if (collisionDetected && !self.isBeingDestroyed) { // Debug when collision happens if (self.element === 'wind') { collisionDebugText.setText('WIND COLLISION! XDist: ' + Math.round(xDistance) + ' Damage: ' + self.damage); } // Deal damage to tower first - always attack regardless of cooldown when touching tower self.attackTower(); // Mark as being destroyed to prevent multiple collision detections self.isBeingDestroyed = true; // Remove from warriors array immediately var index = warriors.indexOf(self); if (index > -1) { warriors.splice(index, 1); } // Warrior self-destructs when touching the tower - immediate destruction self.destroy(); return; // Exit update to prevent further execution after destruction } // Check projectile collision with enemy tower for ranged units - tower is invulnerable to projectiles if (self.isRanged) { for (var p = self.projectiles.length - 1; p >= 0; p--) { var proj = self.projectiles[p]; var projTowerDistance = Math.sqrt(Math.pow(proj.x - enemyTower.x, 2) + Math.pow(proj.y - enemyTower.y, 2)); if (projTowerDistance < 700) { // Fixed collider radius // Projectile hit the tower but tower is invulnerable - just destroy projectile proj.destroy(); self.projectiles.splice(p, 1); } } } // Check if warrior is off-screen and destroy if (self.x < -500 || self.x > 4500 || self.y > 3500) { self.destroy(); var index = warriors.indexOf(self); if (index > -1) { warriors.splice(index, 1); } return; // Exit update to prevent further execution } // Update health bar var healthPercent = self.health / self.maxHealth; self.healthBar.scaleX = healthPercent; self.healthBar.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; self.attack = function (target) { self.attackCooldown = 60; // 1 second at 60fps if (target === enemyTower) { self.attackTower(); } else if (self.isRanged) { // Create projectile for ranged units with enhanced properties var projectileSize = 120; // Larger projectiles for better visibility (doubled from 60) var projectileAsset = self.element === 'light' ? 'proyectil_electricidad' : 'projectile'; var projectile = game.addChild(LK.getAsset(projectileAsset, { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y - 20, // Start slightly above warrior width: projectileSize, height: projectileSize })); // Calculate direction to target var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var speed = 10; // Increased speed for better gameplay projectile.speedX = dx / distance * speed; projectile.speedY = dy / distance * speed; // Set projectile appearance based on element if (self.element === 'light') { projectile.alpha = 0.9; // Slightly transparent for glow effect // Add pulsing effect for lightning tween(projectile, { scaleX: 1.3, scaleY: 1.3 }, { duration: 300, yoyo: true, repeat: -1 }); } else if (self.element === 'wind') { projectile.tint = 0x44ff44; // Green for wind projectile.alpha = 0.8; // Add spinning effect for wind tween(projectile, { rotation: Math.PI * 2 }, { duration: 500, repeat: -1 }); } else if (self.element === 'water') { projectile.tint = 0x1e90ff; // Sea blue for water (DodgerBlue) projectile.alpha = 0.85; // Add wobbling effect for water tween(projectile, { scaleX: 1.2, scaleY: 0.8 }, { duration: 200, yoyo: true, repeat: -1 }); } self.projectiles.push(projectile); // Auto-destroy projectile after 5 seconds to prevent map clutter tween(projectile, { alpha: projectile.alpha // Dummy property to track time }, { duration: 5000, // 5 seconds onFinish: function onFinish() { // Find and remove projectile from array var index = self.projectiles.indexOf(projectile); if (index > -1) { self.projectiles.splice(index, 1); } // Destroy the projectile projectile.destroy(); } }); // Play element-specific projectile sound playRandomProjectileSound(self.element); return; // Exit after creating projectile to prevent melee sound } else { // Melee attack target.takeDamage(self.damage); // Play sword attack sound for melee attacks sonidoEspadas(); } }; self.attackTower = function () { self.attackCooldown = 60; enemyTowerHealth -= self.damage; // Play random tower damage sound var towerSounds = ['sonido_torre_1', 'sonido_torre_2', 'sonido_torre_3', 'sonido_torre_4']; var randomIndex = Math.floor(Math.random() * towerSounds.length); var sound = LK.getSound(towerSounds[randomIndex]); sound.volume = soundValue; sound.play(); // Create escombros particles when enemy tower takes damage - quantity based on damage var particleCount = self.damage * 12; // Multiply particle count by damage for (var escombrosIndex = 0; escombrosIndex < particleCount; escombrosIndex++) { // 360-degree explosion pattern var angle = escombrosIndex / particleCount * Math.PI * 2; // Distribute evenly in 360 degrees var force = (200 + Math.random() * 300) * 4; // Quadruple the force var velocityX = Math.cos(angle) * force; var velocityY = Math.sin(angle) * force; var escombrosParticle = game.addChild(LK.getAsset('escombros_torre_enemiga', { anchorX: 0.5, anchorY: 0.5, x: enemyTower.x, y: enemyTower.y - 800, width: (60 + Math.random() * 40) * 5, height: (60 + Math.random() * 40) * 5, rotation: Math.random() * Math.PI * 2 })); escombrosParticle.alpha = 0.9; escombrosParticle.tint = 0x696969; // Dark gray color for enemy debris // Add gravity and physics properties escombrosParticle.velocityX = velocityX * 0.02; // Scale down for smooth movement escombrosParticle.velocityY = velocityY * 0.02; escombrosParticle.gravity = 0.8; // Gravity effect // Animate escombros particles with physics tween(escombrosParticle, { y: enemyTower.y + 200 + escombrosParticle.velocityY * 100, x: enemyTower.x + escombrosParticle.velocityX * 100, alpha: 0, rotation: escombrosParticle.rotation + Math.PI * 4, scaleX: 0.1, scaleY: 0.1 }, { duration: 2000 + Math.random() * 1000, easing: tween.easeOut, onFinish: function onFinish() { escombrosParticle.destroy(); } }); } if (enemyTowerHealth <= 0) { LK.showYouWin(); } updateTowerHealthBars(); }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { // Mark as being destroyed to prevent multiple destruction attempts self.isBeingDestroyed = true; // Death animation - fade out and scale down tween(warriorGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: -Math.PI * 2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); // Only remove from warriors array if not already removed by collision detection if (!self.isBeingDestroyed || self.isBeingDestroyed) { var index = warriors.indexOf(self); if (index > -1) { warriors.splice(index, 1); } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50, width: 3840, height: 1080 }); /**** * Game Code ****/ function _typeof3(o) { "@babel/helpers - typeof"; return _typeof3 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof3(o); } function _typeof2(o) { "@babel/helpers - typeof"; return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof2(o); } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var warriors = []; var enemies = []; var playerTowerHealth = 30; var enemyTowerHealth = 10; var enemySpawnTimer = 0; var isDragging = false; var lastMouseX = 0; var cameraX = 0; var maxCameraX = 1792; // 3840 - 2048 = max scroll distance var currentMana = 5; var maxMana = 5; var manaRegenTimer = 0; // Combination system variables var currentCombination = []; var combinationTimer = 0; var combinationCooldown = 0; var maxCombinationLength = 5; var combinationWindowTime = 30; // 0.5 seconds at 60fps var combinationResetTime = 60; // 1 second at 60fps var temporaryNoteCounter = 0; // Helper counter for tracking notes (1-5) // Timing interval tracking variables var noteTimingIntervals = []; // Store time intervals between note presses var lastNoteTime = 0; // Timestamp of last note press var isFirstNote = true; // Track if this is the first note in a sequence // Touch position tracking variables var initialTouchX = 0; var initialTouchY = 0; var currentTouchX = 0; var currentTouchY = 0; // Music beat detection variables var musicBeatThreshold = 0; // Default sensitivity threshold set to 0 - will be controlled by sensitivity button var lastBeatTime = 0; var beatCooldown = 15; // Reduced cooldown for more frequent detections (0.25 seconds at 60fps) // UI Elements var scoreText = new Text2('Score: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); scoreText.x = 120; scoreText.y = 50; LK.gui.topLeft.addChild(scoreText); // Create mana display var manaText = new Text2('Mana: 5/5', { size: 40, fill: 0x00FFFF }); manaText.anchor.set(0, 0); manaText.x = 1100; manaText.y = 100; LK.gui.topLeft.addChild(manaText); // Create mana orbs visual display var manaOrbs = []; for (var i = 0; i < maxMana; i++) { var orb = LK.getAsset('manaOrbShape', { width: 40, height: 40 }); orb.anchor.set(0.5, 0.5); orb.x = 1100 + i * 50; orb.y = 160; LK.gui.topLeft.addChild(orb); manaOrbs.push(orb); } // Settings panel state var settingsPanelVisible = false; var settingsBars = []; // Settings values (0.0 to 1.0 range) var musicValue = 0.8; var soundValue = 0.8; var sensitivityValue = 0.5; // Initialize sound volume properly updateSoundVolume(80); // Create settings button below mana bar var settingsButton = LK.getAsset('settingsIcon', { width: 120, height: 120 }); settingsButton.anchor.set(0.5, 0.5); settingsButton.x = 1200; // Move slightly to the right settingsButton.y = 250; // Move down a bit more settingsButton.alpha = 0.8; LK.gui.topLeft.addChild(settingsButton); // Create music volume text input var musicVolumeInput = new Text2('Volumen Música: 80', { size: 30, fill: 0xFFFFFF }); musicVolumeInput.anchor.set(0.5, 0.5); musicVolumeInput.x = 1200; musicVolumeInput.y = 380; musicVolumeInput.alpha = 0; LK.gui.topLeft.addChild(musicVolumeInput); // Create sound volume text input var soundVolumeInput = new Text2('Volumen Sonido: 80', { size: 30, fill: 0xFFFFFF }); soundVolumeInput.anchor.set(0.5, 0.5); soundVolumeInput.x = 1200; soundVolumeInput.y = 460; soundVolumeInput.alpha = 0; LK.gui.topLeft.addChild(soundVolumeInput); // Store all settings elements settingsBars = [musicVolumeInput, soundVolumeInput]; // Function to update music volume function updateMusicVolume(value) { // Parse and validate the input value var volumeNumber = parseInt(value); if (isNaN(volumeNumber)) { volumeNumber = 80; } volumeNumber = Math.max(0, Math.min(100, volumeNumber)); musicValue = volumeNumber / 100; musicVolumeInput.setText('Volumen Música: ' + volumeNumber); // Apply music volume changes immediately LK.stopMusic(); LK.playMusic('Music', { volume: musicValue }); } // Function to update sound volume function updateSoundVolume(value) { // Parse and validate the input value var volumeNumber = parseInt(value); if (isNaN(volumeNumber)) { volumeNumber = 80; } volumeNumber = Math.max(0, Math.min(100, volumeNumber)); soundValue = volumeNumber / 100; if (soundVolumeInput && typeof soundVolumeInput.setText === 'function') { soundVolumeInput.setText('Volumen Sonido: ' + volumeNumber); } // Force update the debug text immediately if (soundValueText && typeof soundValueText.setText === 'function') { soundValueText.setText('soundValue: ' + soundValue.toFixed(2)); } } // Music volume input interaction musicVolumeInput.down = function (x, y, obj) { // Simple interaction for now - could be enhanced with actual text input var currentVolume = Math.round(musicValue * 100); var newVolume = (currentVolume + 10) % 110; // Cycle through 0-100 by 10s updateMusicVolume(newVolume); }; // Sound volume input interaction soundVolumeInput.down = function (x, y, obj) { // Simple interaction for now - could be enhanced with actual text input var currentVolume = Math.round(soundValue * 100); var newVolume = (currentVolume + 10) % 110; // Cycle through 0-100 by 10s updateSoundVolume(newVolume); }; settingsButton.down = function (x, y, obj) { // Play settings click sound with dynamic volume - test different volumes var settingsSound = LK.getSound('settings_click'); settingsSound.volume = soundValue * 0.7; // Apply current soundValue with 70% modifier settingsSound.play(); // Debug: Test volume sequence to verify dynamic control works LK.setTimeout(function () { var testSound = LK.getSound('settings_click'); testSound.volume = 0.1; // Very quiet test testSound.play(); }, 500); LK.setTimeout(function () { var testSound2 = LK.getSound('settings_click'); testSound2.volume = 1.0; // Full volume test testSound2.play(); }, 1000); // Visual feedback with bounce effect tween(settingsButton, { scaleX: 0.85, scaleY: 0.85, alpha: 0.6, rotation: Math.PI * 0.1 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(settingsButton, { scaleX: 1.05, scaleY: 1.05, alpha: 0.9, rotation: 0 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { tween(settingsButton, { scaleX: 1.0, scaleY: 1.0, alpha: 0.8 }, { duration: 100 }); } }); } }); // Toggle settings panel with staggered animations if (settingsPanelVisible) { // Hide settings panel with staggered fade out settingsPanelVisible = false; for (var i = 0; i < settingsBars.length; i++) { var delay = i * 30; // Stagger each element by 30ms tween(settingsBars[i], { alpha: 0, y: settingsBars[i].y - 20, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, delay: delay, easing: tween.easeInOut }); } } else { // Show settings panel with bouncy entrance settingsPanelVisible = true; for (var i = 0; i < settingsBars.length; i++) { var delay = i * 40; // Stagger each element by 40ms var targetY = settingsBars[i].y; settingsBars[i].y = targetY - 30; settingsBars[i].scaleX = 0.6; settingsBars[i].scaleY = 0.6; tween(settingsBars[i], { alpha: 1, y: targetY, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, delay: delay, easing: tween.elasticOut }); } } }; // Create collision debug text in center of game var collisionDebugText = new Text2('Collision Debug', { size: 60, fill: 0xFFFF00 }); collisionDebugText.anchor.set(0.5, 0.5); collisionDebugText.x = 1024; // Center of screen width (2048/2) collisionDebugText.y = 1366; // Center of screen height (2732/2) game.addChild(collisionDebugText); // Create audio debug text to show real-time values var audioDebugText = new Text2('Audio: 0.00 | Threshold: 0.15 | Diff: 0.00', { size: 40, fill: 0x00FFFF }); audioDebugText.anchor.set(0.5, 0.5); audioDebugText.x = 1024; // Center of screen width audioDebugText.y = 1200; // Above collision debug text game.addChild(audioDebugText); // Create touch position debug text var touchDebugText = new Text2('Touch Info: Initial(0,0) Current(0,0)', { size: 40, fill: 0xFF00FF }); touchDebugText.anchor.set(0.5, 0.5); touchDebugText.x = 1024; // Center of screen width touchDebugText.y = 1500; // Below collision debug text game.addChild(touchDebugText); // Create combination message text var combinationMessageText = new Text2('', { size: 60, fill: 0xFFFF00 }); combinationMessageText.anchor.set(0.5, 0.5); combinationMessageText.x = 1024; // Center of screen width combinationMessageText.y = 800; // Above other debug texts combinationMessageText.alpha = 0; game.addChild(combinationMessageText); // Create temporary note counter info text var tempCounterInfoText = new Text2('Notas presionadas: 0', { size: 40, fill: 0x00FF00 }); tempCounterInfoText.anchor.set(0.5, 0.5); tempCounterInfoText.x = 1024; // Center of screen width tempCounterInfoText.y = 600; // Above combination message text game.addChild(tempCounterInfoText); // Create timing intervals info text var timingIntervalsText = new Text2('Intervalos: []', { size: 35, fill: 0xFFAA00 }); timingIntervalsText.anchor.set(0.5, 0.5); timingIntervalsText.x = 1024; // Center of screen width timingIntervalsText.y = 500; // Above temp counter text game.addChild(timingIntervalsText); // Create sound value debug text var soundValueText = new Text2('soundValue: 0.80', { size: 40, fill: 0xFF8800 }); soundValueText.anchor.set(0.5, 0.5); soundValueText.x = 1024; // Center of screen width soundValueText.y = 400; // Above timing intervals text game.addChild(soundValueText); // Create tiled ground floor var groundTiles = []; var tileSize = 592.704; // Size of each ground tile (increased by 5% more) var groundY = 2732; // Position at bottom of screen var groundHeight = 728.6; // Extend height to fill bottom gap (tileSize + 136 pixels) var numTiles = Math.ceil(3840 / tileSize) + 2; // Cover full width plus extra for seamless tiling for (var i = 0; i < numTiles; i++) { var groundTile = game.addChild(LK.getAsset('ground', { anchorX: 0.0, anchorY: 1.0, x: i * tileSize, y: groundY, width: tileSize, height: groundHeight })); groundTiles.push(groundTile); } // Create towers (horizontal layout) var playerTower = game.addChild(LK.getAsset('playerTower', { anchorX: 0.5, anchorY: 1.0, x: 250, y: 2559, width: 1200, height: 1728 })); var enemyTower = game.addChild(LK.getAsset('enemyTower', { anchorX: 0.5, anchorY: 1.0, x: 3590, y: 2559, width: 1200, height: 1728 })); // Tower health bars var playerTowerHealthBar = LK.getAsset('playerTowerHealthBar', { width: 1200, height: 160 }); playerTowerHealthBar.anchor.set(0.5, 0.5); playerTowerHealthBar.x = playerTower.x; playerTowerHealthBar.y = playerTower.y - 1840; game.addChild(playerTowerHealthBar); var enemyTowerHealthBar = LK.getAsset('enemyTowerHealthBar', { width: 1200, height: 160 }); enemyTowerHealthBar.anchor.set(0.5, 0.5); enemyTowerHealthBar.x = enemyTower.x; enemyTowerHealthBar.y = enemyTower.y - 1840; game.addChild(enemyTowerHealthBar); // Create elemental notes (horizontal layout at top left) - show all elements var elements = ['fire', 'water', 'earth', 'wind', 'light']; var notes = []; for (var i = 0; i < elements.length; i++) { var note = new ElementalNote(elements[i], 0, 0); LK.gui.topLeft.addChild(note); // Make buttons smaller note.scaleX = 0.4; note.scaleY = 0.4; // Position buttons horizontally in upper left with proper spacing (moved 50% right total) note.x = 234 + i * 140; // Start at x:234 (moved from 180), space buttons 140 pixels apart note.y = 120; // Fixed y position in upper area notes.push(note); } // Create camera control buttons var leftButton = LK.getAsset('leftCameraButton', { width: 100, height: 100 }); leftButton.anchor.set(0.5, 0.5); leftButton.alpha = 0.5; // 50% transparency LK.gui.left.addChild(leftButton); var leftButtonText = new Text2('<', { size: 60, fill: 0xffffff }); leftButtonText.anchor.set(0.5, 0.5); leftButton.addChild(leftButtonText); var rightButton = LK.getAsset('rightCameraButton', { width: 100, height: 100 }); rightButton.anchor.set(0.5, 0.5); rightButton.alpha = 0.5; // 50% transparency LK.gui.right.addChild(rightButton); var rightButtonText = new Text2('>', { size: 60, fill: 0xffffff }); rightButtonText.anchor.set(0.5, 0.5); rightButton.addChild(rightButtonText); function notePressed(element) { // If this is the start of a new combination, clear previous timing data if (currentCombination.length === 0) { noteTimingIntervals = []; isFirstNote = true; lastNoteTime = 0; } // Record timing for interval tracking var currentTime = Date.now(); if (isFirstNote) { // First note - record time and initialize with 0 interval lastNoteTime = currentTime; isFirstNote = false; noteTimingIntervals = [0]; // Initialize with 0 for first note } else { // Calculate interval since last note var interval = currentTime - lastNoteTime; noteTimingIntervals.push(interval); lastNoteTime = currentTime; } // Update timing intervals display var intervalsDisplay = noteTimingIntervals.length > 0 ? 'Intervalos: [' + noteTimingIntervals.map(function (interval) { return Math.round(interval) + 'ms'; }).join(', ') + ']' : 'Intervalos: []'; timingIntervalsText.setText(intervalsDisplay); // Increment temporary counter temporaryNoteCounter++; // Add element to current combination addToCombination(element); // Disable buttons if temporary counter equals or exceeds available mana if (temporaryNoteCounter >= currentMana) { disableAllNoteButtons(); } // Only process immediately if we've reached max combination length if (currentCombination.length >= maxCombinationLength) { processCombination(); } } function spawnEnemy() { var enemy = new Enemy(); enemy.x = enemyTower.x - 300; enemy.y = 2186; // Spawn on ground level enemy.onGround = true; // Start on ground game.addChild(enemy); enemies.push(enemy); } function updateTowerHealthBars() { var playerHealthPercent = Math.max(0, playerTowerHealth / 30); var enemyHealthPercent = Math.max(0, enemyTowerHealth / 10); playerTowerHealthBar.scaleX = playerHealthPercent; enemyTowerHealthBar.scaleX = enemyHealthPercent; // Scale towers based on health - minimum scale of 0.3 (30%), maximum 1.0 (100%) var playerTowerScale = 0.3 + playerHealthPercent * 0.7; // 0.3 to 1.0 range var enemyTowerScale = 0.3 + enemyHealthPercent * 0.7; // 0.3 to 1.0 range // Apply scaling to towers tween.stop(playerTower, { scaleX: true, scaleY: true }); tween.stop(enemyTower, { scaleX: true, scaleY: true }); tween(playerTower, { scaleX: playerTowerScale, scaleY: playerTowerScale }, { duration: 500, easing: tween.easeInOut }); tween(enemyTower, { scaleX: enemyTowerScale, scaleY: enemyTowerScale }, { duration: 500, easing: tween.easeInOut }); } function updateManaDisplay() { // Update text manaText.setText('Mana: ' + currentMana + '/' + maxMana); // Update orb visuals for (var i = 0; i < manaOrbs.length; i++) { if (i < currentMana) { manaOrbs[i].alpha = 1.0; // Full opacity for available mana manaOrbs[i].tint = 0x00FFFF; // Cyan color } else { manaOrbs[i].alpha = 0.3; // Low opacity for depleted mana manaOrbs[i].tint = 0x666666; // Gray color } } // Update note button states based on mana and current combination length var requiredMana = currentCombination.length + 1; // Mana needed to add one more note for (var i = 0; i < notes.length; i++) { if (currentMana < requiredMana) { notes[i].alpha = 0.5; // Grayed out when not enough mana notes[i].isDisabled = true; } else { notes[i].alpha = 1.0; // Normal when mana available notes[i].isDisabled = false; } } } function playRandomCombatSound() { var combatSounds = ['combatir_1', 'combatir_2', 'combatir_3', 'combatir_4']; var randomIndex = Math.floor(Math.random() * combatSounds.length); var sound = LK.getSound(combatSounds[randomIndex]); sound.volume = soundValue; sound.play(); } function sonidoEspadas() { var sound = LK.getSound('attack'); sound.volume = soundValue; sound.play(); } function playRandomProjectileSound(element) { var projectileSounds = []; if (element === 'water') { projectileSounds = ['sonido_proyectil_agua_1', 'sonido_proyectil_agua_2', 'sonido_proyectil_agua_3', 'sonido_proyectil_agua_4']; } else if (element === 'wind') { projectileSounds = ['sonido_proyectil_viento_1', 'sonido_proyectil_viento_2', 'sonido_proyectil_viento_3', 'sonido_proyectil_viento_4']; } else if (element === 'light') { projectileSounds = ['sonido_proyectil_energia_1', 'sonido_proyectil_energia_2', 'sonido_proyectil_energia_3', 'sonido_proyectil_energia_4']; } if (projectileSounds.length > 0) { var randomIndex = Math.floor(Math.random() * projectileSounds.length); var sound = LK.getSound(projectileSounds[randomIndex]); sound.volume = soundValue; sound.play(); } } function disableAllNoteButtons() { for (var i = 0; i < notes.length; i++) { notes[i].isDisabled = true; notes[i].alpha = 0.5; // Visual feedback } } function enableNoteButtons() { // Re-enable buttons only if we have enough mana updateManaDisplay(); } function addToCombination(element) { currentCombination.push(element); combinationTimer = combinationWindowTime; combinationCooldown = combinationResetTime; // Show current combination showCombinationMessage('Combinación: [' + currentCombination.join(', ') + ']'); } function processCombination() { if (currentCombination.length === 0) { return; } // Store combination and timing intervals for melody playback before reset var combinationForMelody = currentCombination.slice(); // Create a copy var timingIntervalsForMelody = noteTimingIntervals.slice(); // Create a copy of intervals // Check if combination is valid if (isValidCombination(currentCombination)) { // Execute the combination executeCombination(currentCombination); // Play melody after successful summoning with preserved intervals playMelodySequenceWithIntervals(combinationForMelody, timingIntervalsForMelody); } else { // Show invalid combination message showCombinationMessage('Combinación no existente'); } // Reset combination resetCombination(); // Re-enable buttons after 1 second (invocation phase) LK.setTimeout(function () { temporaryNoteCounter = 0; // Reset helper counter after invocation phase enableNoteButtons(); }, 1000); } function isValidCombination(combination) { // Single element combinations are valid if (combination.length === 1) { var element = combination[0]; return element === 'fire' || element === 'water' || element === 'earth' || element === 'wind' || element === 'light'; } // Multiple fire combinations (2-5 fire notes) if (combination.length >= 2 && combination.length <= 5) { // Check if all elements are fire for (var i = 0; i < combination.length; i++) { if (combination[i] !== 'fire') { return false; } } return true; } return false; } function executeCombination(combination) { // Check if we have enough mana for this combination if (currentMana < combination.length) { showCombinationMessage('No hay suficiente mana'); return; } // Consume mana based on combination length currentMana -= combination.length; updateManaDisplay(); if (combination.length === 1) { // Single element summon var element = combination[0]; summonWarrior(element, 1); showCombinationMessage('¡' + element.toUpperCase() + ' nivel 1 invocado!'); } else if (combination.length >= 2 && combination.length <= 5) { // Multiple fire combination var element = combination[0]; // Should be 'fire' var level = combination.length; summonWarrior(element, level); showCombinationMessage('¡' + element.toUpperCase() + ' nivel ' + level + ' invocado!'); } } function summonWarrior(element, tier) { // Default tier to 1 if not specified if (tier === undefined) { tier = 1; } // Create elemental warrior based on the element and tier var warrior = new Warrior(element, tier); warrior.x = playerTower.x + 300; warrior.y = 2186; // Spawn on ground level warrior.onGround = true; // Start on ground // Add elemental-specific visual effects on spawn var warriorGraphics = warrior.children[0]; // Get the warrior graphics if (element === 'water') { // Water splash effect - blue particles tween(warriorGraphics, { tint: 0x0066ff, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); } else if (element === 'earth') { // Earth rumble effect - brown particles var originalY = warriorGraphics.y; tween(warriorGraphics, { tint: 0x8b4513, y: originalY - 50 }, { duration: 200, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, y: originalY }, { duration: 200 }); } }); } else if (element === 'fire') { // Fire burst effect - red/orange flames tween(warriorGraphics, { tint: 0xff4400, scaleX: 1.3, scaleY: 1.3, rotation: Math.PI * 0.1 }, { duration: 250, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 150 }); } }); } else if (element === 'light') { // Lightning effect - bright yellow flash tween(warriorGraphics, { tint: 0xffff00, alpha: 1.5, scaleX: 1.2, scaleY: 1.2 }, { duration: 150, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); } else if (element === 'wind') { // Wind swirl effect - green spiral tween(warriorGraphics, { tint: 0x44ff44, rotation: Math.PI * 2, scaleX: 1.1, scaleY: 1.1 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(warriorGraphics, { tint: 0xffffff, rotation: 0, scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); } game.addChild(warrior); warriors.push(warrior); var sound = LK.getSound('summon'); sound.volume = soundValue; sound.play(); // Add jump effect to all units when any warrior is summoned // Make all warriors jump for (var i = 0; i < warriors.length; i++) { var jumpWarrior = warriors[i]; // Store current Y position if not already stored if (jumpWarrior.baseY === 0) { jumpWarrior.baseY = jumpWarrior.y; } // Apply jump tween - go up then back down tween(jumpWarrior, { y: jumpWarrior.baseY - 100 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(jumpWarrior, { y: jumpWarrior.baseY }, { duration: 200, easing: tween.easeIn }); } }); } // Make all enemies jump for (var i = 0; i < enemies.length; i++) { var jumpEnemy = enemies[i]; // Store current Y position if not already stored if (jumpEnemy.baseY === 0) { jumpEnemy.baseY = jumpEnemy.y; } // Apply jump tween - go up then back down tween(jumpEnemy, { y: jumpEnemy.baseY - 100 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(jumpEnemy, { y: jumpEnemy.baseY }, { duration: 200, easing: tween.easeIn }); } }); } } function playMelodySequenceWithIntervals(combination, intervals) { // Wait 1 second before starting melody playback to differentiate from invocation LK.setTimeout(function () { // Play notes sequentially using cumulative timing var cumulativeDelay = 0; for (var i = 0; i < combination.length; i++) { var element = combination[i]; // First note plays immediately (0ms), subsequent notes use intervals var delay = i === 0 ? 0 : cumulativeDelay; // Use setTimeout with closure to preserve the element value (function (noteElement, currentDelay) { LK.setTimeout(function () { // Play the appropriate elemental note sound with controlled volume if (noteElement === 'fire') { var fireSound = LK.getSound('Nota_Fire'); fireSound.volume = soundValue; fireSound.play(); } else if (noteElement === 'water') { var waterSound = LK.getSound('Nota_Water'); waterSound.volume = soundValue; waterSound.play(); } else if (noteElement === 'earth') { var earthSound = LK.getSound('Nota_Earth'); earthSound.volume = soundValue; earthSound.play(); } else if (noteElement === 'wind') { var windSound = LK.getSound('Nota_Wind'); windSound.volume = soundValue; windSound.play(); } else if (noteElement === 'light') { var lightSound = LK.getSound('Nota_Light'); lightSound.volume = soundValue; lightSound.play(); } else { var summonSound = LK.getSound('summon'); summonSound.volume = soundValue; summonSound.play(); } }, currentDelay); })(element, delay); // Add interval for next note (skip first note since it's 0) if (i < intervals.length && i > 0) { cumulativeDelay += intervals[i]; } else if (i === 0 && intervals.length > 1) { // For first note, set cumulative delay to the second interval cumulativeDelay = intervals[1]; } } }, 500); // 0.5 second delay before melody playback } function playMelodySequence(combination) { // Wait 1 second before starting melody playback to differentiate from invocation LK.setTimeout(function () { // Play each note in the combination using recorded timing intervals var cumulativeDelay = 0; for (var i = 0; i < combination.length; i++) { var element = combination[i]; var delay = cumulativeDelay; // Use setTimeout with closure to preserve the element value (function (noteElement, currentDelay) { LK.setTimeout(function () { // Play the appropriate elemental note sound with controlled volume if (noteElement === 'fire') { var fireSound = LK.getSound('Nota_Fire'); fireSound.volume = soundValue; fireSound.play(); } else if (noteElement === 'water') { var waterSound = LK.getSound('Nota_Water'); waterSound.volume = soundValue; waterSound.play(); } else if (noteElement === 'earth') { var earthSound = LK.getSound('Nota_Earth'); earthSound.volume = soundValue; earthSound.play(); } else if (noteElement === 'wind') { var windSound = LK.getSound('Nota_Wind'); windSound.volume = soundValue; windSound.play(); } else if (noteElement === 'light') { var lightSound = LK.getSound('Nota_Light'); lightSound.volume = soundValue; lightSound.play(); } else { var summonSound = LK.getSound('summon'); summonSound.volume = soundValue; summonSound.play(); } }, currentDelay); })(element, delay); // Update cumulative delay for next note if (i < noteTimingIntervals.length) { cumulativeDelay += noteTimingIntervals[i]; } else if (i > 0) { // Fallback to 200ms if no interval recorded cumulativeDelay += 200; } } }, 1000); // 1 second delay before melody playback } function resetCombination() { currentCombination = []; combinationTimer = 0; combinationCooldown = 0; temporaryNoteCounter = 0; // Reset helper counter // Don't reset timing intervals here - they should persist until new combination starts // Only reset when a new note is pressed // Update display only when actually clearing intervals } function showCombinationMessage(message) { combinationMessageText.setText(message); combinationMessageText.alpha = 1.0; // Fade out message after 2 seconds tween(combinationMessageText, { alpha: 0 }, { duration: 2000 }); } game.down = function (x, y, obj) { // Handle initial touch in game layer directly // Store initial touch position for debug initialTouchX = x; initialTouchY = y; currentTouchX = x; currentTouchY = y; if (touchDebugText && typeof touchDebugText.setText === 'function') { touchDebugText.setText('Touch Info: Initial(' + Math.round(x) + ',' + Math.round(y) + ') Current(' + Math.round(x) + ',' + Math.round(y) + ')'); } if (obj.event && obj.event.button === 2) { // Right mouse button isDragging = true; lastMouseX = x; obj.event.preventDefault(); // Prevent context menu } }; leftButton.down = function (x, y, obj) { // Move camera left cameraX -= 100; cameraX = Math.max(0, Math.min(cameraX, maxCameraX)); game.x = -cameraX; // Visual feedback tween(leftButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(leftButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); }; rightButton.down = function (x, y, obj) { // Move camera right cameraX += 100; cameraX = Math.max(0, Math.min(cameraX, maxCameraX)); game.x = -cameraX; // Visual feedback tween(rightButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(rightButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); }; game.up = function (x, y, obj) { if (obj.event && obj.event.button === 2) { // Right mouse button isDragging = false; } }; game.move = function (x, y, obj) { if (isDragging) { var deltaX = lastMouseX - x; cameraX += deltaX; cameraX = Math.max(0, Math.min(cameraX, maxCameraX)); game.x = -cameraX; lastMouseX = x; } // Update current touch position for debug (game coordinates) currentTouchX = x; currentTouchY = y; // Update debug text with both initial and current positions if (touchDebugText && typeof touchDebugText.setText === 'function') { touchDebugText.setText('Game Move - Initial(' + Math.round(initialTouchX) + ',' + Math.round(initialTouchY) + ') Current(' + Math.round(currentTouchX) + ',' + Math.round(currentTouchY) + ')'); } }; // Add GUI move handler for touch tracking LK.gui.topLeft.move = function (x, y, obj) { // Update current touch position for debug (GUI coordinates) currentTouchX = x; currentTouchY = y; // Update debug text with both initial and current positions if (touchDebugText && typeof touchDebugText.setText === 'function') { touchDebugText.setText('GUI Move - Initial(' + Math.round(initialTouchX) + ',' + Math.round(initialTouchY) + ') Current(' + Math.round(currentTouchX) + ',' + Math.round(currentTouchY) + ')'); } }; // Cloud system for background decoration var clouds = []; var cloudSpawnTimer = 0; function createCloud() { var cloud = new Nube(); cloud.x = -200; // Start off-screen left // Create clouds randomly between y=0 and y=1000 with depth layering cloud.y = Math.random() * 2000; // Random position between y=0 and y=2000 cloud.startFloating(); // Start floating animation after position is set // Determine if cloud is background (behind game) or foreground (in front of game) var isBackground = Math.random() < 0.6; // 60% chance to be background if (isBackground) { // Background clouds - behind game elements, more transparent // Scale already randomized in Nube constructor, apply additional uniform background scaling var additionalScale = 0.5 + Math.random() * 0.6; // Apply additional 50-110% scaling cloud.scaleX *= additionalScale; cloud.scaleY *= additionalScale; cloud.alpha = 0.4 + Math.random() * 0.5; // Random opacity between 40% and 90% cloud.children[0].tint = 0xE0E0E0; // Slightly darker for background effect // Add background clouds before other game elements game.addChildAt(cloud, 0); // Add at index 0 to be behind everything } else { // Foreground clouds - in front of game elements, more visible // Scale already randomized in Nube constructor, apply additional uniform foreground scaling var additionalScale = 0.8 + Math.random() * 0.8; // Apply additional 80-160% scaling cloud.scaleX *= additionalScale; cloud.scaleY *= additionalScale; cloud.alpha = 0.4 + Math.random() * 0.5; // Random opacity between 40% and 90% cloud.children[0].tint = 0xF8F8F8; // Brighter for foreground effect // Add foreground clouds on top of game elements game.addChild(cloud); // Add normally to be in front } // Vary speed based on position for depth effect if (cloud.y < 600) { // Higher clouds move slower (distance effect) cloud.baseSpeed = cloud.baseSpeed * 0.5; } else if (cloud.y > 1400) { // Lower clouds move faster (proximity effect) cloud.baseSpeed = cloud.baseSpeed * 1.5; } clouds.push(cloud); } function updateClouds() { // Note: Cloud movement is now handled by the Nube class update method // Spawn new clouds periodically cloudSpawnTimer++; if (cloudSpawnTimer >= 300 + Math.random() * 600) { // Every 5-15 seconds createCloud(); cloudSpawnTimer = 0; } } // Create initial clouds for (var i = 0; i < 24; i++) { // Doubled number for better coverage var cloud = new Nube(); cloud.x = Math.random() * 4000; // Random initial position across screen // Create clouds randomly between y=0 and y=1000 with depth layering cloud.y = Math.random() * 2000; // Random position between y=0 and y=2000 cloud.startFloating(); // Start floating animation after position is set // Determine if cloud is background (behind game) or foreground (in front of game) var isBackground = Math.random() < 0.6; // 60% chance to be background if (isBackground) { // Background clouds - behind game elements, more transparent // Scale already randomized in Nube constructor, apply additional uniform background scaling var additionalScale = 0.5 + Math.random() * 0.6; // Apply additional 50-110% scaling cloud.scaleX *= additionalScale; cloud.scaleY *= additionalScale; cloud.alpha = 0.4 + Math.random() * 0.5; // Random opacity between 40% and 90% cloud.children[0].tint = 0xE0E0E0; // Slightly darker for background effect // Add background clouds before other game elements game.addChildAt(cloud, 0); // Add at index 0 to be behind everything } else { // Foreground clouds - in front of game elements, more visible // Scale already randomized in Nube constructor, apply additional uniform foreground scaling var additionalScale = 0.8 + Math.random() * 0.8; // Apply additional 80-160% scaling cloud.scaleX *= additionalScale; cloud.scaleY *= additionalScale; cloud.alpha = 0.4 + Math.random() * 0.5; // Random opacity between 40% and 90% cloud.children[0].tint = 0xF8F8F8; // Brighter for foreground effect // Add foreground clouds on top of game elements game.addChild(cloud); // Add normally to be in front } // Vary speed based on position for depth effect if (cloud.y < 600) { // Higher clouds move slower (distance effect) cloud.baseSpeed = cloud.baseSpeed * 0.5; } else if (cloud.y > 1400) { // Lower clouds move faster (proximity effect) cloud.baseSpeed = cloud.baseSpeed * 1.5; } clouds.push(cloud); } // Function to simulate music beat detection based on game timing function getGameMusicLevel() { // Simulate music beats based on game ticks and music timing // Create a beat pattern that varies over time var beatPattern = Math.sin(LK.ticks * 0.1) * 0.3 + 0.5; // Base sine wave var strongBeat = Math.sin(LK.ticks * 0.05) * 0.4; // Slower variation for stronger beats var randomVariation = (Math.random() - 0.5) * 0.2; // Add some randomness // Combine patterns to create realistic music-like variation var musicLevel = beatPattern + strongBeat + randomVariation; // Ensure the value stays within realistic bounds (0.0 to 1.0) musicLevel = Math.max(0, Math.min(1, musicLevel)); return musicLevel; } // Start background music with initial volume from slider LK.playMusic('Music', { volume: musicValue }); game.update = function () { // Music beat detection and character synchronization var audioLevel = getGameMusicLevel(); // Calculate sensitivity difference for debug display var sensitivityDifference = Math.max(0, audioLevel - musicBeatThreshold); // Update audio debug text in real-time if (audioDebugText && typeof audioDebugText.setText === 'function') { audioDebugText.setText('Audio: ' + audioLevel.toFixed(3) + ' | Threshold: ' + musicBeatThreshold.toFixed(2) + ' | Diff: ' + sensitivityDifference.toFixed(3)); } // Enhanced beat detection with multiple triggers var beatDetected = false; // Primary beat detection - only when audio level reaches 1 if (audioLevel >= 1.0 && LK.ticks - lastBeatTime > beatCooldown) { beatDetected = true; } // Remove fallback timer-based beat detection to prevent constant particle spam if (beatDetected) { // Beat detected - activate effect on all characters lastBeatTime = LK.ticks; // Activate effect on warriors for (var i = 0; i < warriors.length; i++) { warriors[i].beatEffectTimer = 120; // 2 seconds of sine wave effect } // Activate effect on enemies for (var i = 0; i < enemies.length; i++) { enemies[i].beatEffectTimer = 120; // 2 seconds of sine wave effect } // Activate particle effects on towers instead of scaling // Create particles around player tower in cone shape for (var p = 0; p < 24; p++) { // Calculate cone angle - wider at the top, narrower at bottom var angle = (Math.random() - 0.5) * Math.PI * 0.5; // 90 degree cone spread var distance = Math.random() * 300 + 100; // Random distance from center var startX = playerTower.x + Math.sin(angle) * (distance * 0.3); // Narrow at bottom var endX = playerTower.x + Math.sin(angle) * distance; // Wide at top var playerTowerCurrentScale = playerTower.scaleX; // Get current tower scale var scaledOffsetY = (1728 - 50) * playerTowerCurrentScale; // Scale the Y offset var particle = game.addChild(LK.getAsset('particula_torre_jugador', { anchorX: 0.5, anchorY: 0.5, x: startX + 100, y: playerTower.y - scaledOffsetY, width: 300 + Math.random() * 200, height: 300 + Math.random() * 200, rotation: Math.PI })); particle.alpha = 0.8; // Animate particles upward to the sky in cone shape and fade out tween(particle, { y: playerTower.y - 2000 - Math.random() * 500, x: endX + 100, alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 3000 + Math.random() * 500, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Create particles around enemy tower in cone shape for (var p = 0; p < 24; p++) { // Calculate cone angle - wider at the top, narrower at bottom var angle = (Math.random() - 0.5) * Math.PI * 0.5; // 90 degree cone spread var distance = Math.random() * 300 + 100; // Random distance from center var startX = enemyTower.x + Math.sin(angle) * (distance * 0.3); // Narrow at bottom var endX = enemyTower.x + Math.sin(angle) * distance; // Wide at top var enemyTowerCurrentScale = enemyTower.scaleX; // Get current tower scale var scaledOffsetY = (1728 - 50) * enemyTowerCurrentScale; // Scale the Y offset var particle = game.addChild(LK.getAsset('particula_torre_enemiga', { anchorX: 0.5, anchorY: 0.5, x: startX, y: enemyTower.y - scaledOffsetY, width: 300 + Math.random() * 200, height: 300 + Math.random() * 200, rotation: Math.PI })); particle.alpha = 0.8; // Animate particles upward to the sky in cone shape and fade out tween(particle, { y: enemyTower.y - 2000 - Math.random() * 500, x: endX, alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 3000 + Math.random() * 500, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } } // Mana regeneration - every 10 seconds (600 frames at 60fps) manaRegenTimer++; if (manaRegenTimer >= 600) { if (currentMana < maxMana) { currentMana++; updateManaDisplay(); } manaRegenTimer = 0; } // Spawn enemies periodically enemySpawnTimer++; if (enemySpawnTimer >= 180) { // Every 3 seconds spawnEnemy(); enemySpawnTimer = 0; } // Clean up off-screen warriors for (var i = warriors.length - 1; i >= 0; i--) { var warrior = warriors[i]; if (warrior.x > 4000) { warrior.destroy(); warriors.splice(i, 1); } } // Clean up off-screen enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.x < -200) { enemy.destroy(); enemies.splice(i, 1); } } // Update cloud system updateClouds(); // Update temporary counter info text tempCounterInfoText.setText('Notas presionadas: ' + temporaryNoteCounter); // Update sound value debug text soundValueText.setText('soundValue: ' + soundValue.toFixed(2)); // Update combination system timers if (combinationTimer > 0) { combinationTimer--; if (combinationTimer <= 0 && currentCombination.length > 0) { // Time window expired, process current combination processCombination(); } } if (combinationCooldown > 0) { combinationCooldown--; if (combinationCooldown <= 0 && currentCombination.length > 0) { // Reset timeout reached, clear combination showCombinationMessage('Tiempo agotado - Combinación reiniciada'); resetCombination(); // Re-enable buttons after timeout enableNoteButtons(); } } };
===================================================================
--- original.js
+++ change.js
@@ -1236,12 +1236,23 @@
var newVolume = (currentVolume + 10) % 110; // Cycle through 0-100 by 10s
updateSoundVolume(newVolume);
};
settingsButton.down = function (x, y, obj) {
- // Play settings click sound with dynamic volume
+ // Play settings click sound with dynamic volume - test different volumes
var settingsSound = LK.getSound('settings_click');
- settingsSound.volume = 0; // Apply current soundValue with 70% modifier
+ settingsSound.volume = soundValue * 0.7; // Apply current soundValue with 70% modifier
settingsSound.play();
+ // Debug: Test volume sequence to verify dynamic control works
+ LK.setTimeout(function () {
+ var testSound = LK.getSound('settings_click');
+ testSound.volume = 0.1; // Very quiet test
+ testSound.play();
+ }, 500);
+ LK.setTimeout(function () {
+ var testSound2 = LK.getSound('settings_click');
+ testSound2.volume = 1.0; // Full volume test
+ testSound2.play();
+ }, 1000);
// Visual feedback with bounce effect
tween(settingsButton, {
scaleX: 0.85,
scaleY: 0.85,
Generame un guerrero azteca con patrones, estilo pixelar, ademas sera un El lagarto azul de Gorgona humanoide. Va tener una armadura roja con efetos de llamitas pequeñas. In-Game asset. 2d. High contrast. No shadows
Genérame una Rana de dardo venenosa guerra azteca con eso patrones estilo pixelar, con una apariencia maligna. In-Game asset. 2d. High contrast. No shadows
geerame una esmeralda pixelar. In-Game asset. 2d. High contrast. No shadows
Generame una boton con dentro de forma de una nota musical con efectos de agua.. In-Game asset. 2d. High contrast. No shadows
Generame una boton con dentro de forma de una nota musical con efectos de fuego .. In-Game asset. 2d. High contrast. No shadows
Generame una boton con dentro de forma de una nota musical con efectos de energia. In-Game asset. 2d. High contrast. No shadows
Generame una boton con dentro de forma de una nota musical con efectos de viento. In-Game asset. 2d. High contrast. No shadows
Generame una boton con dentro de forma de una nota musical con efectos de tierra. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero voaldor Colibrí esmeralda del Chiribiquete estilo azteca con patrones, estilo pixelar. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero meduza cone fectos de agua, que cura como mago, estilo pixelar, ambeintado a lo azteca. In-Game asset. 2d. High contrast. No shadows
Generame un jaguar guerrero con efectos de energia estilo magico, pixelar, con ambientacion azteca. In-Game asset. 2d. High contrast. No shadows
Proyectil agua pixelar. In-Game asset. 2d. High contrast. No shadows
Luz oscura particulas, moradas. In-Game asset. 2d. High contrast. No shadows
Particula de luz. In-Game asset. 2d. High contrast. No shadows
Generame una piedras corrupta
Genérame una MONO TITÍ guerra azteca con eso patrones estilo pixelar, con una apariencia maligna.. In-Game asset. 2d. High contrast. No shadows
Genérame un Tucan guerra azteca con eso patrones estilo pixelar, con una apariencia maligna. In-Game asset. 2d. High contrast. No shadows
Un signo de más en verde. In-Game asset. 2d. High contrast. No shadows
Un proyectil de electricidad pixelar. In-Game asset. 2d. High contrast. No shadows
Generame una explosion de este proyectil de forma circular
Creame una nubes pixelar. In-Game asset. 2d. High contrast. No shadows
Una tuerca pixelar como boton. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, ademas sera un Tortuga de ciénaga colombiana humanoide. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, ademas sera una iguana humanoide, con efectos de fuego. In-Game asset. 2d. High contrast. No shadows
Agregale efectos de fuego pero en un fondo de alto contraste, mejor dicho solo pono mas rojo y llmas en la espada
Agregale lava y fuego a esta textrua
Creame una explosion de fuego pixelar. In-Game asset. 2d. High contrast. No shadows
agregale un poquito de ver y azul sin perder la identidad de l aimagen, solo cuadrar colores
Generame un guerrero azteca con patrones, estilo pixelar, además será una Pez loro, con efectos de AGUA. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será una Cangrejo violinista, con efectos de AGUA. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será una Delfin Rosado con efectos de AGUA. In-Game asset. 2d. High contrast. No shadows
Generame unm meteorito pixelar elemental con todos los elementos. In-Game asset. 2d. High contrast. No shadows
particulas rosadas, de poder. In-Game asset. 2d. High contrast. No shadows
Haz este candando con los 5 ewlementos, fuego tierra, agua, aire, energia
Creame un cielo pixelar hermoso, sin sol ni nubes, ni montañas, nia rboles. In-Game asset. 2d. High contrast. No shadows
Generame una montañas pixelar en fondo blanco. In-Game asset. 2d. High contrast. No shadows
Generame una montañas de selva pixelar en fondo blanco, cercanas. In-Game asset. 2d. High contrast. No shadows
Generame un muro pixelar de tierra isometrico con aptornes aztecas. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será un animal Tapir, con efectos de tierra, cargando un gran escudo o muro.. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será un animal Anaconda verde, con efectos de tierra, cargando un gran escudo o muro.. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será un animal manati con efectos de tierra, cargando un enrome muro. gigante. In-Game asset. 2d. High contrast. No shadows
uan flor pixelar para plantar, sin matera sola una hermosa flor. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será un Cóndor de los Andes, unidad voladora con alas, con efectos de viento. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será una Mariposa alas de vidrio (Greta oto), unidad voladora con alas, con efectos de viento. Tiene que ser un animal.. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será Murciélago frugívoro, unidad voladora con alas, con efectos de viento. Tiene que ser un animal.. In-Game asset. 2d. High contrast. No shadows
Generame un guerrero azteca con patrones, estilo pixelar, además será Tucán toco , unidad voladora con alas, con efectos de viento. Tiene que ser un animal.. In-Game asset. 2d. High contrast. No shadows
Gotas de agua pixelar. In-Game asset. 2d. High contrast. No shadows
Genrame un muro con mas detalle que se vea superior es decir un nivel mas fuerte.
Generame una particula de espora pixela rt. In-Game asset. 2d. High contrast. No shadows
z de sueño pixelar. In-Game asset. 2d. High contrast. No shadows
Generame una lanza pixelar. In-Game asset. 2d. High contrast. No shadows
Creame un tornado pixelar en un fondo azul, para elimianrlo despues. In-Game asset. 2d. High contrast. No shadows
Hazme el rayo de color amarillo
Creame un boton de este personaje extilo pixelar cuadrado
POnlo trizte el perosnaje y gris el boton
Jugar
Pon una casa
deja todo naranaja
Genérame una Jaguar guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. In-Game asset. 2d. High contrast. No shadows
Genérame una Oso de Anteojos guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. In-Game asset. 2d. High contrast. No shadows
Genérame una Pecari de collar guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. In-Game asset. 2d. High contrast. No shadows
Genérame una Puma guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Tayra guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Nutria Neotropical guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Caiman llanero guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Capibara guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Zorro Cangrejero guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Demonio de Tasmnia guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. POderes, super rojo y rabioso, como un ejfe final. Animal. No tiene arams solo una gran y poderosa mordida. In-Game asset. 2d. High contrast. No shadows
Genérame una olibrí Esmeralda Andina guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Zopilote Rey guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Paujil guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Halcon Murcielago guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Buho de anteojos guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Mariposa monarca guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Chicharra guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una paloma guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad aerea con alas. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Rana de Cristal guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Iguana Verde guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Boa de arcoiris guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Ciempies gigante amazonico guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Escorpion Colombiano guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Araña guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con un arco o cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Pez leon guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Serpiente coral guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame una Rana de dardo venenosa guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad a distancia, con cerbatana. Animal. In-Game asset. 2d. High contrast. No shadows
Genérame un hipopotamo guerrero azteca con eso patrones, estilo pixelar, con una apariencia maligna, ojos rojos, rabioso. Unidad cuerpo a cuerpo. Animal.. In-Game asset. 2d. High contrast. No shadows
Flecha maligna, de color rojo, pixelar. In-Game asset. 2d. High contrast. No shadows
Luna llena blanca, pixelar. In-Game asset. 2d. High contrast. No shadows
sol pixelart. In-Game asset. 2d. High contrast. No shadows
Un cielo noche pixelar 16:04 con estrellas. In-Game asset. 2d. High contrast. No shadows
Hazme un boton pixelar azteca, que diga Fin. In-Game asset. 2d. High contrast. No shadows
Nota_Fire
Sound effect
tower_damage
Sound effect
combat
Sound effect
enemy_death
Sound effect
combatir_1
Sound effect
Music
Music
combatir_2
Sound effect
combatir_3
Sound effect
combatir_4
Sound effect
attack
Sound effect
Nota_Water
Sound effect
Nota_Earth
Sound effect
Nota_Wind
Sound effect
Nota_Light
Sound effect
sonido_torre_2
Sound effect
sonido_torre_3
Sound effect
sonido_torre_4
Sound effect
sonido_torre_1
Sound effect
sonido_proyectil_agua_1
Sound effect
sonido_proyectil_agua_2
Sound effect
sonido_proyectil_agua_3
Sound effect
sonido_proyectil_agua_4
Sound effect
sonido_proyectil_viento_1
Sound effect
sonido_proyectil_viento_2
Sound effect
sonido_proyectil_viento_3
Sound effect
sonido_proyectil_viento_4
Sound effect
sonido_proyectil_energia_1
Sound effect
sonido_proyectil_energia_2
Sound effect
sonido_proyectil_energia_3
Sound effect
sonido_proyectil_energia_4
Sound effect
settings_click
Sound effect
burn_sound
Sound effect
musicId
Music
Level_1_en
Sound effect
Level_1_es
Sound effect
Level_2_en
Sound effect
Level_3_en
Sound effect
Level_4_en
Sound effect
Level_5_en
Sound effect
Level_6_en
Sound effect
Level_7_en
Sound effect
Level_9_en
Sound effect
Level_10_en
Sound effect
Level_11_en
Sound effect
Level_12_en
Sound effect
Level_13_en
Sound effect
Level_14_en
Sound effect
Level_15_en
Sound effect
Level_16_en
Sound effect
Level_17_en
Sound effect
Level_18_en
Sound effect
Level_19_en
Sound effect
Level_20_en
Sound effect
Level_21_en
Sound effect
Level_22_en
Sound effect
Level_23_en
Sound effect
Level_24_en
Sound effect
Level_25_en
Sound effect
Level_26_en
Sound effect
Level_2_es
Sound effect
Level_3_es
Sound effect
Level_4_es
Sound effect
Level_5_es
Sound effect
Level_6_es
Sound effect
Level_7_es
Sound effect
Level_8_es
Sound effect
Level_9_es
Sound effect
Level_10_es
Sound effect
Level_11_es
Sound effect
Level_12_es
Sound effect
Level_13_es
Sound effect
Level_14_es
Sound effect
Level_15_es
Sound effect
Level_16_es
Sound effect
Level_17_es
Sound effect
Level_18_es
Sound effect
Level_19_es
Sound effect
Level_20_es
Sound effect
Level_21_es
Sound effect
Level_22_es
Sound effect
Level_23_es
Sound effect
Level_24_es
Sound effect
Level_25_es
Sound effect
Level_26_es
Sound effect
Level_8_en
Sound effect
ganar
Sound effect
comic1_sound
Sound effect
comic2_sound
Sound effect
comic3_sound
Sound effect
comic4_sound
Sound effect
comic5_sound
Sound effect
comic6_sound
Sound effect
comic7_sound
Sound effect
comic8_sound
Sound effect
comic9_sound
Sound effect
comic10_sound
Sound effect
comic11_sound
Sound effect
music_menu_en
Music
music_menu_es
Music
Music2
Music
Music3
Music
Music4
Music
Music5
Music
Music8
Music
Music7
Music
Nota_Earth2
Sound effect
Nota_Fire2
Sound effect
Nota_Light2
Sound effect
Nota_Water2
Sound effect
Nota_Wind2
Sound effect
explosion_meteorito
Sound effect
muerte_guerrero
Sound effect
MusicVictoria
Music