User prompt
Oyunu sil
User prompt
Oyunu en baştan yaratalım
User prompt
Oyundaki katman mantığını sıfırla arkplanı sıfırla zemin sıfırla
User prompt
Bana bir düğme ver ve ona bastığımızda bölüm2 nin başına ışınlanma olsun
User prompt
Bölüm1 deki bütün düzenlemeleri bölüm 2 içinde yapın
User prompt
Karakterin katmanını 3 katmana taşı
User prompt
Zemin soldan sağ doğru sonsuz bir döngüde devam etsin hızı arkaplan hızı ile bir olsun
User prompt
Karakteri zemin varligin üzerine getir tam üstünde görünsün
User prompt
Karakter zeminin üst kısmında yer alsın
User prompt
0ve1 katmanları yer değiştir
User prompt
Zemini ekranın orta alt kısmına getir
User prompt
0ve1 katmanını kilitle
User prompt
0 ve 1 katmanını kilitle
User prompt
Zemini 1 katmana taşı arkaplanları 0 taşı
User prompt
Katman sırasını düzenleyelim 0cı katman en arka sıra 1 ci katman 0 üstünde 2 katman 1 üstünde
User prompt
Katman sırasını şöyle düzenle 0,cı katman en arka sıraya 1,ci katman 0ci katmanın bir üstüne 2,ci katman 1 katmanın bir üstüne 3,cü katman 2,ci katmanın bir üzerine
User prompt
Please fix the bug: 'Error: The supplied index is out of bounds' in or related to this line: 'ground1.setChildIndex(ground1, 1);' Line Number: 3315
User prompt
Zemin varlığı oluştur zemin sabit kalsın zemin varlığını katman 1 taşı zemin soldan sağ ekranın alt kısmını tamamen doldursun
User prompt
Zemini sağ doğru bayağı uzat
User prompt
Zemini sağa doğru bayağı uzat
User prompt
Zemin sabit dursun
User prompt
Bana bir zemin varlığı yarat bu zemin varlığı soldan sağ doğru sürekli bir gidiş döngüsü olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyundan zemin2 varlığını tamamen sil
User prompt
Karakterin hitboxunu ve boyutunu 200x200
User prompt
Zz1 varlığını tamamen sil
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { totalCoins: 0, powerUps: {}, playerName: "Player", lastScore: 0, highScore: 0, gamesPlayed: 0, totalDistance: 0, bestDistance: 0, achievements: {}, settings: { soundEnabled: true, musicEnabled: true, difficulty: "normal" } }); /**** * Classes ****/ var Box = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xFFB347 // Bright orange color }); self.speed = gameSpeed; self.broken = false; self.health = 1; // Can be broken in one hit self.update = function () { self.x -= self.speed; }; // Method to break the box and spawn coins self.breakBox = function (brokenByBullet) { if (!self.broken) { self.broken = true; // Create breaking effect LK.effects.flashObject(self, 0xFFFFFF, 300); // Only spawn coins if not broken by bullet if (!brokenByBullet) { // Spawn 2-3 coins around the box var numCoins = 2 + Math.floor(Math.random() * 2); for (var c = 0; c < numCoins; c++) { var coin = new Coin(); coin.x = self.x + (Math.random() - 0.5) * 100; coin.y = self.y + (Math.random() - 0.5) * 80; coins.push(coin); game.addChild(coin); } } // Play box breaking sound LK.getSound('box_break').play(); // Check for boxes above this one and make them fall for (var i = 0; i < boxes.length; i++) { var otherBox = boxes[i]; if (!otherBox.broken && otherBox !== self) { // Check if this box is above the broken box (within range) var horizontalDistance = Math.abs(otherBox.x - self.x); var verticalDistance = self.y - otherBox.y; // If box is above and close horizontally, make it fall if (horizontalDistance < 60 && verticalDistance > 0 && verticalDistance < 150) { // Start falling animation tween(otherBox, { y: self.y }, { duration: 800, easing: tween.easeOut }); } } } // Simple fade out without scaling or rotation tween(self, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('fire_projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); self.speed = 8; // Bullet moves right at reduced speed self.destroyed = false; self.update = function () { self.x += self.speed; // Move bullet to the right }; // Create minimal particle effects around bullet - reduced count for performance self.particles = []; // Create only 2 particles instead of 4 var _loop3 = function _loop3() { particle = LK.getAsset('fire_projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, alpha: 0.5, tint: 0xFF6600 }); self.addChild(particle); self.particles.push(particle); // Position particles in a circle around bullet center angle = p / 2 * Math.PI * 2; radius = 30; particle.x = Math.cos(angle) * radius; particle.y = Math.sin(angle) * radius; // Simple static positioning - no orbit animation to prevent lag }, particle, angle, radius; for (var p = 0; p < 2; p++) { _loop3(); } // Simplified rotation - no continuous animation to prevent lag bulletGraphics.rotation = Math.random() * Math.PI * 2; // Random initial rotation only // Method to destroy the bullet and create minimal explosion effect self.destroyBullet = function () { if (!self.destroyed) { self.destroyed = true; // Create minimal explosion particles - reduced count for performance for (var p = 0; p < 3; p++) { var particle = LK.getAsset('fire_projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 0.8, x: self.x, y: self.y, tint: 0xFF4500 }); game.addChild(particle); var angle = p / 3 * Math.PI * 2; var distance = 60; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Simple fade out effect tween(self, { alpha: 0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); var C10 = Container.expand(function () { var self = Container.call(this); var c10Graphics = self.attachAsset('C10', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C11 = Container.expand(function () { var self = Container.call(this); var c11Graphics = self.attachAsset('C11', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C12 = Container.expand(function () { var self = Container.call(this); var c12Graphics = self.attachAsset('C12', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C13 = Container.expand(function () { var self = Container.call(this); var c13Graphics = self.attachAsset('C13', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C14 = Container.expand(function () { var self = Container.call(this); var c14Graphics = self.attachAsset('C14', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C15 = Container.expand(function () { var self = Container.call(this); var c15Graphics = self.attachAsset('C15', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C16 = Container.expand(function () { var self = Container.call(this); var c16Graphics = self.attachAsset('C16', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C2 = Container.expand(function () { var self = Container.call(this); var c2Graphics = self.attachAsset('C2', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 200; self.hitboxHeight = 200; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C3 = Container.expand(function () { var self = Container.call(this); var c3Graphics = self.attachAsset('C3', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C4 = Container.expand(function () { var self = Container.call(this); var c4Graphics = self.attachAsset('C4', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C5 = Container.expand(function () { var self = Container.call(this); var c5Graphics = self.attachAsset('C5', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C6 = Container.expand(function () { var self = Container.call(this); var c6Graphics = self.attachAsset('C6', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C7 = Container.expand(function () { var self = Container.call(this); var c7Graphics = self.attachAsset('C7', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C8 = Container.expand(function () { var self = Container.call(this); var c8Graphics = self.attachAsset('C8', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var C9 = Container.expand(function () { var self = Container.call(this); var c9Graphics = self.attachAsset('C9', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('wumpa', { anchorX: 0.5, anchorY: 0.5 }); self.speed = gameSpeed; self.collected = false; // Floating animation self.floatOffset = 0; self.update = function () { self.x -= self.speed; // Floating animation self.floatOffset += 0.15; coinGraphics.y = Math.sin(self.floatOffset) * 10; // Rotation animation coinGraphics.rotation += 0.1; }; return self; }); var DamageBox = Container.expand(function () { var self = Container.call(this); var damageBoxGraphics = self.attachAsset('tnt_box', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, tint: 0x8B4513 // Brown box color with TNT styling }); self.speed = gameSpeed; self.damaged = false; self.update = function () { self.x -= self.speed; }; // Method to cause damage to player self.damagePlayer = function () { if (!self.damaged && !player.isInvulnerable && !godModeActive) { self.damaged = true; playerLives--; // Play heart damage sound when lives decrease LK.getSound('Canazalma').play(); // Play TNT break sound when dangerous box is damaged LK.getSound('tnt_break').play(); // Check for TNT boxes above this one and make them fall for (var i = 0; i < damageBoxes.length; i++) { var otherDamageBox = damageBoxes[i]; if (!otherDamageBox.damaged && otherDamageBox !== self) { // Check if this TNT box is above the damaged box (within range) var horizontalDistance = Math.abs(otherDamageBox.x - self.x); var verticalDistance = self.y - otherDamageBox.y; // If TNT box is above and close horizontally, make it fall if (horizontalDistance < 60 && verticalDistance > 0 && verticalDistance < 150) { // Start falling animation tween(otherDamageBox, { y: self.y }, { duration: 800, easing: tween.easeOut }); } } } // Add screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 20; var shakeDuration = 300; // Create shake animation sequence tween(game, { x: originalX + shakeIntensity, y: originalY + shakeIntensity * 0.5 }, { duration: shakeDuration / 6, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX - shakeIntensity, y: originalY - shakeIntensity * 0.5 }, { duration: shakeDuration / 6, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX + shakeIntensity * 0.5, y: originalY + shakeIntensity * 0.3 }, { duration: shakeDuration / 6, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX - shakeIntensity * 0.5, y: originalY - shakeIntensity * 0.3 }, { duration: shakeDuration / 6, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: shakeDuration / 3, easing: tween.easeOut }); } }); } }); } }); } }); // Update heart icons display for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Flash damaged heart when taking damage if (playerLives >= 0 && playerLives < hearts.length) { LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500); } // Make player invulnerable temporarily player.isInvulnerable = true; // Add light red flash effect to player character when colliding with damage objects tween(player, { tint: 0xFF6666 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(player, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Add full-screen light red flash effect LK.effects.flashScreen(0xFF6666, 400); // Remove invulnerability after 2 seconds LK.setTimeout(function () { player.isInvulnerable = false; }, 2000); // Check for game over if (playerLives <= 0) { LK.showGameOver(); } // Create explosion effect when damaged self.createExplosion(); } }; // Method to create explosion effect - reduced particles to prevent lag self.createExplosion = function () { // Create explosion particles - reduced count for better performance for (var p = 0; p < 6; p++) { var particle = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, alpha: 1.0, x: self.x, y: self.y, tint: 0x654321 }); game.addChild(particle); var angle = p / 6 * Math.PI * 2; var distance = 100 + Math.random() * 60; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1) }, { duration: 400 + Math.random() * 100, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Hide the damage box tween(self, { alpha: 0, scaleX: 2.0, scaleY: 2.0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Düşman1 = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('dman1', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, rotation: -Math.PI / 4 // -45 degrees rotation }); self.speed = gameSpeed; self.damaged = false; self.floatOffset = Math.random() * Math.PI * 2; self.floatSpeed = 0.05; self.baseY = self.y; self.update = function () { // Add wave effect to düşman1 entity self.floatOffset += self.floatSpeed; enemyGraphics.y = Math.sin(self.floatOffset) * 12; // Wave movement with 12 pixel amplitude enemyGraphics.rotation = -Math.PI / 4 + Math.sin(self.floatOffset * 1.2) * 0.08; // Base rotation with wave effect // Move düşman1 with the map like other game objects self.x -= self.speed; }; // Method to damage player on collision self.damagePlayer = function () { if (!self.damaged && !player.isInvulnerable && !godModeActive) { self.damaged = true; playerLives--; // Play heart damage sound when lives decrease LK.getSound('Canazalma').play(); // Add screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 15; var shakeDuration = 200; tween(game, { x: originalX + shakeIntensity, y: originalY + shakeIntensity * 0.5 }, { duration: shakeDuration / 4, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX - shakeIntensity, y: originalY - shakeIntensity * 0.5 }, { duration: shakeDuration / 4, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: shakeDuration / 2, easing: tween.easeOut }); } }); } }); // Update heart icons display for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Flash damaged heart when taking damage if (playerLives >= 0 && playerLives < hearts.length) { LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500); } // Make player invulnerable temporarily player.isInvulnerable = true; // Add light red flash effect to player character body tween(player, { tint: 0xFF6666 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(player, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Add full-screen light red flash effect LK.effects.flashScreen(0xFF6666, 400); // Remove invulnerability after 1.5 seconds LK.setTimeout(function () { player.isInvulnerable = false; }, 1500); // Check for game over if (playerLives <= 0) { LK.showGameOver(); } // Create explosion effect when damaged self.createExplosion(); } }; // Method to create explosion effect self.createExplosion = function () { // Create explosion particles for (var p = 0; p < 5; p++) { var particle = LK.getAsset('dman1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 1.0, x: self.x, y: self.y, tint: 0xFF4444 }); game.addChild(particle); var angle = p / 5 * Math.PI * 2; var distance = 80 + Math.random() * 40; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1) }, { duration: 300 + Math.random() * 100, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Hide the enemy tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var EndGate = Container.expand(function () { var self = Container.call(this); var gateGraphics = self.attachAsset('B1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2, tint: 0xFFD700 // Golden color for finish gate }); // Create circular portal effect inside the gate (same as StartingGate) var portalCircle = self.attachAsset('B1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, x: 0, y: -280, alpha: 0.8, tint: 0x00FFFF }); // Start rotating animation for the portal function startPortalRotation() { // Animation removed - portal remains static } // Add pulsing animation to make portal more dynamic function startPortalPulse() { // Animation removed - portal remains static } // Animation functions removed - portal remains static // Add victory glow effect var victoryGlow = self.attachAsset('B1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.5, scaleY: 1.5, alpha: 0.4, tint: 0xFFFFFF // White victory glow }); // Start victory glow pulsing animation function startVictoryPulse() { // Animation removed - victory glow remains static } // Animation function removed - victory glow remains static self.speed = gameSpeed; self.crossed = false; self.update = function () { self.x -= self.speed; }; // Method to trigger win condition self.triggerWin = function () { if (!self.crossed) { self.crossed = true; // Game completion var completionMessage = 'GAME COMPLETED!'; var completionColor = 0x00FF00; // Create victory particle effect for (var p = 0; p < 20; p++) { var particle = LK.getAsset('B1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 1.0, x: self.x, y: self.y - 200, tint: p % 3 === 0 ? 0xFFD700 : p % 3 === 1 ? 0xFFFFFF : 0x00FF00 }); game.addChild(particle); var angle = p / 20 * Math.PI * 2; var distance = 200 + Math.random() * 150; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y - 200 + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 3 }, { duration: 1500 + Math.random() * 500, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Chapter completion message removed for Chapter 2 // Flash screen with victory colors LK.effects.flashScreen(0xFFD700, 800); // Show intermediate screen after a brief delay LK.setTimeout(function () { intermediateScreen.showScreen(); }, 800); // Final game completion removed - no "You won the game" screen } }; return self; }); var Gem = Container.expand(function () { var self = Container.call(this); var gemGraphics = self.attachAsset('gem', { anchorX: 0.5, anchorY: 0.5 }); // Create crystalline aura effect var aura1 = self.attachAsset('gem', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.3, scaleY: 1.3, alpha: 0.4, tint: 0x00FFFF }); var aura2 = self.attachAsset('gem', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.6, scaleY: 1.6, alpha: 0.2, tint: 0x8A2BE2 }); self.speed = gameSpeed; self.collected = false; // Crystal aura remains steady without pulsing animation self.update = function () { self.x -= self.speed; // Crystal remains steady without rotation }; // Method to create particle effect when collected self.createParticles = function () { for (var p = 0; p < 8; p++) { var particle = LK.getAsset('gem', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 0.8, x: self.x, y: self.y, tint: p % 2 === 0 ? 0x00FFFF : 0x8A2BE2 }); game.addChild(particle); var angle = p / 8 * Math.PI * 2; var distance = 150 + Math.random() * 100; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 800 + Math.random() * 400, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } }; return self; }); var IntermediateScreen = Container.expand(function () { var self = Container.call(this); self.isActive = false; self.showScreen = function () { if (self.isActive) return; self.isActive = true; // Pause the game LK.pauseGame(); // Create dark overlay self.overlay = LK.getAsset('ekn1', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95, x: 0, y: 0 }); LK.gui.center.addChild(self.overlay); // Create main panel self.panel = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 30, tint: 0x1a1a2e, x: 0, y: 0 }); LK.gui.center.addChild(self.panel); // Title text self.titleText = new Text2('CHAPTER COMPLETE!', { size: 120, fill: 0xFFD700, font: "Avenir", fontWeight: 'bold' }); self.titleText.anchor.set(0.5, 0.5); self.titleText.x = 0; self.titleText.y = -300; LK.gui.center.addChild(self.titleText); // Statistics display self.statsText = new Text2('Coins Collected: ' + coinCount + '\nDistance Traveled: ' + Math.floor(distanceScore / 10) + 'm\nLives Remaining: ' + playerLives, { size: 60, fill: 0xFFFFFF, font: "Avenir" }); self.statsText.anchor.set(0.5, 0.5); self.statsText.x = 0; self.statsText.y = -100; LK.gui.center.addChild(self.statsText); // Continue button self.continueButton = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, x: 0, y: 150 }); LK.gui.center.addChild(self.continueButton); self.continueText = new Text2('CONTINUE TO CHAPTER 2', { size: 50, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); self.continueText.anchor.set(0.5, 0.5); self.continueText.x = 0; self.continueText.y = 150; LK.gui.center.addChild(self.continueText); // Add pulse animation to continue button function continuePulse() { tween(self.continueButton, { scaleX: 1.6, scaleY: 1.6 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.continueButton, { scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeInOut, onFinish: continuePulse }); } }); } continuePulse(); // Continue button interaction self.continueButton.down = function () { self.closeScreen(); }; // Flash effect when showing LK.effects.flashScreen(0x00FF00, 500); }; self.closeScreen = function () { if (!self.isActive) return; self.isActive = false; // Stop pulse animation if (self.continueButton) { tween.stop(self.continueButton); } // Clean up all elements if (self.overlay) self.overlay.destroy(); if (self.panel) self.panel.destroy(); if (self.titleText) self.titleText.destroy(); if (self.statsText) self.statsText.destroy(); if (self.continueButton) self.continueButton.destroy(); if (self.continueText) self.continueText.destroy(); // Flash effect and start chapter 2 LK.effects.flashScreen(0x00AA00, 300); // Initialize Chapter 2 self.startChapter2(); }; self.startChapter2 = function () { // Reset game variables for chapter 2 distanceScore = 0; coinCount = 0; gemCount = 0; playerLives = storage.currentLives || 5; gameSpeed = 24; normalSpeed = 24; crystalSpawned = false; endGateSpawned = false; spawnTimer = 0; trailTimer = 0; isSecondPart = true; // Clear all arrays coins.length = 0; gems.length = 0; boxes.length = 0; damageBoxes.length = 0; trails.length = 0; düşman1Enemies.length = 0; // Reset character switching currentCharacterIndex = 0; currentCharacter = characterOrder[currentCharacterIndex]; lastSwapDistance = 0; nextSwapDistance = 2; // Reset player player.x = 400; player.y = groundY + 20; player.isJumping = false; player.velocityY = 0; player.jumpsRemaining = 2; player.isInvulnerable = false; player.isSpinning = false; // Reset graphics to first character player.removeChildAt(0); var newGraphics = player.attachAsset('C1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Reset UI elements coinText.setText('0'); distanceText.setText('0m'); // Update heart display based on current lives for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; hearts[h].tint = 0xFFFFFF; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Reset progress line elements progressChar.x = 200; progressGem.x = 200 + 500 / 1500 * 1120; progressGem.visible = true; progressGem.tint = 0xFFFFFF; progressA1.x = 200 + 30 / 1500 * 1120; progressA1.visible = true; progressA1.tint = 0x00FFFF; progressB1.x = 200 + 1000 / 1000 * 1120; progressB1.visible = true; progressB1.tint = 0xFFD700; // Reset gem UI if exists if (gemIcon) { gemIcon.destroy(); gemIcon = null; } if (gemText) { gemText.destroy(); gemText = null; } // Reset god mode if (godModeActive) { toggleGodMode(); } // Create new starting gate for chapter 2 if (startingGate) { startingGate.destroy(); } startingGate = new StartingGate(); startingGate.x = 400 + 3 * 10; startingGate.y = groundY + 75; game.addChild(startingGate); // Switch to background2 for chapter 2 background2.destroy(); background3.destroy(); // Create new backgrounds using background2 asset background1 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); background2 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 2250, y: 0 })); background3 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 4500, y: 0 })); // Replace ground assets with ground2 for chapter 2 ground1.destroy(); ground2.destroy(); ground3.destroy(); // Create new ground elements using ground2 asset ground1 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 0, y: groundY })); ground2 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 4008, y: groundY })); ground3 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 8016, y: groundY })); // Resume game LK.resumeGame(); }; return self; }); var Ml = Container.expand(function () { var self = Container.call(this); var mlGraphics = self.attachAsset('ml', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.6 }); self.speed = gameSpeed; self.damaged = false; self.isMovingToPlayer = false; // Track if ml is currently moving towards player self.floatOffset = Math.random() * Math.PI * 2; self.floatSpeed = 0.05; self.baseY = self.y; self.update = function () { // Add wave effect to ml entity self.floatOffset += self.floatSpeed; mlGraphics.y = Math.sin(self.floatOffset) * 15; // Wave movement with 15 pixel amplitude mlGraphics.rotation = Math.sin(self.floatOffset * 1.5) * 0.1; // Slight rotation wave effect // Check if any düşman1 entity is on screen to trigger movement var düşman1OnScreen = false; for (var i = 0; i < düşman1Enemies.length; i++) { var enemy = düşman1Enemies[i]; if (enemy.x >= 0 && enemy.x <= 2048) { düşman1OnScreen = true; break; } } // If düşman1 is on screen, start moving towards player immediately if (düşman1OnScreen && !self.damaged) { // Randomly choose between player's right front face or left back face var isRightFront = Math.random() < 0.5; // 50% chance for each position var targetX, targetY; if (isRightFront) { // Move towards player's right front face targetX = player.x + 80; // Position slightly to the right of player targetY = groundY - 100; // Move towards upper part of ground } else { // Move towards player's left back face targetX = player.x - 80; // Position slightly to the left of player targetY = groundY - 100; // Move towards upper part of ground } // Use tween to smoothly move ml towards target position if (!self.isMovingToPlayer) { self.isMovingToPlayer = true; // Random speed between 10 (slow) and 40 (fast) units - converted to duration var randomSpeed = 10 + Math.random() * 30; // Speed between 10-40 var randomDuration = 2000 - randomSpeed * 25; // Convert speed to duration (higher speed = lower duration) tween(self, { x: targetX, y: targetY }, { duration: randomDuration, easing: tween.easeOut }); } } else if (!düşman1OnScreen) { // Move ml with the map like other game objects when no düşman1 on screen self.x -= self.speed; } // Check if ml has reached the upper part of ground and destroy it if (self.y >= groundY - 120) { // Upper part of ground threshold self.damaged = true; self.destroy(); // Remove from mlEntities array will be handled in main update loop } }; // Method to damage player on collision self.damagePlayer = function () { if (!self.damaged && !player.isInvulnerable && !godModeActive) { self.damaged = true; playerLives--; // Play heart damage sound when lives decrease LK.getSound('Canazalma').play(); // Add screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 15; var shakeDuration = 200; tween(game, { x: originalX + shakeIntensity, y: originalY + shakeIntensity * 0.5 }, { duration: shakeDuration / 4, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX - shakeIntensity, y: originalY - shakeIntensity * 0.5 }, { duration: shakeDuration / 4, easing: tween.easeOut, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: shakeDuration / 2, easing: tween.easeOut }); } }); } }); // Update heart icons display for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Flash damaged heart when taking damage if (playerLives >= 0 && playerLives < hearts.length) { LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500); } // Make player invulnerable temporarily player.isInvulnerable = true; // Add light red flash effect to player character body tween(player, { tint: 0xFF6666 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(player, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Add full-screen light red flash effect LK.effects.flashScreen(0xFF6666, 400); // Remove invulnerability after 1.5 seconds LK.setTimeout(function () { player.isInvulnerable = false; }, 1500); // Check for game over if (playerLives <= 0) { LK.showGameOver(); } // Create explosion effect when damaged self.createExplosion(); } }; // Method to create explosion effect self.createExplosion = function () { // Create explosion particles for (var p = 0; p < 5; p++) { var particle = LK.getAsset('ml', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, alpha: 1.0, x: self.x, y: self.y, tint: 0xFF4444 }); game.addChild(particle); var angle = p / 5 * Math.PI * 2; var distance = 80 + Math.random() * 40; var targetX = self.x + Math.cos(angle) * distance; var targetY = self.y + Math.sin(angle) * distance; tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1) }, { duration: 300 + Math.random() * 100, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Hide the ml entity tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var foxGraphics = self.attachAsset('C1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Set custom hitbox dimensions self.hitboxWidth = 450; self.hitboxHeight = 450; // Override width and height properties for collision detection Object.defineProperty(self, 'width', { get: function get() { return self.hitboxWidth; }, set: function set(value) { self.hitboxWidth = value; } }); Object.defineProperty(self, 'height', { get: function get() { return self.hitboxHeight; }, set: function set(value) { self.hitboxHeight = value; } }); self.isJumping = false; self.velocityY = 0; self.groundY = 2732 - 150 + 20; // Ground level self.jumpPower = -27; self.gravity = 1.2; self.runAnimationTimer = 0; self.isSpinning = false; self.spinDamageRadius = 150; self.jumpsRemaining = 2; // Allow double jump self.jump = function () { if (self.jumpsRemaining > 0) { // First jump or double jump if (!self.isJumping) { self.isJumping = true; } // Different jump power for double jump var isDoubleJump = self.jumpsRemaining === 1 && self.isJumping; if (isDoubleJump) { // Double jump - higher jump power self.velocityY = self.jumpPower - 5; // Slightly higher jump (-5 makes it more negative, so higher) } else { // Regular jump self.velocityY = self.jumpPower; } self.jumpsRemaining--; LK.getSound('jump').play(); // Simple jump animation without somersault - just scale effect var jumpDuration = 300; // Shorter duration for simple jump // Different animation for double jump if (isDoubleJump) { // Double jump animation - enhanced scale effect tween(foxGraphics, { scaleX: 1.4, scaleY: 1.4 }, { duration: jumpDuration, easing: tween.easeOut, onFinish: function onFinish() { tween(foxGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } else { // Regular jump animation - simple scale effect tween(foxGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: jumpDuration, easing: tween.easeOut, onFinish: function onFinish() { tween(foxGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } } }; self.spinAttack = function () { if (!self.isSpinning) { self.isSpinning = true; LK.getSound('jump').play(); // Reuse jump sound for spin // Horizontal rotation animation around character's center tween(foxGraphics, { rotation: Math.PI * 4, // 2 full horizontal rotations scaleX: 1.5, scaleY: 1.5, tint: 0xFF4500 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { self.isSpinning = false; foxGraphics.rotation = 0; foxGraphics.scaleX = 1.0; foxGraphics.scaleY = 1.0; foxGraphics.tint = 0xFFFFFF; } }); } }; self.update = function () { if (self.isJumping) { self.velocityY += self.gravity; self.y += self.velocityY; // Land on ground if (self.y >= self.groundY) { self.y = self.groundY; self.isJumping = false; self.velocityY = 0; self.jumpsRemaining = 2; // Reset double jump when landing // Reset character scale when landing tween(foxGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut }); } } else { // Running animation when on ground self.runAnimationTimer += 0.2; foxGraphics.y = Math.sin(self.runAnimationTimer) * 3; foxGraphics.scaleX = 1.0 + Math.sin(self.runAnimationTimer * 2) * 0.05; } }; return self; }); var StartingGate = Container.expand(function () { var self = Container.call(this); var gateGraphics = self.attachAsset('A1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.0, scaleY: 1.0 }); // Create circular portal effect inside the gate var portalCircle = self.attachAsset('A1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, x: 0, y: -200, alpha: 0.8, tint: 0x00FFFF }); // Start rotating animation for the portal function startPortalRotation() { // Animation removed - portal remains static } // Add pulsing animation to make portal more dynamic function startPortalPulse() { // Animation removed - portal remains static } // Animation functions removed - portal remains static self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var Store = Container.expand(function () { var self = Container.call(this); self.isOpen = false; self.storeItems = [{ id: 'doubleJump', name: 'Super Jump', price: 50, description: 'Higher jumps!', owned: false }, { id: 'coinMagnet', name: 'Coin Magnet', price: 100, description: 'Attract coins!', owned: false }, { id: 'speedBoost', name: 'Speed Boost', price: 75, description: 'Move faster!', owned: false }, { id: 'shield', name: 'Shield', price: 150, description: 'Extra protection!', owned: false }]; // Load owned items from storage for (var i = 0; i < self.storeItems.length; i++) { var item = self.storeItems[i]; item.owned = storage.powerUps[item.id] || false; } self.openStore = function () { if (self.isOpen) return; self.isOpen = true; // Pause the game when store opens LK.pauseGame(); // Create overlay self.overlay = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 30, scaleY: 40, alpha: 0.9, tint: 0x000033, x: 1024, y: 1366 }); game.addChild(self.overlay); // Create store panel self.panel = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 25, tint: 0x1a1a2e, x: 1024, y: 1366 }); game.addChild(self.panel); // Store title self.titleText = new Text2('POWER-UP STORE', { size: 100, fill: 0xFFD700, font: "Avenir", fontWeight: 'bold' }); self.titleText.anchor.set(0.5, 0.5); self.titleText.x = 1024; self.titleText.y = 600; game.addChild(self.titleText); // Coin display var totalCoins = storage.totalCoins || 0; self.coinDisplay = new Text2('Coins: ' + totalCoins, { size: 60, fill: 0xFFD700, font: "Avenir", fontWeight: 'bold' }); self.coinDisplay.anchor.set(0.5, 0.5); self.coinDisplay.x = 1024; self.coinDisplay.y = 700; game.addChild(self.coinDisplay); // Create store items self.itemElements = []; for (var i = 0; i < self.storeItems.length; i++) { self.createStoreItem(i); } // Close button self.closeButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, tint: 0xFF4444, x: 1024, y: 2000 }); game.addChild(self.closeButton); self.closeText = new Text2('CLOSE', { size: 50, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); self.closeText.anchor.set(0.5, 0.5); self.closeText.x = 1024; self.closeText.y = 2000; game.addChild(self.closeText); // Close button interaction self.closeButton.down = function () { self.closeStore(); }; // Animate store opening tween(self.overlay, { alpha: 0.9 }, { duration: 300 }); tween(self.panel, { scaleX: 20, scaleY: 25 }, { duration: 400, easing: tween.easeOut }); }; self.createStoreItem = function (index) { var item = self.storeItems[index]; var yPos = 850 + index * 180; // Item background var itemBg = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 15, scaleY: 3, tint: item.owned ? 0x004400 : 0x333366, x: 1024, y: yPos }); game.addChild(itemBg); // Item name var nameText = new Text2(item.name, { size: 50, fill: item.owned ? 0x88FF88 : 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); nameText.anchor.set(0.5, 0.5); nameText.x = 800; nameText.y = yPos - 20; game.addChild(nameText); // Item description var descText = new Text2(item.description, { size: 35, fill: 0xCCCCCC, font: "Avenir" }); descText.anchor.set(0.5, 0.5); descText.x = 800; descText.y = yPos + 20; game.addChild(descText); // Price/Status var priceText = new Text2(item.owned ? 'OWNED' : item.price + ' coins', { size: 45, fill: item.owned ? 0x00FF00 : 0xFFD700, font: "Avenir", fontWeight: 'bold' }); priceText.anchor.set(0.5, 0.5); priceText.x = 1200; priceText.y = yPos; game.addChild(priceText); // Buy button (only if not owned) if (!item.owned) { var buyButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5, tint: 0x00AA00, x: 1350, y: yPos }); game.addChild(buyButton); var buyText = new Text2('BUY', { size: 40, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); buyText.anchor.set(0.5, 0.5); buyText.x = 1350; buyText.y = yPos; game.addChild(buyText); buyButton.down = function () { self.purchaseItem(index); }; self.itemElements.push({ bg: itemBg, name: nameText, desc: descText, price: priceText, buyBtn: buyButton, buyTxt: buyText }); } else { self.itemElements.push({ bg: itemBg, name: nameText, desc: descText, price: priceText }); } }; self.purchaseItem = function (index) { var item = self.storeItems[index]; var totalCoins = storage.totalCoins || 0; if (totalCoins >= item.price && !item.owned) { // Purchase successful storage.totalCoins = totalCoins - item.price; storage.powerUps[item.id] = true; item.owned = true; // Update coin display self.coinDisplay.setText('Coins: ' + storage.totalCoins); // Flash effect LK.effects.flashScreen(0x00FF00, 300); // Update item appearance var elements = self.itemElements[index]; elements.bg.tint = 0x004400; elements.name.fill = 0x88FF88; elements.price.setText('OWNED'); elements.price.fill = 0x00FF00; if (elements.buyBtn) { elements.buyBtn.destroy(); elements.buyTxt.destroy(); } } else { // Not enough coins LK.effects.flashScreen(0xFF0000, 300); } }; self.closeStore = function () { if (!self.isOpen) return; self.isOpen = false; // Resume the game when store closes LK.resumeGame(); // Clean up all store elements if (self.overlay) self.overlay.destroy(); if (self.panel) self.panel.destroy(); if (self.titleText) self.titleText.destroy(); if (self.coinDisplay) self.coinDisplay.destroy(); if (self.closeButton) self.closeButton.destroy(); if (self.closeText) self.closeText.destroy(); for (var i = 0; i < self.itemElements.length; i++) { var elements = self.itemElements[i]; elements.bg.destroy(); elements.name.destroy(); elements.desc.destroy(); elements.price.destroy(); if (elements.buyBtn) elements.buyBtn.destroy(); if (elements.buyTxt) elements.buyTxt.destroy(); } self.itemElements = []; }; return self; }); var Trail = Container.expand(function () { var self = Container.call(this); var trailGraphics = self.attachAsset('C1', { anchorX: 0.5, anchorY: 1.0, scaleX: 0.6, scaleY: 0.6, alpha: 0.7 }); self.speed = gameSpeed; self.update = function () { self.x -= self.speed; }; return self; }); var TutorialScreen = Container.expand(function () { var self = Container.call(this); self.isActive = false; self.currentStep = 0; self.tutorialSteps = [{ title: "WELCOME TO ENDLESS RUNNER!", description: "Learn the basics to survive and collect coins", icon: "C1" }, { title: "JUMPING", description: "Swipe UP to jump over obstacles\nDouble tap for double jump!", icon: "heart" }, { title: "SHOOTING", description: "Swipe RIGHT to shoot bullets\nNeed gems first, costs 1 coin per shot", icon: "fire_projectile" }, { title: "COLLECTIBLES", description: "Collect coins and gems\nGems unlock shooting ability", icon: "wumpa" }, { title: "POWER-UPS", description: "Spin attack destroys enemies\nGod mode for invincibility", icon: "gem" }]; self.showTutorial = function () { if (self.isActive) return; self.isActive = true; self.currentStep = 0; // Create overlay self.overlay = LK.getAsset('ekn1', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95, x: 0, y: 0 }); LK.gui.center.addChild(self.overlay); // Create tutorial panel self.panel = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 30, tint: 0x1a1a2e, x: 0, y: 0 }); LK.gui.center.addChild(self.panel); self.showCurrentStep(); }; self.showCurrentStep = function () { // Clean up previous step elements self.cleanupStepElements(); var step = self.tutorialSteps[self.currentStep]; // Tutorial title self.titleText = new Text2(step.title, { size: 80, fill: 0xFFD700, font: "Avenir", fontWeight: 'bold' }); self.titleText.anchor.set(0.5, 0.5); self.titleText.x = 0; self.titleText.y = -400; LK.gui.center.addChild(self.titleText); // Tutorial description self.descText = new Text2(step.description, { size: 50, fill: 0xFFFFFF, font: "Avenir" }); self.descText.anchor.set(0.5, 0.5); self.descText.x = 0; self.descText.y = -250; LK.gui.center.addChild(self.descText); // Tutorial icon self.iconAsset = LK.getAsset(step.icon, { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, x: 0, y: 100 }); LK.gui.center.addChild(self.iconAsset); // Step counter self.stepText = new Text2(self.currentStep + 1 + " / " + self.tutorialSteps.length, { size: 40, fill: 0x888888, font: "Avenir" }); self.stepText.anchor.set(0.5, 0.5); self.stepText.x = 0; self.stepText.y = 250; LK.gui.center.addChild(self.stepText); // Navigation buttons if (self.currentStep > 0) { self.prevButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, tint: 0x666666, x: -200, y: 350 }); LK.gui.center.addChild(self.prevButton); self.prevText = new Text2('PREVIOUS', { size: 35, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); self.prevText.anchor.set(0.5, 0.5); self.prevText.x = -200; self.prevText.y = 350; LK.gui.center.addChild(self.prevText); self.prevButton.down = function () { self.previousStep(); }; } if (self.currentStep < self.tutorialSteps.length - 1) { self.nextButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, tint: 0x00AA00, x: 200, y: 350 }); LK.gui.center.addChild(self.nextButton); self.nextText = new Text2('NEXT', { size: 35, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); self.nextText.anchor.set(0.5, 0.5); self.nextText.x = 200; self.nextText.y = 350; LK.gui.center.addChild(self.nextText); self.nextButton.down = function () { self.nextStep(); }; } else { // Final step - show start button self.startButton = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, x: 0, y: 350 }); LK.gui.center.addChild(self.startButton); self.startButton.down = function () { self.closeTutorial(); }; } // Skip button self.skipButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xFF4444, x: 0, y: 450 }); LK.gui.center.addChild(self.skipButton); self.skipText = new Text2('SKIP TUTORIAL', { size: 30, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); self.skipText.anchor.set(0.5, 0.5); self.skipText.x = 0; self.skipText.y = 450; LK.gui.center.addChild(self.skipText); self.skipButton.down = function () { self.closeTutorial(); }; }; self.nextStep = function () { if (self.currentStep < self.tutorialSteps.length - 1) { self.currentStep++; self.showCurrentStep(); } }; self.previousStep = function () { if (self.currentStep > 0) { self.currentStep--; self.showCurrentStep(); } }; self.cleanupStepElements = function () { if (self.titleText) { self.titleText.destroy(); self.titleText = null; } if (self.descText) { self.descText.destroy(); self.descText = null; } if (self.iconAsset) { self.iconAsset.destroy(); self.iconAsset = null; } if (self.stepText) { self.stepText.destroy(); self.stepText = null; } if (self.prevButton) { self.prevButton.destroy(); self.prevButton = null; } if (self.prevText) { self.prevText.destroy(); self.prevText = null; } if (self.nextButton) { self.nextButton.destroy(); self.nextButton = null; } if (self.nextText) { self.nextText.destroy(); self.nextText = null; } if (self.startButton) { self.startButton.destroy(); self.startButton = null; } if (self.skipButton) { self.skipButton.destroy(); self.skipButton = null; } if (self.skipText) { self.skipText.destroy(); self.skipText = null; } }; self.closeTutorial = function () { if (!self.isActive) return; self.isActive = false; // Clean up all tutorial elements self.cleanupStepElements(); if (self.overlay) { self.overlay.destroy(); self.overlay = null; } if (self.panel) { self.panel.destroy(); self.panel = null; } // Flash effect when closing LK.effects.flashScreen(0x00FF00, 300); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var player; var coins = []; var gems = []; var boxes = []; var damageBoxes = []; var düşman1Enemies = []; var mlEntities = []; var trails = []; var bullets = []; var gameSpeed = 24; var spawnTimer = 0; var coinCount = 0; var gemCount = 0; var distanceScore = 0; var groundY = 2732 - 150 - 2; var playerLives = 5; // Always start with 5 lives var trailTimer = 0; var crystalSpawned = false; var endGateSpawned = false; var startingGate; var endGate; var background1, background2; // UI Elements var coinFrame = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0, scaleX: 2.5, scaleY: 2, tint: 0x000000, x: 590, y: 5 }); LK.gui.top.addChild(coinFrame); var coinIcon = LK.getAsset('coin_icon', { anchorX: 0.5, anchorY: 0, x: 590, y: 0 }); LK.gui.top.addChild(coinIcon); var coinText = new Text2('0', { size: 100, fill: 0xFF6600, font: "Avenir", fontWeight: '900', stroke: 0x000000, strokeThickness: 12 }); coinText.anchor.set(0.5, 0); coinText.x = 590; coinText.y = 70; LK.gui.top.addChild(coinText); // Distance meter - hidden var distanceText = new Text2('0m', { size: 140, fill: 0x00FF00, font: "avenir", fontWeight: 'bold', stroke: 0x000000, strokeThickness: 20 }); distanceText.anchor.set(1.0, 0); distanceText.x = 0; distanceText.y = 20; distanceText.visible = false; LK.gui.topRight.addChild(distanceText); var gemIcon = null; var gemText = null; // Create heart UI elements - multiple heart icons for visual health representation var hearts = []; var maxHearts = 8; // Maximum collectible lives set to 8 // Initialize storage with current lives at game start storage.currentLives = playerLives; storage.currentHearts = playerLives; // Create multiple heart icons based on current lives count var savedHeartCount = playerLives; var _loop = function _loop() { heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, x: 150 + heartIndex * 100, y: 193 }); hearts.push(heart); LK.gui.topLeft.addChild(heart); // Set initial heart display based on current lives if (heartIndex < playerLives) { heart.alpha = 1.0; heart.tint = 0xFFFFFF; } else { heart.alpha = 0.3; heart.tint = 0x666666; } // Add synchronized pulse animation to each heart function startHeartPulse(heartElement, delay) { LK.setTimeout(function () { function pulseUp() { tween(heartElement, { scaleX: 1.4, scaleY: 1.4 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseDown }); } function pulseDown() { tween(heartElement, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseUp }); } pulseUp(); }, delay); } // Start synchronized pulse animation with slight delay between hearts startHeartPulse(heart, heartIndex * 200); }, heart; for (var heartIndex = 0; heartIndex < savedHeartCount; heartIndex++) { _loop(); } ; // Function to show collectibles summary function showCollectiblesSummary() { // Pause all game movement LK.pauseGame(); // Create matte black screen overlay - add to GUI to stay in front of all assets var blackOverlay = LK.getAsset('ekn1', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, x: 0, y: 0 }); LK.gui.center.addChild(blackOverlay); // Title text removed // Collectible items removed from black screen summary var summaryItems = []; // Coin icons removed from black screen summary // Gem icons removed from black screen summary // Coins summary text removed // Gems summary text removed // Total score text removed // Save final game statistics var finalDistance = Math.floor(distanceScore / 10); storage.lastScore = coinCount; storage.totalCoins = (storage.totalCoins || 0) + coinCount; if (coinCount > (storage.highScore || 0)) { storage.highScore = coinCount; } if (finalDistance > (storage.bestDistance || 0)) { storage.bestDistance = finalDistance; } storage.gamesPlayed = (storage.gamesPlayed || 0) + 1; // Save current lives and heart display state for Chapter 2 storage.currentLives = playerLives; storage.currentHearts = hearts.length; // Create main menu buttons after delay LK.setTimeout(function () { // Square box container for buttons removed // Create pause button var pauseButton = LK.getAsset('d2', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, x: -150, y: 200 }); LK.gui.center.addChild(pauseButton); var pauseButtonText = new Text2('PAUSE', { size: 60, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); pauseButtonText.anchor.set(0.5, 0.5); pauseButtonText.x = -150; pauseButtonText.y = 200; LK.gui.center.addChild(pauseButtonText); // Create continue button var continueButton = LK.getAsset('d1', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, x: 150, y: 200 }); LK.gui.center.addChild(continueButton); var continueButtonText = new Text2('CONTINUE', { size: 50, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); continueButtonText.anchor.set(0.5, 0.5); continueButtonText.x = 150; continueButtonText.y = 200; LK.gui.center.addChild(continueButtonText); // Add button functionality pauseButton.down = function () { LK.pauseGame(); LK.effects.flashScreen(0xFF4444, 300); }; continueButton.down = function () { // Hide continue button and d1 asset immediately continueButton.visible = false; continueButtonText.visible = false; // Clean up all UI elements blackOverlay.destroy(); pauseButton.destroy(); pauseButtonText.destroy(); continueButton.destroy(); continueButtonText.destroy(); // Flash effect and reset game for second part LK.effects.flashScreen(0x00AA00, 300); // Reset game variables for second part distanceScore = 0; coinCount = 0; gemCount = 0; playerLives = storage.currentLives || 5; // Load saved lives or default to 5 gameSpeed = 24; normalSpeed = 24; crystalSpawned = false; endGateSpawned = false; spawnTimer = 0; trailTimer = 0; isSecondPart = true; // Clear all arrays coins.length = 0; gems.length = 0; boxes.length = 0; damageBoxes.length = 0; trails.length = 0; düşman1Enemies.length = 0; // Reset character switching currentCharacterIndex = 0; currentCharacter = characterOrder[currentCharacterIndex]; lastSwapDistance = 0; nextSwapDistance = 2; // Reset player player.x = 400; player.y = groundY + 20; player.isJumping = false; player.velocityY = 0; player.jumpsRemaining = 2; player.isInvulnerable = false; player.isSpinning = false; // Reset graphics to first character player.removeChildAt(0); var newGraphics = player.attachAsset('C1', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); // Reset UI elements coinText.setText('0'); distanceText.setText('0m'); // Reset heart icons display - preserve saved heart count var savedHeartCount = storage.currentHearts || 5; // Ensure we have enough heart icons for saved lives while (hearts.length < savedHeartCount) { var heartIndex = hearts.length; var positionX, positionY; if (heartIndex < 8) { positionX = 150 + heartIndex * 100; positionY = 193; } else { positionX = 150 + (heartIndex - 8) * 100; positionY = 193 + 100; } var newHeart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, x: positionX, y: positionY }); hearts.push(newHeart); LK.gui.topLeft.addChild(newHeart); } // Update heart display based on current lives for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; hearts[h].tint = 0xFFFFFF; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Reset progress line for second part progressChar.x = 200; // Reset progress gem for second part progressGem.x = 200 + 500 / 1500 * 1120; // Position at 500m mark progressGem.visible = true; progressGem.tint = 0xFFFFFF; // Reset progress A1 for second part progressA1.x = 200 + 30 / 1500 * 1120; // Position at 30m mark progressA1.visible = true; progressA1.tint = 0x00FFFF; // Reset progress B1 for second part progressB1.x = 200 + 1000 / 1000 * 1120; // Position at 1000m mark (end of line) progressB1.visible = true; progressB1.tint = 0xFFD700; // Reset gem UI if exists if (gemIcon) { gemIcon.destroy(); gemIcon = null; } if (gemText) { gemText.destroy(); gemText = null; } // Reset hearts display to match current lives for (var h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; hearts[h].tint = 0xFFFFFF; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Reset god mode if (godModeActive) { toggleGodMode(); } // Create new starting gate for second part if (startingGate) { startingGate.destroy(); } startingGate = new StartingGate(); startingGate.x = 400 + 3 * 10; startingGate.y = groundY + 75; game.addChild(startingGate); // Switch to background2 for second part background2.destroy(); background3.destroy(); // Create new backgrounds using background2 asset background1 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); background2 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 2250, y: 0 })); background3 = game.addChild(LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 4500, y: 0 })); // Replace ground assets with ground2 for second part ground1.destroy(); ground2.destroy(); ground3.destroy(); // Create new ground elements using ground2 asset ground1 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 0, y: groundY })); ground2 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 4008, // Position second ground at end of first ground y: groundY })); ground3 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 8016, // Position third ground to eliminate gaps during transitions y: groundY })); // Resume game movement LK.resumeGame(); }; }, 2000); } ; ; // Spin button removed // Background music will be played when game starts // Create animated background elements for endless scrolling with third element to fill gaps var background1 = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, // Position first background starting behind character y: 0 })); var background2 = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 2250, // Position second background at end of first background y: 0 })); var background3 = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 4500, // Position third background to eliminate gaps during transitions y: 0 })); // Create animated ground elements for endless scrolling var ground1 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 0, y: groundY })); var ground2 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 4008, // Position second ground at end of first ground y: groundY })); var ground3 = game.addChild(LK.getAsset('ground2', { anchorX: 0, anchorY: 0, x: 8016, // Position third ground to eliminate gaps during transitions y: groundY })); // Ground animation variables var groundAnimationTimer = 0; // Create starting gate startingGate = new StartingGate(); startingGate.x = 400 + 3 * 10; // Position at 3 meters (3m * 10 pixels per meter) startingGate.y = groundY + 75; // Position gate a little higher above the ground game.addChild(startingGate); // Create player (will be added to foreground later) player = new Player(); player.x = 400; player.y = groundY + 20; player.isInvulnerable = false; // Touch controls for swipe up to jump and swipe right to shoot var touchStartY = null; var touchStartX = null; var minSwipeDistance = 100; // Minimum distance for swipe detection game.down = function (x, y, obj) { touchStartY = y; touchStartX = x; }; // Bullet firing timer var lastBulletTime = 0; var bulletCooldown = 300; // 0.3 second cooldown in milliseconds game.up = function (x, y, obj) { if (touchStartY !== null && touchStartX !== null) { var swipeDistanceY = touchStartY - y; // Positive means swipe up var swipeDistanceX = x - touchStartX; // Positive means swipe right if (swipeDistanceY >= minSwipeDistance) { // Swipe up detected - make player jump player.jump(); } else if (swipeDistanceX >= minSwipeDistance) { // Swipe right detected - shoot bullet only if we have gems collected and coins available var currentTime = LK.ticks * 16.67; // Use game ticks for more stable timing if (gemCount > 0 && coinCount > 0 && currentTime - lastBulletTime >= bulletCooldown) { var bullet = new Bullet(); bullet.x = player.x + 50; // Start bullet slightly ahead of player bullet.y = player.y - 50; // Start bullet at player's center height bullets.push(bullet); game.addChild(bullet); // Play bullet sound when firing LK.getSound('bullet_sound').play(); // Consume one coin for bullet (after gem has been collected) coinCount--; coinText.setText(coinCount); // Update last bullet time lastBulletTime = currentTime; } else { // No gems collected or no coins available or cooldown active - don't show flash effect } } touchStartY = null; touchStartX = null; } }; // Spin button interaction removed function spawnCoin() { var coin = new Coin(); coin.x = 2048 + 100; // Randomly place coins either high in air or at medium height to avoid ground-level objects var coinHeightOptions = [groundY - 300 - Math.random() * 100, // High in air groundY - 180 - Math.random() * 80 // Medium height ]; coin.y = coinHeightOptions[Math.floor(Math.random() * coinHeightOptions.length)]; coins.push(coin); game.addChild(coin); } function spawnGem() { var gem = new Gem(); gem.x = 2048 + 100; gem.y = groundY - 80 - Math.random() * 200; gems.push(gem); game.addChild(gem); } function spawnBox() { // Randomly decide formation type: 1 box (20%), 2 boxes (30%), 3 boxes (30%), or 2x2 arrangement (20%) var formationType = Math.random(); if (formationType < 0.2) { // Single box var box = new Box(); box.x = 2048 + 100; box.y = groundY - 45; boxes.push(box); game.addChild(box); } else if (formationType < 0.5) { // 2 boxes - randomly horizontal or vertical var isHorizontal = Math.random() < 0.5; if (isHorizontal) { // 2 boxes horizontally for (var i = 0; i < 2; i++) { var box = new Box(); box.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally box.y = groundY - 45; // All at same height (ground level) boxes.push(box); game.addChild(box); } } else { // 2 boxes vertically for (var i = 0; i < 2; i++) { var box = new Box(); box.x = 2048 + 100; // All at same x position box.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing boxes.push(box); game.addChild(box); } } } else if (formationType < 0.8) { // 3 boxes - randomly horizontal or vertical var isHorizontal = Math.random() < 0.5; if (isHorizontal) { // Create 3 boxes in a horizontal row for (var i = 0; i < 3; i++) { var box = new Box(); box.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally box.y = groundY - 45; // All at same height (ground level) boxes.push(box); game.addChild(box); } } else { // Create 3 boxes in a vertical column for (var i = 0; i < 3; i++) { var box = new Box(); box.x = 2048 + 100; // All at same x position box.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing boxes.push(box); game.addChild(box); } } } else { // 2x2 arrangement (4 boxes in a square) for (var i = 0; i < 2; i++) { for (var j = 0; j < 2; j++) { var box = new Box(); box.x = 2048 + 100 + i * 130; // Horizontal spacing box.y = groundY - 45 - j * 120; // Vertical spacing boxes.push(box); game.addChild(box); } } } } function spawnDamageBox() { // Randomly decide formation type: 1 box (20%), 2 boxes (30%), 3 boxes (30%), or 2x2 arrangement (20%) var formationType = Math.random(); if (formationType < 0.2) { // Single TNT box var damageBox = new DamageBox(); damageBox.x = 2048 + 100; damageBox.y = groundY - 45; damageBoxes.push(damageBox); game.addChild(damageBox); } else if (formationType < 0.5) { // 2 TNT boxes - randomly horizontal or vertical var isHorizontal = Math.random() < 0.5; if (isHorizontal) { // 2 TNT boxes horizontally for (var i = 0; i < 2; i++) { var damageBox = new DamageBox(); damageBox.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally damageBox.y = groundY - 45; // All at same height (ground level) damageBoxes.push(damageBox); game.addChild(damageBox); } } else { // 2 TNT boxes vertically for (var i = 0; i < 2; i++) { var damageBox = new DamageBox(); damageBox.x = 2048 + 100; // All at same x position damageBox.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing damageBoxes.push(damageBox); game.addChild(damageBox); } } } else if (formationType < 0.8) { // 3 TNT boxes - randomly horizontal or vertical var isHorizontal = Math.random() < 0.5; if (isHorizontal) { // Create 3 TNT boxes in a horizontal row for (var i = 0; i < 3; i++) { var damageBox = new DamageBox(); damageBox.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally damageBox.y = groundY - 45; // All at same height (ground level) damageBoxes.push(damageBox); game.addChild(damageBox); } } else { // Create 3 TNT boxes in a vertical column for (var i = 0; i < 3; i++) { var damageBox = new DamageBox(); damageBox.x = 2048 + 100; // All at same x position damageBox.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing damageBoxes.push(damageBox); game.addChild(damageBox); } } } else { // 2x2 arrangement (4 TNT boxes in a square) for (var i = 0; i < 2; i++) { for (var j = 0; j < 2; j++) { var damageBox = new DamageBox(); damageBox.x = 2048 + 100 + i * 130; // Horizontal spacing damageBox.y = groundY - 45 - j * 120; // Vertical spacing damageBoxes.push(damageBox); game.addChild(damageBox); } } } } function spawnMl() { var ml = new Ml(); ml.x = 2048 + 100; // Position ml from right side like other spawned objects ml.y = 1700; // Position at y=1700 (moved up from 1960, same as düşman1) ml.baseY = ml.y; mlEntities.push(ml); game.addChild(ml); } function spawnDüşman1() { var enemy = new Düşman1(); enemy.x = 2048 + 100; // Position enemy from right side like other spawned objects enemy.y = 1700; // Position at y=1700 (moved up from 1960) enemy.baseY = enemy.y; düşman1Enemies.push(enemy); game.addChild(enemy); } game.update = function () { // Only run game logic if game has started if (!gameStarted) { return; } // Increase distance score distanceScore += 1.5; // Update distance meter display var currentDistance = Math.floor(distanceScore / 10); distanceText.setText(currentDistance + 'm'); // Update progress line elements var targetDistance = 1000; // Distance to reach 2nd part var progressPercent = Math.min(currentDistance / targetDistance, 1.0); var lineWidth = 480; // Total width of progress line - shortened horizontally // Move mini character along the progress line progressChar.x = 200 + progressPercent * lineWidth; // Update gem position on progress line var gemDistance = 500; // Gem spawns at 500 meters var gemProgressPercent = Math.min(gemDistance / targetDistance, 1.0); progressGem.x = 200 + gemProgressPercent * lineWidth; // Show/hide gem based on whether it's been collected if (crystalSpawned && gemCount > 0) { // Gem has been collected - hide it progressGem.visible = false; } else if (currentDistance >= gemDistance) { // Past gem location but not collected - make it red to indicate missed progressGem.tint = 0xFF0000; progressGem.visible = true; } else { // Gem not yet reached - show normal gem color progressGem.tint = 0xFFFFFF; progressGem.visible = true; } // Update A1 entity position on progress line var a1Distance = 30; // A1 spawns at 30 meters (starting gate location) var a1ProgressPercent = Math.min(a1Distance / targetDistance, 1.0); progressA1.x = 200 + a1ProgressPercent * lineWidth; // Show/hide A1 based on whether it's been passed if (currentDistance >= a1Distance + 50) { // Well past A1 location - hide it progressA1.visible = false; } else if (currentDistance >= a1Distance) { // At or past A1 location - show it clearly progressA1.tint = 0x00FF00; progressA1.visible = true; } else { // A1 not yet reached - show normal cyan color progressA1.tint = 0x00FFFF; progressA1.visible = true; } // Update B1 entity position on progress line var b1Distance = 1000; // B1 spawns at 1000 meters (end gate) var b1ProgressPercent = Math.min(b1Distance / targetDistance, 1.0); progressB1.x = 200 + b1ProgressPercent * lineWidth; // Show/hide B1 based on whether it's been reached if (endGateSpawned && endGate && endGate.crossed) { // End gate has been crossed - hide it progressB1.visible = false; } else if (currentDistance >= b1Distance) { // At or past B1 location - show it clearly progressB1.tint = 0x00FF00; progressB1.visible = true; } else { // B1 not yet reached - show normal golden color progressB1.tint = 0xFFD700; progressB1.visible = true; } // Remaining distance text updates removed // Update mini character asset to match current player character - less frequent updates if (LK.ticks % 7 == 0) { if (progressChar && progressChar.children.length > 0) { progressChar.removeChildAt(0); } if (progressChar) { var miniCharGraphics = progressChar.attachAsset(currentCharacter, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); } } // Character switching logic - cycle through all 7 characters every 7 frames if (LK.ticks % 7 == 0) { // Move to next character in the cycle currentCharacterIndex = (currentCharacterIndex + 1) % characterOrder.length; currentCharacter = characterOrder[currentCharacterIndex]; // Remove old graphics and add new character graphics if (player && player.children.length > 0) { player.removeChildAt(0); // Remove current graphics } if (player) { var newGraphics = player.attachAsset(currentCharacter, { anchorX: 0.5, anchorY: 1.0, scaleX: 1.2, scaleY: 1.2 }); } // Visual feedback for swap LK.effects.flashObject(player, 0xFFFFFF, 300); } // Gradually increase speed - but respect God mode if (!godModeActive) { gameSpeed = Math.min(24 + distanceScore / 1000, 60); // Cap at 60 for performance normalSpeed = Math.min(24 + distanceScore / 1000, 60); // Track normal speed for God mode toggle } else { gameSpeed = Math.min(normalSpeed * 2.5, 100); // Reduced multiplier and capped at 100 } // Update starting gate if (startingGate && startingGate.parent) { startingGate.speed = gameSpeed; // Remove gate when it goes off screen if (startingGate.x < -200) { startingGate.destroy(); startingGate = null; } } // Update end gate if (endGate && endGate.parent) { endGate.speed = gameSpeed; // Remove gate when it goes off screen (after win condition) if (endGate.x < -400) { endGate.destroy(); endGate = null; } } // Move all background elements with game progression (same speed as ground - no parallax effect) background1.x -= gameSpeed; background2.x -= gameSpeed; background3.x -= gameSpeed; // Reset background positions for endless scrolling with immediate positioning to eliminate gaps if (background1.x <= -2250) { // Find the rightmost background element var rightmostX = Math.max(background2.x, background3.x); // Immediately position to eliminate gaps background1.x = rightmostX + 2250; } if (background2.x <= -2250) { // Find the rightmost background element var rightmostX = Math.max(background1.x, background3.x); // Immediately position to eliminate gaps background2.x = rightmostX + 2250; } if (background3.x <= -2250) { // Find the rightmost background element var rightmostX = Math.max(background1.x, background2.x); // Immediately position to eliminate gaps background3.x = rightmostX + 2250; } // Move all ground elements with game progression ground1.x -= gameSpeed; ground2.x -= gameSpeed; ground3.x -= gameSpeed; // Reset ground positions for endless scrolling with immediate positioning to eliminate gaps if (ground1.x <= -4008) { // Find the rightmost ground element var rightmostX = Math.max(ground2.x, ground3.x); // Immediately position to eliminate gaps ground1.x = rightmostX + 4008; } if (ground2.x <= -4008) { // Find the rightmost ground element var rightmostX = Math.max(ground1.x, ground3.x); // Immediately position to eliminate gaps ground2.x = rightmostX + 4008; } if (ground3.x <= -4008) { // Find the rightmost ground element var rightmostX = Math.max(ground1.x, ground2.x); // Immediately position to eliminate gaps ground3.x = rightmostX + 4008; } // Background animations removed - backgrounds remain static groundAnimationTimer += 0.1; // Keep backgrounds at fixed positions background1.y = 0; background2.y = 0; background3.y = 0; // Keep backgrounds at fixed scale background1.scaleY = 1.0; background2.scaleY = 1.0; background3.scaleY = 1.0; // Ground animations removed - ground remains static // Keep ground at fixed positions ground1.y = groundY; ground2.y = groundY; ground3.y = groundY; // Keep ground at fixed scale ground1.scaleY = 1.0; ground2.scaleY = 1.0; ground3.scaleY = 1.0; // Update spawn timer spawnTimer++; trailTimer++; // Create trail when player is jumping - reduced frequency to prevent lag if (player.isJumping && trailTimer % 8 == 0) { var trail = new Trail(); trail.x = player.x; trail.y = player.y; trail.speed = gameSpeed; trails.push(trail); game.addChild(trail); // Fade out trail with shorter duration tween(trail, { alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 300, onFinish: function onFinish() { trail.destroy(); } }); } // Spawn additional coins with reduced frequency for less air appearance if (spawnTimer % 45 == 0 && Math.random() < 0.3) { spawnCoin(); } // Spawn boxes occasionally if (spawnTimer % 90 == 0 && Math.random() < 0.6) { spawnBox(); } // Spawn damage boxes occasionally (less frequent than regular boxes) if (spawnTimer % 120 == 0 && Math.random() < 0.4) { spawnDamageBox(); } // Spawn ml and düşman1 together at the same time and position - only in second part if (spawnTimer % 100 == 0 && Math.random() < 0.3 && isSecondPart) { // Create both entities at the same position var ml = new Ml(); ml.x = 2048 + 100; // Position ml at exactly the same x as düşman1 ml.y = 1700; // Move both entities up by 260 pixels (1960 - 260 = 1700) ml.baseY = ml.y; mlEntities.push(ml); game.addChild(ml); var enemy = new Düşman1(); enemy.x = 2048 + 100; // Position enemy from right side like other spawned objects enemy.y = 1700; // Move both entities up by 260 pixels (1960 - 260 = 1700) enemy.baseY = enemy.y; düşman1Enemies.push(enemy); game.addChild(enemy); } // Spawn crystal at exactly 500 meters (within 1000 meters) var currentDistance = Math.floor(distanceScore / 10); if (currentDistance >= 500 && !crystalSpawned) { spawnGem(); crystalSpawned = true; } // Spawn end gate at exactly 1000 meters var endGateDistance = 1000; if (currentDistance >= endGateDistance && !endGateSpawned) { endGate = new EndGate(); endGate.x = 2048 + 200; // Spawn off-screen right endGate.y = groundY + 75; // Same position as starting gate game.addChild(endGate); endGateSpawned = true; } // Check if player crosses the end gate if (endGate && endGate.parent && !endGate.crossed) { if (player.x >= endGate.x - 50 && player.x <= endGate.x + 50) { endGate.triggerWin(); } } // Update and check coins var _loop2 = function _loop2() { coin = coins[j]; coin.speed = gameSpeed; // Check collection or spin attack distanceX = coin.x - player.x; distanceY = coin.y - player.y; distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius; if (!coin.collected && (player.intersects(coin) || isInSpinRange)) { coin.collected = true; coinCount++; // Add coin to total persistent storage storage.totalCoins = (storage.totalCoins || 0) + 1; LK.setScore(coinCount); coinText.setText(coinCount); // Font is already set in the Text2 constructor, no need to change it here // Scoreboard update removed // Check if player gets a new chance every 50 coins if (coinCount > 0 && coinCount % 50 === 0) { playerLives++; // Add new heart icon if needed if (playerLives > hearts.length) { // Start synchronized pulse animation for new heart var startNewHeartPulse = function startNewHeartPulse(heartElement) { function pulseUp() { tween(heartElement, { scaleX: 1.4, scaleY: 1.4 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseDown }); } function pulseDown() { tween(heartElement, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseUp }); } pulseUp(); }; heartIndex = hearts.length; // Position hearts: first 8 in a row, then below for additional hearts if (heartIndex < 8) { positionX = 150 + heartIndex * 100; positionY = 193; } else { positionX = 150 + (heartIndex - 8) * 100; positionY = 193 + 100; // Position below initial row } newHeart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, x: positionX, y: positionY }); hearts.push(newHeart); LK.gui.topLeft.addChild(newHeart); startNewHeartPulse(newHeart); } // Update heart icons display for (h = 0; h < hearts.length; h++) { if (h < playerLives) { hearts[h].alpha = 1.0; hearts[h].tint = 0xFFFFFF; } else { hearts[h].alpha = 0.3; hearts[h].tint = 0x666666; } } // Flash effect for new chance LK.effects.flashScreen(0x00FF00, 500); // Flash all active hearts for new chance for (h = 0; h < Math.min(playerLives, hearts.length); h++) { LK.effects.flashObject(hearts[h], 0x00FF00, 800); } } LK.getSound('coin').play(); // Visual feedback - enhanced for spin attacks if (isInSpinRange) { LK.effects.flashObject(coin, 0xFF4500, 300); } else { LK.effects.flashObject(coin, 0xFFFFFF, 300); } tween(coin, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, onFinish: function onFinish() { coin.destroy(); } }); coins.splice(j, 1); return 0; // continue } // Remove off-screen coins if (coin.x < -50) { coin.destroy(); coins.splice(j, 1); return 0; // continue } }, coin, distanceX, distanceY, distance, isInSpinRange, heartIndex, positionX, positionY, newHeart, h, h, _ret; for (var j = coins.length - 1; j >= 0; j--) { _ret = _loop2(); if (_ret === 0) continue; } // Update and check gems for (var g = gems.length - 1; g >= 0; g--) { var gem = gems[g]; gem.speed = gameSpeed; // Check collection or spin attack var distanceX = gem.x - player.x; var distanceY = gem.y - player.y; var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius; if (!gem.collected && (player.intersects(gem) || isInSpinRange)) { gem.collected = true; gemCount++; coinCount += 5; // Gems are worth 5 points // Add gem bonus to total coins storage storage.totalCoins = (storage.totalCoins || 0) + 5; LK.setScore(coinCount); coinText.setText(coinCount); // Scoreboard update removed // Create gem UI elements on first gem collection if (!gemIcon) { gemIcon = LK.getAsset('gem_icon', { anchorX: 0.5, anchorY: 0, x: 150, y: 20 }); LK.gui.top.addChild(gemIcon); gemText = new Text2('0', { size: 100, fill: 0xFF69B4, font: "Avenir", fontWeight: '900', stroke: 0x000000, strokeThickness: 15 }); gemText.anchor.set(0.5, 0); gemText.x = 150; gemText.y = 90; LK.gui.top.addChild(gemText); } gemText.setText(gemCount); // Font is already set in the Text2 constructor, no need to change it here LK.getSound('gem_collect').play(); LK.getSound('happy_giggle').play(); // Fade out gem UI elements after 2 seconds LK.setTimeout(function () { if (gemIcon && gemIcon.parent) { tween(gemIcon, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { gemIcon.destroy(); gemIcon = null; } }); } if (gemText && gemText.parent) { tween(gemText, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { gemText.destroy(); gemText = null; } }); } }, 2000); // Visual feedback with particle explosion - enhanced for spin attacks if (isInSpinRange) { LK.effects.flashScreen(0xFF4500, 200); } else { LK.effects.flashScreen(0x00FFFF, 200); } gem.createParticles(); gem.destroy(); gems.splice(g, 1); continue; } // Remove off-screen gems if (gem.x < -50) { gem.destroy(); gems.splice(g, 1); continue; } } // Update and check bullets - optimized collision detection for (var bullet_i = bullets.length - 1; bullet_i >= 0; bullet_i--) { var bullet = bullets[bullet_i]; if (!bullet || bullet.destroyed) { bullets.splice(bullet_i, 1); continue; } // Quick bounds check before expensive intersection tests if (bullet.x < -50 || bullet.x > 2200) { bullet.destroy(); bullets.splice(bullet_i, 1); continue; } // Check bullet collision with boxes var bulletDestroyed = false; for (var b = boxes.length - 1; b >= 0 && !bulletDestroyed; b--) { var box = boxes[b]; if (box && !box.broken && bullet.intersects(box)) { box.breakBox(true); boxes.splice(b, 1); bullet.destroyBullet(); bullets.splice(bullet_i, 1); bulletDestroyed = true; } } if (bulletDestroyed) continue; // Check bullet collision with damage boxes (TNT) for (var d = damageBoxes.length - 1; d >= 0; d--) { var damageBox = damageBoxes[d]; if (!damageBox.damaged && bullet.intersects(damageBox)) { // Create explosion effect for TNT without damaging player damageBox.createExplosion(); damageBox.destroy(); damageBoxes.splice(d, 1); bullet.destroyBullet(); bullets.splice(bullet_i, 1); break; } } // Check bullet collision with ml entities for (var m = mlEntities.length - 1; m >= 0; m--) { var ml = mlEntities[m]; if (!ml.damaged && bullet.intersects(ml)) { ml.damaged = true; // Create explosion effect ml.createExplosion(); mlEntities.splice(m, 1); bullet.destroyBullet(); bullets.splice(bullet_i, 1); break; } } // Check bullet collision with düşman1 enemies for (var e = düşman1Enemies.length - 1; e >= 0; e--) { var enemy = düşman1Enemies[e]; if (!enemy.damaged && bullet.intersects(enemy)) { enemy.damaged = true; // Create explosion effect enemy.createExplosion(); düşman1Enemies.splice(e, 1); bullet.destroyBullet(); bullets.splice(bullet_i, 1); break; } } // Remove off-screen bullets if (bullet.x > 2200 || bullet.destroyed) { bullet.destroy(); bullets.splice(bullet_i, 1); continue; } } // Update and check boxes for (var b = boxes.length - 1; b >= 0; b--) { var box = boxes[b]; box.speed = gameSpeed; // Check collision with player or spin attack var distanceX = box.x - player.x; var distanceY = box.y - player.y; var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius; if (!box.broken && (player.intersects(box) || isInSpinRange)) { box.breakBox(false); boxes.splice(b, 1); continue; } // Remove off-screen boxes if (box.x < -50) { box.destroy(); boxes.splice(b, 1); continue; } } // Update and check damage boxes for (var d = damageBoxes.length - 1; d >= 0; d--) { var damageBox = damageBoxes[d]; damageBox.speed = gameSpeed; // Check collision with player (damage boxes can't be destroyed by spin attack) if (!damageBox.damaged && player.intersects(damageBox)) { damageBox.damagePlayer(); damageBoxes.splice(d, 1); continue; } // Remove off-screen damage boxes if (damageBox.x < -50) { damageBox.destroy(); damageBoxes.splice(d, 1); continue; } } // Update and clean up trails - more aggressive cleanup to prevent lag for (var k = trails.length - 1; k >= 0; k--) { var trail = trails[k]; trail.speed = gameSpeed; // Remove off-screen, faded, or old trails more aggressively if (trail.x < -50 || trail.alpha <= 0.2) { trail.destroy(); trails.splice(k, 1); continue; } } // Update and check ml entities for (var m = mlEntities.length - 1; m >= 0; m--) { var ml = mlEntities[m]; ml.speed = gameSpeed; // Check collision with player if (!ml.damaged && player.intersects(ml)) { ml.damagePlayer(); mlEntities.splice(m, 1); continue; } // Check if ml can be destroyed by spin attack var distanceX = ml.x - player.x; var distanceY = ml.y - player.y; var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius; if (isInSpinRange && !ml.damaged) { ml.damaged = true; // Create explosion effect ml.createExplosion(); mlEntities.splice(m, 1); continue; } // Remove off-screen ml entities if (ml.x < -100) { ml.destroy(); mlEntities.splice(m, 1); continue; } } // Update and check düşman1 enemies for (var e = düşman1Enemies.length - 1; e >= 0; e--) { var enemy = düşman1Enemies[e]; if (!enemy || enemy.damaged) { düşman1Enemies.splice(e, 1); continue; } enemy.speed = gameSpeed; // Check collision with player if (!enemy.damaged && player.intersects(enemy)) { enemy.damagePlayer(); düşman1Enemies.splice(e, 1); continue; } // Check if enemy can be destroyed by spin attack var distanceX = enemy.x - player.x; var distanceY = enemy.y - player.y; var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius; if (isInSpinRange && !enemy.damaged) { enemy.damaged = true; // Create explosion effect enemy.createExplosion(); düşman1Enemies.splice(e, 1); continue; } // Remove off-screen enemies if (enemy.x < -100) { enemy.destroy(); düşman1Enemies.splice(e, 1); continue; } } // Zoom in effect - scale the game container by 10 units game.scaleX = 1.0 + 10 / 1000; // Convert 10 units to scale factor game.scaleY = 1.0 + 10 / 1000; // Convert 10 units to scale factor // Music will transition automatically when first track ends // Ensure player stays in foreground - less frequent checks to prevent lag if (LK.ticks % 30 == 0) { if (player.parent !== game) { game.addChild(player); } else { // Move player to top of render order game.removeChild(player); game.addChild(player); } } // Move player to front layer order every frame for maximum visibility if (player && player.parent === game) { game.removeChild(player); game.addChild(player); } }; // Scoreboard background removed // Game pause/resume functionality var gamePaused = false; var pausedUpdateFunction = null; LK.pauseGame = function () { if (!gamePaused) { gamePaused = true; pausedUpdateFunction = game.update; game.update = function () { // Game is paused - no updates }; } }; LK.resumeGame = function () { if (gamePaused) { gamePaused = false; if (pausedUpdateFunction) { game.update = pausedUpdateFunction; pausedUpdateFunction = null; } } }; // Initialize store var store = new Store(); // Initialize tutorial screen var tutorialScreen = new TutorialScreen(); // Initialize intermediate screen var intermediateScreen = new IntermediateScreen(); // God Mode variables var godModeActive = false; var normalSpeed = 24; // God Mode button - now hidden var godModeButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2, tint: 0xFF4444, x: 0, y: 400 }); godModeButton.visible = false; LK.gui.topLeft.addChild(godModeButton); var godModeButtonText = new Text2('GOD MODE', { size: 35, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); godModeButtonText.anchor.set(0.5, 0.5); godModeButtonText.x = 0; godModeButtonText.y = 400; godModeButtonText.visible = false; LK.gui.topLeft.addChild(godModeButtonText); // Teleport button - now hidden var teleportButton = LK.getAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2, tint: 0x8A2BE2, x: 0, y: 520 }); teleportButton.visible = false; LK.gui.topLeft.addChild(teleportButton); godModeButton.down = function () { toggleGodMode(); }; // var teleportButtonText = new Text2('TELEPORT', { var teleportButtonText = new Text2('TELEPORT', { size: 30, fill: 0xFFFFFF, font: "Avenir", fontWeight: 'bold' }); teleportButtonText.anchor.set(0.5, 0.5); teleportButtonText.x = 0; teleportButtonText.y = 520; teleportButtonText.visible = false; LK.gui.topLeft.addChild(teleportButtonText); // teleportButton.down = function () { // teleportToLastGate(); teleportButton.down = function () { teleportToLastGate(); }; function teleportToLastGate() { var targetDistance = 950; // 50 meters before the gate at 1000 meters var currentDistance = Math.floor(distanceScore / 10); if (currentDistance < targetDistance) { var distanceToAdd = (targetDistance - currentDistance) * 10; distanceScore += distanceToAdd; // Flash effect when teleporting LK.effects.flashScreen(0x8A2BE2, 500); LK.effects.flashObject(player, 0x8A2BE2, 800); } } // Function to toggle God Mode function toggleGodMode() { godModeActive = !godModeActive; if (godModeActive) { // Activate God Mode player.isInvulnerable = true; gameSpeed = normalSpeed * 3; // Very high speed // Flash effect when activating LK.effects.flashScreen(0xFFD700, 500); LK.effects.flashObject(player, 0xFFD700, 1000); } else { // Deactivate God Mode player.isInvulnerable = false; gameSpeed = normalSpeed + distanceScore / 1000; // Return to normal progression } } // Store button hidden for now // var storeButton = LK.getAsset('square_button', { // anchorX: 0.5, // anchorY: 0.5, // scaleX: 2, // scaleY: 2, // tint: 0x4444FF, // x: 0, // y: 400 // }); // LK.gui.topLeft.addChild(storeButton); // var storeButtonText = new Text2('STORE', { // size: 40, // fill: 0xFFFFFF, // fontWeight: 'bold' // }); // storeButtonText.anchor.set(0.5, 0.5); // storeButtonText.x = 0; // storeButtonText.y = 400; // LK.gui.topLeft.addChild(storeButtonText); // Store button interaction // storeButton.down = function () { // store.openStore(); // }; // Progress line UI elements var progressLine = LK.getAsset('box1', { anchorX: 0, anchorY: 0.5, scaleX: 6, // Further reduced horizontal line width scaleY: 0.2, // Slightly thicker line for better visibility tint: 0x666666, // Brighter color for better visibility x: 200, y: 200 }); LK.gui.top.addChild(progressLine); // Mini character on progress line var progressChar = LK.getAsset('C1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: 200, y: 200 }); LK.gui.top.addChild(progressChar); // Mini gem on progress line to show gem location var progressGem = LK.getAsset('gem_icon', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, x: 200, y: 200 }); LK.gui.top.addChild(progressGem); // Mini A1 entity on progress line to show starting gate location var progressA1 = LK.getAsset('A1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.12, scaleY: 0.12, x: 200, y: 200, tint: 0x00FFFF }); LK.gui.top.addChild(progressA1); // Mini B1 entity on progress line to show end gate location var progressB1 = LK.getAsset('B1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.15, scaleY: 0.15, x: 200, y: 200, tint: 0xFFD700 }); LK.gui.top.addChild(progressB1); // Remaining distance text removed // Get player name and last score from storage var playerName = storage.playerName || 'Player'; var lastScore = storage.lastScore || 0; // Character switching variables for C1-C16 cycling every 6 frames var characterOrder = ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'C11', 'C12', 'C13', 'C14', 'C15', 'C16']; var currentCharacterIndex = 0; var currentCharacter = characterOrder[currentCharacterIndex]; var lastSwapDistance = 0; var nextSwapDistance = 2; // Create start screen var startScreen = LK.getAsset('kk', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, x: 0, y: 0 }); LK.gui.center.addChild(startScreen); // Create start button var startButton = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 520 }); LK.gui.center.addChild(startButton); // Start button text removed - no text will appear // Add pulse effect to start button function startButtonPulse() { tween(startButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(startButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: startButtonPulse }); } }); } startButtonPulse(); // Start button interaction startButton.down = function () { if (!gameStarted) { // Check if kk asset is present and show tutorial if (startScreen && startScreen.children && startScreen.children.length > 0) { // Hide start screen temporarily startScreen.visible = false; startButton.visible = false; // Show tutorial screen tutorialScreen.showTutorial(); // Override tutorial close to start game var originalClose = tutorialScreen.closeTutorial; tutorialScreen.closeTutorial = function () { originalClose.call(tutorialScreen); // Start the game after tutorial gameStarted = true; // Stop the pulse animation tween.stop(startButton); // Play background music when game starts LK.playMusic('Arkaplanmuzik1'); // Hide start screen elements startScreen.destroy(); startButton.destroy(); // Flash effect when starting LK.effects.flashScreen(0x00FF00, 500); }; } else { // No kk asset, start game directly gameStarted = true; // Stop the pulse animation tween.stop(startButton); // Play background music when game starts LK.playMusic('Arkaplanmuzik1'); // Hide start screen elements startScreen.destroy(); startButton.destroy(); // Flash effect when starting LK.effects.flashScreen(0x00FF00, 500); } } }; // Player name text removed // Combined score text removed // Scoreboard update function removed // Game variables (single chapter only) var gamePartTitle = "ENDLESS RUNNER"; var gamePartNumber = 1; var isFirstChapter = true; var gameStarted = false; var isSecondPart = false; ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
totalCoins: 0,
powerUps: {},
playerName: "Player",
lastScore: 0,
highScore: 0,
gamesPlayed: 0,
totalDistance: 0,
bestDistance: 0,
achievements: {},
settings: {
soundEnabled: true,
musicEnabled: true,
difficulty: "normal"
}
});
/****
* Classes
****/
var Box = Container.expand(function () {
var self = Container.call(this);
var boxGraphics = self.attachAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFB347 // Bright orange color
});
self.speed = gameSpeed;
self.broken = false;
self.health = 1; // Can be broken in one hit
self.update = function () {
self.x -= self.speed;
};
// Method to break the box and spawn coins
self.breakBox = function (brokenByBullet) {
if (!self.broken) {
self.broken = true;
// Create breaking effect
LK.effects.flashObject(self, 0xFFFFFF, 300);
// Only spawn coins if not broken by bullet
if (!brokenByBullet) {
// Spawn 2-3 coins around the box
var numCoins = 2 + Math.floor(Math.random() * 2);
for (var c = 0; c < numCoins; c++) {
var coin = new Coin();
coin.x = self.x + (Math.random() - 0.5) * 100;
coin.y = self.y + (Math.random() - 0.5) * 80;
coins.push(coin);
game.addChild(coin);
}
}
// Play box breaking sound
LK.getSound('box_break').play();
// Check for boxes above this one and make them fall
for (var i = 0; i < boxes.length; i++) {
var otherBox = boxes[i];
if (!otherBox.broken && otherBox !== self) {
// Check if this box is above the broken box (within range)
var horizontalDistance = Math.abs(otherBox.x - self.x);
var verticalDistance = self.y - otherBox.y;
// If box is above and close horizontally, make it fall
if (horizontalDistance < 60 && verticalDistance > 0 && verticalDistance < 150) {
// Start falling animation
tween(otherBox, {
y: self.y
}, {
duration: 800,
easing: tween.easeOut
});
}
}
}
// Simple fade out without scaling or rotation
tween(self, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('fire_projectile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.speed = 8; // Bullet moves right at reduced speed
self.destroyed = false;
self.update = function () {
self.x += self.speed; // Move bullet to the right
};
// Create minimal particle effects around bullet - reduced count for performance
self.particles = [];
// Create only 2 particles instead of 4
var _loop3 = function _loop3() {
particle = LK.getAsset('fire_projectile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.5,
tint: 0xFF6600
});
self.addChild(particle);
self.particles.push(particle);
// Position particles in a circle around bullet center
angle = p / 2 * Math.PI * 2;
radius = 30;
particle.x = Math.cos(angle) * radius;
particle.y = Math.sin(angle) * radius;
// Simple static positioning - no orbit animation to prevent lag
},
particle,
angle,
radius;
for (var p = 0; p < 2; p++) {
_loop3();
}
// Simplified rotation - no continuous animation to prevent lag
bulletGraphics.rotation = Math.random() * Math.PI * 2; // Random initial rotation only
// Method to destroy the bullet and create minimal explosion effect
self.destroyBullet = function () {
if (!self.destroyed) {
self.destroyed = true;
// Create minimal explosion particles - reduced count for performance
for (var p = 0; p < 3; p++) {
var particle = LK.getAsset('fire_projectile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.8,
x: self.x,
y: self.y,
tint: 0xFF4500
});
game.addChild(particle);
var angle = p / 3 * Math.PI * 2;
var distance = 60;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Simple fade out effect
tween(self, {
alpha: 0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var C10 = Container.expand(function () {
var self = Container.call(this);
var c10Graphics = self.attachAsset('C10', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C11 = Container.expand(function () {
var self = Container.call(this);
var c11Graphics = self.attachAsset('C11', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C12 = Container.expand(function () {
var self = Container.call(this);
var c12Graphics = self.attachAsset('C12', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C13 = Container.expand(function () {
var self = Container.call(this);
var c13Graphics = self.attachAsset('C13', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C14 = Container.expand(function () {
var self = Container.call(this);
var c14Graphics = self.attachAsset('C14', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C15 = Container.expand(function () {
var self = Container.call(this);
var c15Graphics = self.attachAsset('C15', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C16 = Container.expand(function () {
var self = Container.call(this);
var c16Graphics = self.attachAsset('C16', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C2 = Container.expand(function () {
var self = Container.call(this);
var c2Graphics = self.attachAsset('C2', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 200;
self.hitboxHeight = 200;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C3 = Container.expand(function () {
var self = Container.call(this);
var c3Graphics = self.attachAsset('C3', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C4 = Container.expand(function () {
var self = Container.call(this);
var c4Graphics = self.attachAsset('C4', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C5 = Container.expand(function () {
var self = Container.call(this);
var c5Graphics = self.attachAsset('C5', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C6 = Container.expand(function () {
var self = Container.call(this);
var c6Graphics = self.attachAsset('C6', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C7 = Container.expand(function () {
var self = Container.call(this);
var c7Graphics = self.attachAsset('C7', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C8 = Container.expand(function () {
var self = Container.call(this);
var c8Graphics = self.attachAsset('C8', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var C9 = Container.expand(function () {
var self = Container.call(this);
var c9Graphics = self.attachAsset('C9', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('wumpa', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.collected = false;
// Floating animation
self.floatOffset = 0;
self.update = function () {
self.x -= self.speed;
// Floating animation
self.floatOffset += 0.15;
coinGraphics.y = Math.sin(self.floatOffset) * 10;
// Rotation animation
coinGraphics.rotation += 0.1;
};
return self;
});
var DamageBox = Container.expand(function () {
var self = Container.call(this);
var damageBoxGraphics = self.attachAsset('tnt_box', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x8B4513 // Brown box color with TNT styling
});
self.speed = gameSpeed;
self.damaged = false;
self.update = function () {
self.x -= self.speed;
};
// Method to cause damage to player
self.damagePlayer = function () {
if (!self.damaged && !player.isInvulnerable && !godModeActive) {
self.damaged = true;
playerLives--;
// Play heart damage sound when lives decrease
LK.getSound('Canazalma').play();
// Play TNT break sound when dangerous box is damaged
LK.getSound('tnt_break').play();
// Check for TNT boxes above this one and make them fall
for (var i = 0; i < damageBoxes.length; i++) {
var otherDamageBox = damageBoxes[i];
if (!otherDamageBox.damaged && otherDamageBox !== self) {
// Check if this TNT box is above the damaged box (within range)
var horizontalDistance = Math.abs(otherDamageBox.x - self.x);
var verticalDistance = self.y - otherDamageBox.y;
// If TNT box is above and close horizontally, make it fall
if (horizontalDistance < 60 && verticalDistance > 0 && verticalDistance < 150) {
// Start falling animation
tween(otherDamageBox, {
y: self.y
}, {
duration: 800,
easing: tween.easeOut
});
}
}
}
// Add screen shake effect
var originalX = game.x;
var originalY = game.y;
var shakeIntensity = 20;
var shakeDuration = 300;
// Create shake animation sequence
tween(game, {
x: originalX + shakeIntensity,
y: originalY + shakeIntensity * 0.5
}, {
duration: shakeDuration / 6,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX - shakeIntensity,
y: originalY - shakeIntensity * 0.5
}, {
duration: shakeDuration / 6,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX + shakeIntensity * 0.5,
y: originalY + shakeIntensity * 0.3
}, {
duration: shakeDuration / 6,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX - shakeIntensity * 0.5,
y: originalY - shakeIntensity * 0.3
}, {
duration: shakeDuration / 6,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: shakeDuration / 3,
easing: tween.easeOut
});
}
});
}
});
}
});
}
});
// Update heart icons display
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Flash damaged heart when taking damage
if (playerLives >= 0 && playerLives < hearts.length) {
LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500);
}
// Make player invulnerable temporarily
player.isInvulnerable = true;
// Add light red flash effect to player character when colliding with damage objects
tween(player, {
tint: 0xFF6666
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Add full-screen light red flash effect
LK.effects.flashScreen(0xFF6666, 400);
// Remove invulnerability after 2 seconds
LK.setTimeout(function () {
player.isInvulnerable = false;
}, 2000);
// Check for game over
if (playerLives <= 0) {
LK.showGameOver();
}
// Create explosion effect when damaged
self.createExplosion();
}
};
// Method to create explosion effect - reduced particles to prevent lag
self.createExplosion = function () {
// Create explosion particles - reduced count for better performance
for (var p = 0; p < 6; p++) {
var particle = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
alpha: 1.0,
x: self.x,
y: self.y,
tint: 0x654321
});
game.addChild(particle);
var angle = p / 6 * Math.PI * 2;
var distance = 100 + Math.random() * 60;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1)
}, {
duration: 400 + Math.random() * 100,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Hide the damage box
tween(self, {
alpha: 0,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Düşman1 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('dman1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
rotation: -Math.PI / 4 // -45 degrees rotation
});
self.speed = gameSpeed;
self.damaged = false;
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.05;
self.baseY = self.y;
self.update = function () {
// Add wave effect to düşman1 entity
self.floatOffset += self.floatSpeed;
enemyGraphics.y = Math.sin(self.floatOffset) * 12; // Wave movement with 12 pixel amplitude
enemyGraphics.rotation = -Math.PI / 4 + Math.sin(self.floatOffset * 1.2) * 0.08; // Base rotation with wave effect
// Move düşman1 with the map like other game objects
self.x -= self.speed;
};
// Method to damage player on collision
self.damagePlayer = function () {
if (!self.damaged && !player.isInvulnerable && !godModeActive) {
self.damaged = true;
playerLives--;
// Play heart damage sound when lives decrease
LK.getSound('Canazalma').play();
// Add screen shake effect
var originalX = game.x;
var originalY = game.y;
var shakeIntensity = 15;
var shakeDuration = 200;
tween(game, {
x: originalX + shakeIntensity,
y: originalY + shakeIntensity * 0.5
}, {
duration: shakeDuration / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX - shakeIntensity,
y: originalY - shakeIntensity * 0.5
}, {
duration: shakeDuration / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: shakeDuration / 2,
easing: tween.easeOut
});
}
});
}
});
// Update heart icons display
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Flash damaged heart when taking damage
if (playerLives >= 0 && playerLives < hearts.length) {
LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500);
}
// Make player invulnerable temporarily
player.isInvulnerable = true;
// Add light red flash effect to player character body
tween(player, {
tint: 0xFF6666
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Add full-screen light red flash effect
LK.effects.flashScreen(0xFF6666, 400);
// Remove invulnerability after 1.5 seconds
LK.setTimeout(function () {
player.isInvulnerable = false;
}, 1500);
// Check for game over
if (playerLives <= 0) {
LK.showGameOver();
}
// Create explosion effect when damaged
self.createExplosion();
}
};
// Method to create explosion effect
self.createExplosion = function () {
// Create explosion particles
for (var p = 0; p < 5; p++) {
var particle = LK.getAsset('dman1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 1.0,
x: self.x,
y: self.y,
tint: 0xFF4444
});
game.addChild(particle);
var angle = p / 5 * Math.PI * 2;
var distance = 80 + Math.random() * 40;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1)
}, {
duration: 300 + Math.random() * 100,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Hide the enemy
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var EndGate = Container.expand(function () {
var self = Container.call(this);
var gateGraphics = self.attachAsset('B1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700 // Golden color for finish gate
});
// Create circular portal effect inside the gate (same as StartingGate)
var portalCircle = self.attachAsset('B1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: 0,
y: -280,
alpha: 0.8,
tint: 0x00FFFF
});
// Start rotating animation for the portal
function startPortalRotation() {
// Animation removed - portal remains static
}
// Add pulsing animation to make portal more dynamic
function startPortalPulse() {
// Animation removed - portal remains static
}
// Animation functions removed - portal remains static
// Add victory glow effect
var victoryGlow = self.attachAsset('B1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.4,
tint: 0xFFFFFF // White victory glow
});
// Start victory glow pulsing animation
function startVictoryPulse() {
// Animation removed - victory glow remains static
}
// Animation function removed - victory glow remains static
self.speed = gameSpeed;
self.crossed = false;
self.update = function () {
self.x -= self.speed;
};
// Method to trigger win condition
self.triggerWin = function () {
if (!self.crossed) {
self.crossed = true;
// Game completion
var completionMessage = 'GAME COMPLETED!';
var completionColor = 0x00FF00;
// Create victory particle effect
for (var p = 0; p < 20; p++) {
var particle = LK.getAsset('B1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 1.0,
x: self.x,
y: self.y - 200,
tint: p % 3 === 0 ? 0xFFD700 : p % 3 === 1 ? 0xFFFFFF : 0x00FF00
});
game.addChild(particle);
var angle = p / 20 * Math.PI * 2;
var distance = 200 + Math.random() * 150;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y - 200 + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 3
}, {
duration: 1500 + Math.random() * 500,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Chapter completion message removed for Chapter 2
// Flash screen with victory colors
LK.effects.flashScreen(0xFFD700, 800);
// Show intermediate screen after a brief delay
LK.setTimeout(function () {
intermediateScreen.showScreen();
}, 800);
// Final game completion removed - no "You won the game" screen
}
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
var gemGraphics = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5
});
// Create crystalline aura effect
var aura1 = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.4,
tint: 0x00FFFF
});
var aura2 = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.6,
scaleY: 1.6,
alpha: 0.2,
tint: 0x8A2BE2
});
self.speed = gameSpeed;
self.collected = false;
// Crystal aura remains steady without pulsing animation
self.update = function () {
self.x -= self.speed;
// Crystal remains steady without rotation
};
// Method to create particle effect when collected
self.createParticles = function () {
for (var p = 0; p < 8; p++) {
var particle = LK.getAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.8,
x: self.x,
y: self.y,
tint: p % 2 === 0 ? 0x00FFFF : 0x8A2BE2
});
game.addChild(particle);
var angle = p / 8 * Math.PI * 2;
var distance = 150 + Math.random() * 100;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
};
return self;
});
var IntermediateScreen = Container.expand(function () {
var self = Container.call(this);
self.isActive = false;
self.showScreen = function () {
if (self.isActive) return;
self.isActive = true;
// Pause the game
LK.pauseGame();
// Create dark overlay
self.overlay = LK.getAsset('ekn1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.95,
x: 0,
y: 0
});
LK.gui.center.addChild(self.overlay);
// Create main panel
self.panel = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 30,
tint: 0x1a1a2e,
x: 0,
y: 0
});
LK.gui.center.addChild(self.panel);
// Title text
self.titleText = new Text2('CHAPTER COMPLETE!', {
size: 120,
fill: 0xFFD700,
font: "Avenir",
fontWeight: 'bold'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 0;
self.titleText.y = -300;
LK.gui.center.addChild(self.titleText);
// Statistics display
self.statsText = new Text2('Coins Collected: ' + coinCount + '\nDistance Traveled: ' + Math.floor(distanceScore / 10) + 'm\nLives Remaining: ' + playerLives, {
size: 60,
fill: 0xFFFFFF,
font: "Avenir"
});
self.statsText.anchor.set(0.5, 0.5);
self.statsText.x = 0;
self.statsText.y = -100;
LK.gui.center.addChild(self.statsText);
// Continue button
self.continueButton = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
x: 0,
y: 150
});
LK.gui.center.addChild(self.continueButton);
self.continueText = new Text2('CONTINUE TO CHAPTER 2', {
size: 50,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
self.continueText.anchor.set(0.5, 0.5);
self.continueText.x = 0;
self.continueText.y = 150;
LK.gui.center.addChild(self.continueText);
// Add pulse animation to continue button
function continuePulse() {
tween(self.continueButton, {
scaleX: 1.6,
scaleY: 1.6
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.continueButton, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: continuePulse
});
}
});
}
continuePulse();
// Continue button interaction
self.continueButton.down = function () {
self.closeScreen();
};
// Flash effect when showing
LK.effects.flashScreen(0x00FF00, 500);
};
self.closeScreen = function () {
if (!self.isActive) return;
self.isActive = false;
// Stop pulse animation
if (self.continueButton) {
tween.stop(self.continueButton);
}
// Clean up all elements
if (self.overlay) self.overlay.destroy();
if (self.panel) self.panel.destroy();
if (self.titleText) self.titleText.destroy();
if (self.statsText) self.statsText.destroy();
if (self.continueButton) self.continueButton.destroy();
if (self.continueText) self.continueText.destroy();
// Flash effect and start chapter 2
LK.effects.flashScreen(0x00AA00, 300);
// Initialize Chapter 2
self.startChapter2();
};
self.startChapter2 = function () {
// Reset game variables for chapter 2
distanceScore = 0;
coinCount = 0;
gemCount = 0;
playerLives = storage.currentLives || 5;
gameSpeed = 24;
normalSpeed = 24;
crystalSpawned = false;
endGateSpawned = false;
spawnTimer = 0;
trailTimer = 0;
isSecondPart = true;
// Clear all arrays
coins.length = 0;
gems.length = 0;
boxes.length = 0;
damageBoxes.length = 0;
trails.length = 0;
düşman1Enemies.length = 0;
// Reset character switching
currentCharacterIndex = 0;
currentCharacter = characterOrder[currentCharacterIndex];
lastSwapDistance = 0;
nextSwapDistance = 2;
// Reset player
player.x = 400;
player.y = groundY + 20;
player.isJumping = false;
player.velocityY = 0;
player.jumpsRemaining = 2;
player.isInvulnerable = false;
player.isSpinning = false;
// Reset graphics to first character
player.removeChildAt(0);
var newGraphics = player.attachAsset('C1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Reset UI elements
coinText.setText('0');
distanceText.setText('0m');
// Update heart display based on current lives
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
hearts[h].tint = 0xFFFFFF;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Reset progress line elements
progressChar.x = 200;
progressGem.x = 200 + 500 / 1500 * 1120;
progressGem.visible = true;
progressGem.tint = 0xFFFFFF;
progressA1.x = 200 + 30 / 1500 * 1120;
progressA1.visible = true;
progressA1.tint = 0x00FFFF;
progressB1.x = 200 + 1000 / 1000 * 1120;
progressB1.visible = true;
progressB1.tint = 0xFFD700;
// Reset gem UI if exists
if (gemIcon) {
gemIcon.destroy();
gemIcon = null;
}
if (gemText) {
gemText.destroy();
gemText = null;
}
// Reset god mode
if (godModeActive) {
toggleGodMode();
}
// Create new starting gate for chapter 2
if (startingGate) {
startingGate.destroy();
}
startingGate = new StartingGate();
startingGate.x = 400 + 3 * 10;
startingGate.y = groundY + 75;
game.addChild(startingGate);
// Switch to background2 for chapter 2
background2.destroy();
background3.destroy();
// Create new backgrounds using background2 asset
background1 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
background2 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 2250,
y: 0
}));
background3 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 4500,
y: 0
}));
// Replace ground assets with ground2 for chapter 2
ground1.destroy();
ground2.destroy();
ground3.destroy();
// Create new ground elements using ground2 asset
ground1 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY
}));
ground2 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 4008,
y: groundY
}));
ground3 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 8016,
y: groundY
}));
// Resume game
LK.resumeGame();
};
return self;
});
var Ml = Container.expand(function () {
var self = Container.call(this);
var mlGraphics = self.attachAsset('ml', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.6
});
self.speed = gameSpeed;
self.damaged = false;
self.isMovingToPlayer = false; // Track if ml is currently moving towards player
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.05;
self.baseY = self.y;
self.update = function () {
// Add wave effect to ml entity
self.floatOffset += self.floatSpeed;
mlGraphics.y = Math.sin(self.floatOffset) * 15; // Wave movement with 15 pixel amplitude
mlGraphics.rotation = Math.sin(self.floatOffset * 1.5) * 0.1; // Slight rotation wave effect
// Check if any düşman1 entity is on screen to trigger movement
var düşman1OnScreen = false;
for (var i = 0; i < düşman1Enemies.length; i++) {
var enemy = düşman1Enemies[i];
if (enemy.x >= 0 && enemy.x <= 2048) {
düşman1OnScreen = true;
break;
}
}
// If düşman1 is on screen, start moving towards player immediately
if (düşman1OnScreen && !self.damaged) {
// Randomly choose between player's right front face or left back face
var isRightFront = Math.random() < 0.5; // 50% chance for each position
var targetX, targetY;
if (isRightFront) {
// Move towards player's right front face
targetX = player.x + 80; // Position slightly to the right of player
targetY = groundY - 100; // Move towards upper part of ground
} else {
// Move towards player's left back face
targetX = player.x - 80; // Position slightly to the left of player
targetY = groundY - 100; // Move towards upper part of ground
}
// Use tween to smoothly move ml towards target position
if (!self.isMovingToPlayer) {
self.isMovingToPlayer = true;
// Random speed between 10 (slow) and 40 (fast) units - converted to duration
var randomSpeed = 10 + Math.random() * 30; // Speed between 10-40
var randomDuration = 2000 - randomSpeed * 25; // Convert speed to duration (higher speed = lower duration)
tween(self, {
x: targetX,
y: targetY
}, {
duration: randomDuration,
easing: tween.easeOut
});
}
} else if (!düşman1OnScreen) {
// Move ml with the map like other game objects when no düşman1 on screen
self.x -= self.speed;
}
// Check if ml has reached the upper part of ground and destroy it
if (self.y >= groundY - 120) {
// Upper part of ground threshold
self.damaged = true;
self.destroy();
// Remove from mlEntities array will be handled in main update loop
}
};
// Method to damage player on collision
self.damagePlayer = function () {
if (!self.damaged && !player.isInvulnerable && !godModeActive) {
self.damaged = true;
playerLives--;
// Play heart damage sound when lives decrease
LK.getSound('Canazalma').play();
// Add screen shake effect
var originalX = game.x;
var originalY = game.y;
var shakeIntensity = 15;
var shakeDuration = 200;
tween(game, {
x: originalX + shakeIntensity,
y: originalY + shakeIntensity * 0.5
}, {
duration: shakeDuration / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX - shakeIntensity,
y: originalY - shakeIntensity * 0.5
}, {
duration: shakeDuration / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: shakeDuration / 2,
easing: tween.easeOut
});
}
});
}
});
// Update heart icons display
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Flash damaged heart when taking damage
if (playerLives >= 0 && playerLives < hearts.length) {
LK.effects.flashObject(hearts[playerLives], 0xFF0000, 500);
}
// Make player invulnerable temporarily
player.isInvulnerable = true;
// Add light red flash effect to player character body
tween(player, {
tint: 0xFF6666
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Add full-screen light red flash effect
LK.effects.flashScreen(0xFF6666, 400);
// Remove invulnerability after 1.5 seconds
LK.setTimeout(function () {
player.isInvulnerable = false;
}, 1500);
// Check for game over
if (playerLives <= 0) {
LK.showGameOver();
}
// Create explosion effect when damaged
self.createExplosion();
}
};
// Method to create explosion effect
self.createExplosion = function () {
// Create explosion particles
for (var p = 0; p < 5; p++) {
var particle = LK.getAsset('ml', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 1.0,
x: self.x,
y: self.y,
tint: 0xFF4444
});
game.addChild(particle);
var angle = p / 5 * Math.PI * 2;
var distance = 80 + Math.random() * 40;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2 * (Math.random() > 0.5 ? 1 : -1)
}, {
duration: 300 + Math.random() * 100,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Hide the ml entity
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var foxGraphics = self.attachAsset('C1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Set custom hitbox dimensions
self.hitboxWidth = 450;
self.hitboxHeight = 450;
// Override width and height properties for collision detection
Object.defineProperty(self, 'width', {
get: function get() {
return self.hitboxWidth;
},
set: function set(value) {
self.hitboxWidth = value;
}
});
Object.defineProperty(self, 'height', {
get: function get() {
return self.hitboxHeight;
},
set: function set(value) {
self.hitboxHeight = value;
}
});
self.isJumping = false;
self.velocityY = 0;
self.groundY = 2732 - 150 + 20; // Ground level
self.jumpPower = -27;
self.gravity = 1.2;
self.runAnimationTimer = 0;
self.isSpinning = false;
self.spinDamageRadius = 150;
self.jumpsRemaining = 2; // Allow double jump
self.jump = function () {
if (self.jumpsRemaining > 0) {
// First jump or double jump
if (!self.isJumping) {
self.isJumping = true;
}
// Different jump power for double jump
var isDoubleJump = self.jumpsRemaining === 1 && self.isJumping;
if (isDoubleJump) {
// Double jump - higher jump power
self.velocityY = self.jumpPower - 5; // Slightly higher jump (-5 makes it more negative, so higher)
} else {
// Regular jump
self.velocityY = self.jumpPower;
}
self.jumpsRemaining--;
LK.getSound('jump').play();
// Simple jump animation without somersault - just scale effect
var jumpDuration = 300; // Shorter duration for simple jump
// Different animation for double jump
if (isDoubleJump) {
// Double jump animation - enhanced scale effect
tween(foxGraphics, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: jumpDuration,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(foxGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeIn
});
}
});
} else {
// Regular jump animation - simple scale effect
tween(foxGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: jumpDuration,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(foxGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
};
self.spinAttack = function () {
if (!self.isSpinning) {
self.isSpinning = true;
LK.getSound('jump').play(); // Reuse jump sound for spin
// Horizontal rotation animation around character's center
tween(foxGraphics, {
rotation: Math.PI * 4,
// 2 full horizontal rotations
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4500
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isSpinning = false;
foxGraphics.rotation = 0;
foxGraphics.scaleX = 1.0;
foxGraphics.scaleY = 1.0;
foxGraphics.tint = 0xFFFFFF;
}
});
}
};
self.update = function () {
if (self.isJumping) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Land on ground
if (self.y >= self.groundY) {
self.y = self.groundY;
self.isJumping = false;
self.velocityY = 0;
self.jumpsRemaining = 2; // Reset double jump when landing
// Reset character scale when landing
tween(foxGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
}
} else {
// Running animation when on ground
self.runAnimationTimer += 0.2;
foxGraphics.y = Math.sin(self.runAnimationTimer) * 3;
foxGraphics.scaleX = 1.0 + Math.sin(self.runAnimationTimer * 2) * 0.05;
}
};
return self;
});
var StartingGate = Container.expand(function () {
var self = Container.call(this);
var gateGraphics = self.attachAsset('A1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.0,
scaleY: 1.0
});
// Create circular portal effect inside the gate
var portalCircle = self.attachAsset('A1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: 0,
y: -200,
alpha: 0.8,
tint: 0x00FFFF
});
// Start rotating animation for the portal
function startPortalRotation() {
// Animation removed - portal remains static
}
// Add pulsing animation to make portal more dynamic
function startPortalPulse() {
// Animation removed - portal remains static
}
// Animation functions removed - portal remains static
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Store = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.storeItems = [{
id: 'doubleJump',
name: 'Super Jump',
price: 50,
description: 'Higher jumps!',
owned: false
}, {
id: 'coinMagnet',
name: 'Coin Magnet',
price: 100,
description: 'Attract coins!',
owned: false
}, {
id: 'speedBoost',
name: 'Speed Boost',
price: 75,
description: 'Move faster!',
owned: false
}, {
id: 'shield',
name: 'Shield',
price: 150,
description: 'Extra protection!',
owned: false
}];
// Load owned items from storage
for (var i = 0; i < self.storeItems.length; i++) {
var item = self.storeItems[i];
item.owned = storage.powerUps[item.id] || false;
}
self.openStore = function () {
if (self.isOpen) return;
self.isOpen = true;
// Pause the game when store opens
LK.pauseGame();
// Create overlay
self.overlay = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 30,
scaleY: 40,
alpha: 0.9,
tint: 0x000033,
x: 1024,
y: 1366
});
game.addChild(self.overlay);
// Create store panel
self.panel = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 25,
tint: 0x1a1a2e,
x: 1024,
y: 1366
});
game.addChild(self.panel);
// Store title
self.titleText = new Text2('POWER-UP STORE', {
size: 100,
fill: 0xFFD700,
font: "Avenir",
fontWeight: 'bold'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 600;
game.addChild(self.titleText);
// Coin display
var totalCoins = storage.totalCoins || 0;
self.coinDisplay = new Text2('Coins: ' + totalCoins, {
size: 60,
fill: 0xFFD700,
font: "Avenir",
fontWeight: 'bold'
});
self.coinDisplay.anchor.set(0.5, 0.5);
self.coinDisplay.x = 1024;
self.coinDisplay.y = 700;
game.addChild(self.coinDisplay);
// Create store items
self.itemElements = [];
for (var i = 0; i < self.storeItems.length; i++) {
self.createStoreItem(i);
}
// Close button
self.closeButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
tint: 0xFF4444,
x: 1024,
y: 2000
});
game.addChild(self.closeButton);
self.closeText = new Text2('CLOSE', {
size: 50,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
self.closeText.anchor.set(0.5, 0.5);
self.closeText.x = 1024;
self.closeText.y = 2000;
game.addChild(self.closeText);
// Close button interaction
self.closeButton.down = function () {
self.closeStore();
};
// Animate store opening
tween(self.overlay, {
alpha: 0.9
}, {
duration: 300
});
tween(self.panel, {
scaleX: 20,
scaleY: 25
}, {
duration: 400,
easing: tween.easeOut
});
};
self.createStoreItem = function (index) {
var item = self.storeItems[index];
var yPos = 850 + index * 180;
// Item background
var itemBg = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 3,
tint: item.owned ? 0x004400 : 0x333366,
x: 1024,
y: yPos
});
game.addChild(itemBg);
// Item name
var nameText = new Text2(item.name, {
size: 50,
fill: item.owned ? 0x88FF88 : 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 800;
nameText.y = yPos - 20;
game.addChild(nameText);
// Item description
var descText = new Text2(item.description, {
size: 35,
fill: 0xCCCCCC,
font: "Avenir"
});
descText.anchor.set(0.5, 0.5);
descText.x = 800;
descText.y = yPos + 20;
game.addChild(descText);
// Price/Status
var priceText = new Text2(item.owned ? 'OWNED' : item.price + ' coins', {
size: 45,
fill: item.owned ? 0x00FF00 : 0xFFD700,
font: "Avenir",
fontWeight: 'bold'
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 1200;
priceText.y = yPos;
game.addChild(priceText);
// Buy button (only if not owned)
if (!item.owned) {
var buyButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1.5,
tint: 0x00AA00,
x: 1350,
y: yPos
});
game.addChild(buyButton);
var buyText = new Text2('BUY', {
size: 40,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
buyText.anchor.set(0.5, 0.5);
buyText.x = 1350;
buyText.y = yPos;
game.addChild(buyText);
buyButton.down = function () {
self.purchaseItem(index);
};
self.itemElements.push({
bg: itemBg,
name: nameText,
desc: descText,
price: priceText,
buyBtn: buyButton,
buyTxt: buyText
});
} else {
self.itemElements.push({
bg: itemBg,
name: nameText,
desc: descText,
price: priceText
});
}
};
self.purchaseItem = function (index) {
var item = self.storeItems[index];
var totalCoins = storage.totalCoins || 0;
if (totalCoins >= item.price && !item.owned) {
// Purchase successful
storage.totalCoins = totalCoins - item.price;
storage.powerUps[item.id] = true;
item.owned = true;
// Update coin display
self.coinDisplay.setText('Coins: ' + storage.totalCoins);
// Flash effect
LK.effects.flashScreen(0x00FF00, 300);
// Update item appearance
var elements = self.itemElements[index];
elements.bg.tint = 0x004400;
elements.name.fill = 0x88FF88;
elements.price.setText('OWNED');
elements.price.fill = 0x00FF00;
if (elements.buyBtn) {
elements.buyBtn.destroy();
elements.buyTxt.destroy();
}
} else {
// Not enough coins
LK.effects.flashScreen(0xFF0000, 300);
}
};
self.closeStore = function () {
if (!self.isOpen) return;
self.isOpen = false;
// Resume the game when store closes
LK.resumeGame();
// Clean up all store elements
if (self.overlay) self.overlay.destroy();
if (self.panel) self.panel.destroy();
if (self.titleText) self.titleText.destroy();
if (self.coinDisplay) self.coinDisplay.destroy();
if (self.closeButton) self.closeButton.destroy();
if (self.closeText) self.closeText.destroy();
for (var i = 0; i < self.itemElements.length; i++) {
var elements = self.itemElements[i];
elements.bg.destroy();
elements.name.destroy();
elements.desc.destroy();
elements.price.destroy();
if (elements.buyBtn) elements.buyBtn.destroy();
if (elements.buyTxt) elements.buyTxt.destroy();
}
self.itemElements = [];
};
return self;
});
var Trail = Container.expand(function () {
var self = Container.call(this);
var trailGraphics = self.attachAsset('C1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.6,
scaleY: 0.6,
alpha: 0.7
});
self.speed = gameSpeed;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var TutorialScreen = Container.expand(function () {
var self = Container.call(this);
self.isActive = false;
self.currentStep = 0;
self.tutorialSteps = [{
title: "WELCOME TO ENDLESS RUNNER!",
description: "Learn the basics to survive and collect coins",
icon: "C1"
}, {
title: "JUMPING",
description: "Swipe UP to jump over obstacles\nDouble tap for double jump!",
icon: "heart"
}, {
title: "SHOOTING",
description: "Swipe RIGHT to shoot bullets\nNeed gems first, costs 1 coin per shot",
icon: "fire_projectile"
}, {
title: "COLLECTIBLES",
description: "Collect coins and gems\nGems unlock shooting ability",
icon: "wumpa"
}, {
title: "POWER-UPS",
description: "Spin attack destroys enemies\nGod mode for invincibility",
icon: "gem"
}];
self.showTutorial = function () {
if (self.isActive) return;
self.isActive = true;
self.currentStep = 0;
// Create overlay
self.overlay = LK.getAsset('ekn1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.95,
x: 0,
y: 0
});
LK.gui.center.addChild(self.overlay);
// Create tutorial panel
self.panel = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 30,
tint: 0x1a1a2e,
x: 0,
y: 0
});
LK.gui.center.addChild(self.panel);
self.showCurrentStep();
};
self.showCurrentStep = function () {
// Clean up previous step elements
self.cleanupStepElements();
var step = self.tutorialSteps[self.currentStep];
// Tutorial title
self.titleText = new Text2(step.title, {
size: 80,
fill: 0xFFD700,
font: "Avenir",
fontWeight: 'bold'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 0;
self.titleText.y = -400;
LK.gui.center.addChild(self.titleText);
// Tutorial description
self.descText = new Text2(step.description, {
size: 50,
fill: 0xFFFFFF,
font: "Avenir"
});
self.descText.anchor.set(0.5, 0.5);
self.descText.x = 0;
self.descText.y = -250;
LK.gui.center.addChild(self.descText);
// Tutorial icon
self.iconAsset = LK.getAsset(step.icon, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
x: 0,
y: 100
});
LK.gui.center.addChild(self.iconAsset);
// Step counter
self.stepText = new Text2(self.currentStep + 1 + " / " + self.tutorialSteps.length, {
size: 40,
fill: 0x888888,
font: "Avenir"
});
self.stepText.anchor.set(0.5, 0.5);
self.stepText.x = 0;
self.stepText.y = 250;
LK.gui.center.addChild(self.stepText);
// Navigation buttons
if (self.currentStep > 0) {
self.prevButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
tint: 0x666666,
x: -200,
y: 350
});
LK.gui.center.addChild(self.prevButton);
self.prevText = new Text2('PREVIOUS', {
size: 35,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
self.prevText.anchor.set(0.5, 0.5);
self.prevText.x = -200;
self.prevText.y = 350;
LK.gui.center.addChild(self.prevText);
self.prevButton.down = function () {
self.previousStep();
};
}
if (self.currentStep < self.tutorialSteps.length - 1) {
self.nextButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
tint: 0x00AA00,
x: 200,
y: 350
});
LK.gui.center.addChild(self.nextButton);
self.nextText = new Text2('NEXT', {
size: 35,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
self.nextText.anchor.set(0.5, 0.5);
self.nextText.x = 200;
self.nextText.y = 350;
LK.gui.center.addChild(self.nextText);
self.nextButton.down = function () {
self.nextStep();
};
} else {
// Final step - show start button
self.startButton = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
x: 0,
y: 350
});
LK.gui.center.addChild(self.startButton);
self.startButton.down = function () {
self.closeTutorial();
};
}
// Skip button
self.skipButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4444,
x: 0,
y: 450
});
LK.gui.center.addChild(self.skipButton);
self.skipText = new Text2('SKIP TUTORIAL', {
size: 30,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
self.skipText.anchor.set(0.5, 0.5);
self.skipText.x = 0;
self.skipText.y = 450;
LK.gui.center.addChild(self.skipText);
self.skipButton.down = function () {
self.closeTutorial();
};
};
self.nextStep = function () {
if (self.currentStep < self.tutorialSteps.length - 1) {
self.currentStep++;
self.showCurrentStep();
}
};
self.previousStep = function () {
if (self.currentStep > 0) {
self.currentStep--;
self.showCurrentStep();
}
};
self.cleanupStepElements = function () {
if (self.titleText) {
self.titleText.destroy();
self.titleText = null;
}
if (self.descText) {
self.descText.destroy();
self.descText = null;
}
if (self.iconAsset) {
self.iconAsset.destroy();
self.iconAsset = null;
}
if (self.stepText) {
self.stepText.destroy();
self.stepText = null;
}
if (self.prevButton) {
self.prevButton.destroy();
self.prevButton = null;
}
if (self.prevText) {
self.prevText.destroy();
self.prevText = null;
}
if (self.nextButton) {
self.nextButton.destroy();
self.nextButton = null;
}
if (self.nextText) {
self.nextText.destroy();
self.nextText = null;
}
if (self.startButton) {
self.startButton.destroy();
self.startButton = null;
}
if (self.skipButton) {
self.skipButton.destroy();
self.skipButton = null;
}
if (self.skipText) {
self.skipText.destroy();
self.skipText = null;
}
};
self.closeTutorial = function () {
if (!self.isActive) return;
self.isActive = false;
// Clean up all tutorial elements
self.cleanupStepElements();
if (self.overlay) {
self.overlay.destroy();
self.overlay = null;
}
if (self.panel) {
self.panel.destroy();
self.panel = null;
}
// Flash effect when closing
LK.effects.flashScreen(0x00FF00, 300);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var coins = [];
var gems = [];
var boxes = [];
var damageBoxes = [];
var düşman1Enemies = [];
var mlEntities = [];
var trails = [];
var bullets = [];
var gameSpeed = 24;
var spawnTimer = 0;
var coinCount = 0;
var gemCount = 0;
var distanceScore = 0;
var groundY = 2732 - 150 - 2;
var playerLives = 5; // Always start with 5 lives
var trailTimer = 0;
var crystalSpawned = false;
var endGateSpawned = false;
var startingGate;
var endGate;
var background1, background2;
// UI Elements
var coinFrame = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0,
scaleX: 2.5,
scaleY: 2,
tint: 0x000000,
x: 590,
y: 5
});
LK.gui.top.addChild(coinFrame);
var coinIcon = LK.getAsset('coin_icon', {
anchorX: 0.5,
anchorY: 0,
x: 590,
y: 0
});
LK.gui.top.addChild(coinIcon);
var coinText = new Text2('0', {
size: 100,
fill: 0xFF6600,
font: "Avenir",
fontWeight: '900',
stroke: 0x000000,
strokeThickness: 12
});
coinText.anchor.set(0.5, 0);
coinText.x = 590;
coinText.y = 70;
LK.gui.top.addChild(coinText);
// Distance meter - hidden
var distanceText = new Text2('0m', {
size: 140,
fill: 0x00FF00,
font: "avenir",
fontWeight: 'bold',
stroke: 0x000000,
strokeThickness: 20
});
distanceText.anchor.set(1.0, 0);
distanceText.x = 0;
distanceText.y = 20;
distanceText.visible = false;
LK.gui.topRight.addChild(distanceText);
var gemIcon = null;
var gemText = null;
// Create heart UI elements - multiple heart icons for visual health representation
var hearts = [];
var maxHearts = 8; // Maximum collectible lives set to 8
// Initialize storage with current lives at game start
storage.currentLives = playerLives;
storage.currentHearts = playerLives;
// Create multiple heart icons based on current lives count
var savedHeartCount = playerLives;
var _loop = function _loop() {
heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
x: 150 + heartIndex * 100,
y: 193
});
hearts.push(heart);
LK.gui.topLeft.addChild(heart);
// Set initial heart display based on current lives
if (heartIndex < playerLives) {
heart.alpha = 1.0;
heart.tint = 0xFFFFFF;
} else {
heart.alpha = 0.3;
heart.tint = 0x666666;
}
// Add synchronized pulse animation to each heart
function startHeartPulse(heartElement, delay) {
LK.setTimeout(function () {
function pulseUp() {
tween(heartElement, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseDown
});
}
function pulseDown() {
tween(heartElement, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseUp
});
}
pulseUp();
}, delay);
}
// Start synchronized pulse animation with slight delay between hearts
startHeartPulse(heart, heartIndex * 200);
},
heart;
for (var heartIndex = 0; heartIndex < savedHeartCount; heartIndex++) {
_loop();
}
;
// Function to show collectibles summary
function showCollectiblesSummary() {
// Pause all game movement
LK.pauseGame();
// Create matte black screen overlay - add to GUI to stay in front of all assets
var blackOverlay = LK.getAsset('ekn1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0,
x: 0,
y: 0
});
LK.gui.center.addChild(blackOverlay);
// Title text removed
// Collectible items removed from black screen summary
var summaryItems = [];
// Coin icons removed from black screen summary
// Gem icons removed from black screen summary
// Coins summary text removed
// Gems summary text removed
// Total score text removed
// Save final game statistics
var finalDistance = Math.floor(distanceScore / 10);
storage.lastScore = coinCount;
storage.totalCoins = (storage.totalCoins || 0) + coinCount;
if (coinCount > (storage.highScore || 0)) {
storage.highScore = coinCount;
}
if (finalDistance > (storage.bestDistance || 0)) {
storage.bestDistance = finalDistance;
}
storage.gamesPlayed = (storage.gamesPlayed || 0) + 1;
// Save current lives and heart display state for Chapter 2
storage.currentLives = playerLives;
storage.currentHearts = hearts.length;
// Create main menu buttons after delay
LK.setTimeout(function () {
// Square box container for buttons removed
// Create pause button
var pauseButton = LK.getAsset('d2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
x: -150,
y: 200
});
LK.gui.center.addChild(pauseButton);
var pauseButtonText = new Text2('PAUSE', {
size: 60,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
pauseButtonText.anchor.set(0.5, 0.5);
pauseButtonText.x = -150;
pauseButtonText.y = 200;
LK.gui.center.addChild(pauseButtonText);
// Create continue button
var continueButton = LK.getAsset('d1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
x: 150,
y: 200
});
LK.gui.center.addChild(continueButton);
var continueButtonText = new Text2('CONTINUE', {
size: 50,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
continueButtonText.anchor.set(0.5, 0.5);
continueButtonText.x = 150;
continueButtonText.y = 200;
LK.gui.center.addChild(continueButtonText);
// Add button functionality
pauseButton.down = function () {
LK.pauseGame();
LK.effects.flashScreen(0xFF4444, 300);
};
continueButton.down = function () {
// Hide continue button and d1 asset immediately
continueButton.visible = false;
continueButtonText.visible = false;
// Clean up all UI elements
blackOverlay.destroy();
pauseButton.destroy();
pauseButtonText.destroy();
continueButton.destroy();
continueButtonText.destroy();
// Flash effect and reset game for second part
LK.effects.flashScreen(0x00AA00, 300);
// Reset game variables for second part
distanceScore = 0;
coinCount = 0;
gemCount = 0;
playerLives = storage.currentLives || 5; // Load saved lives or default to 5
gameSpeed = 24;
normalSpeed = 24;
crystalSpawned = false;
endGateSpawned = false;
spawnTimer = 0;
trailTimer = 0;
isSecondPart = true;
// Clear all arrays
coins.length = 0;
gems.length = 0;
boxes.length = 0;
damageBoxes.length = 0;
trails.length = 0;
düşman1Enemies.length = 0;
// Reset character switching
currentCharacterIndex = 0;
currentCharacter = characterOrder[currentCharacterIndex];
lastSwapDistance = 0;
nextSwapDistance = 2;
// Reset player
player.x = 400;
player.y = groundY + 20;
player.isJumping = false;
player.velocityY = 0;
player.jumpsRemaining = 2;
player.isInvulnerable = false;
player.isSpinning = false;
// Reset graphics to first character
player.removeChildAt(0);
var newGraphics = player.attachAsset('C1', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
// Reset UI elements
coinText.setText('0');
distanceText.setText('0m');
// Reset heart icons display - preserve saved heart count
var savedHeartCount = storage.currentHearts || 5;
// Ensure we have enough heart icons for saved lives
while (hearts.length < savedHeartCount) {
var heartIndex = hearts.length;
var positionX, positionY;
if (heartIndex < 8) {
positionX = 150 + heartIndex * 100;
positionY = 193;
} else {
positionX = 150 + (heartIndex - 8) * 100;
positionY = 193 + 100;
}
var newHeart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
x: positionX,
y: positionY
});
hearts.push(newHeart);
LK.gui.topLeft.addChild(newHeart);
}
// Update heart display based on current lives
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
hearts[h].tint = 0xFFFFFF;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Reset progress line for second part
progressChar.x = 200;
// Reset progress gem for second part
progressGem.x = 200 + 500 / 1500 * 1120; // Position at 500m mark
progressGem.visible = true;
progressGem.tint = 0xFFFFFF;
// Reset progress A1 for second part
progressA1.x = 200 + 30 / 1500 * 1120; // Position at 30m mark
progressA1.visible = true;
progressA1.tint = 0x00FFFF;
// Reset progress B1 for second part
progressB1.x = 200 + 1000 / 1000 * 1120; // Position at 1000m mark (end of line)
progressB1.visible = true;
progressB1.tint = 0xFFD700;
// Reset gem UI if exists
if (gemIcon) {
gemIcon.destroy();
gemIcon = null;
}
if (gemText) {
gemText.destroy();
gemText = null;
}
// Reset hearts display to match current lives
for (var h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
hearts[h].tint = 0xFFFFFF;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Reset god mode
if (godModeActive) {
toggleGodMode();
}
// Create new starting gate for second part
if (startingGate) {
startingGate.destroy();
}
startingGate = new StartingGate();
startingGate.x = 400 + 3 * 10;
startingGate.y = groundY + 75;
game.addChild(startingGate);
// Switch to background2 for second part
background2.destroy();
background3.destroy();
// Create new backgrounds using background2 asset
background1 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
background2 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 2250,
y: 0
}));
background3 = game.addChild(LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 4500,
y: 0
}));
// Replace ground assets with ground2 for second part
ground1.destroy();
ground2.destroy();
ground3.destroy();
// Create new ground elements using ground2 asset
ground1 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY
}));
ground2 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 4008,
// Position second ground at end of first ground
y: groundY
}));
ground3 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 8016,
// Position third ground to eliminate gaps during transitions
y: groundY
}));
// Resume game movement
LK.resumeGame();
};
}, 2000);
}
;
;
// Spin button removed
// Background music will be played when game starts
// Create animated background elements for endless scrolling with third element to fill gaps
var background1 = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
// Position first background starting behind character
y: 0
}));
var background2 = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 2250,
// Position second background at end of first background
y: 0
}));
var background3 = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 4500,
// Position third background to eliminate gaps during transitions
y: 0
}));
// Create animated ground elements for endless scrolling
var ground1 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY
}));
var ground2 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 4008,
// Position second ground at end of first ground
y: groundY
}));
var ground3 = game.addChild(LK.getAsset('ground2', {
anchorX: 0,
anchorY: 0,
x: 8016,
// Position third ground to eliminate gaps during transitions
y: groundY
}));
// Ground animation variables
var groundAnimationTimer = 0;
// Create starting gate
startingGate = new StartingGate();
startingGate.x = 400 + 3 * 10; // Position at 3 meters (3m * 10 pixels per meter)
startingGate.y = groundY + 75; // Position gate a little higher above the ground
game.addChild(startingGate);
// Create player (will be added to foreground later)
player = new Player();
player.x = 400;
player.y = groundY + 20;
player.isInvulnerable = false;
// Touch controls for swipe up to jump and swipe right to shoot
var touchStartY = null;
var touchStartX = null;
var minSwipeDistance = 100; // Minimum distance for swipe detection
game.down = function (x, y, obj) {
touchStartY = y;
touchStartX = x;
};
// Bullet firing timer
var lastBulletTime = 0;
var bulletCooldown = 300; // 0.3 second cooldown in milliseconds
game.up = function (x, y, obj) {
if (touchStartY !== null && touchStartX !== null) {
var swipeDistanceY = touchStartY - y; // Positive means swipe up
var swipeDistanceX = x - touchStartX; // Positive means swipe right
if (swipeDistanceY >= minSwipeDistance) {
// Swipe up detected - make player jump
player.jump();
} else if (swipeDistanceX >= minSwipeDistance) {
// Swipe right detected - shoot bullet only if we have gems collected and coins available
var currentTime = LK.ticks * 16.67; // Use game ticks for more stable timing
if (gemCount > 0 && coinCount > 0 && currentTime - lastBulletTime >= bulletCooldown) {
var bullet = new Bullet();
bullet.x = player.x + 50; // Start bullet slightly ahead of player
bullet.y = player.y - 50; // Start bullet at player's center height
bullets.push(bullet);
game.addChild(bullet);
// Play bullet sound when firing
LK.getSound('bullet_sound').play();
// Consume one coin for bullet (after gem has been collected)
coinCount--;
coinText.setText(coinCount);
// Update last bullet time
lastBulletTime = currentTime;
} else {
// No gems collected or no coins available or cooldown active - don't show flash effect
}
}
touchStartY = null;
touchStartX = null;
}
};
// Spin button interaction removed
function spawnCoin() {
var coin = new Coin();
coin.x = 2048 + 100;
// Randomly place coins either high in air or at medium height to avoid ground-level objects
var coinHeightOptions = [groundY - 300 - Math.random() * 100,
// High in air
groundY - 180 - Math.random() * 80 // Medium height
];
coin.y = coinHeightOptions[Math.floor(Math.random() * coinHeightOptions.length)];
coins.push(coin);
game.addChild(coin);
}
function spawnGem() {
var gem = new Gem();
gem.x = 2048 + 100;
gem.y = groundY - 80 - Math.random() * 200;
gems.push(gem);
game.addChild(gem);
}
function spawnBox() {
// Randomly decide formation type: 1 box (20%), 2 boxes (30%), 3 boxes (30%), or 2x2 arrangement (20%)
var formationType = Math.random();
if (formationType < 0.2) {
// Single box
var box = new Box();
box.x = 2048 + 100;
box.y = groundY - 45;
boxes.push(box);
game.addChild(box);
} else if (formationType < 0.5) {
// 2 boxes - randomly horizontal or vertical
var isHorizontal = Math.random() < 0.5;
if (isHorizontal) {
// 2 boxes horizontally
for (var i = 0; i < 2; i++) {
var box = new Box();
box.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally
box.y = groundY - 45; // All at same height (ground level)
boxes.push(box);
game.addChild(box);
}
} else {
// 2 boxes vertically
for (var i = 0; i < 2; i++) {
var box = new Box();
box.x = 2048 + 100; // All at same x position
box.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing
boxes.push(box);
game.addChild(box);
}
}
} else if (formationType < 0.8) {
// 3 boxes - randomly horizontal or vertical
var isHorizontal = Math.random() < 0.5;
if (isHorizontal) {
// Create 3 boxes in a horizontal row
for (var i = 0; i < 3; i++) {
var box = new Box();
box.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally
box.y = groundY - 45; // All at same height (ground level)
boxes.push(box);
game.addChild(box);
}
} else {
// Create 3 boxes in a vertical column
for (var i = 0; i < 3; i++) {
var box = new Box();
box.x = 2048 + 100; // All at same x position
box.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing
boxes.push(box);
game.addChild(box);
}
}
} else {
// 2x2 arrangement (4 boxes in a square)
for (var i = 0; i < 2; i++) {
for (var j = 0; j < 2; j++) {
var box = new Box();
box.x = 2048 + 100 + i * 130; // Horizontal spacing
box.y = groundY - 45 - j * 120; // Vertical spacing
boxes.push(box);
game.addChild(box);
}
}
}
}
function spawnDamageBox() {
// Randomly decide formation type: 1 box (20%), 2 boxes (30%), 3 boxes (30%), or 2x2 arrangement (20%)
var formationType = Math.random();
if (formationType < 0.2) {
// Single TNT box
var damageBox = new DamageBox();
damageBox.x = 2048 + 100;
damageBox.y = groundY - 45;
damageBoxes.push(damageBox);
game.addChild(damageBox);
} else if (formationType < 0.5) {
// 2 TNT boxes - randomly horizontal or vertical
var isHorizontal = Math.random() < 0.5;
if (isHorizontal) {
// 2 TNT boxes horizontally
for (var i = 0; i < 2; i++) {
var damageBox = new DamageBox();
damageBox.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally
damageBox.y = groundY - 45; // All at same height (ground level)
damageBoxes.push(damageBox);
game.addChild(damageBox);
}
} else {
// 2 TNT boxes vertically
for (var i = 0; i < 2; i++) {
var damageBox = new DamageBox();
damageBox.x = 2048 + 100; // All at same x position
damageBox.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing
damageBoxes.push(damageBox);
game.addChild(damageBox);
}
}
} else if (formationType < 0.8) {
// 3 TNT boxes - randomly horizontal or vertical
var isHorizontal = Math.random() < 0.5;
if (isHorizontal) {
// Create 3 TNT boxes in a horizontal row
for (var i = 0; i < 3; i++) {
var damageBox = new DamageBox();
damageBox.x = 2048 + 100 + i * 130; // Space boxes 130 pixels apart horizontally
damageBox.y = groundY - 45; // All at same height (ground level)
damageBoxes.push(damageBox);
game.addChild(damageBox);
}
} else {
// Create 3 TNT boxes in a vertical column
for (var i = 0; i < 3; i++) {
var damageBox = new DamageBox();
damageBox.x = 2048 + 100; // All at same x position
damageBox.y = groundY - 45 - i * 120; // Stack vertically with 120 pixel spacing
damageBoxes.push(damageBox);
game.addChild(damageBox);
}
}
} else {
// 2x2 arrangement (4 TNT boxes in a square)
for (var i = 0; i < 2; i++) {
for (var j = 0; j < 2; j++) {
var damageBox = new DamageBox();
damageBox.x = 2048 + 100 + i * 130; // Horizontal spacing
damageBox.y = groundY - 45 - j * 120; // Vertical spacing
damageBoxes.push(damageBox);
game.addChild(damageBox);
}
}
}
}
function spawnMl() {
var ml = new Ml();
ml.x = 2048 + 100; // Position ml from right side like other spawned objects
ml.y = 1700; // Position at y=1700 (moved up from 1960, same as düşman1)
ml.baseY = ml.y;
mlEntities.push(ml);
game.addChild(ml);
}
function spawnDüşman1() {
var enemy = new Düşman1();
enemy.x = 2048 + 100; // Position enemy from right side like other spawned objects
enemy.y = 1700; // Position at y=1700 (moved up from 1960)
enemy.baseY = enemy.y;
düşman1Enemies.push(enemy);
game.addChild(enemy);
}
game.update = function () {
// Only run game logic if game has started
if (!gameStarted) {
return;
}
// Increase distance score
distanceScore += 1.5;
// Update distance meter display
var currentDistance = Math.floor(distanceScore / 10);
distanceText.setText(currentDistance + 'm');
// Update progress line elements
var targetDistance = 1000; // Distance to reach 2nd part
var progressPercent = Math.min(currentDistance / targetDistance, 1.0);
var lineWidth = 480; // Total width of progress line - shortened horizontally
// Move mini character along the progress line
progressChar.x = 200 + progressPercent * lineWidth;
// Update gem position on progress line
var gemDistance = 500; // Gem spawns at 500 meters
var gemProgressPercent = Math.min(gemDistance / targetDistance, 1.0);
progressGem.x = 200 + gemProgressPercent * lineWidth;
// Show/hide gem based on whether it's been collected
if (crystalSpawned && gemCount > 0) {
// Gem has been collected - hide it
progressGem.visible = false;
} else if (currentDistance >= gemDistance) {
// Past gem location but not collected - make it red to indicate missed
progressGem.tint = 0xFF0000;
progressGem.visible = true;
} else {
// Gem not yet reached - show normal gem color
progressGem.tint = 0xFFFFFF;
progressGem.visible = true;
}
// Update A1 entity position on progress line
var a1Distance = 30; // A1 spawns at 30 meters (starting gate location)
var a1ProgressPercent = Math.min(a1Distance / targetDistance, 1.0);
progressA1.x = 200 + a1ProgressPercent * lineWidth;
// Show/hide A1 based on whether it's been passed
if (currentDistance >= a1Distance + 50) {
// Well past A1 location - hide it
progressA1.visible = false;
} else if (currentDistance >= a1Distance) {
// At or past A1 location - show it clearly
progressA1.tint = 0x00FF00;
progressA1.visible = true;
} else {
// A1 not yet reached - show normal cyan color
progressA1.tint = 0x00FFFF;
progressA1.visible = true;
}
// Update B1 entity position on progress line
var b1Distance = 1000; // B1 spawns at 1000 meters (end gate)
var b1ProgressPercent = Math.min(b1Distance / targetDistance, 1.0);
progressB1.x = 200 + b1ProgressPercent * lineWidth;
// Show/hide B1 based on whether it's been reached
if (endGateSpawned && endGate && endGate.crossed) {
// End gate has been crossed - hide it
progressB1.visible = false;
} else if (currentDistance >= b1Distance) {
// At or past B1 location - show it clearly
progressB1.tint = 0x00FF00;
progressB1.visible = true;
} else {
// B1 not yet reached - show normal golden color
progressB1.tint = 0xFFD700;
progressB1.visible = true;
}
// Remaining distance text updates removed
// Update mini character asset to match current player character - less frequent updates
if (LK.ticks % 7 == 0) {
if (progressChar && progressChar.children.length > 0) {
progressChar.removeChildAt(0);
}
if (progressChar) {
var miniCharGraphics = progressChar.attachAsset(currentCharacter, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
}
}
// Character switching logic - cycle through all 7 characters every 7 frames
if (LK.ticks % 7 == 0) {
// Move to next character in the cycle
currentCharacterIndex = (currentCharacterIndex + 1) % characterOrder.length;
currentCharacter = characterOrder[currentCharacterIndex];
// Remove old graphics and add new character graphics
if (player && player.children.length > 0) {
player.removeChildAt(0); // Remove current graphics
}
if (player) {
var newGraphics = player.attachAsset(currentCharacter, {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.2,
scaleY: 1.2
});
}
// Visual feedback for swap
LK.effects.flashObject(player, 0xFFFFFF, 300);
}
// Gradually increase speed - but respect God mode
if (!godModeActive) {
gameSpeed = Math.min(24 + distanceScore / 1000, 60); // Cap at 60 for performance
normalSpeed = Math.min(24 + distanceScore / 1000, 60); // Track normal speed for God mode toggle
} else {
gameSpeed = Math.min(normalSpeed * 2.5, 100); // Reduced multiplier and capped at 100
}
// Update starting gate
if (startingGate && startingGate.parent) {
startingGate.speed = gameSpeed;
// Remove gate when it goes off screen
if (startingGate.x < -200) {
startingGate.destroy();
startingGate = null;
}
}
// Update end gate
if (endGate && endGate.parent) {
endGate.speed = gameSpeed;
// Remove gate when it goes off screen (after win condition)
if (endGate.x < -400) {
endGate.destroy();
endGate = null;
}
}
// Move all background elements with game progression (same speed as ground - no parallax effect)
background1.x -= gameSpeed;
background2.x -= gameSpeed;
background3.x -= gameSpeed;
// Reset background positions for endless scrolling with immediate positioning to eliminate gaps
if (background1.x <= -2250) {
// Find the rightmost background element
var rightmostX = Math.max(background2.x, background3.x);
// Immediately position to eliminate gaps
background1.x = rightmostX + 2250;
}
if (background2.x <= -2250) {
// Find the rightmost background element
var rightmostX = Math.max(background1.x, background3.x);
// Immediately position to eliminate gaps
background2.x = rightmostX + 2250;
}
if (background3.x <= -2250) {
// Find the rightmost background element
var rightmostX = Math.max(background1.x, background2.x);
// Immediately position to eliminate gaps
background3.x = rightmostX + 2250;
}
// Move all ground elements with game progression
ground1.x -= gameSpeed;
ground2.x -= gameSpeed;
ground3.x -= gameSpeed;
// Reset ground positions for endless scrolling with immediate positioning to eliminate gaps
if (ground1.x <= -4008) {
// Find the rightmost ground element
var rightmostX = Math.max(ground2.x, ground3.x);
// Immediately position to eliminate gaps
ground1.x = rightmostX + 4008;
}
if (ground2.x <= -4008) {
// Find the rightmost ground element
var rightmostX = Math.max(ground1.x, ground3.x);
// Immediately position to eliminate gaps
ground2.x = rightmostX + 4008;
}
if (ground3.x <= -4008) {
// Find the rightmost ground element
var rightmostX = Math.max(ground1.x, ground2.x);
// Immediately position to eliminate gaps
ground3.x = rightmostX + 4008;
}
// Background animations removed - backgrounds remain static
groundAnimationTimer += 0.1;
// Keep backgrounds at fixed positions
background1.y = 0;
background2.y = 0;
background3.y = 0;
// Keep backgrounds at fixed scale
background1.scaleY = 1.0;
background2.scaleY = 1.0;
background3.scaleY = 1.0;
// Ground animations removed - ground remains static
// Keep ground at fixed positions
ground1.y = groundY;
ground2.y = groundY;
ground3.y = groundY;
// Keep ground at fixed scale
ground1.scaleY = 1.0;
ground2.scaleY = 1.0;
ground3.scaleY = 1.0;
// Update spawn timer
spawnTimer++;
trailTimer++;
// Create trail when player is jumping - reduced frequency to prevent lag
if (player.isJumping && trailTimer % 8 == 0) {
var trail = new Trail();
trail.x = player.x;
trail.y = player.y;
trail.speed = gameSpeed;
trails.push(trail);
game.addChild(trail);
// Fade out trail with shorter duration
tween(trail, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 300,
onFinish: function onFinish() {
trail.destroy();
}
});
}
// Spawn additional coins with reduced frequency for less air appearance
if (spawnTimer % 45 == 0 && Math.random() < 0.3) {
spawnCoin();
}
// Spawn boxes occasionally
if (spawnTimer % 90 == 0 && Math.random() < 0.6) {
spawnBox();
}
// Spawn damage boxes occasionally (less frequent than regular boxes)
if (spawnTimer % 120 == 0 && Math.random() < 0.4) {
spawnDamageBox();
}
// Spawn ml and düşman1 together at the same time and position - only in second part
if (spawnTimer % 100 == 0 && Math.random() < 0.3 && isSecondPart) {
// Create both entities at the same position
var ml = new Ml();
ml.x = 2048 + 100; // Position ml at exactly the same x as düşman1
ml.y = 1700; // Move both entities up by 260 pixels (1960 - 260 = 1700)
ml.baseY = ml.y;
mlEntities.push(ml);
game.addChild(ml);
var enemy = new Düşman1();
enemy.x = 2048 + 100; // Position enemy from right side like other spawned objects
enemy.y = 1700; // Move both entities up by 260 pixels (1960 - 260 = 1700)
enemy.baseY = enemy.y;
düşman1Enemies.push(enemy);
game.addChild(enemy);
}
// Spawn crystal at exactly 500 meters (within 1000 meters)
var currentDistance = Math.floor(distanceScore / 10);
if (currentDistance >= 500 && !crystalSpawned) {
spawnGem();
crystalSpawned = true;
}
// Spawn end gate at exactly 1000 meters
var endGateDistance = 1000;
if (currentDistance >= endGateDistance && !endGateSpawned) {
endGate = new EndGate();
endGate.x = 2048 + 200; // Spawn off-screen right
endGate.y = groundY + 75; // Same position as starting gate
game.addChild(endGate);
endGateSpawned = true;
}
// Check if player crosses the end gate
if (endGate && endGate.parent && !endGate.crossed) {
if (player.x >= endGate.x - 50 && player.x <= endGate.x + 50) {
endGate.triggerWin();
}
}
// Update and check coins
var _loop2 = function _loop2() {
coin = coins[j];
coin.speed = gameSpeed;
// Check collection or spin attack
distanceX = coin.x - player.x;
distanceY = coin.y - player.y;
distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius;
if (!coin.collected && (player.intersects(coin) || isInSpinRange)) {
coin.collected = true;
coinCount++;
// Add coin to total persistent storage
storage.totalCoins = (storage.totalCoins || 0) + 1;
LK.setScore(coinCount);
coinText.setText(coinCount);
// Font is already set in the Text2 constructor, no need to change it here
// Scoreboard update removed
// Check if player gets a new chance every 50 coins
if (coinCount > 0 && coinCount % 50 === 0) {
playerLives++;
// Add new heart icon if needed
if (playerLives > hearts.length) {
// Start synchronized pulse animation for new heart
var startNewHeartPulse = function startNewHeartPulse(heartElement) {
function pulseUp() {
tween(heartElement, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseDown
});
}
function pulseDown() {
tween(heartElement, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseUp
});
}
pulseUp();
};
heartIndex = hearts.length;
// Position hearts: first 8 in a row, then below for additional hearts
if (heartIndex < 8) {
positionX = 150 + heartIndex * 100;
positionY = 193;
} else {
positionX = 150 + (heartIndex - 8) * 100;
positionY = 193 + 100; // Position below initial row
}
newHeart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
x: positionX,
y: positionY
});
hearts.push(newHeart);
LK.gui.topLeft.addChild(newHeart);
startNewHeartPulse(newHeart);
}
// Update heart icons display
for (h = 0; h < hearts.length; h++) {
if (h < playerLives) {
hearts[h].alpha = 1.0;
hearts[h].tint = 0xFFFFFF;
} else {
hearts[h].alpha = 0.3;
hearts[h].tint = 0x666666;
}
}
// Flash effect for new chance
LK.effects.flashScreen(0x00FF00, 500);
// Flash all active hearts for new chance
for (h = 0; h < Math.min(playerLives, hearts.length); h++) {
LK.effects.flashObject(hearts[h], 0x00FF00, 800);
}
}
LK.getSound('coin').play();
// Visual feedback - enhanced for spin attacks
if (isInSpinRange) {
LK.effects.flashObject(coin, 0xFF4500, 300);
} else {
LK.effects.flashObject(coin, 0xFFFFFF, 300);
}
tween(coin, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(j, 1);
return 0; // continue
}
// Remove off-screen coins
if (coin.x < -50) {
coin.destroy();
coins.splice(j, 1);
return 0; // continue
}
},
coin,
distanceX,
distanceY,
distance,
isInSpinRange,
heartIndex,
positionX,
positionY,
newHeart,
h,
h,
_ret;
for (var j = coins.length - 1; j >= 0; j--) {
_ret = _loop2();
if (_ret === 0) continue;
}
// Update and check gems
for (var g = gems.length - 1; g >= 0; g--) {
var gem = gems[g];
gem.speed = gameSpeed;
// Check collection or spin attack
var distanceX = gem.x - player.x;
var distanceY = gem.y - player.y;
var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius;
if (!gem.collected && (player.intersects(gem) || isInSpinRange)) {
gem.collected = true;
gemCount++;
coinCount += 5; // Gems are worth 5 points
// Add gem bonus to total coins storage
storage.totalCoins = (storage.totalCoins || 0) + 5;
LK.setScore(coinCount);
coinText.setText(coinCount);
// Scoreboard update removed
// Create gem UI elements on first gem collection
if (!gemIcon) {
gemIcon = LK.getAsset('gem_icon', {
anchorX: 0.5,
anchorY: 0,
x: 150,
y: 20
});
LK.gui.top.addChild(gemIcon);
gemText = new Text2('0', {
size: 100,
fill: 0xFF69B4,
font: "Avenir",
fontWeight: '900',
stroke: 0x000000,
strokeThickness: 15
});
gemText.anchor.set(0.5, 0);
gemText.x = 150;
gemText.y = 90;
LK.gui.top.addChild(gemText);
}
gemText.setText(gemCount);
// Font is already set in the Text2 constructor, no need to change it here
LK.getSound('gem_collect').play();
LK.getSound('happy_giggle').play();
// Fade out gem UI elements after 2 seconds
LK.setTimeout(function () {
if (gemIcon && gemIcon.parent) {
tween(gemIcon, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
gemIcon.destroy();
gemIcon = null;
}
});
}
if (gemText && gemText.parent) {
tween(gemText, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
gemText.destroy();
gemText = null;
}
});
}
}, 2000);
// Visual feedback with particle explosion - enhanced for spin attacks
if (isInSpinRange) {
LK.effects.flashScreen(0xFF4500, 200);
} else {
LK.effects.flashScreen(0x00FFFF, 200);
}
gem.createParticles();
gem.destroy();
gems.splice(g, 1);
continue;
}
// Remove off-screen gems
if (gem.x < -50) {
gem.destroy();
gems.splice(g, 1);
continue;
}
}
// Update and check bullets - optimized collision detection
for (var bullet_i = bullets.length - 1; bullet_i >= 0; bullet_i--) {
var bullet = bullets[bullet_i];
if (!bullet || bullet.destroyed) {
bullets.splice(bullet_i, 1);
continue;
}
// Quick bounds check before expensive intersection tests
if (bullet.x < -50 || bullet.x > 2200) {
bullet.destroy();
bullets.splice(bullet_i, 1);
continue;
}
// Check bullet collision with boxes
var bulletDestroyed = false;
for (var b = boxes.length - 1; b >= 0 && !bulletDestroyed; b--) {
var box = boxes[b];
if (box && !box.broken && bullet.intersects(box)) {
box.breakBox(true);
boxes.splice(b, 1);
bullet.destroyBullet();
bullets.splice(bullet_i, 1);
bulletDestroyed = true;
}
}
if (bulletDestroyed) continue;
// Check bullet collision with damage boxes (TNT)
for (var d = damageBoxes.length - 1; d >= 0; d--) {
var damageBox = damageBoxes[d];
if (!damageBox.damaged && bullet.intersects(damageBox)) {
// Create explosion effect for TNT without damaging player
damageBox.createExplosion();
damageBox.destroy();
damageBoxes.splice(d, 1);
bullet.destroyBullet();
bullets.splice(bullet_i, 1);
break;
}
}
// Check bullet collision with ml entities
for (var m = mlEntities.length - 1; m >= 0; m--) {
var ml = mlEntities[m];
if (!ml.damaged && bullet.intersects(ml)) {
ml.damaged = true;
// Create explosion effect
ml.createExplosion();
mlEntities.splice(m, 1);
bullet.destroyBullet();
bullets.splice(bullet_i, 1);
break;
}
}
// Check bullet collision with düşman1 enemies
for (var e = düşman1Enemies.length - 1; e >= 0; e--) {
var enemy = düşman1Enemies[e];
if (!enemy.damaged && bullet.intersects(enemy)) {
enemy.damaged = true;
// Create explosion effect
enemy.createExplosion();
düşman1Enemies.splice(e, 1);
bullet.destroyBullet();
bullets.splice(bullet_i, 1);
break;
}
}
// Remove off-screen bullets
if (bullet.x > 2200 || bullet.destroyed) {
bullet.destroy();
bullets.splice(bullet_i, 1);
continue;
}
}
// Update and check boxes
for (var b = boxes.length - 1; b >= 0; b--) {
var box = boxes[b];
box.speed = gameSpeed;
// Check collision with player or spin attack
var distanceX = box.x - player.x;
var distanceY = box.y - player.y;
var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius;
if (!box.broken && (player.intersects(box) || isInSpinRange)) {
box.breakBox(false);
boxes.splice(b, 1);
continue;
}
// Remove off-screen boxes
if (box.x < -50) {
box.destroy();
boxes.splice(b, 1);
continue;
}
}
// Update and check damage boxes
for (var d = damageBoxes.length - 1; d >= 0; d--) {
var damageBox = damageBoxes[d];
damageBox.speed = gameSpeed;
// Check collision with player (damage boxes can't be destroyed by spin attack)
if (!damageBox.damaged && player.intersects(damageBox)) {
damageBox.damagePlayer();
damageBoxes.splice(d, 1);
continue;
}
// Remove off-screen damage boxes
if (damageBox.x < -50) {
damageBox.destroy();
damageBoxes.splice(d, 1);
continue;
}
}
// Update and clean up trails - more aggressive cleanup to prevent lag
for (var k = trails.length - 1; k >= 0; k--) {
var trail = trails[k];
trail.speed = gameSpeed;
// Remove off-screen, faded, or old trails more aggressively
if (trail.x < -50 || trail.alpha <= 0.2) {
trail.destroy();
trails.splice(k, 1);
continue;
}
}
// Update and check ml entities
for (var m = mlEntities.length - 1; m >= 0; m--) {
var ml = mlEntities[m];
ml.speed = gameSpeed;
// Check collision with player
if (!ml.damaged && player.intersects(ml)) {
ml.damagePlayer();
mlEntities.splice(m, 1);
continue;
}
// Check if ml can be destroyed by spin attack
var distanceX = ml.x - player.x;
var distanceY = ml.y - player.y;
var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius;
if (isInSpinRange && !ml.damaged) {
ml.damaged = true;
// Create explosion effect
ml.createExplosion();
mlEntities.splice(m, 1);
continue;
}
// Remove off-screen ml entities
if (ml.x < -100) {
ml.destroy();
mlEntities.splice(m, 1);
continue;
}
}
// Update and check düşman1 enemies
for (var e = düşman1Enemies.length - 1; e >= 0; e--) {
var enemy = düşman1Enemies[e];
if (!enemy || enemy.damaged) {
düşman1Enemies.splice(e, 1);
continue;
}
enemy.speed = gameSpeed;
// Check collision with player
if (!enemy.damaged && player.intersects(enemy)) {
enemy.damagePlayer();
düşman1Enemies.splice(e, 1);
continue;
}
// Check if enemy can be destroyed by spin attack
var distanceX = enemy.x - player.x;
var distanceY = enemy.y - player.y;
var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
var isInSpinRange = player.isSpinning && distance <= player.spinDamageRadius;
if (isInSpinRange && !enemy.damaged) {
enemy.damaged = true;
// Create explosion effect
enemy.createExplosion();
düşman1Enemies.splice(e, 1);
continue;
}
// Remove off-screen enemies
if (enemy.x < -100) {
enemy.destroy();
düşman1Enemies.splice(e, 1);
continue;
}
}
// Zoom in effect - scale the game container by 10 units
game.scaleX = 1.0 + 10 / 1000; // Convert 10 units to scale factor
game.scaleY = 1.0 + 10 / 1000; // Convert 10 units to scale factor
// Music will transition automatically when first track ends
// Ensure player stays in foreground - less frequent checks to prevent lag
if (LK.ticks % 30 == 0) {
if (player.parent !== game) {
game.addChild(player);
} else {
// Move player to top of render order
game.removeChild(player);
game.addChild(player);
}
}
// Move player to front layer order every frame for maximum visibility
if (player && player.parent === game) {
game.removeChild(player);
game.addChild(player);
}
};
// Scoreboard background removed
// Game pause/resume functionality
var gamePaused = false;
var pausedUpdateFunction = null;
LK.pauseGame = function () {
if (!gamePaused) {
gamePaused = true;
pausedUpdateFunction = game.update;
game.update = function () {
// Game is paused - no updates
};
}
};
LK.resumeGame = function () {
if (gamePaused) {
gamePaused = false;
if (pausedUpdateFunction) {
game.update = pausedUpdateFunction;
pausedUpdateFunction = null;
}
}
};
// Initialize store
var store = new Store();
// Initialize tutorial screen
var tutorialScreen = new TutorialScreen();
// Initialize intermediate screen
var intermediateScreen = new IntermediateScreen();
// God Mode variables
var godModeActive = false;
var normalSpeed = 24;
// God Mode button - now hidden
var godModeButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2,
tint: 0xFF4444,
x: 0,
y: 400
});
godModeButton.visible = false;
LK.gui.topLeft.addChild(godModeButton);
var godModeButtonText = new Text2('GOD MODE', {
size: 35,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
godModeButtonText.anchor.set(0.5, 0.5);
godModeButtonText.x = 0;
godModeButtonText.y = 400;
godModeButtonText.visible = false;
LK.gui.topLeft.addChild(godModeButtonText);
// Teleport button - now hidden
var teleportButton = LK.getAsset('box1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2,
tint: 0x8A2BE2,
x: 0,
y: 520
});
teleportButton.visible = false;
LK.gui.topLeft.addChild(teleportButton);
godModeButton.down = function () {
toggleGodMode();
};
// var teleportButtonText = new Text2('TELEPORT', {
var teleportButtonText = new Text2('TELEPORT', {
size: 30,
fill: 0xFFFFFF,
font: "Avenir",
fontWeight: 'bold'
});
teleportButtonText.anchor.set(0.5, 0.5);
teleportButtonText.x = 0;
teleportButtonText.y = 520;
teleportButtonText.visible = false;
LK.gui.topLeft.addChild(teleportButtonText);
// teleportButton.down = function () {
// teleportToLastGate();
teleportButton.down = function () {
teleportToLastGate();
};
function teleportToLastGate() {
var targetDistance = 950; // 50 meters before the gate at 1000 meters
var currentDistance = Math.floor(distanceScore / 10);
if (currentDistance < targetDistance) {
var distanceToAdd = (targetDistance - currentDistance) * 10;
distanceScore += distanceToAdd;
// Flash effect when teleporting
LK.effects.flashScreen(0x8A2BE2, 500);
LK.effects.flashObject(player, 0x8A2BE2, 800);
}
}
// Function to toggle God Mode
function toggleGodMode() {
godModeActive = !godModeActive;
if (godModeActive) {
// Activate God Mode
player.isInvulnerable = true;
gameSpeed = normalSpeed * 3; // Very high speed
// Flash effect when activating
LK.effects.flashScreen(0xFFD700, 500);
LK.effects.flashObject(player, 0xFFD700, 1000);
} else {
// Deactivate God Mode
player.isInvulnerable = false;
gameSpeed = normalSpeed + distanceScore / 1000; // Return to normal progression
}
}
// Store button hidden for now
// var storeButton = LK.getAsset('square_button', {
// anchorX: 0.5,
// anchorY: 0.5,
// scaleX: 2,
// scaleY: 2,
// tint: 0x4444FF,
// x: 0,
// y: 400
// });
// LK.gui.topLeft.addChild(storeButton);
// var storeButtonText = new Text2('STORE', {
// size: 40,
// fill: 0xFFFFFF,
// fontWeight: 'bold'
// });
// storeButtonText.anchor.set(0.5, 0.5);
// storeButtonText.x = 0;
// storeButtonText.y = 400;
// LK.gui.topLeft.addChild(storeButtonText);
// Store button interaction
// storeButton.down = function () {
// store.openStore();
// };
// Progress line UI elements
var progressLine = LK.getAsset('box1', {
anchorX: 0,
anchorY: 0.5,
scaleX: 6,
// Further reduced horizontal line width
scaleY: 0.2,
// Slightly thicker line for better visibility
tint: 0x666666,
// Brighter color for better visibility
x: 200,
y: 200
});
LK.gui.top.addChild(progressLine);
// Mini character on progress line
var progressChar = LK.getAsset('C1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: 200,
y: 200
});
LK.gui.top.addChild(progressChar);
// Mini gem on progress line to show gem location
var progressGem = LK.getAsset('gem_icon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: 200,
y: 200
});
LK.gui.top.addChild(progressGem);
// Mini A1 entity on progress line to show starting gate location
var progressA1 = LK.getAsset('A1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.12,
scaleY: 0.12,
x: 200,
y: 200,
tint: 0x00FFFF
});
LK.gui.top.addChild(progressA1);
// Mini B1 entity on progress line to show end gate location
var progressB1 = LK.getAsset('B1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.15,
x: 200,
y: 200,
tint: 0xFFD700
});
LK.gui.top.addChild(progressB1);
// Remaining distance text removed
// Get player name and last score from storage
var playerName = storage.playerName || 'Player';
var lastScore = storage.lastScore || 0;
// Character switching variables for C1-C16 cycling every 6 frames
var characterOrder = ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'C11', 'C12', 'C13', 'C14', 'C15', 'C16'];
var currentCharacterIndex = 0;
var currentCharacter = characterOrder[currentCharacterIndex];
var lastSwapDistance = 0;
var nextSwapDistance = 2;
// Create start screen
var startScreen = LK.getAsset('kk', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: 0,
y: 0
});
LK.gui.center.addChild(startScreen);
// Create start button
var startButton = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 520
});
LK.gui.center.addChild(startButton);
// Start button text removed - no text will appear
// Add pulse effect to start button
function startButtonPulse() {
tween(startButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: startButtonPulse
});
}
});
}
startButtonPulse();
// Start button interaction
startButton.down = function () {
if (!gameStarted) {
// Check if kk asset is present and show tutorial
if (startScreen && startScreen.children && startScreen.children.length > 0) {
// Hide start screen temporarily
startScreen.visible = false;
startButton.visible = false;
// Show tutorial screen
tutorialScreen.showTutorial();
// Override tutorial close to start game
var originalClose = tutorialScreen.closeTutorial;
tutorialScreen.closeTutorial = function () {
originalClose.call(tutorialScreen);
// Start the game after tutorial
gameStarted = true;
// Stop the pulse animation
tween.stop(startButton);
// Play background music when game starts
LK.playMusic('Arkaplanmuzik1');
// Hide start screen elements
startScreen.destroy();
startButton.destroy();
// Flash effect when starting
LK.effects.flashScreen(0x00FF00, 500);
};
} else {
// No kk asset, start game directly
gameStarted = true;
// Stop the pulse animation
tween.stop(startButton);
// Play background music when game starts
LK.playMusic('Arkaplanmuzik1');
// Hide start screen elements
startScreen.destroy();
startButton.destroy();
// Flash effect when starting
LK.effects.flashScreen(0x00FF00, 500);
}
}
};
// Player name text removed
// Combined score text removed
// Scoreboard update function removed
// Game variables (single chapter only)
var gamePartTitle = "ENDLESS RUNNER";
var gamePartNumber = 1;
var isFirstChapter = true;
var gameStarted = false;
var isSecondPart = false;
;
Just crystal
Just his head
Background, endless, forest, winter, cartoon. In-Game asset. 2d. High contrast. No shadows
Only the line of the ears and the color of the paws should be gray
Only the line of the ears and the color of the paws should be gray
Let C2 have the character's color
Only the line of the ears and the color of the paws should be gray
Delete the character on it
A version without snow
Koyu mavi elips start butonu. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
Uçan bir dinazor. In-Game asset. 2d. High contrast. No shadows
Alev topu. In-Game asset. 2d. High contrast. No shadows
Mavi top rasengan top. In-Game asset. 2d. High contrast. No shadows
jump
Sound effect
coin
Sound effect
Arkaplanmuzik
Music
gem_collect
Sound effect
happy_giggle
Sound effect
Canazalma
Sound effect
Arkaplanmuzik1
Music
wumpa1
Sound effect
cancan
Sound effect
box_break
Sound effect
tnt_break
Sound effect
enemy_sound
Sound effect
bullet_sound
Sound effect