User prompt
100 px aşağı
User prompt
90 px daha sola al
User prompt
ses butonunu 700 px sola al
User prompt
ses butonunun üstündeki center circleyi sil
User prompt
Please fix the bug: 'melodyBtn is not defined' in or related to this line: 'melodyIcon.x = melodyBtn.x;' Line Number: 628
User prompt
delete melodyBtnIcon
User prompt
100 px asağı al
User prompt
10 px sola al
User prompt
20 px sağa al
User prompt
ses butonunu 200 px sola al
User prompt
ses butonunu büyült
User prompt
ses butonunun önündeki centre cinle ı sil ve melody buttonu koy
User prompt
melody butonunu 300 px daha sola al
User prompt
300 px sola al
User prompt
ses butonunu 400 px sola al
User prompt
ses butonu için bir asset ekle
User prompt
ses butonuna tıklayınca z ve r sesi çıkmamaya başlasın
User prompt
Please fix the bug: 'Uncaught TypeError: LK.mute is not a function' in or related to this line: 'LK.mute();' Line Number: 663
User prompt
Please fix the bug: 'Uncaught TypeError: LK.setMuted is not a function' in or related to this line: 'LK.setMuted(true);' Line Number: 663
User prompt
Please fix the bug: 'Uncaught TypeError: LK.mute is not a function' in or related to this line: 'LK.mute();' Line Number: 663
User prompt
oyunun sol üstüne sesleri açıp kapatan bir melodi butonu koy
User prompt
her ileri veya geri butonuna basıldığında veya ototmatiktede y sesini çıkartsın
User prompt
y sesini ekle her yürüdüğünde
User prompt
her adımında r sesi 1 kere çıksın
User prompt
karakter her adım attığında r sesi çıksın
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Boss class (for 2nd area end boss) var Boss = Container.expand(function () { var self = Container.call(this); // Use the new unique boss image asset for the boss look var bossAsset = self.attachAsset('bossUnique', { anchorX: 0.5, anchorY: 0.5 }); self.width = bossAsset.width; self.height = bossAsset.height; self.vx = -2; // Slow horizontal movement (optional) self.vy = 0; self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; self.hp = 15; // Boss hit points (increased by 50%) self.isBoss = true; // Boss fight state self.phase = 1; // 1: normal, 2: jump, 3: fast self.attackTimer = 0; self.attackCooldown = 60; // frames between attacks (1.0 seconds at 60fps) // Boss only starts firing after player reaches boss platform self.bossStartFiring = false; self.jumpTimer = 0; self.isJumping = false; self.jumpVy = 0; self.groundY = self.y; // y position where boss stands self.shieldActive = false; self.shieldTimer = 0; self.shieldDuration = 60; // frames self.weakSpotOpen = false; self.weakSpotTimer = 0; self.weakSpotDuration = 40; // frames self.lastPhase = 1; self.update = function () { self.lastX = self.x; self.lastY = self.y; // --- Boss Phase Logic --- // Phase changes based on HP if (self.hp <= 7.5 && self.phase === 1) { self.phase = 2; // Start jumping attacks self.attackCooldown = 60; // 1.0 seconds at 60fps } if (self.hp <= 3 && self.phase === 2) { self.phase = 3; // Faster, more aggressive self.attackCooldown = 60; // 1.0 seconds at 60fps } // --- Boss Shield (defense) --- if (!self.shieldActive && Math.random() < 0.008 && self.phase > 1) { self.shieldActive = true; self.shieldTimer = self.shieldDuration; // Optional: visual effect for shield (tint blue) if (self.displayObject) { self.displayObject.tint = 0x44aaff; } } if (self.shieldActive) { self.shieldTimer--; if (self.shieldTimer <= 0) { self.shieldActive = false; if (self.displayObject) { self.displayObject.tint = 0xffffff; } } } // --- Weak Spot (vulnerable) --- if (!self.weakSpotOpen && Math.random() < 0.01 && self.phase > 1 && !self.shieldActive) { self.weakSpotOpen = true; self.weakSpotTimer = self.weakSpotDuration; // Optional: visual effect for weak spot (tint yellow) if (self.displayObject) { self.displayObject.tint = 0xffee44; } } if (self.weakSpotOpen) { self.weakSpotTimer--; if (self.weakSpotTimer <= 0) { self.weakSpotOpen = false; if (self.displayObject) { self.displayObject.tint = 0xffffff; } } } // --- Boss Attacks --- if (self.bossStartFiring) { self.attackTimer++; if (self.attackTimer >= self.attackCooldown && !self.shieldActive && !self.isJumping && !self.isLeaping) { self.attackTimer = 0; // Choose attack: 50% chance to leap, 50% to fire var doLeap = false; if (self.phase >= 2 && Math.random() < 0.5) { doLeap = true; } if (doLeap) { // Start leap attack: jump toward player, then return self.isLeaping = true; self.leapPhase = 0; // 0: going to player, 1: returning self.leapStartX = self.x; self.leapStartY = self.y; // Target player position at leap start self.leapTargetX = typeof player !== "undefined" ? player.x : self.x; self.leapTargetY = self.groundY; // Calculate leap velocity to reach player in N frames var leapFrames = 24; self.leapTimer = 0; self.leapTotalFrames = leapFrames; self.leapVX = (self.leapTargetX - self.x) / leapFrames; self.leapVY = -44; // Upward velocity self.leapGravity = (self.groundY - self.y - self.leapVY * leapFrames) * 2 / (leapFrames * leapFrames); } else { // Boss always fires projectile at player every attack, regardless of phase if (typeof bossFireProjectile === "function") { bossFireProjectile(self, self.phase === 3); } } } } // --- Boss Leap Attack --- if (self.isLeaping) { // Leap phase 0: jump toward player if (self.leapPhase === 0) { self.x += self.leapVX; self.y += self.leapVY; self.leapVY += self.leapGravity; self.leapTimer++; // If reached or passed groundY, land and start return if (self.y >= self.groundY) { self.y = self.groundY; self.leapPhase = 1; // On landing, create shockwave (damage if player is close) if (typeof bossShockwave === "function") { bossShockwave(self); } // Prepare return leap var returnFrames = 24; self.leapTimer = 0; self.leapTotalFrames = returnFrames; self.leapVX = (self.leapStartX - self.x) / returnFrames; self.leapVY = -38; // Upward velocity for return self.leapGravity = (self.groundY - self.y - self.leapVY * returnFrames) * 2 / (returnFrames * returnFrames); } } else if (self.leapPhase === 1) { // Return leap to original position self.x += self.leapVX; self.y += self.leapVY; self.leapVY += self.leapGravity; self.leapTimer++; if (self.y >= self.groundY || self.leapTimer >= self.leapTotalFrames) { self.y = self.groundY; self.x = self.leapStartX; self.isLeaping = false; self.leapPhase = 0; // On landing, create shockwave (damage if player is close) if (typeof bossShockwave === "function") { bossShockwave(self); } } } } // --- Boss Jumping (old jump attack, only used if not leaping) --- if (self.isJumping) { self.y += self.jumpVy; self.jumpVy += 4.5; // gravity if (self.y >= self.groundY) { self.y = self.groundY; self.isJumping = false; // On landing, create shockwave (damage if player is close) if (typeof bossShockwave === "function") { bossShockwave(self); } } } // --- Boss Movement (side to side in phase 3) --- if (self.phase === 3 && !self.isJumping && !self.isLeaping) { // Move left and right slowly if (!self.moveDir) { self.moveDir = -1; } self.x += self.moveDir * 7; // Clamp to wide platform area (assume platform at y = self.groundY + boss.height/2 + 200) var minX = self.x0 || self.x - 600; var maxX = self.x1 || self.x + 600; if (!self.x0) { self.x0 = self.x - 600; } if (!self.x1) { self.x1 = self.x + 600; } if (self.x < minX) { self.x = minX; self.moveDir = 1; } if (self.x > maxX) { self.x = maxX; self.moveDir = -1; } } }; return self; }); // BossBullet class: used for boss projectiles, uses bossBullet asset var BossBullet = Container.expand(function () { var self = Container.call(this); var bossBulletAsset = self.attachAsset('bossBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bossBulletAsset.width; self.height = bossBulletAsset.height; self.vx = 0; self.vy = 0; self.lastX = 0; self.lastY = 0; self.isBossProjectile = true; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.vx; self.y += self.vy; // Clamp boss projectiles within boss platform bounds if (typeof platforms !== "undefined" && platforms.length > 0) { // Find the boss platform (the widest one, used for boss) var bossPlat = null; for (var i = 0; i < platforms.length; i++) { if (platforms[i].width >= 1800) { bossPlat = platforms[i]; break; } } if (bossPlat) { var minX = bossPlat.x; var maxX = bossPlat.x + bossPlat.width; // Clamp self.x to platform bounds if (self.x < minX) { self.x = minX; } if (self.x > maxX) { self.x = maxX; } } } }; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); // Use the new bullet figure asset var bulletAsset = self.attachAsset('bulletFigure', { anchorX: 0.5, anchorY: 0.5 }); self.width = bulletAsset.width; self.height = bulletAsset.height; self.vx = 40; // Bullet speed (right) self.vy = 0; // Add vy for vertical movement self.active = true; self.lastX = 0; self.lastY = 0; self.isControlled = false; // If true, player can control direction self.update = function () { self.lastX = self.x; self.lastY = self.y; // If controlled, vx/vy may be set by player, else keep moving self.x += self.vx; self.y += self.vy; }; return self; }); // Coin class var Coin = Container.expand(function () { var self = Container.call(this); var coinAsset = self.attachAsset('coinCircle', { anchorX: 0.5, anchorY: 0.5 }); self.width = coinAsset.width; self.height = coinAsset.height; return self; }); // Enemy class: simple flying enemy that moves left across the screen var Enemy = Container.expand(function () { var self = Container.call(this); // Use a unique asset for the enemy (use '682f46a9c0116d543bc37477' as image) var enemyAsset = self.attachAsset('682f46a9c0116d543bc37477', { anchorX: 0.5, anchorY: 0.5 }); self.width = enemyAsset.width; self.height = enemyAsset.height; self.vx = -14 - Math.random() * 6; // Move left at random speed self.vy = 0; self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; self.isBossProjectile = false; // Not a boss projectile self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.vx; self.y += self.vy; // Optionally, add up/down movement for variety if (Math.random() < 0.02) { self.vy = (Math.random() - 0.5) * 8; } // Clamp Y to play area if (self.y < 200) self.y = 200; if (self.y > 2300) self.y = 2300; }; return self; }); // Platform class var Platform = Container.expand(function () { var self = Container.call(this); var platAsset = self.attachAsset('platformBox', { anchorX: 0, anchorY: 0 }); self.width = platAsset.width; self.height = platAsset.height; return self; }); // Player character class var Player = Container.expand(function () { var self = Container.call(this); // Attach player asset (red box or terlikIcon if skin1 is owned) var assetId = typeof shopItems !== "undefined" && shopItems.skin1 > 0 ? 'terlikIcon' : 'playerBox'; var playerAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 1 }); // Physics properties self.vx = 0; self.vy = 0; self.isOnGround = false; self.width = playerAsset.width; self.height = playerAsset.height; // For jump control self.jumpRequested = false; // Animation properties self.isRunning = false; self.runningTween = null; self.jumpingTween = null; self.originalScaleX = 1; self.originalScaleY = 1; // Animation methods self.startRunningAnimation = function () { if (!self.isRunning && !self.runningTween) { self.isRunning = true; // Create bobbing animation while running self.runningTween = tween(playerAsset, { scaleY: 0.9, scaleX: 1.1 }, { duration: 150, easing: tween.easeInOut, onFinish: function onFinish() { if (self.isRunning) { // Bounce back tween(playerAsset, { scaleY: 1.1, scaleX: 0.9 }, { duration: 150, easing: tween.easeInOut, onFinish: function onFinish() { if (self.isRunning) { self.runningTween = null; self.startRunningAnimation(); // Loop animation } } }); } } }); } }; self.stopRunningAnimation = function () { if (self.isRunning) { self.isRunning = false; if (self.runningTween) { tween.stop(playerAsset, { scaleX: true, scaleY: true }); self.runningTween = null; } // Return to original scale smoothly tween(playerAsset, { scaleX: self.originalScaleX, scaleY: self.originalScaleY }, { duration: 100, easing: tween.easeOut }); } }; self.startJumpAnimation = function () { if (!self.jumpingTween) { // Squash before jump self.jumpingTween = tween(playerAsset, { scaleY: 0.7, scaleX: 1.3 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { // Stretch during jump tween(playerAsset, { scaleY: 1.2, scaleX: 0.8 }, { duration: 120, easing: tween.easeInOut, onFinish: function onFinish() { // Return to normal on landing tween(playerAsset, { scaleX: self.originalScaleX, scaleY: self.originalScaleY }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { self.jumpingTween = null; } }); } }); } }); } }; // Touch down on player (for jump) self.down = function (x, y, obj) { // Only allow jump if on ground if (self.isOnGround) { self.jumpRequested = true; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Sky blue }); /**** * Game Code ****/ // Example asset, replace id as needed // Melody (ses) button asset (example: use a speaker icon or music note image, replace id with your asset id) // Tween for animations (jump, enemy movement, etc) // --- Shop System Variables --- var shopCoins = storage.shopCoins || 0; var shopItems = storage.shopItems || { skin1: 0 }; var shopVisible = false; var shopButton = null; var shopPanel = null; // --- Game Variables --- // Boss health bar assets // Karakterin terliği için örnek asset (id: '6832a1b2terlikicon') // --- Asset Initialization (shapes) --- // Sun and cloud assets (example IDs, replace with real asset IDs as needed) // New bullet figure asset (example: blue ellipse, unique id) // Unique boss asset // Boss attack: fire projectile at player // new kebabBox asset (fullscreen, kebab color) function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function bossFireProjectile(boss, fast) { // Fire 1 or 2 projectiles toward player var num = fast ? 2 : 1; for (var i = 0; i < num; i++) { var proj = new BossBullet(); proj.x = boss.x; proj.y = boss.y + boss.height / 2 - 80 + i * 60; // Aim at player var dx = player.x - boss.x; var dy = player.y - player.height / 2 - proj.y; var len = Math.sqrt(dx * dx + dy * dy); var speed = fast ? 28 : 18; if (len > 0) { proj.vx = dx / len * speed; proj.vy = dy / len * speed; } else { proj.vx = speed; proj.vy = 0; } // Mark as boss projectile (for collision logic) proj.isBossProjectile = true; enemies.push(proj); game.addChild(proj); } } // Boss shockwave: damage player if close to boss when landing function bossShockwave(boss) { // If player is within 220px horizontally and below boss, take damage var px = player.x; var py = player.y; var bx = boss.x; var by = boss.y + boss.height / 2; if (Math.abs(px - bx) < 220 && py > by) { LK.effects.flashScreen(0xff0000, 800); playerLives--; updateHearts(); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } } // Optional: visual effect for shockwave (flash boss yellow) if (boss.displayObject) { boss.displayObject.tint = 0xffff00; LK.setTimeout(function () { if (boss.displayObject) { boss.displayObject.tint = 0xffffff; } }, 200); } } var GRAVITY = 2.2; var JUMP_VELOCITY = -54; var PLAYER_SPEED = 16; var SCROLL_SPEED = 10; var LEVEL_LENGTH = 950 * 9 + 600 + 500; // 10 platforms, spacing 950, start at 600, plus last platform width var player; var platforms = []; var coins = []; var bullets = []; // Bullets array for shooting var enemies = []; // Array for flying enemies var coffeeHouse = null; var boss = null; // Boss instance for 2nd area var cameraX = 0; var score = 0; var distance = 0; var gameOver = false; var hazards = []; var checkpoints = []; var currentLevel = 1; var autoMoveRightActive = false; var lastCheckpointIndex = 0; // --- Ava: Cephane refill timer --- var playerAmmo = 0; var maxPlayerAmmo = 10; var ammoRefillTimer = LK.setInterval(function () { if (typeof playerAmmo === "undefined") { playerAmmo = 0; } if (typeof maxPlayerAmmo === "undefined") { maxPlayerAmmo = 10; } if (playerAmmo < maxPlayerAmmo) { playerAmmo++; } }, 250); // --- GUI --- // Hearts (5 total, left-aligned, with spacing) var heartAssets = []; var heartSpacing = 120; var playerLives = 3; // Total lives/can // --- Melody Button (Sound/Music Toggle) --- // Use the dedicated melody button image asset var melodyBtn = LK.getAsset('melodyBtnIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); melodyBtn.x = 100 + 60 - 800 + 10; // 10px more to the right (net: 10px to the left) melodyBtn.y = 100 + 60 + 100; // 100px margin from top, 60px for radius, 100px further down melodyBtn.width = 180; melodyBtn.height = 180; melodyBtn.interactive = true; melodyBtn.alpha = 0.92; // Melody icon (♪) var melodyIcon = new Text2('♪', { size: 120, fill: 0x222222 }); melodyIcon.anchor.set(0.5, 0.5); melodyIcon.x = melodyBtn.x; melodyIcon.y = melodyBtn.y; // Track mute state var isMuted = false; function updateMelodyIcon() { if (isMuted) { melodyIcon.setText('🔇'); melodyBtn.alpha = 0.5; } else { melodyIcon.setText('♪'); melodyBtn.alpha = 0.92; } } // Add to GUI (top left, but offset to avoid platform menu) LK.gui.top.addChild(melodyBtn); LK.gui.top.addChild(melodyIcon); updateMelodyIcon(); // Melody button touch handler melodyBtn.down = function (x, y, obj) { isMuted = !isMuted; updateMelodyIcon(); // Mute/unmute all sounds and music if (isMuted) { if (typeof LK.setMuted === "function") { LK.setMuted(true); } } else { if (typeof LK.setMuted === "function") { LK.setMuted(false); } } }; // Also allow toggling by tapping the icon itself melodyIcon.down = function (x, y, obj) { melodyBtn.down(x, y, obj); }; function updateHearts() { for (var i = 0; i < heartAssets.length; i++) { if (i < playerLives) { heartAssets[i].visible = true; } else { heartAssets[i].visible = false; } } } for (var i = 0; i < 5; i++) { var heart = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5 }); // Skip the first heart position (in front of ses button) and start from the next position heart.x = 180 + (i + 1) * heartSpacing; // Shift all hearts right by one slot heart.y = 100; // Moved hearts higher up LK.gui.top.addChild(heart); heartAssets.push(heart); } updateHearts(); var scoreTxt = new Text2('0', { size: 100, fill: 0xFFF700 }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 20; // Moved score text to very top LK.gui.top.addChild(scoreTxt); var distTxt = new Text2('0m', { size: 60, fill: 0xFFFFFF }); distTxt.anchor.set(0.5, 0); LK.gui.top.addChild(distTxt); distTxt.y = 120; // Moved distance text higher // --- Level Generation --- function createLevel() { // Clear old for (var i = 0; i < platforms.length; i++) { platforms[i].destroy(); } for (var i = 0; i < coins.length; i++) { coins[i].destroy(); } if (typeof coffeeHouse !== "undefined" && coffeeHouse) { coffeeHouse.destroy(); } platforms = []; coins = []; coffeeHouse = null; // Add sun to the sky var sun = LK.getAsset('sun', { anchorX: 0.5, anchorY: 0.5 }); sun.x = 300; sun.y = 300; game.addChild(sun); // Add a few clouds at different positions var cloud1 = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5 }); cloud1.x = 700; cloud1.y = 400; game.addChild(cloud1); var cloud2 = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5 }); cloud2.x = 1400; cloud2.y = 600; game.addChild(cloud2); var cloud3 = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5 }); cloud3.x = 2000; cloud3.y = 350; game.addChild(cloud3); // (bottomCloud removed) // Clear and initialize hazards array properly if (typeof hazards !== "undefined" && hazards && hazards.length) { for (var i = 0; i < hazards.length; i++) { if (hazards[i] && typeof hazards[i].destroy === "function") { hazards[i].destroy(); } } } hazards = []; // --- Restore old hazard spawning logic: spawn falling hazards on random platforms except boss level --- if (!isBossLevel) { var hazardCount = Math.max(2, Math.floor(numPlatforms / 3)); for (var h = 0; h < hazardCount; h++) { // Pick a random platform (not the first or last) var platIdx = 1 + Math.floor(Math.random() * (numPlatforms - 2)); var plat = platforms[platIdx]; if (!plat) continue; var hazard = LK.getAsset('hazard', { anchorX: 0.5, anchorY: 0.5 }); // Place hazard above the platform, random X within platform width hazard.x = plat.x + plat.width * (0.2 + 0.6 * Math.random()); hazard.y = plat.y - 400 - Math.random() * 300; hazard.width = 120; hazard.height = 120; hazard.vy = 12 + Math.random() * 6; hazards.push(hazard); game.addChild(hazard); } } // Platform layout: up/down, not fixed order, player can jump between them // 5 levels: 1-4 classic, 5 is boss fight var isBossLevel = typeof currentLevel !== "undefined" && currentLevel === 5; // Set platform count per level var numPlatforms = 10; if (typeof currentLevel !== "undefined") { if (currentLevel === 1) { numPlatforms = 15; } else if (currentLevel === 2) { numPlatforms = 15; } else if (currentLevel === 3) { numPlatforms = 20; } else if (currentLevel === 4) { numPlatforms = 20; } else if (currentLevel === 5) { numPlatforms = 15; } } var platSpacingX = 950; // Further increased horizontal spacing for much more space var platMinY = 400; // Moved higher up to use more of top area var platMaxY = 2400; // Extended lower to use more bottom area // Calculate max jump height based on physics // vy = JUMP_VELOCITY, gravity = GRAVITY // maxJumpHeight = - (vy^2) / (2 * gravity) var maxJumpHeight = -(JUMP_VELOCITY * JUMP_VELOCITY) / (2 * GRAVITY); // Use 90% of maxJumpHeight for margin of error var platformGapY = Math.floor(maxJumpHeight * 0.9); var lastY = 1800; // (Removed initial spawn platform and its coin) for (var i = 0; i < numPlatforms; i++) { // If this is the last platform of the boss level, add a wide area instead of a platform if (isBossLevel && i === numPlatforms - 1) { // Create a wide area using a platform asset, but much wider var wideArea = new Platform(); wideArea.x = 600 + i * platSpacingX; wideArea.y = lastY; wideArea.width = 2048; // Full screen width wideArea.height = 300; // Taller for effect // Set the display object size as well if (wideArea.displayObject) { wideArea.displayObject.width = wideArea.width; wideArea.displayObject.height = wideArea.height; } platforms.push(wideArea); game.addChild(wideArea); // Optionally, add a coin or heart in the middle of the wide area var coin = new Coin(); coin.x = wideArea.x + wideArea.width / 2; coin.y = wideArea.y - 80; coins.push(coin); game.addChild(coin); // Add boss at the right end of the wide area if (typeof boss !== "undefined" && boss) { boss.destroy(); } // Remove all hazards before boss fight if (typeof hazards !== "undefined" && hazards.length) { for (var h = 0; h < hazards.length; h++) { if (hazards[h] && typeof hazards[h].destroy === "function") { hazards[h].destroy(); } } } hazards = []; boss = new Boss(); // Place boss so its feet are 200px above the platform boss.x = wideArea.x + wideArea.width - boss.width / 2 - 60; // Near right edge // Boss anchorY is 0.5, so y is at center. To put feet 200px above platform: y = platform.y + platform.height - boss.height/2 - 200 boss.y = wideArea.y + wideArea.height - boss.height / 2 - 200; // Set boss.groundY to correct y so boss doesn't jump to top boss.groundY = boss.y; game.addChild(boss); // No checkpoint on the wide area continue; } var plat = new Platform(); plat.x = 600 + i * platSpacingX; // Alternate up/down, but keep within jumpable range if (i === 0) { plat.y = lastY; } else { // Randomly go up or down, but clamp to min/max var deltaY = (Math.random() > 0.5 ? -1 : 1) * (platformGapY + Math.floor(Math.random() * 40) - 20); // Small random offset plat.y = lastY + deltaY; if (plat.y < platMinY) { plat.y = platMinY; } if (plat.y > platMaxY) { plat.y = platMaxY; } lastY = plat.y; } platforms.push(plat); game.addChild(plat); // Place a coin above every platform, but rarely replace with a heart (extra life) if (Math.random() < 0.07) { // ~7% chance, very rare var heart = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5 }); heart.x = plat.x + plat.width / 2; heart.y = plat.y - 80; heart.isHeart = true; coins.push(heart); game.addChild(heart); } else { var coin = new Coin(); coin.x = plat.x + plat.width / 2; coin.y = plat.y - 80; coins.push(coin); game.addChild(coin); } // Add a checkpoint marker every 10th platform (not the first platform) if (i > 0 && i % 10 === 0) { var checkpoint = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5 }); checkpoint.x = plat.x + plat.width / 2; checkpoint.y = plat.y - 120; checkpoint.width = 120; checkpoint.height = 120; checkpoint.isCheckpoint = true; checkpoint.platformIndex = i; game.addChild(checkpoint); // Initialize checkpoints array if not defined var checkpoints = []; // Store checkpoint objects in an array for respawn logic if (typeof checkpoints === "undefined") { checkpoints = []; } checkpoints.push(checkpoint); } } // Add coffee house on the last platform for levels 1, 2, 3, 4 (not boss level) if (platforms.length > 0 && (typeof currentLevel === "undefined" || currentLevel === 1 || currentLevel === 2 || currentLevel === 3 || currentLevel === 4)) { var lastPlat = platforms[platforms.length - 1]; coffeeHouse = LK.getAsset('coffeeHouse', { anchorX: 0.5, anchorY: 1 }); coffeeHouse.x = lastPlat.x + lastPlat.width / 2; coffeeHouse.y = lastPlat.y; game.addChild(coffeeHouse); } } // --- Player Initialization --- // Track the last safe platform index for respawn var lastSafePlatformIndex = 0; // Track the platform the player fell from for respawn var lastFallenPlatformIndex = 0; function resetPlayer(respawnToLastSafe) { if (player) { player.destroy(); } player = new Player(); // Place player on the start platform or the platform where they fell if requested if (platforms.length > 0) { var platIdx = 0; if (respawnToLastSafe && typeof lastFallenPlatformIndex === "number" && lastFallenPlatformIndex >= 0 && lastFallenPlatformIndex < platforms.length) { platIdx = lastFallenPlatformIndex; } else if (respawnToLastSafe && typeof lastSafePlatformIndex === "number" && lastSafePlatformIndex >= 0 && lastSafePlatformIndex < platforms.length) { platIdx = lastSafePlatformIndex; } player.x = platforms[platIdx].x + platforms[platIdx].width / 2; player.y = platforms[platIdx].y; } else { player.x = 200; player.y = 2000; // Moved default spawn position higher for better screen usage } player.vx = 0; player.vy = 0; player.isOnGround = false; // No upgrades to apply, only skin player.hasSkin1 = shopItems.skin1 > 0; game.addChild(player); // --- Ava: Stop auto-move and movement if spawning on first platform --- if (typeof autoMoveRightActive === "undefined") { autoMoveRightActive = false; } if (typeof moveDir === "undefined") { moveDir = 0; } if (platIdx === 0) { autoMoveRightActive = false; moveDir = 0; // Set a flag to require left button press to resume movement player.waitingForLeftBtn = true; } else { player.waitingForLeftBtn = false; } } // --- Camera --- function updateCamera() { // Camera always follows player, no clamping cameraX = player.x - 600; // Move all game objects (except GUI) by -cameraX for (var i = 0; i < platforms.length; i++) { platforms[i].xScreen = platforms[i].x - cameraX; } for (var i = 0; i < coins.length; i++) { coins[i].xScreen = coins[i].x - cameraX; } player.xScreen = player.x - cameraX; // Move coffeeHouse relative to camera if (coffeeHouse && platforms.length > 0) { var lastPlat = platforms[platforms.length - 1]; coffeeHouse.xScreen = coffeeHouse.x - cameraX; coffeeHouse.yScreen = coffeeHouse.y; } // --- Ava: Keep bottomCloud at fixed screen position if it exists --- if (typeof bottomCloud !== "undefined" && bottomCloud) { bottomCloud.x = 2048 / 2 - 200; bottomCloud.y = 2732 - 120; } // (hazard removed) } // --- Utility: AABB collision --- function intersectsAABB(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; } // --- Touch Controls --- // On-screen left, right, and jump buttons (bottom left corner) // Only these buttons control movement/jump; fire is still tap/double-tap on right side var moveDir = 0; // -1 = left, 1 = right, 0 = none var leftBtn, rightBtn, jumpBtn; var leftBtnPressed = false, rightBtnPressed = false, jumpBtnPressed = false; // Create left button leftBtn = LK.getAsset('btnLeftBg', { anchorX: 0.5, anchorY: 0.5 }); leftBtn.x = 180; // Move control buttons visually in front of platforms by increasing their y position (platforms are at y ~400-2400, so buttons should be in front) leftBtn.y = 2400 + 120; // Place left button just in front of lowest platform leftBtn.width = 260; leftBtn.height = 260; var leftIcon = LK.getAsset('btnLeftIcon', { anchorX: 0.5, anchorY: 0.5 }); leftIcon.x = leftBtn.x; leftIcon.y = leftBtn.y; leftIcon.width = 140; leftIcon.height = 140; // Create right button rightBtn = LK.getAsset('btnRightBg', { anchorX: 0.5, anchorY: 0.5 }); rightBtn.x = 470 + 150 - 125; rightBtn.y = 2400 + 120; // Place right button just in front of lowest platform rightBtn.width = 260; rightBtn.height = 260; var rightIcon = LK.getAsset('btnRightIcon', { anchorX: 0.5, anchorY: 0.5 }); rightIcon.x = rightBtn.x; rightIcon.y = rightBtn.y; rightIcon.width = 140; rightIcon.height = 140; // Create jump button jumpBtn = LK.getAsset('btnJumpBg', { anchorX: 0.5, anchorY: 0.5 }); jumpBtn.x = 220 + 200 - 90; jumpBtn.y = 2400 - 120; // Place jump button just above the other buttons, still in front of platforms jumpBtn.width = 260; jumpBtn.height = 260; var jumpIcon = LK.getAsset('btnJumpIcon', { anchorX: 0.5, anchorY: 0.5 }); jumpIcon.x = jumpBtn.x; jumpIcon.y = jumpBtn.y; jumpIcon.width = 140; jumpIcon.height = 140; // Create fire button (bottom right, red circle) var fireBtn = LK.getAsset('btnFireBg', { anchorX: 0.5, anchorY: 0.5 }); fireBtn.x = 2048 - 180; fireBtn.y = 2400 + 120; // Place fire button just in front of lowest platform fireBtn.width = 260; fireBtn.height = 260; // Terlik ikonunu fire butonun ortasına ekle var terlikIcon = LK.getAsset('terlikIcon', { anchorX: 0.5, anchorY: 0.5 }); terlikIcon.x = fireBtn.x; terlikIcon.y = fireBtn.y; terlikIcon.width = 160; terlikIcon.height = 160; // Add all buttons and icons to the display list at the very end so they are always in front game.addChild(leftBtn); game.addChild(leftIcon); game.addChild(rightBtn); game.addChild(rightIcon); game.addChild(jumpBtn); game.addChild(jumpIcon); game.addChild(fireBtn); game.addChild(terlikIcon); // --- Ava: Move all control and UI buttons to the absolute front of the display list every frame to guarantee they are always in front of everything, including the player and platforms --- game.bringButtonsToFront = function () { if (leftBtn && leftBtn.parent) { leftBtn.parent.setChildIndex(leftBtn, leftBtn.parent.children.length - 1); } if (leftIcon && leftIcon.parent) { leftIcon.parent.setChildIndex(leftIcon, leftIcon.parent.children.length - 1); } if (rightBtn && rightBtn.parent) { rightBtn.parent.setChildIndex(rightBtn, rightBtn.parent.children.length - 1); } if (rightIcon && rightIcon.parent) { rightIcon.parent.setChildIndex(rightIcon, rightIcon.parent.children.length - 1); } if (jumpBtn && jumpBtn.parent) { jumpBtn.parent.setChildIndex(jumpBtn, jumpBtn.parent.children.length - 1); } if (jumpIcon && jumpIcon.parent) { jumpIcon.parent.setChildIndex(jumpIcon, jumpIcon.parent.children.length - 1); } if (fireBtn && fireBtn.parent) { fireBtn.parent.setChildIndex(fireBtn, fireBtn.parent.children.length - 1); } if (terlikIcon && terlikIcon.parent) { terlikIcon.parent.setChildIndex(terlikIcon, terlikIcon.parent.children.length - 1); } }; // Call this in every game.update to ensure buttons are always in front var _origUpdate = game.update; game.update = function () { game.bringButtonsToFront && game.bringButtonsToFront(); if (_origUpdate) { return _origUpdate.apply(this, arguments); } }; // Helper to check if a point is inside a button function isInsideBtn(btn, x, y) { var bx = btn.x, by = btn.y, bw = btn.width, bh = btn.height; // LK.gui is scaled, so use screen coordinates directly return x >= bx - bw / 2 && x <= bx + bw / 2 && y >= by - bh / 2 && y <= by + bh / 2; } // Overwrite game.down for button controls game.down = function (x, y, obj) { // Handle title screen play button if (!gameStarted && playButton && isInsidePlayButton(x, y)) { startGameFromTitle(); return; } // Handle title screen shop button if (!gameStarted && shopButton && isInsideShopButton(x, y)) { toggleShop(); return; } // Handle shop interactions if (shopVisible && shopPanel) { handleShopTouch(x, y); return; } // Don't process game controls if game hasn't started yet if (!gameStarted) { return; } if (gameOver) { return; } // Check if pressed on left, right, or jump button if (isInsideBtn(leftBtn, x, y)) { leftBtnPressed = true; // --- Ava: If waitingForLeftBtn, allow movement to resume only on left button press --- if (player && player.waitingForLeftBtn) { player.waitingForLeftBtn = false; moveDir = -1; } else if (!player.waitingForLeftBtn) { moveDir = -1; } // Stop auto-move right if active if (typeof autoMoveRightActive !== "undefined" && autoMoveRightActive) { autoMoveRightActive = false; } // Play 'y' sound on left button press var ySound = LK.getSound && LK.getSound('y'); if (ySound && typeof ySound.play === "function") { ySound.play(); } } if (isInsideBtn(rightBtn, x, y)) { rightBtnPressed = true; // --- Ava: If waitingForLeftBtn, allow movement to resume on right button as well --- if (player && player.waitingForLeftBtn) { player.waitingForLeftBtn = false; moveDir = 1; } else if (!player.waitingForLeftBtn) { moveDir = 1; } // --- Double-tap detection for right button --- if (typeof rightBtnLastTapTime === "undefined") { rightBtnLastTapTime = 0; rightBtnTapCount = 0; } var now = Date.now(); if (now - rightBtnLastTapTime < 400) { rightBtnTapCount++; } else { rightBtnTapCount = 1; } rightBtnLastTapTime = now; if (rightBtnTapCount === 2) { // Toggle auto-move right: if already active, turn off; if not, turn on if (typeof autoMoveRightActive === "undefined") { autoMoveRightActive = false; } if (autoMoveRightActive) { autoMoveRightActive = false; moveDir = 0; } else { autoMoveRightActive = true; moveDir = 1; } rightBtnTapCount = 0; } // Play 'y' sound on right button press var ySound = LK.getSound && LK.getSound('y'); if (ySound && typeof ySound.play === "function") { ySound.play(); } } if (isInsideBtn(jumpBtn, x, y)) { jumpBtnPressed = true; if (player.isOnGround) { player.jumpRequested = true; } } // Fire button: shoot bullet if (typeof fireBtn !== "undefined" && isInsideBtn(fireBtn, x, y)) { if (typeof playerAmmo === "undefined" || playerAmmo > 0) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - player.height / 2; bullet.lastX = bullet.x; bullet.vx = 40; bullet.vy = 0; bullet.isControlled = false; bullets.push(bullet); game.addChild(bullet); if (typeof playerAmmo !== "undefined") { playerAmmo--; } } return; } // If not on any button, allow fire mechanic as before (right half of screen) if (!isInsideBtn(leftBtn, x, y) && !isInsideBtn(rightBtn, x, y) && !isInsideBtn(jumpBtn, x, y)) { // Fire a bullet only if this is a double-tap (within 350ms) on the right side if (x > 2048 / 2) { if (typeof lastFireTapTime === "undefined") { lastFireTapTime = 0; } var now = Date.now(); if (now - lastFireTapTime < 350) { // Double-tap detected: fire bullet if (typeof playerAmmo === "undefined" || playerAmmo > 0) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - player.height / 2; bullet.lastX = bullet.x; // Set initial direction to right, but allow control bullet.vx = 0; bullet.vy = 0; bullet.isControlled = true; // Mark as controlled bullets.push(bullet); game.addChild(bullet); // Store the controlled bullet reference for move/up game.controlledBullet = bullet; if (typeof playerAmmo !== "undefined") { playerAmmo--; } } lastFireTapTime = 0; // Reset } else { // First tap: just record time lastFireTapTime = now; } } } }; // Overwrite game.up for button controls game.up = function (x, y, obj) { // Don't process game controls if game hasn't started yet if (!gameStarted) { return; } // Release movement/jump on button up if (isInsideBtn(leftBtn, x, y)) { leftBtnPressed = false; if (!rightBtnPressed) { moveDir = 0; } else { moveDir = 1; } } if (isInsideBtn(rightBtn, x, y)) { rightBtnPressed = false; if (!leftBtnPressed) { moveDir = 0; } else { moveDir = -1; } } if (isInsideBtn(jumpBtn, x, y)) { jumpBtnPressed = false; } // Release bullet control on touch up if (game.controlledBullet && game.controlledBullet.isControlled) { game.controlledBullet.isControlled = false; game.controlledBullet = null; } }; // Overwrite game.move for button controls and bullet direction game.move = function (x, y, obj) { // Don't process game controls if game hasn't started yet if (!gameStarted) { return; } // If dragging on left/right button, update moveDir if (leftBtnPressed && isInsideBtn(leftBtn, x, y)) { moveDir = -1; } else if (rightBtnPressed && isInsideBtn(rightBtn, x, y)) { moveDir = 1; } else if (!leftBtnPressed && !rightBtnPressed) { moveDir = 0; } // If a controlled bullet exists, update its velocity based on drag direction if (game.controlledBullet && game.controlledBullet.isControlled) { var bx = game.controlledBullet.x; var by = game.controlledBullet.y; var gx = x + cameraX; var gy = y; var dx = gx - bx; var dy = gy - by; var len = Math.sqrt(dx * dx + dy * dy); if (len > 0) { // Set bullet speed (fixed magnitude, e.g. 40 px/frame) var speed = 40; game.controlledBullet.vx = dx / len * speed; game.controlledBullet.vy = dy / len * speed; } } }; // --- Game Update Loop --- game.update = function () { // Don't run game logic if game hasn't started yet if (!gameStarted) { return; } if (gameOver) { return; } // --- Player Movement --- // Auto-move right logic if (typeof autoMoveRightActive === "undefined") { autoMoveRightActive = false; } if (autoMoveRightActive) { // Play 'y' sound every time auto-move right is active and player is on ground and moving if (typeof player.lastAutoMoveYSound === "undefined") { player.lastAutoMoveYSound = 0; } // Only play every 12 frames to avoid spamming if (player.isOnGround && Math.abs(player.vx) > 0 && LK.ticks - player.lastAutoMoveYSound > 12) { var ySound = LK.getSound && LK.getSound('y'); if (ySound && typeof ySound.play === "function") { ySound.play(); } player.lastAutoMoveYSound = LK.ticks; } moveDir = 1; } // --- Ava: Prevent all movement if waitingForLeftBtn is true --- if (player && player.waitingForLeftBtn) { player.vx = 0; } else { var speedMultiplier = 1 + (player.speedBoost || 0) * 0.2; player.vx = moveDir * PLAYER_SPEED * speedMultiplier; } // --- Character Animations --- // Running animation if (Math.abs(player.vx) > 0 && player.isOnGround) { // Start running animation if not already running if (typeof player.startRunningAnimation === "function") { player.startRunningAnimation(); } } else { // Stop running animation if not moving or not on ground if (typeof player.stopRunningAnimation === "function") { player.stopRunningAnimation(); } } // Apply gravity player.vy += GRAVITY; // Jump if (player.jumpRequested) { var jumpMultiplier = 1 + (player.jumpBoost || 0) * 0.15; player.vy = JUMP_VELOCITY * jumpMultiplier; player.jumpRequested = false; player.isOnGround = false; // Start jump animation if (typeof player.startJumpAnimation === "function") { player.startJumpAnimation(); } // Play jump sound only if not muted if (!isMuted) { var zSound = LK.getSound && LK.getSound('z'); if (zSound && typeof zSound.play === "function") { zSound.play(); } } } // --- Play 'r' and 'y' sound on each step (horizontal movement, only once per step) --- if (typeof player.lastStepX === "undefined") { player.lastStepX = player.x; } if (typeof player.hasPlayedStepSound === "undefined") { player.hasPlayedStepSound = false; } if (player.isOnGround && Math.abs(player.vx) > 0 && Math.abs(player.x - player.lastStepX) >= player.width * 0.7 // step size: 0.7x width ) { if (!player.hasPlayedStepSound) { if (!isMuted) { var rSound = LK.getSound && LK.getSound('r'); if (rSound && typeof rSound.play === "function") { rSound.play(); } var ySound = LK.getSound && LK.getSound('y'); if (ySound && typeof ySound.play === "function") { ySound.play(); } } player.hasPlayedStepSound = true; } // Update lastStepX to current position player.lastStepX = player.x; } else if (player.isOnGround && Math.abs(player.vx) === 0) { // Reset flag when player stops moving player.hasPlayedStepSound = false; } // Move horizontally, check collisions player.x += player.vx; var collidedX = false; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; if (intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: plat.x, y: plat.y, width: plat.width, height: plat.height })) { // Collided horizontally, push player out if (player.vx > 0) { player.x = plat.x - player.width / 2; } else if (player.vx < 0) { player.x = plat.x + plat.width + player.width / 2; } collidedX = true; } } // Move vertically, check collisions player.y += player.vy; var collidedY = false; player.isOnGround = false; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; if (intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: plat.x, y: plat.y, width: plat.width, height: plat.height })) { // Collided vertically if (player.vy > 0) { // Falling, land on platform player.y = plat.y; player.vy = 0; player.isOnGround = true; // Update last safe platform index to this platform lastSafePlatformIndex = i; // If this is the boss platform and boss exists, start boss firing if (boss && plat.width >= 1800 && // Boss platform is the wide one typeof boss.bossStartFiring !== "undefined") { boss.bossStartFiring = true; } } else if (player.vy < 0) { // Hitting head player.y = plat.y + plat.height + player.height; player.vy = 0; } collidedY = true; } } // (bottomCloud platform collision removed) // (bottomCloud instant death logic removed) // --- Coin/Heart Collection --- for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; if (intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: coin.x - coin.width / 2, y: coin.y - coin.height / 2, width: coin.width, height: coin.height })) { // If this is a heart (centerCircle), increase playerLives, up to max 5 if (coin.isHeart) { if (playerLives < 5) { playerLives++; updateHearts(); } else { // If already at max health, give 20 points instead score += 20; scoreTxt.setText(score); // Every 20 points, convert to 1 life (up to max 5) if (score >= 20) { var extraLives = Math.floor(score / 20); var livesToAdd = Math.min(extraLives, 5 - playerLives); if (livesToAdd > 0) { playerLives += livesToAdd; updateHearts(); score -= livesToAdd * 20; scoreTxt.setText(score); } } } } else { // Otherwise, it's a coin, increase score and shop coins score += 1; shopCoins += 1; storage.shopCoins = shopCoins; scoreTxt.setText(score); // Every 20 points, convert to 1 life (up to max 5) if (score >= 20) { var extraLives = Math.floor(score / 20); var livesToAdd = Math.min(extraLives, 5 - playerLives); if (livesToAdd > 0) { playerLives += livesToAdd; updateHearts(); score -= livesToAdd * 20; scoreTxt.setText(score); } } } coin.destroy(); coins.splice(i, 1); } } // --- Checkpoint Collection --- // Only mark checkpoint as collected when falling, not on touch // (handled in fall logic below) // --- Bullets Update --- var bossFightActive = boss && boss.bossStartFiring === true; // Only update bullets if not in boss fight, or if they are boss/player bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // During boss fight, only allow boss/player bullets to move (skip all others) if (bossFightActive && !bullet.isBossProjectile) { // Pause non-boss bullets (do not update position) // Optionally, you could hide or destroy them here if desired continue; } bullet.update(); // Remove bullet if off screen (right side) if (bullet.lastX <= LEVEL_LENGTH && bullet.x > LEVEL_LENGTH) { bullet.destroy(); bullets.splice(i, 1); continue; } // Remove bullet if off left or out of vertical bounds, respawn at top if falls below if (bullet.x < 0 || bullet.y < 0) { bullet.destroy(); bullets.splice(i, 1); continue; } else if (bullet.y > 2732) { // Respawn bullet at the top of the screen, keep its x and vx/vy bullet.y = 0; // Optionally, you can randomize x or keep as is // bullet.x = Math.random() * 2048; // Keep lastY in sync to avoid false triggers bullet.lastY = bullet.y; } // --- Bullet stuck detection: remove if not moving for 12 frames --- if (typeof bullet.stuckFrames === "undefined") { bullet.stuckFrames = 0; } if (Math.abs(bullet.x - bullet.lastX) < 1 && Math.abs(bullet.y - bullet.lastY) < 1) { bullet.stuckFrames++; if (bullet.stuckFrames > 12) { bullet.destroy(); bullets.splice(i, 1); continue; } } else { bullet.stuckFrames = 0; } // Render bullet at camera-relative position bullet.displayObject = bullet.displayObject || bullet; bullet.displayObject.x = bullet.x - cameraX; bullet.displayObject.y = bullet.y; } // --- Auto-fire at boss when visible --- if (!bossFightActive) { if (boss && _typeof(boss) === "object" && typeof boss.x === "number" && typeof boss.y === "number") { // Check if boss is visible on screen (simple check: boss.x - cameraX in [0, 2048]) var bossScreenX = boss.x - cameraX; if (bossScreenX > 0 && bossScreenX < 2048) { // Only fire if enough time has passed since last auto-fire if (typeof bossAutoFireTimer === "undefined") { bossAutoFireTimer = 0; } bossAutoFireTimer++; // Fire every 18 frames (~3 shots per second) if (bossAutoFireTimer > 18) { bossAutoFireTimer = 0; // Create a bullet aimed at boss var autoBullet = new Bullet(); autoBullet.x = player.x; autoBullet.y = player.y - player.height / 2; autoBullet.lastX = autoBullet.x; // Aim at boss center var dx = boss.x - autoBullet.x; var dy = boss.y - boss.height / 2 - autoBullet.y; var len = Math.sqrt(dx * dx + dy * dy); var speed = 40; if (len > 0) { autoBullet.vx = dx / len * speed; autoBullet.vy = dy / len * speed; } else { autoBullet.vx = speed; autoBullet.vy = 0; } autoBullet.isControlled = false; bullets.push(autoBullet); game.addChild(autoBullet); } } else { // Reset timer if boss is not visible bossAutoFireTimer = 18; } } } // --- Enemy Update & Collision --- if (!bossFightActive) { // Delay enemy movement for 3 seconds after game start if (typeof enemyStartDelay === "undefined") { enemyStartDelay = 180; } // 3 seconds at 60fps if (enemyStartDelay > 0) { enemyStartDelay--; } else { if (typeof enemySpawnTimer === "undefined") { enemySpawnTimer = 0; } enemySpawnTimer++; // Spawn a new enemy every 120-200 frames (randomized) if (enemySpawnTimer > 120 + Math.floor(Math.random() * 80)) { var enemy = new Enemy(); // Spawn at right edge, random Y within play area enemy.x = cameraX + 2048 + enemy.width / 2; // Avoid top 200px and bottom 400px enemy.y = 400 + Math.random() * (2100 - 400); enemy.lastX = enemy.x; enemy.lastWasIntersecting = false; enemies.push(enemy); game.addChild(enemy); enemySpawnTimer = 0; } // Update and render enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Remove if off left side if (enemy.lastX >= -enemy.width && enemy.x < -enemy.width) { enemy.destroy(); enemies.splice(i, 1); continue; } // Render at camera-relative position enemy.displayObject = enemy.displayObject || enemy; enemy.displayObject.x = enemy.x - cameraX; enemy.displayObject.y = enemy.y; // --- Bullet-Enemy Collision --- var enemyDestroyed = false; for (var j = bullets.length - 1; j >= 0; j--) { var bullet = bullets[j]; // Boss projectiles do not collide with other enemies if (enemy.isBossProjectile) { continue; } // Use AABB for bullet-enemy collision if (intersectsAABB({ x: bullet.x - bullet.width / 2, y: bullet.y - bullet.height / 2, width: bullet.width, height: bullet.height }, { x: enemy.x - enemy.width / 2, y: enemy.y - enemy.height / 2, width: enemy.width, height: enemy.height })) { // Destroy both bullet and enemy bullet.destroy(); bullets.splice(j, 1); enemy.destroy(); enemies.splice(i, 1); // Optionally, add score or effect here score += 5; scoreTxt.setText(score); // Every 20 points, convert to 1 life (up to max 5) if (score >= 20) { var extraLives = Math.floor(score / 20); var livesToAdd = Math.min(extraLives, 5 - playerLives); if (livesToAdd > 0) { playerLives += livesToAdd; updateHearts(); score -= livesToAdd * 20; scoreTxt.setText(score); } } enemyDestroyed = true; break; } } if (enemyDestroyed) { continue; } // Check collision with player (only on the frame it starts) var isIntersecting = intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: enemy.x - enemy.width / 2, y: enemy.y - enemy.height / 2, width: enemy.width, height: enemy.height }); if (!enemy.lastWasIntersecting && isIntersecting) { // If this is a boss projectile, damage player and destroy projectile if (enemy.isBossProjectile) { LK.effects.flashScreen(0xff0000, 1000); playerLives--; updateHearts(); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } enemy.destroy(); enemies.splice(i, 1); continue; } // Player hit by enemy! LK.effects.flashScreen(0xff0000, 1000); playerLives--; updateHearts(); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } // Do not respawn or move player, just continue playing } enemy.lastWasIntersecting = isIntersecting; } } // end else for enemyStartDelay } // --- Boss Fight: Boss projectiles damage player --- if (bossFightActive) { for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Remove if off left side or out of bounds if (enemy.lastX >= -enemy.width && enemy.x < -enemy.width) { enemy.destroy(); enemies.splice(i, 1); continue; } // Render at camera-relative position enemy.displayObject = enemy.displayObject || enemy; enemy.displayObject.x = enemy.x - cameraX; enemy.displayObject.y = enemy.y; // Only check boss projectiles for player collision if (enemy.isBossProjectile) { var isIntersecting = intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: enemy.x - enemy.width / 2, y: enemy.y - enemy.height / 2, width: enemy.width, height: enemy.height }); if (!enemy.lastWasIntersecting && isIntersecting) { LK.effects.flashScreen(0xff0000, 1000); playerLives--; updateHearts(); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } enemy.destroy(); enemies.splice(i, 1); continue; } enemy.lastWasIntersecting = isIntersecting; } } } // --- Boss Update & Collision --- // Boss health bar setup (global, so only one at a time) if (typeof bossHealthBarBg === "undefined") { bossHealthBarBg = null; } if (typeof bossHealthBarFill === "undefined") { bossHealthBarFill = null; } if (boss && typeof boss.update === "function") { boss.update(); // Render boss at camera-relative position boss.displayObject = boss.displayObject || boss; boss.displayObject.x = boss.x - cameraX; boss.displayObject.y = boss.y; // --- Boss Health Bar --- // Create health bar if not exists if (!bossHealthBarBg) { // Background bar (custom asset) bossHealthBarBg = LK.getAsset('bossHealthBarBg', { anchorX: 0.5, anchorY: 0.5 }); bossHealthBarBg.alpha = 0.7; game.addChild(bossHealthBarBg); // Fill bar (custom asset) bossHealthBarFill = LK.getAsset('bossHealthBarFill', { anchorX: 0, anchorY: 0.5 }); bossHealthBarFill.alpha = 0.95; game.addChild(bossHealthBarFill); } // Update health bar position above boss if (bossHealthBarBg && bossHealthBarFill) { // Bar width and percent var barW = boss.width * 0.8; var barH = 44; var fillW = boss.width * 0.78; var fillH = 32; var percent = Math.max(0, boss.hp / 15); // Position above boss head (50px above top) var barX = boss.x - cameraX; var barY = boss.y - boss.height / 2 - 50; bossHealthBarBg.x = barX; bossHealthBarBg.y = barY; bossHealthBarBg.width = barW; bossHealthBarBg.height = barH; bossHealthBarBg.visible = true; bossHealthBarFill.x = barX - fillW / 2; bossHealthBarFill.y = barY; bossHealthBarFill.width = fillW * percent; bossHealthBarFill.height = fillH; bossHealthBarFill.visible = true; } // Bullet-boss collision for (var j = bullets.length - 1; j >= 0; j--) { var bullet = bullets[j]; if (intersectsAABB({ x: bullet.x - bullet.width / 2, y: bullet.y - bullet.height / 2, width: bullet.width, height: bullet.height }, { x: boss.x - boss.width / 2, y: boss.y - boss.height / 2, width: boss.width, height: boss.height })) { // Boss can only be damaged if not shielded, or if weak spot is open if (!boss.shieldActive && (boss.phase === 1 || boss.weakSpotOpen || boss.phase === 1)) { boss.hp--; bullet.destroy(); bullets.splice(j, 1); // Flash boss on hit LK.effects.flashObject(boss, 0xff0000, 200); // If boss defeated if (boss.hp <= 0) { LK.effects.flashScreen(0x00ff00, 1000); boss.destroy(); boss = null; score += 50; scoreTxt.setText(score); // Remove boss health bar if (bossHealthBarBg) { bossHealthBarBg.visible = false; bossHealthBarBg.destroy(); bossHealthBarBg = null; } if (bossHealthBarFill) { bossHealthBarFill.visible = false; bossHealthBarFill.destroy(); bossHealthBarFill = null; } // End the game with a win when boss is defeated LK.setScore(score); LK.showYouWin(); return; } break; } else { // Boss is shielded or not vulnerable, bullet bounces off (destroy bullet) bullet.destroy(); bullets.splice(j, 1); // Optional: flash boss blue for shield if (boss.shieldActive && boss.displayObject) { LK.effects.flashObject(boss, 0x44aaff, 120); } break; } } } // Boss-player collision (only on the frame it starts) if (boss) { // Defensive: boss may have been destroyed above var bossIntersect = intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: boss.x - boss.width / 2, y: boss.y - boss.height / 2, width: boss.width, height: boss.height }); if (!boss.lastWasIntersecting && bossIntersect) { LK.effects.flashScreen(0xff0000, 1000); playerLives--; updateHearts(); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); // Remove boss health bar if (bossHealthBarBg) { bossHealthBarBg.visible = false; bossHealthBarBg.destroy(); bossHealthBarBg = null; } if (bossHealthBarFill) { bossHealthBarFill.visible = false; bossHealthBarFill.destroy(); bossHealthBarFill = null; } return; } } boss.lastWasIntersecting = bossIntersect; } } else { // No boss: remove health bar if exists if (bossHealthBarBg) { bossHealthBarBg.visible = false; bossHealthBarBg.destroy(); bossHealthBarBg = null; } if (bossHealthBarFill) { bossHealthBarFill.visible = false; bossHealthBarFill.destroy(); bossHealthBarFill = null; } } // --- Hazard Update & Collision --- // Remove hazards during boss fight (currentLevel === 2 and boss exists) if (typeof hazards !== "undefined" && hazards.length && (typeof currentLevel === "undefined" || currentLevel === 1 || typeof currentLevel !== "undefined" && currentLevel === 2 && !boss)) { for (var i = hazards.length - 1; i >= 0; i--) { var hazard = hazards[i]; // Ensure hazard has valid properties if (!hazard || typeof hazard.x !== "number" || typeof hazard.y !== "number") { hazards.splice(i, 1); continue; } // Initialize velocity if not set if (typeof hazard.vy !== "number") { hazard.vy = 12 + Math.random() * 6; } // Move hazard down hazard.y += hazard.vy; // Render at camera-relative position hazard.displayObject = hazard.displayObject || hazard; if (hazard.displayObject) { hazard.displayObject.x = hazard.x - cameraX; hazard.displayObject.y = hazard.y; } // Remove if off screen if (hazard.y > 2732 + 200) { hazard.destroy(); hazards.splice(i, 1); continue; } // Check collision with player (AABB) if (player.x - player.width / 2 < hazard.x + hazard.width / 2 && player.x + player.width / 2 > hazard.x - hazard.width / 2 && player.y - player.height < hazard.y + hazard.height / 2 && player.y > hazard.y - hazard.height / 2) { LK.effects.flashScreen(0xff0000, 800); playerLives--; updateHearts(); hazard.destroy(); hazards.splice(i, 1); if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } } } } else if (typeof hazards !== "undefined" && hazards.length && typeof currentLevel !== "undefined" && currentLevel === 2 && boss) { // If boss fight is active, despawn all hazards immediately for (var i = hazards.length - 1; i >= 0; i--) { if (hazards[i] && typeof hazards[i].destroy === "function") { hazards[i].destroy(); } } hazards = []; } // --- Camera & Distance --- updateCamera(); // Move all objects to screen position (for rendering only, do not overwrite world position) for (var i = 0; i < platforms.length; i++) { platforms[i].displayObject = platforms[i].displayObject || platforms[i]; platforms[i].displayObject.x = platforms[i].xScreen; platforms[i].displayObject.y = platforms[i].y; } for (var i = 0; i < coins.length; i++) { coins[i].displayObject = coins[i].displayObject || coins[i]; coins[i].displayObject.x = coins[i].xScreen; coins[i].displayObject.y = coins[i].y; } player.displayObject = player.displayObject || player; player.displayObject.x = player.xScreen; player.displayObject.y = player.y; // Move coffeeHouse to screen position if exists if (coffeeHouse && typeof coffeeHouse.xScreen !== "undefined") { coffeeHouse.x = coffeeHouse.xScreen; coffeeHouse.y = coffeeHouse.yScreen; } // (bottomCloud render removed) // (hazard removed) // --- Distance --- distance = Math.floor((player.x + cameraX) / 10); distTxt.setText(distance + "m"); // --- Win/Lose Conditions --- // Fall off screen if (player.y > 2732) { LK.effects.flashScreen(0xff0000, 1000); playerLives--; updateHearts(); // Find the platform the player was last above before falling if (typeof lastFallenPlatformIndex === "undefined") { lastFallenPlatformIndex = 0; } lastFallenPlatformIndex = 0; var minDist = Infinity; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; // Check if player was horizontally above this platform when falling if (player.x + player.width / 2 >= plat.x && player.x - player.width / 2 <= plat.x + plat.width) { // Find the closest platform vertically below the player var dy = player.y - plat.y; if (dy >= 0 && dy < minDist) { minDist = dy; lastFallenPlatformIndex = i; } } } // Find the nearest checkpoint at or before the fallen platform var checkpointToRespawn = 0; if (typeof checkpoints !== "undefined" && checkpoints.length) { var closestCheckpointIndex = -1; for (var i = 0; i < checkpoints.length; i++) { var checkpoint = checkpoints[i]; if (checkpoint.platformIndex <= lastFallenPlatformIndex) { if (closestCheckpointIndex === -1 || checkpoint.platformIndex > checkpoints[closestCheckpointIndex].platformIndex) { closestCheckpointIndex = i; } } } if (closestCheckpointIndex !== -1) { checkpointToRespawn = checkpoints[closestCheckpointIndex].platformIndex; // Mark checkpoint as collected if (!checkpoints[closestCheckpointIndex].collected) { checkpoints[closestCheckpointIndex].collected = true; lastCheckpointIndex = checkpointToRespawn; checkpoints[closestCheckpointIndex].alpha = 0.5; } } } if (playerLives <= 0) { gameOver = true; LK.showGameOver(); return; } else { // Respawn player at the nearest checkpoint (every 10th platform), or at the platform they fell from if no checkpoint reached if (typeof checkpointToRespawn !== "undefined" && checkpointToRespawn > 0 && checkpointToRespawn < platforms.length) { lastFallenPlatformIndex = checkpointToRespawn; } resetPlayer(true); // Optionally, move camera to player updateCamera(); return; } } // Reached coffee house (win condition) if (coffeeHouse && intersectsAABB({ x: player.x - player.width / 2, y: player.y - player.height, width: player.width, height: player.height }, { x: coffeeHouse.x - coffeeHouse.width / 2, y: coffeeHouse.y - coffeeHouse.height, width: coffeeHouse.width, height: coffeeHouse.height })) { LK.effects.flashScreen(0x00ff00, 1000); LK.setScore(score); // If on level 1, 2, 3, or 4, transition to next level if (typeof currentLevel === "undefined" || currentLevel === 1 || currentLevel === 2 || currentLevel === 3 || currentLevel === 4) { if (typeof showKiraathaneSection === "function") { showKiraathaneSection(); } else { // Fallback: just pause the game and show a message overlay var overlay = new Text2("Kıraathaneye ulaştın!\nYeni bölüm geliyor...", { size: 120, fill: 0x222222, align: "center" }); overlay.anchor.set(0.5, 0.5); overlay.x = 2048 / 2; overlay.y = 2732 / 2; LK.gui.center.addChild(overlay); gameOver = true; } return; } } // Win condition: player reaches the last platform // (Removed win condition when stepping on the last platform so the game does not end) // if (platforms.length > 0) { // var lastPlat = platforms[platforms.length - 1]; // if (player.x + player.width / 2 >= lastPlat.x && player.x - player.width / 2 <= lastPlat.x + lastPlat.width && player.y >= lastPlat.y && player.y - player.height <= lastPlat.y + lastPlat.height) { // LK.effects.flashScreen(0x00ff00, 1000); // LK.setScore(score); // LK.showYouWin(); // gameOver = true; // return; // } // } }; // --- Game Start --- // --- Title Screen with Play Button --- var gameStarted = false; var titleScreen = null; var playButton = null; var gameTitle = null; function createTitleScreen() { // Create animated background elements first var bgElements = []; // Add moving clouds for (var i = 0; i < 5; i++) { var cloud = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5 }); cloud.x = i * 500 - 200; cloud.y = 300 + Math.random() * 400; cloud.speed = 2 + Math.random() * 3; cloud.alpha = 0.3; bgElements.push(cloud); game.addChild(cloud); } // Add moving platforms across entire screen area for (var i = 0; i < 6; i++) { var platform = LK.getAsset('platformBox', { anchorX: 0, anchorY: 0 }); platform.x = i * 700 - 1000; // Fewer platforms, wider spacing // Store original Y for animation reference platform.baseY = Math.random() * 2732; // Distribute across entire screen height (0 to 2732) platform.y = platform.baseY; platform.speed = 1.5 + Math.random() * 3; // Varied speed range platform.alpha = 0.3 + Math.random() * 0.3; // Varied transparency bgElements.push(platform); game.addChild(platform); // Gentle up-down animation using tween, looped (function animatePlatformY(p) { var amplitude = 40 + Math.random() * 30; // 40-70px var duration = 1200 + Math.random() * 600; // 1.2-1.8s tween(p, { y: p.baseY + amplitude }, { duration: duration, easing: tween.sineInOut, onFinish: function onFinish() { tween(p, { y: p.baseY - amplitude }, { duration: duration, easing: tween.sineInOut, onFinish: function onFinish() { animatePlatformY(p); } }); } }); })(platform); } // Add animated tea (çay) assets with gentle up-down animation for (var i = 0; i < 3; i++) { var cay = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); // Place çay at visually pleasing locations on the title screen cay.x = 600 + i * 400; cay.baseY = 1200 + Math.random() * 400; cay.y = cay.baseY; cay.alpha = 0.85; bgElements.push(cay); game.addChild(cay); // Gentle up-down animation using tween, looped (function animateCayY(c) { var amplitude = 30 + Math.random() * 20; // 30-50px var duration = 1100 + Math.random() * 500; // 1.1-1.6s tween(c, { y: c.baseY + amplitude }, { duration: duration, easing: tween.sineInOut, onFinish: function onFinish() { tween(c, { y: c.baseY - amplitude }, { duration: duration, easing: tween.sineInOut, onFinish: function onFinish() { animateCayY(c); } }); } }); })(cay); } // Add market building moving across title screen var market = LK.getAsset('coffeeHouse', { anchorX: 0.5, anchorY: 1 }); market.x = -600; // Start off screen left market.y = 1800 + Math.random() * 400; // Position in lower area market.speed = 2.5 + Math.random() * 2; // Medium speed market.alpha = 0.5; market.scaleX = 0.8; market.scaleY = 0.8; bgElements.push(market); game.addChild(market); // Add occasional boss passing through (every ~8-12 seconds) var boss = LK.getAsset('bossUnique', { anchorX: 0.5, anchorY: 0.5 }); boss.x = -800; // Start off screen left boss.y = 1000 + Math.random() * 600; boss.speed = 6 + Math.random() * 3; // Faster than other elements boss.alpha = 0.6; boss.nextSpawnTime = 480 + Math.random() * 240; // 8-12 seconds at 60fps boss.isVisible = false; bgElements.push(boss); game.addChild(boss); // Add moving sun var sun = LK.getAsset('sun', { anchorX: 0.5, anchorY: 0.5 }); sun.x = 300; sun.y = 200; sun.alpha = 0.5; bgElements.push(sun); game.addChild(sun); // Store background elements for animation game.titleBgElements = bgElements; // Create title background - use existing color background instead of asset game.setBackgroundColor(0x87ceeb); // Keep sky blue background visible // Create game title as image asset gameTitle = LK.getAsset('kebabRunnerTitle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); gameTitle.x = 2048 / 2; gameTitle.y = 400; game.addChild(gameTitle); // Create play button background playButton = LK.getAsset('playButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); playButton.x = 2048 / 2 - 400 - 150; playButton.y = 1600; playButton.interactive = true; game.addChild(playButton); // Create shop button with dedicated asset shopButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); shopButton.x = 2048 / 2 + 400 + 150; shopButton.y = 1635; // 10px lower than before shopButton.interactive = true; game.addChild(shopButton); // Add shop icon on button var shopIcon = LK.getAsset('shopIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); shopIcon.x = shopButton.x; shopIcon.y = shopButton.y; game.addChild(shopIcon); shopButton.shopIcon = shopIcon; // (Removed shop text below icon as requested) // Add pulsing animation to play button if (playButton) { tween(playButton, { scaleX: 0.35, scaleY: 0.35 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { if (playButton) { tween(playButton, { scaleX: 0.3, scaleY: 0.3 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Recursive call to create infinite loop if (playButton && !gameStarted) { tween(playButton, { scaleX: 0.35, scaleY: 0.35 }, { duration: 1000, easing: tween.easeInOut, onFinish: arguments.callee.caller }); } } }); } } }); } // Hide game UI during title screen if (scoreTxt) { scoreTxt.visible = false; } if (distTxt) { distTxt.visible = false; } if (heartAssets && heartAssets.length) { for (var i = 0; i < heartAssets.length; i++) { if (heartAssets[i]) { heartAssets[i].visible = false; } } } // Hide control buttons during title screen if (leftBtn) { leftBtn.visible = false; } if (rightBtn) { rightBtn.visible = false; } if (jumpBtn) { jumpBtn.visible = false; } if (fireBtn) { fireBtn.visible = false; } if (leftIcon) { leftIcon.visible = false; } if (rightIcon) { rightIcon.visible = false; } if (jumpIcon) { jumpIcon.visible = false; } if (terlikIcon) { terlikIcon.visible = false; } } function removeTitleScreen() { // Clean up animated background elements if (game.titleBgElements) { for (var i = 0; i < game.titleBgElements.length; i++) { if (game.titleBgElements[i]) { game.titleBgElements[i].destroy(); } } game.titleBgElements = null; } if (titleScreen) { titleScreen.destroy(); titleScreen = null; } if (playButton) { playButton.destroy(); playButton = null; } if (gameTitle) { gameTitle.destroy(); gameTitle = null; } if (shopButton) { if (shopButton.shopText) { shopButton.shopText.destroy(); } if (shopButton.shopIcon) { shopButton.shopIcon.destroy(); } shopButton.destroy(); shopButton = null; } if (shopVisible) { hideShop(); } // Show control buttons when title screen is removed if (leftBtn) { leftBtn.visible = true; } if (rightBtn) { rightBtn.visible = true; } if (jumpBtn) { jumpBtn.visible = true; } if (fireBtn) { fireBtn.visible = true; } if (leftIcon) { leftIcon.visible = true; } if (rightIcon) { rightIcon.visible = true; } if (jumpIcon) { jumpIcon.visible = true; } if (terlikIcon) { terlikIcon.visible = true; } } function startGameFromTitle() { gameStarted = true; removeTitleScreen(); // Show game UI if (scoreTxt) { scoreTxt.visible = true; } if (distTxt) { distTxt.visible = true; } if (heartAssets && heartAssets.length) { for (var i = 0; i < heartAssets.length; i++) { if (heartAssets[i]) { heartAssets[i].visible = i < playerLives; } } } // Start the actual game startGame(); } // Check if point is inside play button function isInsidePlayButton(x, y) { if (!playButton) { return false; } var bx = playButton.x; var by = playButton.y; var bw = playButton.width; var bh = playButton.height; return x >= bx - bw / 2 && x <= bx + bw / 2 && y >= by - bh / 2 && y <= by + bh / 2; } // Check if point is inside shop button function isInsideShopButton(x, y) { if (!shopButton) { return false; } var bx = shopButton.x; var by = shopButton.y; var bw = shopButton.width; var bh = shopButton.height; return x >= bx - bw / 2 && x <= bx + bw / 2 && y >= by - bh / 2 && y <= by + bh / 2; } // Toggle shop visibility function toggleShop() { if (shopVisible) { hideShop(); } else { showShop(); } } // Show shop panel function showShop() { if (shopPanel) { return; } // Already showing shopVisible = true; // Disable playButton while shop is open if (playButton) { playButton.interactive = false; playButton.alpha = 0.5; } // Create shop background panel shopPanel = LK.getAsset('heartBox', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 35 }); shopPanel.x = 2048 / 2; shopPanel.y = 2732 / 2; shopPanel.alpha = 0.95; game.addChild(shopPanel); // Shop title var title = new Text2('SHOP', { size: 120, fill: 0x000000 }); title.anchor.set(0.5, 0.5); title.x = 2048 / 2; title.y = 600; game.addChild(title); shopPanel.title = title; // Coins display var coinsText = new Text2('Coins: ' + shopCoins, { size: 80, fill: 0x000000 }); coinsText.anchor.set(0.5, 0.5); coinsText.x = 2048 / 2; coinsText.y = 750; game.addChild(coinsText); shopPanel.coinsText = coinsText; // Create shop items createShopItems(); // Close button var closeBtn = LK.getAsset('btnFireBg', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); closeBtn.x = 2048 / 2; closeBtn.y = 2300; game.addChild(closeBtn); shopPanel.closeBtn = closeBtn; var closeText = new Text2('CLOSE', { size: 60, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.x = closeBtn.x; closeText.y = closeBtn.y; game.addChild(closeText); shopPanel.closeText = closeText; } // Hide shop panel function hideShop() { if (!shopPanel) { return; } shopVisible = false; // Re-enable playButton when shop is closed if (playButton) { playButton.interactive = true; playButton.alpha = 1; } // Destroy all shop elements if (shopPanel.title) { shopPanel.title.destroy(); } if (shopPanel.coinsText) { shopPanel.coinsText.destroy(); } if (shopPanel.closeBtn) { shopPanel.closeBtn.destroy(); } if (shopPanel.closeText) { shopPanel.closeText.destroy(); } // Destroy shop items if (shopPanel.items) { for (var i = 0; i < shopPanel.items.length; i++) { var item = shopPanel.items[i]; if (item.bg) { item.bg.destroy(); } if (item.nameText) { item.nameText.destroy(); } if (item.priceText) { item.priceText.destroy(); } if (item.levelText) { item.levelText.destroy(); } } } shopPanel.destroy(); shopPanel = null; } // Create shop items function createShopItems() { if (!shopPanel) { return; } shopPanel.items = []; // No items to add, shop is empty } // Handle shop touch interactions function handleShopTouch(x, y) { if (!shopPanel) { return; } // Check close button if (shopPanel.closeBtn) { var btn = shopPanel.closeBtn; if (x >= btn.x - btn.width / 2 && x <= btn.x + btn.width / 2 && y >= btn.y - btn.height / 2 && y <= btn.y + btn.height / 2) { hideShop(); return; } } // Check item purchases if (shopPanel.items) { for (var i = 0; i < shopPanel.items.length; i++) { var item = shopPanel.items[i]; var bg = item.bg; if (x >= bg.x - bg.width / 2 && x <= bg.x + bg.width / 2 && y >= bg.y - bg.height / 2 && y <= bg.y + bg.height / 2) { purchaseItem(item); return; } } } } // Purchase shop item function purchaseItem(item) { if (item.owned) { // Already owned, do nothing LK.effects.flashScreen(0x00ff00, 300); return; } if (shopCoins >= item.price) { shopCoins -= item.price; shopItems[item.key] = 1; // Mark as owned // Save to storage storage.shopCoins = shopCoins; storage.shopItems = shopItems; // Update display hideShop(); showShop(); // If skin1 was just purchased and player exists, update player asset if (item.key === 'skin1' && typeof player !== "undefined" && player) { // Remove old asset if present if (player.displayObject && player.displayObject.parent) { player.displayObject.parent.removeChild(player.displayObject); } // Attach new asset (terlikIcon) var newAsset = player.attachAsset('terlikIcon', { anchorX: 0.5, anchorY: 1 }); player.width = newAsset.width; player.height = newAsset.height; player.displayObject = newAsset; } // Flash effect LK.effects.flashScreen(0x00ff00, 500); } else { // Not enough coins LK.effects.flashScreen(0xff0000, 500); } } // Create title screen initially createTitleScreen(); var _origUpdate = game.update; game.update = function () { // Animate title screen background elements if (!gameStarted && game.titleBgElements) { for (var i = 0; i < game.titleBgElements.length; i++) { var element = game.titleBgElements[i]; if (element) { // Special handling for boss element if (element.nextSpawnTime !== undefined) { // This is the boss element if (!element.isVisible) { // Boss is waiting to spawn element.nextSpawnTime--; if (element.nextSpawnTime <= 0) { // Time to spawn boss element.isVisible = true; element.x = -800; element.y = 1000 + Math.random() * 600; element.visible = true; // Add slight tween animation for dramatic effect tween(element, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(element, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut }); } }); } } else { // Boss is moving across screen element.x += element.speed || 6; // Reset when off screen if (element.x > 2048 + 400) { element.isVisible = false; element.visible = false; element.nextSpawnTime = 480 + Math.random() * 240; // 8-12 seconds } } } else { // Regular element movement element.x += element.speed || 2; // Reset position when off screen if (element.x > 2048 + 200) { element.x = -500; // Start further off-screen for better distribution // Randomize Y position for clouds, platforms, and market if (element.speed < 5) { // clouds have lower speed element.y = 300 + Math.random() * 400; } else if (element.scaleX === 0.8 && element.scaleY === 0.8) { // market building - reset in lower area element.y = 1800 + Math.random() * 400; } else { // platforms - reset across entire screen height (0 to 2732) element.y = Math.random() * 2732; } } // Add gentle floating animation to sun if (element === game.titleBgElements[game.titleBgElements.length - 1] && element.nextSpawnTime === undefined) { element.y = 200 + Math.sin(LK.ticks * 0.02) * 20; } } } } } if (_origUpdate) { return _origUpdate.apply(this, arguments); } }; function startGame() { score = 0; distance = 0; gameOver = false; playerLives = 3; maxPlayerAmmo = 10; playerAmmo = maxPlayerAmmo; // Ava: refill ammo at game start scoreTxt.setText(score); distTxt.setText(distance + "m"); // Reset level to 1 at game start currentLevel = 1; // Reset enemies array and destroy old enemies if any if (typeof enemies !== "undefined" && enemies && enemies.length) { for (var i = 0; i < enemies.length; i++) { if (enemies[i] && typeof enemies[i].destroy === "function") { enemies[i].destroy(); } } } enemies = []; // Reset checkpoints and lastCheckpointIndex checkpoints = []; lastCheckpointIndex = 0; createLevel(); resetPlayer(); updateHearts(); // (hazard removed) // Remove hazards if any if (typeof hazards !== "undefined" && hazards.length) { for (var i = 0; i < hazards.length; i++) { if (hazards[i] && typeof hazards[i].destroy === "function") { hazards[i].destroy(); } } } hazards = []; cameraX = 0; moveDir = 0; enemyStartDelay = 180; // 3 seconds at 60fps } // --- Start --- // Game will start when play button is pressed on title screen // Show new section/scene after reaching coffeehouse (placeholder, can be customized) // Track current level globally (1-based) var currentLevel = 1; if (typeof currentLevel === "undefined") { currentLevel = 1; } function showKiraathaneSection() { // Increase level up to 5 if (typeof currentLevel === "undefined") { currentLevel = 1; } if (currentLevel < 5) { currentLevel++; } // Remove all game objects except GUI for (var i = 0; i < platforms.length; i++) { platforms[i].destroy(); } for (var i = 0; i < coins.length; i++) { coins[i].destroy(); } if (player) { player.destroy(); } if (coffeeHouse) { coffeeHouse.destroy(); } for (var i = 0; i < enemies.length; i++) { enemies[i].destroy(); } for (var i = 0; i < bullets.length; i++) { bullets[i].destroy(); } if (typeof boss !== "undefined" && boss) { boss.destroy(); boss = null; } // Reset arrays platforms = []; coins = []; enemies = []; bullets = []; coffeeHouse = null; // Optionally, clear checkpoints for the new section checkpoints = []; lastCheckpointIndex = 0; // Remove hazards if any if (typeof hazards !== "undefined" && hazards.length) { for (var i = 0; i < hazards.length; i++) { if (hazards[i] && typeof hazards[i].destroy === "function") { hazards[i].destroy(); } } } hazards = []; // Move camera to the start cameraX = 0; // Create a new set of platforms, coins, and coffeehouse (same as first section) createLevel(); resetPlayer(); playerAmmo = maxPlayerAmmo; // Ava: refill ammo on level transition // Reset game state for the new section gameOver = false; moveDir = 0; enemyStartDelay = 180; // 3 seconds at 60fps // Show overlay for transition, indicating level number with black background and white text var levelText = currentLevel + ". lvl"; var overlayBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, width: 900, height: 300, color: 0x000000 }); overlayBg.x = 2048 / 2; overlayBg.y = 2732 / 2; overlayBg.alpha = 0.85; LK.gui.center.addChild(overlayBg); var kiraathaneOverlay = new Text2(levelText, { size: 180, fill: 0xffffff, align: "center" }); kiraathaneOverlay.anchor.set(0.5, 0.5); kiraathaneOverlay.x = 2048 / 2; kiraathaneOverlay.y = 2732 / 2; LK.gui.center.addChild(kiraathaneOverlay); // Remove overlay after 1.5 seconds LK.setTimeout(function () { kiraathaneOverlay.destroy(); overlayBg.destroy(); }, 1500); }
===================================================================
--- original.js
+++ change.js
@@ -587,9 +587,9 @@
scaleX: 1.5,
scaleY: 1.5
});
melodyBtn.x = 100 + 60 - 800 + 10; // 10px more to the right (net: 10px to the left)
-melodyBtn.y = 100 + 60; // 100px margin from top, 60px for radius
+melodyBtn.y = 100 + 60 + 100; // 100px margin from top, 60px for radius, 100px further down
melodyBtn.width = 180;
melodyBtn.height = 180;
melodyBtn.interactive = true;
melodyBtn.alpha = 0.92;
cloud. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
sun. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
çay bardağı. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a kebap. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
baba terliği. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
starbucks kahvesi ama kızgın ve canlı. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
geleneksel türk kıraathanesi. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
starbucks kahvesi ama kaslı ve kıravartı olan sinirli bir starbucks kahvesi. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
180 derece stabucks kahvesi . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
kırmızı ok. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
okun ucu sola baksın ve hiçbirşey değişmesin
şimdi ok yine değişmesin sadece ucu sağa baksın
şiş in içine geçmiş bir şekilde play yazıcak ama domates biber ve etten yani gerçek kebab gibi ama harfler var. daha çizgifilmsel olacak mesela "p" et "l" biber "a" domates "y" et
"Kebab Runner" yaz ama 1 şiş kebab yazının üstünde duracak olacak yani oyunun
çaydanlık adam. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
buzlu bir americano ama stabucks kahvesi çevresi beyaz olsun içinde çok buz olsun No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat