User prompt
HP yazısını stage yazısının 2 satır altına taşı.
User prompt
Oyunda HP sistemi olsun. Düşen topların sayısı kadar HP azalsın. Mesela 3 sayılı top geçerse, 3 can azalsın. Gibi.
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Topları gönderdikten sonra kendimiz de tıklama yaparak top gönderebilelim. Normal topun hasarının %50 daha düşük olsun.
User prompt
Add combo multiplier visual effects with dynamic scaling ✅ Add magnetized ball class that attracts projectiles ✅ Add critical hit visual effects and damage multiplier ✅ Add magnet ball spawning to level generation ✅ Add special weapon combo system ✅ Add magnet ball collision and attraction effects ✅ Add special victory conditions and epic win effects ✅ Add power-up combo system to track active effects ✅ Add special ball destruction tracking for achievements 🔄 Add lucky shot tracking from long distance ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Create the image file behind the achievements button and the achievements text in it.
User prompt
Hız artırma bölgeleri ile ilgili herşeyi sil. Olmasın oyunda.
User prompt
Başarımların olduğu buton ekle ve birbirinden farklı, oyun özelliklerinden oluşan 50 başarım ekle. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Add combo multiplier display and visual feedback ✅ Add rainbow ball special enemy type ✅ Add bomb ball that explodes on impact ✅ Add spawning for rainbow and bomb balls ✅ Add special handling for rainbow and bomb balls in collision ✅ Add double shot power-up ✅ Add double shot spawning and variables ✅ Add double shot variables and update ✅ Add double shot update loop ✅ Add double shot movement ✅ Add double shot collision and effect ✅ Add double shot timer update ✅ Modify fireProjectiles to support double shot ✅ Add critical hit visual indicator ✅ Add perfect shot bonus ✅ Add speed boost zones visual indicator 🔄 Add projectile speed boost in zones
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage['99balls_save'] = savedData;' Line Number: 1191
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle. (alevli top, büyük top, çarpınca parçalanan top, çarpınca çoğalan top vs.)
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var savedData = storage.get('99balls_save') || {};' Line Number: 353 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage['99balls_save'] = savedData;' Line Number: 919
User prompt
Sorunu çöz
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var savedData = storage.get('99balls_save') || {};' Line Number: 353 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Oluşturduğun özelliğin kodlamasına devam et. Yarım kaldı.
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'weaponText.style.fill = 0xFFFFFF;' Line Number: 758
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak özellik ekle.
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'call')' in or related to this line: 'AddBallButton.prototype.up.call(addBallButton, x, y, obj);' Line Number: 229
User prompt
3 top arka arkaya hizalı şekilde gitsin ve her seviye sonrası artsın. Bu sayıyı artırmak için buton ekle.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AimLine = Container.expand(function () { var self = Container.call(this); for (var i = 0; i < 10; i++) { var dot = self.attachAsset('aimline', { anchorX: 0.5, anchorY: 0.5, y: -i * 30, alpha: 0.5 - i * 0.05 }); } return self; }); var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.numberText = new Text2('1', { size: 40, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 1; self.radius = 40; self.velocityX = 0; self.velocityY = 0; self.setNumber = function (num) { self.hits = num; self.numberText.setText(num.toString()); var scale = 1 + num / 50 * 0.5; ballGraphics.scale.set(scale); self.radius = 40 * scale; }; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); tween(ballGraphics, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); return false; }; return self; }); var BombBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0x333333, scaleX: 1.3, scaleY: 1.3 }); self.numberText = new Text2('💣', { size: 40, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 5; self.radius = 50; self.velocityX = 0; self.velocityY = 0; self.pulseTimer = 0; self.isBomb = true; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); ballGraphics.tint = self.hits <= 2 ? 0xff0000 : 0x333333; return false; }; self.update = function () { self.pulseTimer += 0.15; if (self.hits <= 2) { var pulse = 1 + Math.sin(self.pulseTimer) * 0.2; ballGraphics.scale.set(1.3 * pulse); } }; return self; }); var BossBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0xff1744, scaleX: 2, scaleY: 2 }); self.numberText = new Text2('BOSS', { size: 50, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 50; self.radius = 80; self.velocityX = 2; self.moveTimer = 0; self.isBoss = true; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); ballGraphics.tint = Math.random() > 0.5 ? 0xff1744 : 0xff6600; tween(ballGraphics, { scaleX: 1.8, scaleY: 1.8 }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 2, scaleY: 2 }, { duration: 100 }); } }); return false; }; self.update = function () { self.moveTimer += 0.05; self.x += self.velocityX; if (self.x <= self.radius || self.x >= 2048 - self.radius) { self.velocityX *= -1; } ballGraphics.rotation += 0.02; }; return self; }); var Cannon = Container.expand(function () { var self = Container.call(this); var cannonGraphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 0.8 }); self.rotation = 0; return self; }); var ChainReactionPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xff8800, scaleX: 1.4, scaleY: 1.4 }); self.radius = 35; self.chainTimer = 0; self.update = function () { self.chainTimer += 0.2; var scale = 1.4 + Math.sin(self.chainTimer) * 0.2; powerupGraphics.scale.set(scale); // Chain effect if (Math.random() < 0.2) { var chain = self.attachAsset('aimline', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0xff8800, alpha: 0.6, rotation: Math.random() * Math.PI * 2 }); tween(chain, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 400, onFinish: function onFinish() { chain.destroy(); } }); } }; return self; }); var DoubleShotPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xffff00, scaleX: 1.2, scaleY: 1.2 }); self.radius = 30; self.bounceTimer = 0; self.update = function () { self.bounceTimer += 0.08; var scale = 1.2 + Math.sin(self.bounceTimer * 2) * 0.1; powerupGraphics.scale.set(scale); powerupGraphics.rotation -= 0.03; }; return self; }); var FireBallPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xff6600 }); self.radius = 25; self.flameTimer = 0; self.update = function () { self.flameTimer += 0.15; var scale = 1 + Math.sin(self.flameTimer) * 0.4; powerupGraphics.scale.set(scale); powerupGraphics.alpha = 0.7 + Math.sin(self.flameTimer * 2) * 0.3; }; return self; }); var FreezeBombPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ccff, scaleX: 1.3, scaleY: 1.3 }); self.radius = 30; self.iceTimer = 0; self.update = function () { self.iceTimer += 0.15; powerupGraphics.alpha = 0.6 + Math.sin(self.iceTimer) * 0.4; powerupGraphics.rotation += 0.02; // Ice particle effect if (Math.random() < 0.1) { var iceParticle = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0x00ffff, alpha: 0.8 }); iceParticle.x = (Math.random() - 0.5) * 40; iceParticle.y = (Math.random() - 0.5) * 40; tween(iceParticle, { y: iceParticle.y - 20, alpha: 0, scaleX: 0, scaleY: 0 }, { duration: 500, onFinish: function onFinish() { iceParticle.destroy(); } }); } }; return self; }); var GhostBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0x8888ff, alpha: 0.5 }); self.numberText = new Text2('G', { size: 40, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 7; self.radius = 40; self.phaseTimer = 0; self.isPhased = false; self.isGhost = true; self.takeDamage = function () { if (self.isPhased) return false; self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); return false; }; self.update = function () { self.phaseTimer += 0.1; self.isPhased = Math.sin(self.phaseTimer) > 0; ballGraphics.alpha = self.isPhased ? 0.2 : 0.8; self.numberText.alpha = self.isPhased ? 0.2 : 1; }; return self; }); var GiantBallPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ff00, scaleX: 1.5, scaleY: 1.5 }); self.radius = 35; self.bounceTimer = 0; self.update = function () { self.bounceTimer += 0.1; var scale = 1.5 + Math.sin(self.bounceTimer) * 0.3; powerupGraphics.scale.set(scale); }; return self; }); var GravityWellBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0x4a0080, scaleX: 1.8, scaleY: 1.8 }); self.numberText = new Text2('GRAV', { size: 30, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 30; self.radius = 70; self.gravityRadius = 300; self.isGravityWell = true; self.pullTimer = 0; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); // Pulse effect tween(ballGraphics, { scaleX: 1.6, scaleY: 1.6 }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.8, scaleY: 1.8 }, { duration: 100 }); } }); return false; }; self.update = function () { self.pullTimer += 0.05; ballGraphics.rotation = self.pullTimer; // Gravity field visual if (Math.random() < 0.1) { var ring = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3, tint: 0x4a0080, alpha: 0.2 }); tween(ring, { scaleX: 0.1, scaleY: 0.1, alpha: 0.8 }, { duration: 1000, onFinish: function onFinish() { ring.destroy(); } }); } }; return self; }); var LaserPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ffff }); self.radius = 25; self.glowTimer = 0; self.update = function () { self.glowTimer += 0.2; powerupGraphics.alpha = 0.5 + Math.sin(self.glowTimer) * 0.5; }; return self; }); var LightningPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x9966ff }); self.radius = 25; self.sparkTimer = 0; self.update = function () { self.sparkTimer += 0.3; powerupGraphics.alpha = 0.4 + Math.random() * 0.6; powerupGraphics.scale.set(1 + Math.sin(self.sparkTimer) * 0.3); }; return self; }); var MagnetBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0x0066cc, scaleX: 1.3, scaleY: 1.3 }); self.numberText = new Text2('MAG', { size: 35, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 20; self.radius = 50; self.magnetRadius = 200; self.isMagnet = true; self.magnetTimer = 0; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); // Pulse effect on hit tween(ballGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 100 }); } }); return false; }; self.update = function () { self.magnetTimer += 0.1; // Magnetic field visual effect if (Math.random() < 0.2) { var field = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, tint: 0x0099ff, alpha: 0.3 }); var angle = Math.random() * Math.PI * 2; var radius = Math.random() * self.magnetRadius; field.x = Math.cos(angle) * radius; field.y = Math.sin(angle) * radius; tween(field, { scaleX: 0.5, scaleY: 0.5, alpha: 0, x: field.x * 0.5, y: field.y * 0.5 }, { duration: 1000, onFinish: function onFinish() { field.destroy(); } }); } ballGraphics.rotation = self.magnetTimer * 0.5; }; return self; }); var MirrorBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: 0xc0c0c0, scaleX: 1.2, scaleY: 1.2 }); self.numberText = new Text2('M', { size: 40, fill: 0x000000 }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 15; self.radius = 45; self.velocityX = 0; self.velocityY = 0; self.isMirror = true; self.reflectTimer = 0; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); // Flash effect on hit tween(ballGraphics, { tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { tint: 0xc0c0c0 }, { duration: 100 }); } }); return false; }; self.update = function () { self.reflectTimer += 0.1; ballGraphics.alpha = 0.7 + Math.sin(self.reflectTimer * 2) * 0.3; // Shine effect if (Math.random() < 0.05) { var shine = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0xffffff, alpha: 0.8 }); shine.x = (Math.random() - 0.5) * 40; shine.y = (Math.random() - 0.5) * 40; tween(shine, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { shine.destroy(); } }); } }; return self; }); var MultiballPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xe74c3c }); self.radius = 25; self.rotationSpeed = 0.05; self.update = function () { powerupGraphics.rotation += self.rotationSpeed; var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.3; powerupGraphics.scale.set(scale); }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.lifetime = 30; self.fadeSpeed = 0.03; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.velocityY += 0.5; // gravity self.lifetime--; self.alpha -= self.fadeSpeed; if (self.lifetime <= 0 || self.alpha <= 0) { return true; // destroy } return false; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 20; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.speed = 15; self.radius = 10; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; if (self.x <= self.radius || self.x >= 2048 - self.radius) { self.velocityX *= -1; self.x = Math.max(self.radius, Math.min(2048 - self.radius, self.x)); } if (self.y <= self.radius) { self.velocityY *= -1; self.y = self.radius; } }; return self; }); var RainbowBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.numberText = new Text2('★', { size: 50, fill: 0xFFFFFF }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.hits = 10; self.radius = 60; self.velocityX = 0; self.velocityY = 0; self.colorTimer = 0; self.isRainbow = true; self.takeDamage = function () { self.hits--; if (self.hits <= 0) { return true; } self.numberText.setText(self.hits.toString()); return false; }; self.update = function () { self.colorTimer += 0.1; var hue = (Math.sin(self.colorTimer) + 1) * 0.5; var r = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128); var g = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128); var b = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128); ballGraphics.tint = r << 16 | g << 8 | b; ballGraphics.rotation += 0.05; }; return self; }); var RainbowLaserPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xff00ff, scaleX: 1.5, scaleY: 1.5 }); self.radius = 35; self.rainbowTimer = 0; self.update = function () { self.rainbowTimer += 0.2; var hue = (Math.sin(self.rainbowTimer) + 1) * 0.5; var r = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128); var g = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128); var b = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128); powerupGraphics.tint = r << 16 | g << 8 | b; powerupGraphics.rotation += 0.05; // Rainbow particles if (Math.random() < 0.3) { var particle = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, tint: powerupGraphics.tint, alpha: 0.8 }); particle.x = (Math.random() - 0.5) * 30; particle.y = (Math.random() - 0.5) * 30; tween(particle, { y: particle.y - 30, alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 800, onFinish: function onFinish() { particle.destroy(); } }); } }; return self; }); var ShieldPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x3498db }); self.radius = 25; self.shieldTimer = 0; self.update = function () { self.shieldTimer += 0.1; var scale = 1 + Math.sin(self.shieldTimer * 2) * 0.2; powerupGraphics.scale.set(scale); powerupGraphics.rotation += 0.05; }; return self; }); var SlowMotionPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x9b59b6 }); self.radius = 30; self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; var scale = 1 + Math.sin(self.pulseTimer) * 0.2; powerupGraphics.scale.set(scale); }; return self; }); var SpecialProjectile = Container.expand(function () { var self = Container.call(this); self.type = 'normal'; self.velocityX = 0; self.velocityY = 0; self.speed = 15; self.radius = 10; self.piercing = 0; self.bounces = 999; var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.setType = function (type) { self.type = type; switch (type) { case 'piercing': projectileGraphics.tint = 0xff00ff; self.piercing = 3; projectileGraphics.scale.set(1.5); self.radius = 15; break; case 'explosive': projectileGraphics.tint = 0xff4444; projectileGraphics.scale.set(2); self.radius = 20; self.speed = 10; break; case 'rapid': projectileGraphics.tint = 0x44ff44; projectileGraphics.scale.set(0.7); self.radius = 7; self.speed = 25; break; case 'fireball': projectileGraphics.tint = 0xff6600; projectileGraphics.scale.set(1.8); self.radius = 18; self.speed = 12; self.piercing = 999; break; case 'giant': projectileGraphics.tint = 0x00ff00; projectileGraphics.scale.set(3); self.radius = 30; self.speed = 8; break; case 'split': projectileGraphics.tint = 0xff00ff; projectileGraphics.scale.set(1.2); self.radius = 12; self.speed = 15; break; case 'laser': projectileGraphics.tint = 0x00ffff; projectileGraphics.scale.set(0.5); self.radius = 5; self.speed = 30; self.piercing = 999; break; case 'lightning': projectileGraphics.tint = 0x9966ff; projectileGraphics.scale.set(1.5); self.radius = 15; self.speed = 20; self.piercing = 1; break; } }; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; if (self.x <= self.radius || self.x >= 2048 - self.radius) { self.velocityX *= -1; self.x = Math.max(self.radius, Math.min(2048 - self.radius, self.x)); self.bounces--; } if (self.y <= self.radius) { self.velocityY *= -1; self.y = self.radius; self.bounces--; } if (self.type === 'rapid') { // Add trail effect if (Math.random() < 0.3) { var trail = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 0.5, tint: 0x44ff44 }); tween(trail, { alpha: 0, scaleX: 0, scaleY: 0 }, { duration: 300, onFinish: function onFinish() { trail.destroy(); } }); } } else if (self.type === 'fireball') { // Add flame trail if (Math.random() < 0.5) { var flame = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, alpha: 0.8, tint: Math.random() > 0.5 ? 0xff6600 : 0xffaa00 }); tween(flame, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 200, onFinish: function onFinish() { flame.destroy(); } }); } } else if (self.type === 'laser') { // Add laser glow projectileGraphics.alpha = 0.8 + Math.sin(LK.ticks * 0.3) * 0.2; } return self.bounces <= 0; }; return self; }); var SplitBallPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0xff00ff }); self.radius = 25; self.rotationSpeed = 0.1; self.update = function () { powerupGraphics.rotation += self.rotationSpeed; }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 25; starGraphics.rotation = Math.PI / 4; self.update = function () { starGraphics.rotation += 0.02; }; return self; }); var TeleportPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x8000ff, scaleX: 1.2, scaleY: 1.2 }); self.radius = 30; self.teleportTimer = 0; self.update = function () { self.teleportTimer += 0.3; powerupGraphics.alpha = 0.3 + Math.abs(Math.sin(self.teleportTimer)) * 0.7; // Portal effect if (powerupGraphics.alpha < 0.4) { powerupGraphics.x = (Math.random() - 0.5) * 10; powerupGraphics.y = (Math.random() - 0.5) * 10; } }; return self; }); var TimeWarpPowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ff88, scaleX: 1.4, scaleY: 1.4 }); self.radius = 35; self.warpTimer = 0; self.update = function () { self.warpTimer += 0.25; powerupGraphics.alpha = 0.4 + Math.sin(self.warpTimer) * 0.6; powerupGraphics.scale.set(1.4 + Math.sin(self.warpTimer * 2) * 0.3); // Time distortion effect if (Math.random() < 0.2) { var distortion = self.attachAsset('aimline', { anchorX: 0.5, anchorY: 0.5, scaleX: Math.random() * 2 + 0.5, scaleY: 0.1, tint: 0x00ff88, alpha: 0.6, rotation: Math.random() * Math.PI * 2 }); tween(distortion, { scaleY: 2, alpha: 0, rotation: distortion.rotation + Math.PI }, { duration: 600, onFinish: function onFinish() { distortion.destroy(); } }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ var cannon; var aimLine; var balls = []; var projectiles = []; var powerups = []; var stars = []; var isAiming = false; var canShoot = true; var projectileCount = 1; var stage = 1; var ballsPerRow = 6; var ballSpeed = 0.5; var gameActive = true; var stageText = new Text2('Stage 1', { size: 60, fill: 0xFFFFFF }); stageText.anchor.set(0.5, 0); stageText.y = 20; LK.gui.top.addChild(stageText); var projectileCountText = new Text2('x1', { size: 50, fill: 0x4ECDC4 }); projectileCountText.anchor.set(0.5, 0); projectileCountText.y = 100; LK.gui.top.addChild(projectileCountText); var scoreText = new Text2('Score: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); scoreText.x = -20; scoreText.y = 20; LK.gui.topRight.addChild(scoreText); var combo = 0; var comboTimer = 0; var scoreMultiplier = 1; var comboText = new Text2('', { size: 60, fill: 0xFFD700 }); comboText.anchor.set(0.5, 0.5); LK.gui.center.addChild(comboText); var particles = []; var currentWeapon = 'normal'; var weaponUnlocks = { piercing: false, explosive: false, rapid: false }; var slowMotionActive = false; var slowMotionTimer = 0; var gameSpeed = 1; var magnetActive = false; var magnetTimer = 0; var specialEffects = []; var chainReactionActive = false; var lastBallDestroyed = null; var consecutiveHits = 0; var slowMotionPowerups = []; var multiballPowerups = []; var multiballActive = false; var fireballPowerups = []; var giantBallPowerups = []; var splitBallPowerups = []; var laserPowerups = []; var fireballActive = false; var giantBallActive = false; var splitBallActive = false; var laserActive = false; var shieldPowerups = []; var shieldActive = false; var shieldTimer = 0; var bossBalls = []; var bossSpawnCounter = 0; var freezeActive = false; var freezeTimer = 0; var criticalHitChance = 0.1; var magnetBalls = []; var perfectStageBonus = false; var rainbowBalls = []; var bombBalls = []; var doubleShotPowerups = []; var doubleShotActive = false; var doubleShotTimer = 0; var lightningPowerups = []; var lightningActive = false; var ghostBalls = []; var reverseGravityActive = false; var reverseGravityTimer = 0; var scoreBoostActive = false; var scoreBoostTimer = 0; var scoreBoostMultiplier = 1; var autoAimActive = false; var autoAimTimer = 0; var freezeBombPowerups = []; var freezeBombActive = false; var mirrorBalls = []; var chainReactionPowerups = []; var chainReactionBombActive = false; var teleportPowerups = []; var teleportActive = false; var ballsDestroyed = 0; var perfectHits = 0; var missedShots = 0; var powerupsCollected = 0; var maxCombo = 0; var timePlayed = 0; var achievements = { // Basic achievements firstWin: false, combo10: false, score1000: false, allWeapons: false, bossKiller: false, perfectStage: false, shieldMaster: false, lightningMaster: false, ghostHunter: false, reverseGravity: false, // New achievements stage10: false, stage25: false, stage50: false, score5000: false, score10000: false, score50000: false, combo20: false, combo50: false, multiKill5: false, multiKill10: false, projectiles50: false, projectiles100: false, fireballKills: false, laserKills: false, explosiveKills: false, piercingKills: false, rapidKills: false, splitKills: false, giantKills: false, lightningChain: false, bombExpert: false, rainbowHunter: false, starCollector: false, powerupMaster: false, dodgeMaster: false, speedDemon: false, slowMotionPro: false, magnetMaster: false, freezeMaster: false, doubleTrouble: false, tripleCombo: false, chainReactionPro: false, perfectAccuracy: false, luckyShot: false, survivor: false, pacifist: false, aggressive: false, versatile: false, persistent: false, flawless: false, comeback: false, closeCall: false, longShot: false, richPlayer: false, masterOfAll: false }; var achievementDescriptions = { firstWin: "Clear your first stage", combo10: "Achieve a 10x combo", score1000: "Score 1,000 points", allWeapons: "Unlock all basic weapons", bossKiller: "Defeat a boss", perfectStage: "Clear a stage with only 1 projectile", shieldMaster: "Use a shield power-up", lightningMaster: "Use lightning power-up", ghostHunter: "Defeat a ghost ball", reverseGravity: "Use reverse gravity", stage10: "Reach stage 10", stage25: "Reach stage 25", stage50: "Reach stage 50", score5000: "Score 5,000 points", score10000: "Score 10,000 points", score50000: "Score 50,000 points", combo20: "Achieve a 20x combo", combo50: "Achieve a 50x combo", multiKill5: "Destroy 5 balls with one shot", multiKill10: "Destroy 10 balls with one shot", projectiles50: "Collect 50 projectiles total", projectiles100: "Collect 100 projectiles total", fireballKills: "Destroy 100 balls with fireball", laserKills: "Destroy 100 balls with laser", explosiveKills: "Destroy 100 balls with explosive", piercingKills: "Destroy 100 balls with piercing", rapidKills: "Destroy 100 balls with rapid fire", splitKills: "Destroy 100 balls with split shot", giantKills: "Destroy 100 balls with giant ball", lightningChain: "Chain lightning to 5 balls", bombExpert: "Trigger 10 bomb explosions", rainbowHunter: "Destroy 20 rainbow balls", starCollector: "Collect 50 stars", powerupMaster: "Use 100 power-ups", dodgeMaster: "Survive with balls at bottom 10 times", speedDemon: "Clear a stage in under 30 seconds", slowMotionPro: "Use slow motion 20 times", magnetMaster: "Use magnet 20 times", freezeMaster: "Use freeze 20 times", doubleTrouble: "Use double shot 20 times", tripleCombo: "Get 3 different power-ups active", chainReactionPro: "Trigger 50 chain reactions", perfectAccuracy: "Hit 100 balls without missing", luckyShot: "Hit a ball from max distance", survivor: "Survive for 10 minutes", pacifist: "Clear a stage without power-ups", aggressive: "Clear a stage in under 10 shots", versatile: "Use all weapon types in one game", persistent: "Play 100 games", flawless: "Clear 5 stages without taking damage", comeback: "Win with 1 projectile left", closeCall: "Survive with shield save 5 times", longShot: "Hit a ball from bottom to top", richPlayer: "Have 10+ projectiles at once", masterOfAll: "Unlock all 50 achievements" }; var achievementProgress = { fireballKills: 0, laserKills: 0, explosiveKills: 0, piercingKills: 0, rapidKills: 0, splitKills: 0, giantKills: 0, bombExpert: 0, rainbowHunter: 0, starCollector: 0, powerupMaster: 0, dodgeMaster: 0, slowMotionPro: 0, magnetMaster: 0, freezeMaster: 0, doubleTrouble: 0, chainReactionPro: 0, perfectAccuracy: 0, persistent: 0, flawless: 0, closeCall: 0 }; var rainbowLaserPowerups = []; var rainbowLaserActive = false; var gravityWellBalls = []; var timeWarpPowerups = []; var timeWarpActive = false; var timeWarpTimer = 0; var superComboActive = false; var superComboTimer = 0; var bulletTimeActive = false; var bulletTimeTimer = 0; // Load saved data var savedData = storage['99balls_save'] || {}; if (savedData.highScore) { var highScoreText = new Text2('Best: ' + savedData.highScore, { size: 30, fill: 0xFFD700 }); highScoreText.anchor.set(1, 0); highScoreText.x = -20; highScoreText.y = 70; LK.gui.topRight.addChild(highScoreText); } // Load achievements from flattened structure for (var key in achievements) { if (savedData[key] !== undefined) { achievements[key] = savedData[key]; } } // Load achievement progress for (var key in achievementProgress) { if (savedData[key + 'Progress'] !== undefined) { achievementProgress[key] = savedData[key + 'Progress']; } } var weaponText = new Text2('Normal', { size: 40, fill: 0xFFFFFF }); weaponText.anchor.set(0.5, 1); weaponText.y = -20; LK.gui.bottom.addChild(weaponText); var slowMotionOverlay = new Container(); var slowMotionBg = slowMotionOverlay.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 50, scaleY: 50, alpha: 0, tint: 0x9b59b6 }); LK.gui.center.addChild(slowMotionOverlay); var powerUpIndicator = new Text2('', { size: 50, fill: 0xFFFFFF }); powerUpIndicator.anchor.set(0, 0); powerUpIndicator.x = 20; powerUpIndicator.y = 200; LK.gui.topLeft.addChild(powerUpIndicator); var doubleShotIndicator = new Text2('', { size: 40, fill: 0xffff00 }); doubleShotIndicator.anchor.set(0, 0); doubleShotIndicator.x = 20; doubleShotIndicator.y = 260; LK.gui.topLeft.addChild(doubleShotIndicator); var shieldIndicator = new Container(); var shieldBg = shieldIndicator.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3, alpha: 0, tint: 0x3498db }); game.addChild(shieldIndicator); function initializeLevel() { // Reset game state gameActive = true; canShoot = true; isAiming = false; cannon = game.addChild(new Cannon()); cannon.x = 1024; cannon.y = 2600; aimLine = game.addChild(new AimLine()); aimLine.x = cannon.x; aimLine.y = cannon.y; aimLine.visible = false; spawnBallRow(); } function spawnBallRow() { var spacing = 2048 / (ballsPerRow + 1); for (var i = 0; i < ballsPerRow; i++) { if (Math.random() < 0.8) { var ball = new Ball(); ball.x = spacing * (i + 1); ball.y = -50; ball.setNumber(Math.floor(Math.random() * stage * 5) + stage); balls.push(ball); game.addChild(ball); if (Math.random() < 0.15) { var powerup = new PowerUp(); powerup.x = ball.x; powerup.y = ball.y; powerups.push(powerup); game.addChild(powerup); } else if (Math.random() < 0.1) { var star = new Star(); star.x = ball.x; star.y = ball.y; stars.push(star); game.addChild(star); } else if (Math.random() < 0.05 && stage > 2) { var slowPowerup = new SlowMotionPowerUp(); slowPowerup.x = ball.x; slowPowerup.y = ball.y; slowMotionPowerups.push(slowPowerup); game.addChild(slowPowerup); } else if (Math.random() < 0.04 && stage > 3) { var multiballPowerup = new MultiballPowerUp(); multiballPowerup.x = ball.x; multiballPowerup.y = ball.y; multiballPowerups.push(multiballPowerup); game.addChild(multiballPowerup); } else if (Math.random() < 0.04 && stage > 1) { var fireballPowerup = new FireBallPowerUp(); fireballPowerup.x = ball.x; fireballPowerup.y = ball.y; fireballPowerups.push(fireballPowerup); game.addChild(fireballPowerup); } else if (Math.random() < 0.03 && stage > 2) { var giantBallPowerup = new GiantBallPowerUp(); giantBallPowerup.x = ball.x; giantBallPowerup.y = ball.y; giantBallPowerups.push(giantBallPowerup); game.addChild(giantBallPowerup); } else if (Math.random() < 0.03 && stage > 4) { var splitBallPowerup = new SplitBallPowerUp(); splitBallPowerup.x = ball.x; splitBallPowerup.y = ball.y; splitBallPowerups.push(splitBallPowerup); game.addChild(splitBallPowerup); } else if (Math.random() < 0.02 && stage > 5) { var laserPowerup = new LaserPowerUp(); laserPowerup.x = ball.x; laserPowerup.y = ball.y; laserPowerups.push(laserPowerup); game.addChild(laserPowerup); } else if (Math.random() < 0.03 && stage > 3) { var shieldPowerup = new ShieldPowerUp(); shieldPowerup.x = ball.x; shieldPowerup.y = ball.y; shieldPowerups.push(shieldPowerup); game.addChild(shieldPowerup); } else if (Math.random() < 0.04 && stage > 2) { var doubleShotPowerup = new DoubleShotPowerUp(); doubleShotPowerup.x = ball.x; doubleShotPowerup.y = ball.y; doubleShotPowerups.push(doubleShotPowerup); game.addChild(doubleShotPowerup); } else if (Math.random() < 0.03 && stage > 4) { var lightningPowerup = new LightningPowerUp(); lightningPowerup.x = ball.x; lightningPowerup.y = ball.y; lightningPowerups.push(lightningPowerup); game.addChild(lightningPowerup); } } else if (Math.random() < 0.05 && stage > 3) { // Spawn rainbow ball var rainbowBall = new RainbowBall(); rainbowBall.x = ball.x; rainbowBall.y = ball.y; rainbowBalls.push(rainbowBall); game.addChild(rainbowBall); } else if (Math.random() < 0.04 && stage > 4) { // Spawn bomb ball var bombBall = new BombBall(); bombBall.x = ball.x; bombBall.y = ball.y; bombBalls.push(bombBall); game.addChild(bombBall); } else if (Math.random() < 0.03 && stage > 5) { // Spawn ghost ball var ghostBall = new GhostBall(); ghostBall.x = ball.x; ghostBall.y = ball.y; ghostBalls.push(ghostBall); game.addChild(ghostBall); } else if (Math.random() < 0.02 && stage > 6) { // Spawn mirror ball var mirrorBall = new MirrorBall(); mirrorBall.x = ball.x; mirrorBall.y = ball.y; mirrorBalls.push(mirrorBall); game.addChild(mirrorBall); } else if (Math.random() < 0.03 && stage > 4) { // Spawn freeze bomb power-up var freezeBombPowerup = new FreezeBombPowerUp(); freezeBombPowerup.x = ball.x; freezeBombPowerup.y = ball.y; freezeBombPowerups.push(freezeBombPowerup); game.addChild(freezeBombPowerup); } else if (Math.random() < 0.02 && stage > 5) { // Spawn chain reaction power-up var chainReactionPowerup = new ChainReactionPowerUp(); chainReactionPowerup.x = ball.x; chainReactionPowerup.y = ball.y; chainReactionPowerups.push(chainReactionPowerup); game.addChild(chainReactionPowerup); } else if (Math.random() < 0.02 && stage > 7) { // Spawn teleport power-up var teleportPowerup = new TeleportPowerUp(); teleportPowerup.x = ball.x; teleportPowerup.y = ball.y; teleportPowerups.push(teleportPowerup); game.addChild(teleportPowerup); } else if (Math.random() < 0.03 && stage > 6) { // Spawn magnet ball var magnetBall = new MagnetBall(); magnetBall.x = ball.x; magnetBall.y = ball.y; magnetBalls.push(magnetBall); game.addChild(magnetBall); } else if (Math.random() < 0.02 && stage > 8) { // Spawn rainbow laser power-up var rainbowLaserPowerup = new RainbowLaserPowerUp(); rainbowLaserPowerup.x = ball.x; rainbowLaserPowerup.y = ball.y; rainbowLaserPowerups.push(rainbowLaserPowerup); game.addChild(rainbowLaserPowerup); } else if (Math.random() < 0.02 && stage > 10) { // Spawn gravity well ball var gravityWellBall = new GravityWellBall(); gravityWellBall.x = ball.x; gravityWellBall.y = ball.y; gravityWellBalls.push(gravityWellBall); game.addChild(gravityWellBall); } else if (Math.random() < 0.02 && stage > 9) { // Spawn time warp power-up var timeWarpPowerup = new TimeWarpPowerUp(); timeWarpPowerup.x = ball.x; timeWarpPowerup.y = ball.y; timeWarpPowerups.push(timeWarpPowerup); game.addChild(timeWarpPowerup); } } // Spawn boss every 5 stages bossSpawnCounter++; if (stage > 0 && stage % 5 === 0 && bossSpawnCounter === 1) { var boss = new BossBall(); boss.x = 1024; boss.y = 200; bossBalls.push(boss); game.addChild(boss); var bossWarning = new Text2('BOSS INCOMING!', { size: 100, fill: 0xff1744 }); bossWarning.anchor.set(0.5, 0.5); bossWarning.alpha = 0; LK.gui.center.addChild(bossWarning); tween(bossWarning, { alpha: 1, scaleX: 1.5, scaleY: 1.5 }, { duration: 500, onFinish: function onFinish() { tween(bossWarning, { alpha: 0 }, { duration: 500, delay: 1000, onFinish: function onFinish() { bossWarning.destroy(); } }); } }); } else if (stage % 5 !== 0) { bossSpawnCounter = 0; } } function fireProjectiles(angle) { var shotCount = projectileCount; var delay = 100; var weaponType = currentWeapon; if (currentWeapon === 'rapid') { shotCount = Math.min(projectileCount * 3, 15); delay = 30; } // Double shot modifier if (doubleShotActive) { shotCount *= 2; } // Check for active power-ups if (rainbowLaserActive) { weaponType = 'laser'; rainbowLaserActive = false; shotCount = 7; // Fire 7 rainbow lasers // Rainbow laser special effect for (var rl = 0; rl < 7; rl++) { (function (index) { LK.setTimeout(function () { var laserProjectile = new SpecialProjectile(); laserProjectile.x = cannon.x + (index - 3) * 50; laserProjectile.y = cannon.y - 40; laserProjectile.setType('laser'); laserProjectile.velocityX = (index - 3) * 2; laserProjectile.velocityY = -laserProjectile.speed; // Rainbow tint var hue = index / 7; var r = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128); var g = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128); var b = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128); laserProjectile.tint = r << 16 | g << 8 | b; projectiles.push(laserProjectile); game.addChild(laserProjectile); }, index * 50); })(rl); } return; } else if (fireballActive) { weaponType = 'fireball'; fireballActive = false; } else if (giantBallActive) { weaponType = 'giant'; giantBallActive = false; } else if (splitBallActive) { weaponType = 'split'; splitBallActive = false; } else if (laserActive) { weaponType = 'laser'; laserActive = false; shotCount = 1; } else if (lightningActive) { weaponType = 'lightning'; lightningActive = false; } // Add cannon fire effect var muzzleFlash = cannon.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, y: -40, scaleX: 0.5, scaleY: 0.5, alpha: 0.8, tint: weaponType === 'fireball' ? 0xff6600 : weaponType === 'laser' ? 0x00ffff : 0xffffff }); // Special combo effects for weapon combinations var activeEffects = 0; if (fireballActive) activeEffects++; if (giantBallActive) activeEffects++; if (splitBallActive) activeEffects++; if (laserActive) activeEffects++; if (lightningActive) activeEffects++; if (multiballActive) activeEffects++; if (doubleShotActive) activeEffects++; if (activeEffects >= 3) { // Triple combo effect var comboFlash = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: cannon.x, y: cannon.y, scaleX: 0.1, scaleY: 0.1, alpha: 0.8, tint: 0xff00ff }); tween(comboFlash, { scaleX: 10, scaleY: 10, alpha: 0, rotation: Math.PI * 4 }, { duration: 1000, onFinish: function onFinish() { comboFlash.destroy(); } }); checkAchievement('tripleCombo'); } tween(muzzleFlash, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 200, onFinish: function onFinish() { muzzleFlash.destroy(); } }); if (multiballActive) { // Fire in multiple directions var angles = [-0.3, -0.15, 0, 0.15, 0.3]; for (var a = 0; a < angles.length; a++) { (function (angleOffset) { LK.setTimeout(function () { var projectile = new SpecialProjectile(); projectile.x = cannon.x; projectile.y = cannon.y - 40; projectile.setType(weaponType); projectile.velocityX = Math.cos(angle + angleOffset) * projectile.speed; projectile.velocityY = Math.sin(angle + angleOffset) * projectile.speed; projectiles.push(projectile); game.addChild(projectile); }, a * 50); })(angles[a]); } multiballActive = false; return; } for (var i = 0; i < shotCount; i++) { LK.setTimeout(function () { var projectile = new SpecialProjectile(); projectile.x = cannon.x; projectile.y = cannon.y - 40; projectile.setType(weaponType); if (weaponType === 'rapid') { var spread = (Math.random() - 0.5) * 0.2; projectile.velocityX = Math.cos(angle + spread) * projectile.speed; projectile.velocityY = Math.sin(angle + spread) * projectile.speed; } else if (weaponType === 'laser') { // Laser goes straight up projectile.velocityX = 0; projectile.velocityY = -projectile.speed; } else { projectile.velocityX = Math.cos(angle) * projectile.speed; projectile.velocityY = Math.sin(angle) * projectile.speed; } projectiles.push(projectile); game.addChild(projectile); LK.getSound('shoot').play(); }, i * delay); } } function checkCollision(obj1, obj2, radius1, radius2) { var dx = obj1.x - obj2.x; var dy = obj1.y - obj2.y; var distance = Math.sqrt(dx * dx + dy * dy); return distance < radius1 + radius2; } function createExplosion(x, y, color, count) { for (var i = 0; i < count; i++) { var particle = new Particle(); particle.x = x; particle.y = y; var angle = Math.random() * Math.PI * 2; var speed = Math.random() * 10 + 5; particle.velocityX = Math.cos(angle) * speed; particle.velocityY = Math.sin(angle) * speed; particle.tint = color; particles.push(particle); game.addChild(particle); } // Create shockwave effect for chain reactions if (chainReactionActive && count > 15) { var shockwave = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: x, y: y, scaleX: 0.1, scaleY: 0.1, alpha: 0.8, tint: color }); tween(shockwave, { scaleX: 5, scaleY: 5, alpha: 0 }, { duration: 500, onFinish: function onFinish() { shockwave.destroy(); } }); } // Screen shake for explosive weapons if (currentWeapon === 'explosive' && count > 15) { var shakeAmount = 20; var originalX = game.x; var originalY = game.y; tween(game, { x: originalX + (Math.random() - 0.5) * shakeAmount, y: originalY + (Math.random() - 0.5) * shakeAmount }, { duration: 50, onFinish: function onFinish() { tween(game, { x: originalX + (Math.random() - 0.5) * shakeAmount * 0.5, y: originalY + (Math.random() - 0.5) * shakeAmount * 0.5 }, { duration: 50, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: 50 }); } }); } }); } } function updateAchievementDisplay() { // Clear existing achievement displays for (var i = achievementPanel.children.length - 1; i >= 0; i--) { var child = achievementPanel.children[i]; if (child !== panelBg && child !== achievementTitle && child !== closeButton) { child.destroy(); } } var unlocked = 0; var total = 0; var yOffset = -500; var xOffset = -400; var row = 0; var col = 0; for (var key in achievements) { total++; if (achievements[key]) unlocked++; var achContainer = new Container(); var achBg = achContainer.attachAsset('achievementItemBg', { anchorX: 0.5, anchorY: 0.5, tint: achievements[key] ? 0x27ae60 : 0x7f8c8d, alpha: 0.9 }); var achText = new Text2(key.replace(/([A-Z])/g, ' $1').trim(), { size: 20, fill: achievements[key] ? 0xFFFFFF : 0x95a5a6 }); achText.anchor.set(0.5, 0.5); achText.y = -10; achContainer.addChild(achText); var achDesc = new Text2(achievementDescriptions[key] || '', { size: 15, fill: achievements[key] ? 0xecf0f1 : 0x7f8c8d }); achDesc.anchor.set(0.5, 0.5); achDesc.y = 10; achContainer.addChild(achDesc); achContainer.x = xOffset + col * 250; achContainer.y = yOffset + row * 60; achievementPanel.addChild(achContainer); col++; if (col > 3) { col = 0; row++; } } var progressText = new Text2('Progress: ' + unlocked + '/' + total, { size: 40, fill: 0xFFD700 }); progressText.anchor.set(0.5, 0.5); progressText.y = 600; achievementPanel.addChild(progressText); } function checkAchievement(key) { if (!achievements[key]) { achievements[key] = true; showAchievement(achievementDescriptions[key] || key, 0xFFD700); saveAchievements(); // Check master achievement var allUnlocked = true; for (var k in achievements) { if (k !== 'masterOfAll' && !achievements[k]) { allUnlocked = false; break; } } if (allUnlocked && !achievements.masterOfAll) { achievements.masterOfAll = true; showAchievement("MASTER OF ALL ACHIEVEMENTS!", 0xFF00FF); } } } function saveAchievements() { savedData.highScore = savedData.highScore || 0; for (var key in achievements) { savedData[key] = achievements[key]; } for (var key in achievementProgress) { savedData[key + 'Progress'] = achievementProgress[key]; } storage['99balls_save'] = savedData; } function showAchievement(text, color) { var achievementText = new Text2('Achievement: ' + text, { size: 60, fill: color }); achievementText.anchor.set(0.5, 0.5); achievementText.y = 200; achievementText.alpha = 0; LK.gui.center.addChild(achievementText); tween(achievementText, { alpha: 1, y: 100 }, { duration: 500, onFinish: function onFinish() { tween(achievementText, { alpha: 0 }, { duration: 1000, delay: 2000, onFinish: function onFinish() { achievementText.destroy(); } }); } }); } function updateCombo() { combo++; comboTimer = 120; // 2 seconds at 60 FPS if (combo >= 5) { scoreMultiplier = Math.min(combo / 5, 5); comboText.setText('COMBO x' + Math.floor(scoreMultiplier)); comboText.alpha = 1; // Enhanced visual feedback var colors = [0xFFD700, 0xFF6347, 0x00CED1, 0xFF1493, 0x32CD32]; comboText.tint = colors[Math.min(Math.floor(scoreMultiplier) - 1, 4)]; tween(comboText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(comboText, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); // Super combo activation if (combo >= 25 && !superComboActive) { superComboActive = true; superComboTimer = 300; // 5 seconds criticalHitChance = 0.5; // 50% critical chance // Super combo activation effect var superComboEffect = new Text2('SUPER COMBO MODE!', { size: 100, fill: 0xff00ff }); superComboEffect.anchor.set(0.5, 0.5); superComboEffect.alpha = 0; LK.gui.center.addChild(superComboEffect); tween(superComboEffect, { alpha: 1, rotation: Math.PI * 2 }, { duration: 500, onFinish: function onFinish() { tween(superComboEffect, { alpha: 0 }, { duration: 1000, delay: 1000, onFinish: function onFinish() { superComboEffect.destroy(); } }); } }); } // Combo milestone effects if (combo === 10 || combo === 20 || combo === 30 || combo === 50 || combo === 100) { var message = combo === 100 ? 'LEGENDARY!' : combo === 50 ? 'UNSTOPPABLE!' : 'AMAZING!'; var comboFlash = new Text2(message, { size: 80 + combo / 10, fill: combo === 100 ? 0xff00ff : 0xFFD700 }); comboFlash.anchor.set(0.5, 0.5); comboFlash.y = -100; comboFlash.alpha = 0; LK.gui.center.addChild(comboFlash); tween(comboFlash, { alpha: 1, y: -150 }, { duration: 300, onFinish: function onFinish() { tween(comboFlash, { alpha: 0 }, { duration: 500, delay: 200, onFinish: function onFinish() { comboFlash.destroy(); } }); } }); } } } function moveRow() { chainReactionActive = false; consecutiveHits = 0; spawnBallRow(); } game.down = function (x, y, obj) { if (!canShoot || !gameActive) return; isAiming = true; aimLine.visible = true; }; game.move = function (x, y, obj) { if (!isAiming || !gameActive) return; var dx = x - cannon.x; var dy = y - cannon.y; var angle = Math.atan2(dy, dx); // Auto aim to nearest ball if (autoAimActive && balls.length > 0) { var closestBall = null; var closestDist = 999999; for (var i = 0; i < balls.length; i++) { var ball = balls[i]; var ballDx = ball.x - cannon.x; var ballDy = ball.y - cannon.y; var dist = Math.sqrt(ballDx * ballDx + ballDy * ballDy); if (dist < closestDist && ball.y < cannon.y) { closestDist = dist; closestBall = ball; } } if (closestBall) { dx = closestBall.x - cannon.x; dy = closestBall.y - cannon.y; angle = Math.atan2(dy, dx); } } if (angle > -Math.PI && angle < 0) { cannon.rotation = angle + Math.PI / 2; aimLine.rotation = angle + Math.PI / 2; } }; game.up = function (x, y, obj) { if (!isAiming || !gameActive) return; isAiming = false; aimLine.visible = false; canShoot = false; var dx = x - cannon.x; var dy = y - cannon.y; var angle = Math.atan2(dy, dx); if (angle > -Math.PI && angle < 0) { fireProjectiles(angle); } }; game.update = function () { if (!gameActive) return; // Update slow motion if (slowMotionActive) { slowMotionTimer--; gameSpeed = 0.3; if (slowMotionTimer <= 0) { slowMotionActive = false; gameSpeed = 1; tween(slowMotionBg, { alpha: 0 }, { duration: 300 }); powerUpIndicator.setText(''); } } else { gameSpeed = 1; } // Update magnet effect if (magnetActive) { magnetTimer--; if (magnetTimer <= 0) { magnetActive = false; } } // Update combo timer if (comboTimer > 0) { comboTimer--; if (comboTimer === 0) { combo = 0; scoreMultiplier = 1; consecutiveHits = 0; tween(comboText, { alpha: 0 }, { duration: 300 }); } } else if (combo > 0) { // Add dynamic combo multiplier visual var comboScale = 1 + Math.sin(LK.ticks * 0.2) * 0.1 * Math.min(combo / 10, 1); comboText.scale.set(comboScale); } // Update particles for (var i = particles.length - 1; i >= 0; i--) { if (particles[i].update()) { particles[i].destroy(); particles.splice(i, 1); } } // Update slow motion powerups for (var i = 0; i < slowMotionPowerups.length; i++) { slowMotionPowerups[i].update(); } // Update multiball powerups for (var i = 0; i < multiballPowerups.length; i++) { multiballPowerups[i].update(); } // Update shield if (shieldActive) { shieldTimer--; shieldIndicator.x = cannon.x; shieldIndicator.y = cannon.y; shieldBg.alpha = 0.3 + Math.sin(LK.ticks * 0.2) * 0.2; shieldBg.rotation += 0.05; if (shieldTimer <= 0) { shieldActive = false; tween(shieldBg, { alpha: 0 }, { duration: 300 }); powerUpIndicator.setText(''); } } // Update freeze if (freezeActive) { freezeTimer--; if (freezeTimer <= 0) { freezeActive = false; gameSpeed = 1; for (var i = 0; i < balls.length; i++) { balls[i].tint = 0xffffff; } } } // Update new power-ups for (var i = 0; i < shieldPowerups.length; i++) { shieldPowerups[i].update(); } for (var i = 0; i < fireballPowerups.length; i++) { fireballPowerups[i].update(); } for (var i = 0; i < giantBallPowerups.length; i++) { giantBallPowerups[i].update(); } for (var i = 0; i < splitBallPowerups.length; i++) { splitBallPowerups[i].update(); } for (var i = 0; i < laserPowerups.length; i++) { laserPowerups[i].update(); } for (var i = 0; i < doubleShotPowerups.length; i++) { doubleShotPowerups[i].update(); } // Update double shot timer if (doubleShotActive) { doubleShotTimer--; if (doubleShotTimer <= 0) { doubleShotActive = false; doubleShotIndicator.setText(''); } } // Update lightning powerups for (var i = 0; i < lightningPowerups.length; i++) { lightningPowerups[i].update(); } // Update ghost balls for (var i = 0; i < ghostBalls.length; i++) { ghostBalls[i].update(); } // Update reverse gravity if (reverseGravityActive) { reverseGravityTimer--; if (reverseGravityTimer <= 0) { reverseGravityActive = false; ballSpeed = Math.abs(ballSpeed); powerUpIndicator.setText(''); } } // Update score boost if (scoreBoostActive) { scoreBoostTimer--; scoreBoostMultiplier = 3; if (scoreBoostTimer <= 0) { scoreBoostActive = false; scoreBoostMultiplier = 1; powerUpIndicator.setText(''); } } else { scoreBoostMultiplier = 1; } // Update auto aim if (autoAimActive) { autoAimTimer--; if (autoAimTimer <= 0) { autoAimActive = false; powerUpIndicator.setText(''); } } // Update freeze bomb powerups for (var i = 0; i < freezeBombPowerups.length; i++) { freezeBombPowerups[i].update(); } // Update mirror balls for (var i = 0; i < mirrorBalls.length; i++) { if (mirrorBalls[i].update) { mirrorBalls[i].update(); } } // Update magnet balls for (var i = 0; i < magnetBalls.length; i++) { if (magnetBalls[i].update) { magnetBalls[i].update(); } } // Update chain reaction powerups for (var i = 0; i < chainReactionPowerups.length; i++) { chainReactionPowerups[i].update(); } // Update teleport powerups for (var i = 0; i < teleportPowerups.length; i++) { teleportPowerups[i].update(); } // Update rainbow laser powerups for (var i = 0; i < rainbowLaserPowerups.length; i++) { rainbowLaserPowerups[i].update(); } // Update gravity well balls for (var i = 0; i < gravityWellBalls.length; i++) { if (gravityWellBalls[i].update) { gravityWellBalls[i].update(); } } // Update time warp powerups for (var i = 0; i < timeWarpPowerups.length; i++) { timeWarpPowerups[i].update(); } // Update time warp effect if (timeWarpActive) { timeWarpTimer--; // Alternate between fast and slow if (Math.floor(timeWarpTimer / 60) % 2 === 0) { gameSpeed = 0.2; } else { gameSpeed = 2; } if (timeWarpTimer <= 0) { timeWarpActive = false; gameSpeed = 1; powerUpIndicator.setText(''); } } // Update super combo if (superComboActive) { superComboTimer--; if (superComboTimer <= 0) { superComboActive = false; criticalHitChance = 0.1; } } // Update bullet time if (bulletTimeActive) { bulletTimeTimer--; if (bulletTimeTimer <= 0) { bulletTimeActive = false; } } // Track time played timePlayed++; if (timePlayed % 3600 === 0) { // Every minute var minutes = timePlayed / 3600; if (minutes === 5) checkAchievement('persistent'); } // Track max combo if (combo > maxCombo) { maxCombo = combo; } // Update boss balls for (var i = 0; i < bossBalls.length; i++) { if (bossBalls[i].update) { bossBalls[i].update(); } bossBalls[i].y += ballSpeed * gameSpeed * 0.5; // Boss moves slower } // Update ball falling speed and call update for (var i = 0; i < balls.length; i++) { balls[i].y += ballSpeed * gameSpeed; if (balls[i].update) { balls[i].update(); } } for (var i = 0; i < powerups.length; i++) { powerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < stars.length; i++) { stars[i].y += ballSpeed * gameSpeed; if (stars[i].update) { stars[i].update(); } } for (var i = 0; i < slowMotionPowerups.length; i++) { slowMotionPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < multiballPowerups.length; i++) { multiballPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < fireballPowerups.length; i++) { fireballPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < giantBallPowerups.length; i++) { giantBallPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < splitBallPowerups.length; i++) { splitBallPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < laserPowerups.length; i++) { laserPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < shieldPowerups.length; i++) { shieldPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < doubleShotPowerups.length; i++) { doubleShotPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < lightningPowerups.length; i++) { lightningPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < ghostBalls.length; i++) { ghostBalls[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < mirrorBalls.length; i++) { mirrorBalls[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < magnetBalls.length; i++) { magnetBalls[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < freezeBombPowerups.length; i++) { freezeBombPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < chainReactionPowerups.length; i++) { chainReactionPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < teleportPowerups.length; i++) { teleportPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < rainbowLaserPowerups.length; i++) { rainbowLaserPowerups[i].y += ballSpeed * gameSpeed; } for (var i = 0; i < gravityWellBalls.length; i++) { gravityWellBalls[i].y += ballSpeed * gameSpeed * 0.7; // Gravity wells move slower } for (var i = 0; i < timeWarpPowerups.length; i++) { timeWarpPowerups[i].y += ballSpeed * gameSpeed; } // Update rainbow balls for (var i = 0; i < rainbowBalls.length; i++) { rainbowBalls[i].y += ballSpeed * gameSpeed; if (rainbowBalls[i].update) { rainbowBalls[i].update(); } } // Update bomb balls for (var i = 0; i < bombBalls.length; i++) { bombBalls[i].y += ballSpeed * gameSpeed; if (bombBalls[i].update) { bombBalls[i].update(); } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; // Apply game speed to projectile movement var oldVelX = projectile.velocityX; var oldVelY = projectile.velocityY; projectile.velocityX *= gameSpeed; projectile.velocityY *= gameSpeed; if (projectile.update() || projectile.y > 2732 + 50) { projectile.destroy(); projectiles.splice(i, 1); continue; } projectile.velocityX = oldVelX; projectile.velocityY = oldVelY; // Apply magnet effect if (magnetActive) { var closestBall = null; var closestDist = 200; for (var j = 0; j < balls.length; j++) { var ball = balls[j]; var dx = ball.x - projectile.x; var dy = ball.y - projectile.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < closestDist) { closestDist = dist; closestBall = ball; } } if (closestBall) { var dx = closestBall.x - projectile.x; var dy = closestBall.y - projectile.y; var dist = Math.sqrt(dx * dx + dy * dy); projectile.velocityX += dx / dist * 2; projectile.velocityY += dy / dist * 2; var speed = Math.sqrt(projectile.velocityX * projectile.velocityX + projectile.velocityY * projectile.velocityY); if (speed > projectile.speed * 1.5) { projectile.velocityX = projectile.velocityX / speed * projectile.speed * 1.5; projectile.velocityY = projectile.velocityY / speed * projectile.speed * 1.5; } } } // Apply magnet ball attraction for (var m = 0; m < magnetBalls.length; m++) { var magnetBall = magnetBalls[m]; var dx = magnetBall.x - projectile.x; var dy = magnetBall.y - projectile.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < magnetBall.magnetRadius && dist > magnetBall.radius) { // Attract projectile var force = (1 - dist / magnetBall.magnetRadius) * 3; projectile.velocityX += dx / dist * force; projectile.velocityY += dy / dist * force; // Normalize speed var speed = Math.sqrt(projectile.velocityX * projectile.velocityX + projectile.velocityY * projectile.velocityY); if (speed > projectile.speed * 2) { projectile.velocityX = projectile.velocityX / speed * projectile.speed * 2; projectile.velocityY = projectile.velocityY / speed * projectile.speed * 2; } } } // Apply gravity well effects for (var g = 0; g < gravityWellBalls.length; g++) { var gravityWell = gravityWellBalls[g]; var dx = gravityWell.x - projectile.x; var dy = gravityWell.y - projectile.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < gravityWell.gravityRadius && dist > gravityWell.radius) { // Pull projectile towards gravity well var force = (1 - dist / gravityWell.gravityRadius) * 5; projectile.velocityX += dx / dist * force; projectile.velocityY += dy / dist * force; // Add swirl effect var angle = Math.atan2(dy, dx) + Math.PI / 2; projectile.velocityX += Math.cos(angle) * force * 0.3; projectile.velocityY += Math.sin(angle) * force * 0.3; // Normalize speed var speed = Math.sqrt(projectile.velocityX * projectile.velocityX + projectile.velocityY * projectile.velocityY); if (speed > projectile.speed * 3) { projectile.velocityX = projectile.velocityX / speed * projectile.speed * 3; projectile.velocityY = projectile.velocityY / speed * projectile.speed * 3; } } } var hitBall = false; // Check boss collisions first for (var j = bossBalls.length - 1; j >= 0; j--) { var boss = bossBalls[j]; if (checkCollision(projectile, boss, projectile.radius, boss.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; // Critical hit chance var isCritical = Math.random() < criticalHitChance; var damage = isCritical ? 5 : 1; if (isCritical) { var critText = new Text2('CRITICAL!', { size: 60, fill: 0xffff00 }); critText.anchor.set(0.5, 0.5); critText.x = boss.x; critText.y = boss.y - 100; game.addChild(critText); tween(critText, { y: boss.y - 150, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { critText.destroy(); } }); // Add critical hit effect var critEffect = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: boss.x, y: boss.y, scaleX: 0.1, scaleY: 0.1, alpha: 0.8, tint: 0xffff00 }); tween(critEffect, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 500, onFinish: function onFinish() { critEffect.destroy(); } }); } for (var d = 0; d < damage; d++) { if (boss.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 500); createExplosion(boss.x, boss.y, 0xff1744, 50); boss.destroy(); bossBalls.splice(j, 1); // Boss killed achievement if (!achievements.bossKiller) { achievements.bossKiller = true; showAchievement('Boss Slayer!', 0xff1744); } break; } } // Handle projectile after boss hit if (projectile.type !== 'piercing' && projectile.type !== 'fireball' && projectile.type !== 'laser') { projectile.destroy(); projectiles.splice(i, 1); i--; break; } } } // Check rainbow ball collisions for (var j = rainbowBalls.length - 1; j >= 0; j--) { var rainbowBall = rainbowBalls[j]; if (checkCollision(projectile, rainbowBall, projectile.radius, rainbowBall.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; // Rainbow balls give bonus points var bonus = 50 * scoreMultiplier; if (rainbowBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + bonus * 5); createExplosion(rainbowBall.x, rainbowBall.y, 0xffffff, 40); achievementProgress.rainbowHunter++; if (achievementProgress.rainbowHunter >= 20) checkAchievement('rainbowHunter'); // Create rainbow particle effect for (var p = 0; p < 20; p++) { var particle = new Particle(); particle.x = rainbowBall.x; particle.y = rainbowBall.y; var angle = p / 20 * Math.PI * 2; particle.velocityX = Math.cos(angle) * 8; particle.velocityY = Math.sin(angle) * 8; particle.tint = Math.random() * 0xffffff | 0; particles.push(particle); game.addChild(particle); } rainbowBall.destroy(); rainbowBalls.splice(j, 1); } // Projectile continues through rainbow balls } } // Check ghost ball collisions for (var j = ghostBalls.length - 1; j >= 0; j--) { var ghostBall = ghostBalls[j]; if (!ghostBall.isPhased && checkCollision(projectile, ghostBall, projectile.radius, ghostBall.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; if (ghostBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 100 * scoreMultiplier * scoreBoostMultiplier); createExplosion(ghostBall.x, ghostBall.y, 0x8888ff, 30); ghostBall.destroy(); ghostBalls.splice(j, 1); ballsDestroyed++; if (!achievements.ghostHunter) { achievements.ghostHunter = true; showAchievement('Ghost Hunter!', 0x8888ff); } } } } // Check magnet ball collisions for (var j = magnetBalls.length - 1; j >= 0; j--) { var magnetBall = magnetBalls[j]; if (checkCollision(projectile, magnetBall, projectile.radius, magnetBall.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; if (magnetBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 200 * scoreMultiplier * scoreBoostMultiplier); createExplosion(magnetBall.x, magnetBall.y, 0x0066cc, 45); // Create magnetic shockwave var shockwave = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: magnetBall.x, y: magnetBall.y, scaleX: 0.1, scaleY: 0.1, alpha: 0.6, tint: 0x0099ff }); tween(shockwave, { scaleX: 8, scaleY: 8, alpha: 0 }, { duration: 800, onFinish: function onFinish() { shockwave.destroy(); } }); magnetBall.destroy(); magnetBalls.splice(j, 1); ballsDestroyed++; checkAchievement('magnetMaster'); } // Projectile behavior after magnet hit if (projectile.type !== 'laser' && projectile.type !== 'piercing') { projectile.destroy(); projectiles.splice(i, 1); i--; break; } } } // Check gravity well collisions for (var j = gravityWellBalls.length - 1; j >= 0; j--) { var gravityWell = gravityWellBalls[j]; if (checkCollision(projectile, gravityWell, projectile.radius, gravityWell.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; // Gravity wells suck in the projectile if (gravityWell.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 300 * scoreMultiplier * scoreBoostMultiplier); // Create implosion effect for (var p = 0; p < 30; p++) { var particle = new Particle(); particle.x = gravityWell.x + (Math.random() - 0.5) * 200; particle.y = gravityWell.y + (Math.random() - 0.5) * 200; var dx = gravityWell.x - particle.x; var dy = gravityWell.y - particle.y; var dist = Math.sqrt(dx * dx + dy * dy); particle.velocityX = dx / dist * 10; particle.velocityY = dy / dist * 10; particle.tint = 0x4a0080; particles.push(particle); game.addChild(particle); } // Pull nearby balls for (var k = 0; k < balls.length; k++) { var nearbyBall = balls[k]; if (checkCollision(gravityWell, nearbyBall, 200, nearbyBall.radius)) { var dx = gravityWell.x - nearbyBall.x; var dy = gravityWell.y - nearbyBall.y; nearbyBall.x += dx * 0.3; nearbyBall.y += dy * 0.3; } } gravityWell.destroy(); gravityWellBalls.splice(j, 1); ballsDestroyed++; } projectile.destroy(); projectiles.splice(i, 1); i--; break; } } // Check mirror ball collisions for (var j = mirrorBalls.length - 1; j >= 0; j--) { var mirrorBall = mirrorBalls[j]; if (checkCollision(projectile, mirrorBall, projectile.radius, mirrorBall.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; // Reflect projectile var dx = projectile.x - mirrorBall.x; var dy = projectile.y - mirrorBall.y; var dist = Math.sqrt(dx * dx + dy * dy); dx /= dist; dy /= dist; projectile.velocityX = dx * projectile.speed * 1.5; projectile.velocityY = dy * projectile.speed * 1.5; // Mirror flash effect var flash = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: mirrorBall.x, y: mirrorBall.y, scaleX: 1, scaleY: 1, alpha: 0.8, tint: 0xffffff }); tween(flash, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { flash.destroy(); } }); if (mirrorBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 150 * scoreMultiplier * scoreBoostMultiplier); createExplosion(mirrorBall.x, mirrorBall.y, 0xc0c0c0, 40); mirrorBall.destroy(); mirrorBalls.splice(j, 1); ballsDestroyed++; } // Projectile bounces off mirror balls if (projectile.type !== 'laser') { break; } } } // Check bomb ball collisions for (var j = bombBalls.length - 1; j >= 0; j--) { var bombBall = bombBalls[j]; if (checkCollision(projectile, bombBall, projectile.radius, bombBall.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; if (bombBall.takeDamage()) { LK.getSound('destroy').play(); // Bomb explosion damages all nearby balls createExplosion(bombBall.x, bombBall.y, 0xff0000, 50); LK.effects.flashScreen(0xff0000, 300); achievementProgress.bombExpert++; if (achievementProgress.bombExpert >= 10) checkAchievement('bombExpert'); // Damage all balls in explosion radius for (var k = balls.length - 1; k >= 0; k--) { var nearbyBall = balls[k]; if (checkCollision(bombBall, nearbyBall, 200, nearbyBall.radius)) { for (var d = 0; d < 3; d++) { if (nearbyBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + Math.floor(stage * scoreMultiplier * 2)); createExplosion(nearbyBall.x, nearbyBall.y, 0xffff00, 20); nearbyBall.destroy(); balls.splice(k, 1); break; } } } } bombBall.destroy(); bombBalls.splice(j, 1); } projectile.destroy(); projectiles.splice(i, 1); i--; break; } } // Check ball collisions for (var j = balls.length - 1; j >= 0; j--) { var ball = balls[j]; if (checkCollision(projectile, ball, projectile.radius, ball.radius)) { LK.getSound('hit').play(); updateCombo(); hitBall = true; // Handle explosive projectiles if (projectile.type === 'explosive') { createExplosion(ball.x, ball.y, 0xff4444, 20); // Damage nearby balls for (var k = balls.length - 1; k >= 0; k--) { var otherBall = balls[k]; if (checkCollision(ball, otherBall, 150, otherBall.radius)) { if (otherBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + Math.floor(stage * scoreMultiplier)); createExplosion(otherBall.x, otherBall.y, 0xffff00, 10); otherBall.destroy(); balls.splice(k, 1); } } } } if (ball.takeDamage()) { LK.getSound('destroy').play(); consecutiveHits++; if (consecutiveHits >= 3) { chainReactionActive = true; achievementProgress.chainReactionPro++; if (achievementProgress.chainReactionPro >= 50) checkAchievement('chainReactionPro'); } // Track weapon kills switch (projectile.type) { case 'fireball': achievementProgress.fireballKills++; if (achievementProgress.fireballKills >= 100) checkAchievement('fireballKills'); break; case 'laser': achievementProgress.laserKills++; if (achievementProgress.laserKills >= 100) checkAchievement('laserKills'); break; case 'explosive': achievementProgress.explosiveKills++; if (achievementProgress.explosiveKills >= 100) checkAchievement('explosiveKills'); break; case 'piercing': achievementProgress.piercingKills++; if (achievementProgress.piercingKills >= 100) checkAchievement('piercingKills'); break; case 'rapid': achievementProgress.rapidKills++; if (achievementProgress.rapidKills >= 100) checkAchievement('rapidKills'); break; case 'split': achievementProgress.splitKills++; if (achievementProgress.splitKills >= 100) checkAchievement('splitKills'); break; case 'giant': achievementProgress.giantKills++; if (achievementProgress.giantKills >= 100) checkAchievement('giantKills'); break; } // Track perfect accuracy achievementProgress.perfectAccuracy++; if (achievementProgress.perfectAccuracy >= 100) checkAchievement('perfectAccuracy'); // Check for lucky long distance shot var shotDistance = Math.sqrt(Math.pow(ball.x - cannon.x, 2) + Math.pow(ball.y - cannon.y, 2)); if (shotDistance > 2000) { checkAchievement('luckyShot'); // Lucky shot visual effect var luckyText = new Text2('LUCKY SHOT!', { size: 80, fill: 0xffd700 }); luckyText.anchor.set(0.5, 0.5); luckyText.x = ball.x; luckyText.y = ball.y - 100; game.addChild(luckyText); tween(luckyText, { y: ball.y - 200, alpha: 0 }, { duration: 1500, onFinish: function onFinish() { luckyText.destroy(); } }); } var points = Math.floor(stage * scoreMultiplier * scoreBoostMultiplier * (chainReactionActive ? 2 : 1)); LK.setScore(LK.getScore() + points); scoreText.setText('Score: ' + LK.getScore()); createExplosion(ball.x, ball.y, 0xffff00, chainReactionActive ? 25 : 15); // Chain reaction damage if (chainReactionActive) { for (var k = balls.length - 1; k >= 0; k--) { var nearbyBall = balls[k]; if (nearbyBall !== ball && checkCollision(ball, nearbyBall, 100, nearbyBall.radius)) { if (nearbyBall.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + Math.floor(stage * scoreMultiplier * 2)); createExplosion(nearbyBall.x, nearbyBall.y, 0xffff00, 20); nearbyBall.destroy(); balls.splice(k, 1); } } } } ball.destroy(); balls.splice(j, 1); ballsDestroyed++; perfectHits++; } // Handle projectile behavior after hit if (projectile.type === 'lightning') { // Chain to nearby balls var chainTargets = []; for (var k = 0; k < balls.length; k++) { var nearbyBall = balls[k]; if (nearbyBall !== ball && checkCollision(ball, nearbyBall, 150, nearbyBall.radius)) { chainTargets.push(nearbyBall); } } // Create lightning visual effect for (var c = 0; c < Math.min(chainTargets.length, 3); c++) { var target = chainTargets[c]; var lightning = game.attachAsset('aimline', { anchorX: 0.5, anchorY: 0, x: ball.x, y: ball.y, tint: 0x9966ff, alpha: 0.8 }); var dx = target.x - ball.x; var dy = target.y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); lightning.height = dist; lightning.rotation = Math.atan2(dy, dx) + Math.PI / 2; tween(lightning, { alpha: 0, scaleX: 0.1 }, { duration: 300, onFinish: function onFinish() { lightning.destroy(); } }); // Damage chained balls if (target.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + Math.floor(stage * scoreMultiplier * scoreBoostMultiplier)); createExplosion(target.x, target.y, 0x9966ff, 20); target.destroy(); var idx = balls.indexOf(target); if (idx > -1) balls.splice(idx, 1); } } projectile.destroy(); projectiles.splice(i, 1); i--; break; } else if (projectile.type === 'piercing' && projectile.piercing > 0) { projectile.piercing--; // Continue in same direction } else if (projectile.type === 'explosive') { projectile.destroy(); projectiles.splice(i, 1); i--; break; } else if (projectile.type === 'fireball') { // Fireball burns through everything createExplosion(ball.x, ball.y, 0xff6600, 15); } else if (projectile.type === 'split') { // Split into 3 projectiles for (var s = 0; s < 3; s++) { var splitProjectile = new SpecialProjectile(); splitProjectile.x = projectile.x; splitProjectile.y = projectile.y; splitProjectile.setType('normal'); var splitAngle = Math.atan2(projectile.velocityY, projectile.velocityX) + (s - 1) * 0.5; splitProjectile.velocityX = Math.cos(splitAngle) * splitProjectile.speed; splitProjectile.velocityY = Math.sin(splitAngle) * splitProjectile.speed; projectiles.push(splitProjectile); game.addChild(splitProjectile); } projectile.destroy(); projectiles.splice(i, 1); i--; break; } else if (projectile.type === 'laser') { // Laser continues straight } else { // Normal bounce var dx = projectile.x - ball.x; var dy = projectile.y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); dx /= dist; dy /= dist; projectile.velocityX = dx * projectile.speed; projectile.velocityY = dy * projectile.speed; } if (!projectile.type || projectile.type === 'normal' || projectile.type === 'rapid' || projectile.type === 'giant') { break; } } } if (hitBall) { // Perfect shot bonus if (consecutiveHits >= 10 && consecutiveHits % 5 === 0) { var perfectBonus = 100 * scoreMultiplier; LK.setScore(LK.getScore() + perfectBonus); var perfectText = new Text2('PERFECT SHOT! +' + perfectBonus, { size: 60, fill: 0x00ff00 }); perfectText.anchor.set(0.5, 0.5); perfectText.alpha = 0; LK.gui.center.addChild(perfectText); tween(perfectText, { alpha: 1, y: -50 }, { duration: 300, onFinish: function onFinish() { tween(perfectText, { alpha: 0 }, { duration: 500, delay: 500, onFinish: function onFinish() { perfectText.destroy(); } }); } }); } continue; } else { chainReactionActive = false; consecutiveHits = 0; } // Check powerup collisions for (var j = powerups.length - 1; j >= 0; j--) { var powerup = powerups[j]; if (checkCollision(projectile, powerup, projectile.radius, powerup.radius)) { LK.getSound('collect').play(); projectileCount++; projectileCountText.setText('x' + projectileCount); createExplosion(powerup.x, powerup.y, 0x4ecdc4, 10); powerup.destroy(); powerups.splice(j, 1); } } // Check slow motion power-up collisions for (var j = slowMotionPowerups.length - 1; j >= 0; j--) { var slowPowerup = slowMotionPowerups[j]; if (checkCollision(projectile, slowPowerup, projectile.radius, slowPowerup.radius)) { LK.getSound('collect').play(); slowMotionActive = true; slowMotionTimer = 300; // 5 seconds at 60 FPS powerUpIndicator.setText('SLOW MOTION'); achievementProgress.slowMotionPro++; achievementProgress.powerupMaster++; if (achievementProgress.slowMotionPro >= 20) checkAchievement('slowMotionPro'); if (achievementProgress.powerupMaster >= 100) checkAchievement('powerupMaster'); tween(slowMotionBg, { alpha: 0.1 }, { duration: 300 }); createExplosion(slowPowerup.x, slowPowerup.y, 0x9b59b6, 20); slowPowerup.destroy(); slowMotionPowerups.splice(j, 1); } } // Check multiball power-up collisions for (var j = multiballPowerups.length - 1; j >= 0; j--) { var multiballPowerup = multiballPowerups[j]; if (checkCollision(projectile, multiballPowerup, projectile.radius, multiballPowerup.radius)) { LK.getSound('collect').play(); multiballActive = true; powerUpIndicator.setText('MULTIBALL!'); createExplosion(multiballPowerup.x, multiballPowerup.y, 0xe74c3c, 25); multiballPowerup.destroy(); multiballPowerups.splice(j, 1); } } // Check fireball power-up collisions for (var j = fireballPowerups.length - 1; j >= 0; j--) { var fireballPowerup = fireballPowerups[j]; if (checkCollision(projectile, fireballPowerup, projectile.radius, fireballPowerup.radius)) { LK.getSound('collect').play(); fireballActive = true; powerUpIndicator.setText('FIREBALL!'); createExplosion(fireballPowerup.x, fireballPowerup.y, 0xff6600, 30); fireballPowerup.destroy(); fireballPowerups.splice(j, 1); } } // Check giant ball power-up collisions for (var j = giantBallPowerups.length - 1; j >= 0; j--) { var giantBallPowerup = giantBallPowerups[j]; if (checkCollision(projectile, giantBallPowerup, projectile.radius, giantBallPowerup.radius)) { LK.getSound('collect').play(); giantBallActive = true; powerUpIndicator.setText('GIANT BALL!'); createExplosion(giantBallPowerup.x, giantBallPowerup.y, 0x00ff00, 35); giantBallPowerup.destroy(); giantBallPowerups.splice(j, 1); } } // Check split ball power-up collisions for (var j = splitBallPowerups.length - 1; j >= 0; j--) { var splitBallPowerup = splitBallPowerups[j]; if (checkCollision(projectile, splitBallPowerup, projectile.radius, splitBallPowerup.radius)) { LK.getSound('collect').play(); splitBallActive = true; powerUpIndicator.setText('SPLIT BALL!'); createExplosion(splitBallPowerup.x, splitBallPowerup.y, 0xff00ff, 30); splitBallPowerup.destroy(); splitBallPowerups.splice(j, 1); } } // Check laser power-up collisions for (var j = laserPowerups.length - 1; j >= 0; j--) { var laserPowerup = laserPowerups[j]; if (checkCollision(projectile, laserPowerup, projectile.radius, laserPowerup.radius)) { LK.getSound('collect').play(); laserActive = true; powerUpIndicator.setText('LASER BEAM!'); createExplosion(laserPowerup.x, laserPowerup.y, 0x00ffff, 40); laserPowerup.destroy(); laserPowerups.splice(j, 1); } } // Check shield power-up collisions for (var j = shieldPowerups.length - 1; j >= 0; j--) { var shieldPowerup = shieldPowerups[j]; if (checkCollision(projectile, shieldPowerup, projectile.radius, shieldPowerup.radius)) { LK.getSound('collect').play(); shieldActive = true; shieldTimer = 600; // 10 seconds powerUpIndicator.setText('SHIELD ACTIVE!'); tween(shieldBg, { alpha: 0.3 }, { duration: 300 }); createExplosion(shieldPowerup.x, shieldPowerup.y, 0x3498db, 30); shieldPowerup.destroy(); shieldPowerups.splice(j, 1); // Shield achievement if (!achievements.shieldMaster) { achievements.shieldMaster = true; showAchievement('Shield Master!', 0x3498db); } } } // Check double shot power-up collisions for (var j = doubleShotPowerups.length - 1; j >= 0; j--) { var doubleShotPowerup = doubleShotPowerups[j]; if (checkCollision(projectile, doubleShotPowerup, projectile.radius, doubleShotPowerup.radius)) { LK.getSound('collect').play(); doubleShotActive = true; doubleShotTimer = 600; // 10 seconds doubleShotIndicator.setText('DOUBLE SHOT!'); createExplosion(doubleShotPowerup.x, doubleShotPowerup.y, 0xffff00, 35); doubleShotPowerup.destroy(); doubleShotPowerups.splice(j, 1); } } // Check lightning power-up collisions for (var j = lightningPowerups.length - 1; j >= 0; j--) { var lightningPowerup = lightningPowerups[j]; if (checkCollision(projectile, lightningPowerup, projectile.radius, lightningPowerup.radius)) { LK.getSound('collect').play(); lightningActive = true; powerUpIndicator.setText('LIGHTNING CHAIN!'); createExplosion(lightningPowerup.x, lightningPowerup.y, 0x9966ff, 40); lightningPowerup.destroy(); lightningPowerups.splice(j, 1); powerupsCollected++; if (!achievements.lightningMaster) { achievements.lightningMaster = true; showAchievement('Lightning Master!', 0x9966ff); } } } // Check freeze bomb power-up collisions for (var j = freezeBombPowerups.length - 1; j >= 0; j--) { var freezeBombPowerup = freezeBombPowerups[j]; if (checkCollision(projectile, freezeBombPowerup, projectile.radius, freezeBombPowerup.radius)) { LK.getSound('collect').play(); // Freeze explosion effect createExplosion(freezeBombPowerup.x, freezeBombPowerup.y, 0x00ccff, 50); LK.effects.flashScreen(0x00ccff, 500); // Freeze all balls in radius for (var k = 0; k < balls.length; k++) { var ball = balls[k]; if (checkCollision(freezeBombPowerup, ball, 300, ball.radius)) { ball.tint = 0x00ccff; // Create ice effect on ball var ice = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: ball.x, y: ball.y, scaleX: 1.2, scaleY: 1.2, alpha: 0.3, tint: 0x00ffff }); tween(ice, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 2000, onFinish: function onFinish() { ice.destroy(); } }); // Damage frozen ball for (var d = 0; d < 5; d++) { if (ball.takeDamage()) { LK.getSound('destroy').play(); LK.setScore(LK.getScore() + Math.floor(stage * scoreMultiplier * 3)); createExplosion(ball.x, ball.y, 0x00ccff, 25); ball.destroy(); var idx = balls.indexOf(ball); if (idx > -1) balls.splice(idx, 1); ballsDestroyed++; break; } } } } freezeBombPowerup.destroy(); freezeBombPowerups.splice(j, 1); powerupsCollected++; } } // Check chain reaction power-up collisions for (var j = chainReactionPowerups.length - 1; j >= 0; j--) { var chainReactionPowerup = chainReactionPowerups[j]; if (checkCollision(projectile, chainReactionPowerup, projectile.radius, chainReactionPowerup.radius)) { LK.getSound('collect').play(); chainReactionBombActive = true; powerUpIndicator.setText('CHAIN BOMB!'); createExplosion(chainReactionPowerup.x, chainReactionPowerup.y, 0xff8800, 40); // Make next hit cause massive chain reaction consecutiveHits = 10; chainReactionActive = true; chainReactionPowerup.destroy(); chainReactionPowerups.splice(j, 1); powerupsCollected++; } } // Check teleport power-up collisions for (var j = teleportPowerups.length - 1; j >= 0; j--) { var teleportPowerup = teleportPowerups[j]; if (checkCollision(projectile, teleportPowerup, projectile.radius, teleportPowerup.radius)) { LK.getSound('collect').play(); // Teleport effect var portal1 = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: projectile.x, y: projectile.y, scaleX: 0.1, scaleY: 0.1, alpha: 0.8, tint: 0x8000ff }); tween(portal1, { scaleX: 2, scaleY: 2, alpha: 0, rotation: Math.PI * 2 }, { duration: 500, onFinish: function onFinish() { portal1.destroy(); } }); // Teleport projectile to random position projectile.x = Math.random() * 1648 + 200; projectile.y = Math.random() * 1000 + 500; // Exit portal effect var portal2 = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: projectile.x, y: projectile.y, scaleX: 2, scaleY: 2, alpha: 0, tint: 0x8000ff }); tween(portal2, { scaleX: 0.1, scaleY: 0.1, alpha: 0.8, rotation: -Math.PI * 2 }, { duration: 500, onFinish: function onFinish() { portal2.destroy(); } }); teleportPowerup.destroy(); teleportPowerups.splice(j, 1); powerupsCollected++; } } // Check rainbow laser power-up collisions for (var j = rainbowLaserPowerups.length - 1; j >= 0; j--) { var rainbowLaserPowerup = rainbowLaserPowerups[j]; if (checkCollision(projectile, rainbowLaserPowerup, projectile.radius, rainbowLaserPowerup.radius)) { LK.getSound('collect').play(); rainbowLaserActive = true; powerUpIndicator.setText('RAINBOW LASER!'); // Epic rainbow explosion for (var r = 0; r < 50; r++) { var particle = new Particle(); particle.x = rainbowLaserPowerup.x; particle.y = rainbowLaserPowerup.y; var angle = r / 50 * Math.PI * 2; particle.velocityX = Math.cos(angle) * 15; particle.velocityY = Math.sin(angle) * 15; var hue = r / 50; var red = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128); var green = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128); var blue = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128); particle.tint = red << 16 | green << 8 | blue; particles.push(particle); game.addChild(particle); } rainbowLaserPowerup.destroy(); rainbowLaserPowerups.splice(j, 1); powerupsCollected++; } } // Check time warp power-up collisions for (var j = timeWarpPowerups.length - 1; j >= 0; j--) { var timeWarpPowerup = timeWarpPowerups[j]; if (checkCollision(projectile, timeWarpPowerup, projectile.radius, timeWarpPowerup.radius)) { LK.getSound('collect').play(); timeWarpActive = true; timeWarpTimer = 600; // 10 seconds of time warping powerUpIndicator.setText('TIME WARP!'); // Time distortion visual var warpEffect = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: timeWarpPowerup.x, y: timeWarpPowerup.y, scaleX: 0.1, scaleY: 0.1, alpha: 0.8, tint: 0x00ff88 }); tween(warpEffect, { scaleX: 20, scaleY: 20, alpha: 0, rotation: Math.PI * 4 }, { duration: 1000, onFinish: function onFinish() { warpEffect.destroy(); } }); timeWarpPowerup.destroy(); timeWarpPowerups.splice(j, 1); powerupsCollected++; } } // Check star collisions for (var j = stars.length - 1; j >= 0; j--) { var star = stars[j]; if (checkCollision(projectile, star, projectile.radius, star.radius)) { LK.getSound('collect').play(); // Random bonus effect var randomEffect = Math.random(); if (randomEffect < 0.15) { magnetActive = true; magnetTimer = 180; // 3 seconds powerUpIndicator.setText('MAGNET ACTIVE'); } else if (randomEffect < 0.3) { projectileCount += 2; projectileCountText.setText('x' + projectileCount); } else if (randomEffect < 0.45) { // Freeze all balls temporarily freezeActive = true; freezeTimer = 180; // 3 seconds powerUpIndicator.setText('FREEZE!'); for (var k = 0; k < balls.length; k++) { balls[k].tint = 0x00ffff; } } else if (randomEffect < 0.6) { // Reverse gravity reverseGravityActive = true; reverseGravityTimer = 300; // 5 seconds ballSpeed = -Math.abs(ballSpeed); powerUpIndicator.setText('REVERSE GRAVITY!'); LK.effects.flashScreen(0xff00ff, 500); if (!achievements.reverseGravity) { achievements.reverseGravity = true; showAchievement('Gravity Master!', 0xff00ff); } } else if (randomEffect < 0.75) { // Score boost scoreBoostActive = true; scoreBoostTimer = 600; // 10 seconds powerUpIndicator.setText('3X SCORE!'); } else if (randomEffect < 0.9) { // Auto aim autoAimActive = true; autoAimTimer = 300; // 5 seconds powerUpIndicator.setText('AUTO AIM!'); } else { // Random weapon power-up var weapons = ['fireball', 'giant', 'split', 'laser', 'lightning']; var randomWeapon = weapons[Math.floor(Math.random() * weapons.length)]; switch (randomWeapon) { case 'fireball': fireballActive = true; break; case 'giant': giantBallActive = true; break; case 'split': splitBallActive = true; break; case 'laser': laserActive = true; break; case 'lightning': lightningActive = true; break; } powerUpIndicator.setText(randomWeapon.toUpperCase() + '!'); } // Unlock weapons based on score // Check achievements if (combo >= 10 && !achievements.combo10) { achievements.combo10 = true; showAchievement('Combo Master!', 0xFF00FF); } if (LK.getScore() >= 1000 && !achievements.score1000) { achievements.score1000 = true; showAchievement('Score Champion!', 0xFFD700); } if (weaponUnlocks.piercing && weaponUnlocks.explosive && weaponUnlocks.rapid && !achievements.allWeapons) { achievements.allWeapons = true; showAchievement('Weapon Master!', 0x00FF00); } // Save high score if (!savedData.highScore || LK.getScore() > savedData.highScore) { savedData.highScore = LK.getScore(); // Flatten achievements into savedData directly savedData.firstWin = achievements.firstWin; savedData.combo10 = achievements.combo10; savedData.score1000 = achievements.score1000; savedData.allWeapons = achievements.allWeapons; storage['99balls_save'] = savedData; } if (LK.getScore() >= 100 && !weaponUnlocks.piercing) { weaponUnlocks.piercing = true; var unlockText = new Text2('Piercing Weapon Unlocked!', { size: 80, fill: 0xFF00FF }); unlockText.anchor.set(0.5, 0.5); unlockText.alpha = 0; LK.gui.center.addChild(unlockText); tween(unlockText, { alpha: 1, y: -100 }, { duration: 500, onFinish: function onFinish() { tween(unlockText, { alpha: 0 }, { duration: 1000, delay: 1000, onFinish: function onFinish() { unlockText.destroy(); } }); } }); } if (LK.getScore() >= 300 && !weaponUnlocks.explosive) { weaponUnlocks.explosive = true; var unlockText = new Text2('Explosive Weapon Unlocked!', { size: 80, fill: 0xFF4444 }); unlockText.anchor.set(0.5, 0.5); unlockText.alpha = 0; LK.gui.center.addChild(unlockText); tween(unlockText, { alpha: 1, y: -100 }, { duration: 500, onFinish: function onFinish() { tween(unlockText, { alpha: 0 }, { duration: 1000, delay: 1000, onFinish: function onFinish() { unlockText.destroy(); } }); } }); } if (LK.getScore() >= 500 && !weaponUnlocks.rapid) { weaponUnlocks.rapid = true; var unlockText = new Text2('Rapid Fire Unlocked!', { size: 80, fill: 0x44FF44 }); unlockText.anchor.set(0.5, 0.5); unlockText.alpha = 0; LK.gui.center.addChild(unlockText); tween(unlockText, { alpha: 1, y: -100 }, { duration: 500, onFinish: function onFinish() { tween(unlockText, { alpha: 0 }, { duration: 1000, delay: 1000, onFinish: function onFinish() { unlockText.destroy(); } }); } }); } LK.setScore(LK.getScore() + Math.floor(10 * scoreMultiplier)); scoreText.setText('Score: ' + LK.getScore()); createExplosion(star.x, star.y, 0xffd93d, 15); star.destroy(); stars.splice(j, 1); achievementProgress.starCollector++; if (achievementProgress.starCollector >= 50) checkAchievement('starCollector'); } } } // Check if all projectiles are gone if (projectiles.length === 0 && !canShoot) { canShoot = true; moveRow(); if (balls.length === 0) { stage++; stageText.setText('Stage ' + stage); ballSpeed += 0.1; // Bonus for clearing stage var bonus = stage * 50; LK.setScore(LK.getScore() + bonus); scoreText.setText('Score: ' + LK.getScore()); var bonusText = new Text2('Stage Clear! +' + bonus, { size: 100, fill: 0x00FF00 }); bonusText.anchor.set(0.5, 0.5); bonusText.alpha = 0; LK.gui.center.addChild(bonusText); // Check if this is first stage clear if (stage === 2 && !achievements.firstWin) { achievements.firstWin = true; showAchievement('First Victory!', 0x00FF00); } // Perfect stage bonus if (projectileCount === 1) { perfectStageBonus = true; var perfectBonus = stage * 100; LK.setScore(LK.getScore() + perfectBonus); showAchievement('Perfect Stage! +' + perfectBonus, 0xFFD700); if (!achievements.perfectStage) { achievements.perfectStage = true; showAchievement('Perfectionist!', 0xFFD700); } } tween(bonusText, { alpha: 1, y: -200 }, { duration: 500, onFinish: function onFinish() { tween(bonusText, { alpha: 0 }, { duration: 500, delay: 500, onFinish: function onFinish() { bonusText.destroy(); } }); } }); } } // Check time-based achievements if (LK.ticks % 60 === 0) { var seconds = Math.floor(LK.ticks / 60); if (seconds >= 600 && !achievements.survivor) { checkAchievement('survivor'); } } // Check stage achievements if (stage >= 10) checkAchievement('stage10'); if (stage >= 25) checkAchievement('stage25'); if (stage >= 50) checkAchievement('stage50'); // Check score achievements if (LK.getScore() >= 5000) checkAchievement('score5000'); if (LK.getScore() >= 10000) checkAchievement('score10000'); if (LK.getScore() >= 50000) checkAchievement('score50000'); // Check combo achievements if (combo >= 20) checkAchievement('combo20'); if (combo >= 50) checkAchievement('combo50'); // Check projectile achievements if (projectileCount >= 10) checkAchievement('richPlayer'); if (achievementProgress.projectiles50 >= 50) checkAchievement('projectiles50'); if (achievementProgress.projectiles100 >= 100) checkAchievement('projectiles100'); // Special win condition - collect all power-up types in one game var allPowerUpsCollected = fireballActive || giantBallActive || splitBallActive || laserActive || lightningActive || multiballActive || doubleShotActive || slowMotionActive || magnetActive || shieldActive || freezeActive; if (allPowerUpsCollected && powerupsCollected >= 20 && !achievements.versatile) { checkAchievement('versatile'); // Epic win effect var epicWin = new Text2('POWER MASTER!', { size: 120, fill: 0xff00ff }); epicWin.anchor.set(0.5, 0.5); epicWin.alpha = 0; LK.gui.center.addChild(epicWin); tween(epicWin, { alpha: 1, rotation: Math.PI * 2 }, { duration: 1000, onFinish: function onFinish() { tween(epicWin, { alpha: 0, scaleX: 3, scaleY: 3 }, { duration: 1000, onFinish: function onFinish() { epicWin.destroy(); } }); } }); } // Check power-up master achievement if (powerupsCollected >= 100) checkAchievement('powerupMaster'); // Special effects for high combos if (combo > 30 && combo % 10 === 0) { var rainbowFlash = game.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.1, scaleY: 0.1, alpha: 0.5, tint: Math.random() * 0xffffff | 0 }); tween(rainbowFlash, { scaleX: 30, scaleY: 30, alpha: 0, rotation: Math.PI * 4 }, { duration: 1000, onFinish: function onFinish() { rainbowFlash.destroy(); } }); } // Check for danger zone - activate bullet time var dangerBalls = 0; for (var i = 0; i < balls.length; i++) { if (balls[i].y > 2000 && balls[i].y < 2400) { dangerBalls++; } } if (dangerBalls >= 3 && !bulletTimeActive && !shieldActive) { bulletTimeActive = true; bulletTimeTimer = 180; // 3 seconds gameSpeed = 0.1; // Bullet time effect var bulletTimeEffect = new Text2('BULLET TIME!', { size: 80, fill: 0xff0000 }); bulletTimeEffect.anchor.set(0.5, 0.5); bulletTimeEffect.alpha = 0; LK.gui.center.addChild(bulletTimeEffect); tween(bulletTimeEffect, { alpha: 1, y: -100 }, { duration: 300, onFinish: function onFinish() { tween(bulletTimeEffect, { alpha: 0 }, { duration: 500, delay: 1000, onFinish: function onFinish() { bulletTimeEffect.destroy(); } }); } }); LK.effects.flashScreen(0xff0000, 300); achievementProgress.dodgeMaster++; if (achievementProgress.dodgeMaster >= 10) checkAchievement('dodgeMaster'); } // Check game over if (gameActive) { for (var i = 0; i < balls.length; i++) { if (balls[i].y > 2400) { if (shieldActive) { // Shield protects from game over once shieldActive = false; shieldTimer = 0; tween(shieldBg, { alpha: 0 }, { duration: 300 }); balls[i].destroy(); balls.splice(i, 1); var shieldSaveText = new Text2('SHIELD SAVED YOU!', { size: 80, fill: 0x3498db }); shieldSaveText.anchor.set(0.5, 0.5); shieldSaveText.alpha = 0; LK.gui.center.addChild(shieldSaveText); tween(shieldSaveText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { tween(shieldSaveText, { alpha: 0 }, { duration: 500, delay: 1000, onFinish: function onFinish() { shieldSaveText.destroy(); } }); } }); LK.effects.flashScreen(0x3498db, 500); continue; } gameActive = false; // Save progress before game over if (!savedData.highScore || LK.getScore() > savedData.highScore) { savedData.highScore = LK.getScore(); // Flatten achievements into savedData directly savedData.firstWin = achievements.firstWin; savedData.combo10 = achievements.combo10; savedData.score1000 = achievements.score1000; savedData.allWeapons = achievements.allWeapons; storage['99balls_save'] = savedData; } LK.showGameOver(); break; } } } }; // Add achievements button var achievementsButton = game.addChild(new Container()); var achievementsBg = achievementsButton.attachAsset('addBallButton', { anchorX: 0.5, anchorY: 0.5, tint: 0xFFD700, scaleX: 1.2, scaleY: 1.2 }); var achievementsButtonText = new Text2('Achievements', { size: 25, fill: 0x000000 }); achievementsButtonText.anchor.set(0.5, 0.5); achievementsButton.addChild(achievementsButtonText); achievementsButton.x = 1924; achievementsButton.y = 200; // Add glow effect to achievements button achievementsButton.update = function () { achievementsBg.alpha = 0.8 + Math.sin(LK.ticks * 0.05) * 0.2; }; // Achievement panel var achievementPanel = new Container(); var panelBg = achievementPanel.attachAsset('achievementPanelBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95 }); achievementPanel.visible = false; LK.gui.center.addChild(achievementPanel); var achievementTitle = new Text2('ACHIEVEMENTS', { size: 60, fill: 0xFFD700 }); achievementTitle.anchor.set(0.5, 0.5); achievementTitle.y = -600; achievementPanel.addChild(achievementTitle); var closeButton = new Container(); var closeBg = closeButton.attachAsset('addBallButton', { anchorX: 0.5, anchorY: 0.5, tint: 0xff4444 }); var closeText = new Text2('X', { size: 40, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.x = 450; closeButton.y = -600; achievementPanel.addChild(closeButton); closeButton.down = function () { achievementPanel.visible = false; gameActive = true; }; achievementsButton.down = function () { achievementPanel.visible = true; gameActive = false; updateAchievementDisplay(); }; // Add weapon switch button var weaponButton = game.addChild(new Container()); var buttonBg = weaponButton.attachAsset('addBallButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2('Switch', { size: 30, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); weaponButton.addChild(buttonText); weaponButton.x = 1024; weaponButton.y = 2400; weaponButton.down = function () { var weapons = ['normal']; if (weaponUnlocks.piercing) weapons.push('piercing'); if (weaponUnlocks.explosive) weapons.push('explosive'); if (weaponUnlocks.rapid) weapons.push('rapid'); var currentIndex = weapons.indexOf(currentWeapon); currentWeapon = weapons[(currentIndex + 1) % weapons.length]; switch (currentWeapon) { case 'normal': weaponText.setText('Normal'); weaponText.tint = 0xFFFFFF; break; case 'piercing': weaponText.setText('Piercing'); weaponText.tint = 0xFF00FF; break; case 'explosive': weaponText.setText('Explosive'); weaponText.tint = 0xFF4444; break; case 'rapid': weaponText.setText('Rapid Fire'); weaponText.tint = 0x44FF44; break; } tween(weaponButton, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(weaponButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); }; initializeLevel();
===================================================================
--- original.js
+++ change.js
@@ -338,8 +338,78 @@
powerupGraphics.scale.set(scale);
};
return self;
});
+var GravityWellBall = Container.expand(function () {
+ var self = Container.call(this);
+ var ballGraphics = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x4a0080,
+ scaleX: 1.8,
+ scaleY: 1.8
+ });
+ self.numberText = new Text2('GRAV', {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ self.numberText.anchor.set(0.5, 0.5);
+ self.addChild(self.numberText);
+ self.hits = 30;
+ self.radius = 70;
+ self.gravityRadius = 300;
+ self.isGravityWell = true;
+ self.pullTimer = 0;
+ self.takeDamage = function () {
+ self.hits--;
+ if (self.hits <= 0) {
+ return true;
+ }
+ self.numberText.setText(self.hits.toString());
+ // Pulse effect
+ tween(ballGraphics, {
+ scaleX: 1.6,
+ scaleY: 1.6
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(ballGraphics, {
+ scaleX: 1.8,
+ scaleY: 1.8
+ }, {
+ duration: 100
+ });
+ }
+ });
+ return false;
+ };
+ self.update = function () {
+ self.pullTimer += 0.05;
+ ballGraphics.rotation = self.pullTimer;
+ // Gravity field visual
+ if (Math.random() < 0.1) {
+ var ring = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 3,
+ scaleY: 3,
+ tint: 0x4a0080,
+ alpha: 0.2
+ });
+ tween(ring, {
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0.8
+ }, {
+ duration: 1000,
+ onFinish: function onFinish() {
+ ring.destroy();
+ }
+ });
+ }
+ };
+ return self;
+});
var LaserPowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
@@ -629,8 +699,54 @@
ballGraphics.rotation += 0.05;
};
return self;
});
+var RainbowLaserPowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ var powerupGraphics = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0xff00ff,
+ scaleX: 1.5,
+ scaleY: 1.5
+ });
+ self.radius = 35;
+ self.rainbowTimer = 0;
+ self.update = function () {
+ self.rainbowTimer += 0.2;
+ var hue = (Math.sin(self.rainbowTimer) + 1) * 0.5;
+ var r = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128);
+ var g = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128);
+ var b = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128);
+ powerupGraphics.tint = r << 16 | g << 8 | b;
+ powerupGraphics.rotation += 0.05;
+ // Rainbow particles
+ if (Math.random() < 0.3) {
+ var particle = self.attachAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.2,
+ scaleY: 0.2,
+ tint: powerupGraphics.tint,
+ alpha: 0.8
+ });
+ particle.x = (Math.random() - 0.5) * 30;
+ particle.y = (Math.random() - 0.5) * 30;
+ tween(particle, {
+ y: particle.y - 30,
+ alpha: 0,
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 800,
+ onFinish: function onFinish() {
+ particle.destroy();
+ }
+ });
+ }
+ };
+ return self;
+});
var ShieldPowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
@@ -845,8 +961,48 @@
}
};
return self;
});
+var TimeWarpPowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ var powerupGraphics = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x00ff88,
+ scaleX: 1.4,
+ scaleY: 1.4
+ });
+ self.radius = 35;
+ self.warpTimer = 0;
+ self.update = function () {
+ self.warpTimer += 0.25;
+ powerupGraphics.alpha = 0.4 + Math.sin(self.warpTimer) * 0.6;
+ powerupGraphics.scale.set(1.4 + Math.sin(self.warpTimer * 2) * 0.3);
+ // Time distortion effect
+ if (Math.random() < 0.2) {
+ var distortion = self.attachAsset('aimline', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: Math.random() * 2 + 0.5,
+ scaleY: 0.1,
+ tint: 0x00ff88,
+ alpha: 0.6,
+ rotation: Math.random() * Math.PI * 2
+ });
+ tween(distortion, {
+ scaleY: 2,
+ alpha: 0,
+ rotation: distortion.rotation + Math.PI
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ distortion.destroy();
+ }
+ });
+ }
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -1104,8 +1260,18 @@
persistent: 0,
flawless: 0,
closeCall: 0
};
+var rainbowLaserPowerups = [];
+var rainbowLaserActive = false;
+var gravityWellBalls = [];
+var timeWarpPowerups = [];
+var timeWarpActive = false;
+var timeWarpTimer = 0;
+var superComboActive = false;
+var superComboTimer = 0;
+var bulletTimeActive = false;
+var bulletTimeTimer = 0;
// Load saved data
var savedData = storage['99balls_save'] || {};
if (savedData.highScore) {
var highScoreText = new Text2('Best: ' + savedData.highScore, {
@@ -1161,16 +1327,8 @@
doubleShotIndicator.anchor.set(0, 0);
doubleShotIndicator.x = 20;
doubleShotIndicator.y = 260;
LK.gui.topLeft.addChild(doubleShotIndicator);
-var manualShotIndicator = new Text2('', {
- size: 35,
- fill: 0x8888ff
-});
-manualShotIndicator.anchor.set(0, 0);
-manualShotIndicator.x = 20;
-manualShotIndicator.y = 320;
-LK.gui.topLeft.addChild(manualShotIndicator);
var shieldIndicator = new Container();
var shieldBg = shieldIndicator.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
@@ -1326,8 +1484,29 @@
magnetBall.x = ball.x;
magnetBall.y = ball.y;
magnetBalls.push(magnetBall);
game.addChild(magnetBall);
+ } else if (Math.random() < 0.02 && stage > 8) {
+ // Spawn rainbow laser power-up
+ var rainbowLaserPowerup = new RainbowLaserPowerUp();
+ rainbowLaserPowerup.x = ball.x;
+ rainbowLaserPowerup.y = ball.y;
+ rainbowLaserPowerups.push(rainbowLaserPowerup);
+ game.addChild(rainbowLaserPowerup);
+ } else if (Math.random() < 0.02 && stage > 10) {
+ // Spawn gravity well ball
+ var gravityWellBall = new GravityWellBall();
+ gravityWellBall.x = ball.x;
+ gravityWellBall.y = ball.y;
+ gravityWellBalls.push(gravityWellBall);
+ game.addChild(gravityWellBall);
+ } else if (Math.random() < 0.02 && stage > 9) {
+ // Spawn time warp power-up
+ var timeWarpPowerup = new TimeWarpPowerUp();
+ timeWarpPowerup.x = ball.x;
+ timeWarpPowerup.y = ball.y;
+ timeWarpPowerups.push(timeWarpPowerup);
+ game.addChild(timeWarpPowerup);
}
}
// Spawn boss every 5 stages
bossSpawnCounter++;
@@ -1365,41 +1544,8 @@
} else if (stage % 5 !== 0) {
bossSpawnCounter = 0;
}
}
-function fireManualProjectile(angle) {
- var projectile = new SpecialProjectile();
- projectile.x = cannon.x;
- projectile.y = cannon.y - 40;
- projectile.setType(currentWeapon);
- projectile.velocityX = Math.cos(angle) * projectile.speed;
- projectile.velocityY = Math.sin(angle) * projectile.speed;
- // Mark as manual shot for reduced damage
- projectile.isManualShot = true;
- projectiles.push(projectile);
- game.addChild(projectile);
- LK.getSound('shoot').play();
- // Visual effect for manual shot
- var manualFlash = cannon.attachAsset('ball', {
- anchorX: 0.5,
- anchorY: 0.5,
- y: -40,
- scaleX: 0.3,
- scaleY: 0.3,
- alpha: 0.6,
- tint: 0x8888ff
- });
- tween(manualFlash, {
- scaleX: 1.5,
- scaleY: 1.5,
- alpha: 0
- }, {
- duration: 200,
- onFinish: function onFinish() {
- manualFlash.destroy();
- }
- });
-}
function fireProjectiles(angle) {
var shotCount = projectileCount;
var delay = 100;
var weaponType = currentWeapon;
@@ -1411,9 +1557,35 @@
if (doubleShotActive) {
shotCount *= 2;
}
// Check for active power-ups
- if (fireballActive) {
+ if (rainbowLaserActive) {
+ weaponType = 'laser';
+ rainbowLaserActive = false;
+ shotCount = 7; // Fire 7 rainbow lasers
+ // Rainbow laser special effect
+ for (var rl = 0; rl < 7; rl++) {
+ (function (index) {
+ LK.setTimeout(function () {
+ var laserProjectile = new SpecialProjectile();
+ laserProjectile.x = cannon.x + (index - 3) * 50;
+ laserProjectile.y = cannon.y - 40;
+ laserProjectile.setType('laser');
+ laserProjectile.velocityX = (index - 3) * 2;
+ laserProjectile.velocityY = -laserProjectile.speed;
+ // Rainbow tint
+ var hue = index / 7;
+ var r = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128);
+ var g = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128);
+ var b = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128);
+ laserProjectile.tint = r << 16 | g << 8 | b;
+ projectiles.push(laserProjectile);
+ game.addChild(laserProjectile);
+ }, index * 50);
+ })(rl);
+ }
+ return;
+ } else if (fireballActive) {
weaponType = 'fireball';
fireballActive = false;
} else if (giantBallActive) {
weaponType = 'giant';
@@ -1732,8 +1904,39 @@
duration: 200
});
}
});
+ // Super combo activation
+ if (combo >= 25 && !superComboActive) {
+ superComboActive = true;
+ superComboTimer = 300; // 5 seconds
+ criticalHitChance = 0.5; // 50% critical chance
+ // Super combo activation effect
+ var superComboEffect = new Text2('SUPER COMBO MODE!', {
+ size: 100,
+ fill: 0xff00ff
+ });
+ superComboEffect.anchor.set(0.5, 0.5);
+ superComboEffect.alpha = 0;
+ LK.gui.center.addChild(superComboEffect);
+ tween(superComboEffect, {
+ alpha: 1,
+ rotation: Math.PI * 2
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ tween(superComboEffect, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ delay: 1000,
+ onFinish: function onFinish() {
+ superComboEffect.destroy();
+ }
+ });
+ }
+ });
+ }
// Combo milestone effects
if (combo === 10 || combo === 20 || combo === 30 || combo === 50 || combo === 100) {
var message = combo === 100 ? 'LEGENDARY!' : combo === 50 ? 'UNSTOPPABLE!' : 'AMAZING!';
var comboFlash = new Text2(message, {
@@ -1804,28 +2007,17 @@
aimLine.rotation = angle + Math.PI / 2;
}
};
game.up = function (x, y, obj) {
- if (!gameActive) return;
- if (isAiming) {
- // Initial shooting
- isAiming = false;
- aimLine.visible = false;
- canShoot = false;
- var dx = x - cannon.x;
- var dy = y - cannon.y;
- var angle = Math.atan2(dy, dx);
- if (angle > -Math.PI && angle < 0) {
- fireProjectiles(angle);
- }
- } else if (!canShoot && projectiles.length > 0) {
- // Manual shooting after initial projectiles
- var dx = x - cannon.x;
- var dy = y - cannon.y;
- var angle = Math.atan2(dy, dx);
- if (angle > -Math.PI && angle < 0) {
- fireManualProjectile(angle);
- }
+ if (!isAiming || !gameActive) return;
+ isAiming = false;
+ aimLine.visible = false;
+ canShoot = false;
+ var dx = x - cannon.x;
+ var dy = y - cannon.y;
+ var angle = Math.atan2(dy, dx);
+ if (angle > -Math.PI && angle < 0) {
+ fireProjectiles(angle);
}
};
game.update = function () {
if (!gameActive) return;
@@ -2001,8 +2193,52 @@
// Update teleport powerups
for (var i = 0; i < teleportPowerups.length; i++) {
teleportPowerups[i].update();
}
+ // Update rainbow laser powerups
+ for (var i = 0; i < rainbowLaserPowerups.length; i++) {
+ rainbowLaserPowerups[i].update();
+ }
+ // Update gravity well balls
+ for (var i = 0; i < gravityWellBalls.length; i++) {
+ if (gravityWellBalls[i].update) {
+ gravityWellBalls[i].update();
+ }
+ }
+ // Update time warp powerups
+ for (var i = 0; i < timeWarpPowerups.length; i++) {
+ timeWarpPowerups[i].update();
+ }
+ // Update time warp effect
+ if (timeWarpActive) {
+ timeWarpTimer--;
+ // Alternate between fast and slow
+ if (Math.floor(timeWarpTimer / 60) % 2 === 0) {
+ gameSpeed = 0.2;
+ } else {
+ gameSpeed = 2;
+ }
+ if (timeWarpTimer <= 0) {
+ timeWarpActive = false;
+ gameSpeed = 1;
+ powerUpIndicator.setText('');
+ }
+ }
+ // Update super combo
+ if (superComboActive) {
+ superComboTimer--;
+ if (superComboTimer <= 0) {
+ superComboActive = false;
+ criticalHitChance = 0.1;
+ }
+ }
+ // Update bullet time
+ if (bulletTimeActive) {
+ bulletTimeTimer--;
+ if (bulletTimeTimer <= 0) {
+ bulletTimeActive = false;
+ }
+ }
// Track time played
timePlayed++;
if (timePlayed % 3600 === 0) {
// Every minute
@@ -2080,8 +2316,17 @@
}
for (var i = 0; i < teleportPowerups.length; i++) {
teleportPowerups[i].y += ballSpeed * gameSpeed;
}
+ for (var i = 0; i < rainbowLaserPowerups.length; i++) {
+ rainbowLaserPowerups[i].y += ballSpeed * gameSpeed;
+ }
+ for (var i = 0; i < gravityWellBalls.length; i++) {
+ gravityWellBalls[i].y += ballSpeed * gameSpeed * 0.7; // Gravity wells move slower
+ }
+ for (var i = 0; i < timeWarpPowerups.length; i++) {
+ timeWarpPowerups[i].y += ballSpeed * gameSpeed;
+ }
// Update rainbow balls
for (var i = 0; i < rainbowBalls.length; i++) {
rainbowBalls[i].y += ballSpeed * gameSpeed;
if (rainbowBalls[i].update) {
@@ -2155,8 +2400,31 @@
projectile.velocityY = projectile.velocityY / speed * projectile.speed * 2;
}
}
}
+ // Apply gravity well effects
+ for (var g = 0; g < gravityWellBalls.length; g++) {
+ var gravityWell = gravityWellBalls[g];
+ var dx = gravityWell.x - projectile.x;
+ var dy = gravityWell.y - projectile.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < gravityWell.gravityRadius && dist > gravityWell.radius) {
+ // Pull projectile towards gravity well
+ var force = (1 - dist / gravityWell.gravityRadius) * 5;
+ projectile.velocityX += dx / dist * force;
+ projectile.velocityY += dy / dist * force;
+ // Add swirl effect
+ var angle = Math.atan2(dy, dx) + Math.PI / 2;
+ projectile.velocityX += Math.cos(angle) * force * 0.3;
+ projectile.velocityY += Math.sin(angle) * force * 0.3;
+ // Normalize speed
+ var speed = Math.sqrt(projectile.velocityX * projectile.velocityX + projectile.velocityY * projectile.velocityY);
+ if (speed > projectile.speed * 3) {
+ projectile.velocityX = projectile.velocityX / speed * projectile.speed * 3;
+ projectile.velocityY = projectile.velocityY / speed * projectile.speed * 3;
+ }
+ }
+ }
var hitBall = false;
// Check boss collisions first
for (var j = bossBalls.length - 1; j >= 0; j--) {
var boss = bossBalls[j];
@@ -2165,11 +2433,9 @@
updateCombo();
hitBall = true;
// Critical hit chance
var isCritical = Math.random() < criticalHitChance;
- var baseDamage = isCritical ? 5 : 1;
- // Reduce damage by 50% for manual shots
- var damage = projectile.isManualShot ? baseDamage * 0.5 : baseDamage;
+ var damage = isCritical ? 5 : 1;
if (isCritical) {
var critText = new Text2('CRITICAL!', {
size: 60,
fill: 0xffff00
@@ -2332,8 +2598,53 @@
break;
}
}
}
+ // Check gravity well collisions
+ for (var j = gravityWellBalls.length - 1; j >= 0; j--) {
+ var gravityWell = gravityWellBalls[j];
+ if (checkCollision(projectile, gravityWell, projectile.radius, gravityWell.radius)) {
+ LK.getSound('hit').play();
+ updateCombo();
+ hitBall = true;
+ // Gravity wells suck in the projectile
+ if (gravityWell.takeDamage()) {
+ LK.getSound('destroy').play();
+ LK.setScore(LK.getScore() + 300 * scoreMultiplier * scoreBoostMultiplier);
+ // Create implosion effect
+ for (var p = 0; p < 30; p++) {
+ var particle = new Particle();
+ particle.x = gravityWell.x + (Math.random() - 0.5) * 200;
+ particle.y = gravityWell.y + (Math.random() - 0.5) * 200;
+ var dx = gravityWell.x - particle.x;
+ var dy = gravityWell.y - particle.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ particle.velocityX = dx / dist * 10;
+ particle.velocityY = dy / dist * 10;
+ particle.tint = 0x4a0080;
+ particles.push(particle);
+ game.addChild(particle);
+ }
+ // Pull nearby balls
+ for (var k = 0; k < balls.length; k++) {
+ var nearbyBall = balls[k];
+ if (checkCollision(gravityWell, nearbyBall, 200, nearbyBall.radius)) {
+ var dx = gravityWell.x - nearbyBall.x;
+ var dy = gravityWell.y - nearbyBall.y;
+ nearbyBall.x += dx * 0.3;
+ nearbyBall.y += dy * 0.3;
+ }
+ }
+ gravityWell.destroy();
+ gravityWellBalls.splice(j, 1);
+ ballsDestroyed++;
+ }
+ projectile.destroy();
+ projectiles.splice(i, 1);
+ i--;
+ break;
+ }
+ }
// Check mirror ball collisions
for (var j = mirrorBalls.length - 1; j >= 0; j--) {
var mirrorBall = mirrorBalls[j];
if (checkCollision(projectile, mirrorBall, projectile.radius, mirrorBall.radius)) {
@@ -2445,23 +2756,9 @@
}
}
}
}
- // Apply damage - manual shots do 50% less damage
- var damageDealt = projectile.isManualShot ? 0.5 : 1;
- var destroyed = false;
- if (damageDealt < 1) {
- // For partial damage, we need to handle it differently
- ball.hits -= damageDealt;
- if (ball.hits <= 0) {
- destroyed = true;
- } else {
- ball.numberText.setText(Math.ceil(ball.hits).toString());
- }
- } else {
- destroyed = ball.takeDamage();
- }
- if (destroyed) {
+ if (ball.takeDamage()) {
LK.getSound('destroy').play();
consecutiveHits++;
if (consecutiveHits >= 3) {
chainReactionActive = true;
@@ -2951,8 +3248,71 @@
teleportPowerups.splice(j, 1);
powerupsCollected++;
}
}
+ // Check rainbow laser power-up collisions
+ for (var j = rainbowLaserPowerups.length - 1; j >= 0; j--) {
+ var rainbowLaserPowerup = rainbowLaserPowerups[j];
+ if (checkCollision(projectile, rainbowLaserPowerup, projectile.radius, rainbowLaserPowerup.radius)) {
+ LK.getSound('collect').play();
+ rainbowLaserActive = true;
+ powerUpIndicator.setText('RAINBOW LASER!');
+ // Epic rainbow explosion
+ for (var r = 0; r < 50; r++) {
+ var particle = new Particle();
+ particle.x = rainbowLaserPowerup.x;
+ particle.y = rainbowLaserPowerup.y;
+ var angle = r / 50 * Math.PI * 2;
+ particle.velocityX = Math.cos(angle) * 15;
+ particle.velocityY = Math.sin(angle) * 15;
+ var hue = r / 50;
+ var red = Math.floor(Math.sin(hue * Math.PI * 2) * 127 + 128);
+ var green = Math.floor(Math.sin((hue + 0.33) * Math.PI * 2) * 127 + 128);
+ var blue = Math.floor(Math.sin((hue + 0.67) * Math.PI * 2) * 127 + 128);
+ particle.tint = red << 16 | green << 8 | blue;
+ particles.push(particle);
+ game.addChild(particle);
+ }
+ rainbowLaserPowerup.destroy();
+ rainbowLaserPowerups.splice(j, 1);
+ powerupsCollected++;
+ }
+ }
+ // Check time warp power-up collisions
+ for (var j = timeWarpPowerups.length - 1; j >= 0; j--) {
+ var timeWarpPowerup = timeWarpPowerups[j];
+ if (checkCollision(projectile, timeWarpPowerup, projectile.radius, timeWarpPowerup.radius)) {
+ LK.getSound('collect').play();
+ timeWarpActive = true;
+ timeWarpTimer = 600; // 10 seconds of time warping
+ powerUpIndicator.setText('TIME WARP!');
+ // Time distortion visual
+ var warpEffect = game.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: timeWarpPowerup.x,
+ y: timeWarpPowerup.y,
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0.8,
+ tint: 0x00ff88
+ });
+ tween(warpEffect, {
+ scaleX: 20,
+ scaleY: 20,
+ alpha: 0,
+ rotation: Math.PI * 4
+ }, {
+ duration: 1000,
+ onFinish: function onFinish() {
+ warpEffect.destroy();
+ }
+ });
+ timeWarpPowerup.destroy();
+ timeWarpPowerups.splice(j, 1);
+ powerupsCollected++;
+ }
+ }
// Check star collisions
for (var j = stars.length - 1; j >= 0; j--) {
var star = stars[j];
if (checkCollision(projectile, star, projectile.radius, star.radius)) {
@@ -3132,18 +3492,11 @@
if (achievementProgress.starCollector >= 50) checkAchievement('starCollector');
}
}
}
- // Update manual shot indicator
- if (!canShoot && projectiles.length > 0) {
- manualShotIndicator.setText('TAP TO SHOOT (50% DMG)');
- } else {
- manualShotIndicator.setText('');
- }
// Check if all projectiles are gone
if (projectiles.length === 0 && !canShoot) {
canShoot = true;
- manualShotIndicator.setText('');
moveRow();
if (balls.length === 0) {
stage++;
stageText.setText('Stage ' + stage);
@@ -3272,8 +3625,48 @@
rainbowFlash.destroy();
}
});
}
+ // Check for danger zone - activate bullet time
+ var dangerBalls = 0;
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].y > 2000 && balls[i].y < 2400) {
+ dangerBalls++;
+ }
+ }
+ if (dangerBalls >= 3 && !bulletTimeActive && !shieldActive) {
+ bulletTimeActive = true;
+ bulletTimeTimer = 180; // 3 seconds
+ gameSpeed = 0.1;
+ // Bullet time effect
+ var bulletTimeEffect = new Text2('BULLET TIME!', {
+ size: 80,
+ fill: 0xff0000
+ });
+ bulletTimeEffect.anchor.set(0.5, 0.5);
+ bulletTimeEffect.alpha = 0;
+ LK.gui.center.addChild(bulletTimeEffect);
+ tween(bulletTimeEffect, {
+ alpha: 1,
+ y: -100
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ tween(bulletTimeEffect, {
+ alpha: 0
+ }, {
+ duration: 500,
+ delay: 1000,
+ onFinish: function onFinish() {
+ bulletTimeEffect.destroy();
+ }
+ });
+ }
+ });
+ LK.effects.flashScreen(0xff0000, 300);
+ achievementProgress.dodgeMaster++;
+ if (achievementProgress.dodgeMaster >= 10) checkAchievement('dodgeMaster');
+ }
// Check game over
if (gameActive) {
for (var i = 0; i < balls.length; i++) {
if (balls[i].y > 2400) {
Renkli yuvarlak Balon, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. 2d. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows
tek renk top, üstten görünüm, Gerçekçi, yazısız.. In-Game asset. High contrast. No shadows