/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bubble = Container.expand(function () { var self = Container.call(this); var size = 20 + Math.random() * 40; var bubbleGraphic = self.attachAsset('bubble', { anchorX: 0.5, anchorY: 0.5, width: size, height: size, alpha: 0.6 }); self.speed = 1 + Math.random() * 2; self.update = function () { self.y -= self.speed; // Add slight horizontal drift self.x += Math.sin(LK.ticks / 20 + self.y / 100) * 0.5; // Remove when offscreen if (self.y < -50) { self.destroy(); } }; return self; }); var Coral = Container.expand(function () { var self = Container.call(this); var coralGraphic = self.attachAsset('coral', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Coral does not move, so no update logic is needed }; return self; }); var Fish = Container.expand(function (type, size, speed, color) { var self = Container.call(this); self.type = type || 'player'; self.fishSize = size || 1; self.speed = speed || 3; self.fishColor = color || 0x3498db; self.direction = 1; // 1 = right, -1 = left // Create fish body var fishBody = self.attachAsset(type + 'Fish', { anchorX: 0.5, anchorY: 0.5 }); // Add scales to fish body var scaleCount = Math.floor(self.fishSize * 5); for (var s = 0; s < scaleCount; s++) { var scale = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, width: 5, height: 5, tint: 0xFFFFFF }); scale.x = (Math.random() - 0.5) * fishBody.width * 0.8; scale.y = (Math.random() - 0.5) * fishBody.height * 0.8; self.addChild(scale); } // Create eye var eyeSize = self.type === 'large' ? self.fishSize * 5 : self.fishSize * 10; var eye = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, width: eyeSize, height: eyeSize, tint: 0xffffff }); eye.x = type === 'player' ? 30 : fishBody.width * 0.3; eye.y = type === 'player' ? -10 : -fishBody.height * 0.1; self.addChild(eye); // Create pupil var pupil = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, width: eyeSize * 0.5, height: eyeSize * 0.5, tint: 0x000000 }); pupil.x = eye.x + 2; pupil.y = eye.y; self.addChild(pupil); // Create tail var tail = LK.getAsset('foodParticle', { anchorX: 0.5, anchorY: 0.5, width: fishBody.width * 0.4, height: fishBody.height * 0.6, tint: self.fishColor - 0x202020 // Darker shade of the fish color }); tail.x = type === 'player' ? -40 : -fishBody.width * 0.4; self.addChild(tail); // Set fish properties self.width = fishBody.width; self.height = fishBody.height; self.originalWidth = fishBody.width; self.originalHeight = fishBody.height; // Movement AI for non-player fish self.updateMovement = function () { if (self.type !== 'player') { // Random direction change if (self.type !== 'small' && Math.random() < 0.005) { self.direction = -self.direction; self.scale.x = -self.direction; } // Random vertical movement if (Math.random() < 0.05) { self.verticalDirection = Math.random() > 0.5 ? 1 : -1; } // Move horizontally self.x += self.speed * self.direction; // Move vertically if direction is set if (self.verticalDirection) { self.y += self.verticalDirection * (self.speed * 0.5); // Stop vertical movement randomly if (Math.random() < 0.1) { self.verticalDirection = 0; } } // Wrap around screen if (self.x < -100) { self.x = 2148; } if (self.x > 2148) { self.x = -100; } // Bounce off top and bottom if (self.y < 100) { self.y = 100; self.verticalDirection = 1; } if (self.y > 2632) { self.y = 2632; self.verticalDirection = -1; } } }; // Fish can eat other fish that are smaller than them self.canEat = function (otherFish) { return self.fishSize > otherFish.fishSize * 1.2; }; // Grow fish size self.grow = function (amount) { self.fishSize += amount; var newScale = 0.5 + self.fishSize * 0.5; tween(self.scale, { x: self.direction * newScale, y: newScale }, { duration: 300, easing: tween.elasticOut }); if (self.type === 'player') { LK.getSound('grow').play(); } }; // Check if this fish is visible on screen self.isOnScreen = function () { return self.x >= -100 && self.x <= 2148 && self.y >= -100 && self.y <= 2832; }; // Update method called every frame self.update = function () { self.updateMovement(); if (LK.ticks % 360 === 0) { // Create a bubble every 360 frames (10 bubbles per minute at 60 FPS) var bubble = new Bubble(); bubble.x = self.x + (self.direction === 1 ? fishBody.width / 2 : -fishBody.width / 2); bubble.y = self.y; game.addChild(bubble); bubbles.push(bubble); } }; // Create size text var sizeText = new Text2(self.fishSize.toFixed(0), { // Display size as an integer size: 50, // Increase font size fill: 0xFFFFFF }); sizeText.anchor.set(0.5, 1); sizeText.y = -fishBody.height / 2 - 10; self.addChild(sizeText); // Update size text when fish grows self.grow = function (amount) { self.fishSize += amount; var newScale = 1 + (self.fishSize - 1) * 0.2; tween(self.scale, { x: self.direction * newScale, y: newScale }, { duration: 300, easing: tween.elasticOut }); sizeText.setText(self.fishSize.toFixed(1)); // Update size text with one decimal place sizeText.scale.set(newScale); // Adjust text size based on fish size if (self.type === 'player') { LK.getSound('grow').play(); // Display 'Nice' or 'Cool' text randomly var growText = Math.random() > 0.5 ? 'Nice' : 'Cool'; var growTextDisplay = new Text2(growText, { size: 100, fill: 0xFFFFFF }); growTextDisplay.anchor.set(1, 0); // Set anchor to top-right corner growTextDisplay.x = self.width / 2; // Position at the top-right corner of the fish growTextDisplay.y = -self.height / 2; self.addChild(growTextDisplay); tween(growTextDisplay, { alpha: 0, y: growTextDisplay.y - 50 }, { duration: 1000, onComplete: function onComplete() { growTextDisplay.destroy(); } }); // Change color based on size if (self.fishSize < 2) { self.fishColor = 0x3498db; // Blue } else if (self.fishSize < 3) { self.fishColor = 0xe74c3c; // Red } else { self.fishColor = 0x9b59b6; // Purple } fishBody.tint = self.fishColor; tail.tint = self.fishColor; } }; return self; }); var FoodParticle = Container.expand(function () { var self = Container.call(this); var foodGraphic = self.attachAsset('foodParticle', { anchorX: 0.5, anchorY: 0.5 }); self.value = 0.1; self.speed = 0.5 + Math.random() * 1; // Slowly sink self.update = function () { self.y += self.speed; // Add slight horizontal drift self.x += Math.sin(LK.ticks / 10 + self.y / 100) * 0.3; // Remove when offscreen if (self.y > 2800) { self.destroy(); } }; return self; }); var Powerup = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'speed'; var powerupGraphic = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); // Different colors for different power-ups if (self.type === 'speed') { powerupGraphic.tint = 0xe67e22; // Orange } else if (self.type === 'invincibility') { powerupGraphic.tint = 0xe74c3c; // Red } else if (self.type === 'magnet') { powerupGraphic.tint = 0x9b59b6; // Purple } // Floating animation self.update = function () { self.y += Math.sin(LK.ticks / 10) * 0.5; // Slowly sink if (LK.ticks % 3 === 0) { self.y += 0.5; } // Remove when offscreen if (self.y > 2800) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4682B4 // Steel blue color }); /**** * Game Code ****/ // Game variables var player; var enemies = []; var bubbles = []; var foodParticles = []; var powerups = []; var score = 0; var highScore = storage.highScore || 0; var playerIsInvincible = false; var hasMagnet = false; var isGameActive = true; // Game difficulty settings var difficulty = 1; var maxEnemies = 15; var enemySpawnRate = 120; // frames between enemy spawns var foodSpawnRate = 60; // frames between food spawns var powerupSpawnRate = 600; // frames between powerup spawns // Track if player is being dragged var isDragging = false; // Setup UI elements var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.top.addChild(scoreText); scoreText.x = 150; scoreText.y = 50; var highScoreText = new Text2('High Score: ' + highScore, { size: 50, fill: 0xFFFFFF }); highScoreText.anchor.set(1, 0); LK.gui.topRight.addChild(highScoreText); highScoreText.x = -50; highScoreText.y = 120; var sizeText = new Text2('Size: 1.0', { size: 60, fill: 0xFFFFFF }); sizeText.anchor.set(0, 1); LK.gui.bottomLeft.addChild(sizeText); sizeText.x = 50; sizeText.y = -50; var statusText = new Text2('', { size: 45, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0); LK.gui.top.addChild(statusText); statusText.y = 120; // Initialize player fish function initializeGame() { // Add coral objects to the game for (var i = 0; i < 5; i++) { var coral = new Coral(); coral.x = 200 + i * 700; // Further increased spacing between corals coral.y = 2500; game.addChild(coral); } // Add seaweed and rocks to the game for (var j = 0; j < 3; j++) { var seaweed = new Coral(); seaweed.x = 400 + j * 600; seaweed.y = 2600; game.addChild(seaweed); } for (var k = 0; k < 3; k++) { var rock = new Coral(); rock.x = 600 + k * 800; rock.y = 2700; game.addChild(rock); } // Reset game state player = new Fish('player', 1, 3, 0x3498db); // Reduced speed from 5 to 3 for heavier movement player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); // Reset game state enemies = []; bubbles = []; foodParticles = []; powerups = []; score = 0; playerIsInvincible = false; hasMagnet = false; isGameActive = true; difficulty = 1; // Update UI scoreText.setText('Score: 0'); sizeText.setText('Size: 1.0'); statusText.setText(''); // Start game music LK.playMusic('oceanTheme'); } // Initialize the game initializeGame(); // Function to spawn bubbles function spawnBubble() { if (Math.random() < 0.02) { var bubble = new Bubble(); bubble.x = Math.random() * 2048; bubble.y = 2732 + 50; game.addChild(bubble); bubbles.push(bubble); } } // Function to spawn food particles function spawnFood() { if (LK.ticks % foodSpawnRate === 0) { var food = new FoodParticle(); food.x = Math.random() * 2048; food.y = -50; game.addChild(food); foodParticles.push(food); } } // Function to spawn power-ups function spawnPowerup() { if (LK.ticks % powerupSpawnRate === 0 && Math.random() < 0.3) { var types = ['speed', 'invincibility', 'magnet']; var type = types[Math.floor(Math.random() * types.length)]; var powerup = new Powerup(type); powerup.x = 100 + Math.random() * (2048 - 200); powerup.y = -50; game.addChild(powerup); powerups.push(powerup); } } // Function to spawn enemy fish function spawnEnemy() { if (LK.ticks % enemySpawnRate === 0 && enemies.length < maxEnemies) { // Decide fish size relative to player var sizeFactor; var rnd = Math.random(); if (rnd < 0.6) { // 60% chance for smaller fish sizeFactor = 0.5 + Math.random() * 0.4; } else if (rnd < 0.85) { // 25% chance for similar sized fish sizeFactor = 0.9 + Math.random() * 0.2; } else { // 15% chance for larger fish sizeFactor = 1.2 + Math.random() * (difficulty * 0.5); } var fishSize = player.fishSize * sizeFactor; // Determine fish type based on size var fishType; if (fishSize < 1) { fishType = 'small'; } else if (fishSize < 2) { fishType = 'medium'; } else { fishType = 'large'; } // Create the enemy var enemy = new Fish(fishType, fishSize, 1 + Math.random() * 3); // Position on either left or right side of screen var fromLeft = Math.random() > 0.5; enemy.x = fromLeft ? -100 : 2148; enemy.y = 200 + Math.random() * (2732 - 400); enemy.direction = fromLeft ? 1 : -1; enemy.scale.x = enemy.direction; // Add to game game.addChild(enemy); enemies.push(enemy); } } // Function to check collisions between player and other entities function checkCollisions() { if (!isGameActive) { return; } // Check collisions with enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // If enemy is off-screen for too long, remove it if (!enemy.isOnScreen() && (enemy.x < -200 || enemy.x > 2248)) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check collision with player if (player.intersects(enemy)) { if (player.canEat(enemy) || playerIsInvincible) { // Player eats enemy var growAmount = enemy.fishSize * 0.1; player.grow(growAmount); // Update score score += Math.floor(enemy.fishSize * 10) + Math.floor(enemy.fishSize); scoreText.setText('Score: ' + score); sizeText.setText('Size: ' + player.fishSize.toFixed(1)); // Display 'Kill' text statusText.setText('Kill'); LK.setTimeout(function () { statusText.setText(''); }, 1000); // Check for high score if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreText.setText('High Score: ' + highScore); } // Remove enemy enemy.destroy(); enemies.splice(i, 1); // Play eat sound LK.getSound('eat').play(); // Increase difficulty if (score > difficulty * 100) { difficulty++; enemySpawnRate = Math.max(40, 120 - difficulty * 5); foodSpawnRate = Math.max(30, 60 - difficulty * 2); } } else if (!playerIsInvincible && enemy.fishColor !== 0x2ecc71 && enemy.type !== 'small') { // Player gets eaten LK.effects.flashScreen(0xff0000, 1000); statusText.setText('Kill'); isGameActive = false; LK.showGameOver(); // End the game and show game over screen } } } // Check collisions with food particles for (var j = foodParticles.length - 1; j >= 0; j--) { var food = foodParticles[j]; // If food is magnet-attracted if (hasMagnet) { var dx = player.x - food.x; var dy = player.y - food.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 300) { var factor = 0.05; food.x += dx * factor; food.y += dy * factor; } } // Check collision if (player.intersects(food)) { // Player eats food player.grow(food.value); score += 1; scoreText.setText('Score: ' + score); sizeText.setText('Size: ' + player.fishSize.toFixed(1)); // Check for high score if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreText.setText('High Score: ' + highScore); } // Remove food food.destroy(); foodParticles.splice(j, 1); } } // Check collisions with powerups for (var k = powerups.length - 1; k >= 0; k--) { var powerup = powerups[k]; if (player.intersects(powerup)) { // Apply powerup effect if (powerup.type === 'speed') { // Speed boost player.speed = 10; statusText.setText('Speed Boost!'); LK.setTimeout(function () { player.speed = 5; statusText.setText(''); }, 5000); } else if (powerup.type === 'invincibility') { // Invincibility playerIsInvincible = true; statusText.setText('Invincible!'); player.alpha = 0.7; LK.setTimeout(function () { playerIsInvincible = false; statusText.setText(''); player.alpha = 1; }, 7000); } else if (powerup.type === 'magnet') { // Food magnet hasMagnet = true; statusText.setText('Food Magnet!'); LK.setTimeout(function () { hasMagnet = false; statusText.setText(''); }, 10000); } // Remove powerup powerup.destroy(); powerups.splice(k, 1); } } } // Update game state game.update = function () { if (!isGameActive) { return; } // Spawn entities spawnBubble(); spawnFood(); spawnEnemy(); spawnPowerup(); // Update entities that don't have auto-update for (var i = 0; i < bubbles.length; i++) { if (bubbles[i] && typeof bubbles[i].update === 'function') { bubbles[i].update(); } } for (var j = 0; j < foodParticles.length; j++) { if (foodParticles[j] && typeof foodParticles[j].update === 'function') { foodParticles[j].update(); } } for (var k = 0; k < powerups.length; k++) { if (powerups[k] && typeof powerups[k].update === 'function') { powerups[k].update(); } } // Check collisions checkCollisions(); // Update player direction based on movement if (isDragging && player.lastX) { if (player.x > player.lastX + 5) { player.direction = 1; player.scale.x = player.direction * (1 + (player.fishSize - 1) * 0.2); } else if (player.x < player.lastX - 5) { player.direction = -1; player.scale.x = player.direction * (1 + (player.fishSize - 1) * 0.2); } } // Store player's last position player.lastX = player.x; player.lastY = player.y; }; // Handle touch/mouse input for player movement game.down = function (x, y) { isDragging = true; player.x = x; player.y = y; }; game.move = function (x, y) { if (isDragging) { player.x = x; player.y = y; } }; game.up = function () { isDragging = false; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
var size = 20 + Math.random() * 40;
var bubbleGraphic = self.attachAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
width: size,
height: size,
alpha: 0.6
});
self.speed = 1 + Math.random() * 2;
self.update = function () {
self.y -= self.speed;
// Add slight horizontal drift
self.x += Math.sin(LK.ticks / 20 + self.y / 100) * 0.5;
// Remove when offscreen
if (self.y < -50) {
self.destroy();
}
};
return self;
});
var Coral = Container.expand(function () {
var self = Container.call(this);
var coralGraphic = self.attachAsset('coral', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Coral does not move, so no update logic is needed
};
return self;
});
var Fish = Container.expand(function (type, size, speed, color) {
var self = Container.call(this);
self.type = type || 'player';
self.fishSize = size || 1;
self.speed = speed || 3;
self.fishColor = color || 0x3498db;
self.direction = 1; // 1 = right, -1 = left
// Create fish body
var fishBody = self.attachAsset(type + 'Fish', {
anchorX: 0.5,
anchorY: 0.5
});
// Add scales to fish body
var scaleCount = Math.floor(self.fishSize * 5);
for (var s = 0; s < scaleCount; s++) {
var scale = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
width: 5,
height: 5,
tint: 0xFFFFFF
});
scale.x = (Math.random() - 0.5) * fishBody.width * 0.8;
scale.y = (Math.random() - 0.5) * fishBody.height * 0.8;
self.addChild(scale);
}
// Create eye
var eyeSize = self.type === 'large' ? self.fishSize * 5 : self.fishSize * 10;
var eye = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
width: eyeSize,
height: eyeSize,
tint: 0xffffff
});
eye.x = type === 'player' ? 30 : fishBody.width * 0.3;
eye.y = type === 'player' ? -10 : -fishBody.height * 0.1;
self.addChild(eye);
// Create pupil
var pupil = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
width: eyeSize * 0.5,
height: eyeSize * 0.5,
tint: 0x000000
});
pupil.x = eye.x + 2;
pupil.y = eye.y;
self.addChild(pupil);
// Create tail
var tail = LK.getAsset('foodParticle', {
anchorX: 0.5,
anchorY: 0.5,
width: fishBody.width * 0.4,
height: fishBody.height * 0.6,
tint: self.fishColor - 0x202020 // Darker shade of the fish color
});
tail.x = type === 'player' ? -40 : -fishBody.width * 0.4;
self.addChild(tail);
// Set fish properties
self.width = fishBody.width;
self.height = fishBody.height;
self.originalWidth = fishBody.width;
self.originalHeight = fishBody.height;
// Movement AI for non-player fish
self.updateMovement = function () {
if (self.type !== 'player') {
// Random direction change
if (self.type !== 'small' && Math.random() < 0.005) {
self.direction = -self.direction;
self.scale.x = -self.direction;
}
// Random vertical movement
if (Math.random() < 0.05) {
self.verticalDirection = Math.random() > 0.5 ? 1 : -1;
}
// Move horizontally
self.x += self.speed * self.direction;
// Move vertically if direction is set
if (self.verticalDirection) {
self.y += self.verticalDirection * (self.speed * 0.5);
// Stop vertical movement randomly
if (Math.random() < 0.1) {
self.verticalDirection = 0;
}
}
// Wrap around screen
if (self.x < -100) {
self.x = 2148;
}
if (self.x > 2148) {
self.x = -100;
}
// Bounce off top and bottom
if (self.y < 100) {
self.y = 100;
self.verticalDirection = 1;
}
if (self.y > 2632) {
self.y = 2632;
self.verticalDirection = -1;
}
}
};
// Fish can eat other fish that are smaller than them
self.canEat = function (otherFish) {
return self.fishSize > otherFish.fishSize * 1.2;
};
// Grow fish size
self.grow = function (amount) {
self.fishSize += amount;
var newScale = 0.5 + self.fishSize * 0.5;
tween(self.scale, {
x: self.direction * newScale,
y: newScale
}, {
duration: 300,
easing: tween.elasticOut
});
if (self.type === 'player') {
LK.getSound('grow').play();
}
};
// Check if this fish is visible on screen
self.isOnScreen = function () {
return self.x >= -100 && self.x <= 2148 && self.y >= -100 && self.y <= 2832;
};
// Update method called every frame
self.update = function () {
self.updateMovement();
if (LK.ticks % 360 === 0) {
// Create a bubble every 360 frames (10 bubbles per minute at 60 FPS)
var bubble = new Bubble();
bubble.x = self.x + (self.direction === 1 ? fishBody.width / 2 : -fishBody.width / 2);
bubble.y = self.y;
game.addChild(bubble);
bubbles.push(bubble);
}
};
// Create size text
var sizeText = new Text2(self.fishSize.toFixed(0), {
// Display size as an integer
size: 50,
// Increase font size
fill: 0xFFFFFF
});
sizeText.anchor.set(0.5, 1);
sizeText.y = -fishBody.height / 2 - 10;
self.addChild(sizeText);
// Update size text when fish grows
self.grow = function (amount) {
self.fishSize += amount;
var newScale = 1 + (self.fishSize - 1) * 0.2;
tween(self.scale, {
x: self.direction * newScale,
y: newScale
}, {
duration: 300,
easing: tween.elasticOut
});
sizeText.setText(self.fishSize.toFixed(1)); // Update size text with one decimal place
sizeText.scale.set(newScale); // Adjust text size based on fish size
if (self.type === 'player') {
LK.getSound('grow').play();
// Display 'Nice' or 'Cool' text randomly
var growText = Math.random() > 0.5 ? 'Nice' : 'Cool';
var growTextDisplay = new Text2(growText, {
size: 100,
fill: 0xFFFFFF
});
growTextDisplay.anchor.set(1, 0); // Set anchor to top-right corner
growTextDisplay.x = self.width / 2; // Position at the top-right corner of the fish
growTextDisplay.y = -self.height / 2;
self.addChild(growTextDisplay);
tween(growTextDisplay, {
alpha: 0,
y: growTextDisplay.y - 50
}, {
duration: 1000,
onComplete: function onComplete() {
growTextDisplay.destroy();
}
});
// Change color based on size
if (self.fishSize < 2) {
self.fishColor = 0x3498db; // Blue
} else if (self.fishSize < 3) {
self.fishColor = 0xe74c3c; // Red
} else {
self.fishColor = 0x9b59b6; // Purple
}
fishBody.tint = self.fishColor;
tail.tint = self.fishColor;
}
};
return self;
});
var FoodParticle = Container.expand(function () {
var self = Container.call(this);
var foodGraphic = self.attachAsset('foodParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 0.1;
self.speed = 0.5 + Math.random() * 1;
// Slowly sink
self.update = function () {
self.y += self.speed;
// Add slight horizontal drift
self.x += Math.sin(LK.ticks / 10 + self.y / 100) * 0.3;
// Remove when offscreen
if (self.y > 2800) {
self.destroy();
}
};
return self;
});
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'speed';
var powerupGraphic = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Different colors for different power-ups
if (self.type === 'speed') {
powerupGraphic.tint = 0xe67e22; // Orange
} else if (self.type === 'invincibility') {
powerupGraphic.tint = 0xe74c3c; // Red
} else if (self.type === 'magnet') {
powerupGraphic.tint = 0x9b59b6; // Purple
}
// Floating animation
self.update = function () {
self.y += Math.sin(LK.ticks / 10) * 0.5;
// Slowly sink
if (LK.ticks % 3 === 0) {
self.y += 0.5;
}
// Remove when offscreen
if (self.y > 2800) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4682B4 // Steel blue color
});
/****
* Game Code
****/
// Game variables
var player;
var enemies = [];
var bubbles = [];
var foodParticles = [];
var powerups = [];
var score = 0;
var highScore = storage.highScore || 0;
var playerIsInvincible = false;
var hasMagnet = false;
var isGameActive = true;
// Game difficulty settings
var difficulty = 1;
var maxEnemies = 15;
var enemySpawnRate = 120; // frames between enemy spawns
var foodSpawnRate = 60; // frames between food spawns
var powerupSpawnRate = 600; // frames between powerup spawns
// Track if player is being dragged
var isDragging = false;
// Setup UI elements
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
scoreText.x = 150;
scoreText.y = 50;
var highScoreText = new Text2('High Score: ' + highScore, {
size: 50,
fill: 0xFFFFFF
});
highScoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(highScoreText);
highScoreText.x = -50;
highScoreText.y = 120;
var sizeText = new Text2('Size: 1.0', {
size: 60,
fill: 0xFFFFFF
});
sizeText.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(sizeText);
sizeText.x = 50;
sizeText.y = -50;
var statusText = new Text2('', {
size: 45,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0);
LK.gui.top.addChild(statusText);
statusText.y = 120;
// Initialize player fish
function initializeGame() {
// Add coral objects to the game
for (var i = 0; i < 5; i++) {
var coral = new Coral();
coral.x = 200 + i * 700; // Further increased spacing between corals
coral.y = 2500;
game.addChild(coral);
}
// Add seaweed and rocks to the game
for (var j = 0; j < 3; j++) {
var seaweed = new Coral();
seaweed.x = 400 + j * 600;
seaweed.y = 2600;
game.addChild(seaweed);
}
for (var k = 0; k < 3; k++) {
var rock = new Coral();
rock.x = 600 + k * 800;
rock.y = 2700;
game.addChild(rock);
}
// Reset game state
player = new Fish('player', 1, 3, 0x3498db); // Reduced speed from 5 to 3 for heavier movement
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// Reset game state
enemies = [];
bubbles = [];
foodParticles = [];
powerups = [];
score = 0;
playerIsInvincible = false;
hasMagnet = false;
isGameActive = true;
difficulty = 1;
// Update UI
scoreText.setText('Score: 0');
sizeText.setText('Size: 1.0');
statusText.setText('');
// Start game music
LK.playMusic('oceanTheme');
}
// Initialize the game
initializeGame();
// Function to spawn bubbles
function spawnBubble() {
if (Math.random() < 0.02) {
var bubble = new Bubble();
bubble.x = Math.random() * 2048;
bubble.y = 2732 + 50;
game.addChild(bubble);
bubbles.push(bubble);
}
}
// Function to spawn food particles
function spawnFood() {
if (LK.ticks % foodSpawnRate === 0) {
var food = new FoodParticle();
food.x = Math.random() * 2048;
food.y = -50;
game.addChild(food);
foodParticles.push(food);
}
}
// Function to spawn power-ups
function spawnPowerup() {
if (LK.ticks % powerupSpawnRate === 0 && Math.random() < 0.3) {
var types = ['speed', 'invincibility', 'magnet'];
var type = types[Math.floor(Math.random() * types.length)];
var powerup = new Powerup(type);
powerup.x = 100 + Math.random() * (2048 - 200);
powerup.y = -50;
game.addChild(powerup);
powerups.push(powerup);
}
}
// Function to spawn enemy fish
function spawnEnemy() {
if (LK.ticks % enemySpawnRate === 0 && enemies.length < maxEnemies) {
// Decide fish size relative to player
var sizeFactor;
var rnd = Math.random();
if (rnd < 0.6) {
// 60% chance for smaller fish
sizeFactor = 0.5 + Math.random() * 0.4;
} else if (rnd < 0.85) {
// 25% chance for similar sized fish
sizeFactor = 0.9 + Math.random() * 0.2;
} else {
// 15% chance for larger fish
sizeFactor = 1.2 + Math.random() * (difficulty * 0.5);
}
var fishSize = player.fishSize * sizeFactor;
// Determine fish type based on size
var fishType;
if (fishSize < 1) {
fishType = 'small';
} else if (fishSize < 2) {
fishType = 'medium';
} else {
fishType = 'large';
}
// Create the enemy
var enemy = new Fish(fishType, fishSize, 1 + Math.random() * 3);
// Position on either left or right side of screen
var fromLeft = Math.random() > 0.5;
enemy.x = fromLeft ? -100 : 2148;
enemy.y = 200 + Math.random() * (2732 - 400);
enemy.direction = fromLeft ? 1 : -1;
enemy.scale.x = enemy.direction;
// Add to game
game.addChild(enemy);
enemies.push(enemy);
}
}
// Function to check collisions between player and other entities
function checkCollisions() {
if (!isGameActive) {
return;
}
// Check collisions with enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// If enemy is off-screen for too long, remove it
if (!enemy.isOnScreen() && (enemy.x < -200 || enemy.x > 2248)) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (player.intersects(enemy)) {
if (player.canEat(enemy) || playerIsInvincible) {
// Player eats enemy
var growAmount = enemy.fishSize * 0.1;
player.grow(growAmount);
// Update score
score += Math.floor(enemy.fishSize * 10) + Math.floor(enemy.fishSize);
scoreText.setText('Score: ' + score);
sizeText.setText('Size: ' + player.fishSize.toFixed(1));
// Display 'Kill' text
statusText.setText('Kill');
LK.setTimeout(function () {
statusText.setText('');
}, 1000);
// Check for high score
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
highScoreText.setText('High Score: ' + highScore);
}
// Remove enemy
enemy.destroy();
enemies.splice(i, 1);
// Play eat sound
LK.getSound('eat').play();
// Increase difficulty
if (score > difficulty * 100) {
difficulty++;
enemySpawnRate = Math.max(40, 120 - difficulty * 5);
foodSpawnRate = Math.max(30, 60 - difficulty * 2);
}
} else if (!playerIsInvincible && enemy.fishColor !== 0x2ecc71 && enemy.type !== 'small') {
// Player gets eaten
LK.effects.flashScreen(0xff0000, 1000);
statusText.setText('Kill');
isGameActive = false;
LK.showGameOver(); // End the game and show game over screen
}
}
}
// Check collisions with food particles
for (var j = foodParticles.length - 1; j >= 0; j--) {
var food = foodParticles[j];
// If food is magnet-attracted
if (hasMagnet) {
var dx = player.x - food.x;
var dy = player.y - food.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 300) {
var factor = 0.05;
food.x += dx * factor;
food.y += dy * factor;
}
}
// Check collision
if (player.intersects(food)) {
// Player eats food
player.grow(food.value);
score += 1;
scoreText.setText('Score: ' + score);
sizeText.setText('Size: ' + player.fishSize.toFixed(1));
// Check for high score
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
highScoreText.setText('High Score: ' + highScore);
}
// Remove food
food.destroy();
foodParticles.splice(j, 1);
}
}
// Check collisions with powerups
for (var k = powerups.length - 1; k >= 0; k--) {
var powerup = powerups[k];
if (player.intersects(powerup)) {
// Apply powerup effect
if (powerup.type === 'speed') {
// Speed boost
player.speed = 10;
statusText.setText('Speed Boost!');
LK.setTimeout(function () {
player.speed = 5;
statusText.setText('');
}, 5000);
} else if (powerup.type === 'invincibility') {
// Invincibility
playerIsInvincible = true;
statusText.setText('Invincible!');
player.alpha = 0.7;
LK.setTimeout(function () {
playerIsInvincible = false;
statusText.setText('');
player.alpha = 1;
}, 7000);
} else if (powerup.type === 'magnet') {
// Food magnet
hasMagnet = true;
statusText.setText('Food Magnet!');
LK.setTimeout(function () {
hasMagnet = false;
statusText.setText('');
}, 10000);
}
// Remove powerup
powerup.destroy();
powerups.splice(k, 1);
}
}
}
// Update game state
game.update = function () {
if (!isGameActive) {
return;
}
// Spawn entities
spawnBubble();
spawnFood();
spawnEnemy();
spawnPowerup();
// Update entities that don't have auto-update
for (var i = 0; i < bubbles.length; i++) {
if (bubbles[i] && typeof bubbles[i].update === 'function') {
bubbles[i].update();
}
}
for (var j = 0; j < foodParticles.length; j++) {
if (foodParticles[j] && typeof foodParticles[j].update === 'function') {
foodParticles[j].update();
}
}
for (var k = 0; k < powerups.length; k++) {
if (powerups[k] && typeof powerups[k].update === 'function') {
powerups[k].update();
}
}
// Check collisions
checkCollisions();
// Update player direction based on movement
if (isDragging && player.lastX) {
if (player.x > player.lastX + 5) {
player.direction = 1;
player.scale.x = player.direction * (1 + (player.fishSize - 1) * 0.2);
} else if (player.x < player.lastX - 5) {
player.direction = -1;
player.scale.x = player.direction * (1 + (player.fishSize - 1) * 0.2);
}
}
// Store player's last position
player.lastX = player.x;
player.lastY = player.y;
};
// Handle touch/mouse input for player movement
game.down = function (x, y) {
isDragging = true;
player.x = x;
player.y = y;
};
game.move = function (x, y) {
if (isDragging) {
player.x = x;
player.y = y;
}
};
game.up = function () {
isDragging = false;
};