User prompt
Zemini çimen yap
User prompt
Addsilingshoutbase
User prompt
Please fix the bug: 'Uncaught TypeError: LK.effects.shakeScreen is not a function' in or related to this line: 'LK.effects.shakeScreen(distance / 10, 200);' Line Number: 499
User prompt
Sapanı daha gerçekçi yap efekt animasyon ekle. Top giderken de animasyonlu gitsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Top bitince yeniden başlat
User prompt
Tamam yap
User prompt
Topa vurdugumda ses çalsın. Birde sapan asset yükledim bunu playerin eline ekle
User prompt
Player hize düzelt büyüt
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(self, 0.1, {' Line Number: 44 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Player yok
Code edit (1 edits merged)
Please save this source code
User prompt
Slingshot Strike
Initial prompt
Angry birds tarzı
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AchievementSystem = Container.expand(function () { var self = Container.call(this); self.achievements = { perfectShot: false, oneShot: false, destructionMaster: false, sharpshooter: false }; self.loadAchievements = function () { var saved = storage.achievements; if (saved) { self.achievements = saved; } }; self.saveAchievements = function () { storage.achievements = self.achievements; }; self.checkAchievement = function (type, value) { switch (type) { case 'perfectShot': if (value === 1 && !self.achievements.perfectShot) { self.achievements.perfectShot = true; self.showAchievement('Mükemmel Atış!', 'Tek atışta tüm hedefleri yok et'); } break; case 'oneShot': if (value >= 5 && !self.achievements.oneShot) { self.achievements.oneShot = true; self.showAchievement('Tek Atış Ustası!', 'Tek atışta 5 blok yok et'); } break; case 'destructionMaster': if (value >= 100 && !self.achievements.destructionMaster) { self.achievements.destructionMaster = true; self.showAchievement('Yıkım Ustası!', '100 blok yok et'); } break; case 'sharpshooter': if (value >= 10 && !self.achievements.sharpshooter) { self.achievements.sharpshooter = true; self.showAchievement('Keskin Nişancı!', '10 seviye tamamla'); } break; } self.saveAchievements(); }; self.showAchievement = function (title, description) { LK.getSound('achievement').play(); var popup = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); popup.x = 1024; popup.y = 400; popup.scaleX = 4; popup.scaleY = 2; popup.tint = 0xFFD700; popup.alpha = 0; var titleText = new Text2(title, { size: 60, fill: 0x000000 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 380; game.addChild(titleText); var descText = new Text2(description, { size: 40, fill: 0x333333 }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 420; game.addChild(descText); // Animate in tween(popup, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); tween(titleText, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); tween(descText, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); // Animate out after delay LK.setTimeout(function () { tween(popup, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { popup.destroy(); } }); tween(titleText, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { titleText.destroy(); } }); tween(descText, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { descText.destroy(); } }); }, 3000); }; return self; }); var FlyingBird = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2 + Math.random() * 3; self.direction = Math.random() > 0.5 ? 1 : -1; self.flightHeight = 300 + Math.random() * 500; self.destroyed = false; self.lastX = 0; self.lastY = 0; self.wingFlapTimer = 0; // Initialize flight animation tween(graphics, { scaleY: 0.8 }, { duration: 300, easing: tween.easeInOut, yoyo: true, repeat: -1 }); self.init = function () { // Set random starting position if (self.direction > 0) { self.x = -100; graphics.scaleX = 1; // Face right } else { self.x = 2148; graphics.scaleX = -1; // Face left } self.y = self.flightHeight; self.lastX = self.x; self.lastY = self.y; }; self.update = function () { if (self.destroyed) return; // Move horizontally self.x += self.speed * self.direction; // Add gentle vertical wave motion self.y = self.flightHeight + Math.sin(LK.ticks * 0.05) * 30; // Wing flap animation self.wingFlapTimer++; if (self.wingFlapTimer % 20 === 0) { tween(graphics, { rotation: 0.1 * self.direction }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(graphics, { rotation: 0 }, { duration: 100, easing: tween.easeIn }); } }); } // Check if bird flew off screen if (self.lastX >= -150 && self.lastX <= 2198 && (self.x < -150 || self.x > 2198)) { self.destroyed = true; } self.lastX = self.x; self.lastY = self.y; }; return self; }); var IntroScreen = Container.expand(function () { var self = Container.call(this); // Create background overlay var overlay = self.attachAsset('grass', { anchorX: 0.5, anchorY: 0.5, color: 0x000000, alpha: 0.8 }); overlay.width = 2048; overlay.height = 2732; overlay.x = 1024; overlay.y = 1366; // Title text var titleText = new Text2('SAPAN USTASI', { size: 120, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; self.addChild(titleText); // Play button var playButton = self.attachAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 }); playButton.x = 1024; playButton.y = 1200; playButton.scaleX = 2; playButton.scaleY = 1.2; playButton.tint = 0x4CAF50; var playText = new Text2('OYNA', { size: 80, fill: 0xFFFFFF }); playText.anchor.set(0.5, 0.5); playText.x = 1024; playText.y = 1200; self.addChild(playText); // Settings button var settingsButton = self.attachAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 }); settingsButton.x = 1024; settingsButton.y = 1400; settingsButton.scaleX = 2; settingsButton.scaleY = 1.2; settingsButton.tint = 0x2196F3; var settingsText = new Text2('AYARLAR', { size: 80, fill: 0xFFFFFF }); settingsText.anchor.set(0.5, 0.5); settingsText.x = 1024; settingsText.y = 1400; self.addChild(settingsText); // Level selector button var levelButton = self.attachAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 }); levelButton.x = 1024; levelButton.y = 1600; levelButton.scaleX = 2; levelButton.scaleY = 1.2; levelButton.tint = 0xFF9800; var levelText = new Text2('BÖLÜMLER', { size: 80, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0.5); levelText.x = 1024; levelText.y = 1600; self.addChild(levelText); // How to play button var howToPlayButton = self.attachAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 }); howToPlayButton.x = 1024; howToPlayButton.y = 1800; howToPlayButton.scaleX = 2; howToPlayButton.scaleY = 1.2; howToPlayButton.tint = 0x9C27B0; var howToPlayText = new Text2('NASIL OYNANIR', { size: 80, fill: 0xFFFFFF }); howToPlayText.anchor.set(0.5, 0.5); howToPlayText.x = 1024; howToPlayText.y = 1800; self.addChild(howToPlayText); // Click handlers self.down = function (x, y, obj) { // Use the x, y coordinates directly instead of trying to convert object position // Play button if (Math.abs(x - 1024) < 200 && Math.abs(y - 1200) < 60) { startGame(); } // Settings button else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1400) < 60) { showSettings(); } // Level button else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1600) < 60) { showLevelSelector(); } // How to play button else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1800) < 60) { showHowToPlay(); } }; // Animation entrance self.show = function () { self.alpha = 0; tween(self, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); tween(titleText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.elasticOut }); }; self.hide = function (callback) { tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: callback }); }; return self; }); var ParticleSystem = Container.expand(function () { var self = Container.call(this); self.particles = []; self.createExplosion = function (x, y, color, count) { // Limit particle count to prevent performance issues count = Math.min(count, 6); for (var i = 0; i < count; i++) { var particle = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); particle.x = x; particle.y = y; particle.tint = color; particle.alpha = 1; self.particles.push(particle); var angle = i / count * Math.PI * 2; var speed = 50 + Math.random() * 100; var distance = speed * (1 + Math.random()); tween(particle, { x: x + Math.cos(angle) * distance, y: y + Math.sin(angle) * distance, alpha: 0, scaleX: 0, scaleY: 0 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); var index = self.particles.indexOf(particle); if (index > -1) self.particles.splice(index, 1); } }); } }; self.createTrail = function (x, y, vx, vy) { var trail = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); trail.x = x; trail.y = y; trail.alpha = 0.6; trail.scaleX = 0.5; trail.scaleY = 0.5; self.particles.push(trail); tween(trail, { alpha: 0, scaleX: 0, scaleY: 0 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { trail.destroy(); var index = self.particles.indexOf(trail); if (index > -1) self.particles.splice(index, 1); } }); }; self.cleanup = function () { // Clean up any remaining particles for (var i = self.particles.length - 1; i >= 0; i--) { if (self.particles[i] && self.particles[i].destroyed) { self.particles.splice(i, 1); } } // Limit total particles if (self.particles.length > 50) { for (var i = 0; i < 10; i++) { if (self.particles[i]) { self.particles[i].destroy(); self.particles.splice(i, 1); } } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1 }); self.isReady = true; self.celebrate = function () { // More dramatic celebration animation tween(self, { scaleX: 1.3, scaleY: 1.3, rotation: 0.2 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1.2, scaleY: 1.2, rotation: 0 }, { duration: 200, easing: tween.bounceOut }); } }); }; self.aim = function () { // More pronounced aiming stance tween(self, { rotation: 0.15, scaleX: 1.1, scaleY: 1.1 }, { duration: 150, easing: tween.easeOut }); }; self.resetPose = function () { // Return to normal stance with bounce tween(self, { rotation: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.elasticOut }); }; return self; }); var Portal = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 }); graphics.scaleX = 4; graphics.scaleY = 4; graphics.tint = 0x9400D3; self.linkedPortal = null; self.cooldown = 0; self.isActive = true; // Add swirling animation tween(graphics, { rotation: Math.PI * 2 }, { duration: 2000, easing: tween.linear, repeat: -1 }); // Add pulsing effect tween(graphics, { scaleX: 5, scaleY: 5 }, { duration: 1000, easing: tween.easeInOut, yoyo: true, repeat: -1 }); self.teleport = function (projectile) { if (!self.isActive || self.cooldown > 0 || !self.linkedPortal || !self.linkedPortal.isActive) return false; var distance = Math.sqrt((projectile.x - self.x) * (projectile.x - self.x) + (projectile.y - self.y) * (projectile.y - self.y)); if (distance < 50) { // Teleport projectile projectile.x = self.linkedPortal.x; projectile.y = self.linkedPortal.y; // Add teleport effects LK.effects.flashScreen(0x9400D3, 200); LK.getSound('magic').play(); particleSystem.createExplosion(self.x, self.y, 0x9400D3, 8); particleSystem.createExplosion(self.linkedPortal.x, self.linkedPortal.y, 0x9400D3, 8); // Set cooldown for both portals self.cooldown = 60; self.linkedPortal.cooldown = 60; return true; } return false; }; self.update = function () { if (self.cooldown > 0) { self.cooldown--; if (self.cooldown === 0) { graphics.alpha = 1; } } else { graphics.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.type = 'normal'; self.icon = null; self.init = function (type) { self.type = type; var color = 0xFFFFFF; var text = 'N'; switch (type) { case 'explosive': color = 0xFF4444; text = 'E'; break; case 'bouncy': color = 0x44FF44; text = 'B'; break; case 'heavy': color = 0x444444; text = 'H'; break; } self.icon = self.attachAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 }); self.icon.tint = color; self.icon.scaleX = 3; self.icon.scaleY = 3; var powerText = new Text2(text, { size: 40, fill: 0xFFFFFF }); powerText.anchor.set(0.5, 0.5); self.addChild(powerText); }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.gravity = GRAVITY; self.launched = false; self.destroyed = false; self.spinSpeed = 0; self.lastX = 0; self.lastY = 0; self.type = 'normal'; self.bounceCount = 0; self.explosionRadius = 150; self.launch = function (vx, vy, projectileType) { self.type = projectileType || 'normal'; self.velocityX = vx; self.velocityY = vy; self.launched = true; // Calculate spin speed based on velocity self.spinSpeed = Math.sqrt(vx * vx + vy * vy) * 0.02; // Apply type-specific modifications switch (self.type) { case 'explosive': graphics.tint = 0xFF4444; self.gravity = GRAVITY * 0.8; break; case 'bouncy': graphics.tint = 0x44FF44; self.gravity = GRAVITY * 0.9; break; case 'heavy': graphics.tint = 0x444444; self.gravity = GRAVITY * 1.5; self.velocityX *= 1.2; self.velocityY *= 1.2; graphics.scaleX = 1.3; graphics.scaleY = 1.3; break; default: graphics.tint = 0xFFFFFF; } // Add launch scale animation tween(self, { scaleX: 1.3, scaleY: 1.3 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.easeIn }); } }); LK.getSound('launch').play(); }; self.update = function () { if (self.launched && !self.destroyed) { // Apply time slow effect var timeMultiplier = timeSlowActive ? 0.3 : 1.0; self.x += self.velocityX * timeMultiplier; self.y += self.velocityY * timeMultiplier; // Apply gravity based on current gravity state var currentGravity = gravityReversed ? -self.gravity : self.gravity; self.velocityY += currentGravity * timeMultiplier; // Add spinning animation during flight graphics.rotation += self.spinSpeed; // Add slight scale pulsing for trail effect var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY); var scaleEffect = 1 + Math.sin(LK.ticks * 0.3) * 0.1 * (speed / 20); graphics.scaleX = scaleEffect; graphics.scaleY = scaleEffect; // Check ground collision with transition detection if (self.lastY < groundY - 30 && self.y >= groundY - 30) { self.y = groundY - 30; self.velocityY = -self.velocityY * 0.3; self.velocityX *= 0.8; self.spinSpeed *= 0.8; LK.getSound('impact').play(); // Add bounce animation tween(self, { scaleX: 1.5, scaleY: 0.7 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.bounceOut }); } }); if (Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 1) { self.launched = false; self.spinSpeed = 0; } } // Update last position for transition detection self.lastX = self.x; self.lastY = self.y; // Check screen bounds if (self.x > 2200 || self.x < -100 || self.y > 2800) { self.destroyed = true; } } }; self.explode = function () { if (self.type === 'explosive') { // Create explosion effect LK.effects.flashScreen(0xFF4444, 300); LK.getSound('explosion').play(); // Damage all blocks within radius for (var i = 0; i < targetBlocks.length; i++) { var block = targetBlocks[i]; if (!block.destroyed) { var distance = Math.sqrt((block.x - self.x) * (block.x - self.x) + (block.y - self.y) * (block.y - self.y)); if (distance < self.explosionRadius) { block.takeDamage(); // Add explosion knockback tween(block, { x: block.x + (block.x - self.x) * 0.3, y: block.y + (block.y - self.y) * 0.3, rotation: Math.random() * 0.5 - 0.25 }, { duration: 200, easing: tween.easeOut }); } } } // Create particle effect with reduced count particleSystem.createExplosion(self.x, self.y, 0xFF4444, 6); } }; return self; }); var Slingshot = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('slingshot', { anchorX: 0.5, anchorY: 1 }); self.stretched = false; self.originalRotation = 0; self.stretch = function (deltaX, deltaY, distance) { // Calculate stretch angle based on pull direction var stretchAngle = Math.atan2(deltaY, deltaX) * 0.1; var stretchAmount = Math.min(distance / 150, 1) * 0.2; // Play stretch sound if (distance > 50) { LK.getSound('woosh').play(); } // Animate slingshot stretch tween(self, { rotation: stretchAngle, scaleX: 1 + stretchAmount, scaleY: 1 - stretchAmount * 0.5 }, { duration: 50, easing: tween.easeOut }); self.stretched = true; }; self.release = function () { // Dramatic release animation with bounce back tween(self, { rotation: self.originalRotation - 0.3, scaleX: 0.8, scaleY: 1.3 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { rotation: self.originalRotation, scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.elasticOut }); } }); self.stretched = false; }; self.reset = function () { // Return to normal state tween(self, { rotation: self.originalRotation, scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.easeOut }); self.stretched = false; }; return self; }); var TargetBlock = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.destroyed = false; self.magneticType = 'none'; // none, attract, repel self.magneticStrength = 200; self.takeDamage = function () { self.health--; if (self.health <= 0) { self.destroyed = true; LK.getSound('destroy').play(); LK.setScore(LK.getScore() + 100); LK.effects.flashObject(self, 0xFFFFFF, 200); } }; self.setMagnetic = function (type) { self.magneticType = type; if (type === 'attract') { graphics.tint = 0x0066FF; // Blue for attraction // Add pulsing effect tween(graphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeInOut, yoyo: true, repeat: -1 }); } else if (type === 'repel') { graphics.tint = 0xFF0000; // Red for repulsion // Add pulsing effect tween(graphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeInOut, yoyo: true, repeat: -1 }); } }; self.applyMagneticForce = function (projectile) { if (self.magneticType === 'none' || self.destroyed) return; var dx = projectile.x - self.x; var dy = projectile.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magneticStrength && distance > 0) { var force = (self.magneticStrength - distance) / self.magneticStrength * 0.5; var normalizedX = dx / distance; var normalizedY = dy / distance; if (self.magneticType === 'attract') { projectile.velocityX -= normalizedX * force; projectile.velocityY -= normalizedY * force; } else if (self.magneticType === 'repel') { projectile.velocityX += normalizedX * force; projectile.velocityY += normalizedY * force; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game constants var GRAVITY = 0.3; var MAX_DRAG_DISTANCE = 150; var VELOCITY_MULTIPLIER = 0.3; var GROUND_Y = 2550; var INITIAL_SHOTS = 6; var BLOCK_POINTS = 100; // Game state management var gameState = 'intro'; // intro, playing, paused, gameOver var introScreen = null; var particleSystem = null; var achievementSystem = null; var currentProjectileType = 'normal'; var availablePowerUps = ['normal', 'explosive', 'bouncy', 'heavy']; var powerUpIndex = 0; var totalBlocksDestroyed = 0; var levelsCompleted = 0; var windSpeed = 0; var windDirection = 1; var gravityReversed = false; var gravityTimer = 0; var maxGravityTime = 300; // 5 seconds at 60fps var portals = []; var timeSlowActive = false; var timeSlowTimer = 0; var maxTimeSlowDuration = 180; // 3 seconds var timeSlowCooldown = 0; var maxTimeSlowCooldown = 600; // 10 seconds // Game variables var slingshot; var slingshotBase; var player; var currentProjectile = null; var isAiming = false; var aimStartX = 0; var aimStartY = 0; var trajectoryDots = []; var targetBlocks = []; var projectiles = []; var flyingBirds = []; var birdSpawnTimer = 0; var shotsRemaining = INITIAL_SHOTS; var level = 1; var groundY = GROUND_Y; // UI elements var shotsText = new Text2('Atış: 6', { size: 80, fill: 0x000000 }); shotsText.anchor.set(0, 0); LK.gui.topRight.addChild(shotsText); shotsText.x = -300; shotsText.y = 100; var scoreText = new Text2('Puan: 0', { size: 80, fill: 0x000000 }); scoreText.anchor.set(0, 0); LK.gui.top.addChild(scoreText); scoreText.y = 100; // Create ability indicators var gravityButton = new Text2('⬆️', { size: 60, fill: 0x000000 }); gravityButton.anchor.set(1, 0); gravityButton.x = -50; gravityButton.y = 200; LK.gui.topRight.addChild(gravityButton); var timeButton = new Text2('⏱️', { size: 60, fill: 0x000000 }); timeButton.anchor.set(0.5, 1); timeButton.x = 0; timeButton.y = -100; LK.gui.bottom.addChild(timeButton); var typeButton = new Text2('💥', { size: 60, fill: 0x000000 }); typeButton.anchor.set(0, 0); typeButton.x = 50; typeButton.y = 200; LK.gui.topLeft.addChild(typeButton); // Create grass ground var ground = game.addChild(LK.getAsset('grass', { anchorX: 0.5, anchorY: 0.5 })); ground.x = 1024; ground.y = GROUND_Y + 100; // Position grass lower for better visual effect ground.scaleY = 1.5; // Make grass thicker // Create slingshot slingshotBase = game.addChild(LK.getAsset('slingshotBase', { anchorX: 0.5, anchorY: 1 })); slingshotBase.x = 200; slingshotBase.y = GROUND_Y; slingshot = game.addChild(new Slingshot()); slingshot.x = 200; slingshot.y = GROUND_Y; // Create player character player = game.addChild(new Player()); player.x = 80; // Position further behind slingshot player.y = GROUND_Y; player.scaleX = 1.2; // Make player more visible player.scaleY = 1.2; // Add slingshot asset to player's hand var playerSlingshot = player.addChild(LK.getAsset('Sapan', { anchorX: 0.5, anchorY: 0.8 })); playerSlingshot.x = 50; // Offset from player center to hand position playerSlingshot.y = -100; // Offset upward to hand level playerSlingshot.scaleX = 0.8; // Scale down for better proportion playerSlingshot.scaleY = 0.8; // Create trajectory dots for (var i = 0; i < 15; i++) { var dot = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); dot.visible = false; trajectoryDots.push(dot); } // Create slingshot grab area indicator var slingshotArea = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); slingshotArea.x = 200; slingshotArea.y = GROUND_Y - 100; slingshotArea.scaleX = 15; // Large enough to show grab area slingshotArea.scaleY = 15; slingshotArea.alpha = 0.2; slingshotArea.tint = 0x00FF00; // Green to indicate interaction area // Pulse animation for grab area tween(slingshotArea, { scaleX: 18, scaleY: 18, alpha: 0.1 }, { duration: 1500, easing: tween.easeInOut, yoyo: true, repeat: -1 }); // Create target structures function createLevel() { // Clear ALL existing targets (both destroyed and non-destroyed) for (var i = targetBlocks.length - 1; i >= 0; i--) { targetBlocks[i].destroy(); } targetBlocks = []; // Progressive difficulty and varied level designs var levelPattern = level % 8; // Increased variety var startX = Math.min(1400, 1700); // Ensure starting position doesn't go too far right var startY = GROUND_Y - 50; // Procedural generation for levels beyond 20 if (level > 20) { // Generate random but balanced structures - limited to 5 blocks var blockCount = 5; var maxHeight = 5 + Math.floor(level / 10); for (var i = 0; i < blockCount; i++) { var block = game.addChild(new TargetBlock()); // Constrain X position to stay within screen (100px margin on each side) block.x = Math.max(100, Math.min(1948, startX + (Math.random() - 0.5) * 400)); // Constrain Y position to stay above ground and below top of screen block.y = Math.max(200, Math.min(startY, startY - Math.random() * maxHeight * 110)); targetBlocks.push(block); } return; // Skip normal level patterns } // Add wind effect for higher levels if (level > 10) { windSpeed = (Math.random() - 0.5) * 2; windDirection = windSpeed > 0 ? 1 : -1; // Show wind indicator var windText = new Text2('Rüzgar: ' + (windSpeed > 0 ? '→' : '←'), { size: 60, fill: 0x0066CC }); windText.anchor.set(0.5, 0); windText.x = 1024; windText.y = 300; LK.gui.top.addChild(windText); LK.setTimeout(function () { windText.destroy(); }, 3000); } else { windSpeed = 0; } switch (levelPattern) { case 0: // Compact pyramid - 5 blocks - ensure all blocks fit on screen var safeStartX = Math.min(startX, 1700); // Leave room for 3 blocks (240px width) // Bottom row for (var i = 0; i < 3; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + i * 80; block.y = startY; targetBlocks.push(block); } // Top row for (var i = 0; i < 2; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + 40 + i * 80; block.y = startY - 80; targetBlocks.push(block); } break; case 1: // Compact wall formation - 5 blocks var safeStartX = Math.min(startX, 1788); // Leave room for 3 blocks wide (240px) for (var i = 0; i < 5; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + i % 3 * 80; block.y = startY - Math.floor(i / 3) * 80; targetBlocks.push(block); } break; case 2: // Compact L-shape - 5 blocks var safeStartX = Math.min(startX, 1700); // Leave room for 3 blocks wide (240px) // Horizontal part for (var i = 0; i < 3; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + i * 80; block.y = startY; targetBlocks.push(block); } // Vertical part for (var i = 1; i < 3; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX; block.y = startY - i * 80; targetBlocks.push(block); } break; case 3: // Compact cluster - 5 blocks var safeStartX = Math.min(startX, 1668); // Leave room for widest position (160px total) var positions = [{ x: 0, y: 0 }, { x: 80, y: 0 }, { x: 40, y: -80 }, { x: 120, y: -40 }, { x: -40, y: -40 }]; for (var i = 0; i < positions.length; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + positions[i].x; block.y = startY + positions[i].y; targetBlocks.push(block); } break; case 4: // Compact tower - 5 blocks in vertical line var safeStartX = Math.min(startX, 1898); // Single column needs less room for (var i = 0; i < 5; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX; block.y = startY - i * 80; targetBlocks.push(block); } break; case 5: // Compact spiral - 5 blocks var centerX = Math.min(startX + 80, 1800); // Keep spiral center safe var centerY = startY - 80; for (var i = 0; i < 5; i++) { var angle = i * 1.0; var radius = 20 + i * 15; var block = game.addChild(new TargetBlock()); // Constrain spiral positions to screen bounds block.x = Math.max(150, Math.min(1898, centerX + Math.cos(angle) * radius)); block.y = Math.max(200, centerY + Math.sin(angle) * radius); targetBlocks.push(block); } break; case 6: // Compact cross - 5 blocks var safeStartX = Math.min(startX, 1728); // Leave room for 160px wide cross // Center var block = game.addChild(new TargetBlock()); block.x = safeStartX + 80; block.y = startY - 80; targetBlocks.push(block); // Cross arms for (var i = 0; i < 4; i++) { var block = game.addChild(new TargetBlock()); if (i < 2) { block.x = safeStartX + i * 160; block.y = startY - 80; } else { block.x = safeStartX + 80; block.y = startY - (i - 1) * 80; } targetBlocks.push(block); } break; case 7: // Compact diamond - 5 blocks var safeStartX = Math.min(startX, 1768); // Leave room for 160px wide diamond var positions = [{ x: 80, y: -40 }, { x: 40, y: -80 }, { x: 120, y: -80 }, { x: 80, y: -120 }, { x: 80, y: 0 }]; for (var i = 0; i < positions.length; i++) { var block = game.addChild(new TargetBlock()); block.x = safeStartX + positions[i].x; block.y = startY + positions[i].y; targetBlocks.push(block); } break; } // Add special blocks for higher levels if (level > 5) { // Some blocks require multiple hits var specialBlockCount = Math.min(Math.floor(level / 5), 3); for (var i = 0; i < specialBlockCount && i < targetBlocks.length; i++) { var specialBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)]; specialBlock.health = 2; // Visual indicator for special blocks tween(specialBlock, { tint: 0xFF6600 }, { duration: 500, easing: tween.easeInOut }); specialBlock.scaleX = 1.1; specialBlock.scaleY = 1.1; } } // Add magnetic blocks for higher levels if (level > 8) { var magneticBlockCount = Math.min(Math.floor(level / 8), 2); for (var i = 0; i < magneticBlockCount && i < targetBlocks.length; i++) { var magneticBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)]; var magneticType = Math.random() > 0.5 ? 'attract' : 'repel'; magneticBlock.setMagnetic(magneticType); } } // Add portals for very high levels if (level > 12) { // Clear existing portals for (var i = 0; i < portals.length; i++) { portals[i].destroy(); } portals = []; // Create portal pairs - constrain to screen bounds var portal1 = game.addChild(new Portal()); portal1.x = Math.max(150, Math.min(1898, 600 + Math.random() * 200)); portal1.y = Math.max(300, GROUND_Y - 200 - Math.random() * 300); var portal2 = game.addChild(new Portal()); portal2.x = Math.max(150, Math.min(1898, 1400 + Math.random() * 200)); portal2.y = Math.max(300, GROUND_Y - 200 - Math.random() * 300); // Link portals portal1.linkedPortal = portal2; portal2.linkedPortal = portal1; portals.push(portal1, portal2); } } // Initialize game systems particleSystem = new ParticleSystem(); achievementSystem = new AchievementSystem(); achievementSystem.loadAchievements(); // Load saved progress level = storage.currentLevel || 1; totalBlocksDestroyed = storage.totalBlocksDestroyed || 0; levelsCompleted = storage.levelsCompleted || 0; // Show intro screen introScreen = game.addChild(new IntroScreen()); introScreen.show(); // Game control functions function startGame() { gameState = 'playing'; introScreen.hide(function () { introScreen.destroy(); introScreen = null; createLevel(); // Start background music immediately when game starts LK.playMusic('angrybirds', { volume: 1.0 }); }); } function showSettings() { // Create settings overlay var settingsOverlay = game.addChild(LK.getAsset('grass', { anchorX: 0.5, anchorY: 0.5, color: 0x000000, alpha: 0.9 })); settingsOverlay.width = 2048; settingsOverlay.height = 2732; settingsOverlay.x = 1024; settingsOverlay.y = 1366; // Title var titleText = new Text2('AYARLAR', { size: 100, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; game.addChild(titleText); // Load saved settings var savedMusicVolume = storage.musicVolume || 1.0; var savedSoundVolume = storage.soundVolume || 1.0; var savedGraphicsQuality = storage.graphicsQuality || 'high'; var savedAutoAim = storage.autoAim || false; // Music Volume Section var musicVolumeText = new Text2('Müzik Ses Seviyesi: ' + Math.round(savedMusicVolume * 100) + '%', { size: 60, fill: 0xFFFFFF }); musicVolumeText.anchor.set(0.5, 0.5); musicVolumeText.x = 1024; musicVolumeText.y = 800; game.addChild(musicVolumeText); // Music volume slider background var musicSliderBg = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); musicSliderBg.x = 1024; musicSliderBg.y = 900; musicSliderBg.scaleX = 6; musicSliderBg.scaleY = 0.5; musicSliderBg.tint = 0x666666; // Music volume slider handle var musicSliderHandle = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); musicSliderHandle.x = 1024 - 300 + savedMusicVolume * 600; musicSliderHandle.y = 900; musicSliderHandle.scaleX = 4; musicSliderHandle.scaleY = 4; musicSliderHandle.tint = 0x4CAF50; // Sound Effects Volume Section var soundVolumeText = new Text2('Efekt Ses Seviyesi: ' + Math.round(savedSoundVolume * 100) + '%', { size: 60, fill: 0xFFFFFF }); soundVolumeText.anchor.set(0.5, 0.5); soundVolumeText.x = 1024; soundVolumeText.y = 1050; game.addChild(soundVolumeText); // Sound volume slider background var soundSliderBg = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); soundSliderBg.x = 1024; soundSliderBg.y = 1150; soundSliderBg.scaleX = 6; soundSliderBg.scaleY = 0.5; soundSliderBg.tint = 0x666666; // Sound volume slider handle var soundSliderHandle = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); soundSliderHandle.x = 1024 - 300 + savedSoundVolume * 600; soundSliderHandle.y = 1150; soundSliderHandle.scaleX = 4; soundSliderHandle.scaleY = 4; soundSliderHandle.tint = 0x4CAF50; // Graphics Quality Section var graphicsText = new Text2('Grafik Kalitesi: ' + savedGraphicsQuality.toUpperCase(), { size: 60, fill: 0xFFFFFF }); graphicsText.anchor.set(0.5, 0.5); graphicsText.x = 1024; graphicsText.y = 1300; game.addChild(graphicsText); var graphicsButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); graphicsButton.x = 1024; graphicsButton.y = 1400; graphicsButton.scaleX = 3; graphicsButton.scaleY = 1; graphicsButton.tint = 0x2196F3; var graphicsButtonText = new Text2('DEĞİŞTİR', { size: 50, fill: 0xFFFFFF }); graphicsButtonText.anchor.set(0.5, 0.5); graphicsButtonText.x = 1024; graphicsButtonText.y = 1400; game.addChild(graphicsButtonText); // Auto-Aim Section var autoAimText = new Text2('Otomatik Nişan: ' + (savedAutoAim ? 'AÇIK' : 'KAPALI'), { size: 60, fill: 0xFFFFFF }); autoAimText.anchor.set(0.5, 0.5); autoAimText.x = 1024; autoAimText.y = 1550; game.addChild(autoAimText); var autoAimButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); autoAimButton.x = 1024; autoAimButton.y = 1650; autoAimButton.scaleX = 3; autoAimButton.scaleY = 1; autoAimButton.tint = savedAutoAim ? 0x4CAF50 : 0xFF5722; var autoAimButtonText = new Text2('DEĞIŞTIR', { size: 50, fill: 0xFFFFFF }); autoAimButtonText.anchor.set(0.5, 0.5); autoAimButtonText.x = 1024; autoAimButtonText.y = 1650; game.addChild(autoAimButtonText); // Reset Progress Section var resetButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); resetButton.x = 1024; resetButton.y = 1800; resetButton.scaleX = 3; resetButton.scaleY = 1.2; resetButton.tint = 0xFF5722; var resetText = new Text2('İLERLEMEYİ SIFIRLA', { size: 50, fill: 0xFFFFFF }); resetText.anchor.set(0.5, 0.5); resetText.x = 1024; resetText.y = 1800; game.addChild(resetText); // Close button var closeButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); closeButton.x = 1024; closeButton.y = 2000; closeButton.scaleX = 2; closeButton.scaleY = 1.2; closeButton.tint = 0x4CAF50; var closeText = new Text2('KAPAT', { size: 80, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 2000; game.addChild(closeText); // Event handlers var isDraggingMusic = false; var isDraggingSound = false; // Music slider interaction musicSliderHandle.down = function (x, y, obj) { isDraggingMusic = true; }; // Sound slider interaction soundSliderHandle.down = function (x, y, obj) { isDraggingSound = true; }; // Graphics quality toggle graphicsButton.down = function (x, y, obj) { var qualities = ['low', 'medium', 'high']; var currentIndex = qualities.indexOf(savedGraphicsQuality); savedGraphicsQuality = qualities[(currentIndex + 1) % qualities.length]; storage.graphicsQuality = savedGraphicsQuality; graphicsText.setText('Grafik Kalitesi: ' + savedGraphicsQuality.toUpperCase()); }; // Auto-aim toggle autoAimButton.down = function (x, y, obj) { savedAutoAim = !savedAutoAim; storage.autoAim = savedAutoAim; autoAimText.setText('Otomatik Nişan: ' + (savedAutoAim ? 'AÇIK' : 'KAPALI')); autoAimButton.tint = savedAutoAim ? 0x4CAF50 : 0xFF5722; }; // Reset progress resetButton.down = function (x, y, obj) { storage.currentLevel = 1; storage.totalBlocksDestroyed = 0; storage.levelsCompleted = 0; storage.achievements = {}; level = 1; totalBlocksDestroyed = 0; levelsCompleted = 0; // Show confirmation var confirmText = new Text2('İlerleme sıfırlandı!', { size: 60, fill: 0xFF0000 }); confirmText.anchor.set(0.5, 0.5); confirmText.x = 1024; confirmText.y = 1900; game.addChild(confirmText); LK.setTimeout(function () { confirmText.destroy(); }, 2000); }; // Close settings closeButton.down = function (x, y, obj) { settingsOverlay.destroy(); titleText.destroy(); musicVolumeText.destroy(); musicSliderBg.destroy(); musicSliderHandle.destroy(); soundVolumeText.destroy(); soundSliderBg.destroy(); soundSliderHandle.destroy(); graphicsText.destroy(); graphicsButton.destroy(); graphicsButtonText.destroy(); autoAimText.destroy(); autoAimButton.destroy(); autoAimButtonText.destroy(); resetButton.destroy(); resetText.destroy(); closeButton.destroy(); closeText.destroy(); }; // Global move handler for sliders settingsOverlay.move = function (x, y, obj) { if (isDraggingMusic) { var sliderX = Math.max(724, Math.min(1324, x)); musicSliderHandle.x = sliderX; savedMusicVolume = (sliderX - 724) / 600; storage.musicVolume = savedMusicVolume; musicVolumeText.setText('Müzik Ses Seviyesi: ' + Math.round(savedMusicVolume * 100) + '%'); } if (isDraggingSound) { var sliderX = Math.max(724, Math.min(1324, x)); soundSliderHandle.x = sliderX; savedSoundVolume = (sliderX - 724) / 600; storage.soundVolume = savedSoundVolume; soundVolumeText.setText('Efekt Ses Seviyesi: ' + Math.round(savedSoundVolume * 100) + '%'); } }; // Global up handler to stop dragging settingsOverlay.up = function (x, y, obj) { isDraggingMusic = false; isDraggingSound = false; }; } function showLevelSelector() { // Create level selector overlay var levelOverlay = game.addChild(LK.getAsset('grass', { anchorX: 0.5, anchorY: 0.5, color: 0x000000, alpha: 0.9 })); levelOverlay.width = 2048; levelOverlay.height = 2732; levelOverlay.x = 1024; levelOverlay.y = 1366; // Title var titleText = new Text2('BÖLÜMLER', { size: 100, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; game.addChild(titleText); // Load saved progress var unlockedLevel = storage.currentLevel || 1; var completedLevels = storage.completedLevels || {}; var levelStars = storage.levelStars || {}; // Progress indicator var progressText = new Text2('İlerleme: ' + Math.max(1, unlockedLevel - 1) + '/50 Bölüm', { size: 60, fill: 0xFFFFFF }); progressText.anchor.set(0.5, 0.5); progressText.x = 1024; progressText.y = 500; game.addChild(progressText); // Continue button (jump to furthest level) var continueButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); continueButton.x = 1024; continueButton.y = 600; continueButton.scaleX = 3; continueButton.scaleY = 1.2; continueButton.tint = 0x4CAF50; var continueText = new Text2('DEVAM ET (Bölüm ' + unlockedLevel + ')', { size: 50, fill: 0xFFFFFF }); continueText.anchor.set(0.5, 0.5); continueText.x = 1024; continueText.y = 600; game.addChild(continueText); // Level grid setup var startY = 750; var levelsPerRow = 5; var buttonSize = 120; var buttonSpacing = 150; var rowSpacing = 140; var maxLevels = 50; var currentPage = 0; var levelsPerPage = 15; // 3 rows x 5 columns // Page indicator var pageText = new Text2('Sayfa ' + (currentPage + 1) + '/' + Math.ceil(maxLevels / levelsPerPage), { size: 50, fill: 0xFFFFFF }); pageText.anchor.set(0.5, 0.5); pageText.x = 1024; pageText.y = 700; game.addChild(pageText); // Level buttons array for cleanup var levelButtons = []; var levelTexts = []; var starTexts = []; function createLevelGrid() { // Clear existing level buttons for (var i = 0; i < levelButtons.length; i++) { if (levelButtons[i]) levelButtons[i].destroy(); if (levelTexts[i]) levelTexts[i].destroy(); if (starTexts[i]) starTexts[i].destroy(); } levelButtons = []; levelTexts = []; starTexts = []; // Create level buttons for current page for (var i = 0; i < levelsPerPage; i++) { var levelNum = currentPage * levelsPerPage + i + 1; if (levelNum > maxLevels) break; var row = Math.floor(i / levelsPerRow); var col = i % levelsPerRow; var buttonX = 1024 - (levelsPerRow - 1) * buttonSpacing / 2 + col * buttonSpacing; var buttonY = startY + row * rowSpacing; // Level button var isUnlocked = levelNum <= unlockedLevel; var isCompleted = completedLevels[levelNum] || false; var stars = levelStars[levelNum] || 0; var levelButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); levelButton.x = buttonX; levelButton.y = buttonY; levelButton.scaleX = buttonSize / 100; levelButton.scaleY = buttonSize / 100; // Color coding if (!isUnlocked) { levelButton.tint = 0x666666; // Gray for locked levelButton.alpha = 0.5; } else if (isCompleted) { levelButton.tint = 0xFFD700; // Gold for completed } else if (levelNum === unlockedLevel) { levelButton.tint = 0x4CAF50; // Green for current } else { levelButton.tint = 0x2196F3; // Blue for available } // Level number text var levelText = new Text2(levelNum.toString(), { size: 40, fill: isUnlocked ? 0x000000 : 0x999999 }); levelText.anchor.set(0.5, 0.5); levelText.x = buttonX; levelText.y = buttonY - 10; game.addChild(levelText); // Star rating var starText = new Text2('★'.repeat(stars), { size: 25, fill: 0xFFD700 }); starText.anchor.set(0.5, 0.5); starText.x = buttonX; starText.y = buttonY + 25; game.addChild(starText); // Store references levelButtons.push(levelButton); levelTexts.push(levelText); starTexts.push(starText); // Add click handler for unlocked levels if (isUnlocked) { levelButton.levelNumber = levelNum; levelButton.down = function (x, y, obj) { // Start selected level level = obj.levelNumber; storage.currentLevel = level; closeSelector(); startGame(); }; } } } // Navigation buttons var prevButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); prevButton.x = 300; prevButton.y = 1200; prevButton.scaleX = 1.5; prevButton.scaleY = 1; prevButton.tint = currentPage > 0 ? 0xFF9800 : 0x666666; var prevText = new Text2('◀', { size: 60, fill: 0xFFFFFF }); prevText.anchor.set(0.5, 0.5); prevText.x = 300; prevText.y = 1200; game.addChild(prevText); var nextButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); nextButton.x = 1748; nextButton.y = 1200; nextButton.scaleX = 1.5; nextButton.scaleY = 1; nextButton.tint = currentPage < Math.ceil(maxLevels / levelsPerPage) - 1 ? 0xFF9800 : 0x666666; var nextText = new Text2('▶', { size: 60, fill: 0xFFFFFF }); nextText.anchor.set(0.5, 0.5); nextText.x = 1748; nextText.y = 1200; game.addChild(nextText); // Navigation handlers prevButton.down = function (x, y, obj) { if (currentPage > 0) { currentPage--; updateNavigation(); createLevelGrid(); } }; nextButton.down = function (x, y, obj) { if (currentPage < Math.ceil(maxLevels / levelsPerPage) - 1) { currentPage++; updateNavigation(); createLevelGrid(); } }; function updateNavigation() { prevButton.tint = currentPage > 0 ? 0xFF9800 : 0x666666; nextButton.tint = currentPage < Math.ceil(maxLevels / levelsPerPage) - 1 ? 0xFF9800 : 0x666666; pageText.setText('Sayfa ' + (currentPage + 1) + '/' + Math.ceil(maxLevels / levelsPerPage)); } // Difficulty filter var filterText = new Text2('Zorluk Filtresi:', { size: 50, fill: 0xFFFFFF }); filterText.anchor.set(0.5, 0.5); filterText.x = 1024; filterText.y = 1350; game.addChild(filterText); var filters = ['Tümü', 'Kolay', 'Orta', 'Zor']; var currentFilter = 0; var filterButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); filterButton.x = 1024; filterButton.y = 1420; filterButton.scaleX = 2.5; filterButton.scaleY = 1; filterButton.tint = 0x9C27B0; var filterLabel = new Text2(filters[currentFilter], { size: 45, fill: 0xFFFFFF }); filterLabel.anchor.set(0.5, 0.5); filterLabel.x = 1024; filterLabel.y = 1420; game.addChild(filterLabel); filterButton.down = function (x, y, obj) { currentFilter = (currentFilter + 1) % filters.length; filterLabel.setText(filters[currentFilter]); // Apply filter logic here - simplified for now createLevelGrid(); }; // World selector var worldText = new Text2('Dünya: Normal', { size: 50, fill: 0xFFFFFF }); worldText.anchor.set(0.5, 0.5); worldText.x = 1024; worldText.y = 1500; game.addChild(worldText); // Achievement showcase var achievementText = new Text2('Kazanımlar: ' + Object.keys(storage.achievements || {}).length + '/4', { size: 45, fill: 0xFFD700 }); achievementText.anchor.set(0.5, 0.5); achievementText.x = 1024; achievementText.y = 1580; game.addChild(achievementText); // Continue button handler continueButton.down = function (x, y, obj) { level = unlockedLevel; storage.currentLevel = level; closeSelector(); startGame(); }; // Close button var closeButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); closeButton.x = 1024; closeButton.y = 1700; closeButton.scaleX = 2; closeButton.scaleY = 1.2; closeButton.tint = 0x4CAF50; var closeText = new Text2('KAPAT', { size: 80, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 1700; game.addChild(closeText); function closeSelector() { // Clean up all elements levelOverlay.destroy(); titleText.destroy(); progressText.destroy(); continueButton.destroy(); continueText.destroy(); pageText.destroy(); prevButton.destroy(); prevText.destroy(); nextButton.destroy(); nextText.destroy(); filterText.destroy(); filterButton.destroy(); filterLabel.destroy(); worldText.destroy(); achievementText.destroy(); closeButton.destroy(); closeText.destroy(); // Clean up level buttons for (var i = 0; i < levelButtons.length; i++) { if (levelButtons[i]) levelButtons[i].destroy(); if (levelTexts[i]) levelTexts[i].destroy(); if (starTexts[i]) starTexts[i].destroy(); } } closeButton.down = function (x, y, obj) { closeSelector(); }; // Initialize the grid createLevelGrid(); } function showHowToPlay() { // Create overlay for instructions var instructionOverlay = game.addChild(LK.getAsset('grass', { anchorX: 0.5, anchorY: 0.5, color: 0x000000, alpha: 0.9 })); instructionOverlay.width = 2048; instructionOverlay.height = 2732; instructionOverlay.x = 1024; instructionOverlay.y = 1366; // Title var titleText = new Text2('NASIL OYNANIR', { size: 100, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; game.addChild(titleText); // Instructions var instructions = ['🎯 AMAÇ: Tüm blokları yok et', '🏹 ATIŞ: Sapanı çek ve bırak', '⭐ TİPLER:', ' • Normal: Temel mermi', ' • Patlayıcı (E): Çevresi hasar', ' • Zıplayan (B): Sekme özelliği', ' • Ağır (H): Güçlü darbe', '🔄 ÖZEL YETENEKLER:', ' • Yerçekimi kontrolü (6+ seviye)', ' • Zaman yavaşlatma (10+ seviye)', '💫 PORTAL: Mermileri ışınlar', '🧲 MANYETİK: Mavi çeker, kırmızı iter']; for (var i = 0; i < instructions.length; i++) { var instructionText = new Text2(instructions[i], { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 800 + i * 70; game.addChild(instructionText); } // Close button var closeButton = game.addChild(LK.getAsset('targetBlock', { anchorX: 0.5, anchorY: 0.5 })); closeButton.x = 1024; closeButton.y = 2200; closeButton.scaleX = 2; closeButton.scaleY = 1.2; closeButton.tint = 0x4CAF50; var closeText = new Text2('KAPAT', { size: 80, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 2200; game.addChild(closeText); // Close functionality closeButton.down = function (x, y, obj) { // Clean up all instruction elements instructionOverlay.destroy(); titleText.destroy(); closeButton.destroy(); closeText.destroy(); // Clean up instruction texts for (var j = 0; j < instructions.length; j++) { // Find and destroy instruction texts for (var k = game.children.length - 1; k >= 0; k--) { var child = game.children[k]; if (child.constructor === Text2 && child.y >= 800 && child.y <= 1600) { child.destroy(); } } } }; } function switchProjectileType() { powerUpIndex = (powerUpIndex + 1) % availablePowerUps.length; currentProjectileType = availablePowerUps[powerUpIndex]; // Update UI to show current projectile type var typeText = new Text2('Tip: ' + currentProjectileType.toUpperCase(), { size: 60, fill: 0x000000 }); typeText.anchor.set(0.5, 0); typeText.x = 1024; typeText.y = 200; LK.gui.top.addChild(typeText); // Remove after 2 seconds LK.setTimeout(function () { typeText.destroy(); }, 2000); } // Don't initialize level if we're showing intro // createLevel(); // Helper functions function calculateTrajectory(startX, startY, velocityX, velocityY) { var points = []; var x = startX; var y = startY; var vx = velocityX; var vy = velocityY; var timeStep = 2; var gravity = GRAVITY * timeStep; for (var i = 0; i < 15; i++) { points.push({ x: x, y: y }); x += vx * timeStep; y += vy * timeStep; vy += gravity; if (y >= GROUND_Y - 30) break; } return points; } function updateTrajectoryDisplay(points) { for (var i = 0; i < trajectoryDots.length; i++) { if (i < points.length) { trajectoryDots[i].x = points[i].x; trajectoryDots[i].y = points[i].y; trajectoryDots[i].visible = true; } else { trajectoryDots[i].visible = false; } } } function hideTrajectoryDisplay() { for (var i = 0; i < trajectoryDots.length; i++) { trajectoryDots[i].visible = false; } } function checkProjectileCollisions(projectile) { var hitSomething = false; var blocksDestroyed = 0; // Apply magnetic forces from all blocks for (var i = 0; i < targetBlocks.length; i++) { var block = targetBlocks[i]; if (!block.destroyed && block.magneticType !== 'none') { block.applyMagneticForce(projectile); } } // Check portal teleportation for (var i = 0; i < portals.length; i++) { if (portals[i].teleport(projectile)) { break; // Only one teleport per frame } } for (var i = 0; i < targetBlocks.length; i++) { var block = targetBlocks[i]; if (!block.destroyed && projectile.intersects(block)) { var wasDestroyed = block.destroyed; block.takeDamage(); if (!wasDestroyed && block.destroyed) { blocksDestroyed++; totalBlocksDestroyed++; storage.totalBlocksDestroyed = totalBlocksDestroyed; // Create destruction particles particleSystem.createExplosion(block.x, block.y, 0xFFFFFF, 8); } LK.getSound('impact').play(); hitSomething = true; // Type-specific collision effects switch (projectile.type) { case 'explosive': projectile.explode(); projectile.destroyed = true; return true; case 'bouncy': projectile.velocityX *= -0.8; projectile.velocityY *= -0.8; projectile.bounceCount++; if (projectile.bounceCount <= 3) { LK.getSound('bounce').play(); } if (projectile.bounceCount < 3) { // Add bounce particle effect particleSystem.createExplosion(projectile.x, projectile.y, 0x44FF44, 5); } break; case 'heavy': // Heavy projectiles don't bounce much and continue through projectile.velocityX *= -0.1; projectile.velocityY *= -0.1; break; default: // Normal projectile behavior projectile.velocityX *= -0.2; projectile.velocityY *= -0.2; break; } // Add some randomness to bounce projectile.velocityX += (Math.random() - 0.5) * 2; projectile.velocityY += (Math.random() - 0.5) * 2; if (block.destroyed) { player.celebrate(); // Player celebrates when destroying a block } } } // Check achievements if (blocksDestroyed >= 5) { achievementSystem.checkAchievement('oneShot', blocksDestroyed); } achievementSystem.checkAchievement('destructionMaster', totalBlocksDestroyed); return hitSomething; } function checkLevelComplete() { var remainingBlocks = 0; for (var i = 0; i < targetBlocks.length; i++) { if (!targetBlocks[i].destroyed) { remainingBlocks++; } } if (remainingBlocks === 0) { // Level complete - restart with new level var shotsUsed = INITIAL_SHOTS - shotsRemaining; // Calculate star rating var stars = 3; if (shotsUsed > 2) stars = 2; if (shotsUsed > 3) stars = 1; // Save level completion data var completedLevels = storage.completedLevels || {}; var levelStars = storage.levelStars || {}; completedLevels[level] = true; levelStars[level] = Math.max(levelStars[level] || 0, stars); // Keep best star rating storage.completedLevels = completedLevels; storage.levelStars = levelStars; level++; levelsCompleted++; storage.currentLevel = level; storage.levelsCompleted = levelsCompleted; // Check for perfect shot achievement if (shotsUsed === 1) { achievementSystem.checkAchievement('perfectShot', 1); } // Check level completion achievement achievementSystem.checkAchievement('sharpshooter', levelsCompleted); // Enhanced level complete message with star display var completeText = new Text2('Bölüm ' + (level - 1) + ' Tamamlandı!', { size: 80, fill: 0xFFD700 }); completeText.anchor.set(0.5, 0.5); completeText.x = 1024; completeText.y = 950; completeText.alpha = 0; game.addChild(completeText); var starDisplayText = new Text2('★'.repeat(stars) + '☆'.repeat(3 - stars), { size: 100, fill: 0xFFD700 }); starDisplayText.anchor.set(0.5, 0.5); starDisplayText.x = 1024; starDisplayText.y = 1050; starDisplayText.alpha = 0; game.addChild(starDisplayText); var shotsUsedText = new Text2('Kullanılan Atış: ' + shotsUsed + '/' + INITIAL_SHOTS, { size: 60, fill: 0xFFFFFF }); shotsUsedText.anchor.set(0.5, 0.5); shotsUsedText.x = 1024; shotsUsedText.y = 1150; shotsUsedText.alpha = 0; game.addChild(shotsUsedText); // Animate in all elements tween(completeText, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); tween(starDisplayText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 700, delay: 300, easing: tween.bounceOut }); tween(shotsUsedText, { alpha: 1 }, { duration: 500, delay: 600, easing: tween.easeOut }); shotsRemaining = INITIAL_SHOTS; shotsText.setText('Atış: ' + shotsRemaining); LK.setTimeout(function () { tween(completeText, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { completeText.destroy(); } }); tween(starDisplayText, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { starDisplayText.destroy(); } }); tween(shotsUsedText, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { shotsUsedText.destroy(); } }); createLevel(); }, 3000); return true; } if (shotsRemaining <= 0 && projectiles.length === 0) { // Only show game over if there are still blocks remaining var remainingBlocks = 0; for (var i = 0; i < targetBlocks.length; i++) { if (!targetBlocks[i].destroyed) { remainingBlocks++; } } if (remainingBlocks > 0) { // Show game over only if level is not complete LK.showGameOver(); return true; } } return false; } // Event handlers game.down = function (x, y, obj) { if (gameState !== 'playing') return; // Double tap to switch projectile type if (!currentProjectile && shotsRemaining > 0) { var distance = Math.sqrt((x - slingshot.x) * (x - slingshot.x) + (y - slingshot.y) * (y - slingshot.y)); // Check if clicking on projectile type indicator (top left area) if (x < 300 && y < 300) { switchProjectileType(); return; } // Check if clicking on gravity control (top right area) if (x > 1748 && y < 300) { if (level > 6) { // Unlock gravity control after level 6 gravityReversed = !gravityReversed; gravityTimer = maxGravityTime; // Visual feedback var gravityText = new Text2('Yerçekimi: ' + (gravityReversed ? 'TERS' : 'NORMAL'), { size: 60, fill: gravityReversed ? 0xFF0000 : 0x00FF00 }); gravityText.anchor.set(0.5, 0); gravityText.x = 1024; gravityText.y = 250; LK.gui.top.addChild(gravityText); LK.setTimeout(function () { gravityText.destroy(); }, 2000); LK.effects.flashScreen(gravityReversed ? 0xFF0000 : 0x0000FF, 300); } return; } // Check if clicking on time control (bottom center area) if (x > 924 && x < 1124 && y > 2500) { if (level > 10 && timeSlowCooldown === 0 && !timeSlowActive) { // Unlock time control after level 10 timeSlowActive = true; timeSlowTimer = maxTimeSlowDuration; timeSlowCooldown = maxTimeSlowCooldown; // Visual feedback var timeText = new Text2('ZAMAN YAVAŞ!', { size: 80, fill: 0x00FFFF }); timeText.anchor.set(0.5, 0); timeText.x = 1024; timeText.y = 350; LK.gui.top.addChild(timeText); LK.setTimeout(function () { timeText.destroy(); }, 1000); LK.effects.flashScreen(0x00FFFF, 400); } return; } if (distance < 250) { // Increased from 150 to 250 for easier grabbing isAiming = true; aimStartX = x; aimStartY = y; currentProjectile = game.addChild(new Projectile()); currentProjectile.x = slingshot.x; currentProjectile.y = slingshot.y - 100; currentProjectile.type = currentProjectileType; // Visual feedback for successful grab LK.effects.flashObject(slingshot, 0x00FF00, 200); // Scale animation to show projectile is grabbed tween(currentProjectile, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut }); player.aim(); // Player leans forward when aiming } } }; game.move = function (x, y, obj) { if (isAiming && currentProjectile) { var deltaX = aimStartX - x; var deltaY = aimStartY - y; // Restrict aiming to forward direction only (positive deltaX means forward) if (deltaX < 0) { deltaX = 0; // Don't allow backward aiming } // Limit drag distance var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance > MAX_DRAG_DISTANCE) { deltaX = deltaX / distance * MAX_DRAG_DISTANCE; deltaY = deltaY / distance * MAX_DRAG_DISTANCE; distance = MAX_DRAG_DISTANCE; } // Smooth projectile following with magnetic snap to slingshot var targetX = slingshot.x - deltaX * 0.5; var targetY = slingshot.y - 100 - deltaY * 0.5; // If very close to slingshot, snap to it for better control if (distance < 30) { targetX = slingshot.x; targetY = slingshot.y - 100; } // Smooth interpolation for better feel currentProjectile.x += (targetX - currentProjectile.x) * 0.8; currentProjectile.y += (targetY - currentProjectile.y) * 0.8; // Animate slingshot stretch slingshot.stretch(deltaX, deltaY, distance); // Calculate and show trajectory var velocityX = deltaX * VELOCITY_MULTIPLIER; var velocityY = deltaY * VELOCITY_MULTIPLIER; var trajectoryPoints = calculateTrajectory(currentProjectile.x, currentProjectile.y, velocityX, velocityY); updateTrajectoryDisplay(trajectoryPoints); } }; game.up = function (x, y, obj) { if (gameState !== 'playing') return; if (isAiming && currentProjectile) { var deltaX = aimStartX - x; var deltaY = aimStartY - y; // Restrict aiming to forward direction only (positive deltaX means forward) if (deltaX < 0) { deltaX = 0; // Don't allow backward shooting } // Limit drag distance var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance > MAX_DRAG_DISTANCE) { deltaX = deltaX / distance * MAX_DRAG_DISTANCE; deltaY = deltaY / distance * MAX_DRAG_DISTANCE; } if (distance > 10 && deltaX > 0) { // Reduced from 20 to 10 for easier shooting // Only shoot if there's forward movement var velocityX = deltaX * VELOCITY_MULTIPLIER; var velocityY = deltaY * VELOCITY_MULTIPLIER; // Apply wind effect velocityX += windSpeed; // Animate slingshot release slingshot.release(); // Add screen flash effect for dramatic launch LK.effects.flashScreen(0xFFFFFF, 200); currentProjectile.launch(velocityX, velocityY, currentProjectileType); currentProjectile.lastX = currentProjectile.x; currentProjectile.lastY = currentProjectile.y; projectiles.push(currentProjectile); shotsRemaining--; shotsText.setText('Atış: ' + shotsRemaining); player.celebrate(); // Player celebrates the shot // Play power-up sound for special projectiles if (currentProjectileType !== 'normal') { LK.getSound('powerup').play(); } } else { currentProjectile.destroy(); slingshot.reset(); // Reset slingshot if no shot } currentProjectile = null; isAiming = false; hideTrajectoryDisplay(); player.resetPose(); // Player returns to normal stance } }; game.update = function () { if (gameState !== 'playing') return; // Update score display scoreText.setText('Puan: ' + LK.getScore()); // Update gravity timer if (gravityTimer > 0) { gravityTimer--; if (gravityTimer === 0) { gravityReversed = false; var gravityText = new Text2('Yerçekimi Normal', { size: 60, fill: 0x00FF00 }); gravityText.anchor.set(0.5, 0); gravityText.x = 1024; gravityText.y = 250; LK.gui.top.addChild(gravityText); LK.setTimeout(function () { gravityText.destroy(); }, 1500); } } // Update time slow mechanics if (timeSlowActive) { timeSlowTimer--; if (timeSlowTimer === 0) { timeSlowActive = false; var timeText = new Text2('Zaman Normal', { size: 60, fill: 0x00FF00 }); timeText.anchor.set(0.5, 0); timeText.x = 1024; timeText.y = 300; LK.gui.top.addChild(timeText); LK.setTimeout(function () { timeText.destroy(); }, 1500); } } if (timeSlowCooldown > 0) { timeSlowCooldown--; } // Update portals for (var i = 0; i < portals.length; i++) { portals[i].update(); } // Spawn flying birds periodically birdSpawnTimer++; if (birdSpawnTimer > 300 + Math.random() * 600) { // Every 5-15 seconds birdSpawnTimer = 0; var bird = game.addChild(new FlyingBird()); bird.init(); flyingBirds.push(bird); } // Update flying birds for (var i = flyingBirds.length - 1; i >= 0; i--) { var bird = flyingBirds[i]; if (bird.destroyed) { bird.destroy(); flyingBirds.splice(i, 1); continue; } bird.update(); // Check collision with projectiles for (var j = 0; j < projectiles.length; j++) { var projectile = projectiles[j]; if (projectile.launched && !projectile.destroyed && projectile.intersects(bird)) { // Bird hit - reduce shots and destroy bird shotsRemaining = Math.max(0, shotsRemaining - 1); shotsText.setText('Atış: ' + shotsRemaining); bird.destroyed = true; // Visual feedback LK.effects.flashScreen(0xFF0000, 300); particleSystem.createExplosion(bird.x, bird.y, 0xFFFF00, 6); LK.getSound('Bird').play(); break; } } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; if (projectile.destroyed) { projectile.destroy(); projectiles.splice(i, 1); continue; } if (projectile.launched) { // Add wind effect to projectile if (windSpeed !== 0) { projectile.velocityX += windSpeed * 0.05; } // Create particle trail for special projectiles - reduced frequency if (projectile.type !== 'normal' && LK.ticks % 8 === 0) { particleSystem.createTrail(projectile.x - projectile.velocityX * 0.5, projectile.y - projectile.velocityY * 0.5, projectile.velocityX, projectile.velocityY); } checkProjectileCollisions(projectile); } } // Remove destroyed blocks with particle effects for (var i = targetBlocks.length - 1; i >= 0; i--) { if (targetBlocks[i].destroyed) { // Create destruction particles if not already done if (!targetBlocks[i].particlesCreated) { particleSystem.createExplosion(targetBlocks[i].x, targetBlocks[i].y, 0xFFFFFF, 6); targetBlocks[i].particlesCreated = true; } targetBlocks[i].destroy(); targetBlocks.splice(i, 1); } } // Color-changing world based on level progression if (LK.ticks % 120 === 0) { var colorPhase = (level - 1) % 6; var skyColor, grassColor; switch (colorPhase) { case 0: // Dawn skyColor = 0x87CEEB; grassColor = 0x4caf50; break; case 1: // Morning skyColor = 0xADD8E6; grassColor = 0x228B22; break; case 2: // Noon skyColor = 0x00BFFF; grassColor = 0x32CD32; break; case 3: // Afternoon skyColor = 0xFF7F50; grassColor = 0x6B8E23; break; case 4: // Sunset skyColor = 0xFF6347; grassColor = 0x556B2F; break; case 5: // Night skyColor = 0x191970; grassColor = 0x2F4F2F; break; } // Smooth color transition tween(ground, { tint: grassColor }, { duration: 2000, easing: tween.easeInOut }); game.setBackgroundColor(skyColor); } // Environmental effects - reduced frequency if (level > 15 && LK.ticks % 300 === 0) { // Add occasional falling leaves or snow var leaf = game.addChild(LK.getAsset('trajectoryDot', { anchorX: 0.5, anchorY: 0.5 })); leaf.x = Math.random() * 2048; leaf.y = -50; leaf.tint = 0x228B22; leaf.scaleX = 0.5; leaf.scaleY = 0.5; tween(leaf, { x: leaf.x + (Math.random() - 0.5) * 200, y: 2800, rotation: Math.PI * 2, alpha: 0 }, { duration: 2000, easing: tween.linear, onFinish: function onFinish() { leaf.destroy(); } }); } // Periodic cleanup to prevent memory leaks if (LK.ticks % 300 === 0) { particleSystem.cleanup(); } // Check if game over (no shots remaining and no active projectiles) if (shotsRemaining <= 0 && projectiles.length === 0) { // Check if there are still blocks remaining var remainingBlocks = 0; for (var i = 0; i < targetBlocks.length; i++) { if (!targetBlocks[i].destroyed) { remainingBlocks++; } } if (remainingBlocks > 0) { // Show game over only if level is not complete LK.showGameOver(); return; } } // Check level completion checkLevelComplete(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AchievementSystem = Container.expand(function () {
var self = Container.call(this);
self.achievements = {
perfectShot: false,
oneShot: false,
destructionMaster: false,
sharpshooter: false
};
self.loadAchievements = function () {
var saved = storage.achievements;
if (saved) {
self.achievements = saved;
}
};
self.saveAchievements = function () {
storage.achievements = self.achievements;
};
self.checkAchievement = function (type, value) {
switch (type) {
case 'perfectShot':
if (value === 1 && !self.achievements.perfectShot) {
self.achievements.perfectShot = true;
self.showAchievement('Mükemmel Atış!', 'Tek atışta tüm hedefleri yok et');
}
break;
case 'oneShot':
if (value >= 5 && !self.achievements.oneShot) {
self.achievements.oneShot = true;
self.showAchievement('Tek Atış Ustası!', 'Tek atışta 5 blok yok et');
}
break;
case 'destructionMaster':
if (value >= 100 && !self.achievements.destructionMaster) {
self.achievements.destructionMaster = true;
self.showAchievement('Yıkım Ustası!', '100 blok yok et');
}
break;
case 'sharpshooter':
if (value >= 10 && !self.achievements.sharpshooter) {
self.achievements.sharpshooter = true;
self.showAchievement('Keskin Nişancı!', '10 seviye tamamla');
}
break;
}
self.saveAchievements();
};
self.showAchievement = function (title, description) {
LK.getSound('achievement').play();
var popup = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
popup.x = 1024;
popup.y = 400;
popup.scaleX = 4;
popup.scaleY = 2;
popup.tint = 0xFFD700;
popup.alpha = 0;
var titleText = new Text2(title, {
size: 60,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 380;
game.addChild(titleText);
var descText = new Text2(description, {
size: 40,
fill: 0x333333
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 420;
game.addChild(descText);
// Animate in
tween(popup, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
tween(titleText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
tween(descText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Animate out after delay
LK.setTimeout(function () {
tween(popup, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
popup.destroy();
}
});
tween(titleText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
titleText.destroy();
}
});
tween(descText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
descText.destroy();
}
});
}, 3000);
};
return self;
});
var FlyingBird = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.flightHeight = 300 + Math.random() * 500;
self.destroyed = false;
self.lastX = 0;
self.lastY = 0;
self.wingFlapTimer = 0;
// Initialize flight animation
tween(graphics, {
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
self.init = function () {
// Set random starting position
if (self.direction > 0) {
self.x = -100;
graphics.scaleX = 1; // Face right
} else {
self.x = 2148;
graphics.scaleX = -1; // Face left
}
self.y = self.flightHeight;
self.lastX = self.x;
self.lastY = self.y;
};
self.update = function () {
if (self.destroyed) return;
// Move horizontally
self.x += self.speed * self.direction;
// Add gentle vertical wave motion
self.y = self.flightHeight + Math.sin(LK.ticks * 0.05) * 30;
// Wing flap animation
self.wingFlapTimer++;
if (self.wingFlapTimer % 20 === 0) {
tween(graphics, {
rotation: 0.1 * self.direction
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(graphics, {
rotation: 0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Check if bird flew off screen
if (self.lastX >= -150 && self.lastX <= 2198 && (self.x < -150 || self.x > 2198)) {
self.destroyed = true;
}
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
var IntroScreen = Container.expand(function () {
var self = Container.call(this);
// Create background overlay
var overlay = self.attachAsset('grass', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x000000,
alpha: 0.8
});
overlay.width = 2048;
overlay.height = 2732;
overlay.x = 1024;
overlay.y = 1366;
// Title text
var titleText = new Text2('SAPAN USTASI', {
size: 120,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Play button
var playButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
playButton.x = 1024;
playButton.y = 1200;
playButton.scaleX = 2;
playButton.scaleY = 1.2;
playButton.tint = 0x4CAF50;
var playText = new Text2('OYNA', {
size: 80,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = 1200;
self.addChild(playText);
// Settings button
var settingsButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
settingsButton.x = 1024;
settingsButton.y = 1400;
settingsButton.scaleX = 2;
settingsButton.scaleY = 1.2;
settingsButton.tint = 0x2196F3;
var settingsText = new Text2('AYARLAR', {
size: 80,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1024;
settingsText.y = 1400;
self.addChild(settingsText);
// Level selector button
var levelButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
levelButton.x = 1024;
levelButton.y = 1600;
levelButton.scaleX = 2;
levelButton.scaleY = 1.2;
levelButton.tint = 0xFF9800;
var levelText = new Text2('BÖLÜMLER', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 1024;
levelText.y = 1600;
self.addChild(levelText);
// How to play button
var howToPlayButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
howToPlayButton.x = 1024;
howToPlayButton.y = 1800;
howToPlayButton.scaleX = 2;
howToPlayButton.scaleY = 1.2;
howToPlayButton.tint = 0x9C27B0;
var howToPlayText = new Text2('NASIL OYNANIR', {
size: 80,
fill: 0xFFFFFF
});
howToPlayText.anchor.set(0.5, 0.5);
howToPlayText.x = 1024;
howToPlayText.y = 1800;
self.addChild(howToPlayText);
// Click handlers
self.down = function (x, y, obj) {
// Use the x, y coordinates directly instead of trying to convert object position
// Play button
if (Math.abs(x - 1024) < 200 && Math.abs(y - 1200) < 60) {
startGame();
}
// Settings button
else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1400) < 60) {
showSettings();
}
// Level button
else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1600) < 60) {
showLevelSelector();
}
// How to play button
else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1800) < 60) {
showHowToPlay();
}
};
// Animation entrance
self.show = function () {
self.alpha = 0;
tween(self, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(titleText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.elasticOut
});
};
self.hide = function (callback) {
tween(self, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: callback
});
};
return self;
});
var ParticleSystem = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.createExplosion = function (x, y, color, count) {
// Limit particle count to prevent performance issues
count = Math.min(count, 6);
for (var i = 0; i < count; i++) {
var particle = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
particle.x = x;
particle.y = y;
particle.tint = color;
particle.alpha = 1;
self.particles.push(particle);
var angle = i / count * Math.PI * 2;
var speed = 50 + Math.random() * 100;
var distance = speed * (1 + Math.random());
tween(particle, {
x: x + Math.cos(angle) * distance,
y: y + Math.sin(angle) * distance,
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
var index = self.particles.indexOf(particle);
if (index > -1) self.particles.splice(index, 1);
}
});
}
};
self.createTrail = function (x, y, vx, vy) {
var trail = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
trail.x = x;
trail.y = y;
trail.alpha = 0.6;
trail.scaleX = 0.5;
trail.scaleY = 0.5;
self.particles.push(trail);
tween(trail, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
var index = self.particles.indexOf(trail);
if (index > -1) self.particles.splice(index, 1);
}
});
};
self.cleanup = function () {
// Clean up any remaining particles
for (var i = self.particles.length - 1; i >= 0; i--) {
if (self.particles[i] && self.particles[i].destroyed) {
self.particles.splice(i, 1);
}
}
// Limit total particles
if (self.particles.length > 50) {
for (var i = 0; i < 10; i++) {
if (self.particles[i]) {
self.particles[i].destroy();
self.particles.splice(i, 1);
}
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1
});
self.isReady = true;
self.celebrate = function () {
// More dramatic celebration animation
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
rotation: 0.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.2,
scaleY: 1.2,
rotation: 0
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
};
self.aim = function () {
// More pronounced aiming stance
tween(self, {
rotation: 0.15,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
easing: tween.easeOut
});
};
self.resetPose = function () {
// Return to normal stance with bounce
tween(self, {
rotation: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.elasticOut
});
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.scaleX = 4;
graphics.scaleY = 4;
graphics.tint = 0x9400D3;
self.linkedPortal = null;
self.cooldown = 0;
self.isActive = true;
// Add swirling animation
tween(graphics, {
rotation: Math.PI * 2
}, {
duration: 2000,
easing: tween.linear,
repeat: -1
});
// Add pulsing effect
tween(graphics, {
scaleX: 5,
scaleY: 5
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
self.teleport = function (projectile) {
if (!self.isActive || self.cooldown > 0 || !self.linkedPortal || !self.linkedPortal.isActive) return false;
var distance = Math.sqrt((projectile.x - self.x) * (projectile.x - self.x) + (projectile.y - self.y) * (projectile.y - self.y));
if (distance < 50) {
// Teleport projectile
projectile.x = self.linkedPortal.x;
projectile.y = self.linkedPortal.y;
// Add teleport effects
LK.effects.flashScreen(0x9400D3, 200);
LK.getSound('magic').play();
particleSystem.createExplosion(self.x, self.y, 0x9400D3, 8);
particleSystem.createExplosion(self.linkedPortal.x, self.linkedPortal.y, 0x9400D3, 8);
// Set cooldown for both portals
self.cooldown = 60;
self.linkedPortal.cooldown = 60;
return true;
}
return false;
};
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
if (self.cooldown === 0) {
graphics.alpha = 1;
}
} else {
graphics.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal';
self.icon = null;
self.init = function (type) {
self.type = type;
var color = 0xFFFFFF;
var text = 'N';
switch (type) {
case 'explosive':
color = 0xFF4444;
text = 'E';
break;
case 'bouncy':
color = 0x44FF44;
text = 'B';
break;
case 'heavy':
color = 0x444444;
text = 'H';
break;
}
self.icon = self.attachAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
});
self.icon.tint = color;
self.icon.scaleX = 3;
self.icon.scaleY = 3;
var powerText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
powerText.anchor.set(0.5, 0.5);
self.addChild(powerText);
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = GRAVITY;
self.launched = false;
self.destroyed = false;
self.spinSpeed = 0;
self.lastX = 0;
self.lastY = 0;
self.type = 'normal';
self.bounceCount = 0;
self.explosionRadius = 150;
self.launch = function (vx, vy, projectileType) {
self.type = projectileType || 'normal';
self.velocityX = vx;
self.velocityY = vy;
self.launched = true;
// Calculate spin speed based on velocity
self.spinSpeed = Math.sqrt(vx * vx + vy * vy) * 0.02;
// Apply type-specific modifications
switch (self.type) {
case 'explosive':
graphics.tint = 0xFF4444;
self.gravity = GRAVITY * 0.8;
break;
case 'bouncy':
graphics.tint = 0x44FF44;
self.gravity = GRAVITY * 0.9;
break;
case 'heavy':
graphics.tint = 0x444444;
self.gravity = GRAVITY * 1.5;
self.velocityX *= 1.2;
self.velocityY *= 1.2;
graphics.scaleX = 1.3;
graphics.scaleY = 1.3;
break;
default:
graphics.tint = 0xFFFFFF;
}
// Add launch scale animation
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
LK.getSound('launch').play();
};
self.update = function () {
if (self.launched && !self.destroyed) {
// Apply time slow effect
var timeMultiplier = timeSlowActive ? 0.3 : 1.0;
self.x += self.velocityX * timeMultiplier;
self.y += self.velocityY * timeMultiplier;
// Apply gravity based on current gravity state
var currentGravity = gravityReversed ? -self.gravity : self.gravity;
self.velocityY += currentGravity * timeMultiplier;
// Add spinning animation during flight
graphics.rotation += self.spinSpeed;
// Add slight scale pulsing for trail effect
var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
var scaleEffect = 1 + Math.sin(LK.ticks * 0.3) * 0.1 * (speed / 20);
graphics.scaleX = scaleEffect;
graphics.scaleY = scaleEffect;
// Check ground collision with transition detection
if (self.lastY < groundY - 30 && self.y >= groundY - 30) {
self.y = groundY - 30;
self.velocityY = -self.velocityY * 0.3;
self.velocityX *= 0.8;
self.spinSpeed *= 0.8;
LK.getSound('impact').play();
// Add bounce animation
tween(self, {
scaleX: 1.5,
scaleY: 0.7
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
if (Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 1) {
self.launched = false;
self.spinSpeed = 0;
}
}
// Update last position for transition detection
self.lastX = self.x;
self.lastY = self.y;
// Check screen bounds
if (self.x > 2200 || self.x < -100 || self.y > 2800) {
self.destroyed = true;
}
}
};
self.explode = function () {
if (self.type === 'explosive') {
// Create explosion effect
LK.effects.flashScreen(0xFF4444, 300);
LK.getSound('explosion').play();
// Damage all blocks within radius
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed) {
var distance = Math.sqrt((block.x - self.x) * (block.x - self.x) + (block.y - self.y) * (block.y - self.y));
if (distance < self.explosionRadius) {
block.takeDamage();
// Add explosion knockback
tween(block, {
x: block.x + (block.x - self.x) * 0.3,
y: block.y + (block.y - self.y) * 0.3,
rotation: Math.random() * 0.5 - 0.25
}, {
duration: 200,
easing: tween.easeOut
});
}
}
}
// Create particle effect with reduced count
particleSystem.createExplosion(self.x, self.y, 0xFF4444, 6);
}
};
return self;
});
var Slingshot = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('slingshot', {
anchorX: 0.5,
anchorY: 1
});
self.stretched = false;
self.originalRotation = 0;
self.stretch = function (deltaX, deltaY, distance) {
// Calculate stretch angle based on pull direction
var stretchAngle = Math.atan2(deltaY, deltaX) * 0.1;
var stretchAmount = Math.min(distance / 150, 1) * 0.2;
// Play stretch sound
if (distance > 50) {
LK.getSound('woosh').play();
}
// Animate slingshot stretch
tween(self, {
rotation: stretchAngle,
scaleX: 1 + stretchAmount,
scaleY: 1 - stretchAmount * 0.5
}, {
duration: 50,
easing: tween.easeOut
});
self.stretched = true;
};
self.release = function () {
// Dramatic release animation with bounce back
tween(self, {
rotation: self.originalRotation - 0.3,
scaleX: 0.8,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
rotation: self.originalRotation,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.elasticOut
});
}
});
self.stretched = false;
};
self.reset = function () {
// Return to normal state
tween(self, {
rotation: self.originalRotation,
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeOut
});
self.stretched = false;
};
return self;
});
var TargetBlock = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.destroyed = false;
self.magneticType = 'none'; // none, attract, repel
self.magneticStrength = 200;
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
self.destroyed = true;
LK.getSound('destroy').play();
LK.setScore(LK.getScore() + 100);
LK.effects.flashObject(self, 0xFFFFFF, 200);
}
};
self.setMagnetic = function (type) {
self.magneticType = type;
if (type === 'attract') {
graphics.tint = 0x0066FF; // Blue for attraction
// Add pulsing effect
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (type === 'repel') {
graphics.tint = 0xFF0000; // Red for repulsion
// Add pulsing effect
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
};
self.applyMagneticForce = function (projectile) {
if (self.magneticType === 'none' || self.destroyed) return;
var dx = projectile.x - self.x;
var dy = projectile.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.magneticStrength && distance > 0) {
var force = (self.magneticStrength - distance) / self.magneticStrength * 0.5;
var normalizedX = dx / distance;
var normalizedY = dy / distance;
if (self.magneticType === 'attract') {
projectile.velocityX -= normalizedX * force;
projectile.velocityY -= normalizedY * force;
} else if (self.magneticType === 'repel') {
projectile.velocityX += normalizedX * force;
projectile.velocityY += normalizedY * force;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game constants
var GRAVITY = 0.3;
var MAX_DRAG_DISTANCE = 150;
var VELOCITY_MULTIPLIER = 0.3;
var GROUND_Y = 2550;
var INITIAL_SHOTS = 6;
var BLOCK_POINTS = 100;
// Game state management
var gameState = 'intro'; // intro, playing, paused, gameOver
var introScreen = null;
var particleSystem = null;
var achievementSystem = null;
var currentProjectileType = 'normal';
var availablePowerUps = ['normal', 'explosive', 'bouncy', 'heavy'];
var powerUpIndex = 0;
var totalBlocksDestroyed = 0;
var levelsCompleted = 0;
var windSpeed = 0;
var windDirection = 1;
var gravityReversed = false;
var gravityTimer = 0;
var maxGravityTime = 300; // 5 seconds at 60fps
var portals = [];
var timeSlowActive = false;
var timeSlowTimer = 0;
var maxTimeSlowDuration = 180; // 3 seconds
var timeSlowCooldown = 0;
var maxTimeSlowCooldown = 600; // 10 seconds
// Game variables
var slingshot;
var slingshotBase;
var player;
var currentProjectile = null;
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var trajectoryDots = [];
var targetBlocks = [];
var projectiles = [];
var flyingBirds = [];
var birdSpawnTimer = 0;
var shotsRemaining = INITIAL_SHOTS;
var level = 1;
var groundY = GROUND_Y;
// UI elements
var shotsText = new Text2('Atış: 6', {
size: 80,
fill: 0x000000
});
shotsText.anchor.set(0, 0);
LK.gui.topRight.addChild(shotsText);
shotsText.x = -300;
shotsText.y = 100;
var scoreText = new Text2('Puan: 0', {
size: 80,
fill: 0x000000
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
// Create ability indicators
var gravityButton = new Text2('⬆️', {
size: 60,
fill: 0x000000
});
gravityButton.anchor.set(1, 0);
gravityButton.x = -50;
gravityButton.y = 200;
LK.gui.topRight.addChild(gravityButton);
var timeButton = new Text2('⏱️', {
size: 60,
fill: 0x000000
});
timeButton.anchor.set(0.5, 1);
timeButton.x = 0;
timeButton.y = -100;
LK.gui.bottom.addChild(timeButton);
var typeButton = new Text2('💥', {
size: 60,
fill: 0x000000
});
typeButton.anchor.set(0, 0);
typeButton.x = 50;
typeButton.y = 200;
LK.gui.topLeft.addChild(typeButton);
// Create grass ground
var ground = game.addChild(LK.getAsset('grass', {
anchorX: 0.5,
anchorY: 0.5
}));
ground.x = 1024;
ground.y = GROUND_Y + 100; // Position grass lower for better visual effect
ground.scaleY = 1.5; // Make grass thicker
// Create slingshot
slingshotBase = game.addChild(LK.getAsset('slingshotBase', {
anchorX: 0.5,
anchorY: 1
}));
slingshotBase.x = 200;
slingshotBase.y = GROUND_Y;
slingshot = game.addChild(new Slingshot());
slingshot.x = 200;
slingshot.y = GROUND_Y;
// Create player character
player = game.addChild(new Player());
player.x = 80; // Position further behind slingshot
player.y = GROUND_Y;
player.scaleX = 1.2; // Make player more visible
player.scaleY = 1.2;
// Add slingshot asset to player's hand
var playerSlingshot = player.addChild(LK.getAsset('Sapan', {
anchorX: 0.5,
anchorY: 0.8
}));
playerSlingshot.x = 50; // Offset from player center to hand position
playerSlingshot.y = -100; // Offset upward to hand level
playerSlingshot.scaleX = 0.8; // Scale down for better proportion
playerSlingshot.scaleY = 0.8;
// Create trajectory dots
for (var i = 0; i < 15; i++) {
var dot = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
dot.visible = false;
trajectoryDots.push(dot);
}
// Create slingshot grab area indicator
var slingshotArea = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
slingshotArea.x = 200;
slingshotArea.y = GROUND_Y - 100;
slingshotArea.scaleX = 15; // Large enough to show grab area
slingshotArea.scaleY = 15;
slingshotArea.alpha = 0.2;
slingshotArea.tint = 0x00FF00; // Green to indicate interaction area
// Pulse animation for grab area
tween(slingshotArea, {
scaleX: 18,
scaleY: 18,
alpha: 0.1
}, {
duration: 1500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Create target structures
function createLevel() {
// Clear ALL existing targets (both destroyed and non-destroyed)
for (var i = targetBlocks.length - 1; i >= 0; i--) {
targetBlocks[i].destroy();
}
targetBlocks = [];
// Progressive difficulty and varied level designs
var levelPattern = level % 8; // Increased variety
var startX = Math.min(1400, 1700); // Ensure starting position doesn't go too far right
var startY = GROUND_Y - 50;
// Procedural generation for levels beyond 20
if (level > 20) {
// Generate random but balanced structures - limited to 5 blocks
var blockCount = 5;
var maxHeight = 5 + Math.floor(level / 10);
for (var i = 0; i < blockCount; i++) {
var block = game.addChild(new TargetBlock());
// Constrain X position to stay within screen (100px margin on each side)
block.x = Math.max(100, Math.min(1948, startX + (Math.random() - 0.5) * 400));
// Constrain Y position to stay above ground and below top of screen
block.y = Math.max(200, Math.min(startY, startY - Math.random() * maxHeight * 110));
targetBlocks.push(block);
}
return; // Skip normal level patterns
}
// Add wind effect for higher levels
if (level > 10) {
windSpeed = (Math.random() - 0.5) * 2;
windDirection = windSpeed > 0 ? 1 : -1;
// Show wind indicator
var windText = new Text2('Rüzgar: ' + (windSpeed > 0 ? '→' : '←'), {
size: 60,
fill: 0x0066CC
});
windText.anchor.set(0.5, 0);
windText.x = 1024;
windText.y = 300;
LK.gui.top.addChild(windText);
LK.setTimeout(function () {
windText.destroy();
}, 3000);
} else {
windSpeed = 0;
}
switch (levelPattern) {
case 0:
// Compact pyramid - 5 blocks - ensure all blocks fit on screen
var safeStartX = Math.min(startX, 1700); // Leave room for 3 blocks (240px width)
// Bottom row
for (var i = 0; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + i * 80;
block.y = startY;
targetBlocks.push(block);
}
// Top row
for (var i = 0; i < 2; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + 40 + i * 80;
block.y = startY - 80;
targetBlocks.push(block);
}
break;
case 1:
// Compact wall formation - 5 blocks
var safeStartX = Math.min(startX, 1788); // Leave room for 3 blocks wide (240px)
for (var i = 0; i < 5; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + i % 3 * 80;
block.y = startY - Math.floor(i / 3) * 80;
targetBlocks.push(block);
}
break;
case 2:
// Compact L-shape - 5 blocks
var safeStartX = Math.min(startX, 1700); // Leave room for 3 blocks wide (240px)
// Horizontal part
for (var i = 0; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + i * 80;
block.y = startY;
targetBlocks.push(block);
}
// Vertical part
for (var i = 1; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX;
block.y = startY - i * 80;
targetBlocks.push(block);
}
break;
case 3:
// Compact cluster - 5 blocks
var safeStartX = Math.min(startX, 1668); // Leave room for widest position (160px total)
var positions = [{
x: 0,
y: 0
}, {
x: 80,
y: 0
}, {
x: 40,
y: -80
}, {
x: 120,
y: -40
}, {
x: -40,
y: -40
}];
for (var i = 0; i < positions.length; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + positions[i].x;
block.y = startY + positions[i].y;
targetBlocks.push(block);
}
break;
case 4:
// Compact tower - 5 blocks in vertical line
var safeStartX = Math.min(startX, 1898); // Single column needs less room
for (var i = 0; i < 5; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX;
block.y = startY - i * 80;
targetBlocks.push(block);
}
break;
case 5:
// Compact spiral - 5 blocks
var centerX = Math.min(startX + 80, 1800); // Keep spiral center safe
var centerY = startY - 80;
for (var i = 0; i < 5; i++) {
var angle = i * 1.0;
var radius = 20 + i * 15;
var block = game.addChild(new TargetBlock());
// Constrain spiral positions to screen bounds
block.x = Math.max(150, Math.min(1898, centerX + Math.cos(angle) * radius));
block.y = Math.max(200, centerY + Math.sin(angle) * radius);
targetBlocks.push(block);
}
break;
case 6:
// Compact cross - 5 blocks
var safeStartX = Math.min(startX, 1728); // Leave room for 160px wide cross
// Center
var block = game.addChild(new TargetBlock());
block.x = safeStartX + 80;
block.y = startY - 80;
targetBlocks.push(block);
// Cross arms
for (var i = 0; i < 4; i++) {
var block = game.addChild(new TargetBlock());
if (i < 2) {
block.x = safeStartX + i * 160;
block.y = startY - 80;
} else {
block.x = safeStartX + 80;
block.y = startY - (i - 1) * 80;
}
targetBlocks.push(block);
}
break;
case 7:
// Compact diamond - 5 blocks
var safeStartX = Math.min(startX, 1768); // Leave room for 160px wide diamond
var positions = [{
x: 80,
y: -40
}, {
x: 40,
y: -80
}, {
x: 120,
y: -80
}, {
x: 80,
y: -120
}, {
x: 80,
y: 0
}];
for (var i = 0; i < positions.length; i++) {
var block = game.addChild(new TargetBlock());
block.x = safeStartX + positions[i].x;
block.y = startY + positions[i].y;
targetBlocks.push(block);
}
break;
}
// Add special blocks for higher levels
if (level > 5) {
// Some blocks require multiple hits
var specialBlockCount = Math.min(Math.floor(level / 5), 3);
for (var i = 0; i < specialBlockCount && i < targetBlocks.length; i++) {
var specialBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)];
specialBlock.health = 2;
// Visual indicator for special blocks
tween(specialBlock, {
tint: 0xFF6600
}, {
duration: 500,
easing: tween.easeInOut
});
specialBlock.scaleX = 1.1;
specialBlock.scaleY = 1.1;
}
}
// Add magnetic blocks for higher levels
if (level > 8) {
var magneticBlockCount = Math.min(Math.floor(level / 8), 2);
for (var i = 0; i < magneticBlockCount && i < targetBlocks.length; i++) {
var magneticBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)];
var magneticType = Math.random() > 0.5 ? 'attract' : 'repel';
magneticBlock.setMagnetic(magneticType);
}
}
// Add portals for very high levels
if (level > 12) {
// Clear existing portals
for (var i = 0; i < portals.length; i++) {
portals[i].destroy();
}
portals = [];
// Create portal pairs - constrain to screen bounds
var portal1 = game.addChild(new Portal());
portal1.x = Math.max(150, Math.min(1898, 600 + Math.random() * 200));
portal1.y = Math.max(300, GROUND_Y - 200 - Math.random() * 300);
var portal2 = game.addChild(new Portal());
portal2.x = Math.max(150, Math.min(1898, 1400 + Math.random() * 200));
portal2.y = Math.max(300, GROUND_Y - 200 - Math.random() * 300);
// Link portals
portal1.linkedPortal = portal2;
portal2.linkedPortal = portal1;
portals.push(portal1, portal2);
}
}
// Initialize game systems
particleSystem = new ParticleSystem();
achievementSystem = new AchievementSystem();
achievementSystem.loadAchievements();
// Load saved progress
level = storage.currentLevel || 1;
totalBlocksDestroyed = storage.totalBlocksDestroyed || 0;
levelsCompleted = storage.levelsCompleted || 0;
// Show intro screen
introScreen = game.addChild(new IntroScreen());
introScreen.show();
// Game control functions
function startGame() {
gameState = 'playing';
introScreen.hide(function () {
introScreen.destroy();
introScreen = null;
createLevel();
// Start background music immediately when game starts
LK.playMusic('angrybirds', {
volume: 1.0
});
});
}
function showSettings() {
// Create settings overlay
var settingsOverlay = game.addChild(LK.getAsset('grass', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x000000,
alpha: 0.9
}));
settingsOverlay.width = 2048;
settingsOverlay.height = 2732;
settingsOverlay.x = 1024;
settingsOverlay.y = 1366;
// Title
var titleText = new Text2('AYARLAR', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
// Load saved settings
var savedMusicVolume = storage.musicVolume || 1.0;
var savedSoundVolume = storage.soundVolume || 1.0;
var savedGraphicsQuality = storage.graphicsQuality || 'high';
var savedAutoAim = storage.autoAim || false;
// Music Volume Section
var musicVolumeText = new Text2('Müzik Ses Seviyesi: ' + Math.round(savedMusicVolume * 100) + '%', {
size: 60,
fill: 0xFFFFFF
});
musicVolumeText.anchor.set(0.5, 0.5);
musicVolumeText.x = 1024;
musicVolumeText.y = 800;
game.addChild(musicVolumeText);
// Music volume slider background
var musicSliderBg = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
musicSliderBg.x = 1024;
musicSliderBg.y = 900;
musicSliderBg.scaleX = 6;
musicSliderBg.scaleY = 0.5;
musicSliderBg.tint = 0x666666;
// Music volume slider handle
var musicSliderHandle = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
musicSliderHandle.x = 1024 - 300 + savedMusicVolume * 600;
musicSliderHandle.y = 900;
musicSliderHandle.scaleX = 4;
musicSliderHandle.scaleY = 4;
musicSliderHandle.tint = 0x4CAF50;
// Sound Effects Volume Section
var soundVolumeText = new Text2('Efekt Ses Seviyesi: ' + Math.round(savedSoundVolume * 100) + '%', {
size: 60,
fill: 0xFFFFFF
});
soundVolumeText.anchor.set(0.5, 0.5);
soundVolumeText.x = 1024;
soundVolumeText.y = 1050;
game.addChild(soundVolumeText);
// Sound volume slider background
var soundSliderBg = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
soundSliderBg.x = 1024;
soundSliderBg.y = 1150;
soundSliderBg.scaleX = 6;
soundSliderBg.scaleY = 0.5;
soundSliderBg.tint = 0x666666;
// Sound volume slider handle
var soundSliderHandle = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
soundSliderHandle.x = 1024 - 300 + savedSoundVolume * 600;
soundSliderHandle.y = 1150;
soundSliderHandle.scaleX = 4;
soundSliderHandle.scaleY = 4;
soundSliderHandle.tint = 0x4CAF50;
// Graphics Quality Section
var graphicsText = new Text2('Grafik Kalitesi: ' + savedGraphicsQuality.toUpperCase(), {
size: 60,
fill: 0xFFFFFF
});
graphicsText.anchor.set(0.5, 0.5);
graphicsText.x = 1024;
graphicsText.y = 1300;
game.addChild(graphicsText);
var graphicsButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
graphicsButton.x = 1024;
graphicsButton.y = 1400;
graphicsButton.scaleX = 3;
graphicsButton.scaleY = 1;
graphicsButton.tint = 0x2196F3;
var graphicsButtonText = new Text2('DEĞİŞTİR', {
size: 50,
fill: 0xFFFFFF
});
graphicsButtonText.anchor.set(0.5, 0.5);
graphicsButtonText.x = 1024;
graphicsButtonText.y = 1400;
game.addChild(graphicsButtonText);
// Auto-Aim Section
var autoAimText = new Text2('Otomatik Nişan: ' + (savedAutoAim ? 'AÇIK' : 'KAPALI'), {
size: 60,
fill: 0xFFFFFF
});
autoAimText.anchor.set(0.5, 0.5);
autoAimText.x = 1024;
autoAimText.y = 1550;
game.addChild(autoAimText);
var autoAimButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
autoAimButton.x = 1024;
autoAimButton.y = 1650;
autoAimButton.scaleX = 3;
autoAimButton.scaleY = 1;
autoAimButton.tint = savedAutoAim ? 0x4CAF50 : 0xFF5722;
var autoAimButtonText = new Text2('DEĞIŞTIR', {
size: 50,
fill: 0xFFFFFF
});
autoAimButtonText.anchor.set(0.5, 0.5);
autoAimButtonText.x = 1024;
autoAimButtonText.y = 1650;
game.addChild(autoAimButtonText);
// Reset Progress Section
var resetButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
resetButton.x = 1024;
resetButton.y = 1800;
resetButton.scaleX = 3;
resetButton.scaleY = 1.2;
resetButton.tint = 0xFF5722;
var resetText = new Text2('İLERLEMEYİ SIFIRLA', {
size: 50,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5, 0.5);
resetText.x = 1024;
resetText.y = 1800;
game.addChild(resetText);
// Close button
var closeButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.x = 1024;
closeButton.y = 2000;
closeButton.scaleX = 2;
closeButton.scaleY = 1.2;
closeButton.tint = 0x4CAF50;
var closeText = new Text2('KAPAT', {
size: 80,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 2000;
game.addChild(closeText);
// Event handlers
var isDraggingMusic = false;
var isDraggingSound = false;
// Music slider interaction
musicSliderHandle.down = function (x, y, obj) {
isDraggingMusic = true;
};
// Sound slider interaction
soundSliderHandle.down = function (x, y, obj) {
isDraggingSound = true;
};
// Graphics quality toggle
graphicsButton.down = function (x, y, obj) {
var qualities = ['low', 'medium', 'high'];
var currentIndex = qualities.indexOf(savedGraphicsQuality);
savedGraphicsQuality = qualities[(currentIndex + 1) % qualities.length];
storage.graphicsQuality = savedGraphicsQuality;
graphicsText.setText('Grafik Kalitesi: ' + savedGraphicsQuality.toUpperCase());
};
// Auto-aim toggle
autoAimButton.down = function (x, y, obj) {
savedAutoAim = !savedAutoAim;
storage.autoAim = savedAutoAim;
autoAimText.setText('Otomatik Nişan: ' + (savedAutoAim ? 'AÇIK' : 'KAPALI'));
autoAimButton.tint = savedAutoAim ? 0x4CAF50 : 0xFF5722;
};
// Reset progress
resetButton.down = function (x, y, obj) {
storage.currentLevel = 1;
storage.totalBlocksDestroyed = 0;
storage.levelsCompleted = 0;
storage.achievements = {};
level = 1;
totalBlocksDestroyed = 0;
levelsCompleted = 0;
// Show confirmation
var confirmText = new Text2('İlerleme sıfırlandı!', {
size: 60,
fill: 0xFF0000
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = 1024;
confirmText.y = 1900;
game.addChild(confirmText);
LK.setTimeout(function () {
confirmText.destroy();
}, 2000);
};
// Close settings
closeButton.down = function (x, y, obj) {
settingsOverlay.destroy();
titleText.destroy();
musicVolumeText.destroy();
musicSliderBg.destroy();
musicSliderHandle.destroy();
soundVolumeText.destroy();
soundSliderBg.destroy();
soundSliderHandle.destroy();
graphicsText.destroy();
graphicsButton.destroy();
graphicsButtonText.destroy();
autoAimText.destroy();
autoAimButton.destroy();
autoAimButtonText.destroy();
resetButton.destroy();
resetText.destroy();
closeButton.destroy();
closeText.destroy();
};
// Global move handler for sliders
settingsOverlay.move = function (x, y, obj) {
if (isDraggingMusic) {
var sliderX = Math.max(724, Math.min(1324, x));
musicSliderHandle.x = sliderX;
savedMusicVolume = (sliderX - 724) / 600;
storage.musicVolume = savedMusicVolume;
musicVolumeText.setText('Müzik Ses Seviyesi: ' + Math.round(savedMusicVolume * 100) + '%');
}
if (isDraggingSound) {
var sliderX = Math.max(724, Math.min(1324, x));
soundSliderHandle.x = sliderX;
savedSoundVolume = (sliderX - 724) / 600;
storage.soundVolume = savedSoundVolume;
soundVolumeText.setText('Efekt Ses Seviyesi: ' + Math.round(savedSoundVolume * 100) + '%');
}
};
// Global up handler to stop dragging
settingsOverlay.up = function (x, y, obj) {
isDraggingMusic = false;
isDraggingSound = false;
};
}
function showLevelSelector() {
// Create level selector overlay
var levelOverlay = game.addChild(LK.getAsset('grass', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x000000,
alpha: 0.9
}));
levelOverlay.width = 2048;
levelOverlay.height = 2732;
levelOverlay.x = 1024;
levelOverlay.y = 1366;
// Title
var titleText = new Text2('BÖLÜMLER', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
// Load saved progress
var unlockedLevel = storage.currentLevel || 1;
var completedLevels = storage.completedLevels || {};
var levelStars = storage.levelStars || {};
// Progress indicator
var progressText = new Text2('İlerleme: ' + Math.max(1, unlockedLevel - 1) + '/50 Bölüm', {
size: 60,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 1024;
progressText.y = 500;
game.addChild(progressText);
// Continue button (jump to furthest level)
var continueButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
continueButton.x = 1024;
continueButton.y = 600;
continueButton.scaleX = 3;
continueButton.scaleY = 1.2;
continueButton.tint = 0x4CAF50;
var continueText = new Text2('DEVAM ET (Bölüm ' + unlockedLevel + ')', {
size: 50,
fill: 0xFFFFFF
});
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 600;
game.addChild(continueText);
// Level grid setup
var startY = 750;
var levelsPerRow = 5;
var buttonSize = 120;
var buttonSpacing = 150;
var rowSpacing = 140;
var maxLevels = 50;
var currentPage = 0;
var levelsPerPage = 15; // 3 rows x 5 columns
// Page indicator
var pageText = new Text2('Sayfa ' + (currentPage + 1) + '/' + Math.ceil(maxLevels / levelsPerPage), {
size: 50,
fill: 0xFFFFFF
});
pageText.anchor.set(0.5, 0.5);
pageText.x = 1024;
pageText.y = 700;
game.addChild(pageText);
// Level buttons array for cleanup
var levelButtons = [];
var levelTexts = [];
var starTexts = [];
function createLevelGrid() {
// Clear existing level buttons
for (var i = 0; i < levelButtons.length; i++) {
if (levelButtons[i]) levelButtons[i].destroy();
if (levelTexts[i]) levelTexts[i].destroy();
if (starTexts[i]) starTexts[i].destroy();
}
levelButtons = [];
levelTexts = [];
starTexts = [];
// Create level buttons for current page
for (var i = 0; i < levelsPerPage; i++) {
var levelNum = currentPage * levelsPerPage + i + 1;
if (levelNum > maxLevels) break;
var row = Math.floor(i / levelsPerRow);
var col = i % levelsPerRow;
var buttonX = 1024 - (levelsPerRow - 1) * buttonSpacing / 2 + col * buttonSpacing;
var buttonY = startY + row * rowSpacing;
// Level button
var isUnlocked = levelNum <= unlockedLevel;
var isCompleted = completedLevels[levelNum] || false;
var stars = levelStars[levelNum] || 0;
var levelButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
levelButton.x = buttonX;
levelButton.y = buttonY;
levelButton.scaleX = buttonSize / 100;
levelButton.scaleY = buttonSize / 100;
// Color coding
if (!isUnlocked) {
levelButton.tint = 0x666666; // Gray for locked
levelButton.alpha = 0.5;
} else if (isCompleted) {
levelButton.tint = 0xFFD700; // Gold for completed
} else if (levelNum === unlockedLevel) {
levelButton.tint = 0x4CAF50; // Green for current
} else {
levelButton.tint = 0x2196F3; // Blue for available
}
// Level number text
var levelText = new Text2(levelNum.toString(), {
size: 40,
fill: isUnlocked ? 0x000000 : 0x999999
});
levelText.anchor.set(0.5, 0.5);
levelText.x = buttonX;
levelText.y = buttonY - 10;
game.addChild(levelText);
// Star rating
var starText = new Text2('★'.repeat(stars), {
size: 25,
fill: 0xFFD700
});
starText.anchor.set(0.5, 0.5);
starText.x = buttonX;
starText.y = buttonY + 25;
game.addChild(starText);
// Store references
levelButtons.push(levelButton);
levelTexts.push(levelText);
starTexts.push(starText);
// Add click handler for unlocked levels
if (isUnlocked) {
levelButton.levelNumber = levelNum;
levelButton.down = function (x, y, obj) {
// Start selected level
level = obj.levelNumber;
storage.currentLevel = level;
closeSelector();
startGame();
};
}
}
}
// Navigation buttons
var prevButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
prevButton.x = 300;
prevButton.y = 1200;
prevButton.scaleX = 1.5;
prevButton.scaleY = 1;
prevButton.tint = currentPage > 0 ? 0xFF9800 : 0x666666;
var prevText = new Text2('◀', {
size: 60,
fill: 0xFFFFFF
});
prevText.anchor.set(0.5, 0.5);
prevText.x = 300;
prevText.y = 1200;
game.addChild(prevText);
var nextButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
nextButton.x = 1748;
nextButton.y = 1200;
nextButton.scaleX = 1.5;
nextButton.scaleY = 1;
nextButton.tint = currentPage < Math.ceil(maxLevels / levelsPerPage) - 1 ? 0xFF9800 : 0x666666;
var nextText = new Text2('▶', {
size: 60,
fill: 0xFFFFFF
});
nextText.anchor.set(0.5, 0.5);
nextText.x = 1748;
nextText.y = 1200;
game.addChild(nextText);
// Navigation handlers
prevButton.down = function (x, y, obj) {
if (currentPage > 0) {
currentPage--;
updateNavigation();
createLevelGrid();
}
};
nextButton.down = function (x, y, obj) {
if (currentPage < Math.ceil(maxLevels / levelsPerPage) - 1) {
currentPage++;
updateNavigation();
createLevelGrid();
}
};
function updateNavigation() {
prevButton.tint = currentPage > 0 ? 0xFF9800 : 0x666666;
nextButton.tint = currentPage < Math.ceil(maxLevels / levelsPerPage) - 1 ? 0xFF9800 : 0x666666;
pageText.setText('Sayfa ' + (currentPage + 1) + '/' + Math.ceil(maxLevels / levelsPerPage));
}
// Difficulty filter
var filterText = new Text2('Zorluk Filtresi:', {
size: 50,
fill: 0xFFFFFF
});
filterText.anchor.set(0.5, 0.5);
filterText.x = 1024;
filterText.y = 1350;
game.addChild(filterText);
var filters = ['Tümü', 'Kolay', 'Orta', 'Zor'];
var currentFilter = 0;
var filterButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
filterButton.x = 1024;
filterButton.y = 1420;
filterButton.scaleX = 2.5;
filterButton.scaleY = 1;
filterButton.tint = 0x9C27B0;
var filterLabel = new Text2(filters[currentFilter], {
size: 45,
fill: 0xFFFFFF
});
filterLabel.anchor.set(0.5, 0.5);
filterLabel.x = 1024;
filterLabel.y = 1420;
game.addChild(filterLabel);
filterButton.down = function (x, y, obj) {
currentFilter = (currentFilter + 1) % filters.length;
filterLabel.setText(filters[currentFilter]);
// Apply filter logic here - simplified for now
createLevelGrid();
};
// World selector
var worldText = new Text2('Dünya: Normal', {
size: 50,
fill: 0xFFFFFF
});
worldText.anchor.set(0.5, 0.5);
worldText.x = 1024;
worldText.y = 1500;
game.addChild(worldText);
// Achievement showcase
var achievementText = new Text2('Kazanımlar: ' + Object.keys(storage.achievements || {}).length + '/4', {
size: 45,
fill: 0xFFD700
});
achievementText.anchor.set(0.5, 0.5);
achievementText.x = 1024;
achievementText.y = 1580;
game.addChild(achievementText);
// Continue button handler
continueButton.down = function (x, y, obj) {
level = unlockedLevel;
storage.currentLevel = level;
closeSelector();
startGame();
};
// Close button
var closeButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.x = 1024;
closeButton.y = 1700;
closeButton.scaleX = 2;
closeButton.scaleY = 1.2;
closeButton.tint = 0x4CAF50;
var closeText = new Text2('KAPAT', {
size: 80,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 1700;
game.addChild(closeText);
function closeSelector() {
// Clean up all elements
levelOverlay.destroy();
titleText.destroy();
progressText.destroy();
continueButton.destroy();
continueText.destroy();
pageText.destroy();
prevButton.destroy();
prevText.destroy();
nextButton.destroy();
nextText.destroy();
filterText.destroy();
filterButton.destroy();
filterLabel.destroy();
worldText.destroy();
achievementText.destroy();
closeButton.destroy();
closeText.destroy();
// Clean up level buttons
for (var i = 0; i < levelButtons.length; i++) {
if (levelButtons[i]) levelButtons[i].destroy();
if (levelTexts[i]) levelTexts[i].destroy();
if (starTexts[i]) starTexts[i].destroy();
}
}
closeButton.down = function (x, y, obj) {
closeSelector();
};
// Initialize the grid
createLevelGrid();
}
function showHowToPlay() {
// Create overlay for instructions
var instructionOverlay = game.addChild(LK.getAsset('grass', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x000000,
alpha: 0.9
}));
instructionOverlay.width = 2048;
instructionOverlay.height = 2732;
instructionOverlay.x = 1024;
instructionOverlay.y = 1366;
// Title
var titleText = new Text2('NASIL OYNANIR', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
// Instructions
var instructions = ['🎯 AMAÇ: Tüm blokları yok et', '🏹 ATIŞ: Sapanı çek ve bırak', '⭐ TİPLER:', ' • Normal: Temel mermi', ' • Patlayıcı (E): Çevresi hasar', ' • Zıplayan (B): Sekme özelliği', ' • Ağır (H): Güçlü darbe', '🔄 ÖZEL YETENEKLER:', ' • Yerçekimi kontrolü (6+ seviye)', ' • Zaman yavaşlatma (10+ seviye)', '💫 PORTAL: Mermileri ışınlar', '🧲 MANYETİK: Mavi çeker, kırmızı iter'];
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 800 + i * 70;
game.addChild(instructionText);
}
// Close button
var closeButton = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.x = 1024;
closeButton.y = 2200;
closeButton.scaleX = 2;
closeButton.scaleY = 1.2;
closeButton.tint = 0x4CAF50;
var closeText = new Text2('KAPAT', {
size: 80,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 2200;
game.addChild(closeText);
// Close functionality
closeButton.down = function (x, y, obj) {
// Clean up all instruction elements
instructionOverlay.destroy();
titleText.destroy();
closeButton.destroy();
closeText.destroy();
// Clean up instruction texts
for (var j = 0; j < instructions.length; j++) {
// Find and destroy instruction texts
for (var k = game.children.length - 1; k >= 0; k--) {
var child = game.children[k];
if (child.constructor === Text2 && child.y >= 800 && child.y <= 1600) {
child.destroy();
}
}
}
};
}
function switchProjectileType() {
powerUpIndex = (powerUpIndex + 1) % availablePowerUps.length;
currentProjectileType = availablePowerUps[powerUpIndex];
// Update UI to show current projectile type
var typeText = new Text2('Tip: ' + currentProjectileType.toUpperCase(), {
size: 60,
fill: 0x000000
});
typeText.anchor.set(0.5, 0);
typeText.x = 1024;
typeText.y = 200;
LK.gui.top.addChild(typeText);
// Remove after 2 seconds
LK.setTimeout(function () {
typeText.destroy();
}, 2000);
}
// Don't initialize level if we're showing intro
// createLevel();
// Helper functions
function calculateTrajectory(startX, startY, velocityX, velocityY) {
var points = [];
var x = startX;
var y = startY;
var vx = velocityX;
var vy = velocityY;
var timeStep = 2;
var gravity = GRAVITY * timeStep;
for (var i = 0; i < 15; i++) {
points.push({
x: x,
y: y
});
x += vx * timeStep;
y += vy * timeStep;
vy += gravity;
if (y >= GROUND_Y - 30) break;
}
return points;
}
function updateTrajectoryDisplay(points) {
for (var i = 0; i < trajectoryDots.length; i++) {
if (i < points.length) {
trajectoryDots[i].x = points[i].x;
trajectoryDots[i].y = points[i].y;
trajectoryDots[i].visible = true;
} else {
trajectoryDots[i].visible = false;
}
}
}
function hideTrajectoryDisplay() {
for (var i = 0; i < trajectoryDots.length; i++) {
trajectoryDots[i].visible = false;
}
}
function checkProjectileCollisions(projectile) {
var hitSomething = false;
var blocksDestroyed = 0;
// Apply magnetic forces from all blocks
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed && block.magneticType !== 'none') {
block.applyMagneticForce(projectile);
}
}
// Check portal teleportation
for (var i = 0; i < portals.length; i++) {
if (portals[i].teleport(projectile)) {
break; // Only one teleport per frame
}
}
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed && projectile.intersects(block)) {
var wasDestroyed = block.destroyed;
block.takeDamage();
if (!wasDestroyed && block.destroyed) {
blocksDestroyed++;
totalBlocksDestroyed++;
storage.totalBlocksDestroyed = totalBlocksDestroyed;
// Create destruction particles
particleSystem.createExplosion(block.x, block.y, 0xFFFFFF, 8);
}
LK.getSound('impact').play();
hitSomething = true;
// Type-specific collision effects
switch (projectile.type) {
case 'explosive':
projectile.explode();
projectile.destroyed = true;
return true;
case 'bouncy':
projectile.velocityX *= -0.8;
projectile.velocityY *= -0.8;
projectile.bounceCount++;
if (projectile.bounceCount <= 3) {
LK.getSound('bounce').play();
}
if (projectile.bounceCount < 3) {
// Add bounce particle effect
particleSystem.createExplosion(projectile.x, projectile.y, 0x44FF44, 5);
}
break;
case 'heavy':
// Heavy projectiles don't bounce much and continue through
projectile.velocityX *= -0.1;
projectile.velocityY *= -0.1;
break;
default:
// Normal projectile behavior
projectile.velocityX *= -0.2;
projectile.velocityY *= -0.2;
break;
}
// Add some randomness to bounce
projectile.velocityX += (Math.random() - 0.5) * 2;
projectile.velocityY += (Math.random() - 0.5) * 2;
if (block.destroyed) {
player.celebrate(); // Player celebrates when destroying a block
}
}
}
// Check achievements
if (blocksDestroyed >= 5) {
achievementSystem.checkAchievement('oneShot', blocksDestroyed);
}
achievementSystem.checkAchievement('destructionMaster', totalBlocksDestroyed);
return hitSomething;
}
function checkLevelComplete() {
var remainingBlocks = 0;
for (var i = 0; i < targetBlocks.length; i++) {
if (!targetBlocks[i].destroyed) {
remainingBlocks++;
}
}
if (remainingBlocks === 0) {
// Level complete - restart with new level
var shotsUsed = INITIAL_SHOTS - shotsRemaining;
// Calculate star rating
var stars = 3;
if (shotsUsed > 2) stars = 2;
if (shotsUsed > 3) stars = 1;
// Save level completion data
var completedLevels = storage.completedLevels || {};
var levelStars = storage.levelStars || {};
completedLevels[level] = true;
levelStars[level] = Math.max(levelStars[level] || 0, stars); // Keep best star rating
storage.completedLevels = completedLevels;
storage.levelStars = levelStars;
level++;
levelsCompleted++;
storage.currentLevel = level;
storage.levelsCompleted = levelsCompleted;
// Check for perfect shot achievement
if (shotsUsed === 1) {
achievementSystem.checkAchievement('perfectShot', 1);
}
// Check level completion achievement
achievementSystem.checkAchievement('sharpshooter', levelsCompleted);
// Enhanced level complete message with star display
var completeText = new Text2('Bölüm ' + (level - 1) + ' Tamamlandı!', {
size: 80,
fill: 0xFFD700
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 1024;
completeText.y = 950;
completeText.alpha = 0;
game.addChild(completeText);
var starDisplayText = new Text2('★'.repeat(stars) + '☆'.repeat(3 - stars), {
size: 100,
fill: 0xFFD700
});
starDisplayText.anchor.set(0.5, 0.5);
starDisplayText.x = 1024;
starDisplayText.y = 1050;
starDisplayText.alpha = 0;
game.addChild(starDisplayText);
var shotsUsedText = new Text2('Kullanılan Atış: ' + shotsUsed + '/' + INITIAL_SHOTS, {
size: 60,
fill: 0xFFFFFF
});
shotsUsedText.anchor.set(0.5, 0.5);
shotsUsedText.x = 1024;
shotsUsedText.y = 1150;
shotsUsedText.alpha = 0;
game.addChild(shotsUsedText);
// Animate in all elements
tween(completeText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(starDisplayText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 700,
delay: 300,
easing: tween.bounceOut
});
tween(shotsUsedText, {
alpha: 1
}, {
duration: 500,
delay: 600,
easing: tween.easeOut
});
shotsRemaining = INITIAL_SHOTS;
shotsText.setText('Atış: ' + shotsRemaining);
LK.setTimeout(function () {
tween(completeText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
completeText.destroy();
}
});
tween(starDisplayText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
starDisplayText.destroy();
}
});
tween(shotsUsedText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
shotsUsedText.destroy();
}
});
createLevel();
}, 3000);
return true;
}
if (shotsRemaining <= 0 && projectiles.length === 0) {
// Only show game over if there are still blocks remaining
var remainingBlocks = 0;
for (var i = 0; i < targetBlocks.length; i++) {
if (!targetBlocks[i].destroyed) {
remainingBlocks++;
}
}
if (remainingBlocks > 0) {
// Show game over only if level is not complete
LK.showGameOver();
return true;
}
}
return false;
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
// Double tap to switch projectile type
if (!currentProjectile && shotsRemaining > 0) {
var distance = Math.sqrt((x - slingshot.x) * (x - slingshot.x) + (y - slingshot.y) * (y - slingshot.y));
// Check if clicking on projectile type indicator (top left area)
if (x < 300 && y < 300) {
switchProjectileType();
return;
}
// Check if clicking on gravity control (top right area)
if (x > 1748 && y < 300) {
if (level > 6) {
// Unlock gravity control after level 6
gravityReversed = !gravityReversed;
gravityTimer = maxGravityTime;
// Visual feedback
var gravityText = new Text2('Yerçekimi: ' + (gravityReversed ? 'TERS' : 'NORMAL'), {
size: 60,
fill: gravityReversed ? 0xFF0000 : 0x00FF00
});
gravityText.anchor.set(0.5, 0);
gravityText.x = 1024;
gravityText.y = 250;
LK.gui.top.addChild(gravityText);
LK.setTimeout(function () {
gravityText.destroy();
}, 2000);
LK.effects.flashScreen(gravityReversed ? 0xFF0000 : 0x0000FF, 300);
}
return;
}
// Check if clicking on time control (bottom center area)
if (x > 924 && x < 1124 && y > 2500) {
if (level > 10 && timeSlowCooldown === 0 && !timeSlowActive) {
// Unlock time control after level 10
timeSlowActive = true;
timeSlowTimer = maxTimeSlowDuration;
timeSlowCooldown = maxTimeSlowCooldown;
// Visual feedback
var timeText = new Text2('ZAMAN YAVAŞ!', {
size: 80,
fill: 0x00FFFF
});
timeText.anchor.set(0.5, 0);
timeText.x = 1024;
timeText.y = 350;
LK.gui.top.addChild(timeText);
LK.setTimeout(function () {
timeText.destroy();
}, 1000);
LK.effects.flashScreen(0x00FFFF, 400);
}
return;
}
if (distance < 250) {
// Increased from 150 to 250 for easier grabbing
isAiming = true;
aimStartX = x;
aimStartY = y;
currentProjectile = game.addChild(new Projectile());
currentProjectile.x = slingshot.x;
currentProjectile.y = slingshot.y - 100;
currentProjectile.type = currentProjectileType;
// Visual feedback for successful grab
LK.effects.flashObject(slingshot, 0x00FF00, 200);
// Scale animation to show projectile is grabbed
tween(currentProjectile, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
player.aim(); // Player leans forward when aiming
}
}
};
game.move = function (x, y, obj) {
if (isAiming && currentProjectile) {
var deltaX = aimStartX - x;
var deltaY = aimStartY - y;
// Restrict aiming to forward direction only (positive deltaX means forward)
if (deltaX < 0) {
deltaX = 0; // Don't allow backward aiming
}
// Limit drag distance
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > MAX_DRAG_DISTANCE) {
deltaX = deltaX / distance * MAX_DRAG_DISTANCE;
deltaY = deltaY / distance * MAX_DRAG_DISTANCE;
distance = MAX_DRAG_DISTANCE;
}
// Smooth projectile following with magnetic snap to slingshot
var targetX = slingshot.x - deltaX * 0.5;
var targetY = slingshot.y - 100 - deltaY * 0.5;
// If very close to slingshot, snap to it for better control
if (distance < 30) {
targetX = slingshot.x;
targetY = slingshot.y - 100;
}
// Smooth interpolation for better feel
currentProjectile.x += (targetX - currentProjectile.x) * 0.8;
currentProjectile.y += (targetY - currentProjectile.y) * 0.8;
// Animate slingshot stretch
slingshot.stretch(deltaX, deltaY, distance);
// Calculate and show trajectory
var velocityX = deltaX * VELOCITY_MULTIPLIER;
var velocityY = deltaY * VELOCITY_MULTIPLIER;
var trajectoryPoints = calculateTrajectory(currentProjectile.x, currentProjectile.y, velocityX, velocityY);
updateTrajectoryDisplay(trajectoryPoints);
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
if (isAiming && currentProjectile) {
var deltaX = aimStartX - x;
var deltaY = aimStartY - y;
// Restrict aiming to forward direction only (positive deltaX means forward)
if (deltaX < 0) {
deltaX = 0; // Don't allow backward shooting
}
// Limit drag distance
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > MAX_DRAG_DISTANCE) {
deltaX = deltaX / distance * MAX_DRAG_DISTANCE;
deltaY = deltaY / distance * MAX_DRAG_DISTANCE;
}
if (distance > 10 && deltaX > 0) {
// Reduced from 20 to 10 for easier shooting
// Only shoot if there's forward movement
var velocityX = deltaX * VELOCITY_MULTIPLIER;
var velocityY = deltaY * VELOCITY_MULTIPLIER;
// Apply wind effect
velocityX += windSpeed;
// Animate slingshot release
slingshot.release();
// Add screen flash effect for dramatic launch
LK.effects.flashScreen(0xFFFFFF, 200);
currentProjectile.launch(velocityX, velocityY, currentProjectileType);
currentProjectile.lastX = currentProjectile.x;
currentProjectile.lastY = currentProjectile.y;
projectiles.push(currentProjectile);
shotsRemaining--;
shotsText.setText('Atış: ' + shotsRemaining);
player.celebrate(); // Player celebrates the shot
// Play power-up sound for special projectiles
if (currentProjectileType !== 'normal') {
LK.getSound('powerup').play();
}
} else {
currentProjectile.destroy();
slingshot.reset(); // Reset slingshot if no shot
}
currentProjectile = null;
isAiming = false;
hideTrajectoryDisplay();
player.resetPose(); // Player returns to normal stance
}
};
game.update = function () {
if (gameState !== 'playing') return;
// Update score display
scoreText.setText('Puan: ' + LK.getScore());
// Update gravity timer
if (gravityTimer > 0) {
gravityTimer--;
if (gravityTimer === 0) {
gravityReversed = false;
var gravityText = new Text2('Yerçekimi Normal', {
size: 60,
fill: 0x00FF00
});
gravityText.anchor.set(0.5, 0);
gravityText.x = 1024;
gravityText.y = 250;
LK.gui.top.addChild(gravityText);
LK.setTimeout(function () {
gravityText.destroy();
}, 1500);
}
}
// Update time slow mechanics
if (timeSlowActive) {
timeSlowTimer--;
if (timeSlowTimer === 0) {
timeSlowActive = false;
var timeText = new Text2('Zaman Normal', {
size: 60,
fill: 0x00FF00
});
timeText.anchor.set(0.5, 0);
timeText.x = 1024;
timeText.y = 300;
LK.gui.top.addChild(timeText);
LK.setTimeout(function () {
timeText.destroy();
}, 1500);
}
}
if (timeSlowCooldown > 0) {
timeSlowCooldown--;
}
// Update portals
for (var i = 0; i < portals.length; i++) {
portals[i].update();
}
// Spawn flying birds periodically
birdSpawnTimer++;
if (birdSpawnTimer > 300 + Math.random() * 600) {
// Every 5-15 seconds
birdSpawnTimer = 0;
var bird = game.addChild(new FlyingBird());
bird.init();
flyingBirds.push(bird);
}
// Update flying birds
for (var i = flyingBirds.length - 1; i >= 0; i--) {
var bird = flyingBirds[i];
if (bird.destroyed) {
bird.destroy();
flyingBirds.splice(i, 1);
continue;
}
bird.update();
// Check collision with projectiles
for (var j = 0; j < projectiles.length; j++) {
var projectile = projectiles[j];
if (projectile.launched && !projectile.destroyed && projectile.intersects(bird)) {
// Bird hit - reduce shots and destroy bird
shotsRemaining = Math.max(0, shotsRemaining - 1);
shotsText.setText('Atış: ' + shotsRemaining);
bird.destroyed = true;
// Visual feedback
LK.effects.flashScreen(0xFF0000, 300);
particleSystem.createExplosion(bird.x, bird.y, 0xFFFF00, 6);
LK.getSound('Bird').play();
break;
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
if (projectile.destroyed) {
projectile.destroy();
projectiles.splice(i, 1);
continue;
}
if (projectile.launched) {
// Add wind effect to projectile
if (windSpeed !== 0) {
projectile.velocityX += windSpeed * 0.05;
}
// Create particle trail for special projectiles - reduced frequency
if (projectile.type !== 'normal' && LK.ticks % 8 === 0) {
particleSystem.createTrail(projectile.x - projectile.velocityX * 0.5, projectile.y - projectile.velocityY * 0.5, projectile.velocityX, projectile.velocityY);
}
checkProjectileCollisions(projectile);
}
}
// Remove destroyed blocks with particle effects
for (var i = targetBlocks.length - 1; i >= 0; i--) {
if (targetBlocks[i].destroyed) {
// Create destruction particles if not already done
if (!targetBlocks[i].particlesCreated) {
particleSystem.createExplosion(targetBlocks[i].x, targetBlocks[i].y, 0xFFFFFF, 6);
targetBlocks[i].particlesCreated = true;
}
targetBlocks[i].destroy();
targetBlocks.splice(i, 1);
}
}
// Color-changing world based on level progression
if (LK.ticks % 120 === 0) {
var colorPhase = (level - 1) % 6;
var skyColor, grassColor;
switch (colorPhase) {
case 0:
// Dawn
skyColor = 0x87CEEB;
grassColor = 0x4caf50;
break;
case 1:
// Morning
skyColor = 0xADD8E6;
grassColor = 0x228B22;
break;
case 2:
// Noon
skyColor = 0x00BFFF;
grassColor = 0x32CD32;
break;
case 3:
// Afternoon
skyColor = 0xFF7F50;
grassColor = 0x6B8E23;
break;
case 4:
// Sunset
skyColor = 0xFF6347;
grassColor = 0x556B2F;
break;
case 5:
// Night
skyColor = 0x191970;
grassColor = 0x2F4F2F;
break;
}
// Smooth color transition
tween(ground, {
tint: grassColor
}, {
duration: 2000,
easing: tween.easeInOut
});
game.setBackgroundColor(skyColor);
}
// Environmental effects - reduced frequency
if (level > 15 && LK.ticks % 300 === 0) {
// Add occasional falling leaves or snow
var leaf = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
leaf.x = Math.random() * 2048;
leaf.y = -50;
leaf.tint = 0x228B22;
leaf.scaleX = 0.5;
leaf.scaleY = 0.5;
tween(leaf, {
x: leaf.x + (Math.random() - 0.5) * 200,
y: 2800,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
leaf.destroy();
}
});
}
// Periodic cleanup to prevent memory leaks
if (LK.ticks % 300 === 0) {
particleSystem.cleanup();
}
// Check if game over (no shots remaining and no active projectiles)
if (shotsRemaining <= 0 && projectiles.length === 0) {
// Check if there are still blocks remaining
var remainingBlocks = 0;
for (var i = 0; i < targetBlocks.length; i++) {
if (!targetBlocks[i].destroyed) {
remainingBlocks++;
}
}
if (remainingBlocks > 0) {
// Show game over only if level is not complete
LK.showGameOver();
return;
}
}
// Check level completion
checkLevelComplete();
};