/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Obstacle class
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	// Randomly pick a shape for variety
	var types = ['obstacle_box', 'obstacle_ellipse', 'obstacle_tall', 'obstacle_wide'];
	var type = types[Math.floor(Math.random() * types.length)];
	var gfx = self.attachAsset(type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = type;
	// Speed will be set on creation
	self.speed = 0;
	// Update method for movement
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGfx = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For collision, use the container itself
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181818
});
/**** 
* Game Code
****/ 
// Game constants 
// --- Background ---
var bg = LK.getAsset('bg_green', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	scaleX: GAME_WIDTH / 100,
	scaleY: GAME_HEIGHT / 100
});
game.addChild(bg);
// Player character: a colored box
// Obstacle shapes (variety for visual interest)
// Heart icon for lives
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_X = GAME_WIDTH / 2;
var PLAYER_START_Y = GAME_HEIGHT - 400;
var OBSTACLE_SPAWN_Y = 220; // Top area for obstacles
var OBSTACLE_MIN_SPEED = 7;
var OBSTACLE_MAX_SPEED = 15;
var OBSTACLE_SPAWN_INTERVAL = 70; // ticks
var PLAYER_MOVE_AREA = {
	left: 180,
	right: GAME_WIDTH - 180,
	top: 600,
	bottom: GAME_HEIGHT - 100
};
var MAX_LIVES = 3;
// State variables
var player;
var obstacles = [];
var lives = MAX_LIVES;
var score = 0;
var scoreTxt;
var livesNodes = [];
var dragNode = null;
var lastScoreTick = 0;
// --- UI: Score ---
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- UI: Lives (Hearts) ---
function updateLivesUI() {
	// Remove old
	for (var i = 0; i < livesNodes.length; i++) {
		if (livesNodes[i].parent) livesNodes[i].parent.removeChild(livesNodes[i]);
	}
	livesNodes = [];
	// Place hearts at top right, spaced
	for (var i = 0; i < lives; i++) {
		var heart = LK.getAsset('heart', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: 0
		});
		// Place: right margin 60px, then 100px per heart leftward, y=100
		heart.x = GAME_WIDTH - 100 - i * 100;
		heart.y = 100;
		// Add to game (not GUI, so it scales with game)
		game.addChild(heart);
		livesNodes.push(heart);
	}
}
updateLivesUI();
// --- Player ---
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
game.addChild(player);
// --- Touch/Drag Controls ---
function clamp(val, min, max) {
	return Math.max(min, Math.min(max, val));
}
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to allowed area
		dragNode.x = clamp(x, PLAYER_MOVE_AREA.left, PLAYER_MOVE_AREA.right);
		dragNode.y = clamp(y, PLAYER_MOVE_AREA.top, PLAYER_MOVE_AREA.bottom);
	}
}
game.move = handleMove;
game.down = function (x, y, obj) {
	// Only allow drag if touch is on player or below
	if (x >= player.x - 100 && x <= player.x + 100 && y >= player.y - 100 && y <= player.y + 100) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// --- Obstacle Spawning ---
function spawnObstacle() {
	var obs = new Obstacle();
	// Random X in a central band (avoid extreme edges)
	var minX = 300,
		maxX = GAME_WIDTH - 300;
	obs.x = minX + Math.floor(Math.random() * (maxX - minX));
	obs.y = OBSTACLE_SPAWN_Y;
	// Random speed
	obs.speed = OBSTACLE_MIN_SPEED + Math.random() * (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED);
	// Optionally, for some types, add horizontal movement
	if (obs.type === 'obstacle_wide' && Math.random() < 0.5) {
		obs.horizSpeed = (Math.random() < 0.5 ? -1 : 1) * (2 + Math.random() * 3);
		obs.update = function () {
			this.y += this.speed;
			this.x += this.horizSpeed;
			// Bounce off walls
			if (this.x < 200 || this.x > GAME_WIDTH - 200) this.horizSpeed *= -1;
		};
	}
	obstacles.push(obs);
	game.addChild(obs);
}
// --- Game Update Loop ---
game.update = function () {
	// Score increases with time survived (every 30 ticks = 0.5s)
	if (LK.ticks - lastScoreTick >= 30) {
		score += 1;
		scoreTxt.setText(score);
		lastScoreTick = LK.ticks;
	}
	// Spawn obstacles
	if (LK.ticks % OBSTACLE_SPAWN_INTERVAL === 0) {
		spawnObstacle();
	}
	// Update obstacles, check for collision, remove off-screen
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		// Move
		if (typeof obs.update === 'function') obs.update();
		// Remove if off bottom
		if (obs.y > GAME_HEIGHT + 200) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision with player
		if (obs.intersects(player)) {
			// Remove obstacle
			obs.destroy();
			obstacles.splice(i, 1);
			// Lose a life
			lives -= 1;
			updateLivesUI();
			// Flash player red
			LK.effects.flashObject(player, 0xff0000, 600);
			// If out of lives, game over
			if (lives <= 0) {
				LK.effects.flashScreen(0xff0000, 1000);
				LK.showGameOver();
				return;
			}
		}
	}
};
// --- Reset on Game Over ---
LK.on('gameover', function () {
	// Reset state for new game
	lives = MAX_LIVES;
	score = 0;
	scoreTxt.setText(score);
	updateLivesUI();
	// Remove all obstacles
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].destroy();
	}
	obstacles = [];
	// Reset player position
	player.x = PLAYER_START_X;
	player.y = PLAYER_START_Y;
	dragNode = null;
	lastScoreTick = LK.ticks;
});
// --- Initial UI state ---
scoreTxt.setText(score);
updateLivesUI(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Obstacle class
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	// Randomly pick a shape for variety
	var types = ['obstacle_box', 'obstacle_ellipse', 'obstacle_tall', 'obstacle_wide'];
	var type = types[Math.floor(Math.random() * types.length)];
	var gfx = self.attachAsset(type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = type;
	// Speed will be set on creation
	self.speed = 0;
	// Update method for movement
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGfx = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// For collision, use the container itself
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181818
});
/**** 
* Game Code
****/ 
// Game constants 
// --- Background ---
var bg = LK.getAsset('bg_green', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	scaleX: GAME_WIDTH / 100,
	scaleY: GAME_HEIGHT / 100
});
game.addChild(bg);
// Player character: a colored box
// Obstacle shapes (variety for visual interest)
// Heart icon for lives
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_X = GAME_WIDTH / 2;
var PLAYER_START_Y = GAME_HEIGHT - 400;
var OBSTACLE_SPAWN_Y = 220; // Top area for obstacles
var OBSTACLE_MIN_SPEED = 7;
var OBSTACLE_MAX_SPEED = 15;
var OBSTACLE_SPAWN_INTERVAL = 70; // ticks
var PLAYER_MOVE_AREA = {
	left: 180,
	right: GAME_WIDTH - 180,
	top: 600,
	bottom: GAME_HEIGHT - 100
};
var MAX_LIVES = 3;
// State variables
var player;
var obstacles = [];
var lives = MAX_LIVES;
var score = 0;
var scoreTxt;
var livesNodes = [];
var dragNode = null;
var lastScoreTick = 0;
// --- UI: Score ---
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- UI: Lives (Hearts) ---
function updateLivesUI() {
	// Remove old
	for (var i = 0; i < livesNodes.length; i++) {
		if (livesNodes[i].parent) livesNodes[i].parent.removeChild(livesNodes[i]);
	}
	livesNodes = [];
	// Place hearts at top right, spaced
	for (var i = 0; i < lives; i++) {
		var heart = LK.getAsset('heart', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: 0
		});
		// Place: right margin 60px, then 100px per heart leftward, y=100
		heart.x = GAME_WIDTH - 100 - i * 100;
		heart.y = 100;
		// Add to game (not GUI, so it scales with game)
		game.addChild(heart);
		livesNodes.push(heart);
	}
}
updateLivesUI();
// --- Player ---
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
game.addChild(player);
// --- Touch/Drag Controls ---
function clamp(val, min, max) {
	return Math.max(min, Math.min(max, val));
}
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to allowed area
		dragNode.x = clamp(x, PLAYER_MOVE_AREA.left, PLAYER_MOVE_AREA.right);
		dragNode.y = clamp(y, PLAYER_MOVE_AREA.top, PLAYER_MOVE_AREA.bottom);
	}
}
game.move = handleMove;
game.down = function (x, y, obj) {
	// Only allow drag if touch is on player or below
	if (x >= player.x - 100 && x <= player.x + 100 && y >= player.y - 100 && y <= player.y + 100) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// --- Obstacle Spawning ---
function spawnObstacle() {
	var obs = new Obstacle();
	// Random X in a central band (avoid extreme edges)
	var minX = 300,
		maxX = GAME_WIDTH - 300;
	obs.x = minX + Math.floor(Math.random() * (maxX - minX));
	obs.y = OBSTACLE_SPAWN_Y;
	// Random speed
	obs.speed = OBSTACLE_MIN_SPEED + Math.random() * (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED);
	// Optionally, for some types, add horizontal movement
	if (obs.type === 'obstacle_wide' && Math.random() < 0.5) {
		obs.horizSpeed = (Math.random() < 0.5 ? -1 : 1) * (2 + Math.random() * 3);
		obs.update = function () {
			this.y += this.speed;
			this.x += this.horizSpeed;
			// Bounce off walls
			if (this.x < 200 || this.x > GAME_WIDTH - 200) this.horizSpeed *= -1;
		};
	}
	obstacles.push(obs);
	game.addChild(obs);
}
// --- Game Update Loop ---
game.update = function () {
	// Score increases with time survived (every 30 ticks = 0.5s)
	if (LK.ticks - lastScoreTick >= 30) {
		score += 1;
		scoreTxt.setText(score);
		lastScoreTick = LK.ticks;
	}
	// Spawn obstacles
	if (LK.ticks % OBSTACLE_SPAWN_INTERVAL === 0) {
		spawnObstacle();
	}
	// Update obstacles, check for collision, remove off-screen
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		// Move
		if (typeof obs.update === 'function') obs.update();
		// Remove if off bottom
		if (obs.y > GAME_HEIGHT + 200) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision with player
		if (obs.intersects(player)) {
			// Remove obstacle
			obs.destroy();
			obstacles.splice(i, 1);
			// Lose a life
			lives -= 1;
			updateLivesUI();
			// Flash player red
			LK.effects.flashObject(player, 0xff0000, 600);
			// If out of lives, game over
			if (lives <= 0) {
				LK.effects.flashScreen(0xff0000, 1000);
				LK.showGameOver();
				return;
			}
		}
	}
};
// --- Reset on Game Over ---
LK.on('gameover', function () {
	// Reset state for new game
	lives = MAX_LIVES;
	score = 0;
	scoreTxt.setText(score);
	updateLivesUI();
	// Remove all obstacles
	for (var i = 0; i < obstacles.length; i++) {
		obstacles[i].destroy();
	}
	obstacles = [];
	// Reset player position
	player.x = PLAYER_START_X;
	player.y = PLAYER_START_Y;
	dragNode = null;
	lastScoreTick = LK.ticks;
});
// --- Initial UI state ---
scoreTxt.setText(score);
updateLivesUI();