/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	self.hasScored = false;
	self.hasBounced = false;
	var ballGraphics = LK.getAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.addChild(ballGraphics);
	self.speed = {
		x: 0,
		y: 0
	};
	self.hasThrown = false;
	self._move_migrated = function () {
		self.speed.y += 3.2;
		self.x += self.speed.x;
		self.y += self.speed.y;
		self.rotation += self.speed.x * 0.01;
		if (self.hasThrown) {
			var targetScale = 0.8;
			self.scale.x += (targetScale - self.scale.x) * 0.05;
			self.scale.y += (targetScale - self.scale.y) * 0.05;
		}
		if (self.hasScored) {
			self.alpha -= 0.15;
		} else {
			self.alpha += 0.15;
			if (self.alpha > 1) {
				self.alpha = 1;
			}
		}
	};
	self.bounceOffPoint = function (x, y, elasticity) {
		var dx = self.x - x;
		var dy = self.y - y;
		var angle = Math.atan2(dy, dx);
		var speed = Math.sqrt(self.speed.x * self.speed.x + self.speed.y * self.speed.y);
		self.speed.x = Math.cos(angle) * speed * elasticity;
		self.speed.y = Math.sin(angle) * speed * elasticity;
	};
	self.angleTo = function (x, y) {
		var dx = self.x - x;
		var dy = self.y - y;
		return Math.atan2(dy, dx);
	};
	self.distanceTo = function (x, y) {
		var dx = self.x - x;
		var dy = self.y - y;
		return Math.sqrt(dx * dx + dy * dy);
	};
	self.moveToDistance = function (x, y, distance) {
		var angle = self.angleTo(x, y);
		self.x = x + Math.cos(angle) * (distance * 1.05);
		self.y = y + Math.sin(angle) * (distance * 1.05);
	};
});
var Hoop = Container.expand(function () {
	var self = Container.call(this);
	self.setScore = function (score) {
		self.scoreLabel.setText(score.toString());
	};
	self.moveTo = function (newX, newY, hoopRim) {
		var dx = (newX - self.x) / 60;
		var dy = (newY - self.y) / 60;
		var steps = 0;
		var interval = LK.setInterval(function () {
			self.x += dx;
			self.y += dy;
			hoopRim.x = self.x;
			hoopRim.y = self.y + self.children[1].y - 250;
			steps++;
			if (steps >= 60) {
				LK.clearInterval(interval);
			}
		});
	};
	var backboardGraphics = LK.getAsset('backboard', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backboardGraphics.y -= 250;
	self.addChild(backboardGraphics);
	self.hoopRimGraphics = LK.getAsset('hoopRim', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.hoopRimGraphics.y = backboardGraphics.height / 2 - 550 + 20 + 120 + 150 + 100;
	self.hoopRimGraphics.alpha = 0;
	self.addChild(self.hoopRimGraphics);
	self.leftElement = LK.getAsset('leftElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.leftElement.x = self.hoopRimGraphics.x - self.hoopRimGraphics.width / 2 + self.leftElement.width / 2 - 50;
	self.leftElement.y = self.hoopRimGraphics.y - 250;
	self.leftElement.alpha = 0;
	self.addChild(self.leftElement);
	self.rightElement = LK.getAsset('rightElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.rightElement.x = self.hoopRimGraphics.x + self.hoopRimGraphics.width / 2 - self.rightElement.width / 2 + 50;
	self.rightElement.y = self.hoopRimGraphics.y - 250;
	self.rightElement.alpha = 0;
	self.addChild(self.rightElement);
	self.hoopOutlineGraphics = LK.getAsset('hoopOutline', {
		anchorX: 1,
		anchorY: 0.5
	});
	self.hoopOutlineGraphics.y = self.hoopRimGraphics.y - 230;
	self.hoopOutlineGraphics.alpha = 1;
	self.hoopOutlineGraphics.tint = 0xbb502e;
	self.hoopOutlineGraphics.rotation = Math.PI / 2;
	self.addChild(self.hoopOutlineGraphics);
	self.multiplierLabel = new Text2('', {
		size: 200,
		fill: '#8d4529',
		font: 'Impact'
	});
	self.multiplierLabel.anchor.set(.5, 1);
	self.multiplierLabel.x = self.hoopRimGraphics.x;
	self.multiplierLabel.y = self.hoopRimGraphics.y - 250 - 50 + 30;
	self.addChild(self.multiplierLabel);
	self.scoreLabel = new Text2('0', {
		size: 270,
		fill: '#4b190c',
		font: 'Impact'
	});
	self.scoreLabel.anchor.set(.5, .5);
	self.scoreLabel.x = self.hoopRimGraphics.x;
	self.scoreLabel.y = self.hoopRimGraphics.y - 250 - 20 - 420;
	self.addChild(self.scoreLabel);
});
var HoopRim = Container.expand(function () {
	var self = Container.call(this);
	var hoopRimGraphics = LK.getAsset('hoopRimSeparate', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.addChild(hoopRimGraphics);
});
var Particle = Container.expand(function () {
	var self = Container.call(this);
	self.interactive = false;
	var particleGraphics = self.attachAsset('fireParticle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	particleGraphics.blendMode = 1;
	self.lifeSpan = 60;
	self.speed = {
		x: (Math.random() - 0.5) * 2,
		y: (Math.random() - 0.5) * 2
	};
	self.scale.set(Math.random() * 0.6 + 0.2);
	self.rotation = Math.random() * Math.PI * 2;
	self._move_migrated = function () {
		self.x += self.speed.x;
		self.y += self.speed.y;
		self.alpha -= 0.03;
		if (self.alpha <= 0) {
			self.destroy();
		}
	};
});
var Timer = Container.expand(function () {
	var self = Container.call(this);
	self.timerLabel = new Text2('120', {
		size: 150,
		fill: '#ffffff',
		font: 'Impact'
	});
	self.timerLabel.anchor.set(0.5, 0.5);
	self.addChild(self.timerLabel);
	self.timeLeft = 120;
	self.gameEnded = false;
	self.setTime = function (time) {
		self.timeLeft = time;
		self.timerLabel.setText(Math.ceil(self.timeLeft).toString());
		// Flash red when time is low
		if (self.timeLeft <= 10) {
			tween(self.timerLabel, {
				tint: 0xff0000
			}, {
				duration: 200,
				onFinish: function onFinish() {
					tween(self.timerLabel, {
						tint: 0xffffff
					}, {
						duration: 200
					});
				}
			});
		}
	};
	self.update = function () {
		if (self.timeLeft > 0 && !self.gameEnded) {
			self.timeLeft -= 1 / 60; // Decrease by 1 second every 60 frames
			self.setTime(self.timeLeft);
			if (self.timeLeft <= 0) {
				self.gameEnded = true;
				// Save high score
				if (score > (storage.highScore || 0)) {
					storage.highScore = score;
				}
				LK.showGameOver();
			}
		}
	};
	return self;
});
var TitleText = Container.expand(function () {
	var self = Container.call(this);
	self.titleLabel = new Text2("TIME ATTACK!", {
		size: 200,
		fill: 0x0,
		font: "Impact"
	});
	self.titleLabel.anchor.set(0.5, 0.5);
	self.addChild(self.titleLabel);
	self.subtitleLabel = new Text2("Throw ball to start", {
		size: 100,
		fill: 0x0,
		font: "Impact"
	});
	self.subtitleLabel.anchor.set(0.5, 0.5);
	self.subtitleLabel.y = self.titleLabel.y + 150;
	self.addChild(self.subtitleLabel);
	self.fadeOut = function () {
		tween(self, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x477096
});
/**** 
* Game Code
****/ 
// Import plugins
var bg = LK.getAsset('background', {
	anchorX: 0.5,
	anchorY: 0.5
});
bg.x = 2048 / 2;
bg.y = 2732 / 2 + 150;
bg.alpha = 0.7;
game.addChild(bg);
// Play background music
LK.playMusic('basketball', {
	fade: {
		start: 0,
		end: 1,
		duration: 1000
	}
});
var hoop = game.addChild(new Hoop());
var score = 0;
var scoreMultiplier = 1;
// Create title screen
var titleScreen = new TitleText();
titleScreen.x = 2048 / 2;
titleScreen.y = 2732 / 2 - 300;
game.addChild(titleScreen);
// Create timer
var timer = new Timer();
timer.x = 2048 / 2;
timer.y = 150;
timer.timeLeft = 120; // Set initial time to 120 seconds
timer.gameEnded = true; // Pause timer initially until first throw
game.addChild(timer);
// Display high score
var highScoreLabel = new Text2('Best: ' + (storage.highScore || 0), {
	size: 80,
	fill: '#ffffff',
	font: 'Impact'
});
highScoreLabel.anchor.set(1, 0);
highScoreLabel.x = 2048 - 40;
highScoreLabel.y = 40;
game.addChild(highScoreLabel);
var ballShadow = LK.getAsset('ballShadow', {
	anchorX: 0.5,
	anchorY: 0.5
});
ballShadow.alpha = 0.5;
game.addChild(ballShadow);
var ball = game.addChild(new Ball());
var hoopRim = game.addChild(new HoopRim());
ball.hitElement = '';
hoop.x = 2048 / 2;
hoop.y = 2732 / 2;
hoopRim.x = hoop.x;
hoopRim.y = hoop.y + hoop.children[1].y - 250;
ball.x = 2048 / 2;
ball.on('down', function (x, y, obj) {
	if (!ball.hasThrown) {
		var event = obj;
		dragStart = game.toLocal(event.global);
	}
});
var dragStart = null;
game.on('move', function (x, y, obj) {
	var event = obj;
	var pos = game.toLocal(event.global);
	if (dragStart !== null && ball.distanceTo(pos.x, pos.y) > 400) {
		game.fireBall(obj);
	}
});
game.fireBall = function (obj) {
	if (dragStart !== null) {
		var event = obj.event;
		var pos = game.toLocal(event.global);
		var dx = pos.x - dragStart.x;
		var dy = pos.y - dragStart.y;
		var angle = Math.atan2(dy, dx);
		ball.speed.x = Math.cos(angle) * 72 * 1.76 * 0.9 / 3;
		ball.speed.y = Math.sin(angle) * 72 * 1.76 * 0.9;
		ball.hasThrown = true;
		ball.hitElement = '';
		game.removeChild(ball);
		game.addChild(ball);
		dragStart = null;
		// Play throw sound
		LK.getSound('throwSound').play();
		// Start timer on first throw if it's not already running
		if (timer.gameEnded) {
			timer.gameEnded = false;
			timer.timeLeft = 120; // Reset to ensure full 120 seconds
			timer.setTime(timer.timeLeft);
			titleScreen.fadeOut(); // Hide the title screen
		}
	}
};
game.on('up', function (x, y, obj) {
	if (dragStart !== null) {
		var event = obj;
		var pos = game.toLocal(event.global);
		var distance = Math.sqrt(Math.pow(pos.x - dragStart.x, 2) + Math.pow(pos.y - dragStart.y, 2));
		if (distance > 150) {
			game.fireBall(obj);
		}
	}
	dragStart = null;
});
var floorY = 2732 - 40 + 900 * (ball.scale.y - 1);
ball.y = floorY - ball.height;
LK.on('tick', function () {
	// Update timer
	timer.update();
	if (scoreMultiplier === 3) {
		for (var i = 0; i < 2; i++) {
			var particle = new Particle();
			particle.alpha = ball.alpha;
			var angle = Math.random() * Math.PI * 2;
			var radius = ball.width * 0.5 * Math.sqrt(Math.random());
			particle.x = ball.x + Math.cos(angle) * radius;
			particle.y = ball.y + Math.sin(angle) * radius;
			game.addChild(particle);
		}
	}
	game.children.forEach(function (child) {
		if (child instanceof Particle) {
			child._move_migrated();
		}
	});
	var floorY = 2732 - 40 + 900 * (ball.scale.y - 1);
	ball._move_migrated();
	if (ball.speed.y > 0) {
		game.removeChild(hoopRim);
		game.addChild(hoopRim);
		if (ball.distanceTo(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y) < ball.width / 2 + hoop.leftElement.width / 2) {
			ball.moveToDistance(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y, ball.width / 2 + hoop.leftElement.width / 2 + 1);
			ball.bounceOffPoint(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y, 0.5);
			ball.hitElement = 'left';
		}
		if (ball.distanceTo(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y) < ball.width / 2 + hoop.rightElement.width / 2) {
			ball.moveToDistance(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y, ball.width / 2 + hoop.rightElement.width / 2 + 1);
			ball.bounceOffPoint(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y, 0.5);
			ball.hitElement = 'right';
		}
	}
	ballShadow.x = ball.x;
	ballShadow.y = 1800 + ball.height / 2 + 500 * ball.scale.x;
	var scale = (1 - 2 * (ball.y - 2732 + ball.height) / 2732) * ball.scale.x;
	ballShadow.scale.set(scale);
	ballShadow.alpha = (1 - scale + 1) / 2 * ball.alpha;
	if (ball.y + ball.height > floorY) {
		ball.y = floorY - ball.height;
		ball.speed.y *= -0.75;
		ballShadow.x = ball.x;
		ballShadow.visible = true;
		if (ball.hasThrown && !ball.hasScored) {
			if (!ball.hasBounced) {
				ball.hasBounced = true;
			} else if (timer.timeLeft <= 0) {
				LK.showGameOver();
			} else {
				// Play miss sound
				LK.getSound('missSound').play();
				// Create a new ball after it has bounced without scoring
				ball.x = 2048 / 2;
				ball.y = 2532 - ball.height;
				ball.speed.x = 0;
				ball.speed.y = 0;
				ball.hasThrown = false;
				ball.hasScored = false;
				ball.hasBounced = false;
				ball.scale.x = 1;
				ball.scale.y = 1;
				ball.alpha = 1;
				ball.hitElement = '';
				scoreMultiplier = 1;
				hoop.multiplierLabel.setText('');
				// Play whistle sound when new ball is ready
				LK.getSound('whistleSound').play();
			}
		} else if (ball.hasScored) {
			ball.x = 2048 / 2;
			ball.y = 2532 - ball.height;
			ball.speed.x = 0;
			ball.speed.y = 0;
			ball.hasThrown = false;
			ball.hasScored = false;
			ball.hasBounced = false;
			ball.scale.x = 1;
			ball.scale.y = 1;
			if (ball.hitElement === '') {
				if (scoreMultiplier < 3) {
					scoreMultiplier++;
				}
			} else {
				scoreMultiplier = 1;
			}
			if (scoreMultiplier > 1) {
				hoop.multiplierLabel.setText('x' + scoreMultiplier);
			} else {
				hoop.multiplierLabel.setText('');
			}
			ball.hitElement = '';
			// Play whistle sound when new ball is ready after scoring
			LK.getSound('whistleSound').play();
			hoop.moveTo(Math.random() * (2048 - 1000) + 500, Math.random() * (2732 - 2000) + 1000, hoopRim);
		}
	}
	if (ball.x + ball.width / 2 < 0 || ball.x - ball.width / 2 > 2048) {
		if (timer.timeLeft <= 0) {
			LK.showGameOver();
		} else {
			// Play miss sound for out of bounds
			LK.getSound('missSound').play();
			// Create a new ball if the ball goes out of bounds
			ball.x = 2048 / 2;
			ball.y = 2532 - ball.height;
			ball.speed.x = 0;
			ball.speed.y = 0;
			ball.hasThrown = false;
			ball.hasScored = false;
			ball.hasBounced = false;
			ball.scale.x = 1;
			ball.scale.y = 1;
			ball.alpha = 1;
			ball.hitElement = '';
			scoreMultiplier = 1;
			hoop.multiplierLabel.setText('');
			// Play whistle sound when new ball is ready after going out of bounds
			LK.getSound('whistleSound').play();
		}
	} else if (ball.intersects(hoop.hoopRimGraphics) && ball.speed.y > 0 && !ball.hasScored && !ball.hasBounced && ball.x > hoop.x + hoop.leftElement.x && ball.x < hoop.x + hoop.rightElement.x) {
		ball.hasScored = true;
		score += scoreMultiplier;
		LK.setScore(score);
		hoop.scoreLabel.setText(score.toString());
		// Play score sound
		LK.getSound('scoreSound').play();
		// Update high score display if needed
		if (score > (storage.highScore || 0)) {
			storage.highScore = score;
			highScoreLabel.setText('Best: ' + score);
			// Animate high score update
			tween(highScoreLabel, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: 300,
				onFinish: function onFinish() {
					tween(highScoreLabel, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300
					});
				}
			});
		}
	}
}); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	self.hasScored = false;
	self.hasBounced = false;
	var ballGraphics = LK.getAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.addChild(ballGraphics);
	self.speed = {
		x: 0,
		y: 0
	};
	self.hasThrown = false;
	self._move_migrated = function () {
		self.speed.y += 3.2;
		self.x += self.speed.x;
		self.y += self.speed.y;
		self.rotation += self.speed.x * 0.01;
		if (self.hasThrown) {
			var targetScale = 0.8;
			self.scale.x += (targetScale - self.scale.x) * 0.05;
			self.scale.y += (targetScale - self.scale.y) * 0.05;
		}
		if (self.hasScored) {
			self.alpha -= 0.15;
		} else {
			self.alpha += 0.15;
			if (self.alpha > 1) {
				self.alpha = 1;
			}
		}
	};
	self.bounceOffPoint = function (x, y, elasticity) {
		var dx = self.x - x;
		var dy = self.y - y;
		var angle = Math.atan2(dy, dx);
		var speed = Math.sqrt(self.speed.x * self.speed.x + self.speed.y * self.speed.y);
		self.speed.x = Math.cos(angle) * speed * elasticity;
		self.speed.y = Math.sin(angle) * speed * elasticity;
	};
	self.angleTo = function (x, y) {
		var dx = self.x - x;
		var dy = self.y - y;
		return Math.atan2(dy, dx);
	};
	self.distanceTo = function (x, y) {
		var dx = self.x - x;
		var dy = self.y - y;
		return Math.sqrt(dx * dx + dy * dy);
	};
	self.moveToDistance = function (x, y, distance) {
		var angle = self.angleTo(x, y);
		self.x = x + Math.cos(angle) * (distance * 1.05);
		self.y = y + Math.sin(angle) * (distance * 1.05);
	};
});
var Hoop = Container.expand(function () {
	var self = Container.call(this);
	self.setScore = function (score) {
		self.scoreLabel.setText(score.toString());
	};
	self.moveTo = function (newX, newY, hoopRim) {
		var dx = (newX - self.x) / 60;
		var dy = (newY - self.y) / 60;
		var steps = 0;
		var interval = LK.setInterval(function () {
			self.x += dx;
			self.y += dy;
			hoopRim.x = self.x;
			hoopRim.y = self.y + self.children[1].y - 250;
			steps++;
			if (steps >= 60) {
				LK.clearInterval(interval);
			}
		});
	};
	var backboardGraphics = LK.getAsset('backboard', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backboardGraphics.y -= 250;
	self.addChild(backboardGraphics);
	self.hoopRimGraphics = LK.getAsset('hoopRim', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.hoopRimGraphics.y = backboardGraphics.height / 2 - 550 + 20 + 120 + 150 + 100;
	self.hoopRimGraphics.alpha = 0;
	self.addChild(self.hoopRimGraphics);
	self.leftElement = LK.getAsset('leftElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.leftElement.x = self.hoopRimGraphics.x - self.hoopRimGraphics.width / 2 + self.leftElement.width / 2 - 50;
	self.leftElement.y = self.hoopRimGraphics.y - 250;
	self.leftElement.alpha = 0;
	self.addChild(self.leftElement);
	self.rightElement = LK.getAsset('rightElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.rightElement.x = self.hoopRimGraphics.x + self.hoopRimGraphics.width / 2 - self.rightElement.width / 2 + 50;
	self.rightElement.y = self.hoopRimGraphics.y - 250;
	self.rightElement.alpha = 0;
	self.addChild(self.rightElement);
	self.hoopOutlineGraphics = LK.getAsset('hoopOutline', {
		anchorX: 1,
		anchorY: 0.5
	});
	self.hoopOutlineGraphics.y = self.hoopRimGraphics.y - 230;
	self.hoopOutlineGraphics.alpha = 1;
	self.hoopOutlineGraphics.tint = 0xbb502e;
	self.hoopOutlineGraphics.rotation = Math.PI / 2;
	self.addChild(self.hoopOutlineGraphics);
	self.multiplierLabel = new Text2('', {
		size: 200,
		fill: '#8d4529',
		font: 'Impact'
	});
	self.multiplierLabel.anchor.set(.5, 1);
	self.multiplierLabel.x = self.hoopRimGraphics.x;
	self.multiplierLabel.y = self.hoopRimGraphics.y - 250 - 50 + 30;
	self.addChild(self.multiplierLabel);
	self.scoreLabel = new Text2('0', {
		size: 270,
		fill: '#4b190c',
		font: 'Impact'
	});
	self.scoreLabel.anchor.set(.5, .5);
	self.scoreLabel.x = self.hoopRimGraphics.x;
	self.scoreLabel.y = self.hoopRimGraphics.y - 250 - 20 - 420;
	self.addChild(self.scoreLabel);
});
var HoopRim = Container.expand(function () {
	var self = Container.call(this);
	var hoopRimGraphics = LK.getAsset('hoopRimSeparate', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.addChild(hoopRimGraphics);
});
var Particle = Container.expand(function () {
	var self = Container.call(this);
	self.interactive = false;
	var particleGraphics = self.attachAsset('fireParticle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	particleGraphics.blendMode = 1;
	self.lifeSpan = 60;
	self.speed = {
		x: (Math.random() - 0.5) * 2,
		y: (Math.random() - 0.5) * 2
	};
	self.scale.set(Math.random() * 0.6 + 0.2);
	self.rotation = Math.random() * Math.PI * 2;
	self._move_migrated = function () {
		self.x += self.speed.x;
		self.y += self.speed.y;
		self.alpha -= 0.03;
		if (self.alpha <= 0) {
			self.destroy();
		}
	};
});
var Timer = Container.expand(function () {
	var self = Container.call(this);
	self.timerLabel = new Text2('120', {
		size: 150,
		fill: '#ffffff',
		font: 'Impact'
	});
	self.timerLabel.anchor.set(0.5, 0.5);
	self.addChild(self.timerLabel);
	self.timeLeft = 120;
	self.gameEnded = false;
	self.setTime = function (time) {
		self.timeLeft = time;
		self.timerLabel.setText(Math.ceil(self.timeLeft).toString());
		// Flash red when time is low
		if (self.timeLeft <= 10) {
			tween(self.timerLabel, {
				tint: 0xff0000
			}, {
				duration: 200,
				onFinish: function onFinish() {
					tween(self.timerLabel, {
						tint: 0xffffff
					}, {
						duration: 200
					});
				}
			});
		}
	};
	self.update = function () {
		if (self.timeLeft > 0 && !self.gameEnded) {
			self.timeLeft -= 1 / 60; // Decrease by 1 second every 60 frames
			self.setTime(self.timeLeft);
			if (self.timeLeft <= 0) {
				self.gameEnded = true;
				// Save high score
				if (score > (storage.highScore || 0)) {
					storage.highScore = score;
				}
				LK.showGameOver();
			}
		}
	};
	return self;
});
var TitleText = Container.expand(function () {
	var self = Container.call(this);
	self.titleLabel = new Text2("TIME ATTACK!", {
		size: 200,
		fill: 0x0,
		font: "Impact"
	});
	self.titleLabel.anchor.set(0.5, 0.5);
	self.addChild(self.titleLabel);
	self.subtitleLabel = new Text2("Throw ball to start", {
		size: 100,
		fill: 0x0,
		font: "Impact"
	});
	self.subtitleLabel.anchor.set(0.5, 0.5);
	self.subtitleLabel.y = self.titleLabel.y + 150;
	self.addChild(self.subtitleLabel);
	self.fadeOut = function () {
		tween(self, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x477096
});
/**** 
* Game Code
****/ 
// Import plugins
var bg = LK.getAsset('background', {
	anchorX: 0.5,
	anchorY: 0.5
});
bg.x = 2048 / 2;
bg.y = 2732 / 2 + 150;
bg.alpha = 0.7;
game.addChild(bg);
// Play background music
LK.playMusic('basketball', {
	fade: {
		start: 0,
		end: 1,
		duration: 1000
	}
});
var hoop = game.addChild(new Hoop());
var score = 0;
var scoreMultiplier = 1;
// Create title screen
var titleScreen = new TitleText();
titleScreen.x = 2048 / 2;
titleScreen.y = 2732 / 2 - 300;
game.addChild(titleScreen);
// Create timer
var timer = new Timer();
timer.x = 2048 / 2;
timer.y = 150;
timer.timeLeft = 120; // Set initial time to 120 seconds
timer.gameEnded = true; // Pause timer initially until first throw
game.addChild(timer);
// Display high score
var highScoreLabel = new Text2('Best: ' + (storage.highScore || 0), {
	size: 80,
	fill: '#ffffff',
	font: 'Impact'
});
highScoreLabel.anchor.set(1, 0);
highScoreLabel.x = 2048 - 40;
highScoreLabel.y = 40;
game.addChild(highScoreLabel);
var ballShadow = LK.getAsset('ballShadow', {
	anchorX: 0.5,
	anchorY: 0.5
});
ballShadow.alpha = 0.5;
game.addChild(ballShadow);
var ball = game.addChild(new Ball());
var hoopRim = game.addChild(new HoopRim());
ball.hitElement = '';
hoop.x = 2048 / 2;
hoop.y = 2732 / 2;
hoopRim.x = hoop.x;
hoopRim.y = hoop.y + hoop.children[1].y - 250;
ball.x = 2048 / 2;
ball.on('down', function (x, y, obj) {
	if (!ball.hasThrown) {
		var event = obj;
		dragStart = game.toLocal(event.global);
	}
});
var dragStart = null;
game.on('move', function (x, y, obj) {
	var event = obj;
	var pos = game.toLocal(event.global);
	if (dragStart !== null && ball.distanceTo(pos.x, pos.y) > 400) {
		game.fireBall(obj);
	}
});
game.fireBall = function (obj) {
	if (dragStart !== null) {
		var event = obj.event;
		var pos = game.toLocal(event.global);
		var dx = pos.x - dragStart.x;
		var dy = pos.y - dragStart.y;
		var angle = Math.atan2(dy, dx);
		ball.speed.x = Math.cos(angle) * 72 * 1.76 * 0.9 / 3;
		ball.speed.y = Math.sin(angle) * 72 * 1.76 * 0.9;
		ball.hasThrown = true;
		ball.hitElement = '';
		game.removeChild(ball);
		game.addChild(ball);
		dragStart = null;
		// Play throw sound
		LK.getSound('throwSound').play();
		// Start timer on first throw if it's not already running
		if (timer.gameEnded) {
			timer.gameEnded = false;
			timer.timeLeft = 120; // Reset to ensure full 120 seconds
			timer.setTime(timer.timeLeft);
			titleScreen.fadeOut(); // Hide the title screen
		}
	}
};
game.on('up', function (x, y, obj) {
	if (dragStart !== null) {
		var event = obj;
		var pos = game.toLocal(event.global);
		var distance = Math.sqrt(Math.pow(pos.x - dragStart.x, 2) + Math.pow(pos.y - dragStart.y, 2));
		if (distance > 150) {
			game.fireBall(obj);
		}
	}
	dragStart = null;
});
var floorY = 2732 - 40 + 900 * (ball.scale.y - 1);
ball.y = floorY - ball.height;
LK.on('tick', function () {
	// Update timer
	timer.update();
	if (scoreMultiplier === 3) {
		for (var i = 0; i < 2; i++) {
			var particle = new Particle();
			particle.alpha = ball.alpha;
			var angle = Math.random() * Math.PI * 2;
			var radius = ball.width * 0.5 * Math.sqrt(Math.random());
			particle.x = ball.x + Math.cos(angle) * radius;
			particle.y = ball.y + Math.sin(angle) * radius;
			game.addChild(particle);
		}
	}
	game.children.forEach(function (child) {
		if (child instanceof Particle) {
			child._move_migrated();
		}
	});
	var floorY = 2732 - 40 + 900 * (ball.scale.y - 1);
	ball._move_migrated();
	if (ball.speed.y > 0) {
		game.removeChild(hoopRim);
		game.addChild(hoopRim);
		if (ball.distanceTo(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y) < ball.width / 2 + hoop.leftElement.width / 2) {
			ball.moveToDistance(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y, ball.width / 2 + hoop.leftElement.width / 2 + 1);
			ball.bounceOffPoint(hoop.x + hoop.leftElement.x, hoop.y + hoop.leftElement.y, 0.5);
			ball.hitElement = 'left';
		}
		if (ball.distanceTo(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y) < ball.width / 2 + hoop.rightElement.width / 2) {
			ball.moveToDistance(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y, ball.width / 2 + hoop.rightElement.width / 2 + 1);
			ball.bounceOffPoint(hoop.x + hoop.rightElement.x, hoop.y + hoop.rightElement.y, 0.5);
			ball.hitElement = 'right';
		}
	}
	ballShadow.x = ball.x;
	ballShadow.y = 1800 + ball.height / 2 + 500 * ball.scale.x;
	var scale = (1 - 2 * (ball.y - 2732 + ball.height) / 2732) * ball.scale.x;
	ballShadow.scale.set(scale);
	ballShadow.alpha = (1 - scale + 1) / 2 * ball.alpha;
	if (ball.y + ball.height > floorY) {
		ball.y = floorY - ball.height;
		ball.speed.y *= -0.75;
		ballShadow.x = ball.x;
		ballShadow.visible = true;
		if (ball.hasThrown && !ball.hasScored) {
			if (!ball.hasBounced) {
				ball.hasBounced = true;
			} else if (timer.timeLeft <= 0) {
				LK.showGameOver();
			} else {
				// Play miss sound
				LK.getSound('missSound').play();
				// Create a new ball after it has bounced without scoring
				ball.x = 2048 / 2;
				ball.y = 2532 - ball.height;
				ball.speed.x = 0;
				ball.speed.y = 0;
				ball.hasThrown = false;
				ball.hasScored = false;
				ball.hasBounced = false;
				ball.scale.x = 1;
				ball.scale.y = 1;
				ball.alpha = 1;
				ball.hitElement = '';
				scoreMultiplier = 1;
				hoop.multiplierLabel.setText('');
				// Play whistle sound when new ball is ready
				LK.getSound('whistleSound').play();
			}
		} else if (ball.hasScored) {
			ball.x = 2048 / 2;
			ball.y = 2532 - ball.height;
			ball.speed.x = 0;
			ball.speed.y = 0;
			ball.hasThrown = false;
			ball.hasScored = false;
			ball.hasBounced = false;
			ball.scale.x = 1;
			ball.scale.y = 1;
			if (ball.hitElement === '') {
				if (scoreMultiplier < 3) {
					scoreMultiplier++;
				}
			} else {
				scoreMultiplier = 1;
			}
			if (scoreMultiplier > 1) {
				hoop.multiplierLabel.setText('x' + scoreMultiplier);
			} else {
				hoop.multiplierLabel.setText('');
			}
			ball.hitElement = '';
			// Play whistle sound when new ball is ready after scoring
			LK.getSound('whistleSound').play();
			hoop.moveTo(Math.random() * (2048 - 1000) + 500, Math.random() * (2732 - 2000) + 1000, hoopRim);
		}
	}
	if (ball.x + ball.width / 2 < 0 || ball.x - ball.width / 2 > 2048) {
		if (timer.timeLeft <= 0) {
			LK.showGameOver();
		} else {
			// Play miss sound for out of bounds
			LK.getSound('missSound').play();
			// Create a new ball if the ball goes out of bounds
			ball.x = 2048 / 2;
			ball.y = 2532 - ball.height;
			ball.speed.x = 0;
			ball.speed.y = 0;
			ball.hasThrown = false;
			ball.hasScored = false;
			ball.hasBounced = false;
			ball.scale.x = 1;
			ball.scale.y = 1;
			ball.alpha = 1;
			ball.hitElement = '';
			scoreMultiplier = 1;
			hoop.multiplierLabel.setText('');
			// Play whistle sound when new ball is ready after going out of bounds
			LK.getSound('whistleSound').play();
		}
	} else if (ball.intersects(hoop.hoopRimGraphics) && ball.speed.y > 0 && !ball.hasScored && !ball.hasBounced && ball.x > hoop.x + hoop.leftElement.x && ball.x < hoop.x + hoop.rightElement.x) {
		ball.hasScored = true;
		score += scoreMultiplier;
		LK.setScore(score);
		hoop.scoreLabel.setText(score.toString());
		// Play score sound
		LK.getSound('scoreSound').play();
		// Update high score display if needed
		if (score > (storage.highScore || 0)) {
			storage.highScore = score;
			highScoreLabel.setText('Best: ' + score);
			// Animate high score update
			tween(highScoreLabel, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: 300,
				onFinish: function onFinish() {
					tween(highScoreLabel, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300
					});
				}
			});
		}
	}
});
:quality(85)/https://cdn.frvr.ai/657added97129a10b52cd8f0.png%3F3) 
 Basketball, cartoon style Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6571ad9dd95248718581ed6d.png%3F3) 
 4:3 Simple rectangle white outline. Black background
:quality(85)/https://cdn.frvr.ai/6581b325d42aed1b1993922a.png%3F3) 
 Skull explosion
:quality(85)/https://cdn.frvr.ai/9af3e8e0-5a7a-4d11-a13d-f68a450fd563_tl_transparent_trim.png%3F3) 
 Wide Single Orange metal bar lying down Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast. —ar 2:1
:quality(85)/https://cdn.frvr.ai/c31e5553-8e68-463e-961c-5bd296fba62c_bl_transparent_trim.png%3F3) 
 https://kagi.com/proxy/basketball_backboard.png?c=iNrrnnUOe99nVfDGJsYBLujiaX2Hu-zxBFRkvLEyXdRnJ8cU3RjcAYbR-o12E923qVNGy1CEGrQG87ogCD3yUarJdZYt5R03mmEMb7Jrh-8%3D blank backboard Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/fa69edf7-64cc-4dab-8968-f71918ee03f6_br.png%3F3) 
 Indoor stadium seen from court Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast. --no goal