/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Boost: Speed boost pad
var Boost = Container.expand(function () {
	var self = Container.call(this);
	var boost = self.attachAsset('boost', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
// Coin: Collectible
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coin = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For simple spin animation
	self.spinTick = 0;
	self.update = function () {
		self.spinTick++;
		coin.scaleX = 0.7 + 0.3 * Math.abs(Math.sin(self.spinTick * 0.15));
	};
	return self;
});
// Obstacle: Stationary object on the slide
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	var obs = self.attachAsset('obstacle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
// Player: The character controlled by the player
var Player = Container.expand(function () {
	var self = Container.call(this);
	var player = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For jump animation
	self.isJumping = false;
	self.jumpTick = 0;
	self.jumpDuration = 0;
	self.jumpHeight = 0;
	self.update = function () {
		if (self.isJumping) {
			self.jumpTick++;
			// Simple jump arc
			var t = self.jumpTick / self.jumpDuration;
			if (t > 1) t = 1;
			self.y = self.baseY - Math.sin(Math.PI * t) * self.jumpHeight;
			if (self.jumpTick >= self.jumpDuration) {
				self.isJumping = false;
				self.y = self.baseY;
			}
		}
	};
	// Start jump
	self.startJump = function (duration, height) {
		if (!self.isJumping) {
			self.isJumping = true;
			self.jumpTick = 0;
			self.jumpDuration = duration;
			self.jumpHeight = height;
			self.baseY = self.y;
		}
	};
	return self;
});
// SlideSegment: A piece of the slide, can be straight or curved
var SlideSegment = Container.expand(function () {
	var self = Container.call(this);
	var segment = self.attachAsset('slideSegment', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Type: 'straight', 'left', 'right', 'jump', 'boost'
	self.type = 'straight';
	// For curve: curveAmount in px, positive=right, negative=left
	self.curveAmount = 0;
	// For jump: isJump
	self.isJump = false;
	// For boost: isBoost
	self.isBoost = false;
	// For segment index
	self.segmentIndex = 0;
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a2e
});
/**** 
* Game Code
****/ 
// Speed boost
// Player character
// Coin
// Obstacle
// Slide (track) segment
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var SLIDE_WIDTH = 800;
var SLIDE_SEGMENT_HEIGHT = 300;
var PLAYER_START_X = GAME_WIDTH / 2;
var PLAYER_START_Y = GAME_HEIGHT * 0.7;
var PLAYER_MOVE_LIMIT = SLIDE_WIDTH / 2 - 80;
var PLAYER_SPEED = 18; // px per tick (vertical)
var PLAYER_MAX_SPEED = 38;
var PLAYER_MIN_SPEED = 12;
var PLAYER_ACCEL = 0.01;
var PLAYER_DECEL = 0.02;
var BOOST_SPEED = 32;
var BOOST_DURATION = 60; // ticks
var JUMP_DURATION = 50; // ticks
var JUMP_HEIGHT = 220;
var OBSTACLE_RADIUS = 60;
var COIN_RADIUS = 40;
var SLIDE_CURVE_MAX = 220; // px per segment
var SLIDE_CURVE_CHANCE = 0.25;
var OBSTACLE_CHANCE = 0.35;
var COIN_CHANCE = 0.25;
var BOOST_CHANCE = 0.10;
var JUMP_CHANCE = 0.08;
// Game state
var slideSegments = [];
var obstacles = [];
var coins = [];
var boosts = [];
var player = null;
var distance = 0;
var coinCount = 0;
var speed = PLAYER_SPEED;
var boostTicks = 0;
var isGameOver = false;
var dragX = null;
var dragStartX = null;
var dragStartPlayerX = null;
var lastMoveX = null;
var lastMoveY = null;
var lastSegmentIndex = 0;
var jumpQueued = false;
// Score display (English)
var scoreTxt = new Text2('Score: 0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coin display (English)
var coinTxt = new Text2('Coins: 0', {
	size: 70,
	fill: 0xFFE066
});
// Anchor to right edge, top (so text grows leftward, not offscreen)
coinTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(coinTxt);
// Helper: Generate a slide segment
function createSlideSegment(type, curveAmount, y) {
	var seg = new SlideSegment();
	seg.type = type;
	seg.curveAmount = curveAmount || 0;
	seg.x = GAME_WIDTH / 2;
	seg.y = y;
	seg.segmentIndex = lastSegmentIndex++;
	if (type === 'left' || type === 'right') {
		seg.curveAmount = curveAmount;
	}
	if (type === 'jump') {
		seg.isJump = true;
	}
	if (type === 'boost') {
		seg.isBoost = true;
	}
	slideSegments.push(seg);
	game.addChild(seg);
	return seg;
}
// Helper: Generate an obstacle
function createObstacle(x, y) {
	var obs = new Obstacle();
	obs.x = x;
	obs.y = y;
	obstacles.push(obs);
	game.addChild(obs);
	return obs;
}
// Helper: Generate a coin
function createCoin(x, y) {
	var c = new Coin();
	c.x = x;
	c.y = y;
	coins.push(c);
	game.addChild(c);
	return c;
}
// Helper: Generate a boost
function createBoost(x, y) {
	var b = new Boost();
	b.x = x;
	b.y = y;
	boosts.push(b);
	game.addChild(b);
	return b;
}
// Helper: Remove offscreen objects
function cleanupObjects() {
	// Slide segments
	for (var i = slideSegments.length - 1; i >= 0; i--) {
		if (slideSegments[i].y > GAME_HEIGHT + SLIDE_SEGMENT_HEIGHT) {
			slideSegments[i].destroy();
			slideSegments.splice(i, 1);
		}
	}
	// Obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		if (obstacles[i].y > GAME_HEIGHT + 200) {
			obstacles[i].destroy();
			obstacles.splice(i, 1);
		}
	}
	// Coins
	for (var i = coins.length - 1; i >= 0; i--) {
		if (coins[i].y > GAME_HEIGHT + 200) {
			coins[i].destroy();
			coins.splice(i, 1);
		}
	}
	// Boosts
	for (var i = boosts.length - 1; i >= 0; i--) {
		if (boosts[i].y > GAME_HEIGHT + 200) {
			boosts[i].destroy();
			boosts.splice(i, 1);
		}
	}
}
// Helper: Generate next slide segment (randomly)
function generateNextSegment() {
	var lastSeg = slideSegments[slideSegments.length - 1];
	var y = lastSeg.y - SLIDE_SEGMENT_HEIGHT;
	var type = 'straight';
	var curveAmount = 0;
	var rand = Math.random();
	if (rand < SLIDE_CURVE_CHANCE) {
		// Curve
		if (Math.random() < 0.5) {
			type = 'left';
			curveAmount = -SLIDE_CURVE_MAX * (0.5 + Math.random() * 0.5);
		} else {
			type = 'right';
			curveAmount = SLIDE_CURVE_MAX * (0.5 + Math.random() * 0.5);
		}
	} else if (rand < SLIDE_CURVE_CHANCE + JUMP_CHANCE) {
		type = 'jump';
	} else if (rand < SLIDE_CURVE_CHANCE + JUMP_CHANCE + BOOST_CHANCE) {
		type = 'boost';
	}
	var seg = createSlideSegment(type, curveAmount, y);
	// Place obstacles, coins, boosts
	// Obstacles: not on jump or boost
	if (type !== 'jump' && type !== 'boost' && Math.random() < OBSTACLE_CHANCE) {
		var obsX = GAME_WIDTH / 2 + (Math.random() - 0.5) * (SLIDE_WIDTH - 200);
		createObstacle(obsX, y);
	}
	// Coins: not on jump
	if (type !== 'jump' && Math.random() < COIN_CHANCE) {
		var coinX = GAME_WIDTH / 2 + (Math.random() - 0.5) * (SLIDE_WIDTH - 200);
		createCoin(coinX, y - SLIDE_SEGMENT_HEIGHT / 3);
	}
	// Boost: only on boost segment
	if (type === 'boost') {
		createBoost(GAME_WIDTH / 2, y);
	}
}
// Helper: Check if player is on slide
function isPlayerOnSlide() {
	// Find the closest segment under the player
	var minDist = 99999;
	var seg = null;
	for (var i = 0; i < slideSegments.length; i++) {
		var s = slideSegments[i];
		var dy = Math.abs(player.y - s.y);
		if (dy < SLIDE_SEGMENT_HEIGHT / 2 && dy < minDist) {
			minDist = dy;
			seg = s;
		}
	}
	if (!seg) return false;
	// Slide center x
	var centerX = seg.x;
	// Slide width
	var width = SLIDE_WIDTH;
	// For curve, offset centerX
	if (seg.type === 'left' || seg.type === 'right') {
		centerX += seg.curveAmount * ((player.y - seg.y) / SLIDE_SEGMENT_HEIGHT);
	}
	// For jump, always on slide
	if (seg.isJump) return true;
	// Check if player.x is within slide bounds
	return Math.abs(player.x - centerX) < width / 2 - 60;
}
// Helper: Start jump
function startPlayerJump() {
	if (!player.isJumping) {
		player.startJump(JUMP_DURATION, JUMP_HEIGHT);
	}
}
// Helper: End game
function triggerGameOver() {
	if (!isGameOver) {
		isGameOver = true;
		LK.effects.flashScreen(0xff0000, 1000);
		// Calculate and set the final score so it appears in the game over popup
		var finalScore = Math.floor(distance / 10) + coinCount * 10;
		LK.setScore(finalScore);
		LK.showGameOver();
	}
}
// Initialize player
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
game.addChild(player);
// Generate initial slide
slideSegments = [];
lastSegmentIndex = 0;
var segY = PLAYER_START_Y + 200;
for (var i = 0; i < 10; i++) {
	createSlideSegment('straight', 0, segY);
	segY -= SLIDE_SEGMENT_HEIGHT;
}
// Initial objects
obstacles = [];
coins = [];
boosts = [];
distance = 0;
coinCount = 0;
speed = PLAYER_SPEED;
boostTicks = 0;
isGameOver = false;
jumpQueued = false;
// Input: Drag to steer
game.down = function (x, y, obj) {
	if (isGameOver) return;
	dragX = x;
	dragStartX = x;
	dragStartPlayerX = player.x;
	lastMoveX = x;
	lastMoveY = y;
};
game.move = function (x, y, obj) {
	if (isGameOver) return;
	if (dragX !== null) {
		var dx = x - dragStartX;
		var newX = dragStartPlayerX + dx;
		// Clamp to slide width
		var minX = GAME_WIDTH / 2 - PLAYER_MOVE_LIMIT;
		var maxX = GAME_WIDTH / 2 + PLAYER_MOVE_LIMIT;
		if (newX < minX) newX = minX;
		if (newX > maxX) newX = maxX;
		player.x = newX;
		lastMoveX = x;
		lastMoveY = y;
	}
};
game.up = function (x, y, obj) {
	dragX = null;
	dragStartX = null;
	dragStartPlayerX = null;
};
// Main game loop
game.update = function () {
	if (isGameOver) return;
	// Move slide and objects down (simulate player moving down)
	for (var i = 0; i < slideSegments.length; i++) {
		slideSegments[i].y += speed;
		// For curve, move segment center
		if (slideSegments[i].type === 'left' || slideSegments[i].type === 'right') {
			slideSegments[i].x += slideSegments[i].curveAmount * (speed / SLIDE_SEGMENT_HEIGHT);
		}
	}
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].y += speed;
	}
	for (var i = 0; i < coins.length; i++) {
		coins[i].y += speed;
		if (coins[i].update) coins[i].update();
	}
	for (var i = 0; i < boosts.length; i++) {
		boosts[i].y += speed;
	}
	// Player jump update
	if (player.update) player.update();
	// Generate new slide segments if needed
	var lastSeg = slideSegments[slideSegments.length - 1];
	while (lastSeg.y > -SLIDE_SEGMENT_HEIGHT * 0.5) {
		generateNextSegment();
		lastSeg = slideSegments[slideSegments.length - 1];
	}
	// Remove offscreen objects
	cleanupObjects();
	// Check for jump segment under player
	var onJump = false;
	for (var i = 0; i < slideSegments.length; i++) {
		var seg = slideSegments[i];
		if (seg.isJump && Math.abs(player.y - seg.y) < SLIDE_SEGMENT_HEIGHT / 2) {
			onJump = true;
			break;
		}
	}
	if (onJump && !player.isJumping) {
		startPlayerJump();
	}
	// Check for boost under player
	var onBoost = false;
	for (var i = 0; i < boosts.length; i++) {
		if (Math.abs(player.x - boosts[i].x) < 100 && Math.abs(player.y - boosts[i].y) < 80) {
			onBoost = true;
			break;
		}
	}
	if (onBoost) {
		boostTicks = BOOST_DURATION;
	}
	// Handle boost
	if (boostTicks > 0) {
		speed = BOOST_SPEED;
		boostTicks--;
	} else {
		// Gradually return to normal speed
		if (speed > PLAYER_SPEED) {
			speed -= PLAYER_DECEL;
			if (speed < PLAYER_SPEED) speed = PLAYER_SPEED;
		} else if (speed < PLAYER_SPEED) {
			speed += PLAYER_ACCEL;
			if (speed > PLAYER_SPEED) speed = PLAYER_SPEED;
		}
	}
	// Check for coin collection
	for (var i = coins.length - 1; i >= 0; i--) {
		var c = coins[i];
		if (Math.abs(player.x - c.x) < COIN_RADIUS + 40 && Math.abs(player.y - c.y) < COIN_RADIUS + 40) {
			coinCount++;
			coinTxt.setText('Coins: ' + coinCount);
			c.destroy();
			coins.splice(i, 1);
		}
	}
	// Check for obstacle collision (ignore if jumping)
	if (!player.isJumping) {
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(player.x - obs.x) < OBSTACLE_RADIUS + 50 && Math.abs(player.y - obs.y) < OBSTACLE_RADIUS + 50) {
				triggerGameOver();
				return;
			}
		}
	}
	// Check if player is on slide (unless jumping)
	if (!player.isJumping && !isPlayerOnSlide()) {
		// If player is not on slide and not jumping, trigger auto jump instead of game over
		startPlayerJump();
		// Do not trigger game over, allow jump to save the player
		// Optionally, you could add a sound or effect here
	}
	// Update distance and score
	distance += speed;
	var score = Math.floor(distance / 10) + coinCount * 10;
	scoreTxt.setText('Score: ' + score);
	// Win condition: none (endless)
};
/* End of game code */ /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Boost: Speed boost pad
var Boost = Container.expand(function () {
	var self = Container.call(this);
	var boost = self.attachAsset('boost', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
// Coin: Collectible
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coin = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For simple spin animation
	self.spinTick = 0;
	self.update = function () {
		self.spinTick++;
		coin.scaleX = 0.7 + 0.3 * Math.abs(Math.sin(self.spinTick * 0.15));
	};
	return self;
});
// Obstacle: Stationary object on the slide
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	var obs = self.attachAsset('obstacle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
// Player: The character controlled by the player
var Player = Container.expand(function () {
	var self = Container.call(this);
	var player = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For jump animation
	self.isJumping = false;
	self.jumpTick = 0;
	self.jumpDuration = 0;
	self.jumpHeight = 0;
	self.update = function () {
		if (self.isJumping) {
			self.jumpTick++;
			// Simple jump arc
			var t = self.jumpTick / self.jumpDuration;
			if (t > 1) t = 1;
			self.y = self.baseY - Math.sin(Math.PI * t) * self.jumpHeight;
			if (self.jumpTick >= self.jumpDuration) {
				self.isJumping = false;
				self.y = self.baseY;
			}
		}
	};
	// Start jump
	self.startJump = function (duration, height) {
		if (!self.isJumping) {
			self.isJumping = true;
			self.jumpTick = 0;
			self.jumpDuration = duration;
			self.jumpHeight = height;
			self.baseY = self.y;
		}
	};
	return self;
});
// SlideSegment: A piece of the slide, can be straight or curved
var SlideSegment = Container.expand(function () {
	var self = Container.call(this);
	var segment = self.attachAsset('slideSegment', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Type: 'straight', 'left', 'right', 'jump', 'boost'
	self.type = 'straight';
	// For curve: curveAmount in px, positive=right, negative=left
	self.curveAmount = 0;
	// For jump: isJump
	self.isJump = false;
	// For boost: isBoost
	self.isBoost = false;
	// For segment index
	self.segmentIndex = 0;
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a2e
});
/**** 
* Game Code
****/ 
// Speed boost
// Player character
// Coin
// Obstacle
// Slide (track) segment
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var SLIDE_WIDTH = 800;
var SLIDE_SEGMENT_HEIGHT = 300;
var PLAYER_START_X = GAME_WIDTH / 2;
var PLAYER_START_Y = GAME_HEIGHT * 0.7;
var PLAYER_MOVE_LIMIT = SLIDE_WIDTH / 2 - 80;
var PLAYER_SPEED = 18; // px per tick (vertical)
var PLAYER_MAX_SPEED = 38;
var PLAYER_MIN_SPEED = 12;
var PLAYER_ACCEL = 0.01;
var PLAYER_DECEL = 0.02;
var BOOST_SPEED = 32;
var BOOST_DURATION = 60; // ticks
var JUMP_DURATION = 50; // ticks
var JUMP_HEIGHT = 220;
var OBSTACLE_RADIUS = 60;
var COIN_RADIUS = 40;
var SLIDE_CURVE_MAX = 220; // px per segment
var SLIDE_CURVE_CHANCE = 0.25;
var OBSTACLE_CHANCE = 0.35;
var COIN_CHANCE = 0.25;
var BOOST_CHANCE = 0.10;
var JUMP_CHANCE = 0.08;
// Game state
var slideSegments = [];
var obstacles = [];
var coins = [];
var boosts = [];
var player = null;
var distance = 0;
var coinCount = 0;
var speed = PLAYER_SPEED;
var boostTicks = 0;
var isGameOver = false;
var dragX = null;
var dragStartX = null;
var dragStartPlayerX = null;
var lastMoveX = null;
var lastMoveY = null;
var lastSegmentIndex = 0;
var jumpQueued = false;
// Score display (English)
var scoreTxt = new Text2('Score: 0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coin display (English)
var coinTxt = new Text2('Coins: 0', {
	size: 70,
	fill: 0xFFE066
});
// Anchor to right edge, top (so text grows leftward, not offscreen)
coinTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(coinTxt);
// Helper: Generate a slide segment
function createSlideSegment(type, curveAmount, y) {
	var seg = new SlideSegment();
	seg.type = type;
	seg.curveAmount = curveAmount || 0;
	seg.x = GAME_WIDTH / 2;
	seg.y = y;
	seg.segmentIndex = lastSegmentIndex++;
	if (type === 'left' || type === 'right') {
		seg.curveAmount = curveAmount;
	}
	if (type === 'jump') {
		seg.isJump = true;
	}
	if (type === 'boost') {
		seg.isBoost = true;
	}
	slideSegments.push(seg);
	game.addChild(seg);
	return seg;
}
// Helper: Generate an obstacle
function createObstacle(x, y) {
	var obs = new Obstacle();
	obs.x = x;
	obs.y = y;
	obstacles.push(obs);
	game.addChild(obs);
	return obs;
}
// Helper: Generate a coin
function createCoin(x, y) {
	var c = new Coin();
	c.x = x;
	c.y = y;
	coins.push(c);
	game.addChild(c);
	return c;
}
// Helper: Generate a boost
function createBoost(x, y) {
	var b = new Boost();
	b.x = x;
	b.y = y;
	boosts.push(b);
	game.addChild(b);
	return b;
}
// Helper: Remove offscreen objects
function cleanupObjects() {
	// Slide segments
	for (var i = slideSegments.length - 1; i >= 0; i--) {
		if (slideSegments[i].y > GAME_HEIGHT + SLIDE_SEGMENT_HEIGHT) {
			slideSegments[i].destroy();
			slideSegments.splice(i, 1);
		}
	}
	// Obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		if (obstacles[i].y > GAME_HEIGHT + 200) {
			obstacles[i].destroy();
			obstacles.splice(i, 1);
		}
	}
	// Coins
	for (var i = coins.length - 1; i >= 0; i--) {
		if (coins[i].y > GAME_HEIGHT + 200) {
			coins[i].destroy();
			coins.splice(i, 1);
		}
	}
	// Boosts
	for (var i = boosts.length - 1; i >= 0; i--) {
		if (boosts[i].y > GAME_HEIGHT + 200) {
			boosts[i].destroy();
			boosts.splice(i, 1);
		}
	}
}
// Helper: Generate next slide segment (randomly)
function generateNextSegment() {
	var lastSeg = slideSegments[slideSegments.length - 1];
	var y = lastSeg.y - SLIDE_SEGMENT_HEIGHT;
	var type = 'straight';
	var curveAmount = 0;
	var rand = Math.random();
	if (rand < SLIDE_CURVE_CHANCE) {
		// Curve
		if (Math.random() < 0.5) {
			type = 'left';
			curveAmount = -SLIDE_CURVE_MAX * (0.5 + Math.random() * 0.5);
		} else {
			type = 'right';
			curveAmount = SLIDE_CURVE_MAX * (0.5 + Math.random() * 0.5);
		}
	} else if (rand < SLIDE_CURVE_CHANCE + JUMP_CHANCE) {
		type = 'jump';
	} else if (rand < SLIDE_CURVE_CHANCE + JUMP_CHANCE + BOOST_CHANCE) {
		type = 'boost';
	}
	var seg = createSlideSegment(type, curveAmount, y);
	// Place obstacles, coins, boosts
	// Obstacles: not on jump or boost
	if (type !== 'jump' && type !== 'boost' && Math.random() < OBSTACLE_CHANCE) {
		var obsX = GAME_WIDTH / 2 + (Math.random() - 0.5) * (SLIDE_WIDTH - 200);
		createObstacle(obsX, y);
	}
	// Coins: not on jump
	if (type !== 'jump' && Math.random() < COIN_CHANCE) {
		var coinX = GAME_WIDTH / 2 + (Math.random() - 0.5) * (SLIDE_WIDTH - 200);
		createCoin(coinX, y - SLIDE_SEGMENT_HEIGHT / 3);
	}
	// Boost: only on boost segment
	if (type === 'boost') {
		createBoost(GAME_WIDTH / 2, y);
	}
}
// Helper: Check if player is on slide
function isPlayerOnSlide() {
	// Find the closest segment under the player
	var minDist = 99999;
	var seg = null;
	for (var i = 0; i < slideSegments.length; i++) {
		var s = slideSegments[i];
		var dy = Math.abs(player.y - s.y);
		if (dy < SLIDE_SEGMENT_HEIGHT / 2 && dy < minDist) {
			minDist = dy;
			seg = s;
		}
	}
	if (!seg) return false;
	// Slide center x
	var centerX = seg.x;
	// Slide width
	var width = SLIDE_WIDTH;
	// For curve, offset centerX
	if (seg.type === 'left' || seg.type === 'right') {
		centerX += seg.curveAmount * ((player.y - seg.y) / SLIDE_SEGMENT_HEIGHT);
	}
	// For jump, always on slide
	if (seg.isJump) return true;
	// Check if player.x is within slide bounds
	return Math.abs(player.x - centerX) < width / 2 - 60;
}
// Helper: Start jump
function startPlayerJump() {
	if (!player.isJumping) {
		player.startJump(JUMP_DURATION, JUMP_HEIGHT);
	}
}
// Helper: End game
function triggerGameOver() {
	if (!isGameOver) {
		isGameOver = true;
		LK.effects.flashScreen(0xff0000, 1000);
		// Calculate and set the final score so it appears in the game over popup
		var finalScore = Math.floor(distance / 10) + coinCount * 10;
		LK.setScore(finalScore);
		LK.showGameOver();
	}
}
// Initialize player
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
game.addChild(player);
// Generate initial slide
slideSegments = [];
lastSegmentIndex = 0;
var segY = PLAYER_START_Y + 200;
for (var i = 0; i < 10; i++) {
	createSlideSegment('straight', 0, segY);
	segY -= SLIDE_SEGMENT_HEIGHT;
}
// Initial objects
obstacles = [];
coins = [];
boosts = [];
distance = 0;
coinCount = 0;
speed = PLAYER_SPEED;
boostTicks = 0;
isGameOver = false;
jumpQueued = false;
// Input: Drag to steer
game.down = function (x, y, obj) {
	if (isGameOver) return;
	dragX = x;
	dragStartX = x;
	dragStartPlayerX = player.x;
	lastMoveX = x;
	lastMoveY = y;
};
game.move = function (x, y, obj) {
	if (isGameOver) return;
	if (dragX !== null) {
		var dx = x - dragStartX;
		var newX = dragStartPlayerX + dx;
		// Clamp to slide width
		var minX = GAME_WIDTH / 2 - PLAYER_MOVE_LIMIT;
		var maxX = GAME_WIDTH / 2 + PLAYER_MOVE_LIMIT;
		if (newX < minX) newX = minX;
		if (newX > maxX) newX = maxX;
		player.x = newX;
		lastMoveX = x;
		lastMoveY = y;
	}
};
game.up = function (x, y, obj) {
	dragX = null;
	dragStartX = null;
	dragStartPlayerX = null;
};
// Main game loop
game.update = function () {
	if (isGameOver) return;
	// Move slide and objects down (simulate player moving down)
	for (var i = 0; i < slideSegments.length; i++) {
		slideSegments[i].y += speed;
		// For curve, move segment center
		if (slideSegments[i].type === 'left' || slideSegments[i].type === 'right') {
			slideSegments[i].x += slideSegments[i].curveAmount * (speed / SLIDE_SEGMENT_HEIGHT);
		}
	}
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].y += speed;
	}
	for (var i = 0; i < coins.length; i++) {
		coins[i].y += speed;
		if (coins[i].update) coins[i].update();
	}
	for (var i = 0; i < boosts.length; i++) {
		boosts[i].y += speed;
	}
	// Player jump update
	if (player.update) player.update();
	// Generate new slide segments if needed
	var lastSeg = slideSegments[slideSegments.length - 1];
	while (lastSeg.y > -SLIDE_SEGMENT_HEIGHT * 0.5) {
		generateNextSegment();
		lastSeg = slideSegments[slideSegments.length - 1];
	}
	// Remove offscreen objects
	cleanupObjects();
	// Check for jump segment under player
	var onJump = false;
	for (var i = 0; i < slideSegments.length; i++) {
		var seg = slideSegments[i];
		if (seg.isJump && Math.abs(player.y - seg.y) < SLIDE_SEGMENT_HEIGHT / 2) {
			onJump = true;
			break;
		}
	}
	if (onJump && !player.isJumping) {
		startPlayerJump();
	}
	// Check for boost under player
	var onBoost = false;
	for (var i = 0; i < boosts.length; i++) {
		if (Math.abs(player.x - boosts[i].x) < 100 && Math.abs(player.y - boosts[i].y) < 80) {
			onBoost = true;
			break;
		}
	}
	if (onBoost) {
		boostTicks = BOOST_DURATION;
	}
	// Handle boost
	if (boostTicks > 0) {
		speed = BOOST_SPEED;
		boostTicks--;
	} else {
		// Gradually return to normal speed
		if (speed > PLAYER_SPEED) {
			speed -= PLAYER_DECEL;
			if (speed < PLAYER_SPEED) speed = PLAYER_SPEED;
		} else if (speed < PLAYER_SPEED) {
			speed += PLAYER_ACCEL;
			if (speed > PLAYER_SPEED) speed = PLAYER_SPEED;
		}
	}
	// Check for coin collection
	for (var i = coins.length - 1; i >= 0; i--) {
		var c = coins[i];
		if (Math.abs(player.x - c.x) < COIN_RADIUS + 40 && Math.abs(player.y - c.y) < COIN_RADIUS + 40) {
			coinCount++;
			coinTxt.setText('Coins: ' + coinCount);
			c.destroy();
			coins.splice(i, 1);
		}
	}
	// Check for obstacle collision (ignore if jumping)
	if (!player.isJumping) {
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(player.x - obs.x) < OBSTACLE_RADIUS + 50 && Math.abs(player.y - obs.y) < OBSTACLE_RADIUS + 50) {
				triggerGameOver();
				return;
			}
		}
	}
	// Check if player is on slide (unless jumping)
	if (!player.isJumping && !isPlayerOnSlide()) {
		// If player is not on slide and not jumping, trigger auto jump instead of game over
		startPlayerJump();
		// Do not trigger game over, allow jump to save the player
		// Optionally, you could add a sound or effect here
	}
	// Update distance and score
	distance += speed;
	var score = Math.floor(distance / 10) + coinCount * 10;
	scoreTxt.setText('Score: ' + score);
	// Win condition: none (endless)
};
/* End of game code */
:quality(85)/https://cdn.frvr.ai/68325447028282aa344ef050.png%3F3) 
 Arttırmak. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/68335b649ea34f3d08660b48.png%3F3) 
 Madeni Para. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/68335c359ea34f3d08660b7a.png%3F3) 
 Engel. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/68335e539ea34f3d08660bee.png%3F3) 
 Çocuk. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/68335eaf9ea34f3d08660bfe.png%3F3) 
 Kaydırak. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat