User prompt
que el personage aguante 3 golpes
User prompt
que el juego sea infinito
User prompt
un menu
User prompt
que el menu prinsipal tenga las obciones de obciones jugar y creditos
User prompt
que haya un menu prinsipal
User prompt
que el personage aguanta 3 ataques
User prompt
que el juego sea infinito
User prompt
que los ataques sean un fuego teledirigido y un orbe explosivo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
crea 2 ataques nuevos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que hayan 4 enemigos mas
User prompt
que tenga un sistema de ordas que aumentan la dificultad
User prompt
que haya un refugio que luego de 10000 puntos el personage entre y le de un multiplicador de daño mas un escudo al salir por 6 seg ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
añade una vase que luego de tener sierto puntage el personage entre a resguardarse
User prompt
que el ataque de orbe no se pueda tirar mas de 7 veses por orda
User prompt
que el ataque de orbe tenga un tiempo de 7 seg de recarga
User prompt
que el ataque de orbe tenga una recarga de 7
User prompt
que los enemigos tengan una barra de vida
User prompt
ahora que el proyectil ligrto se active con un boton
User prompt
que cada enemigo tenga distinta cantidad de vida
User prompt
ahora que el ataque de luz tenga solo 12 seg de recarga
User prompt
ahora que el ataque de luz tenga una recarga de 3 segundos y que elimine a todos los enemigos en pantalla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que el ataque de fuego valla directamente al enemigo
User prompt
que los ataques del personage se activen con un boton en pantalla
User prompt
que haya una gran bariedad de monstruos
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BerserkerShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('berserkerShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.5 + Math.random() * 1; self.health = 5; self.maxHealth = 5; self.monsterType = 'berserker'; self.enraged = false; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); // Enrage when health is low if (self.health <= self.maxHealth * 0.4 && !self.enraged) { self.enraged = true; self.speed *= 2; shadowGraphics.tint = 0xff0000; } self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Berserker effect when enraged if (self.enraged) { var shake = (Math.random() - 0.5) * 4; self.x += shake; self.y += shake; // Pulsing red effect var pulse = 1 + Math.sin(LK.ticks * 0.8) * 0.5; shadowGraphics.scaleX = pulse; shadowGraphics.scaleY = pulse; } // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var BomberShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('bomberShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2 + Math.random() * 1; self.health = 2; self.maxHealth = 2; self.monsterType = 'bomber'; self.exploding = false; self.explosionTimer = 30; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); var distanceToHero = Math.sqrt(Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2)); if (distanceToHero < 100 && !self.exploding) { self.exploding = true; shadowGraphics.tint = 0xff4444; } if (self.exploding) { self.explosionTimer--; var flash = Math.sin(self.explosionTimer * 0.5) > 0 ? 0xff0000 : 0xffff00; shadowGraphics.tint = flash; if (self.explosionTimer <= 0) { // Create explosion effect for (var i = 0; i < 6; i++) { var explosionAngle = i / 6 * Math.PI * 2; var fragment = new Shadow(); fragment.x = self.x + Math.cos(explosionAngle) * 20; fragment.y = self.y + Math.sin(explosionAngle) * 20; fragment.speed = 2; shadows.push(fragment); game.addChild(fragment); } } } else { self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var FastShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('fastShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3 + Math.random() * 2; self.health = 1; self.maxHealth = 1; self.monsterType = 'fast'; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Add erratic movement self.x += Math.sin(LK.ticks * 0.2) * 2; self.y += Math.cos(LK.ticks * 0.15) * 2; // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var FireSpell = Container.expand(function () { var self = Container.call(this); var spellGraphics = self.attachAsset('fireSpell', { anchorX: 0.5, anchorY: 0.5 }); self.lifetime = 30; // Half second self.radius = 80; self.update = function () { self.lifetime--; // Grow the spell var scale = 1 + (30 - self.lifetime) / 30; spellGraphics.scaleX = scale; spellGraphics.scaleY = scale; spellGraphics.alpha = self.lifetime / 30; }; return self; }); var HealerShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('healerShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0.8 + Math.random() * 0.5; self.health = 3; self.maxHealth = 3; self.monsterType = 'healer'; self.lastHeal = 0; self.healCooldown = 120; // 2 seconds // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Healing ability if (LK.ticks - self.lastHeal > self.healCooldown) { for (var i = 0; i < shadows.length; i++) { var otherShadow = shadows[i]; if (otherShadow !== self) { var distance = Math.sqrt(Math.pow(self.x - otherShadow.x, 2) + Math.pow(self.y - otherShadow.y, 2)); if (distance < 150 && otherShadow.health < otherShadow.maxHealth) { otherShadow.health = Math.min(otherShadow.maxHealth, otherShadow.health + 1); LK.effects.flashObject(otherShadow, 0x00ff00, 300); self.lastHeal = LK.ticks; break; } } } } // Pulsing green effect var pulse = 1 + Math.sin(LK.ticks * 0.4) * 0.3; shadowGraphics.tint = 0x44ff44; shadowGraphics.scaleX = pulse; shadowGraphics.scaleY = pulse; // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.lightPower = 1; self.fireRate = 60; // Fire every 60 ticks initially self.lastLightShot = 0; self.update = function () { // Hero update method - no automatic firing }; return self; }); var LightOrb = Container.expand(function () { var self = Container.call(this); var orbGraphics = self.attachAsset('lightOrb', { anchorX: 0.5, anchorY: 0.5 }); self.bobOffset = Math.random() * Math.PI * 2; self.baseY = self.y; self.update = function () { self.y = self.baseY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 10; }; return self; }); var LightProjectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('lightProjectile', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.lifetime = 180; // 3 seconds at 60fps self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.lifetime--; }; return self; }); var MimicShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('mimicShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.8 + Math.random() * 1.2; self.health = 2; self.maxHealth = 2; self.monsterType = 'mimic'; self.lastCopy = 0; self.copyCooldown = 240; // 4 seconds self.copyTarget = null; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Copy nearest enemy abilities if (LK.ticks - self.lastCopy > self.copyCooldown) { var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < shadows.length; i++) { var otherShadow = shadows[i]; if (otherShadow !== self && otherShadow.monsterType !== 'mimic') { var distance = Math.sqrt(Math.pow(self.x - otherShadow.x, 2) + Math.pow(self.y - otherShadow.y, 2)); if (distance < 200 && distance < nearestDistance) { nearestDistance = distance; nearestEnemy = otherShadow; } } } if (nearestEnemy) { self.copyTarget = nearestEnemy.monsterType; self.lastCopy = LK.ticks; // Visual feedback LK.effects.flashObject(self, 0xff00ff, 500); // Copy some properties if (nearestEnemy.monsterType === 'fast') { self.speed = nearestEnemy.speed; shadowGraphics.tint = 0xffff00; } else if (nearestEnemy.monsterType === 'tank') { self.health = Math.min(self.maxHealth + 2, nearestEnemy.health); shadowGraphics.tint = 0x888888; } else if (nearestEnemy.monsterType === 'teleporter') { shadowGraphics.tint = 0x8844ff; } } } // Rainbow shifting effect var hue = LK.ticks * 0.05 % 1; var r = Math.sin(hue * Math.PI * 2) * 127 + 128; var g = Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128; var b = Math.sin((hue + 0.66) * Math.PI * 2) * 127 + 128; var color = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b); shadowGraphics.tint = color; // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var Shadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1 + Math.random() * 2; self.health = 2; self.maxHealth = 2; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var ShielderShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('shielderShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.2 + Math.random() * 0.8; self.health = 4; self.maxHealth = 4; self.monsterType = 'shielder'; self.shieldActive = false; self.lastShield = 0; self.shieldCooldown = 180; // 3 seconds self.shieldDuration = 120; // 2 seconds self.shieldTimer = 0; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Shield activation when damaged if (self.health < self.maxHealth && !self.shieldActive && LK.ticks - self.lastShield > self.shieldCooldown) { self.shieldActive = true; self.shieldTimer = self.shieldDuration; self.lastShield = LK.ticks; shadowGraphics.tint = 0x4444ff; } // Shield timer if (self.shieldActive) { self.shieldTimer--; if (self.shieldTimer <= 0) { self.shieldActive = false; shadowGraphics.tint = 0xffffff; } // Pulsing blue effect when shielded var pulse = 1 + Math.sin(LK.ticks * 0.6) * 0.4; shadowGraphics.scaleX = pulse; shadowGraphics.scaleY = pulse; } // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var SplitterShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('splitterShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.5 + Math.random() * 1; self.health = 3; self.maxHealth = 3; self.monsterType = 'splitter'; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Pulsing effect var pulse = 1 + Math.sin(LK.ticks * 0.3) * 0.2; shadowGraphics.scaleX = pulse; shadowGraphics.scaleY = pulse; // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var TankShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('tankShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0.5 + Math.random() * 0.5; self.health = 8; self.maxHealth = 8; self.monsterType = 'tank'; // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; // Visual health indicator var healthPercent = self.health / self.maxHealth; shadowGraphics.alpha = 0.5 + healthPercent * 0.5; // Update health bar healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); var TeleporterShadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('teleporterShadow', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1 + Math.random() * 1; self.health = 2; self.maxHealth = 2; self.monsterType = 'teleporter'; self.lastTeleport = 0; self.teleportCooldown = 180; // 3 seconds // Create health bar var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -shadowGraphics.height / 2 - 15; var healthBarFill = self.attachAsset('healthBarFill', { anchorX: 0.5, anchorY: 0.5 }); healthBarFill.y = -shadowGraphics.height / 2 - 15; self.update = function () { var angle = Math.atan2(hero.y - self.y, hero.x - self.x); var distanceToHero = Math.sqrt(Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2)); // Teleport if far from hero and cooldown is ready if (distanceToHero > 300 && LK.ticks - self.lastTeleport > self.teleportCooldown) { var teleportDistance = 150; var teleportAngle = Math.atan2(hero.y - self.y, hero.x - self.x); self.x = hero.x - Math.cos(teleportAngle) * teleportDistance; self.y = hero.y - Math.sin(teleportAngle) * teleportDistance; self.lastTeleport = LK.ticks; LK.effects.flashObject(self, 0x8844ff, 300); } else { // Normal movement self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.scaleX = healthPercent; healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Create single cube background var cube = LK.getAsset('cube', { anchorX: 0.5, anchorY: 0.5 }); cube.x = 1024; cube.y = 1366; game.addChild(cube); var hero = game.addChild(new Hero()); hero.x = 1024; hero.y = 1366; var shadows = []; var lightProjectiles = []; var fireSpells = []; var lightOrbs = []; var lastShadowSpawn = 0; var shadowSpawnRate = 120; // Start spawning every 2 seconds var waveLevel = 1; var score = 0; var lastFireSpell = 0; var fireSpellCooldown = 90; // 1.5 seconds cooldown at 60fps var maxActiveFireSpells = 3; var lastLightAttack = 0; var lightAttackCooldown = 420; // 7 seconds cooldown at 60fps var orbsUsedThisWave = 0; var maxOrbsPerWave = 7; var waveEnemiesRemaining = 0; var waveEnemiesTotal = 0; var waveActive = false; var waveStartDelay = 0; var waveDifficultyMultiplier = 1.0; var shelterActive = false; var shelterScore = 10000; // Score threshold to activate shelter var shelterDuration = 300; // 5 seconds at 60fps var shelterTimer = 0; var shelterGraphics = null; var damageBonusActive = false; var damageBonusTimer = 0; var damageBonusDuration = 360; // 6 seconds at 60fps var shieldActive = false; var shieldTimer = 0; var shieldDuration = 360; // 6 seconds at 60fps var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var waveTxt = new Text2('Wave: 1', { size: 50, fill: 0xFFFF00 }); waveTxt.anchor.set(0.5, 0); waveTxt.y = 70; LK.gui.top.addChild(waveTxt); var waveProgressTxt = new Text2('Enemies: 0/0', { size: 40, fill: 0x00FFFF }); waveProgressTxt.anchor.set(0.5, 0); waveProgressTxt.y = 130; LK.gui.top.addChild(waveProgressTxt); // Create fire button var fireButton = LK.getAsset('fireSpell', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, alpha: 0.8 }); fireButton.x = 200; fireButton.y = 2500; game.addChild(fireButton); // Create light attack button var lightButton = LK.getAsset('lightOrb', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8, alpha: 0.8 }); lightButton.x = 1800; lightButton.y = 2500; game.addChild(lightButton); // Create light projectile button var lightProjectileButton = LK.getAsset('lightProjectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.0, scaleY: 2.0, alpha: 0.8 }); lightProjectileButton.x = 1024; lightProjectileButton.y = 2500; game.addChild(lightProjectileButton); // Fire button press handler fireButton.down = function (x, y, obj) { // Fire spell at nearest enemy - check cooldown and limit var timeSinceLastFire = LK.ticks - lastFireSpell; if (timeSinceLastFire >= fireSpellCooldown && fireSpells.length < maxActiveFireSpells && shadows.length > 0) { // Find nearest shadow var nearestShadow = null; var nearestDistance = Infinity; for (var i = 0; i < shadows.length; i++) { var distance = Math.sqrt(Math.pow(hero.x - shadows[i].x, 2) + Math.pow(hero.y - shadows[i].y, 2)); if (distance < nearestDistance) { nearestDistance = distance; nearestShadow = shadows[i]; } } ; // Light attack button press handler lightButton.down = function (x, y, obj) { // Check cooldown and orb usage limit var timeSinceLastLight = LK.ticks - lastLightAttack; if (timeSinceLastLight >= lightAttackCooldown && orbsUsedThisWave < maxOrbsPerWave) { // Destroy all enemies on screen for (var i = shadows.length - 1; i >= 0; i--) { var shadow = shadows[i]; // Create light orb for each destroyed shadow var newOrb = new LightOrb(); newOrb.x = shadow.x; newOrb.y = shadow.y; newOrb.baseY = newOrb.y; lightOrbs.push(newOrb); game.addChild(newOrb); // Add score based on monster type var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : shadow.monsterType === 'healer' ? 40 : shadow.monsterType === 'shielder' ? 35 : shadow.monsterType === 'berserker' ? 45 : shadow.monsterType === 'mimic' ? 50 : 10; score += scoreValue; // Flash effect on each enemy before destruction tween(shadow, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { shadow.destroy(); } }); shadows.splice(i, 1); } // Update score display scoreTxt.setText('Score: ' + score); // Play sound effect LK.getSound('shadowDestroy').play(); // Screen flash effect LK.effects.flashScreen(0xffffaa, 800); // Button feedback with cooldown visual LK.effects.flashObject(lightButton, 0xffffaa, 400); tween(lightButton, { alpha: 0.3 }, { duration: 0 }); tween(lightButton, { alpha: 0.8 }, { duration: lightAttackCooldown * 16.67 }); // Convert ticks to ms // Update cooldown and usage counter lastLightAttack = LK.ticks; orbsUsedThisWave++; } }; // Light projectile button press handler lightProjectileButton.down = function (x, y, obj) { // Fire light projectile var newProjectile = new LightProjectile(); newProjectile.x = hero.x; newProjectile.y = hero.y; // Fire in 8 directions var directions = 8; for (var i = 0; i < directions; i++) { var angle = i / directions * Math.PI * 2; var projectile = new LightProjectile(); projectile.x = hero.x; projectile.y = hero.y; projectile.velocityX = Math.cos(angle) * 8; projectile.velocityY = Math.sin(angle) * 8; lightProjectiles.push(projectile); game.addChild(projectile); } // Button feedback LK.effects.flashObject(lightProjectileButton, 0xffffaa, 200); }; if (nearestShadow) { var newFireSpell = new FireSpell(); newFireSpell.x = nearestShadow.x; newFireSpell.y = nearestShadow.y; fireSpells.push(newFireSpell); game.addChild(newFireSpell); lastFireSpell = LK.ticks; LK.getSound('fireBlast').play(); // Button feedback LK.effects.flashObject(fireButton, 0xff4400, 200); } } }; var dragNode = null; function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; // Keep hero within bounds if (dragNode.x < 40) dragNode.x = 40; if (dragNode.x > 2008) dragNode.x = 2008; if (dragNode.y < 40) dragNode.y = 40; if (dragNode.y > 2692) dragNode.y = 2692; } } game.move = handleMove; game.down = function (x, y, obj) { // Check if touching hero var heroDistance = Math.sqrt(Math.pow(x - hero.x, 2) + Math.pow(y - hero.y, 2)); if (heroDistance < 60) { dragNode = hero; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { dragNode = null; }; function startWave() { waveActive = true; waveStartDelay = 180; // 3 second delay before spawning waveEnemiesTotal = Math.min(5 + waveLevel * 2, 30); // Cap at 30 enemies waveEnemiesRemaining = waveEnemiesTotal; waveDifficultyMultiplier = 1.0 + (waveLevel - 1) * 0.15; // 15% increase per wave shadowSpawnRate = Math.max(30, 120 - waveLevel * 8); // Faster spawning each wave orbsUsedThisWave = 0; // Reset orb usage for new wave waveTxt.setText('Wave: ' + waveLevel); waveProgressTxt.setText('Enemies: ' + (waveEnemiesTotal - waveEnemiesRemaining) + '/' + waveEnemiesTotal); LK.effects.flashScreen(0x00FF00, 500); } game.update = function () { // Wave management if (!waveActive && shadows.length === 0) { // Start new wave when no enemies remain startWave(); } // Spawn shadows during active wave if (waveActive && waveEnemiesRemaining > 0 && waveStartDelay <= 0 && LK.ticks - lastShadowSpawn >= shadowSpawnRate) { var newShadow; // Choose random monster type based on wave level var monsterRoll = Math.random(); if (waveLevel < 3) { // Early waves: mostly basic shadows if (monsterRoll < 0.7) newShadow = new Shadow();else if (monsterRoll < 0.9) newShadow = new FastShadow();else newShadow = new TankShadow(); } else if (waveLevel < 6) { // Mid waves: introduce more variety if (monsterRoll < 0.4) newShadow = new Shadow();else if (monsterRoll < 0.6) newShadow = new FastShadow();else if (monsterRoll < 0.75) newShadow = new TankShadow();else if (monsterRoll < 0.9) newShadow = new SplitterShadow();else newShadow = new TeleporterShadow(); } else if (waveLevel < 10) { // Late waves: all monster types including dangerous ones if (monsterRoll < 0.2) newShadow = new Shadow();else if (monsterRoll < 0.35) newShadow = new FastShadow();else if (monsterRoll < 0.5) newShadow = new TankShadow();else if (monsterRoll < 0.65) newShadow = new SplitterShadow();else if (monsterRoll < 0.75) newShadow = new TeleporterShadow();else if (monsterRoll < 0.85) newShadow = new BomberShadow();else if (monsterRoll < 0.92) newShadow = new HealerShadow();else newShadow = new ShielderShadow(); } else { // Very late waves: all enemy types including new ones if (monsterRoll < 0.15) newShadow = new Shadow();else if (monsterRoll < 0.25) newShadow = new FastShadow();else if (monsterRoll < 0.35) newShadow = new TankShadow();else if (monsterRoll < 0.45) newShadow = new SplitterShadow();else if (monsterRoll < 0.55) newShadow = new TeleporterShadow();else if (monsterRoll < 0.65) newShadow = new BomberShadow();else if (monsterRoll < 0.75) newShadow = new HealerShadow();else if (monsterRoll < 0.85) newShadow = new ShielderShadow();else if (monsterRoll < 0.93) newShadow = new BerserkerShadow();else newShadow = new MimicShadow(); } // Spawn from random edge var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top newShadow.x = Math.random() * 2048; newShadow.y = -30; break; case 1: // Right newShadow.x = 2078; newShadow.y = Math.random() * 2732; break; case 2: // Bottom newShadow.x = Math.random() * 2048; newShadow.y = 2762; break; case 3: // Left newShadow.x = -30; newShadow.y = Math.random() * 2732; break; } // Apply wave difficulty multiplier newShadow.speed = (newShadow.speed + waveLevel * 0.3) * waveDifficultyMultiplier; newShadow.health = Math.ceil(newShadow.health * waveDifficultyMultiplier); newShadow.maxHealth = newShadow.health; shadows.push(newShadow); game.addChild(newShadow); lastShadowSpawn = LK.ticks; waveEnemiesRemaining--; waveProgressTxt.setText('Enemies: ' + (waveEnemiesTotal - waveEnemiesRemaining) + '/' + waveEnemiesTotal); } // Wave start delay countdown if (waveStartDelay > 0) { waveStartDelay--; } // Check if wave is complete if (waveActive && waveEnemiesRemaining <= 0 && shadows.length === 0) { waveActive = false; waveLevel++; // Wave completion bonus score += waveLevel * 50; scoreTxt.setText('Score: ' + score); LK.effects.flashScreen(0xFFFF00, 800); } // Check hero collision with shadows for (var i = 0; i < shadows.length; i++) { var shadow = shadows[i]; if (hero.intersects(shadow) && !shelterActive && !shieldActive) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Check bomber explosions if (shadow.monsterType === 'bomber' && shadow.exploding && shadow.explosionTimer <= 0) { var explosionDistance = Math.sqrt(Math.pow(hero.x - shadow.x, 2) + Math.pow(hero.y - shadow.y, 2)); if (explosionDistance < 120 && !shelterActive && !shieldActive) { LK.effects.flashScreen(0xff4400, 1000); LK.showGameOver(); return; } // Remove exploded bomber shadow.destroy(); shadows.splice(i, 1); i--; // Adjust index after removal } } // Update and check light projectiles for (var j = lightProjectiles.length - 1; j >= 0; j--) { var projectile = lightProjectiles[j]; if (projectile.lifetime <= 0 || projectile.x < -50 || projectile.x > 2098 || projectile.y < -50 || projectile.y > 2782) { projectile.destroy(); lightProjectiles.splice(j, 1); continue; } // Check collision with shadows for (var k = shadows.length - 1; k >= 0; k--) { if (projectile.intersects(shadows[k])) { var shadow = shadows[k]; // Check if enemy is shielded var damage = damageBonusActive ? 2 : 1; if (shadow.monsterType === 'shielder' && shadow.shieldActive) { damage = 0; // No damage when shielded LK.effects.flashObject(shadow, 0x4444ff, 100); } else { shadow.health -= damage; } var shadowDestroyed = false; if (shadow.health <= 0) { // Handle special monster behaviors on death if (shadow.monsterType === 'splitter' && shadow.health <= 0) { // Create two smaller fast shadows for (var split = 0; split < 2; split++) { var miniShadow = new FastShadow(); miniShadow.x = shadow.x + (split === 0 ? -30 : 30); miniShadow.y = shadow.y + (Math.random() - 0.5) * 60; miniShadow.speed *= 0.8; shadows.push(miniShadow); game.addChild(miniShadow); } } if (shadow.monsterType === 'bomber' && shadow.exploding && shadow.explosionTimer > 0) { // Bomber was destroyed while exploding, cancel explosion shadow.exploding = false; } // Create light orb var newOrb = new LightOrb(); newOrb.x = shadow.x; newOrb.y = shadow.y; newOrb.baseY = newOrb.y; lightOrbs.push(newOrb); game.addChild(newOrb); shadow.destroy(); shadows.splice(k, 1); shadowDestroyed = true; var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : shadow.monsterType === 'healer' ? 40 : shadow.monsterType === 'shielder' ? 35 : shadow.monsterType === 'berserker' ? 45 : shadow.monsterType === 'mimic' ? 50 : 10; score += scoreValue; scoreTxt.setText('Score: ' + score); LK.getSound('shadowDestroy').play(); } else { // Monster took damage but not destroyed LK.effects.flashObject(shadow, 0xffffff, 200); } projectile.destroy(); lightProjectiles.splice(j, 1); break; } } } // Update and check fire spells for (var l = fireSpells.length - 1; l >= 0; l--) { var spell = fireSpells[l]; if (spell.lifetime <= 0) { spell.destroy(); fireSpells.splice(l, 1); continue; } // Check collision with shadows for (var m = shadows.length - 1; m >= 0; m--) { var distance = Math.sqrt(Math.pow(spell.x - shadows[m].x, 2) + Math.pow(spell.y - shadows[m].y, 2)); if (distance < spell.radius) { var shadow = shadows[m]; // Check if enemy is shielded var damage = damageBonusActive ? 4 : 2; // Fire spells do more damage if (shadow.monsterType === 'shielder' && shadow.shieldActive) { damage = Math.ceil(damage / 2); // Reduced damage when shielded LK.effects.flashObject(shadow, 0x4444ff, 100); } shadow.health -= damage; if (shadow.health <= 0) { // Handle special monster behaviors on death if (shadow.monsterType === 'splitter') { // Create two smaller fast shadows for (var split = 0; split < 2; split++) { var miniShadow = new FastShadow(); miniShadow.x = shadow.x + (split === 0 ? -30 : 30); miniShadow.y = shadow.y + (Math.random() - 0.5) * 60; miniShadow.speed *= 0.8; shadows.push(miniShadow); game.addChild(miniShadow); } } if (shadow.monsterType === 'bomber' && shadow.exploding && shadow.explosionTimer > 0) { // Bomber was destroyed while exploding, cancel explosion shadow.exploding = false; } // Create light orb var newOrb = new LightOrb(); newOrb.x = shadow.x; newOrb.y = shadow.y; newOrb.baseY = newOrb.y; lightOrbs.push(newOrb); game.addChild(newOrb); shadow.destroy(); shadows.splice(m, 1); var scoreValue = shadow.monsterType === 'tank' ? 30 : shadow.monsterType === 'splitter' ? 35 : shadow.monsterType === 'teleporter' ? 25 : shadow.monsterType === 'bomber' ? 40 : shadow.monsterType === 'healer' ? 45 : shadow.monsterType === 'shielder' ? 40 : shadow.monsterType === 'berserker' ? 50 : shadow.monsterType === 'mimic' ? 55 : 15; score += scoreValue; scoreTxt.setText('Score: ' + score); LK.getSound('shadowDestroy').play(); } else { // Monster took damage but not destroyed LK.effects.flashObject(shadow, 0xff8800, 200); } } } } // Check light orb collection for (var n = lightOrbs.length - 1; n >= 0; n--) { var orb = lightOrbs[n]; if (hero.intersects(orb)) { hero.lightPower++; if (hero.fireRate > 20) { hero.fireRate -= 2; } orb.destroy(); lightOrbs.splice(n, 1); LK.getSound('collectOrb').play(); // Flash hero with light effect LK.effects.flashObject(hero, 0xffffaa, 500); } } // Shelter activation check if (score >= shelterScore && !shelterActive) { shelterActive = true; shelterTimer = shelterDuration; // Create shelter visual shelterGraphics = LK.getAsset('shelter', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); shelterGraphics.x = hero.x; shelterGraphics.y = hero.y; game.addChild(shelterGraphics); // Visual feedback for shelter activation LK.effects.flashScreen(0x00ffff, 1000); LK.effects.flashObject(hero, 0x00ffff, 1000); // Make hero semi-transparent during shelter hero.alpha = 0.5; // Pulsing effect for shelter tween(shelterGraphics, { alpha: 0.6 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(shelterGraphics, { alpha: 0.3 }, { duration: 500, easing: tween.easeInOut }); } }); } // Shelter timer countdown if (shelterActive) { shelterTimer--; // Move shelter with hero if (shelterGraphics) { shelterGraphics.x = hero.x; shelterGraphics.y = hero.y; } if (shelterTimer <= 0) { shelterActive = false; hero.alpha = 1.0; // Restore normal visibility // Remove shelter visual if (shelterGraphics) { shelterGraphics.destroy(); shelterGraphics = null; } // Activate damage bonus and shield after leaving shelter damageBonusActive = true; damageBonusTimer = damageBonusDuration; shieldActive = true; shieldTimer = shieldDuration; // Visual feedback for bonuses LK.effects.flashScreen(0xff8800, 800); LK.effects.flashObject(hero, 0xff8800, 1000); // Increase shelter score threshold for next activation shelterScore += 10000; } } // Damage bonus timer countdown if (damageBonusActive) { damageBonusTimer--; if (damageBonusTimer <= 0) { damageBonusActive = false; } } // Shield timer countdown if (shieldActive) { shieldTimer--; if (shieldTimer <= 0) { shieldActive = false; } } // Victory condition if (score >= 500) { LK.showYouWin(); } }; // Start first wave startWave();
===================================================================
--- original.js
+++ change.js
@@ -5,8 +5,57 @@
/****
* Classes
****/
+var BerserkerShadow = Container.expand(function () {
+ var self = Container.call(this);
+ var shadowGraphics = self.attachAsset('berserkerShadow', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 1.5 + Math.random() * 1;
+ self.health = 5;
+ self.maxHealth = 5;
+ self.monsterType = 'berserker';
+ self.enraged = false;
+ // Create health bar
+ var healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarBg.y = -shadowGraphics.height / 2 - 15;
+ var healthBarFill = self.attachAsset('healthBarFill', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarFill.y = -shadowGraphics.height / 2 - 15;
+ self.update = function () {
+ var angle = Math.atan2(hero.y - self.y, hero.x - self.x);
+ // Enrage when health is low
+ if (self.health <= self.maxHealth * 0.4 && !self.enraged) {
+ self.enraged = true;
+ self.speed *= 2;
+ shadowGraphics.tint = 0xff0000;
+ }
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ // Berserker effect when enraged
+ if (self.enraged) {
+ var shake = (Math.random() - 0.5) * 4;
+ self.x += shake;
+ self.y += shake;
+ // Pulsing red effect
+ var pulse = 1 + Math.sin(LK.ticks * 0.8) * 0.5;
+ shadowGraphics.scaleX = pulse;
+ shadowGraphics.scaleY = pulse;
+ }
+ // Update health bar
+ var healthPercent = self.health / self.maxHealth;
+ healthBarFill.scaleX = healthPercent;
+ healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
+ };
+ return self;
+});
var BomberShadow = Container.expand(function () {
var self = Container.call(this);
var shadowGraphics = self.attachAsset('bomberShadow', {
anchorX: 0.5,
@@ -115,8 +164,62 @@
spellGraphics.alpha = self.lifetime / 30;
};
return self;
});
+var HealerShadow = Container.expand(function () {
+ var self = Container.call(this);
+ var shadowGraphics = self.attachAsset('healerShadow', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 0.8 + Math.random() * 0.5;
+ self.health = 3;
+ self.maxHealth = 3;
+ self.monsterType = 'healer';
+ self.lastHeal = 0;
+ self.healCooldown = 120; // 2 seconds
+ // Create health bar
+ var healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarBg.y = -shadowGraphics.height / 2 - 15;
+ var healthBarFill = self.attachAsset('healthBarFill', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarFill.y = -shadowGraphics.height / 2 - 15;
+ self.update = function () {
+ var angle = Math.atan2(hero.y - self.y, hero.x - self.x);
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ // Healing ability
+ if (LK.ticks - self.lastHeal > self.healCooldown) {
+ for (var i = 0; i < shadows.length; i++) {
+ var otherShadow = shadows[i];
+ if (otherShadow !== self) {
+ var distance = Math.sqrt(Math.pow(self.x - otherShadow.x, 2) + Math.pow(self.y - otherShadow.y, 2));
+ if (distance < 150 && otherShadow.health < otherShadow.maxHealth) {
+ otherShadow.health = Math.min(otherShadow.maxHealth, otherShadow.health + 1);
+ LK.effects.flashObject(otherShadow, 0x00ff00, 300);
+ self.lastHeal = LK.ticks;
+ break;
+ }
+ }
+ }
+ }
+ // Pulsing green effect
+ var pulse = 1 + Math.sin(LK.ticks * 0.4) * 0.3;
+ shadowGraphics.tint = 0x44ff44;
+ shadowGraphics.scaleX = pulse;
+ shadowGraphics.scaleY = pulse;
+ // Update health bar
+ var healthPercent = self.health / self.maxHealth;
+ healthBarFill.scaleX = healthPercent;
+ healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
+ };
+ return self;
+});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
@@ -158,8 +261,81 @@
self.lifetime--;
};
return self;
});
+var MimicShadow = Container.expand(function () {
+ var self = Container.call(this);
+ var shadowGraphics = self.attachAsset('mimicShadow', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 1.8 + Math.random() * 1.2;
+ self.health = 2;
+ self.maxHealth = 2;
+ self.monsterType = 'mimic';
+ self.lastCopy = 0;
+ self.copyCooldown = 240; // 4 seconds
+ self.copyTarget = null;
+ // Create health bar
+ var healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarBg.y = -shadowGraphics.height / 2 - 15;
+ var healthBarFill = self.attachAsset('healthBarFill', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarFill.y = -shadowGraphics.height / 2 - 15;
+ self.update = function () {
+ var angle = Math.atan2(hero.y - self.y, hero.x - self.x);
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ // Copy nearest enemy abilities
+ if (LK.ticks - self.lastCopy > self.copyCooldown) {
+ var nearestEnemy = null;
+ var nearestDistance = Infinity;
+ for (var i = 0; i < shadows.length; i++) {
+ var otherShadow = shadows[i];
+ if (otherShadow !== self && otherShadow.monsterType !== 'mimic') {
+ var distance = Math.sqrt(Math.pow(self.x - otherShadow.x, 2) + Math.pow(self.y - otherShadow.y, 2));
+ if (distance < 200 && distance < nearestDistance) {
+ nearestDistance = distance;
+ nearestEnemy = otherShadow;
+ }
+ }
+ }
+ if (nearestEnemy) {
+ self.copyTarget = nearestEnemy.monsterType;
+ self.lastCopy = LK.ticks;
+ // Visual feedback
+ LK.effects.flashObject(self, 0xff00ff, 500);
+ // Copy some properties
+ if (nearestEnemy.monsterType === 'fast') {
+ self.speed = nearestEnemy.speed;
+ shadowGraphics.tint = 0xffff00;
+ } else if (nearestEnemy.monsterType === 'tank') {
+ self.health = Math.min(self.maxHealth + 2, nearestEnemy.health);
+ shadowGraphics.tint = 0x888888;
+ } else if (nearestEnemy.monsterType === 'teleporter') {
+ shadowGraphics.tint = 0x8844ff;
+ }
+ }
+ }
+ // Rainbow shifting effect
+ var hue = LK.ticks * 0.05 % 1;
+ var r = Math.sin(hue * Math.PI * 2) * 127 + 128;
+ var g = Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128;
+ var b = Math.sin((hue + 0.66) * Math.PI * 2) * 127 + 128;
+ var color = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b);
+ shadowGraphics.tint = color;
+ // Update health bar
+ var healthPercent = self.health / self.maxHealth;
+ healthBarFill.scaleX = healthPercent;
+ healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
+ };
+ return self;
+});
var Shadow = Container.expand(function () {
var self = Container.call(this);
var shadowGraphics = self.attachAsset('shadow', {
anchorX: 0.5,
@@ -189,8 +365,64 @@
healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
};
return self;
});
+var ShielderShadow = Container.expand(function () {
+ var self = Container.call(this);
+ var shadowGraphics = self.attachAsset('shielderShadow', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 1.2 + Math.random() * 0.8;
+ self.health = 4;
+ self.maxHealth = 4;
+ self.monsterType = 'shielder';
+ self.shieldActive = false;
+ self.lastShield = 0;
+ self.shieldCooldown = 180; // 3 seconds
+ self.shieldDuration = 120; // 2 seconds
+ self.shieldTimer = 0;
+ // Create health bar
+ var healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarBg.y = -shadowGraphics.height / 2 - 15;
+ var healthBarFill = self.attachAsset('healthBarFill', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBarFill.y = -shadowGraphics.height / 2 - 15;
+ self.update = function () {
+ var angle = Math.atan2(hero.y - self.y, hero.x - self.x);
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ // Shield activation when damaged
+ if (self.health < self.maxHealth && !self.shieldActive && LK.ticks - self.lastShield > self.shieldCooldown) {
+ self.shieldActive = true;
+ self.shieldTimer = self.shieldDuration;
+ self.lastShield = LK.ticks;
+ shadowGraphics.tint = 0x4444ff;
+ }
+ // Shield timer
+ if (self.shieldActive) {
+ self.shieldTimer--;
+ if (self.shieldTimer <= 0) {
+ self.shieldActive = false;
+ shadowGraphics.tint = 0xffffff;
+ }
+ // Pulsing blue effect when shielded
+ var pulse = 1 + Math.sin(LK.ticks * 0.6) * 0.4;
+ shadowGraphics.scaleX = pulse;
+ shadowGraphics.scaleY = pulse;
+ }
+ // Update health bar
+ var healthPercent = self.health / self.maxHealth;
+ healthBarFill.scaleX = healthPercent;
+ healthBarFill.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
+ };
+ return self;
+});
var SplitterShadow = Container.expand(function () {
var self = Container.call(this);
var shadowGraphics = self.attachAsset('splitterShadow', {
anchorX: 0.5,
@@ -443,9 +675,9 @@
newOrb.baseY = newOrb.y;
lightOrbs.push(newOrb);
game.addChild(newOrb);
// Add score based on monster type
- var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : 10;
+ var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : shadow.monsterType === 'healer' ? 40 : shadow.monsterType === 'shielder' ? 35 : shadow.monsterType === 'berserker' ? 45 : shadow.monsterType === 'mimic' ? 50 : 10;
score += scoreValue;
// Flash effect on each enemy before destruction
tween(shadow, {
alpha: 0
@@ -566,11 +798,14 @@
if (monsterRoll < 0.7) newShadow = new Shadow();else if (monsterRoll < 0.9) newShadow = new FastShadow();else newShadow = new TankShadow();
} else if (waveLevel < 6) {
// Mid waves: introduce more variety
if (monsterRoll < 0.4) newShadow = new Shadow();else if (monsterRoll < 0.6) newShadow = new FastShadow();else if (monsterRoll < 0.75) newShadow = new TankShadow();else if (monsterRoll < 0.9) newShadow = new SplitterShadow();else newShadow = new TeleporterShadow();
- } else {
+ } else if (waveLevel < 10) {
// Late waves: all monster types including dangerous ones
- if (monsterRoll < 0.25) newShadow = new Shadow();else if (monsterRoll < 0.4) newShadow = new FastShadow();else if (monsterRoll < 0.55) newShadow = new TankShadow();else if (monsterRoll < 0.7) newShadow = new SplitterShadow();else if (monsterRoll < 0.85) newShadow = new TeleporterShadow();else newShadow = new BomberShadow();
+ if (monsterRoll < 0.2) newShadow = new Shadow();else if (monsterRoll < 0.35) newShadow = new FastShadow();else if (monsterRoll < 0.5) newShadow = new TankShadow();else if (monsterRoll < 0.65) newShadow = new SplitterShadow();else if (monsterRoll < 0.75) newShadow = new TeleporterShadow();else if (monsterRoll < 0.85) newShadow = new BomberShadow();else if (monsterRoll < 0.92) newShadow = new HealerShadow();else newShadow = new ShielderShadow();
+ } else {
+ // Very late waves: all enemy types including new ones
+ if (monsterRoll < 0.15) newShadow = new Shadow();else if (monsterRoll < 0.25) newShadow = new FastShadow();else if (monsterRoll < 0.35) newShadow = new TankShadow();else if (monsterRoll < 0.45) newShadow = new SplitterShadow();else if (monsterRoll < 0.55) newShadow = new TeleporterShadow();else if (monsterRoll < 0.65) newShadow = new BomberShadow();else if (monsterRoll < 0.75) newShadow = new HealerShadow();else if (monsterRoll < 0.85) newShadow = new ShielderShadow();else if (monsterRoll < 0.93) newShadow = new BerserkerShadow();else newShadow = new MimicShadow();
}
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
@@ -651,9 +886,16 @@
// Check collision with shadows
for (var k = shadows.length - 1; k >= 0; k--) {
if (projectile.intersects(shadows[k])) {
var shadow = shadows[k];
- shadow.health -= damageBonusActive ? 2 : 1;
+ // Check if enemy is shielded
+ var damage = damageBonusActive ? 2 : 1;
+ if (shadow.monsterType === 'shielder' && shadow.shieldActive) {
+ damage = 0; // No damage when shielded
+ LK.effects.flashObject(shadow, 0x4444ff, 100);
+ } else {
+ shadow.health -= damage;
+ }
var shadowDestroyed = false;
if (shadow.health <= 0) {
// Handle special monster behaviors on death
if (shadow.monsterType === 'splitter' && shadow.health <= 0) {
@@ -680,9 +922,9 @@
game.addChild(newOrb);
shadow.destroy();
shadows.splice(k, 1);
shadowDestroyed = true;
- var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : 10;
+ var scoreValue = shadow.monsterType === 'tank' ? 25 : shadow.monsterType === 'splitter' ? 30 : shadow.monsterType === 'teleporter' ? 20 : shadow.monsterType === 'bomber' ? 35 : shadow.monsterType === 'healer' ? 40 : shadow.monsterType === 'shielder' ? 35 : shadow.monsterType === 'berserker' ? 45 : shadow.monsterType === 'mimic' ? 50 : 10;
score += scoreValue;
scoreTxt.setText('Score: ' + score);
LK.getSound('shadowDestroy').play();
} else {
@@ -707,9 +949,15 @@
for (var m = shadows.length - 1; m >= 0; m--) {
var distance = Math.sqrt(Math.pow(spell.x - shadows[m].x, 2) + Math.pow(spell.y - shadows[m].y, 2));
if (distance < spell.radius) {
var shadow = shadows[m];
- shadow.health -= damageBonusActive ? 4 : 2; // Fire spells do more damage
+ // Check if enemy is shielded
+ var damage = damageBonusActive ? 4 : 2; // Fire spells do more damage
+ if (shadow.monsterType === 'shielder' && shadow.shieldActive) {
+ damage = Math.ceil(damage / 2); // Reduced damage when shielded
+ LK.effects.flashObject(shadow, 0x4444ff, 100);
+ }
+ shadow.health -= damage;
if (shadow.health <= 0) {
// Handle special monster behaviors on death
if (shadow.monsterType === 'splitter') {
// Create two smaller fast shadows
@@ -734,9 +982,9 @@
lightOrbs.push(newOrb);
game.addChild(newOrb);
shadow.destroy();
shadows.splice(m, 1);
- var scoreValue = shadow.monsterType === 'tank' ? 30 : shadow.monsterType === 'splitter' ? 35 : shadow.monsterType === 'teleporter' ? 25 : shadow.monsterType === 'bomber' ? 40 : 15;
+ var scoreValue = shadow.monsterType === 'tank' ? 30 : shadow.monsterType === 'splitter' ? 35 : shadow.monsterType === 'teleporter' ? 25 : shadow.monsterType === 'bomber' ? 40 : shadow.monsterType === 'healer' ? 45 : shadow.monsterType === 'shielder' ? 40 : shadow.monsterType === 'berserker' ? 50 : shadow.monsterType === 'mimic' ? 55 : 15;
score += scoreValue;
scoreTxt.setText('Score: ' + score);
LK.getSound('shadowDestroy').play();
} else {
bola de fuego de pixeles. In-Game asset. 2d. High contrast. No shadows
monstruo de slime negro de pixeles. In-Game asset. 2d. High contrast. No shadows
suelo de sesped oscuro de pixeles. In-Game asset. 2d. High contrast. No shadows
bola de luz de pixeles. In-Game asset. 2d. High contrast. No shadows
sombra de pixeles que de miedo. In-Game asset. 2d. High contrast. No shadows
portal de pixeles de luz. In-Game asset. 2d. High contrast. No shadows
angel en forma de ojo de pixeles. In-Game asset. 2d. High contrast. No shadows
que ahora tenga una exprecion de determinacion
fuego negro de pixeles. In-Game asset. 2d. High contrast. No shadows
bola de luz azul de pixeles. In-Game asset. 2d. High contrast. No shadows
la muerte de pixeles. In-Game asset. 2d. High contrast. No shadows
orbe oscuro de pixeles con cara enojada. In-Game asset. 2d. High contrast. No shadows
berserquer de pixeles. In-Game asset. 2d. High contrast. No shadows
sombra mimica de pixeles. In-Game asset. 2d. High contrast. No shadows
casa de madera con barricadas de pixeles. In-Game asset. 2d. High contrast. No shadows
bola de hielo de pixeles. In-Game asset. 2d. High contrast. No shadows
bola de viento de pixeles. In-Game asset. 2d. High contrast. No shadows