/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Cactus obstacle
var Cactus = Container.expand(function () {
	var self = Container.call(this);
	var cactusSprite = self.attachAsset('cactus', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.width = cactusSprite.width;
	self.height = cactusSprite.height;
	self.speed = 0; // Set by game
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Dino (player) class
var Dino = Container.expand(function () {
	var self = Container.call(this);
	var dinoSprite = self.attachAsset('dino', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.width = dinoSprite.width;
	self.height = dinoSprite.height;
	// State
	self.isJumping = false;
	self.velocityY = 0;
	self.gravity = 2.2 * 1; // gravity is positive, pulls dino down
	self.jumpStrength = -48; // negative jumpStrength makes dino go up (y decreases)
	self.groundY = 0; // Set after adding to game
	// Jump
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.velocityY = self.jumpStrength;
			LK.getSound('jump').play();
		}
	};
	// Update per frame
	self.update = function () {
		if (self.isJumping) {
			self.y += self.velocityY;
			self.velocityY += self.gravity;
			if (self.y >= self.groundY) {
				self.y = self.groundY;
				self.isJumping = false;
				self.velocityY = 0;
			}
		}
	};
	return self;
});
// Pterodactyl obstacle
var Ptero = Container.expand(function () {
	var self = Container.call(this);
	var pteroSprite = self.attachAsset('ptero', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = pteroSprite.width;
	self.height = pteroSprite.height;
	self.speed = 0; // Set by game
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xf5f5f5
});
/**** 
* Game Code
****/ 
// Game constants
// Dinosaur (player)
// Cactus (obstacle)
// Pterodactyl (obstacle)
// Ground
// Jump sound
var GROUND_Y = 2200;
var DINO_START_X = 400;
var OBSTACLE_MIN_GAP = 700;
var OBSTACLE_MAX_GAP = 1200;
var PTERO_MIN_Y = GROUND_Y - 400;
var PTERO_MAX_Y = GROUND_Y - 700;
var GAME_SPEED_START = 22;
var GAME_SPEED_MAX = 60;
var GAME_SPEEDUP_EVERY = 600; // ticks
var GAME_SPEEDUP_AMOUNT = 1.2;
// Game state
var dino;
var ground;
var obstacles = [];
var gameSpeed = GAME_SPEED_START;
var ticksSinceLastObstacle = 0;
var nextObstacleGap = 0;
var score = 0;
var scoreTxt;
var dragNode = null;
var isTouching = false;
var ducking = false;
var lastObstacleType = null;
// Add ground
ground = LK.getAsset('ground', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: GROUND_Y + 1
});
game.addChild(ground);
// Add dino
dino = new Dino();
game.addChild(dino);
dino.x = DINO_START_X;
dino.groundY = GROUND_Y;
dino.y = GROUND_Y;
// Score text
scoreTxt = new Text2('0', {
	size: 120,
	fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn obstacle
function spawnObstacle() {
	// Increase obstacle variety as score increases
	var availableTypes = ['cactus', 'ptero'];
	if (score > 500) {
		availableTypes.push('double_cactus');
	}
	if (score > 1200) {
		availableTypes.push('low_ptero');
	}
	if (score > 2000) {
		availableTypes.push('triple_cactus');
	}
	// Randomly pick type, but avoid two pteros in a row
	var type = availableTypes[Math.floor(Math.random() * availableTypes.length)];
	if ((type === 'ptero' || type === 'low_ptero') && lastObstacleType && (lastObstacleType === 'ptero' || lastObstacleType === 'low_ptero')) {
		type = 'cactus';
	}
	lastObstacleType = type;
	var obs;
	if (type === 'cactus') {
		obs = new Cactus();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // randomize spawn x
		obs.y = GROUND_Y;
		obs.speed = gameSpeed;
		obstacles.push(obs);
		game.addChild(obs);
	} else if (type === 'double_cactus') {
		// Two cacti close together
		for (var i = 0; i < 2; i++) {
			obs = new Cactus();
			obs.x = 2048 + obs.width + i * (obs.width + 60 + Math.floor(Math.random() * 40));
			obs.y = GROUND_Y;
			obs.speed = gameSpeed;
			obstacles.push(obs);
			game.addChild(obs);
		}
	} else if (type === 'triple_cactus') {
		// Three cacti close together
		for (var i = 0; i < 3; i++) {
			obs = new Cactus();
			obs.x = 2048 + obs.width + i * (obs.width + 50 + Math.floor(Math.random() * 30));
			obs.y = GROUND_Y;
			obs.speed = gameSpeed;
			obstacles.push(obs);
			game.addChild(obs);
		}
	} else if (type === 'ptero') {
		obs = new Ptero();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
		// Randomize ptero height
		obs.y = PTERO_MIN_Y + Math.floor(Math.random() * (PTERO_MAX_Y - PTERO_MIN_Y));
		obs.speed = gameSpeed + 2;
		obstacles.push(obs);
		game.addChild(obs);
	} else if (type === 'low_ptero') {
		obs = new Ptero();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
		// Lower flying ptero, forces jump
		obs.y = GROUND_Y - 120 - Math.floor(Math.random() * 60);
		obs.speed = gameSpeed + 2.5;
		obstacles.push(obs);
		game.addChild(obs);
	}
}
// Helper: reset game state
function resetGame() {
	// Remove obstacles
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].destroy();
	}
	obstacles = [];
	gameSpeed = GAME_SPEED_START;
	ticksSinceLastObstacle = 0;
	// Reset with dynamic gap scaling
	var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
	var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
	nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
	score = 0;
	scoreTxt.setText(score);
	dino.x = DINO_START_X;
	dino.y = GROUND_Y;
	dino.isJumping = false;
	dino.velocityY = 0;
	lastObstacleType = null;
}
// Touch/drag controls
game.down = function (x, y, obj) {
	isTouching = true;
	dino.jump();
};
game.up = function (x, y, obj) {
	isTouching = false;
};
game.move = function (x, y, obj) {};
// Main game loop
game.update = function () {
	// Speed up over time
	if (LK.ticks % GAME_SPEEDUP_EVERY === 0 && gameSpeed < GAME_SPEED_MAX) {
		gameSpeed += GAME_SPEEDUP_AMOUNT;
		if (gameSpeed > GAME_SPEED_MAX) {
			gameSpeed = GAME_SPEED_MAX;
		}
	}
	// Update dino
	dino.update();
	// Update obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		obs.speed = gameSpeed + (obs instanceof Ptero ? 2 : 0);
		obs.update();
		// Remove if off screen
		if (obs.x < -300) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision detection
		if (dino.intersects(obs)) {
			LK.getSound('hit').play();
			LK.effects.flashScreen(0xff0000, 800);
			LK.showGameOver();
			return;
		}
	}
	// Obstacle spawning
	ticksSinceLastObstacle += gameSpeed;
	// Make gap smaller as score increases (min 350)
	var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
	var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
	if (ticksSinceLastObstacle >= nextObstacleGap) {
		spawnObstacle();
		ticksSinceLastObstacle = 0;
		nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
	}
	// Score increases with distance
	score += Math.floor(gameSpeed / 6);
	scoreTxt.setText(score);
	LK.setScore(score);
};
// Reset game state on game start
resetGame(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Cactus obstacle
var Cactus = Container.expand(function () {
	var self = Container.call(this);
	var cactusSprite = self.attachAsset('cactus', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.width = cactusSprite.width;
	self.height = cactusSprite.height;
	self.speed = 0; // Set by game
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Dino (player) class
var Dino = Container.expand(function () {
	var self = Container.call(this);
	var dinoSprite = self.attachAsset('dino', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.width = dinoSprite.width;
	self.height = dinoSprite.height;
	// State
	self.isJumping = false;
	self.velocityY = 0;
	self.gravity = 2.2 * 1; // gravity is positive, pulls dino down
	self.jumpStrength = -48; // negative jumpStrength makes dino go up (y decreases)
	self.groundY = 0; // Set after adding to game
	// Jump
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.velocityY = self.jumpStrength;
			LK.getSound('jump').play();
		}
	};
	// Update per frame
	self.update = function () {
		if (self.isJumping) {
			self.y += self.velocityY;
			self.velocityY += self.gravity;
			if (self.y >= self.groundY) {
				self.y = self.groundY;
				self.isJumping = false;
				self.velocityY = 0;
			}
		}
	};
	return self;
});
// Pterodactyl obstacle
var Ptero = Container.expand(function () {
	var self = Container.call(this);
	var pteroSprite = self.attachAsset('ptero', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = pteroSprite.width;
	self.height = pteroSprite.height;
	self.speed = 0; // Set by game
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xf5f5f5
});
/**** 
* Game Code
****/ 
// Game constants
// Dinosaur (player)
// Cactus (obstacle)
// Pterodactyl (obstacle)
// Ground
// Jump sound
var GROUND_Y = 2200;
var DINO_START_X = 400;
var OBSTACLE_MIN_GAP = 700;
var OBSTACLE_MAX_GAP = 1200;
var PTERO_MIN_Y = GROUND_Y - 400;
var PTERO_MAX_Y = GROUND_Y - 700;
var GAME_SPEED_START = 22;
var GAME_SPEED_MAX = 60;
var GAME_SPEEDUP_EVERY = 600; // ticks
var GAME_SPEEDUP_AMOUNT = 1.2;
// Game state
var dino;
var ground;
var obstacles = [];
var gameSpeed = GAME_SPEED_START;
var ticksSinceLastObstacle = 0;
var nextObstacleGap = 0;
var score = 0;
var scoreTxt;
var dragNode = null;
var isTouching = false;
var ducking = false;
var lastObstacleType = null;
// Add ground
ground = LK.getAsset('ground', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: GROUND_Y + 1
});
game.addChild(ground);
// Add dino
dino = new Dino();
game.addChild(dino);
dino.x = DINO_START_X;
dino.groundY = GROUND_Y;
dino.y = GROUND_Y;
// Score text
scoreTxt = new Text2('0', {
	size: 120,
	fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn obstacle
function spawnObstacle() {
	// Increase obstacle variety as score increases
	var availableTypes = ['cactus', 'ptero'];
	if (score > 500) {
		availableTypes.push('double_cactus');
	}
	if (score > 1200) {
		availableTypes.push('low_ptero');
	}
	if (score > 2000) {
		availableTypes.push('triple_cactus');
	}
	// Randomly pick type, but avoid two pteros in a row
	var type = availableTypes[Math.floor(Math.random() * availableTypes.length)];
	if ((type === 'ptero' || type === 'low_ptero') && lastObstacleType && (lastObstacleType === 'ptero' || lastObstacleType === 'low_ptero')) {
		type = 'cactus';
	}
	lastObstacleType = type;
	var obs;
	if (type === 'cactus') {
		obs = new Cactus();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // randomize spawn x
		obs.y = GROUND_Y;
		obs.speed = gameSpeed;
		obstacles.push(obs);
		game.addChild(obs);
	} else if (type === 'double_cactus') {
		// Two cacti close together
		for (var i = 0; i < 2; i++) {
			obs = new Cactus();
			obs.x = 2048 + obs.width + i * (obs.width + 60 + Math.floor(Math.random() * 40));
			obs.y = GROUND_Y;
			obs.speed = gameSpeed;
			obstacles.push(obs);
			game.addChild(obs);
		}
	} else if (type === 'triple_cactus') {
		// Three cacti close together
		for (var i = 0; i < 3; i++) {
			obs = new Cactus();
			obs.x = 2048 + obs.width + i * (obs.width + 50 + Math.floor(Math.random() * 30));
			obs.y = GROUND_Y;
			obs.speed = gameSpeed;
			obstacles.push(obs);
			game.addChild(obs);
		}
	} else if (type === 'ptero') {
		obs = new Ptero();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
		// Randomize ptero height
		obs.y = PTERO_MIN_Y + Math.floor(Math.random() * (PTERO_MAX_Y - PTERO_MIN_Y));
		obs.speed = gameSpeed + 2;
		obstacles.push(obs);
		game.addChild(obs);
	} else if (type === 'low_ptero') {
		obs = new Ptero();
		obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
		// Lower flying ptero, forces jump
		obs.y = GROUND_Y - 120 - Math.floor(Math.random() * 60);
		obs.speed = gameSpeed + 2.5;
		obstacles.push(obs);
		game.addChild(obs);
	}
}
// Helper: reset game state
function resetGame() {
	// Remove obstacles
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].destroy();
	}
	obstacles = [];
	gameSpeed = GAME_SPEED_START;
	ticksSinceLastObstacle = 0;
	// Reset with dynamic gap scaling
	var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
	var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
	nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
	score = 0;
	scoreTxt.setText(score);
	dino.x = DINO_START_X;
	dino.y = GROUND_Y;
	dino.isJumping = false;
	dino.velocityY = 0;
	lastObstacleType = null;
}
// Touch/drag controls
game.down = function (x, y, obj) {
	isTouching = true;
	dino.jump();
};
game.up = function (x, y, obj) {
	isTouching = false;
};
game.move = function (x, y, obj) {};
// Main game loop
game.update = function () {
	// Speed up over time
	if (LK.ticks % GAME_SPEEDUP_EVERY === 0 && gameSpeed < GAME_SPEED_MAX) {
		gameSpeed += GAME_SPEEDUP_AMOUNT;
		if (gameSpeed > GAME_SPEED_MAX) {
			gameSpeed = GAME_SPEED_MAX;
		}
	}
	// Update dino
	dino.update();
	// Update obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		obs.speed = gameSpeed + (obs instanceof Ptero ? 2 : 0);
		obs.update();
		// Remove if off screen
		if (obs.x < -300) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision detection
		if (dino.intersects(obs)) {
			LK.getSound('hit').play();
			LK.effects.flashScreen(0xff0000, 800);
			LK.showGameOver();
			return;
		}
	}
	// Obstacle spawning
	ticksSinceLastObstacle += gameSpeed;
	// Make gap smaller as score increases (min 350)
	var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
	var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
	if (ticksSinceLastObstacle >= nextObstacleGap) {
		spawnObstacle();
		ticksSinceLastObstacle = 0;
		nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
	}
	// Score increases with distance
	score += Math.floor(gameSpeed / 6);
	scoreTxt.setText(score);
	LK.setScore(score);
};
// Reset game state on game start
resetGame();