User prompt
admin bölümlerini kaldır
User prompt
Please update the code so that a custom background image named 'basket' from the assets is used instead of the default background color. Add the following code block at the beginning of the initializeLevel(levelNum) function: js Kopyala Düzenle if (backgroundImage && backgroundImage.parent) { backgroundImage.destroy(); } backgroundImage = LK.getAsset('basket', { anchorX: 0.5, anchorY: 0.5, scaleX: 2048 / 1024, scaleY: 2732 / 1024 }); backgroundImage.x = 1024; backgroundImage.y = 1366; game.addChildAt(backgroundImage, 0); This should place the 'basket' image as a fullscreen background behind all game elements for every level.
User prompt
In my basketball game code, I want to customize level 21 as follows: Make the basketball completely invisible during level 21 (including its shadow). Set the basketball's starting position to x: 1800, y: 2300. Set the hoop's vertical movement speed to 20 during level 21. Please provide the correct code to implement these changes inside my initializeLevel() function and elsewhere if necessary.
Code edit (1 edits merged)
Please save this source code
User prompt
In my basketball game code, I made the hoop invisible for level 20 by setting hoop.rim.alpha, hoop.backboard.alpha, and hoop.supportLine.alpha to 0. I also loop through hoop.netSegments to set their alpha to 0. However, there's still a small black element visible under the hoop on level 20. I believe it's either the rimBracket or wallBracket, but I'm not sure which one or how to hide it. Please provide me with the correct code to make all visible parts of the hoop completely invisible during level 20, including any forgotten brackets or support pieces.
User prompt
son promtu geri al
User prompt
In my game code, I want the background color to be set to black (0x000000) only when Level 20 is initialized. Please do the following inside the initializeLevel(levelNum) function: Add a check: if levelNum === 20, then set game.backgroundColor = 0x000000. For all other levels, keep the default background color (e.g., 0x2F4F4F). The background color should update dynamically when Level 20 starts."
User prompt
In my game code, I want to make the hoop and all wall objects invisible only on Level 20, while keeping their positions and behaviors (movement and collisions) fully functional. Please do the following inside the initializeLevel(levelNum) function, specifically when levelNum === 20: Set alpha = 0 for all wall objects created in Level 20. Set alpha = 0 for the following parts of the hoop object: rim, backboard, and supportLine Each element in the netSegments array Do not modify their movement, physics, or positioning—only make them invisible. This change should only apply to Level 20."
User prompt
son promtu geri al
User prompt
Level 20 de wallslar ve pota görünmez olsun arka planla aynı renk ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
son promtu geri al
User prompt
level 20 top dışında herşey oyuncudan görünmez olsun
Code edit (5 edits merged)
Please save this source code
User prompt
Update the fireball spawning logic in the initializeLevel(levelNum) function: Add a global variable at the top of the code: var fireballTimer = null; At the beginning of initializeLevel, add this to stop previous timers: js Kopyala Düzenle if (fireballTimer !== null) { clearInterval(fireballTimer); fireballTimer = null; } Inside initializeLevel, change the fireball spawn condition from: js Kopyala Düzenle if (levelNum >= 19) { fireballTimer = LK.setInterval(function () { ... }, 1000); } to: js Kopyala Düzenle if (levelNum === 19) { fireballTimer = LK.setInterval(function () { var fireball = game.addChild(new Fireball()); fireball.x = 1024; fireball.y = 2200; var directions = [ {x: -2, y: -2}, {x: 2, y: -2}, {x: -2, y: 2}, {x: 2, y: 2} ]; var direction = directions[Math.floor(Math.random() * directions.length)]; fireball.velocityX = direction.x; fireball.velocityY = direction.y; fireballs.push(fireball); }, 1000); } ✅ This ensures fireballs only spawn on Level 19 and don’t continue in other levels. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
son 3 promtu geri al
User prompt
alev toplarını kaldır x:1024 y:2200 deki sadece level 19 da kalın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
diğer levellardan kaldır sadece level 19 dan onra olsun alev topları
User prompt
level 19 da x:1024 y: 2200 e sürekli çapraz şekilde alev topu atan bir ederha ekle alev topları duvarlardan sekebilsin yok olmasın her 1 sn de 1 alev topu atsın hareket hızları 2 olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
level 18 de walls yukarı asağı hareket yapsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Backboard = Container.expand(function () { var self = Container.call(this); var pole = self.attachAsset('backboardPole', { anchorX: 0.5, anchorY: 1 }); pole.x = 0; pole.y = 0; var board = self.attachAsset('backboard', { anchorX: 0.5, anchorY: 1 }); board.x = 0; board.y = -50; return self; }); var Basketball = Container.expand(function () { var self = Container.call(this); var ball = self.attachAsset('basketball', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.isLaunched = false; self.gravity = 0.3; self.bounceDecay = 0.8; self.startX = 0; self.startY = 0; self.reset = function () { self.x = self.startX; self.y = self.startY; self.velocityX = 0; self.velocityY = 0; self.isLaunched = false; // Update shadow position if it exists if (self.shadow) { self.shadow.x = self.x; self.shadow.y = self.y + 90; } }; self.launch = function (forceX, forceY) { self.velocityX = forceX; self.velocityY = forceY; self.isLaunched = true; LK.getSound('launch').play(); }; self.update = function () { // Handle vertical movement when not launched (level 5) if (!self.isLaunched && self.isMovingVertically) { self.y += self.moveSpeed * self.moveDirection; if (self.y <= self.minY || self.y >= self.maxY) { self.moveDirection *= -1; } // Update shadow position during movement if (self.shadow) { self.shadow.y = self.y + 90; } // Update start position for reset self.startY = self.y; } // Handle horizontal movement when not launched (level 11) if (!self.isLaunched && self.isMovingHorizontally) { self.x += self.moveSpeed * self.moveDirection; if (self.x <= self.minX || self.x >= self.maxX) { self.moveDirection *= -1; } // Update shadow position during movement if (self.shadow) { self.shadow.x = self.x; } // Update start position for reset self.startX = self.x; } if (self.isLaunched) { self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; // Realistic physics for all four screen edges var ballRadius = 80; // Half of basketball width/height var energyLoss = 0.85; // Energy retained after bounce (realistic friction) var minVelocity = 0.5; // Minimum velocity to prevent infinite micro-bounces // Left wall collision if (self.x <= ballRadius) { self.x = ballRadius; if (self.velocityX < 0) { // Only bounce if moving toward wall self.velocityX = -self.velocityX * energyLoss; self.velocityY = self.velocityY * energyLoss; // Slight energy loss on Y too if (Math.abs(self.velocityX) < minVelocity) { self.velocityX = 0; } LK.getSound('bounce').play(); // Track left wall bounce for level 10 objective if (leftWallBounceRequired && !leftWallBounced) { leftWallBounced = true; } } } // Right wall collision if (self.x >= 2048 - ballRadius) { self.x = 2048 - ballRadius; if (self.velocityX > 0) { // Only bounce if moving toward wall self.velocityX = -self.velocityX * energyLoss; self.velocityY = self.velocityY * energyLoss; // Slight energy loss on Y too if (Math.abs(self.velocityX) < minVelocity) { self.velocityX = 0; } LK.getSound('bounce').play(); } } // Top wall collision if (self.y <= ballRadius) { self.y = ballRadius; if (self.velocityY < 0) { // Only bounce if moving toward wall self.velocityY = -self.velocityY * energyLoss; self.velocityX = self.velocityX * energyLoss; // Slight energy loss on X too if (Math.abs(self.velocityY) < minVelocity) { self.velocityY = 0; } LK.getSound('bounce').play(); } } // Bottom wall collision if (self.y >= 2732 - ballRadius) { self.y = 2732 - ballRadius; if (self.velocityY > 0) { // Only bounce if moving toward wall self.velocityY = -self.velocityY * energyLoss; self.velocityX = self.velocityX * energyLoss; // Slight energy loss on X too if (Math.abs(self.velocityY) < minVelocity) { self.velocityY = 0; } LK.getSound('bounce').play(); } } } // Update shadow position if it exists if (self.shadow) { self.shadow.x = self.x; self.shadow.y = self.y + 90; } }; return self; }); var Fireball = Container.expand(function () { var self = Container.call(this); var fireballGraphics = self.attachAsset('spike', { anchorX: 0.5, anchorY: 0.5, tint: 0xFF4500 }); self.velocityX = 0; self.velocityY = 0; self.speed = 2; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; // Bounce off screen edges if (self.x <= 20) { self.x = 20; self.velocityX = -self.velocityX; } if (self.x >= 2028) { self.x = 2028; self.velocityX = -self.velocityX; } if (self.y <= 20) { self.y = 20; self.velocityY = -self.velocityY; } if (self.y >= 2712) { self.y = 2712; self.velocityY = -self.velocityY; } // Bounce off walls walls.forEach(function (wall) { if (self.intersects(wall)) { var ballCenterX = self.x; var ballCenterY = self.y; var wallCenterX = wall.x; var wallCenterY = wall.y; var wallWidth = wall.width * wall.scaleX; var wallHeight = wall.height * wall.scaleY; var overlapX = Math.abs(ballCenterX - wallCenterX) - (20 + wallWidth / 2); var overlapY = Math.abs(ballCenterY - wallCenterY) - (20 + wallHeight / 2); if (overlapX < overlapY) { self.velocityX = -self.velocityX; self.x += ballCenterX < wallCenterX ? -5 : 5; } else { self.velocityY = -self.velocityY; self.y += ballCenterY < wallCenterY ? -5 : 5; } } }); }; return self; }); var Hoop = Container.expand(function () { var self = Container.call(this); // Create backboard as slim vertical bar (only thickness visible) - flush mounted to wall var backboard = self.attachAsset('wall', { anchorX: 1.0, // Right edge anchor for wall attachment anchorY: 0.5, scaleX: 0.2, // Slightly thicker for better visibility scaleY: 2.8, // Much taller backboard extending well above rim tint: 0xFFFFFF }); backboard.x = 0; // Completely flush with wall position (no gap) backboard.y = -80; // Positioned higher so it extends above rim // Create support bracket connecting backboard to wall var wallBracket = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.2, tint: 0x808080 }); wallBracket.x = 12; // Closer to wall for flush mounting wallBracket.y = -50; // Create horizontal rim extending toward left (side view) - made extra wide var rim = self.attachAsset('hoop', { anchorX: 1.0, // Right edge anchored to backboard anchorY: 0.5, scaleX: 2.4, // Extended horizontally toward player - extra wide for very forgiving scoring scaleY: 0.2, // Thin rim profile from side tint: 0xFF4500 }); rim.x = -2; // Closer to backboard for flush mounting rim.y = -80; // Create rim support bracket var rimBracket = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.15, tint: 0x808080 }); rimBracket.x = -35; // Adjusted for better alignment rimBracket.y = -70; // Create vertical backboard support line behind the rim - taller and thicker var supportLine = self.attachAsset('backboardSupport', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, // Thicker for more visual solidity scaleY: 2.0, // Taller extending well above rim tint: 0xC0C0C0, alpha: 0.9 }); supportLine.x = -8; // Closer to backboard for flush mounting supportLine.y = -130; // Positioned much higher above the rim, never dipping below // Create realistic side-view net hanging from rim - positioned to hang naturally below var netSegments = []; for (var i = 0; i < 8; i++) { var netSegment = self.attachAsset('netSegment', { anchorX: 0.5, anchorY: 0, scaleX: 0.8 - i * 0.06, // Tapers as it hangs down scaleY: 1.0, tint: 0xFFFFFF, alpha: 0.7 }); netSegment.x = -140 + i * 10; // Spread across rim width netSegment.y = -60 + i * 12; // Hangs lower below rim with more natural drape netSegments.push(netSegment); } // Store references for animations self.netSegments = netSegments; self.rim = rim; self.backboard = backboard; self.supportLine = supportLine; // Physics collision zones for realistic ball interaction - ultra forgiving self.rimCollisionZone = { x: -110, // Extends even further left from backboard y: -80, width: 320, // Ultra wide rim width for maximum forgiving scoring height: 50 // Extra thick rim height for easiest scoring }; self.backboardCollisionZone = { x: 0, // At wall position - completely flush y: -80, // Positioned higher to match visual backboard width: 40, // Thicker to match visual appearance height: 420 // Much taller backboard height matching visual }; // Vertical support line collision zone for soft redirection self.supportLineCollisionZone = { x: -8, // Closer to backboard for flush mounting y: -130, // Positioned higher above rim width: 12, // Thicker support line width height: 240 // Taller support line height extending well above rim }; self.isMoving = false; self.moveSpeed = 2; self.moveDirection = 1; self.minX = 1700; self.maxX = 1900; self.minY = 200; self.maxY = 2000; self.moveHorizontal = true; self.update = function () { if (self.isMoving) { if (self.moveHorizontal) { self.x += self.moveSpeed * self.moveDirection; if (self.x <= self.minX || self.x >= self.maxX) { self.moveDirection *= -1; } } else { self.y += self.moveSpeed * self.moveDirection; if (self.y <= self.minY || self.y >= self.maxY) { self.moveDirection *= -1; } } } }; return self; }); var RotatingBlock = Container.expand(function () { var self = Container.call(this); var blockGraphics = self.attachAsset('rotatingBlock', { anchorX: 0.5, anchorY: 0.5 }); self.rotationSpeed = 0.05; self.update = function () { blockGraphics.rotation += self.rotationSpeed; // Add horizontal movement for level 16 if (self.isMovingHorizontally) { self.x += self.moveSpeed * self.moveDirection; if (self.x <= self.minX || self.x >= self.maxX) { self.moveDirection *= -1; } } }; return self; }); var Spike = Container.expand(function () { var self = Container.call(this); var spikeGraphics = self.attachAsset('spike', { anchorX: 0.5, anchorY: 0.5 }); self.isMoving = false; self.moveSpeed = 8; // Fast movement speed self.moveDirection = 1; self.minY = 200; self.maxY = 2000; self.minX = 200; self.maxX = 2000; self.update = function () { if (self.isMoving) { // Check if horizontal movement is enabled (has minX/maxX set differently from defaults) if (self.minX !== 200 || self.maxX !== 2000) { // Horizontal movement self.x += self.moveSpeed * self.moveDirection; if (self.x <= self.minX || self.x >= self.maxX) { self.moveDirection *= -1; } } else { // Vertical movement (default) self.y += self.moveSpeed * self.moveDirection; if (self.y <= self.minY || self.y >= self.maxY) { self.moveDirection *= -1; } } } }; return self; }); var TrajectoryDot = Container.expand(function () { var self = Container.call(this); var dot = self.attachAsset('trajectory', { anchorX: 0.5, anchorY: 0.5 }); dot.alpha = 0.6; return self; }); var Wall = Container.expand(function () { var self = Container.call(this); var wallGraphics = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); self.isMoving = false; self.moveSpeed = 2; self.moveDirection = 1; self.minY = 200; self.maxY = 2000; self.update = function () { if (self.isMoving) { self.y += self.moveSpeed * self.moveDirection; if (self.y <= self.minY || self.y >= self.maxY) { self.moveDirection *= -1; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2F4F4F }); /**** * Game Code ****/ // Game state var currentLevel = storage.currentLevel || 1; var maxLevel = storage.maxLevel || 1; var gameState = 'playing'; // playing, levelComplete, gameOver var attempts = 0; var maxAttempts = 0; var scored = false; var levelGoal = ''; // Objective tracking var wallBounces = 0; var requiredBounces = 0; var touchedWall = false; var leftWallBounced = false; var leftWallBounceRequired = false; var touchedNonLeftWall = false; var objectiveFailed = false; var failureReason = ''; // Timer challenge system var ballReleaseTime = 0; var timerChallenge = false; var timerCountdown = 0; var inputDisabled = false; var timerCountdownText = null; // Global 3-second timer for all levels var globalTimerActive = false; var globalTimerStartTime = 0; // Game objects var basketball = null; var hoop = null; var walls = []; var spikes = []; var rotatingBlocks = []; var trajectoryDots = []; var fireballs = []; // Input tracking var isDragging = false; var dragStartX = 0; var dragStartY = 0; // Helper function to generate random positions for obstacles function getRandomPosition() { return { x: Math.random() * 1200 + 300, // Random x between 300 and 1500 y: Math.random() * 1000 + 800 // Random y between 800 and 1800 }; } // Level definitions var levels = [ // Level 1-4: Basic shots { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Make your first shot!', objective: 'score', // Just score walls: [], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 800, goal: 'Higher target challenge!', objective: 'score', // Just score walls: [], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 800, goal: 'Straight shot challenge!', objective: 'no_wall', // Don't touch any wall walls: [], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Bounce off one wall to score!', objective: 'bounce_once', // Must bounce off exactly one wall walls: [], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, // Level 5-10: Bank shots and obstacles { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Bounce off one wall!', objective: 'bounce_once', // Must bounce off exactly one wall walls: [], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Avoid the spikes!', objective: 'no_wall', // Don't touch any wall (spikes auto-fail) walls: [], spikes: [{ x: 1550, y: 1100 }], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Navigate the rotating block!', objective: 'score', // Just score while avoiding blocks walls: [], spikes: [], rotatingBlocks: [{ x: 1700, y: 1050 }], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Avoid walls challenge!', objective: 'no_wall', // Don't touch any wall walls: [{}, { x: 1700, y: 1100, width: 30, height: 200 }], spikes: [], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Precision bank shot!', walls: [{ x: 1600, y: 800, width: 400, height: 30 }], spikes: [{ x: 1650, y: 1200 }], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Precision bank shot!', walls: [{ x: 1600, y: 800, width: 400, height: 30 }], spikes: [{ x: 1650, y: 1200 }], rotatingBlocks: [], movingHoop: false, maxAttempts: 0 }, // Level 11-19: Moving hoops and restrictions { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Hit the moving hoop!', walls: [], spikes: [], rotatingBlocks: [], movingHoop: true, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Moving target with walls!', walls: [{ x: 1700, y: 1000, width: 30, height: 300 }], spikes: [], rotatingBlocks: [], movingHoop: true, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'One shot only!', walls: [], spikes: [{ x: 1800, y: 1200 }], rotatingBlocks: [], movingHoop: false, maxAttempts: 1 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Moving hoop precision!', walls: [{ x: 1600, y: 1000, width: 200, height: 30 }], spikes: [{ x: 1750, y: 1150 }], rotatingBlocks: [], movingHoop: true, maxAttempts: 3 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Vertical moving hoop!', walls: [{ x: 1600, y: 600, width: 30, height: 400 }, { x: 1800, y: 1100, width: 30, height: 400 }], spikes: [], rotatingBlocks: [], movingHoop: true, maxAttempts: 0 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Ultimate obstacle course!', walls: [{ x: 1700, y: 1000, width: 30, height: 200 }, { x: 1800, y: 800, width: 200, height: 30 }], spikes: [{ x: 1650, y: 1200 }, { x: 1850, y: 950 }], rotatingBlocks: [{ x: 1750, y: 1100 }], movingHoop: false, maxAttempts: 2 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Moving maze challenge!', walls: [{ x: 1650, y: 350, width: 30, height: 300 }, { x: 1850, y: 1000, width: 30, height: 300 }], spikes: [{ x: 1700, y: 1150 }, { x: 1800, y: 1050 }], rotatingBlocks: [{ x: 1750, y: 1200 }], movingHoop: true, maxAttempts: 3 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Dont Touch Anywhere', objective: 'bounce_twice', walls: [{ x: 1700, y: 800, width: 30, height: 600 }, { x: 1800, y: 900, width: 30, height: 600 }], spikes: [{ x: 1650, y: 170 }, { x: 1850, y: 1200 }], rotatingBlocks: [], movingHoop: false, maxAttempts: 3 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Complex moving target!', walls: [{ x: 1600, y: 900, width: 200, height: 30 }, { x: 1700, y: 1100, width: 200, height: 30 }], spikes: [{ x: 1750, y: 1200 }, { x: 1800, y: 1000 }], rotatingBlocks: [{ x: 1850, y: 1050 }], movingHoop: true, maxAttempts: 2 }, // Level 20: Ultimate challenge { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Ultimate Basket Challenge!', walls: [{ x: 1600, y: 800, width: 30, height: 400 }, { x: 1700, y: 1000, width: 200, height: 30 }, { x: 1750, y: 900, width: 200, height: 30 }, { x: 1850, y: 1100, width: 30, height: 400 }], spikes: [{ x: 1650, y: 1200 }, { x: 1750, y: 1050 }, { x: 1800, y: 1250 }], rotatingBlocks: [{ x: 1700, y: 1100 }, { x: 1850, y: 950 }], movingHoop: true, maxAttempts: 1 }, { ballX: 1024, ballY: 1366, hoopX: 1024, hoopY: 1366, goal: 'Moving blocks and walls!', walls: [{ x: 1800, y: 800, width: 30, height: 200 }], spikes: [], rotatingBlocks: [{ x: 1600, y: 1000 }, { x: 1700, y: 1200 }], movingHoop: false, maxAttempts: 0 }]; // UI elements var levelText = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); var goalText = new Text2('', { size: 40, fill: 0xFFFF00 }); goalText.anchor.set(0.5, 0); goalText.y = 80; LK.gui.top.addChild(goalText); var attemptsText = new Text2('', { size: 35, fill: 0xFFFFFF }); attemptsText.anchor.set(1, 0); LK.gui.topRight.addChild(attemptsText); // Timer countdown text timerCountdownText = new Text2('', { size: 80, fill: 0xFF0000 }); timerCountdownText.anchor.set(0.5, 0.5); LK.gui.center.addChild(timerCountdownText); timerCountdownText.visible = false; // Next Level button var nextLevelButton = new Text2('Next Level →', { size: 60, fill: 0x00FF00 }); nextLevelButton.anchor.set(0.5, 0.5); nextLevelButton.x = 1024; nextLevelButton.y = 2200; nextLevelButton.visible = false; game.addChild(nextLevelButton); // Add button click functionality nextLevelButton.down = function (x, y, obj) { if (nextLevelButton.visible && gameState === 'levelComplete') { // Hide button nextLevelButton.visible = false; // Proceed to next level if (currentLevel < levels.length) { currentLevel++; if (currentLevel > maxLevel) { maxLevel = currentLevel; storage.maxLevel = maxLevel; } storage.currentLevel = currentLevel; initializeLevel(currentLevel); } else { LK.showYouWin(); } } }; // Admin Next Level button for testing var adminNextButton = new Text2('ADMIN: Next →', { size: 40, fill: 0xFF00FF }); adminNextButton.anchor.set(1, 0); adminNextButton.x = -20; adminNextButton.y = 120; adminNextButton.visible = true; LK.gui.topRight.addChild(adminNextButton); // Admin Previous Level button for testing var adminPrevButton = new Text2('ADMIN: ← Prev', { size: 40, fill: 0xFF00FF }); adminPrevButton.anchor.set(1, 0); adminPrevButton.x = -20; adminPrevButton.y = 170; adminPrevButton.visible = true; LK.gui.topRight.addChild(adminPrevButton); // Admin next button click functionality adminNextButton.down = function (x, y, obj) { // Always allow advancing to next level for testing if (currentLevel < levels.length) { currentLevel++; if (currentLevel > maxLevel) { maxLevel = currentLevel; storage.maxLevel = maxLevel; } storage.currentLevel = currentLevel; initializeLevel(currentLevel); } else { // Reset to level 1 if at the end currentLevel = 1; storage.currentLevel = 1; initializeLevel(currentLevel); } }; // Admin previous button click functionality adminPrevButton.down = function (x, y, obj) { // Always allow going back to previous level for testing if (currentLevel > 1) { currentLevel--; storage.currentLevel = currentLevel; initializeLevel(currentLevel); } else { // Go to last level if at the beginning currentLevel = levels.length; storage.currentLevel = currentLevel; initializeLevel(currentLevel); } }; function initializeLevel(levelNum) { if (levelNum > levels.length || levelNum < 1) { return; } // Clear existing objects if (basketball) { if (basketball.shadow) { basketball.shadow.destroy(); } basketball.destroy(); } if (hoop) { hoop.destroy(); } walls.forEach(function (wall) { wall.destroy(); }); spikes.forEach(function (spike) { spike.destroy(); }); rotatingBlocks.forEach(function (block) { block.destroy(); }); trajectoryDots.forEach(function (dot) { dot.destroy(); }); fireballs.forEach(function (fireball) { fireball.destroy(); }); walls = []; spikes = []; rotatingBlocks = []; trajectoryDots = []; fireballs = []; var level = levels[levelNum - 1]; // Create basketball basketball = game.addChild(new Basketball()); basketball.x = level.ballX; basketball.y = level.ballY; basketball.startX = level.ballX; basketball.startY = level.ballY; // Add vertical movement for level 5 and level 10 if (levelNum === 5 || levelNum === 10) { basketball.isMovingVertically = true; basketball.moveDirection = 1; basketball.moveSpeed = 8; basketball.minY = 1000; basketball.maxY = 1700; } // Add horizontal movement for level 6 if (levelNum === 6) { basketball.isMovingHorizontally = true; basketball.moveDirection = 1; basketball.moveSpeed = 12; basketball.minX = 800; basketball.maxX = 1300; } // Add horizontal movement for level 11 if (levelNum === 11) { basketball.isMovingHorizontally = true; basketball.moveDirection = 1; basketball.moveSpeed = 12; // Increased horizontal movement speed basketball.minX = 800; basketball.maxX = 1300; // Add smooth acceleration using tween for extra visual impact tween(basketball, { scaleX: 1.1, scaleY: 0.9 }, { duration: 300, easing: tween.easeInOut }); } // Add shadow ring under basketball to indicate it's draggable var shadow = LK.getAsset('basketball', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 0.3, tint: 0x000000, alpha: 0.3 }); shadow.x = basketball.x; shadow.y = basketball.y + 90; // Position below ball game.addChild(shadow); basketball.shadow = shadow; // Create hoop hoop = game.addChild(new Hoop()); hoop.x = 2048; // Always position flush against rightmost wall hoop.y = level.hoopY; hoop.isMoving = level.movingHoop; // Configure movement for level 10 and levels after 10 if (levelNum >= 10) { hoop.isMoving = true; hoop.moveHorizontal = false; // Always vertical movement after level 10 hoop.minY = 300; hoop.maxY = 1500; // Gradually increase speed based on level var speedMultiplier = Math.max(1, (levelNum - 10) * 0.5); // Increase by 0.5 each level after 10 hoop.moveSpeed = 2 + speedMultiplier; } // Configure movement for level 15 if (levelNum >= 15) { hoop.isMoving = true; hoop.moveHorizontal = false; hoop.minY = 600; hoop.maxY = 1500; // Gradually increase speed based on level var speedMultiplier = Math.max(1, (levelNum - 10) * 0.5); // Increase by 0.5 each level after 10 hoop.moveSpeed = 6 + speedMultiplier; } // Configure vertical movement for level 17 (keeping original logic for specific level) if (levelNum === 17) { hoop.moveHorizontal = false; hoop.minY = 300; hoop.maxY = 1500; hoop.moveSpeed = 3; } // Create walls level.walls.forEach(function (wallData) { var wall = game.addChild(new Wall()); wall.x = wallData.x; wall.y = wallData.y; if (wallData.width) { wall.scaleX = wallData.width / 200; } if (wallData.height) { wall.scaleY = wallData.height / 30; } // Configure wall movement for level 9 if (levelNum === 9) { wall.isMoving = true; wall.moveSpeed = 12; // Fast vertical movement wall.moveDirection = 1; wall.minY = 500; wall.maxY = 1600; // Start walls at different phases for varied movement var wallIndex = walls.length; if (wallIndex % 2 === 1) { wall.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(wall, { y: wall.y + wall.moveDirection * 100 }, { duration: 1000, easing: tween.easeInOut }); } // Configure wall movement for level 10 if (levelNum === 10) { wall.isMoving = true; wall.moveSpeed = 9; // Fast vertical movement wall.moveDirection = 1; wall.minY = 500; wall.maxY = 1600; // Start walls at different phases for varied movement var wallIndex = walls.length; if (wallIndex % 2 === 1) { wall.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(wall, { y: wall.y + wall.moveDirection * 100 }, { duration: 1000, easing: tween.easeInOut }); } // Configure wall movement for level 14 if (levelNum === 14) { wall.isMoving = true; wall.moveSpeed = 4; // Same speed as hoop wall.moveDirection = 1; wall.minY = 300; wall.maxY = 1500; // Start walls at different phases for varied movement var wallIndex = walls.length; if (wallIndex % 2 === 1) { wall.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(wall, { y: wall.y + wall.moveDirection * 100 }, { duration: 1000, easing: tween.easeInOut }); } // Configure wall rotation for level 15 if (levelNum === 15 && wall.x === 1600 && wall.y === 600) { // Create continuous rotation around center point var _rotateWall = function rotateWall() { tween(wall, { rotation: wall.rotation + Math.PI * 2 // Full 360 degree rotation }, { duration: 3000, // 3 seconds per rotation easing: tween.linear, onFinish: function onFinish() { _rotateWall(); // Loop the rotation continuously } }); }; _rotateWall(); // Start the rotation } // Configure wall movement for level 16 if (levelNum === 16) { wall.isMoving = true; wall.moveSpeed = 9; wall.moveDirection = 1; wall.minY = 400; wall.maxY = 1200; // Use tween for smooth movement animation tween(wall, { y: wall.y + wall.moveDirection * 100 }, { duration: 500, easing: tween.easeInOut }); } // Configure wall rotation for level 17 if (levelNum === 17) { // Create continuous rotation around center point var _rotateWall2 = function rotateWall() { tween(wall, { rotation: wall.rotation + Math.PI * 2 // Full 360 degree rotation }, { duration: 3000, // 3 seconds per rotation easing: tween.linear, onFinish: function onFinish() { _rotateWall2(); // Loop the rotation continuously } }); }; _rotateWall2(); // Start the rotation } // Configure wall movement for level 18 if (levelNum === 18) { wall.isMoving = true; wall.moveSpeed = 10; // Fast vertical movement wall.moveDirection = 1; wall.minY = 810; wall.maxY = 900; // Start walls at different phases for varied movement var wallIndex = walls.length; if (wallIndex % 2 === 1) { wall.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(wall, { y: wall.y + wall.moveDirection * 100 }, { duration: 800, easing: tween.easeInOut }); } walls.push(wall); }); // Create spikes level.spikes.forEach(function (spikeData) { // Skip static spike creation for level 14 if (levelNum === 14) { return; // Don't create static spikes for level 14 } var spike = game.addChild(new Spike()); spike.x = spikeData.x; spike.y = spikeData.y; // Configure spike movement for level 13 if (levelNum === 13) { spike.isMoving = true; spike.moveSpeed = 8; // Fast vertical movement spike.moveDirection = 1; spike.minY = 200; spike.maxY = 1600; // Start spikes at different phases for varied movement var spikeIndex = spikes.length; if (spikeIndex % 2 === 1) { spike.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(spike, { y: spike.y + spike.moveDirection * 100 }, { duration: 500, easing: tween.easeInOut }); } spikes.push(spike); }); level.spikes.forEach(function (spikeData) { var spike = game.addChild(new Spike()); spike.x = spikeData.x; spike.y = spikeData.y; // Configure spike movement for level 14 if (levelNum === 14) { spike.isMoving = true; spike.moveSpeed = 6; // Fast horizontal movement spike.moveDirection = 1; spike.minX = 200; spike.maxX = 2000; // Start spikes at different phases for varied movement var spikeIndex = spikes.length; if (spikeIndex % 2 === 1) { spike.moveDirection = -1; // Alternate initial direction } // Use tween for smooth movement animation tween(spike, { x: spike.x + spike.moveDirection * 50 }, { duration: 500, easing: tween.easeInOut }); } spikes.push(spike); }); // Add 3 additional moving spikes for level 13 if (levelNum === 13) { // Additional spike 1 var extraSpike1 = game.addChild(new Spike()); extraSpike1.x = 1400; extraSpike1.y = 900; extraSpike1.isMoving = true; extraSpike1.moveSpeed = 8; extraSpike1.moveDirection = -1; extraSpike1.minY = 200; extraSpike1.maxY = 2000; tween(extraSpike1, { y: extraSpike1.y + extraSpike1.moveDirection * 100 }, { duration: 500, easing: tween.easeInOut }); spikes.push(extraSpike1); // Additional spike 2 var extraSpike2 = game.addChild(new Spike()); extraSpike2.x = 1600; extraSpike2.y = 1300; extraSpike2.isMoving = true; extraSpike2.moveSpeed = 8; extraSpike2.moveDirection = 1; extraSpike2.minY = 200; extraSpike2.maxY = 2000; tween(extraSpike2, { y: extraSpike2.y + extraSpike2.moveDirection * 100 }, { duration: 500, easing: tween.easeInOut }); spikes.push(extraSpike2); // Additional spike 3 var extraSpike3 = game.addChild(new Spike()); extraSpike3.x = 1900; extraSpike3.y = 700; extraSpike3.isMoving = true; extraSpike3.moveSpeed = 8; extraSpike3.moveDirection = -1; extraSpike3.minY = 200; extraSpike3.maxY = 2000; tween(extraSpike3, { y: extraSpike3.y + extraSpike3.moveDirection * 100 }, { duration: 500, easing: tween.easeInOut }); spikes.push(extraSpike3); } // Create rotating blocks level.rotatingBlocks.forEach(function (blockData) { var block = game.addChild(new RotatingBlock()); block.x = blockData.x; block.y = blockData.y; // Configure horizontal movement for level 16 if (levelNum === 16) { block.isMovingHorizontally = true; block.moveSpeed = 6; block.moveDirection = 1; block.minX = 600; block.maxX = 1900; // Use tween for smooth movement animation tween(block, { x: block.x + block.moveDirection * 50 }, { duration: 1000, easing: tween.easeInOut }); } // Configure horizontal movement for level 17 if (levelNum === 17) { block.isMovingHorizontally = true; block.moveSpeed = 8; block.moveDirection = 1; block.minX = 600; block.maxX = 1900; // Use tween for smooth movement animation tween(block, { x: block.x + block.moveDirection * 50 }, { duration: 1000, easing: tween.easeInOut }); } rotatingBlocks.push(block); }); // Reset game state gameState = 'playing'; attempts = 0; maxAttempts = level.maxAttempts; scored = false; levelGoal = level.goal; // Reset objective tracking wallBounces = 0; requiredBounces = level.objective === 'bounce_once' ? 1 : level.objective === 'bounce_twice' ? 2 : 0; touchedWall = false; leftWallBounced = false; leftWallBounceRequired = levelNum === 10; touchedNonLeftWall = false; objectiveFailed = false; failureReason = ''; // Reset timer challenge variables timerChallenge = level.objective === 'timer_challenge'; ballReleaseTime = 0; timerCountdown = 0; inputDisabled = false; globalTimerActive = false; globalTimerStartTime = 0; if (timerCountdownText) { timerCountdownText.visible = false; } // Hide Next Level button if (nextLevelButton) { nextLevelButton.visible = false; } // Create fire launcher for level 19 only if (levelNum === 19) { var fireballTimer = LK.setInterval(function () { // Create fireball at launcher position var fireball = game.addChild(new Fireball()); fireball.x = 1024; fireball.y = 2200; // Set diagonal velocity (top-left, top-right, bottom-left, bottom-right) var directions = [{ x: -2, y: -2 }, // top-left { x: 2, y: -2 }, // top-right { x: -2, y: 2 }, // bottom-left { x: 2, y: 2 } // bottom-right ]; var direction = directions[Math.floor(Math.random() * directions.length)]; fireball.velocityX = direction.x; fireball.velocityY = direction.y; fireballs.push(fireball); }, 1000); // Every 1 second } // Update UI levelText.setText('Level ' + levelNum); goalText.setText(levelGoal); updateAttemptsText(); } function updateAttemptsText() { if (maxAttempts > 0) { attemptsText.setText('Attempts: ' + attempts + '/' + maxAttempts); } else { attemptsText.setText('Attempts: ' + attempts); } } function checkCollisions() { if (!basketball.isLaunched) { return; } // Check wall collisions (level walls) walls.forEach(function (wall) { if (basketball.intersects(wall)) { var ballCenterX = basketball.x; var ballCenterY = basketball.y; var wallCenterX = wall.x; var wallCenterY = wall.y; var wallWidth = wall.width * wall.scaleX; var wallHeight = wall.height * wall.scaleY; var overlapX = Math.abs(ballCenterX - wallCenterX) - (80 + wallWidth / 2); var overlapY = Math.abs(ballCenterY - wallCenterY) - (80 + wallHeight / 2); // Realistic physics collision with angle-based reflection // For level 9, use better bouncing physics with proper angle calculation var energyLoss = currentLevel === 9 ? 0.85 : 0.85; var minVelocity = 0.5; // Calculate collision normal for proper physics reflection var dx = ballCenterX - wallCenterX; var dy = ballCenterY - wallCenterY; var distance = Math.sqrt(dx * dx + dy * dy); if (currentLevel === 9 && distance > 0) { // Level 9: Use proper physics reflection based on collision angle var normalX = dx / distance; var normalY = dy / distance; // Calculate relative velocity var relativeVelocityX = basketball.velocityX; var relativeVelocityY = basketball.velocityY; // Calculate velocity component along normal var velocityAlongNormal = relativeVelocityX * normalX + relativeVelocityY * normalY; // Only reflect if moving toward the wall if (velocityAlongNormal < 0) { // Calculate reflection with proper physics basketball.velocityX = basketball.velocityX - 2 * velocityAlongNormal * normalX; basketball.velocityY = basketball.velocityY - 2 * velocityAlongNormal * normalY; // Apply energy loss basketball.velocityX *= energyLoss; basketball.velocityY *= energyLoss; // Separate ball from wall to prevent sticking var separation = 85; // Ball radius + small margin basketball.x = wallCenterX + normalX * separation; basketball.y = wallCenterY + normalY * separation; } } else { // Other levels: Use original collision logic if (overlapX < overlapY) { if (ballCenterX < wallCenterX && basketball.velocityX > 0 || ballCenterX > wallCenterX && basketball.velocityX < 0) { basketball.velocityX = -basketball.velocityX * energyLoss; basketball.velocityY = basketball.velocityY * energyLoss; // Apply energy loss to perpendicular component too if (Math.abs(basketball.velocityX) < minVelocity) { basketball.velocityX = 0; } } basketball.x += ballCenterX < wallCenterX ? -5 : 5; } else { if (ballCenterY < wallCenterY && basketball.velocityY > 0 || ballCenterY > wallCenterY && basketball.velocityY < 0) { basketball.velocityY = -basketball.velocityY * energyLoss; basketball.velocityX = basketball.velocityX * energyLoss; // Apply energy loss to perpendicular component too if (Math.abs(basketball.velocityY) < minVelocity) { basketball.velocityY = 0; } } basketball.y += ballCenterY < wallCenterY ? -5 : 5; } } LK.getSound('bounce').play(); // Track wall bounces and check objectives wallBounces++; touchedWall = true; // For level 10, check if touching non-left wall before left wall if (leftWallBounceRequired && !leftWallBounced) { touchedNonLeftWall = true; objectiveFailed = true; failureReason = 'You must hit the left wall first!'; } var level = levels[currentLevel - 1]; if (level.objective === 'no_wall') { objectiveFailed = true; failureReason = 'You touched the wall!'; } // For level 17, hitting any wall causes failure if (currentLevel === 17) { objectiveFailed = true; failureReason = 'You hit the wall!'; } } }); // Check spike collisions spikes.forEach(function (spike) { if (basketball.intersects(spike)) { objectiveFailed = true; failureReason = 'You hit the spikes!'; } }); // Check fireball collisions fireballs.forEach(function (fireball) { if (basketball.intersects(fireball)) { objectiveFailed = true; failureReason = 'You hit the fireball!'; } }); // Check rotating block collisions rotatingBlocks.forEach(function (block) { if (basketball.intersects(block)) { var ballCenterX = basketball.x; var ballCenterY = basketball.y; var blockCenterX = block.x; var blockCenterY = block.y; var overlapX = Math.abs(ballCenterX - blockCenterX) - 120; var overlapY = Math.abs(ballCenterY - blockCenterY) - 120; if (overlapX < overlapY) { basketball.velocityX = -basketball.velocityX * basketball.bounceDecay; basketball.x += ballCenterX < blockCenterX ? -5 : 5; } else { basketball.velocityY = -basketball.velocityY * basketball.bounceDecay; basketball.y += ballCenterY < blockCenterY ? -5 : 5; } LK.getSound('bounce').play(); } }); // Check backboard collision for realistic physics var ballCenterX = basketball.x; var ballCenterY = basketball.y; var hoopCenterX = hoop.x + hoop.backboardCollisionZone.x; var hoopCenterY = hoop.y + hoop.backboardCollisionZone.y; if (Math.abs(ballCenterX - hoopCenterX) < 80 + hoop.backboardCollisionZone.width / 2 && Math.abs(ballCenterY - hoopCenterY) < 80 + hoop.backboardCollisionZone.height / 2) { // Ball hit backboard basketball.velocityX = -basketball.velocityX * basketball.bounceDecay * 0.9; basketball.velocityY = basketball.velocityY * 0.95; basketball.x += basketball.velocityX > 0 ? -8 : 8; LK.getSound('bounce').play(); // Flash backboard LK.effects.flashObject(hoop, 0xFFFFFF, 200); } // Check vertical support line collision for soft redirection helping var supportLineCenterX = hoop.x + hoop.supportLineCollisionZone.x; var supportLineCenterY = hoop.y + hoop.supportLineCollisionZone.y; if (Math.abs(ballCenterX - supportLineCenterX) < 80 + hoop.supportLineCollisionZone.width / 2 && Math.abs(ballCenterY - supportLineCenterY) < 80 + hoop.supportLineCollisionZone.height / 2) { // Ball hit vertical support line - apply soft downward redirection instead of hard bounce var distanceFromRim = Math.abs(ballCenterY - (hoop.y + hoop.rimCollisionZone.y)); var redirectionStrength = Math.max(0.1, 1.0 - distanceFromRim / 80); // Stronger redirection when closer to rim // Gently redirect ball downward into the hoop if shot is close if (basketball.velocityX < 0) { // Ball moving toward hoop from right side var rimCenterX = hoop.x + hoop.rimCollisionZone.x; var rimCenterY = hoop.y + hoop.rimCollisionZone.y; var directionToRimX = rimCenterX - ballCenterX; var directionToRimY = rimCenterY - ballCenterY; // Apply gentle redirection toward rim center basketball.velocityX += directionToRimX * 0.003 * redirectionStrength; basketball.velocityY += Math.abs(directionToRimY) * 0.002 * redirectionStrength; // Gentle downward push // Reduce horizontal velocity to prevent harsh deflection basketball.velocityX *= 0.85; // Small position adjustment to prevent getting stuck basketball.x -= 3; // Subtle flash effect for support line hit LK.effects.flashObject(hoop.supportLine, 0xFFFFAA, 150); } } // Check rim collision for realistic bouncing - extra forgiving scoring zone var rimCenterX = hoop.x + hoop.rimCollisionZone.x; var rimCenterY = hoop.y + hoop.rimCollisionZone.y; if (Math.abs(ballCenterX - rimCenterX) < 80 + hoop.rimCollisionZone.width / 2 && Math.abs(ballCenterY - rimCenterY) < 80 + hoop.rimCollisionZone.height / 2) { // Check if ball is going through the hoop (scoring) - ultra wide scoring zone with auto-absorption var scoringZoneWidth = 140; // Even wider invisible scoring zone for maximum forgiveness var scoringZoneHeight = 40; // Taller scoring zone for easier front rim entry var autoAbsorptionZone = 80; // Larger zone where ball gets gently pulled toward center // Auto-absorption: if ball is close to center, gently guide it inward var distanceFromCenterX = Math.abs(ballCenterX - rimCenterX); var distanceFromCenterY = Math.abs(ballCenterY - rimCenterY); if (distanceFromCenterX < autoAbsorptionZone && distanceFromCenterY < autoAbsorptionZone && basketball.velocityY > 0) { // Gently pull ball toward center for easier scoring var pullStrength = 0.15; // Subtle pull force if (ballCenterX < rimCenterX) { basketball.velocityX += pullStrength; } else if (ballCenterX > rimCenterX) { basketball.velocityX -= pullStrength; } } if (basketball.velocityY > 0 && ballCenterX > rimCenterX - scoringZoneWidth && ballCenterX < rimCenterX + scoringZoneWidth && ballCenterY > rimCenterY - scoringZoneHeight && ballCenterY < rimCenterY + scoringZoneHeight && ballCenterY < rimCenterY) { // Check if objective was met before scoring var level = levels[currentLevel - 1]; var objectiveMet = true; var objectiveFailureMessage = ''; if (leftWallBounceRequired && !leftWallBounced) { objectiveMet = false; objectiveFailureMessage = 'You must hit the left wall first!'; } else if (level.objective === 'bounce_once' && wallBounces !== 1) { objectiveMet = false; objectiveFailureMessage = wallBounces === 0 ? 'You must bounce off one wall!' : 'You bounced too many times!'; } else if (level.objective === 'bounce_twice' && wallBounces !== 2) { objectiveMet = false; objectiveFailureMessage = wallBounces === 0 ? 'You must bounce off two walls!' : wallBounces === 1 ? 'You must bounce off one more wall!' : 'You bounced too many times!'; } else if (level.objective === 'no_wall' && touchedWall) { objectiveMet = false; objectiveFailureMessage = 'You were not supposed to touch any walls!'; } if (!objectiveMet) { // Objective failed LK.effects.flashScreen(0xff0000, 1000); LK.setTimeout(function () { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); }, 2000); return; // Don't continue with scoring } // Score! scored = true; LK.getSound('score').play(); // Check if it's a clean swish (ball passes through center of rim) var distanceFromCenter = Math.abs(ballCenterX - rimCenterX); var isCleanShot = distanceFromCenter < 30; // Within 30 pixels of center if (isCleanShot) { // Clean swish - special effects LK.effects.flashObject(hoop, 0x00FFFF, 800); // Cyan flash for perfect shot // Slow down ball slightly for dramatic effect basketball.velocityX *= 0.8; basketball.velocityY *= 0.9; } else { // Regular score LK.effects.flashObject(hoop, 0x00FF00, 500); } // Let global timer handle level progression for all levels // Animate net swish effect with enhanced 3D movement if (hoop.netSegments) { hoop.netSegments.forEach(function (segment, index) { var swishIntensity = isCleanShot ? 1.5 : 1.0; // More dramatic swish for clean shots // First phase: compress and sway tween(segment, { scaleY: 0.05 * swishIntensity, alpha: 0.2, rotation: segment.rotation + 0.3 * swishIntensity, y: segment.y + 15 // Pull net segments down more }, { duration: isCleanShot ? 200 : 150, easing: tween.easeOut }); LK.setTimeout(function () { // Second phase: bounce back with realistic sway tween(segment, { scaleY: 0.15, alpha: 0.8, rotation: segment.rotation - 0.1 * swishIntensity, y: segment.y - 10 // Natural bounce back position }, { duration: isCleanShot ? 600 : 400, easing: tween.bounceOut }); }, index * (isCleanShot ? 40 : 30)); }); } // Level complete - show success display and Next Level button gameState = 'levelComplete'; // Show immediate success feedback if (timerCountdownText) { timerCountdownText.setText('Level Complete!'); timerCountdownText.tint = 0x00FF00; timerCountdownText.visible = true; timerCountdownText.scaleX = 1.5; timerCountdownText.scaleY = 1.5; // Animate success text tween(timerCountdownText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.bounceOut }); } // Show Next Level button nextLevelButton.visible = true; tween(nextLevelButton, { scaleX: 1.2, scaleY: 1.2, alpha: 1 }, { duration: 500, easing: tween.bounceOut }); // Lock input immediately upon scoring inputDisabled = true; } else { // Ball hit rim but didn't score - ultra soft rim bounce for maximum forgiveness var overlapX = Math.abs(ballCenterX - rimCenterX) - (80 + hoop.rimCollisionZone.width / 2); var overlapY = Math.abs(ballCenterY - rimCenterY) - (80 + hoop.rimCollisionZone.height / 2); // Ultra soft bounces with minimal energy loss for maximum forgiveness var softBounceDecay = 0.2; // Even softer bounce - less harsh rejection var energyLoss = 0.9; // Higher energy retention - keep more momentum var distanceFromCenter = Math.abs(ballCenterX - rimCenterX); var distanceFromFrontEdge = Math.abs(ballCenterX - (rimCenterX - hoop.rimCollisionZone.width / 2)); // Make front edge (facing player) extremely forgiving if (distanceFromFrontEdge < 30 && basketball.velocityX < 0) { // Front edge hit - minimal bounce with downward guidance softBounceDecay = 0.1; energyLoss = 0.95; // Add slight downward velocity to help ball drop into hoop basketball.velocityY += 0.5; } else if (distanceFromCenter < 50) { // Very close to center - barely bounce at all softBounceDecay = 0.15; energyLoss = 0.92; } else if (distanceFromCenter < 100) { // Moderately close - gentle bounce softBounceDecay = 0.25; energyLoss = 0.88; } if (overlapX < overlapY) { basketball.velocityX = -basketball.velocityX * softBounceDecay; basketball.velocityY = basketball.velocityY * energyLoss; // Keep more perpendicular velocity basketball.x += ballCenterX < rimCenterX ? -1 : 1; // Minimal position adjustment } else { basketball.velocityY = -basketball.velocityY * softBounceDecay; basketball.velocityX = basketball.velocityX * energyLoss; // Keep more perpendicular velocity basketball.y += ballCenterY < rimCenterY ? -1 : 1; // Minimal position adjustment } LK.getSound('bounce').play(); // Flash rim on hit with gentler color LK.effects.flashObject(hoop.rim, 0xFFAA00, 300); } } } function resetBall() { basketball.reset(); clearTrajectory(); clearPowerIndicators(); gameState = 'playing'; // Reset objective tracking for new attempt wallBounces = 0; touchedWall = false; leftWallBounced = false; touchedNonLeftWall = false; objectiveFailed = false; failureReason = ''; // Reset timer challenge variables ballReleaseTime = 0; timerCountdown = 0; inputDisabled = false; globalTimerActive = false; globalTimerStartTime = 0; if (timerCountdownText) { timerCountdownText.visible = false; } // Hide Next Level button if (nextLevelButton) { nextLevelButton.visible = false; } } function showTrajectory(forceX, forceY) { clearTrajectory(); var simX = basketball.x; var simY = basketball.y; var simVelX = forceX; var simVelY = forceY; var simGravity = 0.3; var forceMagnitude = Math.sqrt(forceX * forceX + forceY * forceY); var powerPercent = Math.min(forceMagnitude / 40, 1.0); for (var i = 0; i < 30; i++) { simX += simVelX; simY += simVelY; simVelY += simGravity; if (i % 3 === 0) { var dot = game.addChild(new TrajectoryDot()); dot.x = simX; dot.y = simY; // Scale dots based on power level dot.scaleX = 0.5 + powerPercent * 0.8; dot.scaleY = 0.5 + powerPercent * 0.8; // Color dots based on power dot.tint = powerPercent > 0.8 ? 0xff0000 : powerPercent > 0.5 ? 0xffff00 : 0x00ff00; trajectoryDots.push(dot); } if (simX <= 80 || simX >= 1968 || simY <= 80) { break; } } } function clearTrajectory() { trajectoryDots.forEach(function (dot) { dot.destroy(); }); trajectoryDots = []; } function updatePowerIndicators(currentX, currentY, dragDistance, forceMagnitude) { // Clear existing indicators clearPowerIndicators(); // Calculate power percentage (0 to 1) var powerPercent = Math.min(forceMagnitude / 40, 1.0); // Create aim line from ball to current drag position var aimLineAsset = LK.getAsset('trajectory', { anchorX: 0.5, anchorY: 0.5, scaleX: Math.max(1, dragDistance / 8), scaleY: Math.max(2, 2 + powerPercent * 3) }); aimLineAsset.x = (basketball.x + currentX) / 2; aimLineAsset.y = (basketball.y + currentY) / 2; aimLineAsset.rotation = Math.atan2(currentY - basketball.y, currentX - basketball.x); aimLineAsset.alpha = 0.8; aimLineAsset.tint = powerPercent > 0.8 ? 0xff0000 : powerPercent > 0.5 ? 0xffff00 : 0x00ff00; game.addChild(aimLineAsset); aimLine = aimLineAsset; // Create power bar indicator var powerBarWidth = 300; var powerBarHeight = 20; var powerBarX = basketball.x - powerBarWidth / 2; var powerBarY = basketball.y - 120; // Power bar background var powerBarBg = LK.getAsset('wall', { anchorX: 0, anchorY: 0, scaleX: powerBarWidth / 200, scaleY: powerBarHeight / 30, tint: 0x333333 }); powerBarBg.x = powerBarX; powerBarBg.y = powerBarY; powerBarBg.alpha = 0.7; game.addChild(powerBarBg); // Power bar fill var fillWidth = powerBarWidth * powerPercent; if (fillWidth > 0) { var powerBarFill = LK.getAsset('wall', { anchorX: 0, anchorY: 0, scaleX: fillWidth / 200, scaleY: powerBarHeight / 30, tint: powerPercent > 0.8 ? 0xff0000 : powerPercent > 0.5 ? 0xffff00 : 0x00ff00 }); powerBarFill.x = powerBarX; powerBarFill.y = powerBarY; powerBarFill.alpha = 0.9; game.addChild(powerBarFill); powerBar = [powerBarBg, powerBarFill]; } else { powerBar = [powerBarBg]; } } function clearPowerIndicators() { if (aimLine) { aimLine.destroy(); aimLine = null; } if (powerBar) { powerBar.forEach(function (bar) { bar.destroy(); }); powerBar = null; } } // Power indicator variables var powerBar = null; var aimLine = null; var maxDragDistance = 400; // Maximum pixel distance for full power // Input handling game.down = function (x, y, obj) { if (gameState !== 'playing' || basketball.isLaunched || inputDisabled) { return; } isDragging = true; dragStartX = x; dragStartY = y; }; game.move = function (x, y, obj) { if (!isDragging || gameState !== 'playing' || basketball.isLaunched || inputDisabled) { return; } // Calculate drag distance and force with increased sensitivity var dragX = dragStartX - x; var dragY = dragStartY - y; var dragDistance = Math.sqrt(dragX * dragX + dragY * dragY); var dragMultiplier = Math.min(dragDistance / maxDragDistance, 1.0); var forceX = dragX * 0.08 * dragMultiplier; var forceY = dragY * 0.08 * dragMultiplier; // Limit force to maximum power var magnitude = Math.sqrt(forceX * forceX + forceY * forceY); if (magnitude > 40) { forceX = forceX / magnitude * 40; forceY = forceY / magnitude * 40; } // Update visual feedback updatePowerIndicators(x, y, dragDistance, magnitude); showTrajectory(forceX, forceY); }; game.up = function (x, y, obj) { if (!isDragging || gameState !== 'playing' || basketball.isLaunched || inputDisabled) { return; } isDragging = false; // Calculate final force with increased sensitivity var dragX = dragStartX - x; var dragY = dragStartY - y; var dragDistance = Math.sqrt(dragX * dragX + dragY * dragY); var dragMultiplier = Math.min(dragDistance / maxDragDistance, 1.0); var forceX = dragX * 0.08 * dragMultiplier; var forceY = dragY * 0.08 * dragMultiplier; // Limit force to maximum power var magnitude = Math.sqrt(forceX * forceX + forceY * forceY); if (magnitude > 40) { forceX = forceX / magnitude * 40; forceY = forceY / magnitude * 40; } // Clear visual indicators clearPowerIndicators(); if (magnitude > 1) { attempts++; updateAttemptsText(); basketball.launch(forceX, forceY); clearTrajectory(); // Start global 3-second timer for all levels ballReleaseTime = LK.ticks; globalTimerActive = true; globalTimerStartTime = LK.ticks; inputDisabled = true; timerCountdownText.visible = true; // Check if out of attempts if (maxAttempts > 0 && attempts >= maxAttempts && !scored) { LK.setTimeout(function () { if (!scored) { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); } }, 3000); } } }; // Main update loop game.update = function () { if (gameState === 'playing') { // Handle global 3-second timer countdown for all levels if (globalTimerActive && globalTimerStartTime > 0) { var timeSinceRelease = (LK.ticks - globalTimerStartTime) * (1000 / 60); // Convert to milliseconds var remainingTime = Math.max(0, 3000 - timeSinceRelease); var secondsLeft = Math.ceil(remainingTime / 1000); if (timerCountdownText) { timerCountdownText.setText(secondsLeft.toString()); timerCountdownText.visible = true; timerCountdownText.tint = 0xFFFFFF; // Reset tint to white // Animate countdown text var scale = 1.0 + Math.sin(LK.ticks * 0.3) * 0.2; timerCountdownText.scaleX = scale; timerCountdownText.scaleY = scale; } // Check if 3 seconds have passed - end level regardless of success/failure if (remainingTime <= 0) { globalTimerActive = false; var level = levels[currentLevel - 1]; var wasSuccessful = scored; // Check objective completion if (leftWallBounceRequired && !leftWallBounced) { wasSuccessful = false; } else if (level.objective === 'bounce_once' && wallBounces !== 1) { wasSuccessful = false; } else if (level.objective === 'bounce_twice' && wallBounces !== 2) { wasSuccessful = false; } else if (level.objective === 'no_wall' && touchedWall) { wasSuccessful = false; } else if (level.objective === 'timer_challenge') { // For timer challenge, must score within 1 second var timeSinceReleaseForTimer = (LK.ticks - ballReleaseTime) * (1000 / 60); if (!scored || timeSinceReleaseForTimer > 1000) { wasSuccessful = false; } } if (wasSuccessful) { // Flash screen with success color LK.effects.flashScreen(0x00FF00, 500); // Add sparkle effect to hoop if (hoop) { tween(hoop, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut }); LK.setTimeout(function () { tween(hoop, { scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.bounceOut }); }, 200); } // Hide timer countdown as level is complete if (timerCountdownText) { timerCountdownText.visible = false; } // Lock input but don't auto-progress - wait for button click inputDisabled = true; } else { // Level failed if (timerCountdownText) { timerCountdownText.setText('FAIL'); timerCountdownText.tint = 0xFF0000; } LK.effects.flashScreen(0xff0000, 1000); LK.setTimeout(function () { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); }, 2000); } return; } } // Track screen edge bounces for objectives (before calling checkCollisions) if (basketball.isLaunched) { var ballRadius = 80; var lastWallBounces = wallBounces; // Check if ball just bounced off any screen edge this frame if (basketball.x <= ballRadius && basketball.velocityX > 0 || basketball.x >= 2048 - ballRadius && basketball.velocityX < 0 || basketball.y <= ballRadius && basketball.velocityY > 0 || basketball.y >= 2732 - ballRadius && basketball.velocityY < 0) { // Ball just bounced off a screen edge if (wallBounces === lastWallBounces) { // Prevent double counting wallBounces++; touchedWall = true; // Track non-left wall touches for level 10 if (leftWallBounceRequired && (basketball.x >= 2048 - ballRadius || basketball.y <= ballRadius || basketball.y >= 2732 - ballRadius)) { touchedNonLeftWall = true; objectiveFailed = true; failureReason = 'You must hit the left wall first!'; } var level = levels[currentLevel - 1]; if (level.objective === 'no_wall') { objectiveFailed = true; failureReason = 'You touched the wall!'; } } } } checkCollisions(); // Check for objective failures if (objectiveFailed && !scored) { LK.effects.flashScreen(0xff0000, 1000); LK.setTimeout(function () { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); }, 2000); return; } // Check if ball is off screen (reset) if (basketball.isLaunched && basketball.y > 2800) { if (!scored) { // Ball missed - check if this constitutes objective failure var level = levels[currentLevel - 1]; var missedObjectiveMessage = 'Missed the hoop!'; if (leftWallBounceRequired && !leftWallBounced) { missedObjectiveMessage = 'You must hit the left wall first!'; } else if (level.objective === 'bounce_once' && wallBounces !== 1) { missedObjectiveMessage = wallBounces === 0 ? 'You must bounce off one wall!' : 'You bounced too many times!'; } else if (level.objective === 'bounce_twice' && wallBounces !== 2) { missedObjectiveMessage = wallBounces === 0 ? 'You must bounce off two walls!' : wallBounces === 1 ? 'You must bounce off one more wall!' : 'You bounced too many times!'; } else if (level.objective === 'no_wall' && touchedWall) { missedObjectiveMessage = 'You touched the wall!'; } LK.effects.flashScreen(0xff0000, 1000); LK.setTimeout(function () { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); }, 2000); } else if (maxAttempts > 0 && attempts >= maxAttempts) { currentLevel = 1; storage.currentLevel = 1; LK.showGameOver(); } else { resetBall(); } } } }; // Initialize first level initializeLevel(currentLevel);
===================================================================
--- original.js
+++ change.js
@@ -1453,10 +1453,10 @@
// Hide Next Level button
if (nextLevelButton) {
nextLevelButton.visible = false;
}
- // Create fire launcher for level 19 and onwards
- if (levelNum >= 19) {
+ // Create fire launcher for level 19 only
+ if (levelNum === 19) {
var fireballTimer = LK.setInterval(function () {
// Create fireball at launcher position
var fireball = game.addChild(new Fireball());
fireball.x = 1024;
Modern App Store icon, high definition, square with rounded corners, for a game titled "Basket Bounce Challenge" and with the description "A colorful basketball puzzle game with slingshot mechanics across 20 challenging levels. Drag and release the ball to score, progressing from simple shots to complex bank shot puzzles with moving hoops and obstacles.". No text on icon!
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Basket Bounce Challenge" and with the description "A colorful basketball puzzle game with slingshot mechanics across 20 challenging levels. Drag and release the ball to score, progressing from simple shots to complex bank shot puzzles with moving hoops and obstacles.". No text on banner!
A minimalist black and white basketball court background. The court is shown from a side view or slightly isometric angle. It includes clear outlines for the hoop, backboard, half court line, and three-point arc, all in clean black lines on a white surface (or vice versa). The style is modern, simple, and flat — no players, just the environment.. In-Game asset. 2d. High contrast. No shadows