/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Enemy Fish Class
var EnemyFish = Container.expand(function () {
	var self = Container.call(this);
	// Will be set on creation
	self.fishType = 'smallFish'; // 'smallFish', 'mediumFish', 'bigFish'
	self.sizeValue = 1; // Used for collision and logic
	self.speed = 2; // px per frame
	self.direction = 1; // 1: right, -1: left
	// Asset
	var fishAsset = null;
	// Value label
	var valueLabel = null;
	// Collider visual
	var colliderCircle = null;
	self.init = function (type, sizeValue, speed, direction) {
		self.fishType = type;
		self.sizeValue = sizeValue;
		self.speed = speed;
		self.direction = direction;
		// Remove previous asset if any
		if (fishAsset) {
			self.removeChild(fishAsset);
		}
		if (valueLabel) {
			self.removeChild(valueLabel);
		}
		if (colliderCircle) {
			self.removeChild(colliderCircle);
		}
		fishAsset = self.attachAsset(type, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scale.x = direction; // Flip if moving left
		self.scale.y = 1;
		// Set scale based on sizeValue
		self.scale.x *= sizeValue;
		self.scale.y *= sizeValue;
		// Add value label (rounded to 2 decimals)
		valueLabel = new Text2(self.sizeValue.toFixed(2), {
			size: 60,
			fill: 0xffffff,
			align: "center"
		});
		valueLabel.anchor.set(0.5, 0.5);
		// Place label at center of fish
		valueLabel.x = 0;
		valueLabel.y = 0;
		self.addChild(valueLabel);
		// Add collider visual (ellipse for more accurate fit)
		var colliderW = fishAsset.width * Math.abs(self.scale.x) * 0.45;
		var colliderH = fishAsset.height * Math.abs(self.scale.y) * 0.45;
		colliderCircle = LK.getAsset('centerCircle', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: colliderW / 50,
			scaleY: colliderH / 50,
			alpha: 0.25,
			tint: 0xff0000
		});
		self.addChild(colliderCircle);
	};
	self.getRadius = function () {
		return fishAsset.width * Math.abs(self.scale.x) * 0.5;
	};
	// Move fish
	self.update = function () {
		self.x += self.speed * self.direction;
		// Keep collider visual in sync with scale (ellipse)
		if (colliderCircle && fishAsset) {
			var colliderW = fishAsset.width * Math.abs(self.scale.x) * 0.45;
			var colliderH = fishAsset.height * Math.abs(self.scale.y) * 0.45;
			colliderCircle.scale.x = colliderW / 50;
			colliderCircle.scale.y = colliderH / 50;
		}
	};
	return self;
});
// Player Fish Class
var PlayerFish = Container.expand(function () {
	var self = Container.call(this);
	var fish = self.attachAsset('playerFish', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var colliderCircle = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: fish.width * 0.45 / 50,
		scaleY: fish.height * 0.45 / 50,
		alpha: 0.25,
		tint: 0x00ff00
	});
	self.addChild(colliderCircle);
	self.size = 1; // Growth multiplier
	// Update size/scale
	self.setSize = function (scale) {
		self.size = scale;
		self.scale.x = scale;
		self.scale.y = scale;
		// Update collider visual (ellipse)
		if (colliderCircle && fish) {
			var colliderW = fish.width * self.size * 0.45;
			var colliderH = fish.height * self.size * 0.45;
			colliderCircle.scale.x = colliderW / 50;
			colliderCircle.scale.y = colliderH / 50;
		}
	};
	// For collision, always use the container, not the asset
	self.getRadius = function () {
		return fish.width * self.size * 0.5;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a237e // Deep blue ocean
});
/**** 
* Game Code
****/ 
// Game constants
// Fish assets: player, small fish, medium fish, big fish
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_SIZE = 1;
var PLAYER_GROWTH = 0.12; // Each fish eaten increases size by this factor
var MAX_PLAYER_SIZE = 2.5;
var ENEMY_SPAWN_INTERVAL = 60; // frames
var ENEMY_MIN_SPEED = 4;
var ENEMY_MAX_SPEED = 10;
var ENEMY_SPAWN_MARGIN = 120; // px offscreen
// State
var player = null;
var enemyFishes = [];
var score = 0;
var scoreTxt = null;
var dragNode = null;
var lastGameOver = false;
var spawnTick = 0;
// Helper: Get random between min and max
function randBetween(min, max) {
	return min + Math.random() * (max - min);
}
// Helper: Clamp value
function clamp(val, min, max) {
	return Math.max(min, Math.min(max, val));
}
// Initialize player
player = new PlayerFish();
player.setSize(PLAYER_START_SIZE);
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT * 0.7;
game.addChild(player);
// Score text
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Spawning enemy fish
function spawnEnemyFish() {
	// Determine player size for dynamic difficulty
	var pSize = player.size;
	// Decide fish type and size
	var type, sizeValue, speed, direction;
	var r = Math.random();
	// Probability: 50% small, 35% medium, 15% big
	if (r < 0.5) {
		type = 'smallFish';
		// Always smaller than player
		sizeValue = clamp(randBetween(0.5, pSize * 0.85), 0.4, 1.2);
	} else if (r < 0.85) {
		type = 'mediumFish';
		// Medium fish are now noticeably bigger
		sizeValue = clamp(randBetween(pSize * 1.1, pSize * 1.7), 1.2, 2.2);
	} else {
		type = 'bigFish';
		// Big fish are now much bigger
		sizeValue = clamp(randBetween(pSize * 1.7, pSize * 2.7), 2.2, 3.2);
	}
	// Speed: smaller fish are faster
	speed = clamp(ENEMY_MAX_SPEED - sizeValue * 3, ENEMY_MIN_SPEED, ENEMY_MAX_SPEED);
	// Direction: left or right
	direction = Math.random() < 0.5 ? 1 : -1;
	var fish = new EnemyFish();
	fish.init(type, sizeValue, speed, direction);
	// Y position: random, but not too close to top/bottom
	var minY = 200 + fish.getRadius();
	var maxY = GAME_HEIGHT - 200 - fish.getRadius();
	fish.y = randBetween(minY, maxY);
	// X position: offscreen left or right
	if (direction === 1) {
		fish.x = -ENEMY_SPAWN_MARGIN;
	} else {
		fish.x = GAME_WIDTH + ENEMY_SPAWN_MARGIN;
	}
	// Track
	enemyFishes.push(fish);
	game.addChild(fish);
}
// Move handler for dragging player
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to game area
		var r = player.getRadius();
		dragNode.x = clamp(x, r, GAME_WIDTH - r);
		dragNode.y = clamp(y, r, GAME_HEIGHT - r);
	}
}
// Touch/drag events
game.down = function (x, y, obj) {
	// Only allow drag if touch is on player
	var dx = x - player.x;
	var dy = y - player.y;
	var dist = Math.sqrt(dx * dx + dy * dy);
	if (dist < player.getRadius() * 1.1) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
game.move = handleMove;
// Game update loop
game.update = function () {
	// Spawn enemy fish
	spawnTick++;
	if (spawnTick >= ENEMY_SPAWN_INTERVAL) {
		spawnTick = 0;
		spawnEnemyFish();
	}
	// Check if player collides with any edge
	var pr = player.getRadius();
	if (player.x - pr <= 0 || player.x + pr >= GAME_WIDTH || player.y - pr <= 0 || player.y + pr >= GAME_HEIGHT) {
		if (!lastGameOver) {
			lastGameOver = true;
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
			return;
		}
	}
	// Update enemy fish
	for (var i = enemyFishes.length - 1; i >= 0; i--) {
		var fish = enemyFishes[i];
		fish.update();
		// Remove if offscreen
		if (fish.direction === 1 && fish.x - fish.getRadius() > GAME_WIDTH + ENEMY_SPAWN_MARGIN || fish.direction === -1 && fish.x + fish.getRadius() < -ENEMY_SPAWN_MARGIN) {
			fish.destroy();
			enemyFishes.splice(i, 1);
			continue;
		}
		// Collision with player
		var dx = fish.x - player.x;
		var dy = fish.y - player.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var minDist = fish.getRadius() + player.getRadius() * 0.85;
		if (dist < minDist) {
			// Compare sizes
			if (player.size > fish.sizeValue * 1.05) {
				// Eat fish
				// Animate fish fade out
				tween(fish, {
					alpha: 0
				}, {
					duration: 200,
					onFinish: function onFinish() {
						fish.destroy();
					}
				});
				enemyFishes.splice(i, 1);
				// Grow player
				var newSize = clamp(player.size + PLAYER_GROWTH * fish.sizeValue, PLAYER_START_SIZE, MAX_PLAYER_SIZE);
				player.setSize(newSize);
				// Update score
				score += Math.floor(10 * fish.sizeValue);
				scoreTxt.setText(score);
				// Win condition removed: game continues until player is eaten
			} else if (player.size < fish.sizeValue * 0.95) {
				// Player is eaten
				if (!lastGameOver) {
					lastGameOver = true;
					LK.effects.flashScreen(0xff0000, 1000);
					LK.showGameOver();
					return;
				}
			}
			// If similar size, nothing happens
		}
	}
};
// Reset state on game restart
LK.on('gameStart', function () {
	// Remove all enemy fish
	for (var i = 0; i < enemyFishes.length; i++) {
		enemyFishes[i].destroy();
	}
	enemyFishes = [];
	// Reset player
	player.setSize(PLAYER_START_SIZE);
	player.x = GAME_WIDTH / 2;
	player.y = GAME_HEIGHT * 0.7;
	// Reset score
	score = 0;
	scoreTxt.setText(score);
	lastGameOver = false;
	spawnTick = 0;
}); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Enemy Fish Class
var EnemyFish = Container.expand(function () {
	var self = Container.call(this);
	// Will be set on creation
	self.fishType = 'smallFish'; // 'smallFish', 'mediumFish', 'bigFish'
	self.sizeValue = 1; // Used for collision and logic
	self.speed = 2; // px per frame
	self.direction = 1; // 1: right, -1: left
	// Asset
	var fishAsset = null;
	// Value label
	var valueLabel = null;
	// Collider visual
	var colliderCircle = null;
	self.init = function (type, sizeValue, speed, direction) {
		self.fishType = type;
		self.sizeValue = sizeValue;
		self.speed = speed;
		self.direction = direction;
		// Remove previous asset if any
		if (fishAsset) {
			self.removeChild(fishAsset);
		}
		if (valueLabel) {
			self.removeChild(valueLabel);
		}
		if (colliderCircle) {
			self.removeChild(colliderCircle);
		}
		fishAsset = self.attachAsset(type, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scale.x = direction; // Flip if moving left
		self.scale.y = 1;
		// Set scale based on sizeValue
		self.scale.x *= sizeValue;
		self.scale.y *= sizeValue;
		// Add value label (rounded to 2 decimals)
		valueLabel = new Text2(self.sizeValue.toFixed(2), {
			size: 60,
			fill: 0xffffff,
			align: "center"
		});
		valueLabel.anchor.set(0.5, 0.5);
		// Place label at center of fish
		valueLabel.x = 0;
		valueLabel.y = 0;
		self.addChild(valueLabel);
		// Add collider visual (ellipse for more accurate fit)
		var colliderW = fishAsset.width * Math.abs(self.scale.x) * 0.45;
		var colliderH = fishAsset.height * Math.abs(self.scale.y) * 0.45;
		colliderCircle = LK.getAsset('centerCircle', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: colliderW / 50,
			scaleY: colliderH / 50,
			alpha: 0.25,
			tint: 0xff0000
		});
		self.addChild(colliderCircle);
	};
	self.getRadius = function () {
		return fishAsset.width * Math.abs(self.scale.x) * 0.5;
	};
	// Move fish
	self.update = function () {
		self.x += self.speed * self.direction;
		// Keep collider visual in sync with scale (ellipse)
		if (colliderCircle && fishAsset) {
			var colliderW = fishAsset.width * Math.abs(self.scale.x) * 0.45;
			var colliderH = fishAsset.height * Math.abs(self.scale.y) * 0.45;
			colliderCircle.scale.x = colliderW / 50;
			colliderCircle.scale.y = colliderH / 50;
		}
	};
	return self;
});
// Player Fish Class
var PlayerFish = Container.expand(function () {
	var self = Container.call(this);
	var fish = self.attachAsset('playerFish', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var colliderCircle = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: fish.width * 0.45 / 50,
		scaleY: fish.height * 0.45 / 50,
		alpha: 0.25,
		tint: 0x00ff00
	});
	self.addChild(colliderCircle);
	self.size = 1; // Growth multiplier
	// Update size/scale
	self.setSize = function (scale) {
		self.size = scale;
		self.scale.x = scale;
		self.scale.y = scale;
		// Update collider visual (ellipse)
		if (colliderCircle && fish) {
			var colliderW = fish.width * self.size * 0.45;
			var colliderH = fish.height * self.size * 0.45;
			colliderCircle.scale.x = colliderW / 50;
			colliderCircle.scale.y = colliderH / 50;
		}
	};
	// For collision, always use the container, not the asset
	self.getRadius = function () {
		return fish.width * self.size * 0.5;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a237e // Deep blue ocean
});
/**** 
* Game Code
****/ 
// Game constants
// Fish assets: player, small fish, medium fish, big fish
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_SIZE = 1;
var PLAYER_GROWTH = 0.12; // Each fish eaten increases size by this factor
var MAX_PLAYER_SIZE = 2.5;
var ENEMY_SPAWN_INTERVAL = 60; // frames
var ENEMY_MIN_SPEED = 4;
var ENEMY_MAX_SPEED = 10;
var ENEMY_SPAWN_MARGIN = 120; // px offscreen
// State
var player = null;
var enemyFishes = [];
var score = 0;
var scoreTxt = null;
var dragNode = null;
var lastGameOver = false;
var spawnTick = 0;
// Helper: Get random between min and max
function randBetween(min, max) {
	return min + Math.random() * (max - min);
}
// Helper: Clamp value
function clamp(val, min, max) {
	return Math.max(min, Math.min(max, val));
}
// Initialize player
player = new PlayerFish();
player.setSize(PLAYER_START_SIZE);
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT * 0.7;
game.addChild(player);
// Score text
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Spawning enemy fish
function spawnEnemyFish() {
	// Determine player size for dynamic difficulty
	var pSize = player.size;
	// Decide fish type and size
	var type, sizeValue, speed, direction;
	var r = Math.random();
	// Probability: 50% small, 35% medium, 15% big
	if (r < 0.5) {
		type = 'smallFish';
		// Always smaller than player
		sizeValue = clamp(randBetween(0.5, pSize * 0.85), 0.4, 1.2);
	} else if (r < 0.85) {
		type = 'mediumFish';
		// Medium fish are now noticeably bigger
		sizeValue = clamp(randBetween(pSize * 1.1, pSize * 1.7), 1.2, 2.2);
	} else {
		type = 'bigFish';
		// Big fish are now much bigger
		sizeValue = clamp(randBetween(pSize * 1.7, pSize * 2.7), 2.2, 3.2);
	}
	// Speed: smaller fish are faster
	speed = clamp(ENEMY_MAX_SPEED - sizeValue * 3, ENEMY_MIN_SPEED, ENEMY_MAX_SPEED);
	// Direction: left or right
	direction = Math.random() < 0.5 ? 1 : -1;
	var fish = new EnemyFish();
	fish.init(type, sizeValue, speed, direction);
	// Y position: random, but not too close to top/bottom
	var minY = 200 + fish.getRadius();
	var maxY = GAME_HEIGHT - 200 - fish.getRadius();
	fish.y = randBetween(minY, maxY);
	// X position: offscreen left or right
	if (direction === 1) {
		fish.x = -ENEMY_SPAWN_MARGIN;
	} else {
		fish.x = GAME_WIDTH + ENEMY_SPAWN_MARGIN;
	}
	// Track
	enemyFishes.push(fish);
	game.addChild(fish);
}
// Move handler for dragging player
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to game area
		var r = player.getRadius();
		dragNode.x = clamp(x, r, GAME_WIDTH - r);
		dragNode.y = clamp(y, r, GAME_HEIGHT - r);
	}
}
// Touch/drag events
game.down = function (x, y, obj) {
	// Only allow drag if touch is on player
	var dx = x - player.x;
	var dy = y - player.y;
	var dist = Math.sqrt(dx * dx + dy * dy);
	if (dist < player.getRadius() * 1.1) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
game.move = handleMove;
// Game update loop
game.update = function () {
	// Spawn enemy fish
	spawnTick++;
	if (spawnTick >= ENEMY_SPAWN_INTERVAL) {
		spawnTick = 0;
		spawnEnemyFish();
	}
	// Check if player collides with any edge
	var pr = player.getRadius();
	if (player.x - pr <= 0 || player.x + pr >= GAME_WIDTH || player.y - pr <= 0 || player.y + pr >= GAME_HEIGHT) {
		if (!lastGameOver) {
			lastGameOver = true;
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
			return;
		}
	}
	// Update enemy fish
	for (var i = enemyFishes.length - 1; i >= 0; i--) {
		var fish = enemyFishes[i];
		fish.update();
		// Remove if offscreen
		if (fish.direction === 1 && fish.x - fish.getRadius() > GAME_WIDTH + ENEMY_SPAWN_MARGIN || fish.direction === -1 && fish.x + fish.getRadius() < -ENEMY_SPAWN_MARGIN) {
			fish.destroy();
			enemyFishes.splice(i, 1);
			continue;
		}
		// Collision with player
		var dx = fish.x - player.x;
		var dy = fish.y - player.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var minDist = fish.getRadius() + player.getRadius() * 0.85;
		if (dist < minDist) {
			// Compare sizes
			if (player.size > fish.sizeValue * 1.05) {
				// Eat fish
				// Animate fish fade out
				tween(fish, {
					alpha: 0
				}, {
					duration: 200,
					onFinish: function onFinish() {
						fish.destroy();
					}
				});
				enemyFishes.splice(i, 1);
				// Grow player
				var newSize = clamp(player.size + PLAYER_GROWTH * fish.sizeValue, PLAYER_START_SIZE, MAX_PLAYER_SIZE);
				player.setSize(newSize);
				// Update score
				score += Math.floor(10 * fish.sizeValue);
				scoreTxt.setText(score);
				// Win condition removed: game continues until player is eaten
			} else if (player.size < fish.sizeValue * 0.95) {
				// Player is eaten
				if (!lastGameOver) {
					lastGameOver = true;
					LK.effects.flashScreen(0xff0000, 1000);
					LK.showGameOver();
					return;
				}
			}
			// If similar size, nothing happens
		}
	}
};
// Reset state on game restart
LK.on('gameStart', function () {
	// Remove all enemy fish
	for (var i = 0; i < enemyFishes.length; i++) {
		enemyFishes[i].destroy();
	}
	enemyFishes = [];
	// Reset player
	player.setSize(PLAYER_START_SIZE);
	player.x = GAME_WIDTH / 2;
	player.y = GAME_HEIGHT * 0.7;
	// Reset score
	score = 0;
	scoreTxt.setText(score);
	lastGameOver = false;
	spawnTick = 0;
});
:quality(85)/https://cdn.frvr.ai/682d2032fcdb240d4012d8d1.png%3F3) 
 Fish. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/682d2086fcdb240d4012d8d6.png%3F3) 
 A stingray fish . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/682d20c2fcdb240d4012d8e1.png%3F3) 
 A big Black and White Orca. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/682d2133fcdb240d4012d8ed.png%3F3) 
 A blueish Anchovy. In-Game asset. 2d. High contrast. No shadows