/**** * 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();
};