/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	bestScore: "undefined"
});
/**** 
* Classes
****/ 
var AimGuide = Container.expand(function () {
	var self = Container.call(this);
	var arrowGraphics = self.attachAsset('aimArrow', {
		anchorX: 0,
		anchorY: 0.5
	});
	self.setAngle = function (angle) {
		self.rotation = angle;
	};
	self.setVisible = function (visible) {
		self.visible = visible;
	};
	return self;
});
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.vx = 0;
	self.vy = 0;
	self.friction = 0.96;
	self.isMoving = false;
	self.inWater = false;
	self.inHole = false;
	self.update = function () {
		if (self.isMoving && !self.inHole) {
			self.x += self.vx;
			self.y += self.vy;
			self.vx *= self.friction;
			self.vy *= self.friction;
			// Check if ball has basically stopped
			if (Math.abs(self.vx) < 0.1 && Math.abs(self.vy) < 0.1) {
				self.vx = 0;
				self.vy = 0;
				self.isMoving = false;
				self.checkIfStoppedInHazard();
			}
			// Check if ball is out of screen
			if (self.x < 0 || self.x > COURSE_WIDTH || self.y < 0 || self.y > COURSE_HEIGHT) {
				LK.showGameOver(); // Trigger game over when the ball goes out of screen
			}
		}
	};
	self.hit = function (angle, power) {
		if (!self.isMoving && !self.inHole && !self.inWater) {
			self.vx = Math.cos(angle) * power * 1.2; // Further reduce power multiplier for even shorter range
			self.vy = Math.sin(angle) * power * 1.2; // Further reduce power multiplier for even shorter range
			self.isMoving = true;
			LK.getSound('hit').play();
		}
	};
	self.bounce = function () {
		// Reduced velocity bounce
		self.vx *= -0.7;
		self.vy *= -0.7;
		LK.getSound('bounce').play();
	};
	self.resetPosition = function (x, y) {
		self.x = x;
		self.y = y;
		self.vx = 0;
		self.vy = 0;
		self.isMoving = false;
		self.inWater = false;
		self.inHole = false;
		self.visible = true;
		self.alpha = 1; // Reset ball transparency to fully visible
	};
	self.fallInHole = function () {
		self.inHole = true;
		self.isMoving = false;
		LK.getSound('holeIn').play();
		tween(self, {
			alpha: 0,
			width: 15,
			height: 15
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	self.checkIfStoppedInHazard = function () {
		// This will be implemented in the main game code when hazards are detected
	};
	self.fallInWater = function () {
		self.inWater = true;
		self.isMoving = false;
		LK.getSound('splash').play();
		tween(self, {
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
				self.alpha = 0; // Ensure ball is fully transparent when in water
			}
		});
	};
	return self;
});
var Hole = Container.expand(function () {
	var self = Container.call(this);
	var holeGraphics = self.attachAsset('hole', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add a flag or other indicator later
	return self;
});
var Obstacle = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type || 'bunker';
	var obstacleGraphics = self.attachAsset(self.type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
var PowerMeter = Container.expand(function () {
	var self = Container.call(this);
	var barBg = self.attachAsset('powerBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	var barFill = self.attachAsset('powerFill', {
		anchorX: 0,
		anchorY: 0.5,
		width: 0 // Start with no power
	});
	self.power = 0;
	self.charging = false;
	self.chargeRate = 0.0025; // Further slow down the charge rate for an even slower speed gauge
	self.maxPower = 30;
	self.update = function () {
		if (self.charging) {
			self.power += self.chargeRate;
			if (self.power > 1) {
				self.power = 0;
				self.chargeRate *= -1; // Reverse direction
			} else if (self.power < 0) {
				self.power = 0;
				self.chargeRate *= -1; // Reverse direction
			}
			barFill.width = barBg.width * self.power;
		}
	};
	self.startCharging = function () {
		self.power = 0;
		self.chargeRate = Math.abs(self.chargeRate);
		self.charging = true;
	};
	self.stopCharging = function () {
		self.charging = false;
		return self.power * self.maxPower; // Return actual power value
	};
	self.reset = function () {
		self.power = 0;
		self.charging = false;
		barFill.width = 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x33AA33 // Initial color for the grass
});
/**** 
* Game Code
****/ 
// UI elements 
var timerText = new Text2('Time: 0s', {
	size: 60,
	fill: 0xFFFFFF
});
timerText.anchor.set(0, 0);
LK.gui.topLeft.addChild(timerText);
timerText.x = 200; // Position next to the hole text
var holeTimer = 0;
var timerInterval;
var COURSE_WIDTH = 2048;
var COURSE_HEIGHT = 2732;
var TILE_SIZE = 100;
var GAME_STATE = {
	AIMING: 'aiming',
	CHARGING: 'charging',
	BALL_MOVING: 'ballMoving',
	HOLE_COMPLETE: 'holeComplete'
};
// Game variables
var courseLayout = [];
var ball;
var currentHole;
var obstacles = [];
var aimGuide;
var powerMeter;
var currentState;
var strokeCount = 0;
var holeNumber = 1;
var startX, startY;
var ballLastPosition = {
	x: 0,
	y: 0
};
var maxCols = Math.ceil(COURSE_WIDTH / TILE_SIZE);
var maxRows = Math.ceil(COURSE_HEIGHT / TILE_SIZE);
// UI elements
var strokeText = new Text2('Strokes: 0', {
	size: 60,
	fill: 0xFFFFFF
});
strokeText.anchor.set(0, 0);
LK.gui.topRight.addChild(strokeText);
var holeText = new Text2('Hole: 1', {
	size: 60,
	fill: 0xFFFFFF
});
holeText.anchor.set(1, 0);
LK.gui.topLeft.addChild(holeText);
holeText.x = 100; // Move away from the top left corner
// Generate a random course layout
function generateCourse() {
	clearCourse();
	courseLayout = [];
	// Start the timer
	holeTimer = 0;
	timerText.setText('Time: ' + holeTimer + 's');
	timerInterval = LK.setInterval(function () {
		holeTimer++;
		timerText.setText('Time: ' + holeTimer + 's');
	}, 1000);
	// Set initial game state 
	for (var i = 0; i < maxRows; i++) {
		courseLayout[i] = [];
		for (var j = 0; j < maxCols; j++) {
			courseLayout[i][j] = {
				type: 'grass',
				object: null
			};
		}
	}
	// Create a fairway from start to hole using a simple algorithm
	createFairway();
	// Add random bunkers and water hazards
	addHazards();
	// Render the course
	renderCourse();
	// Place the hole
	placeHole();
	// Place the ball at the starting position
	placeBall();
	// Update UI
	updateUI();
	// Set initial game state
	currentState = GAME_STATE.AIMING;
}
function clearCourse() {
	// Remove all existing course elements
	if (ball) {
		game.removeChild(ball);
	}
	if (currentHole) {
		game.removeChild(currentHole);
	}
	for (var i = 0; i < obstacles.length; i++) {
		game.removeChild(obstacles[i]);
	}
	obstacles = [];
}
function createFairway() {
	// Define start and end points
	startX = Math.floor(maxCols / 2);
	startY = maxRows - 2;
	var endX = Math.floor(Math.random() * (maxCols - 4)) + 2;
	var endY = 2;
	// Mark the path as fairway
	var x = startX;
	var y = startY;
	while (x !== endX || y !== endY) {
		// Mark current and surrounding tiles as fairway
		for (var i = -1; i <= 1; i++) {
			for (var j = -1; j <= 1; j++) {
				var newY = y + i;
				var newX = x + j;
				if (newY >= 0 && newY < maxRows && newX >= 0 && newX < maxCols) {
					courseLayout[newY][newX].type = 'fairway';
				}
			}
		}
		// Move one step closer to the hole
		if (x < endX) {
			x++;
		} else if (x > endX) {
			x--;
		}
		if (y < endY) {
			y++;
		} else if (y > endY) {
			y--;
		}
	}
	// Mark the end point (hole location)
	courseLayout[endY][endX].type = 'fairway';
	for (var i = -1; i <= 1; i++) {
		for (var j = -1; j <= 1; j++) {
			var y = endY + i;
			var x = endX + j;
			if (y >= 0 && y < maxRows && x >= 0 && x < maxCols) {
				courseLayout[y][x].type = 'fairway';
			}
		}
	}
	// Remember hole position
	holeX = endX;
	holeY = endY;
}
function addHazards() {
	// Add rough along the sides of the fairway
	for (var y = 0; y < maxRows; y++) {
		for (var x = 0; x < maxCols; x++) {
			if (courseLayout[y][x].type === 'grass') {
				// Check if adjacent to fairway
				var adjacentToFairway = false;
				for (var j = -1; j <= 1; j++) {
					for (var k = -1; k <= 1; k++) {
						var newY = y + j;
						var newX = x + k;
						if (newY >= 0 && newY < maxRows && newX >= 0 && newX < maxCols && courseLayout[newY][newX].type === 'fairway') {
							adjacentToFairway = true;
							break;
						}
					}
					if (adjacentToFairway) {
						break;
					}
				}
				if (adjacentToFairway) {
					courseLayout[y][x].type = 'roughGrass';
				}
			}
		}
	}
}
function renderCourse() {
	// Create the obstacles for hazards
	for (var y = 0; y < maxRows; y++) {
		for (var x = 0; x < maxCols; x++) {
			var tileType = courseLayout[y][x].type;
			var screenX = x * TILE_SIZE;
			var screenY = y * TILE_SIZE;
		}
	}
}
function placeHole() {
	currentHole = new Hole();
	currentHole.x = holeX * TILE_SIZE + TILE_SIZE / 2;
	currentHole.y = holeY * TILE_SIZE + TILE_SIZE / 2;
	game.addChild(currentHole);
}
function placeBall() {
	if (!ball) {
		ball = new Ball();
		game.addChild(ball);
		// Create aim guide
		aimGuide = new AimGuide();
		game.addChild(aimGuide);
		// Create power meter
		powerMeter = new PowerMeter();
		game.addChild(powerMeter);
		powerMeter.x = COURSE_WIDTH / 2 - 200;
		powerMeter.y = COURSE_HEIGHT - 100;
		powerMeter.visible = false;
	}
	// Position the ball at the starting point
	ball.resetPosition(startX * TILE_SIZE + TILE_SIZE / 2, startY * TILE_SIZE + TILE_SIZE / 2);
	ballLastPosition = {
		x: ball.x,
		y: ball.y
	};
	// Update aim guide position
	aimGuide.x = ball.x;
	aimGuide.y = ball.y;
	aimGuide.visible = true;
	aimGuide.setAngle(Math.PI * 1.5); // Point upward by default
}
function updateUI() {
	strokeText.setText('Strokes: ' + strokeCount);
	holeText.setText('Hole: ' + holeNumber);
}
function getTileAtPosition(x, y) {
	var gridX = Math.floor(x / TILE_SIZE);
	var gridY = Math.floor(y / TILE_SIZE);
	if (gridX >= 0 && gridX < maxCols && gridY >= 0 && gridY < maxRows) {
		return courseLayout[gridY][gridX];
	}
	return null;
}
function checkBallCollisions() {
	// Get current tile
	var tile = getTileAtPosition(ball.x, ball.y);
	if (!tile) {
		return;
	}
	// Check for hole
	if (Math.sqrt(Math.pow(ball.x - currentHole.x, 2) + Math.pow(ball.y - currentHole.y, 2)) < 20) {
		ball.fallInHole();
		completeHole();
		LK.showGameOver(); // Trigger game over when the ball falls into the hole
		return;
	}
	// Check for bunker (slows the ball down more)
	if (tile.type === 'bunker') {
		ball.friction = 0.92; // More friction in bunkers
	} else if (tile.type === 'fairway') {
		ball.friction = 0.98; // Less friction on fairway for easier target
	} else {
		ball.friction = 0.96;
	}
	// Check for course boundaries
	if (ball.x < 0 || ball.x > COURSE_WIDTH || ball.y < 0 || ball.y > COURSE_HEIGHT) {
		ball.bounce();
	}
}
function resetBallToLastPosition() {
	strokeCount++; // Penalty stroke
	updateUI();
	ball.resetPosition(ballLastPosition.x, ballLastPosition.y);
	ball.visible = true; // Ensure ball is visible after repositioning
	ball.alpha = 1; // Reset ball transparency to fully visible
	currentState = GAME_STATE.AIMING;
	aimGuide.x = ball.x;
	aimGuide.y = ball.y;
	aimGuide.visible = true;
}
function completeHole() {
	currentState = GAME_STATE.HOLE_COMPLETE;
	// Stop the timer
	LK.clearInterval(timerInterval);
	// Show score for this hole 
	var scoreText = new Text2('Hole ' + holeNumber + ' completed in ' + strokeCount + ' strokes!', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreText.anchor.set(0.5, 0.5);
	scoreText.x = COURSE_WIDTH / 2;
	scoreText.y = COURSE_HEIGHT / 2 - 100;
	game.addChild(scoreText);
	// Save best score
	var bestHoleScore = storage['hole' + holeNumber] || null;
	if (bestHoleScore === null || strokeCount < bestHoleScore) {
		storage['hole' + holeNumber] = strokeCount;
		var newRecordText = new Text2('New Best Score!', {
			size: 50,
			fill: 0xFFFF00
		});
		newRecordText.anchor.set(0.5, 0.5);
		newRecordText.x = COURSE_WIDTH / 2;
		newRecordText.y = COURSE_HEIGHT / 2;
		game.addChild(newRecordText);
	}
	// Add continue button
	var continueText = new Text2('Tap to continue', {
		size: 40,
		fill: 0xFFFFFF
	});
	continueText.anchor.set(0.5, 0.5);
	continueText.x = COURSE_WIDTH / 2;
	continueText.y = COURSE_HEIGHT / 2 + 100;
	game.addChild(continueText);
	// Flash the text
	var flashInterval = LK.setInterval(function () {
		continueText.visible = !continueText.visible;
	}, 500);
	// Wait for tap to continue
	var tapHandler = function tapHandler(x, y) {
		LK.clearInterval(flashInterval);
		game.removeChild(scoreText);
		game.removeChild(continueText);
		if (newRecordText) {
			game.removeChild(newRecordText);
		}
		// Prepare next hole
		holeNumber++;
		strokeCount = 0;
		generateCourse();
		// Remove this handler
		game.up = function () {};
	};
	game.up = tapHandler;
}
// Initialize the course
generateCourse();
// Start playing background music
LK.playMusic('bgMusic');
// Input handling
game.down = function (x, y) {
	if (currentState === GAME_STATE.AIMING && !ball.isMoving && !ball.inHole && !ball.inWater) {
		// Start tracking swipe
		swipeStartX = x;
		swipeStartY = y;
		aimGuide.x = ball.x;
		aimGuide.y = ball.y;
		aimGuide.visible = true;
	}
};
game.move = function (x, y) {
	if (currentState === GAME_STATE.AIMING && aimGuide.visible) {
		// Calculate angle from swipe movement
		var dx = x - swipeStartX;
		var dy = y - swipeStartY;
		var angle = Math.atan2(dy, dx);
		aimGuide.setAngle(angle);
	}
};
game.up = function (x, y) {
	if (currentState === GAME_STATE.AIMING && aimGuide.visible) {
		// Calculate power based on swipe distance
		var dx = x - swipeStartX;
		var dy = y - swipeStartY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var power = Math.min(distance / 100, 1) * powerMeter.maxPower;
		// Hit the ball
		var angle = aimGuide.rotation;
		ball.hit(angle, power);
		aimGuide.visible = false;
		currentState = GAME_STATE.BALL_MOVING;
		strokeCount++;
		updateUI();
		// Remember position for potential penalty
		ballLastPosition = {
			x: ball.x,
			y: ball.y
		};
	}
};
// Game update loop
game.update = function () {
	// Update ball physics
	if (ball && currentState === GAME_STATE.BALL_MOVING) {
		checkBallCollisions();
		// Check if ball has stopped moving
		if (!ball.isMoving && !ball.inHole && !ball.inWater) {
			currentState = GAME_STATE.AIMING;
			aimGuide.x = ball.x;
			aimGuide.y = ball.y;
			aimGuide.visible = true;
		}
	}
	// Update power meter
	if (powerMeter && currentState === GAME_STATE.CHARGING) {
		powerMeter.update();
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	bestScore: "undefined"
});
/**** 
* Classes
****/ 
var AimGuide = Container.expand(function () {
	var self = Container.call(this);
	var arrowGraphics = self.attachAsset('aimArrow', {
		anchorX: 0,
		anchorY: 0.5
	});
	self.setAngle = function (angle) {
		self.rotation = angle;
	};
	self.setVisible = function (visible) {
		self.visible = visible;
	};
	return self;
});
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.vx = 0;
	self.vy = 0;
	self.friction = 0.96;
	self.isMoving = false;
	self.inWater = false;
	self.inHole = false;
	self.update = function () {
		if (self.isMoving && !self.inHole) {
			self.x += self.vx;
			self.y += self.vy;
			self.vx *= self.friction;
			self.vy *= self.friction;
			// Check if ball has basically stopped
			if (Math.abs(self.vx) < 0.1 && Math.abs(self.vy) < 0.1) {
				self.vx = 0;
				self.vy = 0;
				self.isMoving = false;
				self.checkIfStoppedInHazard();
			}
			// Check if ball is out of screen
			if (self.x < 0 || self.x > COURSE_WIDTH || self.y < 0 || self.y > COURSE_HEIGHT) {
				LK.showGameOver(); // Trigger game over when the ball goes out of screen
			}
		}
	};
	self.hit = function (angle, power) {
		if (!self.isMoving && !self.inHole && !self.inWater) {
			self.vx = Math.cos(angle) * power * 1.2; // Further reduce power multiplier for even shorter range
			self.vy = Math.sin(angle) * power * 1.2; // Further reduce power multiplier for even shorter range
			self.isMoving = true;
			LK.getSound('hit').play();
		}
	};
	self.bounce = function () {
		// Reduced velocity bounce
		self.vx *= -0.7;
		self.vy *= -0.7;
		LK.getSound('bounce').play();
	};
	self.resetPosition = function (x, y) {
		self.x = x;
		self.y = y;
		self.vx = 0;
		self.vy = 0;
		self.isMoving = false;
		self.inWater = false;
		self.inHole = false;
		self.visible = true;
		self.alpha = 1; // Reset ball transparency to fully visible
	};
	self.fallInHole = function () {
		self.inHole = true;
		self.isMoving = false;
		LK.getSound('holeIn').play();
		tween(self, {
			alpha: 0,
			width: 15,
			height: 15
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	self.checkIfStoppedInHazard = function () {
		// This will be implemented in the main game code when hazards are detected
	};
	self.fallInWater = function () {
		self.inWater = true;
		self.isMoving = false;
		LK.getSound('splash').play();
		tween(self, {
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
				self.alpha = 0; // Ensure ball is fully transparent when in water
			}
		});
	};
	return self;
});
var Hole = Container.expand(function () {
	var self = Container.call(this);
	var holeGraphics = self.attachAsset('hole', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add a flag or other indicator later
	return self;
});
var Obstacle = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type || 'bunker';
	var obstacleGraphics = self.attachAsset(self.type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
var PowerMeter = Container.expand(function () {
	var self = Container.call(this);
	var barBg = self.attachAsset('powerBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	var barFill = self.attachAsset('powerFill', {
		anchorX: 0,
		anchorY: 0.5,
		width: 0 // Start with no power
	});
	self.power = 0;
	self.charging = false;
	self.chargeRate = 0.0025; // Further slow down the charge rate for an even slower speed gauge
	self.maxPower = 30;
	self.update = function () {
		if (self.charging) {
			self.power += self.chargeRate;
			if (self.power > 1) {
				self.power = 0;
				self.chargeRate *= -1; // Reverse direction
			} else if (self.power < 0) {
				self.power = 0;
				self.chargeRate *= -1; // Reverse direction
			}
			barFill.width = barBg.width * self.power;
		}
	};
	self.startCharging = function () {
		self.power = 0;
		self.chargeRate = Math.abs(self.chargeRate);
		self.charging = true;
	};
	self.stopCharging = function () {
		self.charging = false;
		return self.power * self.maxPower; // Return actual power value
	};
	self.reset = function () {
		self.power = 0;
		self.charging = false;
		barFill.width = 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x33AA33 // Initial color for the grass
});
/**** 
* Game Code
****/ 
// UI elements 
var timerText = new Text2('Time: 0s', {
	size: 60,
	fill: 0xFFFFFF
});
timerText.anchor.set(0, 0);
LK.gui.topLeft.addChild(timerText);
timerText.x = 200; // Position next to the hole text
var holeTimer = 0;
var timerInterval;
var COURSE_WIDTH = 2048;
var COURSE_HEIGHT = 2732;
var TILE_SIZE = 100;
var GAME_STATE = {
	AIMING: 'aiming',
	CHARGING: 'charging',
	BALL_MOVING: 'ballMoving',
	HOLE_COMPLETE: 'holeComplete'
};
// Game variables
var courseLayout = [];
var ball;
var currentHole;
var obstacles = [];
var aimGuide;
var powerMeter;
var currentState;
var strokeCount = 0;
var holeNumber = 1;
var startX, startY;
var ballLastPosition = {
	x: 0,
	y: 0
};
var maxCols = Math.ceil(COURSE_WIDTH / TILE_SIZE);
var maxRows = Math.ceil(COURSE_HEIGHT / TILE_SIZE);
// UI elements
var strokeText = new Text2('Strokes: 0', {
	size: 60,
	fill: 0xFFFFFF
});
strokeText.anchor.set(0, 0);
LK.gui.topRight.addChild(strokeText);
var holeText = new Text2('Hole: 1', {
	size: 60,
	fill: 0xFFFFFF
});
holeText.anchor.set(1, 0);
LK.gui.topLeft.addChild(holeText);
holeText.x = 100; // Move away from the top left corner
// Generate a random course layout
function generateCourse() {
	clearCourse();
	courseLayout = [];
	// Start the timer
	holeTimer = 0;
	timerText.setText('Time: ' + holeTimer + 's');
	timerInterval = LK.setInterval(function () {
		holeTimer++;
		timerText.setText('Time: ' + holeTimer + 's');
	}, 1000);
	// Set initial game state 
	for (var i = 0; i < maxRows; i++) {
		courseLayout[i] = [];
		for (var j = 0; j < maxCols; j++) {
			courseLayout[i][j] = {
				type: 'grass',
				object: null
			};
		}
	}
	// Create a fairway from start to hole using a simple algorithm
	createFairway();
	// Add random bunkers and water hazards
	addHazards();
	// Render the course
	renderCourse();
	// Place the hole
	placeHole();
	// Place the ball at the starting position
	placeBall();
	// Update UI
	updateUI();
	// Set initial game state
	currentState = GAME_STATE.AIMING;
}
function clearCourse() {
	// Remove all existing course elements
	if (ball) {
		game.removeChild(ball);
	}
	if (currentHole) {
		game.removeChild(currentHole);
	}
	for (var i = 0; i < obstacles.length; i++) {
		game.removeChild(obstacles[i]);
	}
	obstacles = [];
}
function createFairway() {
	// Define start and end points
	startX = Math.floor(maxCols / 2);
	startY = maxRows - 2;
	var endX = Math.floor(Math.random() * (maxCols - 4)) + 2;
	var endY = 2;
	// Mark the path as fairway
	var x = startX;
	var y = startY;
	while (x !== endX || y !== endY) {
		// Mark current and surrounding tiles as fairway
		for (var i = -1; i <= 1; i++) {
			for (var j = -1; j <= 1; j++) {
				var newY = y + i;
				var newX = x + j;
				if (newY >= 0 && newY < maxRows && newX >= 0 && newX < maxCols) {
					courseLayout[newY][newX].type = 'fairway';
				}
			}
		}
		// Move one step closer to the hole
		if (x < endX) {
			x++;
		} else if (x > endX) {
			x--;
		}
		if (y < endY) {
			y++;
		} else if (y > endY) {
			y--;
		}
	}
	// Mark the end point (hole location)
	courseLayout[endY][endX].type = 'fairway';
	for (var i = -1; i <= 1; i++) {
		for (var j = -1; j <= 1; j++) {
			var y = endY + i;
			var x = endX + j;
			if (y >= 0 && y < maxRows && x >= 0 && x < maxCols) {
				courseLayout[y][x].type = 'fairway';
			}
		}
	}
	// Remember hole position
	holeX = endX;
	holeY = endY;
}
function addHazards() {
	// Add rough along the sides of the fairway
	for (var y = 0; y < maxRows; y++) {
		for (var x = 0; x < maxCols; x++) {
			if (courseLayout[y][x].type === 'grass') {
				// Check if adjacent to fairway
				var adjacentToFairway = false;
				for (var j = -1; j <= 1; j++) {
					for (var k = -1; k <= 1; k++) {
						var newY = y + j;
						var newX = x + k;
						if (newY >= 0 && newY < maxRows && newX >= 0 && newX < maxCols && courseLayout[newY][newX].type === 'fairway') {
							adjacentToFairway = true;
							break;
						}
					}
					if (adjacentToFairway) {
						break;
					}
				}
				if (adjacentToFairway) {
					courseLayout[y][x].type = 'roughGrass';
				}
			}
		}
	}
}
function renderCourse() {
	// Create the obstacles for hazards
	for (var y = 0; y < maxRows; y++) {
		for (var x = 0; x < maxCols; x++) {
			var tileType = courseLayout[y][x].type;
			var screenX = x * TILE_SIZE;
			var screenY = y * TILE_SIZE;
		}
	}
}
function placeHole() {
	currentHole = new Hole();
	currentHole.x = holeX * TILE_SIZE + TILE_SIZE / 2;
	currentHole.y = holeY * TILE_SIZE + TILE_SIZE / 2;
	game.addChild(currentHole);
}
function placeBall() {
	if (!ball) {
		ball = new Ball();
		game.addChild(ball);
		// Create aim guide
		aimGuide = new AimGuide();
		game.addChild(aimGuide);
		// Create power meter
		powerMeter = new PowerMeter();
		game.addChild(powerMeter);
		powerMeter.x = COURSE_WIDTH / 2 - 200;
		powerMeter.y = COURSE_HEIGHT - 100;
		powerMeter.visible = false;
	}
	// Position the ball at the starting point
	ball.resetPosition(startX * TILE_SIZE + TILE_SIZE / 2, startY * TILE_SIZE + TILE_SIZE / 2);
	ballLastPosition = {
		x: ball.x,
		y: ball.y
	};
	// Update aim guide position
	aimGuide.x = ball.x;
	aimGuide.y = ball.y;
	aimGuide.visible = true;
	aimGuide.setAngle(Math.PI * 1.5); // Point upward by default
}
function updateUI() {
	strokeText.setText('Strokes: ' + strokeCount);
	holeText.setText('Hole: ' + holeNumber);
}
function getTileAtPosition(x, y) {
	var gridX = Math.floor(x / TILE_SIZE);
	var gridY = Math.floor(y / TILE_SIZE);
	if (gridX >= 0 && gridX < maxCols && gridY >= 0 && gridY < maxRows) {
		return courseLayout[gridY][gridX];
	}
	return null;
}
function checkBallCollisions() {
	// Get current tile
	var tile = getTileAtPosition(ball.x, ball.y);
	if (!tile) {
		return;
	}
	// Check for hole
	if (Math.sqrt(Math.pow(ball.x - currentHole.x, 2) + Math.pow(ball.y - currentHole.y, 2)) < 20) {
		ball.fallInHole();
		completeHole();
		LK.showGameOver(); // Trigger game over when the ball falls into the hole
		return;
	}
	// Check for bunker (slows the ball down more)
	if (tile.type === 'bunker') {
		ball.friction = 0.92; // More friction in bunkers
	} else if (tile.type === 'fairway') {
		ball.friction = 0.98; // Less friction on fairway for easier target
	} else {
		ball.friction = 0.96;
	}
	// Check for course boundaries
	if (ball.x < 0 || ball.x > COURSE_WIDTH || ball.y < 0 || ball.y > COURSE_HEIGHT) {
		ball.bounce();
	}
}
function resetBallToLastPosition() {
	strokeCount++; // Penalty stroke
	updateUI();
	ball.resetPosition(ballLastPosition.x, ballLastPosition.y);
	ball.visible = true; // Ensure ball is visible after repositioning
	ball.alpha = 1; // Reset ball transparency to fully visible
	currentState = GAME_STATE.AIMING;
	aimGuide.x = ball.x;
	aimGuide.y = ball.y;
	aimGuide.visible = true;
}
function completeHole() {
	currentState = GAME_STATE.HOLE_COMPLETE;
	// Stop the timer
	LK.clearInterval(timerInterval);
	// Show score for this hole 
	var scoreText = new Text2('Hole ' + holeNumber + ' completed in ' + strokeCount + ' strokes!', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreText.anchor.set(0.5, 0.5);
	scoreText.x = COURSE_WIDTH / 2;
	scoreText.y = COURSE_HEIGHT / 2 - 100;
	game.addChild(scoreText);
	// Save best score
	var bestHoleScore = storage['hole' + holeNumber] || null;
	if (bestHoleScore === null || strokeCount < bestHoleScore) {
		storage['hole' + holeNumber] = strokeCount;
		var newRecordText = new Text2('New Best Score!', {
			size: 50,
			fill: 0xFFFF00
		});
		newRecordText.anchor.set(0.5, 0.5);
		newRecordText.x = COURSE_WIDTH / 2;
		newRecordText.y = COURSE_HEIGHT / 2;
		game.addChild(newRecordText);
	}
	// Add continue button
	var continueText = new Text2('Tap to continue', {
		size: 40,
		fill: 0xFFFFFF
	});
	continueText.anchor.set(0.5, 0.5);
	continueText.x = COURSE_WIDTH / 2;
	continueText.y = COURSE_HEIGHT / 2 + 100;
	game.addChild(continueText);
	// Flash the text
	var flashInterval = LK.setInterval(function () {
		continueText.visible = !continueText.visible;
	}, 500);
	// Wait for tap to continue
	var tapHandler = function tapHandler(x, y) {
		LK.clearInterval(flashInterval);
		game.removeChild(scoreText);
		game.removeChild(continueText);
		if (newRecordText) {
			game.removeChild(newRecordText);
		}
		// Prepare next hole
		holeNumber++;
		strokeCount = 0;
		generateCourse();
		// Remove this handler
		game.up = function () {};
	};
	game.up = tapHandler;
}
// Initialize the course
generateCourse();
// Start playing background music
LK.playMusic('bgMusic');
// Input handling
game.down = function (x, y) {
	if (currentState === GAME_STATE.AIMING && !ball.isMoving && !ball.inHole && !ball.inWater) {
		// Start tracking swipe
		swipeStartX = x;
		swipeStartY = y;
		aimGuide.x = ball.x;
		aimGuide.y = ball.y;
		aimGuide.visible = true;
	}
};
game.move = function (x, y) {
	if (currentState === GAME_STATE.AIMING && aimGuide.visible) {
		// Calculate angle from swipe movement
		var dx = x - swipeStartX;
		var dy = y - swipeStartY;
		var angle = Math.atan2(dy, dx);
		aimGuide.setAngle(angle);
	}
};
game.up = function (x, y) {
	if (currentState === GAME_STATE.AIMING && aimGuide.visible) {
		// Calculate power based on swipe distance
		var dx = x - swipeStartX;
		var dy = y - swipeStartY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var power = Math.min(distance / 100, 1) * powerMeter.maxPower;
		// Hit the ball
		var angle = aimGuide.rotation;
		ball.hit(angle, power);
		aimGuide.visible = false;
		currentState = GAME_STATE.BALL_MOVING;
		strokeCount++;
		updateUI();
		// Remember position for potential penalty
		ballLastPosition = {
			x: ball.x,
			y: ball.y
		};
	}
};
// Game update loop
game.update = function () {
	// Update ball physics
	if (ball && currentState === GAME_STATE.BALL_MOVING) {
		checkBallCollisions();
		// Check if ball has stopped moving
		if (!ball.isMoving && !ball.inHole && !ball.inWater) {
			currentState = GAME_STATE.AIMING;
			aimGuide.x = ball.x;
			aimGuide.y = ball.y;
			aimGuide.visible = true;
		}
	}
	// Update power meter
	if (powerMeter && currentState === GAME_STATE.CHARGING) {
		powerMeter.update();
	}
};