/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var House = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('house', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.active = true;
	// Remove scrolling from update, handled by tweens
	self.update = function () {};
	return self;
});
var Mailbox = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('mailbox', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.hit = false;
	self.active = true;
	self.update = function () {}; // no auto-scrolling
	return self;
});
var Newspaper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('newspaper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Physics properties
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0.4;
	self.active = true;
	// Store starting position for scaling math
	self.startY = null;
	self.update = function () {
		if (!self.active) {
			return;
		}
		// Apply velocity
		self.x += self.vx;
		self.y += self.vy;
		// Apply gravity
		self.vy += self.gravity;
		// Record starting Y on first update
		if (self.startY === null) {
			self.startY = self.y;
		}
		// Scale down as it rises (depth effect)
		var travel = self.startY - self.y;
		var scaleFactor = Math.max(0.2, 1 - travel / 1500);
		graphics.scaleX = graphics.scaleY = scaleFactor;
		// Cleanup when it goes "into the distance"
		if (self.y < mailboxZoneY - 300 || self.y > 2732 || self.x < -200 || self.x > 2300) {
			self.active = false;
			// Trigger turn end if this was the last shot
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					// Clear leftover mailboxes
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x87ceeb
});
/**** 
* Game Code
****/ 
// green
// orange
game.setBackgroundColor(0x87ceeb);
// Start background music immediately when game loads
LK.playMusic('MothmanBoogie');
/**** 
* Color Interpolation Helper
****/ 
function lerpColor(c1, c2, t) {
	var r1 = c1 >> 16 & 0xff,
		g1 = c1 >> 8 & 0xff,
		b1 = c1 & 0xff;
	var r2 = c2 >> 16 & 0xff,
		g2 = c2 >> 8 & 0xff,
		b2 = c2 & 0xff;
	var r = Math.round(r1 + (r2 - r1) * t);
	var g = Math.round(g1 + (g2 - g1) * t);
	var b = Math.round(b1 + (b2 - b1) * t);
	return r << 16 | g << 8 | b;
}
/**** 
* Sun Path Parameters
****/ 
// Sun path parameters
var sunStartX = 100; // left side
var sunEndX = 1948; // right side
var sunBaseY = 600; // baseline (sky zone level)
var sunArcHeight = 400; // how high the sun climbs
/**** 
* Zone Setup
****/ 
// Define Y positions for zones (adjust as needed to match your reference image)
var streetZoneY = 2000; // Green bottom zone where slingshot sits
var mailboxZoneY = 1200; // Orange middle zone where mailbox spawns
var houseZoneY = 1000; // Houses aligned just above mailbox zone
// Ground reference (for houses)
var groundY = 2400;
/**** 
* Visual Zone Placeholders
****/ 
// Street zone background (green)
var streetZone = game.addChild(LK.getAsset('streetZone', {
	anchorX: 0.5,
	anchorY: 0.5
}));
streetZone.x = 1024;
streetZone.y = streetZoneY;
// Mailbox zone background (orange)
var mailboxZone = game.addChild(LK.getAsset('mailboxZone', {
	anchorX: 0.5,
	anchorY: 0.5
}));
mailboxZone.x = 1024;
mailboxZone.y = mailboxZoneY;
// Treeline container to move with houses
var treelineContainer = new Container();
// compute how many tiles we need to cover the screen plus one extra on each side
var tileWidth = LK.getAsset('treeline', {}).width;
var screenWidth = 2048; // your game width
var sideBuffers = 2; // two extra tiles on left side, one on right
var tileCount = Math.ceil(screenWidth / tileWidth) + sideBuffers * 2 + 1; // +1 for additional right side duplicate
var treelines = [];
for (var i = 0; i < tileCount; i++) {
	var tile = treelineContainer.addChild(LK.getAsset('treeline', {
		anchorX: 0,
		anchorY: 1
	}));
	// position so that the first tile starts at –tileWidth
	tile.x = (i - sideBuffers) * tileWidth;
	tile.y = 0;
	treelines.push(tile);
}
// lock the whole strip at the correct vertical position
treelineContainer.x = 0;
treelineContainer.y = mailboxZoneY - 350;
// Add treeline container before other game elements to render behind them
game.addChild(treelineContainer);
// Parallax scrolling parameters
var baseSpeed = 5; // Base movement speed for reference
var treeParallaxFactor = 0.2; // Trees move at 20% of house speed for depth effect
// Update function for treeline infinite scroll
function updateTreeline(speed) {
	for (var i = 0; i < treelines.length; i++) {
		var t = treelines[i];
		t.x -= speed;
		// Snap positions to integers to prevent floating-point drift
		t.x = Math.round(t.x);
	}
	// After moving, check for wrap and re-align all treelines to be flush
	// Find the leftmost treeline
	var leftMostIndex = 0;
	var leftMostX = treelines[0].x;
	for (var i = 1; i < treelines.length; i++) {
		if (treelines[i].x < leftMostX) {
			leftMostX = treelines[i].x;
			leftMostIndex = i;
		}
	}
	// Now, starting from leftmost, set each treeline's x so they are flush
	var startX = treelines[leftMostIndex].x;
	for (var i = 0; i < treelines.length; i++) {
		var idx = (leftMostIndex + i) % treelines.length;
		if (i === 0) {
			treelines[idx].x = startX;
		} else {
			treelines[idx].x = treelines[(idx - 1 + treelines.length) % treelines.length].x + tileWidth;
		}
	}
	// If any treeline is now off the left edge, move it to the right of the last one
	for (var i = 0; i < treelines.length; i++) {
		var t = treelines[i];
		if (t.x + tileWidth < 0) {
			// Find the rightmost treeline
			var rightMost = Math.max.apply(Math, treelines.map(function (tr) {
				return tr.x;
			}));
			t.x = rightMost + tileWidth - 1; // subtract 1px to overlap
		}
	}
}
// Game variables
var mothman;
var sun;
var slingshot;
var newspapers = [];
var mailboxes = [];
var houses = [];
var trajectoryDots = [];
// Create one reusable graphics line for the trajectory
var trajectoryLine = new Container();
// Pull-back origin indicator will be created after slingshot for proper layering
var pullOriginIndicator;
var pennies = 0;
var targetPennies = 650;
var gameTime = 0;
var maxGameTime = 18000; // 5 minutes at 60fps
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var aimPower = 0;
var aimAngle = 0;
var hasThrownThisTurn = false;
// Create UI
var paycheckText = new Text2('Paycheck: $0.00', {
	size: 65,
	fill: 0x006400,
	font: "'Comic Sans MS', cursive"
});
paycheckText.anchor.set(0.5, 0);
paycheckText.y = 100;
LK.gui.top.addChild(paycheckText);
function updatePaycheck() {
	paycheckText.setText('Paycheck: $' + (pennies / 100).toFixed(2));
}
// Power bar background + fill
var powerBarBG = LK.getAsset('powerBarBGShape', {
	anchorX: 0.5,
	anchorY: 0.5
});
powerBarBG.x = 1024;
powerBarBG.y = 200; // top center instead of bottom
LK.gui.top.addChild(powerBarBG);
var powerBarFill = LK.getAsset('powerBarFillShape', {
	width: 0,
	// start empty
	anchorX: 0,
	anchorY: 0.5
});
powerBarFill.x = powerBarBG.x - 150;
powerBarFill.y = powerBarBG.y;
LK.gui.top.addChild(powerBarFill);
// Create mothman
mothman = game.addChild(new Container());
var mothmanGraphics = mothman.attachAsset('mothman', {
	anchorX: 0.5,
	anchorY: 0.5
});
mothman.x = 200;
mothman.y = 400;
// Hide mothman (no sprite during gameplay)
mothman.visible = false;
// Create pull origin indicator after mothman to ensure proper layering in front
pullOriginIndicator = LK.getAsset('aimOriginShape', {
	anchorX: 0.5,
	anchorY: 0.5
});
// Position the aim origin indicator at slingshot position, moved up by 100 pixels
pullOriginIndicator.x = 1024;
pullOriginIndicator.y = 2000; // streetZoneY (2000) + 100 - 100 = 2000
pullOriginIndicator.visible = true; // Always visible
// Add aiming visuals after mothman to ensure they render on top
game.addChild(trajectoryLine);
game.addChild(pullOriginIndicator);
// Create sun
sun = game.addChild(new Container());
var sunGraphics = sun.attachAsset('sun', {
	anchorX: 0.5,
	anchorY: 0.5
});
sun.x = sunStartX;
sun.y = sunBaseY - sunArcHeight;
/**** 
* Draw Sun Arc Path
****/ 
// Draw sun trajectory arc with dotted path
function drawSunPath() {
	for (var t = 0; t <= 1; t += 0.05) {
		var x = sunStartX + (sunEndX - sunStartX) * t;
		var y = sunBaseY - Math.sin(t * Math.PI) * sunArcHeight;
		var dot = game.addChild(LK.getAsset('trajectory', {
			width: 6,
			height: 6,
			color: 0xffff66,
			// pale yellow
			anchorX: 0.5,
			anchorY: 0.5
		}));
		dot.x = x;
		dot.y = y;
		dot.alpha = 0.3; // semi-transparent
	}
}
drawSunPath();
// Create slingshot area - positioned in street zone center
slingshot = game.addChild(new Container());
var slingshotGraphics = slingshot.attachAsset('slingshot', {
	anchorX: 0.5,
	anchorY: 0.5
});
slingshot.x = 1024; // center of screen
slingshot.y = streetZoneY + 100;
// Slingshot bands (for stretch feedback)
var bandLeft = new Container();
var bandRight = new Container();
game.addChild(bandLeft);
game.addChild(bandRight);
// Ground level
var groundY = 2400;
// Turn-based house cycle variables
var currentHouse = null;
var isHouseTransitioning = false;
var turnComplete = true;
var prevHouseX = 1024; // Track previous house X position for treeline scroll
function ensureMailboxForTurn() {
	// Clear leftover mailboxes
	for (var k = mailboxes.length - 1; k >= 0; k--) {
		mailboxes[k].destroy();
		mailboxes.splice(k, 1);
	}
	createMailbox(); // always create (no RNG)
}
function createHouse() {
	var house = new House();
	// Start just off-screen to the right
	house.x = 2200;
	house.y = mailboxZoneY + 250; // roughly center mailbox zone
	houses.push(house);
	game.addChild(house);
	currentHouse = house;
	isHouseTransitioning = true;
	turnComplete = false;
	hasThrownThisTurn = false;
	// Tween it into center of mailbox zone
	tween(house, {
		x: 1024
	}, {
		duration: 1000,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			isHouseTransitioning = false;
			ensureMailboxForTurn(); // mailbox priority
		}
	});
	return house;
}
function removeHouse(house, onComplete) {
	if (!house) {
		return;
	}
	isHouseTransitioning = true;
	tween(house, {
		x: -200
	}, {
		duration: 1000,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			house.destroy();
			var index = houses.indexOf(house);
			if (index !== -1) {
				houses.splice(index, 1);
			}
			isHouseTransitioning = false;
			turnComplete = true;
			if (onComplete) {
				onComplete();
			}
		}
	});
}
function createMailbox() {
	if (!currentHouse) {
		return;
	}
	var mailbox = new Mailbox();
	// Calculate house position and width to avoid overlap
	var houseX = currentHouse.x;
	var houseWidth = 900; // house asset width
	var houseLeftEdge = houseX - houseWidth * 0.5;
	var houseRightEdge = houseX + houseWidth * 0.5;
	// Generate random position that doesn't overlap with house
	var mailboxX;
	var attempts = 0;
	do {
		mailboxX = 400 + Math.random() * 1200; // stays in safe horizontal range
		attempts++;
		// Safety check to prevent infinite loop
		if (attempts > 50) {
			// If we can't find a spot, place it far from house
			if (houseX > 1024) {
				mailboxX = 500; // place on left side
			} else {
				mailboxX = 1500; // place on right side
			}
			break;
		}
	} while (mailboxX >= houseLeftEdge - 100 && mailboxX <= houseRightEdge + 100);
	mailbox.x = mailboxX;
	mailbox.y = mailboxZoneY + (Math.random() * 200 - 100);
	// Random horizontal flip
	if (Math.random() < 0.5) {
		mailbox.scaleX = -1;
	} else {
		mailbox.scaleX = 1;
	}
	mailboxes.push(mailbox);
	game.addChild(mailbox);
	// Ensure mailbox is drawn in front of house
	game.setChildIndex(mailbox, game.getChildIndex(currentHouse) + 1);
	return mailbox;
}
function shootNewspaper(power, angle) {
	var newspaper = new Newspaper();
	newspaper.x = 1024; // slingshot center
	newspaper.y = 2200; // bottom
	// Use power + angle for velocity
	newspaper.vx = Math.cos(angle) * power;
	newspaper.vy = Math.sin(angle) * power;
	newspapers.push(newspaper);
	game.addChild(newspaper);
	LK.getSound('Paperthrow').play();
}
function updateSlingshotBands(endX, endY) {
	bandLeft.removeChildren();
	bandRight.removeChildren();
	// Don't draw visible bands - keep containers for positioning only
}
function calculateScore(distance) {
	if (distance < 15) {
		return 5;
	} // Perfect hit
	if (distance < 25) {
		return 4;
	} // Great hit
	if (distance < 35) {
		return 3;
	} // Good hit
	if (distance < 45) {
		return 2;
	} // OK hit
	return 1; // Glancing hit
}
function payoutFor(distancePx) {
	if (distancePx <= 25) return {
		cents: 25,
		label: '+25¢ Perfect!'
	};
	if (distancePx <= 60) return {
		cents: 15,
		label: '+15¢ Very close'
	};
	if (distancePx <= 120) return {
		cents: 5,
		label: '+5¢ Close'
	};
	return null;
}
function updateTrajectory(originX, originY, pullX, pullY) {
	// Clear any previous drawing
	trajectoryLine.removeChildren();
	if (!isAiming) return;
	// Launch vector = opposite of pull
	var dx = originX - pullX;
	var dy = originY - pullY;
	var power = Math.sqrt(dx * dx + dy * dy) * 0.1;
	var angle = Math.atan2(dy, dx);
	// Launch velocity
	var vX = Math.cos(angle) * power;
	var vY = Math.sin(angle) * power;
	// Choose a projection distance (how long the line should be)
	var projectionTime = 80; // tweak for how far line extends
	var g = 0.3;
	// Predict end point of the line
	var endX = originX + vX * projectionTime;
	var endY = originY + vY * projectionTime - 0.5 * g * projectionTime * projectionTime;
	// Create line graphic
	var lineGraphic = trajectoryLine.addChild(LK.getAsset('trajectory', {
		width: Math.sqrt((endX - originX) * (endX - originX) + (endY - originY) * (endY - originY)),
		height: 4,
		color: 0x00ff00,
		anchorX: 0,
		anchorY: 0.5
	}));
	lineGraphic.x = originX;
	lineGraphic.y = originY;
	lineGraphic.rotation = Math.atan2(endY - originY, endX - originX);
	lineGraphic.alpha = 0.7;
}
// Game input handlers - natural slingshot controls
game.down = function (x, y, obj) {
	// Only allow aiming if player clicks/touches near the slingshot
	if (y > streetZoneY - 200) {
		isAiming = true;
		aimStartX = x;
		aimStartY = y;
		// Pull origin indicator is already positioned and visible
		// No need to reposition it during aiming
	}
};
game.move = function (x, y, obj) {
	if (isAiming) {
		// Draw a preview trajectory
		updateTrajectory(1024, 2000, x, y);
		// Compute pull distance for power
		var dx = 1024 - x;
		var dy = 2200 - y;
		var pullDistance = Math.sqrt(dx * dx + dy * dy);
		var maxPull = 600; // clamp so bar doesn't overflow
		var percent = Math.min(1, pullDistance / maxPull);
		// Dynamic color based on power level
		var color = 0x00ff00; // green
		if (percent > 0.66) {
			color = 0xff0000; // red
		} else if (percent > 0.33) {
			color = 0xffff00; // yellow
		}
		// Re-create the fill shape with new color and width
		powerBarFill.destroy();
		powerBarFill = LK.getAsset('powerBarFillShape', {
			width: percent * 300,
			color: color,
			anchorX: 0,
			anchorY: 0.5
		});
		powerBarFill.x = powerBarBG.x - 150;
		powerBarFill.y = powerBarBG.y;
		LK.gui.top.addChild(powerBarFill);
	}
};
game.up = function (x, y, obj) {
	if (!isAiming || hasThrownThisTurn) return;
	var originX = 1024,
		originY = 2000; // slingshot base moved up by 100 pixels
	var pullX = x - originX;
	var pullY = y - originY;
	// Launch vector = opposite of pull
	var launchX = -pullX;
	var launchY = -pullY;
	// Power is proportional to pull distance
	var pullDistance = Math.sqrt(launchX * launchX + launchY * launchY);
	var powerScale = 0.15; // tweak this number to control speed
	var power = pullDistance * powerScale;
	// Angle from pull-back vector
	var angle = Math.atan2(launchY, launchX);
	if (power > 2) {
		shootNewspaper(power, angle);
		hasThrownThisTurn = true;
	}
	// Reset aiming visuals
	isAiming = false;
	trajectoryLine.removeChildren();
	// Pull origin indicator stays visible
	powerBarFill.width = 0;
};
game.update = function () {
	gameTime++;
	// Update sun position (moves across sky as timer)
	var timeProgress = gameTime / maxGameTime;
	sun.x = sunStartX + (sunEndX - sunStartX) * timeProgress;
	sun.y = sunBaseY - Math.sin(timeProgress * Math.PI) * sunArcHeight;
	// Sky color progression with smooth transitions
	var skyColors = [{
		t: 0.0,
		color: 0xE6E6FA
	},
	// Lavender
	{
		t: 0.2,
		color: 0xADD8E6
	},
	// Light Blue
	{
		t: 0.4,
		color: 0x87CEEB
	},
	// Bright Blue
	{
		t: 0.7,
		color: 0xFFA500
	},
	// Orange
	{
		t: 1.0,
		color: 0x4B0082
	} // Deep Purple
	];
	// Find the two colors to interpolate between
	for (var i = 0; i < skyColors.length - 1; i++) {
		var c1 = skyColors[i];
		var c2 = skyColors[i + 1];
		if (timeProgress >= c1.t && timeProgress <= c2.t) {
			var localT = (timeProgress - c1.t) / (c2.t - c1.t);
			var blended = lerpColor(c1.color, c2.color, localT);
			game.setBackgroundColor(blended);
			break;
		}
	}
	// Turn-based house cycle management
	if (turnComplete && !isHouseTransitioning && !currentHouse) {
		createHouse(); // mailbox is guaranteed in onFinish
	}
	// Watchdog: if for any reason a mailbox isn't present, create one.
	if (currentHouse && !isHouseTransitioning && mailboxes.length === 0) {
		ensureMailboxForTurn();
	}
	// Update newspapers
	for (var i = newspapers.length - 1; i >= 0; i--) {
		var newspaper = newspapers[i];
		if (!newspaper.active) {
			newspaper.destroy();
			newspapers.splice(i, 1);
			continue;
		}
		// Check if newspaper went off screen without hitting (miss)
		if (newspaper.active && (newspaper.x > 2048 || newspaper.y > 2732)) {
			newspaper.active = false;
			// End the turn if no hit occurred
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					// Clear mailboxes for this turn
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
			continue;
		}
		// Check mailbox collisions
		for (var j = 0; j < mailboxes.length; j++) {
			var m = mailboxes[j];
			if (m.hit) continue;
			// enlarge hitbox with tolerance for better hit detection
			var gfx = m.children && m.children[0] ? m.children[0] : m;
			var halfW = (gfx.width || 100) * 0.5;
			var fullH = gfx.height || 100;
			var left = m.x - halfW;
			var right = m.x + halfW;
			var top = m.y - fullH;
			var bottom = m.y;
			// loosen bounds by 20px in all directions
			var tol = 20;
			var insideX = newspaper.x >= left - tol && newspaper.x <= right + tol;
			var insideY = newspaper.y >= top - tol && newspaper.y <= bottom + tol;
			if (!insideX || !insideY) continue;
			// compute accuracy off the mailbox "mouth"
			var mouthY = m.y - fullH * 0.6;
			var dx = newspaper.x - m.x;
			var dy = newspaper.y - mouthY;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// if payoutFor returns null (too far), still give a glancing hit
			var res = payoutFor(dist) || {
				cents: 5,
				label: '+5¢ Close enough'
			};
			pennies += res.cents;
			updatePaycheck();
			m.hit = true;
			newspaper.active = false;
			// floating green payout text that fades away (large and bold)
			var _float = new Text2(res.label, {
				size: 72,
				fill: 0x00aa00,
				font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
			});
			_float.anchor.set(0.5, 1);
			_float.x = m.x;
			_float.y = top - 10;
			game.addChild(_float);
			tween(_float, {
				y: _float.y - 80,
				alpha: 0
			}, {
				duration: 800,
				onFinish: function onFinish() {
					_float.destroy();
				}
			});
			LK.effects.flashObject(m, 0x00ff00, 500);
			LK.getSound('MailboxHit').play();
			// end turn after scoring (keep existing cleanup behavior)
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
			break;
		}
	}
	// Update and clean up mailboxes
	for (var i = mailboxes.length - 1; i >= 0; i--) {
		var mailbox = mailboxes[i];
		if (!mailbox.active) {
			mailbox.destroy();
			mailboxes.splice(i, 1);
		}
	}
	// Update and clean up houses
	for (var i = houses.length - 1; i >= 0; i--) {
		var house = houses[i];
		if (!house.active) {
			house.destroy();
			houses.splice(i, 1);
		}
	}
	// Check win condition
	if (pennies >= targetPennies) {
		LK.showYouWin();
	}
	// Infinite-scroll treeline every frame with parallax effect
	if (currentHouse) {
		var houseSpeed = prevHouseX - currentHouse.x;
		// Apply parallax factor to create depth - trees move slower than houses
		var parallaxSpeed = houseSpeed * treeParallaxFactor;
		updateTreeline(parallaxSpeed);
		prevHouseX = currentHouse.x;
	}
	// Ensure treeline is always behind mailbox zone
	game.setChildIndex(treelineContainer, game.getChildIndex(mailboxZone) - 1);
	// Force aiming visuals to always render on top
	game.setChildIndex(trajectoryLine, game.children.length - 1);
	game.setChildIndex(pullOriginIndicator, game.children.length - 2);
	// Check lose condition
	if (gameTime >= maxGameTime) {
		LK.showGameOver();
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var House = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('house', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.active = true;
	// Remove scrolling from update, handled by tweens
	self.update = function () {};
	return self;
});
var Mailbox = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('mailbox', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.hit = false;
	self.active = true;
	self.update = function () {}; // no auto-scrolling
	return self;
});
var Newspaper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('newspaper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Physics properties
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0.4;
	self.active = true;
	// Store starting position for scaling math
	self.startY = null;
	self.update = function () {
		if (!self.active) {
			return;
		}
		// Apply velocity
		self.x += self.vx;
		self.y += self.vy;
		// Apply gravity
		self.vy += self.gravity;
		// Record starting Y on first update
		if (self.startY === null) {
			self.startY = self.y;
		}
		// Scale down as it rises (depth effect)
		var travel = self.startY - self.y;
		var scaleFactor = Math.max(0.2, 1 - travel / 1500);
		graphics.scaleX = graphics.scaleY = scaleFactor;
		// Cleanup when it goes "into the distance"
		if (self.y < mailboxZoneY - 300 || self.y > 2732 || self.x < -200 || self.x > 2300) {
			self.active = false;
			// Trigger turn end if this was the last shot
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					// Clear leftover mailboxes
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x87ceeb
});
/**** 
* Game Code
****/ 
// green
// orange
game.setBackgroundColor(0x87ceeb);
// Start background music immediately when game loads
LK.playMusic('MothmanBoogie');
/**** 
* Color Interpolation Helper
****/ 
function lerpColor(c1, c2, t) {
	var r1 = c1 >> 16 & 0xff,
		g1 = c1 >> 8 & 0xff,
		b1 = c1 & 0xff;
	var r2 = c2 >> 16 & 0xff,
		g2 = c2 >> 8 & 0xff,
		b2 = c2 & 0xff;
	var r = Math.round(r1 + (r2 - r1) * t);
	var g = Math.round(g1 + (g2 - g1) * t);
	var b = Math.round(b1 + (b2 - b1) * t);
	return r << 16 | g << 8 | b;
}
/**** 
* Sun Path Parameters
****/ 
// Sun path parameters
var sunStartX = 100; // left side
var sunEndX = 1948; // right side
var sunBaseY = 600; // baseline (sky zone level)
var sunArcHeight = 400; // how high the sun climbs
/**** 
* Zone Setup
****/ 
// Define Y positions for zones (adjust as needed to match your reference image)
var streetZoneY = 2000; // Green bottom zone where slingshot sits
var mailboxZoneY = 1200; // Orange middle zone where mailbox spawns
var houseZoneY = 1000; // Houses aligned just above mailbox zone
// Ground reference (for houses)
var groundY = 2400;
/**** 
* Visual Zone Placeholders
****/ 
// Street zone background (green)
var streetZone = game.addChild(LK.getAsset('streetZone', {
	anchorX: 0.5,
	anchorY: 0.5
}));
streetZone.x = 1024;
streetZone.y = streetZoneY;
// Mailbox zone background (orange)
var mailboxZone = game.addChild(LK.getAsset('mailboxZone', {
	anchorX: 0.5,
	anchorY: 0.5
}));
mailboxZone.x = 1024;
mailboxZone.y = mailboxZoneY;
// Treeline container to move with houses
var treelineContainer = new Container();
// compute how many tiles we need to cover the screen plus one extra on each side
var tileWidth = LK.getAsset('treeline', {}).width;
var screenWidth = 2048; // your game width
var sideBuffers = 2; // two extra tiles on left side, one on right
var tileCount = Math.ceil(screenWidth / tileWidth) + sideBuffers * 2 + 1; // +1 for additional right side duplicate
var treelines = [];
for (var i = 0; i < tileCount; i++) {
	var tile = treelineContainer.addChild(LK.getAsset('treeline', {
		anchorX: 0,
		anchorY: 1
	}));
	// position so that the first tile starts at –tileWidth
	tile.x = (i - sideBuffers) * tileWidth;
	tile.y = 0;
	treelines.push(tile);
}
// lock the whole strip at the correct vertical position
treelineContainer.x = 0;
treelineContainer.y = mailboxZoneY - 350;
// Add treeline container before other game elements to render behind them
game.addChild(treelineContainer);
// Parallax scrolling parameters
var baseSpeed = 5; // Base movement speed for reference
var treeParallaxFactor = 0.2; // Trees move at 20% of house speed for depth effect
// Update function for treeline infinite scroll
function updateTreeline(speed) {
	for (var i = 0; i < treelines.length; i++) {
		var t = treelines[i];
		t.x -= speed;
		// Snap positions to integers to prevent floating-point drift
		t.x = Math.round(t.x);
	}
	// After moving, check for wrap and re-align all treelines to be flush
	// Find the leftmost treeline
	var leftMostIndex = 0;
	var leftMostX = treelines[0].x;
	for (var i = 1; i < treelines.length; i++) {
		if (treelines[i].x < leftMostX) {
			leftMostX = treelines[i].x;
			leftMostIndex = i;
		}
	}
	// Now, starting from leftmost, set each treeline's x so they are flush
	var startX = treelines[leftMostIndex].x;
	for (var i = 0; i < treelines.length; i++) {
		var idx = (leftMostIndex + i) % treelines.length;
		if (i === 0) {
			treelines[idx].x = startX;
		} else {
			treelines[idx].x = treelines[(idx - 1 + treelines.length) % treelines.length].x + tileWidth;
		}
	}
	// If any treeline is now off the left edge, move it to the right of the last one
	for (var i = 0; i < treelines.length; i++) {
		var t = treelines[i];
		if (t.x + tileWidth < 0) {
			// Find the rightmost treeline
			var rightMost = Math.max.apply(Math, treelines.map(function (tr) {
				return tr.x;
			}));
			t.x = rightMost + tileWidth - 1; // subtract 1px to overlap
		}
	}
}
// Game variables
var mothman;
var sun;
var slingshot;
var newspapers = [];
var mailboxes = [];
var houses = [];
var trajectoryDots = [];
// Create one reusable graphics line for the trajectory
var trajectoryLine = new Container();
// Pull-back origin indicator will be created after slingshot for proper layering
var pullOriginIndicator;
var pennies = 0;
var targetPennies = 650;
var gameTime = 0;
var maxGameTime = 18000; // 5 minutes at 60fps
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var aimPower = 0;
var aimAngle = 0;
var hasThrownThisTurn = false;
// Create UI
var paycheckText = new Text2('Paycheck: $0.00', {
	size: 65,
	fill: 0x006400,
	font: "'Comic Sans MS', cursive"
});
paycheckText.anchor.set(0.5, 0);
paycheckText.y = 100;
LK.gui.top.addChild(paycheckText);
function updatePaycheck() {
	paycheckText.setText('Paycheck: $' + (pennies / 100).toFixed(2));
}
// Power bar background + fill
var powerBarBG = LK.getAsset('powerBarBGShape', {
	anchorX: 0.5,
	anchorY: 0.5
});
powerBarBG.x = 1024;
powerBarBG.y = 200; // top center instead of bottom
LK.gui.top.addChild(powerBarBG);
var powerBarFill = LK.getAsset('powerBarFillShape', {
	width: 0,
	// start empty
	anchorX: 0,
	anchorY: 0.5
});
powerBarFill.x = powerBarBG.x - 150;
powerBarFill.y = powerBarBG.y;
LK.gui.top.addChild(powerBarFill);
// Create mothman
mothman = game.addChild(new Container());
var mothmanGraphics = mothman.attachAsset('mothman', {
	anchorX: 0.5,
	anchorY: 0.5
});
mothman.x = 200;
mothman.y = 400;
// Hide mothman (no sprite during gameplay)
mothman.visible = false;
// Create pull origin indicator after mothman to ensure proper layering in front
pullOriginIndicator = LK.getAsset('aimOriginShape', {
	anchorX: 0.5,
	anchorY: 0.5
});
// Position the aim origin indicator at slingshot position, moved up by 100 pixels
pullOriginIndicator.x = 1024;
pullOriginIndicator.y = 2000; // streetZoneY (2000) + 100 - 100 = 2000
pullOriginIndicator.visible = true; // Always visible
// Add aiming visuals after mothman to ensure they render on top
game.addChild(trajectoryLine);
game.addChild(pullOriginIndicator);
// Create sun
sun = game.addChild(new Container());
var sunGraphics = sun.attachAsset('sun', {
	anchorX: 0.5,
	anchorY: 0.5
});
sun.x = sunStartX;
sun.y = sunBaseY - sunArcHeight;
/**** 
* Draw Sun Arc Path
****/ 
// Draw sun trajectory arc with dotted path
function drawSunPath() {
	for (var t = 0; t <= 1; t += 0.05) {
		var x = sunStartX + (sunEndX - sunStartX) * t;
		var y = sunBaseY - Math.sin(t * Math.PI) * sunArcHeight;
		var dot = game.addChild(LK.getAsset('trajectory', {
			width: 6,
			height: 6,
			color: 0xffff66,
			// pale yellow
			anchorX: 0.5,
			anchorY: 0.5
		}));
		dot.x = x;
		dot.y = y;
		dot.alpha = 0.3; // semi-transparent
	}
}
drawSunPath();
// Create slingshot area - positioned in street zone center
slingshot = game.addChild(new Container());
var slingshotGraphics = slingshot.attachAsset('slingshot', {
	anchorX: 0.5,
	anchorY: 0.5
});
slingshot.x = 1024; // center of screen
slingshot.y = streetZoneY + 100;
// Slingshot bands (for stretch feedback)
var bandLeft = new Container();
var bandRight = new Container();
game.addChild(bandLeft);
game.addChild(bandRight);
// Ground level
var groundY = 2400;
// Turn-based house cycle variables
var currentHouse = null;
var isHouseTransitioning = false;
var turnComplete = true;
var prevHouseX = 1024; // Track previous house X position for treeline scroll
function ensureMailboxForTurn() {
	// Clear leftover mailboxes
	for (var k = mailboxes.length - 1; k >= 0; k--) {
		mailboxes[k].destroy();
		mailboxes.splice(k, 1);
	}
	createMailbox(); // always create (no RNG)
}
function createHouse() {
	var house = new House();
	// Start just off-screen to the right
	house.x = 2200;
	house.y = mailboxZoneY + 250; // roughly center mailbox zone
	houses.push(house);
	game.addChild(house);
	currentHouse = house;
	isHouseTransitioning = true;
	turnComplete = false;
	hasThrownThisTurn = false;
	// Tween it into center of mailbox zone
	tween(house, {
		x: 1024
	}, {
		duration: 1000,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			isHouseTransitioning = false;
			ensureMailboxForTurn(); // mailbox priority
		}
	});
	return house;
}
function removeHouse(house, onComplete) {
	if (!house) {
		return;
	}
	isHouseTransitioning = true;
	tween(house, {
		x: -200
	}, {
		duration: 1000,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			house.destroy();
			var index = houses.indexOf(house);
			if (index !== -1) {
				houses.splice(index, 1);
			}
			isHouseTransitioning = false;
			turnComplete = true;
			if (onComplete) {
				onComplete();
			}
		}
	});
}
function createMailbox() {
	if (!currentHouse) {
		return;
	}
	var mailbox = new Mailbox();
	// Calculate house position and width to avoid overlap
	var houseX = currentHouse.x;
	var houseWidth = 900; // house asset width
	var houseLeftEdge = houseX - houseWidth * 0.5;
	var houseRightEdge = houseX + houseWidth * 0.5;
	// Generate random position that doesn't overlap with house
	var mailboxX;
	var attempts = 0;
	do {
		mailboxX = 400 + Math.random() * 1200; // stays in safe horizontal range
		attempts++;
		// Safety check to prevent infinite loop
		if (attempts > 50) {
			// If we can't find a spot, place it far from house
			if (houseX > 1024) {
				mailboxX = 500; // place on left side
			} else {
				mailboxX = 1500; // place on right side
			}
			break;
		}
	} while (mailboxX >= houseLeftEdge - 100 && mailboxX <= houseRightEdge + 100);
	mailbox.x = mailboxX;
	mailbox.y = mailboxZoneY + (Math.random() * 200 - 100);
	// Random horizontal flip
	if (Math.random() < 0.5) {
		mailbox.scaleX = -1;
	} else {
		mailbox.scaleX = 1;
	}
	mailboxes.push(mailbox);
	game.addChild(mailbox);
	// Ensure mailbox is drawn in front of house
	game.setChildIndex(mailbox, game.getChildIndex(currentHouse) + 1);
	return mailbox;
}
function shootNewspaper(power, angle) {
	var newspaper = new Newspaper();
	newspaper.x = 1024; // slingshot center
	newspaper.y = 2200; // bottom
	// Use power + angle for velocity
	newspaper.vx = Math.cos(angle) * power;
	newspaper.vy = Math.sin(angle) * power;
	newspapers.push(newspaper);
	game.addChild(newspaper);
	LK.getSound('Paperthrow').play();
}
function updateSlingshotBands(endX, endY) {
	bandLeft.removeChildren();
	bandRight.removeChildren();
	// Don't draw visible bands - keep containers for positioning only
}
function calculateScore(distance) {
	if (distance < 15) {
		return 5;
	} // Perfect hit
	if (distance < 25) {
		return 4;
	} // Great hit
	if (distance < 35) {
		return 3;
	} // Good hit
	if (distance < 45) {
		return 2;
	} // OK hit
	return 1; // Glancing hit
}
function payoutFor(distancePx) {
	if (distancePx <= 25) return {
		cents: 25,
		label: '+25¢ Perfect!'
	};
	if (distancePx <= 60) return {
		cents: 15,
		label: '+15¢ Very close'
	};
	if (distancePx <= 120) return {
		cents: 5,
		label: '+5¢ Close'
	};
	return null;
}
function updateTrajectory(originX, originY, pullX, pullY) {
	// Clear any previous drawing
	trajectoryLine.removeChildren();
	if (!isAiming) return;
	// Launch vector = opposite of pull
	var dx = originX - pullX;
	var dy = originY - pullY;
	var power = Math.sqrt(dx * dx + dy * dy) * 0.1;
	var angle = Math.atan2(dy, dx);
	// Launch velocity
	var vX = Math.cos(angle) * power;
	var vY = Math.sin(angle) * power;
	// Choose a projection distance (how long the line should be)
	var projectionTime = 80; // tweak for how far line extends
	var g = 0.3;
	// Predict end point of the line
	var endX = originX + vX * projectionTime;
	var endY = originY + vY * projectionTime - 0.5 * g * projectionTime * projectionTime;
	// Create line graphic
	var lineGraphic = trajectoryLine.addChild(LK.getAsset('trajectory', {
		width: Math.sqrt((endX - originX) * (endX - originX) + (endY - originY) * (endY - originY)),
		height: 4,
		color: 0x00ff00,
		anchorX: 0,
		anchorY: 0.5
	}));
	lineGraphic.x = originX;
	lineGraphic.y = originY;
	lineGraphic.rotation = Math.atan2(endY - originY, endX - originX);
	lineGraphic.alpha = 0.7;
}
// Game input handlers - natural slingshot controls
game.down = function (x, y, obj) {
	// Only allow aiming if player clicks/touches near the slingshot
	if (y > streetZoneY - 200) {
		isAiming = true;
		aimStartX = x;
		aimStartY = y;
		// Pull origin indicator is already positioned and visible
		// No need to reposition it during aiming
	}
};
game.move = function (x, y, obj) {
	if (isAiming) {
		// Draw a preview trajectory
		updateTrajectory(1024, 2000, x, y);
		// Compute pull distance for power
		var dx = 1024 - x;
		var dy = 2200 - y;
		var pullDistance = Math.sqrt(dx * dx + dy * dy);
		var maxPull = 600; // clamp so bar doesn't overflow
		var percent = Math.min(1, pullDistance / maxPull);
		// Dynamic color based on power level
		var color = 0x00ff00; // green
		if (percent > 0.66) {
			color = 0xff0000; // red
		} else if (percent > 0.33) {
			color = 0xffff00; // yellow
		}
		// Re-create the fill shape with new color and width
		powerBarFill.destroy();
		powerBarFill = LK.getAsset('powerBarFillShape', {
			width: percent * 300,
			color: color,
			anchorX: 0,
			anchorY: 0.5
		});
		powerBarFill.x = powerBarBG.x - 150;
		powerBarFill.y = powerBarBG.y;
		LK.gui.top.addChild(powerBarFill);
	}
};
game.up = function (x, y, obj) {
	if (!isAiming || hasThrownThisTurn) return;
	var originX = 1024,
		originY = 2000; // slingshot base moved up by 100 pixels
	var pullX = x - originX;
	var pullY = y - originY;
	// Launch vector = opposite of pull
	var launchX = -pullX;
	var launchY = -pullY;
	// Power is proportional to pull distance
	var pullDistance = Math.sqrt(launchX * launchX + launchY * launchY);
	var powerScale = 0.15; // tweak this number to control speed
	var power = pullDistance * powerScale;
	// Angle from pull-back vector
	var angle = Math.atan2(launchY, launchX);
	if (power > 2) {
		shootNewspaper(power, angle);
		hasThrownThisTurn = true;
	}
	// Reset aiming visuals
	isAiming = false;
	trajectoryLine.removeChildren();
	// Pull origin indicator stays visible
	powerBarFill.width = 0;
};
game.update = function () {
	gameTime++;
	// Update sun position (moves across sky as timer)
	var timeProgress = gameTime / maxGameTime;
	sun.x = sunStartX + (sunEndX - sunStartX) * timeProgress;
	sun.y = sunBaseY - Math.sin(timeProgress * Math.PI) * sunArcHeight;
	// Sky color progression with smooth transitions
	var skyColors = [{
		t: 0.0,
		color: 0xE6E6FA
	},
	// Lavender
	{
		t: 0.2,
		color: 0xADD8E6
	},
	// Light Blue
	{
		t: 0.4,
		color: 0x87CEEB
	},
	// Bright Blue
	{
		t: 0.7,
		color: 0xFFA500
	},
	// Orange
	{
		t: 1.0,
		color: 0x4B0082
	} // Deep Purple
	];
	// Find the two colors to interpolate between
	for (var i = 0; i < skyColors.length - 1; i++) {
		var c1 = skyColors[i];
		var c2 = skyColors[i + 1];
		if (timeProgress >= c1.t && timeProgress <= c2.t) {
			var localT = (timeProgress - c1.t) / (c2.t - c1.t);
			var blended = lerpColor(c1.color, c2.color, localT);
			game.setBackgroundColor(blended);
			break;
		}
	}
	// Turn-based house cycle management
	if (turnComplete && !isHouseTransitioning && !currentHouse) {
		createHouse(); // mailbox is guaranteed in onFinish
	}
	// Watchdog: if for any reason a mailbox isn't present, create one.
	if (currentHouse && !isHouseTransitioning && mailboxes.length === 0) {
		ensureMailboxForTurn();
	}
	// Update newspapers
	for (var i = newspapers.length - 1; i >= 0; i--) {
		var newspaper = newspapers[i];
		if (!newspaper.active) {
			newspaper.destroy();
			newspapers.splice(i, 1);
			continue;
		}
		// Check if newspaper went off screen without hitting (miss)
		if (newspaper.active && (newspaper.x > 2048 || newspaper.y > 2732)) {
			newspaper.active = false;
			// End the turn if no hit occurred
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					// Clear mailboxes for this turn
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
			continue;
		}
		// Check mailbox collisions
		for (var j = 0; j < mailboxes.length; j++) {
			var m = mailboxes[j];
			if (m.hit) continue;
			// enlarge hitbox with tolerance for better hit detection
			var gfx = m.children && m.children[0] ? m.children[0] : m;
			var halfW = (gfx.width || 100) * 0.5;
			var fullH = gfx.height || 100;
			var left = m.x - halfW;
			var right = m.x + halfW;
			var top = m.y - fullH;
			var bottom = m.y;
			// loosen bounds by 20px in all directions
			var tol = 20;
			var insideX = newspaper.x >= left - tol && newspaper.x <= right + tol;
			var insideY = newspaper.y >= top - tol && newspaper.y <= bottom + tol;
			if (!insideX || !insideY) continue;
			// compute accuracy off the mailbox "mouth"
			var mouthY = m.y - fullH * 0.6;
			var dx = newspaper.x - m.x;
			var dy = newspaper.y - mouthY;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// if payoutFor returns null (too far), still give a glancing hit
			var res = payoutFor(dist) || {
				cents: 5,
				label: '+5¢ Close enough'
			};
			pennies += res.cents;
			updatePaycheck();
			m.hit = true;
			newspaper.active = false;
			// floating green payout text that fades away (large and bold)
			var _float = new Text2(res.label, {
				size: 72,
				fill: 0x00aa00,
				font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
			});
			_float.anchor.set(0.5, 1);
			_float.x = m.x;
			_float.y = top - 10;
			game.addChild(_float);
			tween(_float, {
				y: _float.y - 80,
				alpha: 0
			}, {
				duration: 800,
				onFinish: function onFinish() {
					_float.destroy();
				}
			});
			LK.effects.flashObject(m, 0x00ff00, 500);
			LK.getSound('MailboxHit').play();
			// end turn after scoring (keep existing cleanup behavior)
			if (currentHouse && !isHouseTransitioning) {
				removeHouse(currentHouse, function () {
					currentHouse = null;
					hasThrownThisTurn = false; // reset throw flag
					for (var k = mailboxes.length - 1; k >= 0; k--) {
						mailboxes[k].destroy();
						mailboxes.splice(k, 1);
					}
				});
			}
			break;
		}
	}
	// Update and clean up mailboxes
	for (var i = mailboxes.length - 1; i >= 0; i--) {
		var mailbox = mailboxes[i];
		if (!mailbox.active) {
			mailbox.destroy();
			mailboxes.splice(i, 1);
		}
	}
	// Update and clean up houses
	for (var i = houses.length - 1; i >= 0; i--) {
		var house = houses[i];
		if (!house.active) {
			house.destroy();
			houses.splice(i, 1);
		}
	}
	// Check win condition
	if (pennies >= targetPennies) {
		LK.showYouWin();
	}
	// Infinite-scroll treeline every frame with parallax effect
	if (currentHouse) {
		var houseSpeed = prevHouseX - currentHouse.x;
		// Apply parallax factor to create depth - trees move slower than houses
		var parallaxSpeed = houseSpeed * treeParallaxFactor;
		updateTreeline(parallaxSpeed);
		prevHouseX = currentHouse.x;
	}
	// Ensure treeline is always behind mailbox zone
	game.setChildIndex(treelineContainer, game.getChildIndex(mailboxZone) - 1);
	// Force aiming visuals to always render on top
	game.setChildIndex(trajectoryLine, game.children.length - 1);
	game.setChildIndex(pullOriginIndicator, game.children.length - 2);
	// Check lose condition
	if (gameTime >= maxGameTime) {
		LK.showGameOver();
	}
};