User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'x')' in or related to this line: 'hazard.x = plat.x + plat.width / 2 + (Math.random() - 0.5) * 200;' Line Number: 463
User prompt
ilk bölümde biraz daha hazard gelsin
User prompt
boss a can barı ekle üstünde dursun
User prompt
oyun 2. bölümde çok fazla düşman gönderiyor bunu düzelt
User prompt
bossun mermileri için yeni bir assets yap
User prompt
boss karakteri görünce ateş etmeye başlasın kodla
User prompt
bunları kodla
User prompt
bossu 200 pixel yukarı al
User prompt
18. satırı düzelt
User prompt
bossu 150 pixel yukarı al
User prompt
bossun ayakları tam platforma değecek şekilde kodla
User prompt
boss için sıfırdan bir assets yap
User prompt
bossa yeni bir görünüm kodla
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'x')' in or related to this line: 'var bossIntersect = intersectsAABB({' Line Number: 816
User prompt
son platforma adım atınca oyun bitmesin
User prompt
2. alanın sonundaki platforma 1 tane yeni boss kodla
User prompt
2. etabın sonuna platform yerine geniş bir alan koy
User prompt
2. etaba geçince 2. etaptan kıraathaneyi kaldır
User prompt
her kıraathanenin içine atladığımda ekrana 2.lvl 3.lvl 4. lvl ve 5.lvl diye yazı gelsin siyah bir fontun üstüne düz yazı şeklinde yazsın kodla
User prompt
her kıraathanenin içine atladığımda ekrana 2.lvl 3.lvl 4. lvl ve 5.lvl diye yazı gelsin siayh bi fontun üstüne düz yazı şeklinde yazsın kodla
User prompt
her kıraathanenin içine atladığımda 2.lvl 3.lvl 4. lvl ve 5.lvl gelsin
User prompt
coffeehouseden geçtikten sonra hemen aynı şekilde platformlar olsun bunu kodla
User prompt
oyunu 10 platform uzunluğunda yap
User prompt
oyunun sonunda kıraathaneye ulaşınca başka bi bölüme geçsin ama lvl değişmesin tek lvl olacak
User prompt
aşağı düşünce başa spawnlama
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // 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: flies from right to left, tries to hit the player var Enemy = Container.expand(function () { var self = Container.call(this); var enemyAsset = self.attachAsset('hazard', { anchorX: 0.5, anchorY: 0.5 }); self.width = enemyAsset.width; self.height = enemyAsset.height; self.vx = -8 - Math.random() * 4; // Move left, much slower speed self.lastX = 0; self.lastWasIntersecting = false; self.update = function () { self.lastX = self.x; self.x += self.vx; }; 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) var playerAsset = self.attachAsset('playerBox', { 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; // 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 ****/ // New bullet figure asset (example: blue ellipse, unique id) // Sun and cloud assets (example IDs, replace with real asset IDs as needed) // --- Asset Initialization (shapes) --- // Tween for animations (jump, enemy movement, etc) // --- Game Variables --- var GRAVITY = 2.2; var JUMP_VELOCITY = -54; var PLAYER_SPEED = 16; var SCROLL_SPEED = 10; var LEVEL_LENGTH = 950 * 149 + 600 + 500; // 150 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 cameraX = 0; var score = 0; var distance = 0; var gameOver = false; // --- GUI --- // Hearts (5 total, left-aligned, with spacing) var heartAssets = []; var heartSpacing = 120; var playerLives = 3; // Total lives/can 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 }); heart.x = 180 + i * heartSpacing; // Shifted 150px left from previous position heart.y = 100; LK.gui.top.addChild(heart); heartAssets.push(heart); } updateHearts(); var scoreTxt = new Text2('0', { size: 100, fill: 0xFFF700 }); scoreTxt.anchor.set(0.5, 0); 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 = 110; // --- 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); // Platform layout: up/down, not fixed order, player can jump between them var numPlatforms = 150; var platSpacingX = 950; // Further increased horizontal spacing for much more space var platMinY = 800; // Lowered min Y for more vertical play area var platMaxY = 1900; // Raised max Y for more vertical play 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; // Add start platform at the very beginning var startPlat = new Platform(); startPlat.x = 100; startPlat.y = 2000; platforms.push(startPlat); game.addChild(startPlat); // Place a coin above the start platform var startCoin = new Coin(); startCoin.x = startPlat.x + startPlat.width / 2; startCoin.y = startPlat.y - 80; coins.push(startCoin); game.addChild(startCoin); for (var i = 0; i < numPlatforms; i++) { 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); // Store checkpoint objects in an array for respawn logic if (typeof checkpoints === "undefined") checkpoints = []; checkpoints.push(checkpoint); } } // Add coffee house on the last platform if (platforms.length > 0) { 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 = 2200; } player.vx = 0; player.vy = 0; player.isOnGround = false; game.addChild(player); } // --- 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; } // (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 --- // Touch controls: tap anywhere to jump, hold left/right for movement var moveDir = 0; // -1 = left, 1 = right, 0 = none game.down = function (x, y, obj) { if (gameOver) return; // Convert to game coordinates var gx = x + cameraX; // Always allow jump on tap down, anywhere if (player.isOnGround) { player.jumpRequested = true; } // Hold left/right for movement if (x < 2048 / 2) { moveDir = -1; } else { moveDir = 1; // Fire a bullet only if the previous tap was an "armed" tap (require two separate taps to fire) if (typeof fireArmed === "undefined") fireArmed = false; if (!fireArmed) { // First tap: arm for firing fireArmed = true; } else { // Second tap: actually fire bullet 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; fireArmed = false; // Reset arming } } }; game.up = function (x, y, obj) { moveDir = 0; // Release bullet control on touch up if (game.controlledBullet && game.controlledBullet.isControlled) { game.controlledBullet.isControlled = false; game.controlledBullet = null; } }; game.move = function (x, y, obj) { // Allow drag to change direction if (x < 2048 / 2) { moveDir = -1; } else { moveDir = 1; } // If a controlled bullet exists, update its velocity based on drag direction if (game.controlledBullet && game.controlledBullet.isControlled) { // Calculate direction from bullet to current pointer 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 () { if (gameOver) return; // --- Player Movement --- // Horizontal movement player.vx = moveDir * PLAYER_SPEED; // Apply gravity player.vy += GRAVITY; // Jump if (player.jumpRequested) { player.vy = JUMP_VELOCITY; player.jumpRequested = false; player.isOnGround = 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; } else if (player.vy < 0) { // Hitting head player.y = plat.y + plat.height + player.height; player.vy = 0; } collidedY = true; } } // --- 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 { // Otherwise, it's a coin, increase score score += 1; 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 --- for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; 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; } // Render bullet at camera-relative position bullet.displayObject = bullet.displayObject || bullet; bullet.displayObject.x = bullet.x - cameraX; bullet.displayObject.y = bullet.y; } // --- Enemy Update & Collision --- // 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]; // 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) { // 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 // --- Hazard Update & Collision --- // (hazard removed) // --- 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; } // (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); LK.showYouWin("You reached the coffeehouse! You win!"); gameOver = true; return; } // Win condition: player reaches the last platform 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 --- function startGame() { score = 0; distance = 0; gameOver = false; playerLives = 3; scoreTxt.setText(score); distTxt.setText(distance + "m"); // 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) cameraX = 0; moveDir = 0; enemyStartDelay = 180; // 3 seconds at 60fps } // --- Start --- startGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// 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: flies from right to left, tries to hit the player
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyAsset = self.attachAsset('hazard', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = enemyAsset.width;
self.height = enemyAsset.height;
self.vx = -8 - Math.random() * 4; // Move left, much slower speed
self.lastX = 0;
self.lastWasIntersecting = false;
self.update = function () {
self.lastX = self.x;
self.x += self.vx;
};
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)
var playerAsset = self.attachAsset('playerBox', {
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;
// 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
****/
// New bullet figure asset (example: blue ellipse, unique id)
// Sun and cloud assets (example IDs, replace with real asset IDs as needed)
// --- Asset Initialization (shapes) ---
// Tween for animations (jump, enemy movement, etc)
// --- Game Variables ---
var GRAVITY = 2.2;
var JUMP_VELOCITY = -54;
var PLAYER_SPEED = 16;
var SCROLL_SPEED = 10;
var LEVEL_LENGTH = 950 * 149 + 600 + 500; // 150 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 cameraX = 0;
var score = 0;
var distance = 0;
var gameOver = false;
// --- GUI ---
// Hearts (5 total, left-aligned, with spacing)
var heartAssets = [];
var heartSpacing = 120;
var playerLives = 3; // Total lives/can
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
});
heart.x = 180 + i * heartSpacing; // Shifted 150px left from previous position
heart.y = 100;
LK.gui.top.addChild(heart);
heartAssets.push(heart);
}
updateHearts();
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFF700
});
scoreTxt.anchor.set(0.5, 0);
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 = 110;
// --- 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);
// Platform layout: up/down, not fixed order, player can jump between them
var numPlatforms = 150;
var platSpacingX = 950; // Further increased horizontal spacing for much more space
var platMinY = 800; // Lowered min Y for more vertical play area
var platMaxY = 1900; // Raised max Y for more vertical play 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;
// Add start platform at the very beginning
var startPlat = new Platform();
startPlat.x = 100;
startPlat.y = 2000;
platforms.push(startPlat);
game.addChild(startPlat);
// Place a coin above the start platform
var startCoin = new Coin();
startCoin.x = startPlat.x + startPlat.width / 2;
startCoin.y = startPlat.y - 80;
coins.push(startCoin);
game.addChild(startCoin);
for (var i = 0; i < numPlatforms; i++) {
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);
// Store checkpoint objects in an array for respawn logic
if (typeof checkpoints === "undefined") checkpoints = [];
checkpoints.push(checkpoint);
}
}
// Add coffee house on the last platform
if (platforms.length > 0) {
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 = 2200;
}
player.vx = 0;
player.vy = 0;
player.isOnGround = false;
game.addChild(player);
}
// --- 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;
}
// (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 ---
// Touch controls: tap anywhere to jump, hold left/right for movement
var moveDir = 0; // -1 = left, 1 = right, 0 = none
game.down = function (x, y, obj) {
if (gameOver) return;
// Convert to game coordinates
var gx = x + cameraX;
// Always allow jump on tap down, anywhere
if (player.isOnGround) {
player.jumpRequested = true;
}
// Hold left/right for movement
if (x < 2048 / 2) {
moveDir = -1;
} else {
moveDir = 1;
// Fire a bullet only if the previous tap was an "armed" tap (require two separate taps to fire)
if (typeof fireArmed === "undefined") fireArmed = false;
if (!fireArmed) {
// First tap: arm for firing
fireArmed = true;
} else {
// Second tap: actually fire bullet
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;
fireArmed = false; // Reset arming
}
}
};
game.up = function (x, y, obj) {
moveDir = 0;
// Release bullet control on touch up
if (game.controlledBullet && game.controlledBullet.isControlled) {
game.controlledBullet.isControlled = false;
game.controlledBullet = null;
}
};
game.move = function (x, y, obj) {
// Allow drag to change direction
if (x < 2048 / 2) {
moveDir = -1;
} else {
moveDir = 1;
}
// If a controlled bullet exists, update its velocity based on drag direction
if (game.controlledBullet && game.controlledBullet.isControlled) {
// Calculate direction from bullet to current pointer
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 () {
if (gameOver) return;
// --- Player Movement ---
// Horizontal movement
player.vx = moveDir * PLAYER_SPEED;
// Apply gravity
player.vy += GRAVITY;
// Jump
if (player.jumpRequested) {
player.vy = JUMP_VELOCITY;
player.jumpRequested = false;
player.isOnGround = 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;
} else if (player.vy < 0) {
// Hitting head
player.y = plat.y + plat.height + player.height;
player.vy = 0;
}
collidedY = true;
}
}
// --- 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 {
// Otherwise, it's a coin, increase score
score += 1;
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 ---
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
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;
}
// Render bullet at camera-relative position
bullet.displayObject = bullet.displayObject || bullet;
bullet.displayObject.x = bullet.x - cameraX;
bullet.displayObject.y = bullet.y;
}
// --- Enemy Update & Collision ---
// 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];
// 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) {
// 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
// --- Hazard Update & Collision ---
// (hazard removed)
// --- 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;
}
// (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);
LK.showYouWin("You reached the coffeehouse! You win!");
gameOver = true;
return;
}
// Win condition: player reaches the last platform
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 ---
function startGame() {
score = 0;
distance = 0;
gameOver = false;
playerLives = 3;
scoreTxt.setText(score);
distTxt.setText(distance + "m");
// 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)
cameraX = 0;
moveDir = 0;
enemyStartDelay = 180; // 3 seconds at 60fps
}
// --- Start ---
startGame();
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