/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BigFish = Container.expand(function () { var self = Container.call(this); var fishGraphics = self.attachAsset('largeFish', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -1.5 - Math.random() * 0.8; self.damage = 20; self.waveAmplitude = Math.random() * 80 + 40; self.waveFrequency = Math.random() * 0.04 + 0.02; self.waveOffset = Math.random() * Math.PI * 2; self.startY = self.y; self.movePattern = Math.random() < 0.8 ? 'straight' : 'wave'; self.update = function () { self.x += self.speed; if (self.movePattern === 'wave') { self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude; } }; return self; }); var Coral = Container.expand(function (type) { var self = Container.call(this); var coralType = type || 'coral1'; var coralGraphics = self.attachAsset(coralType, { anchorX: 0.5, anchorY: 1.0 }); self.coralType = coralType; self.pulseScale = 1.0; self.pulseDirection = 1; self.pulseSpeed = Math.random() * 0.005 + 0.002; self.update = function () { // Gentle pulsing motion self.pulseScale += self.pulseDirection * self.pulseSpeed; if (self.pulseScale > 1.1) { self.pulseScale = 1.1; self.pulseDirection = -1; } else if (self.pulseScale < 0.9) { self.pulseScale = 0.9; self.pulseDirection = 1; } coralGraphics.scaleX = self.pulseScale; coralGraphics.scaleY = self.pulseScale; }; return self; }); var Fish = Container.expand(function (type) { var self = Container.call(this); var fishType = type || 'small'; var fishGraphics = self.attachAsset(fishType + 'Fish', { anchorX: 0.5, anchorY: 0.5 }); self.fishType = fishType; self.speed = -1 - Math.random() * 0.5; self.points = fishType === 'small' ? 10 : fishType === 'medium' ? 25 : 50; self.waveAmplitude = Math.random() * 100 + 50; self.waveFrequency = Math.random() * 0.05 + 0.02; self.waveOffset = Math.random() * Math.PI * 2; self.startY = self.y; self.movePattern = Math.random() < 0.7 ? 'straight' : 'wave'; self.update = function () { self.x += self.speed; if (self.movePattern === 'wave') { self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude; } }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -5; self.animationDirection = 1; self.baseY = self.y; self.animationRange = 150; self.update = function () { self.x += self.speed; }; return self; }); var SeaweedPlant = Container.expand(function (type) { var self = Container.call(this); var plantType = type || 'seaweed1'; var plantGraphics = self.attachAsset(plantType, { anchorX: 0.5, anchorY: 1.0 }); self.plantType = plantType; self.baseX = self.x; self.swayAmount = Math.random() * 10 + 5; self.swaySpeed = Math.random() * 0.02 + 0.01; self.swayOffset = Math.random() * Math.PI * 2; self.update = function () { // Gentle swaying motion self.x = self.baseX + Math.sin(LK.ticks * self.swaySpeed + self.swayOffset) * self.swayAmount; }; return self; }); var Shark = Container.expand(function () { var self = Container.call(this); var sharkGraphics = self.attachAsset('shark', { anchorX: 0.5, anchorY: 0.5 }); self.targetY = 2732 / 2; self.targetX = 300; self.speed = 3; self.scaleX = 1.0; self.scaleY = 1.0; self.update = function () { // Smooth movement towards target Y position var diffY = self.targetY - self.y; self.y += diffY * 0.05; // Smooth movement towards target X position var diffX = self.targetX - self.x; self.x += diffX * 0.05; // Keep shark within map boundaries if (self.x < 75) self.x = 75; if (self.x > 1973) self.x = 1973; if (self.y < 75) self.y = 75; if (self.y > 2657) self.y = 2657; }; return self; }); var Shell = Container.expand(function () { var self = Container.call(this); var shellGraphics = self.attachAsset('shell', { anchorX: 0.5, anchorY: 1.0 }); self.pulseScale = 1.0; self.pulseDirection = 1; self.pulseSpeed = Math.random() * 0.003 + 0.001; self.update = function () { // Very gentle pulsing motion for shells self.pulseScale += self.pulseDirection * self.pulseSpeed; if (self.pulseScale > 1.05) { self.pulseScale = 1.05; self.pulseDirection = -1; } else if (self.pulseScale < 0.95) { self.pulseScale = 0.95; self.pulseDirection = 1; } shellGraphics.scaleX = self.pulseScale; shellGraphics.scaleY = self.pulseScale; }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('ship', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -0.8 - Math.random() * 0.4; self.points = 150; self.bobAmplitude = Math.random() * 8 + 5; self.bobFrequency = Math.random() * 0.02 + 0.01; self.bobOffset = Math.random() * Math.PI * 2; self.startY = self.y; self.update = function () { self.x += self.speed; // Gentle bobbing motion on water surface self.y = self.startY + Math.sin(self.x * self.bobFrequency + self.bobOffset) * self.bobAmplitude; }; return self; }); var Swimmer = Container.expand(function () { var self = Container.call(this); var swimmerGraphics = self.attachAsset('swimmer', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -0.5 - Math.random() * 0.3; self.points = 100; self.waveAmplitude = Math.random() * 20 + 10; self.waveFrequency = Math.random() * 0.03 + 0.01; self.waveOffset = Math.random() * Math.PI * 2; self.startY = self.y; self.update = function () { self.x += self.speed; // Swimming motion with small waves self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001a33 }); /**** * Game Code ****/ // Create beach at the top of the screen var beach = LK.getAsset('beach', { anchorX: 0, anchorY: 0 }); beach.x = 0; beach.y = 0; beach.scaleX = 20.48; // Scale to cover full width (2048/100) beach.scaleY = 1.5; // Make it taller for better visual game.addChild(beach); // Create ocean floor that spans the entire screen width var oceanFloor = LK.getAsset('oceanFloor', { anchorX: 0, anchorY: 1.0 }); oceanFloor.x = 0; oceanFloor.y = 2732; oceanFloor.scaleX = 20.48; // Scale to cover full width (2048/100) oceanFloor.scaleY = 2; // Make it taller for better visual game.addChild(oceanFloor); // Create background plants and corals var plants = []; var corals = []; var shells = []; // Add seaweed plants for (var p = 0; p < 15; p++) { var plantTypes = ['seaweed1', 'seaweed2', 'seaweed3']; var plantType = plantTypes[Math.floor(Math.random() * plantTypes.length)]; var plant = new SeaweedPlant(plantType); plant.x = Math.random() * 2048; plant.y = 2732 - Math.random() * 50; plant.baseX = plant.x; plants.push(plant); game.addChild(plant); } // Add coral decorations for (var c = 0; c < 8; c++) { var coralTypes = ['coral1', 'coral2']; var coralType = coralTypes[Math.floor(Math.random() * coralTypes.length)]; var coral = new Coral(coralType); coral.x = Math.random() * 2048; coral.y = 2732 - Math.random() * 30; corals.push(coral); game.addChild(coral); } // Add shell decorations for (var s = 0; s < 12; s++) { var shell = new Shell(); shell.x = Math.random() * 2048; shell.y = 2732 - Math.random() * 20; shells.push(shell); game.addChild(shell); } var shark = game.addChild(new Shark()); shark.x = 300; shark.y = 2732 / 2; var maxHealth = 100; var currentHealth = 100; var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -20; scoreTxt.y = 20; // Create health bar background var healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(healthBarBg); healthBarBg.x = 120; healthBarBg.y = 20; // Create health bar foreground var healthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(healthBar); healthBar.x = 120; healthBar.y = 20; // Create health text var healthTxt = new Text2('Health: 100', { size: 60, fill: 0xFFFFFF }); healthTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(healthTxt); healthTxt.x = 120; healthTxt.y = 50; var fish = []; var bigFish = []; var obstacles = []; var swimmers = []; var ships = []; var gameSpeed = 1; var spawnTimer = 0; var bigFishTimer = 0; var obstacleTimer = 0; var speedIncreaseTimer = 0; var swimmerTimer = 0; var shipTimer = 0; // Mouse/finger tracking variables var mouseY = 2732 / 2; var mouseX = 300; function takeDamage(amount) { currentHealth -= amount; if (currentHealth < 0) currentHealth = 0; // Add damage points to score var currentScore = LK.getScore(); var newScore = currentScore + amount; LK.setScore(newScore); scoreTxt.setText('Score: ' + newScore); // Update health bar var healthPercent = currentHealth / maxHealth; healthBar.scaleX = healthPercent; healthBar.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000; healthTxt.setText('Health: ' + currentHealth); // Flash screen red when taking damage LK.effects.flashScreen(0xff0000, 300); LK.getSound('damage').play(); // Check for game over if (currentHealth <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } function spawnFish() { var fishTypes = ['small', 'small', 'small', 'medium', 'medium', 'large']; var type = fishTypes[Math.floor(Math.random() * fishTypes.length)]; var newFish = new Fish(type); newFish.x = 2048 + 50; newFish.y = Math.random() * (2732 - 200) + 100; newFish.startY = newFish.y; fish.push(newFish); game.addChild(newFish); } function spawnBigFish() { var newBigFish = new BigFish(); newBigFish.x = 2048 + 75; newBigFish.y = Math.random() * (2732 - 200) + 100; newBigFish.startY = newBigFish.y; bigFish.push(newBigFish); game.addChild(newBigFish); } function spawnSwimmer() { var newSwimmer = new Swimmer(); newSwimmer.x = 2048 + 50; newSwimmer.y = Math.random() * 150 + 100; // Stay near the beach/surface newSwimmer.startY = newSwimmer.y; swimmers.push(newSwimmer); game.addChild(newSwimmer); } function spawnShip() { var newShip = new Ship(); newShip.x = 2048 + 60; newShip.y = Math.random() * 80 + 180; // Stay at water surface level newShip.startY = newShip.y; ships.push(newShip); game.addChild(newShip); } function createBloodEffect(x, y) { // Create multiple blood particles for (var p = 0; p < 8; p++) { var bloodParticle = LK.getAsset('bloodParticle', { anchorX: 0.5, anchorY: 0.5 }); bloodParticle.x = x + (Math.random() - 0.5) * 40; bloodParticle.y = y + (Math.random() - 0.5) * 40; game.addChild(bloodParticle); // Animate blood particle with random direction and fade out var targetX = bloodParticle.x + (Math.random() - 0.5) * 150; var targetY = bloodParticle.y + (Math.random() - 0.5) * 150; tween(bloodParticle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 800 + Math.random() * 400, easing: tween.easeOut, onFinish: function onFinish() { bloodParticle.destroy(); } }); } } function spawnObstacle() { var newObstacle = new Obstacle(); newObstacle.x = 2048 + 50; newObstacle.y = Math.random() * (2732 - 200) + 100; newObstacle.baseY = newObstacle.y; // Start up and down animation function animateObstacle() { var targetY = newObstacle.baseY + newObstacle.animationDirection * newObstacle.animationRange; tween(newObstacle, { y: targetY }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { newObstacle.animationDirection *= -1; animateObstacle(); } }); } animateObstacle(); obstacles.push(newObstacle); game.addChild(newObstacle); } game.down = function (x, y, obj) { mouseY = Math.max(75, Math.min(y, 2657)); mouseX = Math.max(75, Math.min(x, 1973)); shark.targetY = mouseY; shark.targetX = mouseX; }; game.move = function (x, y, obj) { mouseY = Math.max(75, Math.min(y, 2657)); mouseX = Math.max(75, Math.min(x, 1973)); shark.targetY = mouseY; shark.targetX = mouseX; }; game.update = function () { spawnTimer++; bigFishTimer++; obstacleTimer++; speedIncreaseTimer++; swimmerTimer++; shipTimer++; // Spawn fish if (spawnTimer >= Math.max(30 - Math.floor(gameSpeed), 15)) { spawnFish(); spawnTimer = 0; } // Spawn big fish occasionally if (bigFishTimer >= Math.max(450 - Math.floor(gameSpeed * 25), 250)) { if (Math.random() < 0.6) { spawnBigFish(); } bigFishTimer = 0; } // Spawn swimmers occasionally if (swimmerTimer >= Math.max(400 - Math.floor(gameSpeed * 20), 200)) { if (Math.random() < 0.4) { spawnSwimmer(); } swimmerTimer = 0; } // Spawn ships occasionally if (shipTimer >= Math.max(600 - Math.floor(gameSpeed * 30), 300)) { if (Math.random() < 0.3) { spawnShip(); } shipTimer = 0; } // Spawn obstacles occasionally if (obstacleTimer >= Math.max(200 - Math.floor(gameSpeed * 10), 100)) { if (Math.random() < 0.3) { spawnObstacle(); } obstacleTimer = 0; } // Increase game speed over time if (speedIncreaseTimer >= 300) { gameSpeed += 0.1; speedIncreaseTimer = 0; } // Update and check fish for (var i = fish.length - 1; i >= 0; i--) { var currentFish = fish[i]; // Initialize tracking variables if (currentFish.lastX === undefined) currentFish.lastX = currentFish.x; if (currentFish.lastIntersecting === undefined) currentFish.lastIntersecting = false; // Check if fish went off screen if (currentFish.lastX >= -100 && currentFish.x < -100) { currentFish.destroy(); fish.splice(i, 1); continue; } // Check collision with shark var currentIntersecting = shark.intersects(currentFish); if (!currentFish.lastIntersecting && currentIntersecting) { var currentScore = LK.getScore(); var canEat = false; // Check if shark can eat this fish type based on score if (currentFish.fishType === 'small') { canEat = true; // Can always eat small fish } else if (currentFish.fishType === 'medium') { canEat = currentScore >= 200; // Can eat medium fish after 200 points } else if (currentFish.fishType === 'large') { canEat = currentScore >= 500; // Can eat large fish after 500 points } if (canEat) { // Fish eaten var newScore = currentScore + currentFish.points; LK.setScore(newScore); scoreTxt.setText('Score: ' + newScore); LK.getSound('eat').play(); // Scale shark based on score milestones var newScale = 1.0; if (newScore >= 500) { newScale = 1.5; } else if (newScore >= 200) { newScale = 1.25; } // Animate shark scaling if it changed if (shark.scaleX !== newScale) { tween(shark, { scaleX: newScale, scaleY: newScale }, { duration: 300, easing: tween.easeOut }); } // Create blood effect at fish position createBloodEffect(currentFish.x, currentFish.y); // Flash effect LK.effects.flashObject(currentFish, 0x00ff00, 200); currentFish.destroy(); fish.splice(i, 1); continue; } else { // Can't eat this fish - take damage and bounce back effect if (currentFish.fishType === 'medium' && currentScore < 200) { takeDamage(15); // Take damage from medium fish when score is under 200 } else if (currentFish.fishType === 'large' && currentScore < 500) { takeDamage(25); // Take damage from large fish when score is under 500 } LK.effects.flashObject(currentFish, 0xff0000, 200); LK.effects.flashObject(shark, 0xff0000, 200); } } // Update tracking variables currentFish.lastX = currentFish.x; currentFish.lastIntersecting = currentIntersecting; } // Update and check big fish for (var b = bigFish.length - 1; b >= 0; b--) { var currentBigFish = bigFish[b]; // Initialize tracking variables if (currentBigFish.lastX === undefined) currentBigFish.lastX = currentBigFish.x; if (currentBigFish.lastIntersecting === undefined) currentBigFish.lastIntersecting = false; // Check if big fish went off screen if (currentBigFish.lastX >= -120 && currentBigFish.x < -120) { currentBigFish.destroy(); bigFish.splice(b, 1); continue; } // Check collision with shark - big fish damage shark var currentIntersecting = shark.intersects(currentBigFish); if (!currentBigFish.lastIntersecting && currentIntersecting) { // Take damage from big fish takeDamage(currentBigFish.damage); // Flash both objects red LK.effects.flashObject(currentBigFish, 0xff0000, 200); LK.effects.flashObject(shark, 0xff0000, 200); // Create blood effect at collision createBloodEffect(currentBigFish.x, currentBigFish.y); // Remove big fish after collision currentBigFish.destroy(); bigFish.splice(b, 1); continue; } // Update tracking variables currentBigFish.lastX = currentBigFish.x; currentBigFish.lastIntersecting = currentIntersecting; } // Update and check swimmers for (var s = swimmers.length - 1; s >= 0; s--) { var currentSwimmer = swimmers[s]; // Initialize tracking variables if (currentSwimmer.lastX === undefined) currentSwimmer.lastX = currentSwimmer.x; if (currentSwimmer.lastIntersecting === undefined) currentSwimmer.lastIntersecting = false; // Check if swimmer went off screen if (currentSwimmer.lastX >= -100 && currentSwimmer.x < -100) { currentSwimmer.destroy(); swimmers.splice(s, 1); continue; } // Check collision with shark - only if score >= 1000 var currentIntersecting = shark.intersects(currentSwimmer); if (!currentSwimmer.lastIntersecting && currentIntersecting) { var currentScore = LK.getScore(); if (currentScore >= 1000) { // Can eat swimmer var newScore = currentScore + currentSwimmer.points; LK.setScore(newScore); scoreTxt.setText('Score: ' + newScore); LK.getSound('eat').play(); // Create blood effect at swimmer position createBloodEffect(currentSwimmer.x, currentSwimmer.y); // Flash effect LK.effects.flashObject(currentSwimmer, 0x00ff00, 200); currentSwimmer.destroy(); swimmers.splice(s, 1); continue; } else { // Can't eat swimmer yet - bounce back effect LK.effects.flashObject(currentSwimmer, 0xff0000, 200); LK.effects.flashObject(shark, 0xff0000, 200); } } // Update tracking variables currentSwimmer.lastX = currentSwimmer.x; currentSwimmer.lastIntersecting = currentIntersecting; } // Update and check ships for (var h = ships.length - 1; h >= 0; h--) { var currentShip = ships[h]; // Initialize tracking variables if (currentShip.lastX === undefined) currentShip.lastX = currentShip.x; if (currentShip.lastIntersecting === undefined) currentShip.lastIntersecting = false; // Check if ship went off screen if (currentShip.lastX >= -120 && currentShip.x < -120) { currentShip.destroy(); ships.splice(h, 1); continue; } // Check collision with shark - only if score >= 1500 var currentIntersecting = shark.intersects(currentShip); if (!currentShip.lastIntersecting && currentIntersecting) { var currentScore = LK.getScore(); if (currentScore >= 1500) { // Can eat ship var newScore = currentScore + currentShip.points; LK.setScore(newScore); scoreTxt.setText('Score: ' + newScore); LK.getSound('eat').play(); // Create blood effect at ship position createBloodEffect(currentShip.x, currentShip.y); // Flash effect LK.effects.flashObject(currentShip, 0x00ff00, 200); currentShip.destroy(); ships.splice(h, 1); continue; } else { // Can't eat ship yet - bounce back effect LK.effects.flashObject(currentShip, 0xff0000, 200); LK.effects.flashObject(shark, 0xff0000, 200); } } // Update tracking variables currentShip.lastX = currentShip.x; currentShip.lastIntersecting = currentIntersecting; } // Update and check obstacles for (var j = obstacles.length - 1; j >= 0; j--) { var currentObstacle = obstacles[j]; // Initialize tracking variables if (currentObstacle.lastX === undefined) currentObstacle.lastX = currentObstacle.x; if (currentObstacle.lastIntersecting === undefined) currentObstacle.lastIntersecting = false; // Check if obstacle went off screen if (currentObstacle.lastX >= -100 && currentObstacle.x < -100) { currentObstacle.destroy(); obstacles.splice(j, 1); continue; } // Check collision with shark var currentIntersecting = shark.intersects(currentObstacle); if (!currentObstacle.lastIntersecting && currentIntersecting) { // Hit obstacle - game over LK.getSound('hit').play(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Update tracking variables currentObstacle.lastX = currentObstacle.x; currentObstacle.lastIntersecting = currentIntersecting; } // Allow shark to move anywhere on the map - no bounds constraints }; // Play background music LK.playMusic('ocean');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigFish = Container.expand(function () {
var self = Container.call(this);
var fishGraphics = self.attachAsset('largeFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -1.5 - Math.random() * 0.8;
self.damage = 20;
self.waveAmplitude = Math.random() * 80 + 40;
self.waveFrequency = Math.random() * 0.04 + 0.02;
self.waveOffset = Math.random() * Math.PI * 2;
self.startY = self.y;
self.movePattern = Math.random() < 0.8 ? 'straight' : 'wave';
self.update = function () {
self.x += self.speed;
if (self.movePattern === 'wave') {
self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude;
}
};
return self;
});
var Coral = Container.expand(function (type) {
var self = Container.call(this);
var coralType = type || 'coral1';
var coralGraphics = self.attachAsset(coralType, {
anchorX: 0.5,
anchorY: 1.0
});
self.coralType = coralType;
self.pulseScale = 1.0;
self.pulseDirection = 1;
self.pulseSpeed = Math.random() * 0.005 + 0.002;
self.update = function () {
// Gentle pulsing motion
self.pulseScale += self.pulseDirection * self.pulseSpeed;
if (self.pulseScale > 1.1) {
self.pulseScale = 1.1;
self.pulseDirection = -1;
} else if (self.pulseScale < 0.9) {
self.pulseScale = 0.9;
self.pulseDirection = 1;
}
coralGraphics.scaleX = self.pulseScale;
coralGraphics.scaleY = self.pulseScale;
};
return self;
});
var Fish = Container.expand(function (type) {
var self = Container.call(this);
var fishType = type || 'small';
var fishGraphics = self.attachAsset(fishType + 'Fish', {
anchorX: 0.5,
anchorY: 0.5
});
self.fishType = fishType;
self.speed = -1 - Math.random() * 0.5;
self.points = fishType === 'small' ? 10 : fishType === 'medium' ? 25 : 50;
self.waveAmplitude = Math.random() * 100 + 50;
self.waveFrequency = Math.random() * 0.05 + 0.02;
self.waveOffset = Math.random() * Math.PI * 2;
self.startY = self.y;
self.movePattern = Math.random() < 0.7 ? 'straight' : 'wave';
self.update = function () {
self.x += self.speed;
if (self.movePattern === 'wave') {
self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -5;
self.animationDirection = 1;
self.baseY = self.y;
self.animationRange = 150;
self.update = function () {
self.x += self.speed;
};
return self;
});
var SeaweedPlant = Container.expand(function (type) {
var self = Container.call(this);
var plantType = type || 'seaweed1';
var plantGraphics = self.attachAsset(plantType, {
anchorX: 0.5,
anchorY: 1.0
});
self.plantType = plantType;
self.baseX = self.x;
self.swayAmount = Math.random() * 10 + 5;
self.swaySpeed = Math.random() * 0.02 + 0.01;
self.swayOffset = Math.random() * Math.PI * 2;
self.update = function () {
// Gentle swaying motion
self.x = self.baseX + Math.sin(LK.ticks * self.swaySpeed + self.swayOffset) * self.swayAmount;
};
return self;
});
var Shark = Container.expand(function () {
var self = Container.call(this);
var sharkGraphics = self.attachAsset('shark', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetY = 2732 / 2;
self.targetX = 300;
self.speed = 3;
self.scaleX = 1.0;
self.scaleY = 1.0;
self.update = function () {
// Smooth movement towards target Y position
var diffY = self.targetY - self.y;
self.y += diffY * 0.05;
// Smooth movement towards target X position
var diffX = self.targetX - self.x;
self.x += diffX * 0.05;
// Keep shark within map boundaries
if (self.x < 75) self.x = 75;
if (self.x > 1973) self.x = 1973;
if (self.y < 75) self.y = 75;
if (self.y > 2657) self.y = 2657;
};
return self;
});
var Shell = Container.expand(function () {
var self = Container.call(this);
var shellGraphics = self.attachAsset('shell', {
anchorX: 0.5,
anchorY: 1.0
});
self.pulseScale = 1.0;
self.pulseDirection = 1;
self.pulseSpeed = Math.random() * 0.003 + 0.001;
self.update = function () {
// Very gentle pulsing motion for shells
self.pulseScale += self.pulseDirection * self.pulseSpeed;
if (self.pulseScale > 1.05) {
self.pulseScale = 1.05;
self.pulseDirection = -1;
} else if (self.pulseScale < 0.95) {
self.pulseScale = 0.95;
self.pulseDirection = 1;
}
shellGraphics.scaleX = self.pulseScale;
shellGraphics.scaleY = self.pulseScale;
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -0.8 - Math.random() * 0.4;
self.points = 150;
self.bobAmplitude = Math.random() * 8 + 5;
self.bobFrequency = Math.random() * 0.02 + 0.01;
self.bobOffset = Math.random() * Math.PI * 2;
self.startY = self.y;
self.update = function () {
self.x += self.speed;
// Gentle bobbing motion on water surface
self.y = self.startY + Math.sin(self.x * self.bobFrequency + self.bobOffset) * self.bobAmplitude;
};
return self;
});
var Swimmer = Container.expand(function () {
var self = Container.call(this);
var swimmerGraphics = self.attachAsset('swimmer', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -0.5 - Math.random() * 0.3;
self.points = 100;
self.waveAmplitude = Math.random() * 20 + 10;
self.waveFrequency = Math.random() * 0.03 + 0.01;
self.waveOffset = Math.random() * Math.PI * 2;
self.startY = self.y;
self.update = function () {
self.x += self.speed;
// Swimming motion with small waves
self.y = self.startY + Math.sin(self.x * self.waveFrequency + self.waveOffset) * self.waveAmplitude;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001a33
});
/****
* Game Code
****/
// Create beach at the top of the screen
var beach = LK.getAsset('beach', {
anchorX: 0,
anchorY: 0
});
beach.x = 0;
beach.y = 0;
beach.scaleX = 20.48; // Scale to cover full width (2048/100)
beach.scaleY = 1.5; // Make it taller for better visual
game.addChild(beach);
// Create ocean floor that spans the entire screen width
var oceanFloor = LK.getAsset('oceanFloor', {
anchorX: 0,
anchorY: 1.0
});
oceanFloor.x = 0;
oceanFloor.y = 2732;
oceanFloor.scaleX = 20.48; // Scale to cover full width (2048/100)
oceanFloor.scaleY = 2; // Make it taller for better visual
game.addChild(oceanFloor);
// Create background plants and corals
var plants = [];
var corals = [];
var shells = [];
// Add seaweed plants
for (var p = 0; p < 15; p++) {
var plantTypes = ['seaweed1', 'seaweed2', 'seaweed3'];
var plantType = plantTypes[Math.floor(Math.random() * plantTypes.length)];
var plant = new SeaweedPlant(plantType);
plant.x = Math.random() * 2048;
plant.y = 2732 - Math.random() * 50;
plant.baseX = plant.x;
plants.push(plant);
game.addChild(plant);
}
// Add coral decorations
for (var c = 0; c < 8; c++) {
var coralTypes = ['coral1', 'coral2'];
var coralType = coralTypes[Math.floor(Math.random() * coralTypes.length)];
var coral = new Coral(coralType);
coral.x = Math.random() * 2048;
coral.y = 2732 - Math.random() * 30;
corals.push(coral);
game.addChild(coral);
}
// Add shell decorations
for (var s = 0; s < 12; s++) {
var shell = new Shell();
shell.x = Math.random() * 2048;
shell.y = 2732 - Math.random() * 20;
shells.push(shell);
game.addChild(shell);
}
var shark = game.addChild(new Shark());
shark.x = 300;
shark.y = 2732 / 2;
var maxHealth = 100;
var currentHealth = 100;
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -20;
scoreTxt.y = 20;
// Create health bar background
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(healthBarBg);
healthBarBg.x = 120;
healthBarBg.y = 20;
// Create health bar foreground
var healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
// Create health text
var healthTxt = new Text2('Health: 100', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthTxt);
healthTxt.x = 120;
healthTxt.y = 50;
var fish = [];
var bigFish = [];
var obstacles = [];
var swimmers = [];
var ships = [];
var gameSpeed = 1;
var spawnTimer = 0;
var bigFishTimer = 0;
var obstacleTimer = 0;
var speedIncreaseTimer = 0;
var swimmerTimer = 0;
var shipTimer = 0;
// Mouse/finger tracking variables
var mouseY = 2732 / 2;
var mouseX = 300;
function takeDamage(amount) {
currentHealth -= amount;
if (currentHealth < 0) currentHealth = 0;
// Add damage points to score
var currentScore = LK.getScore();
var newScore = currentScore + amount;
LK.setScore(newScore);
scoreTxt.setText('Score: ' + newScore);
// Update health bar
var healthPercent = currentHealth / maxHealth;
healthBar.scaleX = healthPercent;
healthBar.tint = healthPercent > 0.5 ? 0x00ff00 : healthPercent > 0.25 ? 0xffff00 : 0xff0000;
healthTxt.setText('Health: ' + currentHealth);
// Flash screen red when taking damage
LK.effects.flashScreen(0xff0000, 300);
LK.getSound('damage').play();
// Check for game over
if (currentHealth <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
function spawnFish() {
var fishTypes = ['small', 'small', 'small', 'medium', 'medium', 'large'];
var type = fishTypes[Math.floor(Math.random() * fishTypes.length)];
var newFish = new Fish(type);
newFish.x = 2048 + 50;
newFish.y = Math.random() * (2732 - 200) + 100;
newFish.startY = newFish.y;
fish.push(newFish);
game.addChild(newFish);
}
function spawnBigFish() {
var newBigFish = new BigFish();
newBigFish.x = 2048 + 75;
newBigFish.y = Math.random() * (2732 - 200) + 100;
newBigFish.startY = newBigFish.y;
bigFish.push(newBigFish);
game.addChild(newBigFish);
}
function spawnSwimmer() {
var newSwimmer = new Swimmer();
newSwimmer.x = 2048 + 50;
newSwimmer.y = Math.random() * 150 + 100; // Stay near the beach/surface
newSwimmer.startY = newSwimmer.y;
swimmers.push(newSwimmer);
game.addChild(newSwimmer);
}
function spawnShip() {
var newShip = new Ship();
newShip.x = 2048 + 60;
newShip.y = Math.random() * 80 + 180; // Stay at water surface level
newShip.startY = newShip.y;
ships.push(newShip);
game.addChild(newShip);
}
function createBloodEffect(x, y) {
// Create multiple blood particles
for (var p = 0; p < 8; p++) {
var bloodParticle = LK.getAsset('bloodParticle', {
anchorX: 0.5,
anchorY: 0.5
});
bloodParticle.x = x + (Math.random() - 0.5) * 40;
bloodParticle.y = y + (Math.random() - 0.5) * 40;
game.addChild(bloodParticle);
// Animate blood particle with random direction and fade out
var targetX = bloodParticle.x + (Math.random() - 0.5) * 150;
var targetY = bloodParticle.y + (Math.random() - 0.5) * 150;
tween(bloodParticle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
bloodParticle.destroy();
}
});
}
}
function spawnObstacle() {
var newObstacle = new Obstacle();
newObstacle.x = 2048 + 50;
newObstacle.y = Math.random() * (2732 - 200) + 100;
newObstacle.baseY = newObstacle.y;
// Start up and down animation
function animateObstacle() {
var targetY = newObstacle.baseY + newObstacle.animationDirection * newObstacle.animationRange;
tween(newObstacle, {
y: targetY
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
newObstacle.animationDirection *= -1;
animateObstacle();
}
});
}
animateObstacle();
obstacles.push(newObstacle);
game.addChild(newObstacle);
}
game.down = function (x, y, obj) {
mouseY = Math.max(75, Math.min(y, 2657));
mouseX = Math.max(75, Math.min(x, 1973));
shark.targetY = mouseY;
shark.targetX = mouseX;
};
game.move = function (x, y, obj) {
mouseY = Math.max(75, Math.min(y, 2657));
mouseX = Math.max(75, Math.min(x, 1973));
shark.targetY = mouseY;
shark.targetX = mouseX;
};
game.update = function () {
spawnTimer++;
bigFishTimer++;
obstacleTimer++;
speedIncreaseTimer++;
swimmerTimer++;
shipTimer++;
// Spawn fish
if (spawnTimer >= Math.max(30 - Math.floor(gameSpeed), 15)) {
spawnFish();
spawnTimer = 0;
}
// Spawn big fish occasionally
if (bigFishTimer >= Math.max(450 - Math.floor(gameSpeed * 25), 250)) {
if (Math.random() < 0.6) {
spawnBigFish();
}
bigFishTimer = 0;
}
// Spawn swimmers occasionally
if (swimmerTimer >= Math.max(400 - Math.floor(gameSpeed * 20), 200)) {
if (Math.random() < 0.4) {
spawnSwimmer();
}
swimmerTimer = 0;
}
// Spawn ships occasionally
if (shipTimer >= Math.max(600 - Math.floor(gameSpeed * 30), 300)) {
if (Math.random() < 0.3) {
spawnShip();
}
shipTimer = 0;
}
// Spawn obstacles occasionally
if (obstacleTimer >= Math.max(200 - Math.floor(gameSpeed * 10), 100)) {
if (Math.random() < 0.3) {
spawnObstacle();
}
obstacleTimer = 0;
}
// Increase game speed over time
if (speedIncreaseTimer >= 300) {
gameSpeed += 0.1;
speedIncreaseTimer = 0;
}
// Update and check fish
for (var i = fish.length - 1; i >= 0; i--) {
var currentFish = fish[i];
// Initialize tracking variables
if (currentFish.lastX === undefined) currentFish.lastX = currentFish.x;
if (currentFish.lastIntersecting === undefined) currentFish.lastIntersecting = false;
// Check if fish went off screen
if (currentFish.lastX >= -100 && currentFish.x < -100) {
currentFish.destroy();
fish.splice(i, 1);
continue;
}
// Check collision with shark
var currentIntersecting = shark.intersects(currentFish);
if (!currentFish.lastIntersecting && currentIntersecting) {
var currentScore = LK.getScore();
var canEat = false;
// Check if shark can eat this fish type based on score
if (currentFish.fishType === 'small') {
canEat = true; // Can always eat small fish
} else if (currentFish.fishType === 'medium') {
canEat = currentScore >= 200; // Can eat medium fish after 200 points
} else if (currentFish.fishType === 'large') {
canEat = currentScore >= 500; // Can eat large fish after 500 points
}
if (canEat) {
// Fish eaten
var newScore = currentScore + currentFish.points;
LK.setScore(newScore);
scoreTxt.setText('Score: ' + newScore);
LK.getSound('eat').play();
// Scale shark based on score milestones
var newScale = 1.0;
if (newScore >= 500) {
newScale = 1.5;
} else if (newScore >= 200) {
newScale = 1.25;
}
// Animate shark scaling if it changed
if (shark.scaleX !== newScale) {
tween(shark, {
scaleX: newScale,
scaleY: newScale
}, {
duration: 300,
easing: tween.easeOut
});
}
// Create blood effect at fish position
createBloodEffect(currentFish.x, currentFish.y);
// Flash effect
LK.effects.flashObject(currentFish, 0x00ff00, 200);
currentFish.destroy();
fish.splice(i, 1);
continue;
} else {
// Can't eat this fish - take damage and bounce back effect
if (currentFish.fishType === 'medium' && currentScore < 200) {
takeDamage(15); // Take damage from medium fish when score is under 200
} else if (currentFish.fishType === 'large' && currentScore < 500) {
takeDamage(25); // Take damage from large fish when score is under 500
}
LK.effects.flashObject(currentFish, 0xff0000, 200);
LK.effects.flashObject(shark, 0xff0000, 200);
}
}
// Update tracking variables
currentFish.lastX = currentFish.x;
currentFish.lastIntersecting = currentIntersecting;
}
// Update and check big fish
for (var b = bigFish.length - 1; b >= 0; b--) {
var currentBigFish = bigFish[b];
// Initialize tracking variables
if (currentBigFish.lastX === undefined) currentBigFish.lastX = currentBigFish.x;
if (currentBigFish.lastIntersecting === undefined) currentBigFish.lastIntersecting = false;
// Check if big fish went off screen
if (currentBigFish.lastX >= -120 && currentBigFish.x < -120) {
currentBigFish.destroy();
bigFish.splice(b, 1);
continue;
}
// Check collision with shark - big fish damage shark
var currentIntersecting = shark.intersects(currentBigFish);
if (!currentBigFish.lastIntersecting && currentIntersecting) {
// Take damage from big fish
takeDamage(currentBigFish.damage);
// Flash both objects red
LK.effects.flashObject(currentBigFish, 0xff0000, 200);
LK.effects.flashObject(shark, 0xff0000, 200);
// Create blood effect at collision
createBloodEffect(currentBigFish.x, currentBigFish.y);
// Remove big fish after collision
currentBigFish.destroy();
bigFish.splice(b, 1);
continue;
}
// Update tracking variables
currentBigFish.lastX = currentBigFish.x;
currentBigFish.lastIntersecting = currentIntersecting;
}
// Update and check swimmers
for (var s = swimmers.length - 1; s >= 0; s--) {
var currentSwimmer = swimmers[s];
// Initialize tracking variables
if (currentSwimmer.lastX === undefined) currentSwimmer.lastX = currentSwimmer.x;
if (currentSwimmer.lastIntersecting === undefined) currentSwimmer.lastIntersecting = false;
// Check if swimmer went off screen
if (currentSwimmer.lastX >= -100 && currentSwimmer.x < -100) {
currentSwimmer.destroy();
swimmers.splice(s, 1);
continue;
}
// Check collision with shark - only if score >= 1000
var currentIntersecting = shark.intersects(currentSwimmer);
if (!currentSwimmer.lastIntersecting && currentIntersecting) {
var currentScore = LK.getScore();
if (currentScore >= 1000) {
// Can eat swimmer
var newScore = currentScore + currentSwimmer.points;
LK.setScore(newScore);
scoreTxt.setText('Score: ' + newScore);
LK.getSound('eat').play();
// Create blood effect at swimmer position
createBloodEffect(currentSwimmer.x, currentSwimmer.y);
// Flash effect
LK.effects.flashObject(currentSwimmer, 0x00ff00, 200);
currentSwimmer.destroy();
swimmers.splice(s, 1);
continue;
} else {
// Can't eat swimmer yet - bounce back effect
LK.effects.flashObject(currentSwimmer, 0xff0000, 200);
LK.effects.flashObject(shark, 0xff0000, 200);
}
}
// Update tracking variables
currentSwimmer.lastX = currentSwimmer.x;
currentSwimmer.lastIntersecting = currentIntersecting;
}
// Update and check ships
for (var h = ships.length - 1; h >= 0; h--) {
var currentShip = ships[h];
// Initialize tracking variables
if (currentShip.lastX === undefined) currentShip.lastX = currentShip.x;
if (currentShip.lastIntersecting === undefined) currentShip.lastIntersecting = false;
// Check if ship went off screen
if (currentShip.lastX >= -120 && currentShip.x < -120) {
currentShip.destroy();
ships.splice(h, 1);
continue;
}
// Check collision with shark - only if score >= 1500
var currentIntersecting = shark.intersects(currentShip);
if (!currentShip.lastIntersecting && currentIntersecting) {
var currentScore = LK.getScore();
if (currentScore >= 1500) {
// Can eat ship
var newScore = currentScore + currentShip.points;
LK.setScore(newScore);
scoreTxt.setText('Score: ' + newScore);
LK.getSound('eat').play();
// Create blood effect at ship position
createBloodEffect(currentShip.x, currentShip.y);
// Flash effect
LK.effects.flashObject(currentShip, 0x00ff00, 200);
currentShip.destroy();
ships.splice(h, 1);
continue;
} else {
// Can't eat ship yet - bounce back effect
LK.effects.flashObject(currentShip, 0xff0000, 200);
LK.effects.flashObject(shark, 0xff0000, 200);
}
}
// Update tracking variables
currentShip.lastX = currentShip.x;
currentShip.lastIntersecting = currentIntersecting;
}
// Update and check obstacles
for (var j = obstacles.length - 1; j >= 0; j--) {
var currentObstacle = obstacles[j];
// Initialize tracking variables
if (currentObstacle.lastX === undefined) currentObstacle.lastX = currentObstacle.x;
if (currentObstacle.lastIntersecting === undefined) currentObstacle.lastIntersecting = false;
// Check if obstacle went off screen
if (currentObstacle.lastX >= -100 && currentObstacle.x < -100) {
currentObstacle.destroy();
obstacles.splice(j, 1);
continue;
}
// Check collision with shark
var currentIntersecting = shark.intersects(currentObstacle);
if (!currentObstacle.lastIntersecting && currentIntersecting) {
// Hit obstacle - game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Update tracking variables
currentObstacle.lastX = currentObstacle.x;
currentObstacle.lastIntersecting = currentIntersecting;
}
// Allow shark to move anywhere on the map - no bounds constraints
};
// Play background music
LK.playMusic('ocean');
big fish. In-Game asset. 2d. High contrast. No shadows
shark. In-Game asset. 2d. High contrast. No shadows
fish. In-Game asset. 2d. High contrast. No shadows
jelly fish. In-Game asset. 2d. High contrast. No shadows
small fish. In-Game asset. 2d. High contrast. No shadows
large coral. In-Game asset. 2d. High contrast. No shadows
seaweed. In-Game asset. 2d. High contrast. No shadows
shell. In-Game asset. 2d. High contrast. No shadows
sky. In-Game asset. 2d. High contrast. No shadows
swimming person. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
person on a cano. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
heart. In-Game asset. 2d. High contrast. No shadows