/**** 
* Classes
****/ 
/* ********************************************************************************* */ 
/* ********************************** BALL CLASS *********************************** */
/* ********************************************************************************* */ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('basketball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speedX = 0;
	self.speedY = 0;
	self.wallBounceSpeedRatio = 0.95;
	self.floorBounceRatio = 0.8;
	self.gravityAcceleration = 1.2;
	self.half = ballGraphics.width / 2;
	self.isMoving = false;
	self.launch = function (speedX, speedY) {
		self.speedX = speedX;
		self.speedY = speedY;
		self.isMoving = true;
	};
	self.update = function () {
		if (!self.isMoving) {
			return;
		}
		self.x += self.speedX;
		self.y += self.speedY;
		// Make the basketball spin only when moving
		if (self.speedX !== 0 || self.speedY !== 0) {
			ballGraphics.rotation += 0.1 * Math.sign(self.speedX);
		}
		// Gradually reduce horizontal speed
		// Apply friction to horizontal speed and limit to max speed
		self.speedX *= 0.99;
		self.speedX = Math.max(Math.min(self.speedX, maxSpeed), -maxSpeed); // Max speed limit
		// Enhanced gravity effect with gradual vertical speed reduction and limit to max speed
		self.speedY += self.gravityAcceleration;
		self.speedY = Math.max(Math.min(self.speedY, maxSpeed), -maxSpeed); // Max speed limit
		// Top boundary
		if (self.y <= 0 + self.half) {
			self.y = 0 + self.half;
			self.speedY *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, self.x, self.y);
		}
		// Bottom boundary
		if (ball.y > game.height - self.half) {
			ball.y = game.height - self.half;
			ball.speedY *= -1 * self.wallBounceSpeedRatio * self.floorBounceRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Left boundary
		if (ball.x < 0 + self.half) {
			ball.x = 0 + self.half;
			ball.speedX *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Right boundary
		if (ball.x > game.width - self.half) {
			ball.x = game.width - self.half;
			ball.speedX *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Reset ball when in bottom and its speed is very low
		if (ball.y > game.height * 0.6 && Math.abs(self.speedX) < 5 && Math.abs(self.speedY) < 5) {
			self.reset();
			moveHoop();
		}
	};
	self.reset = function () {
		ballPassedAboveHoop = false;
		ballPassedInsideHoop = false;
		bounceMultiplier = 1; // Reset bounce counter
		self.x = game.width / 2;
		self.y = game.height - 300;
		self.speedX = 0;
		self.speedY = 0;
		self.isMoving = false;
		if (isGameOver) {
			isLastShotEnded = true;
		}
	};
});
/* ********************************************************************************* */ 
/* ******************************** CONFETTI CLASS ********************************* */
/* ********************************************************************************* */ 
// Confetti class for creating a confetti effect
var Confetti = Container.expand(function () {
	var self = Container.call(this);
	var confettiColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF];
	var confettiPieces = [];
	// Generate multiple confetti pieces
	for (var i = 0; i < 200; i++) {
		var color = confettiColors[Math.floor(Math.random() * confettiColors.length)];
		var confettiPiece = self.attachAsset('butter', {
			anchorX: 0.5,
			anchorY: 0.5,
			tint: color
		});
		confettiPiece.x = Math.random() * game.width * 2; // Spread across entire screen width
		confettiPiece.y = Math.random() * game.height * 2 - game.height; // Spread across entire screen height
		confettiPiece.scaleX = confettiPiece.scaleY = Math.random() * 0.5 + 0.5; // Random scale
		confettiPieces.push(confettiPiece);
	}
	// Animate confetti pieces
	self.animate = function () {
		confettiPieces.forEach(function (piece) {
			piece.y += Math.random() * 20 + 10; // Further increased fall speed
			piece.rotation += Math.random() * 0.2 - 0.1; // Random rotation
			// Remove piece if it goes off-screen
			if (piece.y > game.height + 50) {
				piece.destroy();
				confettiPieces.splice(confettiPieces.indexOf(piece), 1);
			}
		});
		// Stop animation and destroy confetti container if all pieces are gone
		if (confettiPieces.length === 0) {
			self.destroy();
		}
	};
});
/* ********************************************************************************* */ 
/* ********************************** HOOP CLASS *********************************** */
/* ********************************************************************************* */ 
var Hoop = Container.expand(function () {
	var self = Container.call(this);
	var hoopGraphics = self.attachAsset('hoop', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.setPosition = function (x, y) {
		self.x = x;
		self.y = y;
	};
	// Define hoopTrigger as a new Container object for better intersection detection
	self.hoopTopTrigger = new Container();
	self.hoopTopTrigger.isHandling = false;
	var hoopTriggerGraphics = self.hoopTopTrigger.attachAsset('hoopTrigger', {
		width: 200,
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopTriggerGraphics inside hoopTrigger container
	hoopTriggerGraphics.y = 0;
	// Position hoopTrigger container relative to the hoop
	self.hoopTopTrigger.y = -hoopGraphics.height / 2 + 60;
	// Add hoopTrigger container as a child of Hoop
	self.addChild(self.hoopTopTrigger);
	// Define hoopBottomTrigger as a new Container object for better intersection detection
	self.hoopBottomTrigger = new Container();
	self.hoopTopTrigger.isHandling = false;
	var hoopBottomTriggerGraphics = self.hoopBottomTrigger.attachAsset('hoopTrigger', {
		width: 300,
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0x0000ff
	});
	// Position hoopBottomTriggerGraphics inside hoopBottomTrigger container
	hoopBottomTriggerGraphics.y = 0;
	// Position hoopBottomTrigger container relative to the hoop
	self.hoopBottomTrigger.y = -hoopGraphics.height / 2 + 150;
	// Add hoopBottomTrigger container as a child of Hoop
	self.addChild(self.hoopBottomTrigger);
	// Define hoopBorderLeft as a new Container object for collision detection
	self.hoopBorderLeft = new Container();
	self.hoopBorderLeft.isHandling = false;
	var hoopBorderLeftGraphics = self.hoopBorderLeft.attachAsset('hoopBorder', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopBorderLeftGraphics inside hoopBorderLeft container
	hoopBorderLeftGraphics.y = 0;
	// Position hoopBorderLeft container relative to the hoop
	self.hoopBorderLeft.x = -hoopGraphics.width / 2 + 20;
	self.hoopBorderLeft.y = -hoopGraphics.height / 2 + 40;
	// Add hoopBorderLeft container as a child of Hoop
	self.addChild(self.hoopBorderLeft);
	// Define hoopBorderRight as a new Container object for collision detection
	self.hoopBorderRight = new Container();
	self.hoopBorderRight.isHandling = false;
	var hoopBorderRightGraphics = self.hoopBorderRight.attachAsset('hoopBorder', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopBorderRightGraphics inside hoopBorderRight container
	hoopBorderRightGraphics.y = 0;
	// Position hoopBorderRight container relative to the hoop
	self.hoopBorderRight.x = hoopGraphics.width / 2 - 20;
	self.hoopBorderRight.y = -hoopGraphics.height / 2 + 40;
	// Add hoopBorderRight container as a child of Hoop
	self.addChild(self.hoopBorderRight);
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({});
/**** 
* Game Code
****/ 
/* ********************************************************************************* */ 
/* ******************************* GAME VARIABLES ********************************** */
/* ********************************************************************************* */ 
var isGameRunning = false;
var isHandlingScore = false;
var bounceMultiplier = 1;
var currentShootBuckets = 0;
var maxSpeed = 100;
var ballPassedAboveHoop = false;
var ballPassedInsideHoop = false;
var timerSeconds = 6; // Set the initial timer value in seconds
var ball = null;
var hoop = null;
var score = 0;
var startPosition = null;
var isDebug = false;
// UI
var background = null;
var scoreTxt = null;
var timerTxt = null;
var timerLabelTxt = null;
var minShootSpeed = 30;
var timerInterval = null;
var timerOriginalWeigth = 94; // 1 char
var timerOriginalHeight = 174;
var isScoreAnimating = false;
var scoreAnimationInterval = null;
var previousScore = 0;
var originalScoreWidth = 92;
var originalScoreHeight = 174;
var isGameOver = false;
var isLastShotEnded = false;
/* ********************************************************************************* */ 
/* ******************************* INPUT HANDLERS ********************************** */
/* ********************************************************************************* */ 
game.on('down', function (obj) {
	if (isGameOver) {
		return;
	}
	var pos = obj.event.getLocalPosition(game);
	startPosition = pos;
	if (!isGameRunning) {
		isGameRunning = true;
	}
});
game.on('up', function (obj) {
	if (isGameOver) {
		return;
	}
	if (startPosition && !ball.isMoving) {
		var endPosition = obj.event.getLocalPosition(game);
		var speedX = Math.max(Math.min((endPosition.x - startPosition.x) * 0.1, maxSpeed), -maxSpeed);
		var speedY = Math.max(Math.min((endPosition.y - startPosition.y) * 0.1, maxSpeed), -maxSpeed);
		if (Math.abs(speedX) >= minShootSpeed || Math.abs(speedY) >= minShootSpeed) {
			//console.log("============================= SHOOT ===========================");
			currentShootBuckets = 0;
			ball.launch(speedX, speedY);
		}
		startPosition = null;
	}
});
/* ********************************************************************************* */ 
/* ********************************** GAME FUNCTIONS ************************************ */
/* ********************************************************************************* */ 
function initGame() {
	// Background
	var background = LK.getAsset('background', {
		anchorX: 0.0,
		anchorY: 0.0,
		x: 0,
		y: 0
	});
	game.addChild(background);
	// Score UI
	// Create and configure the 'Score' label text
	var scoreLabelTxt = new Text2('Score', {
		size: 50,
		fill: "#006400",
		weight: 1000,
		dropShadow: true
	});
	scoreLabelTxt.anchor.set(0.5, 0.25);
	LK.gui.top.addChild(scoreLabelTxt);
	scoreTxt = new Text2(score.toString(), {
		size: 150,
		fill: "#006400",
		weight: 1000,
		dropShadow: true
	});
	scoreTxt.anchor.set(0.5, -0.150);
	LK.gui.top.addChild(scoreTxt);
	// Timer UI
	timerLabelTxt = new Text2('Time', {
		size: 50,
		fill: "#FFFFFF",
		weight: 1000,
		dropShadow: true
	});
	timerLabelTxt.tint = 0x646464;
	timerLabelTxt.anchor.set(1.4, 0.25);
	LK.gui.topRight.addChild(timerLabelTxt);
	timerTxt = new Text2(timerSeconds.toString(), {
		size: 150,
		fill: "#FFFFFF",
		weight: 1000,
		dropShadow: true
	});
	timerTxt.tint = timerSeconds <= 5 ? 0xff0000 : 0x646464;
	timerTxt.anchor.set(1.10, -0.150);
	LK.gui.topRight.addChild(timerTxt);
	// Update the timer every second
	timerInterval = LK.setInterval(handleTimer, 1000); // Set the interval to update every 1000ms (1 second)
	ball = game.addChild(new Ball());
	ball.reset();
	hoop = game.addChild(new Hoop());
	if (!isDebug) {
		hoop.hoopTopTrigger.alpha = 0;
		hoop.hoopBottomTrigger.alpha = 0;
		hoop.hoopBorderLeft.alpha = 0;
		hoop.hoopBorderRight.alpha = 0;
	}
	hoop.setPosition(game.width / 2, 1024); // Position the hoop at the top center
	swipeAnim();
}
function handleTimer() {
	if (!isGameRunning) {
		return;
	}
	timerSeconds -= 1; // Decrement the timer by one second
	timerTxt.setText(timerSeconds.toString()); // Update the timer display with conditional color change
	var animateTimer = null;
	if (timerSeconds < 10) {
		timerTxt.anchor.set(1.6, -0.150);
	}
	if (timerSeconds <= 5 && timerSeconds > 0) {
		var maxTimerLabelSize = 200 + (5 - timerSeconds) * 20;
		timerTxt.tint = 0xff0000;
		timerLabelTxt.tint = 0xff0000;
		// Animate timerTxt width and height
		var growDirection = 1;
		animateTimer = LK.setInterval(function () {
			timerTxt.width += growDirection * 4;
			timerTxt.height += growDirection * 4;
			if (timerTxt.width >= maxTimerLabelSize || timerTxt.height >= maxTimerLabelSize || timerTxt.width <= 100 || timerTxt.height <= 100) {
				growDirection *= -1;
			}
		}, 16); // Run every 16ms (~60FPS)
	} else {
		timerTxt.tint = 0x646464;
	}
	if (timerSeconds <= 0) {
		timerTxt.tint = 0x646464;
		timerLabelTxt.tint = 0x646464;
		timerTxt.width = timerOriginalWeigth;
		timerTxt.height = timerOriginalHeight;
		LK.clearInterval(animateTimer);
		isGameOver = true;
	}
	if (isGameOver && isLastShotEnded) {
		LK.clearInterval(timerInterval); // Stop the timer when it reaches 0
		LK.setScore(score); // Save the final score using the platform's tool
		LK.showGameOver(); // Show game over screen
	}
}
function handleTopTrigger() {
	//console.log("Top trigger. speed", ball.speedY);
	hoop.hoopTopTrigger.isHandling = true;
	if (ball.speedY > 0) {
		ballPassedAboveHoop = true;
	}
}
function handleBottomTrigger() {
	//console.log("Bottom trigger", ball.speedY.toFixed(2), ball.x.toFixed(2), hoop.hoopBorderLeft.x.toFixed(2), hoop.hoopBorderRight.x.toFixed(2));
	hoop.hoopBottomTrigger.isHandling = true;
	var leftBorderX = hoop.x + hoop.hoopBorderLeft.x;
	var rightBorderX = hoop.x + hoop.hoopBorderRight.x;
	if (ballPassedAboveHoop && ball.x > leftBorderX && ball.x < rightBorderX) {
		if (ball.speedY > 0) {
			//console.log("--------------- SCORE!!! -----------------");
			ballPassedInsideHoop = true;
			handleScore();
		}
	} else if (ball.speedY < 0) {
		//console.log("touch hoop from bottom");
		ball.speedY *= -0.98;
		ballPassedAboveHoop = false;
		ballPassedInsideHoop = false;
	}
}
function handleHoopBorder(border) {
	//console.log("handleHoopBorder");
	border.isHandling = true;
	// Check if the ball has hit the left or right border
	if (ball.x <= border.x || ball.x >= border.x + border.width) {
		ball.speedX *= -1; // Reverse the x direction
	}
	// Check if the ball has hit the top or bottom border
	if (ball.y <= border.y || ball.y >= border.y + border.height) {
		//ball.speedY *= -1; // Reverse the y direction ???
	}
}
function resetCollisionHandling() {
	//console.log("resetCollisionHandling...");
	hoop.hoopTopTrigger.isHandling = false;
	hoop.hoopBottomTrigger.isHandling = false;
	hoop.hoopBorderLeft.isHandling = false;
	hoop.hoopBorderRight.isHandling = false;
}
// Fonction pour normaliser un vecteur
function normalize(vector) {
	var magnitude = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
	return {
		x: vector.x / magnitude,
		y: vector.y / magnitude
	};
}
function handleScore() {
	if (isHandlingScore) {
		return;
	}
	//console.log("handleScore...bounceMultiplier=", bounceMultiplier, "*", currentShootBuckets);
	isHandlingScore = true;
	currentShootBuckets++;
	score += 10 * bounceMultiplier + 10 * bounceMultiplier * (currentShootBuckets - 1) * (currentShootBuckets - 1); // Add bounce counter to score
	scoreTxt.setText(score.toString());
	animateScore();
	popupBucket(currentShootBuckets - 1);
	ballPassedAboveHoop = false; // Reset the condition after scoring
	ballPassedInsideHoop = false;
	// Create and add confetti effect to the game
	var confetti = game.addChild(new Confetti());
	confetti.x = 0; // Position confetti at the hoop's position
	confetti.y = 0;
	LK.on('tick', function () {
		confetti.animate(); // Animate confetti
	});
}
function animateScore() {
	if (isScoreAnimating) {
		LK.clearInterval(scoreAnimationInterval);
		scoreTxt.width = originalScoreWidth * score.toString().length;
		scoreTxt.height = originalScoreHeight;
		isScoreAnimating = false;
	}
	isScoreAnimating = true;
	var scoreSizeDirection = 1;
	//console.log("score " + score, " / l=" + score.toString().length, " w,h=" + originalScoreWidth + "," + originalScoreHeight);
	var maxScoreWidth = 300 * score.toString().length; // Maximum size to grow to
	var maxScoreHeight = 300;
	var minScoreSize = 100; // Minimum size to shrink to
	scoreAnimationInterval = LK.setInterval(function () {
		scoreTxt.width += scoreSizeDirection * 5; // Adjust width by 5 pixels per frame
		scoreTxt.height += scoreSizeDirection * 5; // Adjust height by 5 pixels per frame
		// Reverse direction if the score text reaches max or min size
		if (scoreTxt.width >= maxScoreWidth || scoreTxt.height >= maxScoreHeight || scoreTxt.width <= minScoreSize || scoreTxt.height <= minScoreSize) {
			scoreSizeDirection *= -1;
		}
		// Restore original size and clear interval when animation is done
		if (scoreTxt.width <= originalScoreWidth * score.toString().length && scoreTxt.height <= originalScoreHeight) {
			LK.clearInterval(scoreAnimationInterval);
			scoreTxt.width = originalScoreWidth * score.toString().length;
			scoreTxt.height = originalScoreHeight;
			isScoreAnimating = false;
		}
	}, 20); // Run every 16ms (~60FPS)
}
function moveHoop() {
	//console.log("moveHoop...");
	// Initiate gradual movement of the hoop to a new random position within the game boundaries
	var targetX = Math.random() * (game.width - hoop.width) + hoop.width / 2;
	var targetY = game.height * 0.3 + Math.random() * game.height * 0.45; //Math.max(Math.random() * (game.height / 2) + 100, 780);
	var moveHoopInterval = LK.setInterval(function () {
		hoop.x += (targetX - hoop.x) * 0.05; // Move 5% of the distance per tick
		hoop.y += (targetY - hoop.y) * 0.05; // Move 5% of the distance per tick
		// Check if the hoop is close enough to the target position to stop
		if (Math.abs(hoop.x - targetX) < 1 && Math.abs(hoop.y - targetY) < 1) {
			hoop.setPosition(targetX, targetY); // Ensure hoop is exactly at target position
			LK.clearInterval(moveHoopInterval); // Stop the interval
			//console.log("Ok can handle score...");
			isHandlingScore = false;
			resetCollisionHandling();
		}
	}, 16); // Run every 16ms (~60FPS)
}
function popupMultiplier(value, x, y) {
	//console.log("popupMultiplier()...", value, x, y);
	// popup the asset corresponding to the value
	if (value < 2) {
		return;
	}
	var possibleValues = [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
	if (!possibleValues.includes(value)) {
		value = 999;
	}
	// Create and configure the x2 asset
	var popupOffset = 384;
	var popupSpeed = 60;
	var multiplierAsset = LK.getAsset('x' + value, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: Math.min(Math.max(x, popupOffset), game.width - popupOffset),
		y: Math.min(Math.max(y, popupOffset), game.height - popupOffset),
		width: 1,
		height: 1
	});
	game.addChild(multiplierAsset);
	// Animate the growth of the x2 asset to 1024x1024
	var growInterval = LK.setInterval(function () {
		multiplierAsset.width += popupSpeed; // Grow the width by 10% each tick
		multiplierAsset.height += popupSpeed;
		// Check if the asset has grown to or beyond 1024x1024
		if (multiplierAsset.width >= 1024 || multiplierAsset.height >= 1024) {
			LK.clearInterval(growInterval); // Stop the growth animation
			// Start fade out animation
			var fadeOutInterval = LK.setInterval(function () {
				multiplierAsset.alpha -= 0.05; // Reduce alpha to fade out
				if (multiplierAsset.alpha <= 0) {
					LK.clearInterval(fadeOutInterval); // Stop the fade out animation
					multiplierAsset.destroy(); // Destroy the asset after fading out
				}
			}, 4); // Run every 16ms (~60FPS)
		}
	}, 1); // Run every 16ms (~60FPS)
}
function popupBucket(isCombo) {
	console.log("popupBucket", isCombo);
	var popupSpeed = 60;
	var popupMaxSize = isCombo ? 4096 : 2048;
	var assetName = isCombo > 1 ? 'megaCombo' : isCombo ? 'superCombo' : 'bucket';
	var bucketAsset = LK.getAsset(assetName, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: game.width / 2,
		y: game.height * 0.75,
		width: 1,
		height: 1,
		alpha: 0.8
	});
	game.addChild(bucketAsset);
	// Animate the growth of the x2 asset to 1024x1024
	var growInterval = LK.setInterval(function () {
		bucketAsset.width += popupSpeed;
		bucketAsset.height += popupSpeed;
		// Check if the asset has grown to or beyond 1024x1024
		if (bucketAsset.width >= popupMaxSize || bucketAsset.height >= popupMaxSize) {
			LK.clearInterval(growInterval); // Stop the growth animation
			LK.setTimeout(function () {
				// Start fade out animation
				var fadeOutInterval = LK.setInterval(function () {
					bucketAsset.alpha -= 0.025; // Reduce alpha to fade out
					bucketAsset.rotation += 0.2; // Rotate the bucketAsset
					if (bucketAsset.alpha <= 0) {
						LK.clearInterval(fadeOutInterval); // Stop the fade out animation
						bucketAsset.destroy(); // Destroy the asset after fading out
					}
				}, 4); // Run every 16ms (~60FPS)
			}, 200);
		}
	}, 1); // Run every 16ms (~60FPS)
}
function swipeAnim() {
	// Don't show while game is running
	if (isGameRunning) {
		return;
	}
	// Start at the ball's position
	var startX = ball.x;
	var startY = ball.y - 400;
	// Create and configure the swipe asset
	var swipeAsset = LK.getAsset('swipe', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: startX,
		y: startY
	});
	game.addChild(swipeAsset);
	// Animate the swipe asset moving towards the center of the screen
	var targetY = game.height / 2;
	var targetXValues = [game.width * 0.25, game.width * 0.75];
	var targetXIndex = 0;
	var targetX = targetXValues[targetXIndex];
	targetXIndex = (targetXIndex + 1) % targetXValues.length;
	targetX = targetXValues[targetXIndex];
	LK.on('tick', function () {
		if (isGameRunning) {
			swipeAsset.destroy();
			return;
		}
		// Update targetX at the beginning of each tick if necessary
		var directionX = targetX - swipeAsset.x;
		var directionY = targetY - swipeAsset.y;
		var magnitude = Math.sqrt(directionX * directionX + directionY * directionY);
		var normalizedDirectionX = directionX / magnitude;
		var normalizedDirectionY = directionY / magnitude;
		// Calculate angle towards the target and update rotation of the swipe asset
		var angle = Math.atan2(directionY, directionX);
		swipeAsset.rotation = angle + Math.PI * 0.04 * Math.sign(directionX);
		// Move the swipe asset towards the center
		swipeAsset.x += normalizedDirectionX * 10; // Adjust speed as necessary
		swipeAsset.y += normalizedDirectionY * 10;
		// Reset position to ball's position if it reaches or overshoots the center
		if (Math.abs(swipeAsset.x - targetX) < 5 && Math.abs(swipeAsset.y - targetY) < 5) {
			targetXIndex = (targetXIndex + 1) % targetXValues.length;
			targetX = targetXValues[targetXIndex];
			swipeAsset.x = startX + (targetX - game.width * 0.5) / 2;
			swipeAsset.y = startY;
		}
	});
}
/* ********************************************************************************* */ 
/* ********************************** MAIN LOOP ************************************ */
/* ********************************************************************************* */ 
LK.on('tick', function () {
	if (!isGameRunning) {
		return;
	}
	ball.update();
	if (ball.intersects(hoop.hoopBorderLeft)) {
		if (!hoop.hoopBorderLeft.isHandling) {
			handleHoopBorder(hoop.hoopBorderLeft);
		}
	} else {
		hoop.hoopBorderLeft.isHandling = false;
	}
	if (ball.intersects(hoop.hoopBorderRight)) {
		if (!hoop.hoopBorderRight.isHandling) {
			handleHoopBorder(hoop.hoopBorderRight);
		}
	} else {
		hoop.hoopBorderRight.isHandling = false;
	}
	if (ball.intersects(hoop.hoopTopTrigger)) {
		if (!hoop.hoopTopTrigger.isHandling) {
			handleTopTrigger();
		}
	} else {
		hoop.hoopTopTrigger.isHandling = false;
	}
	if (ball.intersects(hoop.hoopBottomTrigger)) {
		if (!hoop.hoopBottomTrigger.isHandling) {
			handleBottomTrigger();
		}
	} else {
		hoop.hoopBottomTrigger.isHandling = false;
	}
	// Calculate distance between ball and hoop
	var distanceX = ball.x - hoop.x;
	var distanceY = ball.y - hoop.y;
	var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
	//console.log("Distance between ball and hoop:", distance);
	if (distance > 350) {
		isHandlingScore = false;
		resetCollisionHandling();
	}
});
initGame(); /**** 
* Classes
****/ 
/* ********************************************************************************* */ 
/* ********************************** BALL CLASS *********************************** */
/* ********************************************************************************* */ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('basketball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speedX = 0;
	self.speedY = 0;
	self.wallBounceSpeedRatio = 0.95;
	self.floorBounceRatio = 0.8;
	self.gravityAcceleration = 1.2;
	self.half = ballGraphics.width / 2;
	self.isMoving = false;
	self.launch = function (speedX, speedY) {
		self.speedX = speedX;
		self.speedY = speedY;
		self.isMoving = true;
	};
	self.update = function () {
		if (!self.isMoving) {
			return;
		}
		self.x += self.speedX;
		self.y += self.speedY;
		// Make the basketball spin only when moving
		if (self.speedX !== 0 || self.speedY !== 0) {
			ballGraphics.rotation += 0.1 * Math.sign(self.speedX);
		}
		// Gradually reduce horizontal speed
		// Apply friction to horizontal speed and limit to max speed
		self.speedX *= 0.99;
		self.speedX = Math.max(Math.min(self.speedX, maxSpeed), -maxSpeed); // Max speed limit
		// Enhanced gravity effect with gradual vertical speed reduction and limit to max speed
		self.speedY += self.gravityAcceleration;
		self.speedY = Math.max(Math.min(self.speedY, maxSpeed), -maxSpeed); // Max speed limit
		// Top boundary
		if (self.y <= 0 + self.half) {
			self.y = 0 + self.half;
			self.speedY *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, self.x, self.y);
		}
		// Bottom boundary
		if (ball.y > game.height - self.half) {
			ball.y = game.height - self.half;
			ball.speedY *= -1 * self.wallBounceSpeedRatio * self.floorBounceRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Left boundary
		if (ball.x < 0 + self.half) {
			ball.x = 0 + self.half;
			ball.speedX *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Right boundary
		if (ball.x > game.width - self.half) {
			ball.x = game.width - self.half;
			ball.speedX *= -1 * self.wallBounceSpeedRatio;
			bounceMultiplier *= 2;
			popupMultiplier(bounceMultiplier, ball.x, ball.y);
		}
		// Reset ball when in bottom and its speed is very low
		if (ball.y > game.height * 0.6 && Math.abs(self.speedX) < 5 && Math.abs(self.speedY) < 5) {
			self.reset();
			moveHoop();
		}
	};
	self.reset = function () {
		ballPassedAboveHoop = false;
		ballPassedInsideHoop = false;
		bounceMultiplier = 1; // Reset bounce counter
		self.x = game.width / 2;
		self.y = game.height - 300;
		self.speedX = 0;
		self.speedY = 0;
		self.isMoving = false;
		if (isGameOver) {
			isLastShotEnded = true;
		}
	};
});
/* ********************************************************************************* */ 
/* ******************************** CONFETTI CLASS ********************************* */
/* ********************************************************************************* */ 
// Confetti class for creating a confetti effect
var Confetti = Container.expand(function () {
	var self = Container.call(this);
	var confettiColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF];
	var confettiPieces = [];
	// Generate multiple confetti pieces
	for (var i = 0; i < 200; i++) {
		var color = confettiColors[Math.floor(Math.random() * confettiColors.length)];
		var confettiPiece = self.attachAsset('butter', {
			anchorX: 0.5,
			anchorY: 0.5,
			tint: color
		});
		confettiPiece.x = Math.random() * game.width * 2; // Spread across entire screen width
		confettiPiece.y = Math.random() * game.height * 2 - game.height; // Spread across entire screen height
		confettiPiece.scaleX = confettiPiece.scaleY = Math.random() * 0.5 + 0.5; // Random scale
		confettiPieces.push(confettiPiece);
	}
	// Animate confetti pieces
	self.animate = function () {
		confettiPieces.forEach(function (piece) {
			piece.y += Math.random() * 20 + 10; // Further increased fall speed
			piece.rotation += Math.random() * 0.2 - 0.1; // Random rotation
			// Remove piece if it goes off-screen
			if (piece.y > game.height + 50) {
				piece.destroy();
				confettiPieces.splice(confettiPieces.indexOf(piece), 1);
			}
		});
		// Stop animation and destroy confetti container if all pieces are gone
		if (confettiPieces.length === 0) {
			self.destroy();
		}
	};
});
/* ********************************************************************************* */ 
/* ********************************** HOOP CLASS *********************************** */
/* ********************************************************************************* */ 
var Hoop = Container.expand(function () {
	var self = Container.call(this);
	var hoopGraphics = self.attachAsset('hoop', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.setPosition = function (x, y) {
		self.x = x;
		self.y = y;
	};
	// Define hoopTrigger as a new Container object for better intersection detection
	self.hoopTopTrigger = new Container();
	self.hoopTopTrigger.isHandling = false;
	var hoopTriggerGraphics = self.hoopTopTrigger.attachAsset('hoopTrigger', {
		width: 200,
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopTriggerGraphics inside hoopTrigger container
	hoopTriggerGraphics.y = 0;
	// Position hoopTrigger container relative to the hoop
	self.hoopTopTrigger.y = -hoopGraphics.height / 2 + 60;
	// Add hoopTrigger container as a child of Hoop
	self.addChild(self.hoopTopTrigger);
	// Define hoopBottomTrigger as a new Container object for better intersection detection
	self.hoopBottomTrigger = new Container();
	self.hoopTopTrigger.isHandling = false;
	var hoopBottomTriggerGraphics = self.hoopBottomTrigger.attachAsset('hoopTrigger', {
		width: 300,
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0x0000ff
	});
	// Position hoopBottomTriggerGraphics inside hoopBottomTrigger container
	hoopBottomTriggerGraphics.y = 0;
	// Position hoopBottomTrigger container relative to the hoop
	self.hoopBottomTrigger.y = -hoopGraphics.height / 2 + 150;
	// Add hoopBottomTrigger container as a child of Hoop
	self.addChild(self.hoopBottomTrigger);
	// Define hoopBorderLeft as a new Container object for collision detection
	self.hoopBorderLeft = new Container();
	self.hoopBorderLeft.isHandling = false;
	var hoopBorderLeftGraphics = self.hoopBorderLeft.attachAsset('hoopBorder', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopBorderLeftGraphics inside hoopBorderLeft container
	hoopBorderLeftGraphics.y = 0;
	// Position hoopBorderLeft container relative to the hoop
	self.hoopBorderLeft.x = -hoopGraphics.width / 2 + 20;
	self.hoopBorderLeft.y = -hoopGraphics.height / 2 + 40;
	// Add hoopBorderLeft container as a child of Hoop
	self.addChild(self.hoopBorderLeft);
	// Define hoopBorderRight as a new Container object for collision detection
	self.hoopBorderRight = new Container();
	self.hoopBorderRight.isHandling = false;
	var hoopBorderRightGraphics = self.hoopBorderRight.attachAsset('hoopBorder', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Position hoopBorderRightGraphics inside hoopBorderRight container
	hoopBorderRightGraphics.y = 0;
	// Position hoopBorderRight container relative to the hoop
	self.hoopBorderRight.x = hoopGraphics.width / 2 - 20;
	self.hoopBorderRight.y = -hoopGraphics.height / 2 + 40;
	// Add hoopBorderRight container as a child of Hoop
	self.addChild(self.hoopBorderRight);
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({});
/**** 
* Game Code
****/ 
/* ********************************************************************************* */ 
/* ******************************* GAME VARIABLES ********************************** */
/* ********************************************************************************* */ 
var isGameRunning = false;
var isHandlingScore = false;
var bounceMultiplier = 1;
var currentShootBuckets = 0;
var maxSpeed = 100;
var ballPassedAboveHoop = false;
var ballPassedInsideHoop = false;
var timerSeconds = 6; // Set the initial timer value in seconds
var ball = null;
var hoop = null;
var score = 0;
var startPosition = null;
var isDebug = false;
// UI
var background = null;
var scoreTxt = null;
var timerTxt = null;
var timerLabelTxt = null;
var minShootSpeed = 30;
var timerInterval = null;
var timerOriginalWeigth = 94; // 1 char
var timerOriginalHeight = 174;
var isScoreAnimating = false;
var scoreAnimationInterval = null;
var previousScore = 0;
var originalScoreWidth = 92;
var originalScoreHeight = 174;
var isGameOver = false;
var isLastShotEnded = false;
/* ********************************************************************************* */ 
/* ******************************* INPUT HANDLERS ********************************** */
/* ********************************************************************************* */ 
game.on('down', function (obj) {
	if (isGameOver) {
		return;
	}
	var pos = obj.event.getLocalPosition(game);
	startPosition = pos;
	if (!isGameRunning) {
		isGameRunning = true;
	}
});
game.on('up', function (obj) {
	if (isGameOver) {
		return;
	}
	if (startPosition && !ball.isMoving) {
		var endPosition = obj.event.getLocalPosition(game);
		var speedX = Math.max(Math.min((endPosition.x - startPosition.x) * 0.1, maxSpeed), -maxSpeed);
		var speedY = Math.max(Math.min((endPosition.y - startPosition.y) * 0.1, maxSpeed), -maxSpeed);
		if (Math.abs(speedX) >= minShootSpeed || Math.abs(speedY) >= minShootSpeed) {
			//console.log("============================= SHOOT ===========================");
			currentShootBuckets = 0;
			ball.launch(speedX, speedY);
		}
		startPosition = null;
	}
});
/* ********************************************************************************* */ 
/* ********************************** GAME FUNCTIONS ************************************ */
/* ********************************************************************************* */ 
function initGame() {
	// Background
	var background = LK.getAsset('background', {
		anchorX: 0.0,
		anchorY: 0.0,
		x: 0,
		y: 0
	});
	game.addChild(background);
	// Score UI
	// Create and configure the 'Score' label text
	var scoreLabelTxt = new Text2('Score', {
		size: 50,
		fill: "#006400",
		weight: 1000,
		dropShadow: true
	});
	scoreLabelTxt.anchor.set(0.5, 0.25);
	LK.gui.top.addChild(scoreLabelTxt);
	scoreTxt = new Text2(score.toString(), {
		size: 150,
		fill: "#006400",
		weight: 1000,
		dropShadow: true
	});
	scoreTxt.anchor.set(0.5, -0.150);
	LK.gui.top.addChild(scoreTxt);
	// Timer UI
	timerLabelTxt = new Text2('Time', {
		size: 50,
		fill: "#FFFFFF",
		weight: 1000,
		dropShadow: true
	});
	timerLabelTxt.tint = 0x646464;
	timerLabelTxt.anchor.set(1.4, 0.25);
	LK.gui.topRight.addChild(timerLabelTxt);
	timerTxt = new Text2(timerSeconds.toString(), {
		size: 150,
		fill: "#FFFFFF",
		weight: 1000,
		dropShadow: true
	});
	timerTxt.tint = timerSeconds <= 5 ? 0xff0000 : 0x646464;
	timerTxt.anchor.set(1.10, -0.150);
	LK.gui.topRight.addChild(timerTxt);
	// Update the timer every second
	timerInterval = LK.setInterval(handleTimer, 1000); // Set the interval to update every 1000ms (1 second)
	ball = game.addChild(new Ball());
	ball.reset();
	hoop = game.addChild(new Hoop());
	if (!isDebug) {
		hoop.hoopTopTrigger.alpha = 0;
		hoop.hoopBottomTrigger.alpha = 0;
		hoop.hoopBorderLeft.alpha = 0;
		hoop.hoopBorderRight.alpha = 0;
	}
	hoop.setPosition(game.width / 2, 1024); // Position the hoop at the top center
	swipeAnim();
}
function handleTimer() {
	if (!isGameRunning) {
		return;
	}
	timerSeconds -= 1; // Decrement the timer by one second
	timerTxt.setText(timerSeconds.toString()); // Update the timer display with conditional color change
	var animateTimer = null;
	if (timerSeconds < 10) {
		timerTxt.anchor.set(1.6, -0.150);
	}
	if (timerSeconds <= 5 && timerSeconds > 0) {
		var maxTimerLabelSize = 200 + (5 - timerSeconds) * 20;
		timerTxt.tint = 0xff0000;
		timerLabelTxt.tint = 0xff0000;
		// Animate timerTxt width and height
		var growDirection = 1;
		animateTimer = LK.setInterval(function () {
			timerTxt.width += growDirection * 4;
			timerTxt.height += growDirection * 4;
			if (timerTxt.width >= maxTimerLabelSize || timerTxt.height >= maxTimerLabelSize || timerTxt.width <= 100 || timerTxt.height <= 100) {
				growDirection *= -1;
			}
		}, 16); // Run every 16ms (~60FPS)
	} else {
		timerTxt.tint = 0x646464;
	}
	if (timerSeconds <= 0) {
		timerTxt.tint = 0x646464;
		timerLabelTxt.tint = 0x646464;
		timerTxt.width = timerOriginalWeigth;
		timerTxt.height = timerOriginalHeight;
		LK.clearInterval(animateTimer);
		isGameOver = true;
	}
	if (isGameOver && isLastShotEnded) {
		LK.clearInterval(timerInterval); // Stop the timer when it reaches 0
		LK.setScore(score); // Save the final score using the platform's tool
		LK.showGameOver(); // Show game over screen
	}
}
function handleTopTrigger() {
	//console.log("Top trigger. speed", ball.speedY);
	hoop.hoopTopTrigger.isHandling = true;
	if (ball.speedY > 0) {
		ballPassedAboveHoop = true;
	}
}
function handleBottomTrigger() {
	//console.log("Bottom trigger", ball.speedY.toFixed(2), ball.x.toFixed(2), hoop.hoopBorderLeft.x.toFixed(2), hoop.hoopBorderRight.x.toFixed(2));
	hoop.hoopBottomTrigger.isHandling = true;
	var leftBorderX = hoop.x + hoop.hoopBorderLeft.x;
	var rightBorderX = hoop.x + hoop.hoopBorderRight.x;
	if (ballPassedAboveHoop && ball.x > leftBorderX && ball.x < rightBorderX) {
		if (ball.speedY > 0) {
			//console.log("--------------- SCORE!!! -----------------");
			ballPassedInsideHoop = true;
			handleScore();
		}
	} else if (ball.speedY < 0) {
		//console.log("touch hoop from bottom");
		ball.speedY *= -0.98;
		ballPassedAboveHoop = false;
		ballPassedInsideHoop = false;
	}
}
function handleHoopBorder(border) {
	//console.log("handleHoopBorder");
	border.isHandling = true;
	// Check if the ball has hit the left or right border
	if (ball.x <= border.x || ball.x >= border.x + border.width) {
		ball.speedX *= -1; // Reverse the x direction
	}
	// Check if the ball has hit the top or bottom border
	if (ball.y <= border.y || ball.y >= border.y + border.height) {
		//ball.speedY *= -1; // Reverse the y direction ???
	}
}
function resetCollisionHandling() {
	//console.log("resetCollisionHandling...");
	hoop.hoopTopTrigger.isHandling = false;
	hoop.hoopBottomTrigger.isHandling = false;
	hoop.hoopBorderLeft.isHandling = false;
	hoop.hoopBorderRight.isHandling = false;
}
// Fonction pour normaliser un vecteur
function normalize(vector) {
	var magnitude = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
	return {
		x: vector.x / magnitude,
		y: vector.y / magnitude
	};
}
function handleScore() {
	if (isHandlingScore) {
		return;
	}
	//console.log("handleScore...bounceMultiplier=", bounceMultiplier, "*", currentShootBuckets);
	isHandlingScore = true;
	currentShootBuckets++;
	score += 10 * bounceMultiplier + 10 * bounceMultiplier * (currentShootBuckets - 1) * (currentShootBuckets - 1); // Add bounce counter to score
	scoreTxt.setText(score.toString());
	animateScore();
	popupBucket(currentShootBuckets - 1);
	ballPassedAboveHoop = false; // Reset the condition after scoring
	ballPassedInsideHoop = false;
	// Create and add confetti effect to the game
	var confetti = game.addChild(new Confetti());
	confetti.x = 0; // Position confetti at the hoop's position
	confetti.y = 0;
	LK.on('tick', function () {
		confetti.animate(); // Animate confetti
	});
}
function animateScore() {
	if (isScoreAnimating) {
		LK.clearInterval(scoreAnimationInterval);
		scoreTxt.width = originalScoreWidth * score.toString().length;
		scoreTxt.height = originalScoreHeight;
		isScoreAnimating = false;
	}
	isScoreAnimating = true;
	var scoreSizeDirection = 1;
	//console.log("score " + score, " / l=" + score.toString().length, " w,h=" + originalScoreWidth + "," + originalScoreHeight);
	var maxScoreWidth = 300 * score.toString().length; // Maximum size to grow to
	var maxScoreHeight = 300;
	var minScoreSize = 100; // Minimum size to shrink to
	scoreAnimationInterval = LK.setInterval(function () {
		scoreTxt.width += scoreSizeDirection * 5; // Adjust width by 5 pixels per frame
		scoreTxt.height += scoreSizeDirection * 5; // Adjust height by 5 pixels per frame
		// Reverse direction if the score text reaches max or min size
		if (scoreTxt.width >= maxScoreWidth || scoreTxt.height >= maxScoreHeight || scoreTxt.width <= minScoreSize || scoreTxt.height <= minScoreSize) {
			scoreSizeDirection *= -1;
		}
		// Restore original size and clear interval when animation is done
		if (scoreTxt.width <= originalScoreWidth * score.toString().length && scoreTxt.height <= originalScoreHeight) {
			LK.clearInterval(scoreAnimationInterval);
			scoreTxt.width = originalScoreWidth * score.toString().length;
			scoreTxt.height = originalScoreHeight;
			isScoreAnimating = false;
		}
	}, 20); // Run every 16ms (~60FPS)
}
function moveHoop() {
	//console.log("moveHoop...");
	// Initiate gradual movement of the hoop to a new random position within the game boundaries
	var targetX = Math.random() * (game.width - hoop.width) + hoop.width / 2;
	var targetY = game.height * 0.3 + Math.random() * game.height * 0.45; //Math.max(Math.random() * (game.height / 2) + 100, 780);
	var moveHoopInterval = LK.setInterval(function () {
		hoop.x += (targetX - hoop.x) * 0.05; // Move 5% of the distance per tick
		hoop.y += (targetY - hoop.y) * 0.05; // Move 5% of the distance per tick
		// Check if the hoop is close enough to the target position to stop
		if (Math.abs(hoop.x - targetX) < 1 && Math.abs(hoop.y - targetY) < 1) {
			hoop.setPosition(targetX, targetY); // Ensure hoop is exactly at target position
			LK.clearInterval(moveHoopInterval); // Stop the interval
			//console.log("Ok can handle score...");
			isHandlingScore = false;
			resetCollisionHandling();
		}
	}, 16); // Run every 16ms (~60FPS)
}
function popupMultiplier(value, x, y) {
	//console.log("popupMultiplier()...", value, x, y);
	// popup the asset corresponding to the value
	if (value < 2) {
		return;
	}
	var possibleValues = [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
	if (!possibleValues.includes(value)) {
		value = 999;
	}
	// Create and configure the x2 asset
	var popupOffset = 384;
	var popupSpeed = 60;
	var multiplierAsset = LK.getAsset('x' + value, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: Math.min(Math.max(x, popupOffset), game.width - popupOffset),
		y: Math.min(Math.max(y, popupOffset), game.height - popupOffset),
		width: 1,
		height: 1
	});
	game.addChild(multiplierAsset);
	// Animate the growth of the x2 asset to 1024x1024
	var growInterval = LK.setInterval(function () {
		multiplierAsset.width += popupSpeed; // Grow the width by 10% each tick
		multiplierAsset.height += popupSpeed;
		// Check if the asset has grown to or beyond 1024x1024
		if (multiplierAsset.width >= 1024 || multiplierAsset.height >= 1024) {
			LK.clearInterval(growInterval); // Stop the growth animation
			// Start fade out animation
			var fadeOutInterval = LK.setInterval(function () {
				multiplierAsset.alpha -= 0.05; // Reduce alpha to fade out
				if (multiplierAsset.alpha <= 0) {
					LK.clearInterval(fadeOutInterval); // Stop the fade out animation
					multiplierAsset.destroy(); // Destroy the asset after fading out
				}
			}, 4); // Run every 16ms (~60FPS)
		}
	}, 1); // Run every 16ms (~60FPS)
}
function popupBucket(isCombo) {
	console.log("popupBucket", isCombo);
	var popupSpeed = 60;
	var popupMaxSize = isCombo ? 4096 : 2048;
	var assetName = isCombo > 1 ? 'megaCombo' : isCombo ? 'superCombo' : 'bucket';
	var bucketAsset = LK.getAsset(assetName, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: game.width / 2,
		y: game.height * 0.75,
		width: 1,
		height: 1,
		alpha: 0.8
	});
	game.addChild(bucketAsset);
	// Animate the growth of the x2 asset to 1024x1024
	var growInterval = LK.setInterval(function () {
		bucketAsset.width += popupSpeed;
		bucketAsset.height += popupSpeed;
		// Check if the asset has grown to or beyond 1024x1024
		if (bucketAsset.width >= popupMaxSize || bucketAsset.height >= popupMaxSize) {
			LK.clearInterval(growInterval); // Stop the growth animation
			LK.setTimeout(function () {
				// Start fade out animation
				var fadeOutInterval = LK.setInterval(function () {
					bucketAsset.alpha -= 0.025; // Reduce alpha to fade out
					bucketAsset.rotation += 0.2; // Rotate the bucketAsset
					if (bucketAsset.alpha <= 0) {
						LK.clearInterval(fadeOutInterval); // Stop the fade out animation
						bucketAsset.destroy(); // Destroy the asset after fading out
					}
				}, 4); // Run every 16ms (~60FPS)
			}, 200);
		}
	}, 1); // Run every 16ms (~60FPS)
}
function swipeAnim() {
	// Don't show while game is running
	if (isGameRunning) {
		return;
	}
	// Start at the ball's position
	var startX = ball.x;
	var startY = ball.y - 400;
	// Create and configure the swipe asset
	var swipeAsset = LK.getAsset('swipe', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: startX,
		y: startY
	});
	game.addChild(swipeAsset);
	// Animate the swipe asset moving towards the center of the screen
	var targetY = game.height / 2;
	var targetXValues = [game.width * 0.25, game.width * 0.75];
	var targetXIndex = 0;
	var targetX = targetXValues[targetXIndex];
	targetXIndex = (targetXIndex + 1) % targetXValues.length;
	targetX = targetXValues[targetXIndex];
	LK.on('tick', function () {
		if (isGameRunning) {
			swipeAsset.destroy();
			return;
		}
		// Update targetX at the beginning of each tick if necessary
		var directionX = targetX - swipeAsset.x;
		var directionY = targetY - swipeAsset.y;
		var magnitude = Math.sqrt(directionX * directionX + directionY * directionY);
		var normalizedDirectionX = directionX / magnitude;
		var normalizedDirectionY = directionY / magnitude;
		// Calculate angle towards the target and update rotation of the swipe asset
		var angle = Math.atan2(directionY, directionX);
		swipeAsset.rotation = angle + Math.PI * 0.04 * Math.sign(directionX);
		// Move the swipe asset towards the center
		swipeAsset.x += normalizedDirectionX * 10; // Adjust speed as necessary
		swipeAsset.y += normalizedDirectionY * 10;
		// Reset position to ball's position if it reaches or overshoots the center
		if (Math.abs(swipeAsset.x - targetX) < 5 && Math.abs(swipeAsset.y - targetY) < 5) {
			targetXIndex = (targetXIndex + 1) % targetXValues.length;
			targetX = targetXValues[targetXIndex];
			swipeAsset.x = startX + (targetX - game.width * 0.5) / 2;
			swipeAsset.y = startY;
		}
	});
}
/* ********************************************************************************* */ 
/* ********************************** MAIN LOOP ************************************ */
/* ********************************************************************************* */ 
LK.on('tick', function () {
	if (!isGameRunning) {
		return;
	}
	ball.update();
	if (ball.intersects(hoop.hoopBorderLeft)) {
		if (!hoop.hoopBorderLeft.isHandling) {
			handleHoopBorder(hoop.hoopBorderLeft);
		}
	} else {
		hoop.hoopBorderLeft.isHandling = false;
	}
	if (ball.intersects(hoop.hoopBorderRight)) {
		if (!hoop.hoopBorderRight.isHandling) {
			handleHoopBorder(hoop.hoopBorderRight);
		}
	} else {
		hoop.hoopBorderRight.isHandling = false;
	}
	if (ball.intersects(hoop.hoopTopTrigger)) {
		if (!hoop.hoopTopTrigger.isHandling) {
			handleTopTrigger();
		}
	} else {
		hoop.hoopTopTrigger.isHandling = false;
	}
	if (ball.intersects(hoop.hoopBottomTrigger)) {
		if (!hoop.hoopBottomTrigger.isHandling) {
			handleBottomTrigger();
		}
	} else {
		hoop.hoopBottomTrigger.isHandling = false;
	}
	// Calculate distance between ball and hoop
	var distanceX = ball.x - hoop.x;
	var distanceY = ball.y - hoop.y;
	var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
	//console.log("Distance between ball and hoop:", distance);
	if (distance > 350) {
		isHandlingScore = false;
		resetCollisionHandling();
	}
});
initGame();