/**** 
* 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 fireballTimer = null;
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 = '';
var backgroundImage = null;
// 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: 'Fireball timee!',
	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: 'Whaaatt! U need LUCK',
	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: 'Impossible!',
	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();
		}
	}
};
function initializeLevel(levelNum) {
	if (fireballTimer !== null) {
		LK.clearInterval(fireballTimer);
		fireballTimer = null;
	}
	if (levelNum > levels.length || levelNum < 1) {
		return;
	}
	// Set background image
	if (backgroundImage && backgroundImage.parent) {
		backgroundImage.destroy();
	}
	backgroundImage = LK.getAsset('basket', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2048 / 100,
		scaleY: 2732 / 100
	});
	backgroundImage.x = 1024;
	backgroundImage.y = 1366;
	game.addChildAt(backgroundImage, 0);
	// Set background color based on level
	game.setBackgroundColor(0x2F4F4F);
	// 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());
	// Set custom position for level 21
	if (levelNum === 21) {
		basketball.x = 1800;
		basketball.y = 2300;
		basketball.startX = 1800;
		basketball.startY = 2300;
	} else {
		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;
	// Make basketball and shadow invisible for level 21
	if (levelNum === 21) {
		basketball.alpha = 0;
		shadow.alpha = 0;
	}
	// Create hoop
	hoop = game.addChild(new Hoop());
	hoop.x = 2048; // Always position flush against rightmost wall
	hoop.y = level.hoopY;
	hoop.isMoving = level.movingHoop;
	// Make hoop components invisible for level 20
	if (levelNum === 20) {
		hoop.rim.alpha = 0;
		hoop.backboard.alpha = 0;
		hoop.supportLine.alpha = 0;
		hoop.netSegments.forEach(function (segment) {
			segment.alpha = 0;
		});
		// Make brackets invisible too
		var wallBracket = hoop.children.find(function (child) {
			return child.tint === 0x808080 && child.scaleX === 0.3;
		});
		var rimBracket = hoop.children.find(function (child) {
			return child.tint === 0x808080 && child.scaleX === 0.6;
		});
		if (wallBracket) {
			wallBracket.alpha = 0;
		}
		if (rimBracket) {
			rimBracket.alpha = 0;
		}
	}
	// 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 movement for level 21
	if (levelNum === 21) {
		hoop.isMoving = true;
		hoop.moveHorizontal = false;
		hoop.minY = 300;
		hoop.maxY = 1500;
		hoop.moveSpeed = 20;
	}
	// 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
			});
		}
		// Make walls invisible for level 20
		if (levelNum === 20) {
			wall.alpha = 0;
		}
		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) {
		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); /**** 
* 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 fireballTimer = null;
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 = '';
var backgroundImage = null;
// 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: 'Fireball timee!',
	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: 'Whaaatt! U need LUCK',
	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: 'Impossible!',
	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();
		}
	}
};
function initializeLevel(levelNum) {
	if (fireballTimer !== null) {
		LK.clearInterval(fireballTimer);
		fireballTimer = null;
	}
	if (levelNum > levels.length || levelNum < 1) {
		return;
	}
	// Set background image
	if (backgroundImage && backgroundImage.parent) {
		backgroundImage.destroy();
	}
	backgroundImage = LK.getAsset('basket', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2048 / 100,
		scaleY: 2732 / 100
	});
	backgroundImage.x = 1024;
	backgroundImage.y = 1366;
	game.addChildAt(backgroundImage, 0);
	// Set background color based on level
	game.setBackgroundColor(0x2F4F4F);
	// 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());
	// Set custom position for level 21
	if (levelNum === 21) {
		basketball.x = 1800;
		basketball.y = 2300;
		basketball.startX = 1800;
		basketball.startY = 2300;
	} else {
		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;
	// Make basketball and shadow invisible for level 21
	if (levelNum === 21) {
		basketball.alpha = 0;
		shadow.alpha = 0;
	}
	// Create hoop
	hoop = game.addChild(new Hoop());
	hoop.x = 2048; // Always position flush against rightmost wall
	hoop.y = level.hoopY;
	hoop.isMoving = level.movingHoop;
	// Make hoop components invisible for level 20
	if (levelNum === 20) {
		hoop.rim.alpha = 0;
		hoop.backboard.alpha = 0;
		hoop.supportLine.alpha = 0;
		hoop.netSegments.forEach(function (segment) {
			segment.alpha = 0;
		});
		// Make brackets invisible too
		var wallBracket = hoop.children.find(function (child) {
			return child.tint === 0x808080 && child.scaleX === 0.3;
		});
		var rimBracket = hoop.children.find(function (child) {
			return child.tint === 0x808080 && child.scaleX === 0.6;
		});
		if (wallBracket) {
			wallBracket.alpha = 0;
		}
		if (rimBracket) {
			rimBracket.alpha = 0;
		}
	}
	// 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 movement for level 21
	if (levelNum === 21) {
		hoop.isMoving = true;
		hoop.moveHorizontal = false;
		hoop.minY = 300;
		hoop.maxY = 1500;
		hoop.moveSpeed = 20;
	}
	// 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
			});
		}
		// Make walls invisible for level 20
		if (levelNum === 20) {
			wall.alpha = 0;
		}
		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) {
		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);
:quality(85)/https://cdn.frvr.ai/685ead54d91b6bc6317f9772.png%3F3) 
 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!
:quality(85)/https://cdn.frvr.ai/685ead57d91b6bc6317f9773.png%3F3) 
 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!
:quality(85)/https://cdn.frvr.ai/685fcf9e46f61e05e2ebb026.png%3F3) 
 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
:quality(85)/https://cdn.frvr.ai/685fd22aecde5d1c2c6ebc5c.png%3F3)