/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1", { recordScore: 0 }); var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Fish = Container.expand(function (type, speed) { var self = Container.call(this); self.type = type || 'smallFish'; self.speed = speed || 2; self.value = 1; self.lastY = 0; if (self.type === 'smallFish') { self.value = 1; self.danger = 0; } else if (self.type === 'mediumFish') { self.value = 2; self.danger = 0.5; } else if (self.type === 'largeFish') { self.value = 4; self.danger = 1; } else if (self.type === 'goldenFish') { self.value = 10; self.danger = 0; } var fishGraphics = self.attachAsset(self.type, { anchorX: 0.5, anchorY: 0.5 }); self.direction = Math.random() > 0.5 ? 1 : -1; fishGraphics.scale.x = self.direction; self.update = function () { self.lastY = self.y; self.x += self.speed * self.direction; // Wrap around screen if (self.x < -100 && self.direction < 0) { self.x = 2148; } else if (self.x > 2148 && self.direction > 0) { self.x = -100; } }; return self; }); var Obstacle = Container.expand(function (speed) { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = speed || 1; self.damage = 10; self.lastY = 0; self.update = function () { self.lastY = self.y; self.y += self.speed; // Remove if off screen if (self.y > 2832) { self.shouldRemove = true; } }; return self; }); var OceanBackground = Container.expand(function () { var self = Container.call(this); // Main ocean background - blue gradient ocean var bgGraphics = self.attachAsset('oceanBg', { anchorX: 0, anchorY: 0 }); bgGraphics.tint = 0x0066cc; // Deep blue ocean color // Create gradient effect with multiple layers var deepLayer = self.attachAsset('oceanBg', { anchorX: 0, anchorY: 0 }); deepLayer.tint = 0x003366; // Darker blue for depth deepLayer.alpha = 0.4; deepLayer.y = 1500; var midLayer = self.attachAsset('oceanBg', { anchorX: 0, anchorY: 0 }); midLayer.tint = 0x0088dd; // Mid blue midLayer.alpha = 0.3; midLayer.y = 800; var topLayer = self.attachAsset('oceanBg', { anchorX: 0, anchorY: 0 }); topLayer.tint = 0x66ccff; // Light blue for surface topLayer.alpha = 0.2; topLayer.y = 0; // Ocean floor with sandy texture var floorGraphics = self.attachAsset('oceanFloor', { anchorX: 0, anchorY: 1 }); floorGraphics.y = 2732; floorGraphics.tint = 0xd2b48c; // Sandy color // Water surface with transparency and shimmer var surfaceGraphics = self.attachAsset('waterSurface', { anchorX: 0, anchorY: 0 }); surfaceGraphics.y = 0; surfaceGraphics.alpha = 0.7; surfaceGraphics.tint = 0x99ddff; // Light blue surface // Enhanced light rays for underwater god rays effect var lights = []; for (var i = 0; i < 6; i++) { var light = self.attachAsset('lightRay', { anchorX: 0.5, anchorY: 0 }); light.x = 200 + Math.random() * 1600; light.y = 0; light.alpha = 0.1 + Math.random() * 0.15; light.scale.set(0.5 + Math.random() * 0.8); light.tint = 0xffffcc; // Slight yellow tint for sunlight lights.push(light); } // Bubbles with varied sizes and speeds var bubbles = []; for (var i = 0; i < 25; i++) { spawnBubble(); } function spawnBubble() { var bubble = self.attachAsset('bubbles', { anchorX: 0.5, anchorY: 0.5 }); bubble.tint = 0xffffff; bubble.x = Math.random() * 2048; bubble.y = 500 + Math.random() * 2200; bubble.alpha = 0.3 + Math.random() * 0.5; bubble.scale.set(0.2 + Math.random() * 0.5); bubble.speed = 0.5 + Math.random() * 1.5; bubble.wobbleSpeed = 0.01 + Math.random() * 0.03; bubble.wobbleAmount = 0 + Math.random() * 30; bubble.wobbleOffset = Math.random() * Math.PI * 2; bubbles.push(bubble); } // Create small dust particles for realism var particles = []; for (var i = 0; i < 40; i++) { var particle = self.attachAsset('bubbles', { anchorX: 0.5, anchorY: 0.5 }); particle.tint = 0xcccccc; particle.x = Math.random() * 2048; particle.y = Math.random() * 2732; particle.alpha = 0.1 + Math.random() * 0.2; particle.scale.set(0.05 + Math.random() * 0.15); particle.speed = 0.1 + Math.random() * 0.3; particle.wobbleSpeed = 0.005 + Math.random() * 0.01; particle.wobbleOffset = Math.random() * Math.PI * 2; particles.push(particle); } self.update = function () { // Update bubbles for (var i = bubbles.length - 1; i >= 0; i--) { var bubble = bubbles[i]; bubble.y -= bubble.speed; bubble.x += Math.sin(LK.ticks * bubble.wobbleSpeed + bubble.wobbleOffset) * 0.3; // If bubble reaches surface, respawn it if (bubble.y < 100) { bubble.destroy(); bubbles.splice(i, 1); spawnBubble(); } } // Update dust particles for (var i = particles.length - 1; i >= 0; i--) { var particle = particles[i]; particle.y -= particle.speed; particle.x += Math.sin(LK.ticks * particle.wobbleSpeed + particle.wobbleOffset) * 0.2; // Loop particles at the bottom if (particle.y < 0) { particle.y = 2732; particle.x = Math.random() * 2048; } } // Create dynamic water movement for (var i = 0; i < 4; i++) { var layer = self.getChildAt(i); layer.y += Math.sin(LK.ticks * 0.01 + i * 0.5) * 0.2; } // Gentle animation for water surface surfaceGraphics.y = Math.sin(LK.ticks * 0.02) * 5; surfaceGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.03) * 0.1; // Animate light rays with movement and intensity changes for (var i = 0; i < lights.length; i++) { var light = lights[i]; light.alpha = 0.1 + Math.sin(LK.ticks * 0.01 + i) * 0.1; light.x += Math.sin(LK.ticks * 0.003 + i * 0.2) * 0.3; light.width = light.width + Math.sin(LK.ticks * 0.01 + i * 0.5) * 0.4; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() > 0.5 ? 'speed' : 'invincibility'; self.speed = 1; self.lastY = 0; self.update = function () { self.lastY = self.y; self.y += self.speed; // Simple animation self.rotation += 0.02; // Remove if off screen if (self.y > 2832) { self.shouldRemove = true; } }; return self; }); // Set ocean blue background var Shark = Container.expand(function () { var self = Container.call(this); var sharkGraphics = self.attachAsset('shark', { anchorX: 0.5, anchorY: 0.5 }); self.size = 1; self.speed = 5; self.health = 100; self.oxygen = 100; self.score = 0; self.lastX = 0; self.lastY = 0; self.facing = 1; // 1 = right, -1 = left self.update = function () { self.lastX = self.x; self.lastY = self.y; // Reduce oxygen when deep in the ocean (upper part of the screen is surface) if (self.y > 1000) { self.oxygen -= 0.2; if (self.oxygen <= 0) { self.health -= 0.5; } } else { // Replenish oxygen near the surface self.oxygen = Math.min(100, self.oxygen + 0.5); } // Update scale based on size self.scale.set(self.size); // Flip shark graphic based on direction if (self.facing === 1) { sharkGraphics.scale.x = Math.abs(sharkGraphics.scale.x); } else { sharkGraphics.scale.x = -Math.abs(sharkGraphics.scale.x); } }; self.grow = function (amount) { self.size += amount; self.score += Math.round(amount * 10); }; self.takeDamage = function (amount) { self.health -= amount; LK.getSound('damage').play(); LK.effects.flashObject(self, 0xff0000, 500); }; return self; }); var StartScreen = Container.expand(function () { var self = Container.call(this); // Create ocean-themed background container var bgContainer = new Container(); self.addChild(bgContainer); // Create gradient background var bgGraphics = self.attachAsset('oceanBg', { anchorX: 0, anchorY: 0 }); bgGraphics.tint = 0x0088dd; // Ocean blue // Create decorative bubbles var bubbles = []; for (var i = 0; i < 30; i++) { var bubble = self.attachAsset('bubbles', { anchorX: 0.5, anchorY: 0.5 }); bubble.tint = 0xffffff; bubble.alpha = 0.2 + Math.random() * 0.6; bubble.scale.set(0.2 + Math.random() * 0.8); bubble.x = Math.random() * 2048; bubble.y = Math.random() * 2732; bubble.speed = 0.5 + Math.random() * 2; bubble.wobbleSpeed = 0.01 + Math.random() * 0.04; bubble.wobbleOffset = Math.random() * Math.PI * 2; bubbles.push(bubble); } // Create title text with shadow var titleShadow = new Text2('Shark Adventure', { size: 120, fill: 0x000000 }); titleShadow.anchor.set(0.5, 0.5); titleShadow.x = 2048 / 2 + 6; titleShadow.y = 600 + 6; self.addChild(titleShadow); var titleText = new Text2('Shark Adventure', { size: 120, fill: 0x00ccff }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 600; self.addChild(titleText); // Create shark image var sharkImage = self.attachAsset('shark', { anchorX: 0.5, anchorY: 0.5 }); sharkImage.x = 2048 / 2; sharkImage.y = 1000; sharkImage.scale.set(2); // Create animated fish in background var decorativeFish = []; var fishTypes = ['smallFish', 'mediumFish', 'largeFish', 'goldenFish']; for (var i = 0; i < 10; i++) { var fishType = fishTypes[Math.floor(Math.random() * fishTypes.length)]; var fish = self.attachAsset(fishType, { anchorX: 0.5, anchorY: 0.5 }); fish.x = Math.random() * 2048; fish.y = 300 + Math.random() * 1800; fish.scale.set(0.6 + Math.random() * 0.8); fish.speed = 1 + Math.random() * 3; fish.direction = Math.random() > 0.5 ? 1 : -1; fish.scale.x *= fish.direction; fish.alpha = 0.7; decorativeFish.push(fish); } // Create start button with gradient effect var buttonBg = self.attachAsset('oceanBg', { anchorX: 0.5, anchorY: 0.5 }); buttonBg.width = 500; buttonBg.height = 150; buttonBg.tint = 0x0066aa; buttonBg.x = 2048 / 2; buttonBg.y = 1600; var buttonShadow = new Text2('TAP TO PLAY', { size: 80, fill: 0x000000 }); buttonShadow.anchor.set(0.5, 0.5); buttonShadow.x = 2048 / 2 + 4; buttonShadow.y = 1600 + 4; self.addChild(buttonShadow); var buttonText = new Text2('TAP TO PLAY', { size: 80, fill: 0xffffff }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 2048 / 2; buttonText.y = 1600; self.addChild(buttonText); // Display record score var recordText = new Text2('Record: ' + (storage.recordScore || 0), { size: 60, fill: 0xffdd00 }); recordText.anchor.set(0.5, 0.5); recordText.x = 2048 / 2; recordText.y = 1800; self.addChild(recordText); // Add pulse animation to button function pulseButton() { tween(buttonBg.scale, { x: 1.1, y: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(buttonBg.scale, { x: 1.0, y: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseButton }); } }); } pulseButton(); // Add floating animation to shark function floatShark() { tween(sharkImage, { y: sharkImage.y + 50 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { tween(sharkImage, { y: sharkImage.y - 50 }, { duration: 1500, easing: tween.easeInOut, onFinish: floatShark }); } }); } floatShark(); // Add title animation tween(titleText.scale, { x: 1.1, y: 1.1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText.scale, { x: 1.0, y: 1.0 }, { duration: 2000, easing: tween.easeInOut }); } }); // Handle tap anywhere to start self.down = function (x, y, obj) { self.onStartGame && self.onStartGame(); }; self.update = function () { // Update bubbles for (var i = 0; i < bubbles.length; i++) { var bubble = bubbles[i]; bubble.y -= bubble.speed; bubble.x += Math.sin(LK.ticks * bubble.wobbleSpeed + bubble.wobbleOffset) * 0.5; // Loop bubbles when they reach the top if (bubble.y < -50) { bubble.y = 2732 + 50; bubble.x = Math.random() * 2048; } } // Update fish swimming for (var i = 0; i < decorativeFish.length; i++) { var fish = decorativeFish[i]; fish.x += fish.speed * fish.direction; // Wrap fish around screen if (fish.x < -100 && fish.direction < 0) { fish.x = 2148; } else if (fish.x > 2148 && fish.direction > 0) { fish.x = -100; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Black background, ocean handled by OceanBackground class }); /**** * Game Code ****/ // Background is now handled by the OceanBackground class // Game variables var shark; var fishes = []; var obstacles = []; var powerUps = []; var lastIntersectingFish = {}; var lastIntersectingObstacle = {}; var lastIntersectingPowerUp = {}; var gameActive = false; var gameStarted = false; var powerUpActive = false; var powerUpTimer = 0; var spawnTimer = 0; var difficultyTimer = 0; var difficulty = 1; var maxFishes = 10; var dragNode = null; var oceanBackground; var startScreen; var recordScore = storage.recordScore || 0; // UI elements var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); scoreText.x = 120; scoreText.y = 20; var recordScoreText = new Text2('Record: ' + recordScore, { size: 40, fill: 0xFFDD00 }); recordScoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(recordScoreText); recordScoreText.x = 120; recordScoreText.y = 200; var healthBarBg = LK.getAsset('healthBg', { anchorX: 0, anchorY: 0.5, x: 120, y: 100 }); LK.gui.topLeft.addChild(healthBarBg); var healthBarFill = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, x: 120, y: 100 }); LK.gui.topLeft.addChild(healthBarFill); var oxygenBarBg = LK.getAsset('oxygenBg', { anchorX: 0, anchorY: 0.5, x: 120, y: 150 }); LK.gui.topLeft.addChild(oxygenBarBg); var oxygenBarFill = LK.getAsset('oxygen', { anchorX: 0, anchorY: 0.5, x: 120, y: 150 }); LK.gui.topLeft.addChild(oxygenBarFill); // Initialize shark function initGame() { if (!gameStarted) { // Show start screen first startScreen = new StartScreen(); game.addChild(startScreen); // Set callback for when start button is pressed startScreen.onStartGame = function () { // Remove start screen startScreen.destroy(); startScreen = null; // Start the actual game startGame(); }; gameStarted = true; } else { // Direct game start (for game restarts) startGame(); } } // Function to start the actual game function startGame() { // Create ocean background oceanBackground = new OceanBackground(); game.addChild(oceanBackground); // Create shark shark = new Shark(); shark.x = 2048 / 2; shark.y = 2732 / 2; game.addChild(shark); // Reset variables fishes = []; obstacles = []; powerUps = []; lastIntersectingFish = {}; lastIntersectingObstacle = {}; lastIntersectingPowerUp = {}; gameActive = true; powerUpActive = false; powerUpTimer = 0; spawnTimer = 0; difficultyTimer = 0; difficulty = 1; LK.setScore(0); // Get record score from storage recordScore = storage.recordScore || 0; recordScoreText.setText('Record: ' + recordScore); // Spawn initial fish for (var i = 0; i < 5; i++) { spawnFish(); } } // Spawn a new fish function spawnFish() { var fishType; var rand = Math.random(); if (rand < 0.05) { fishType = 'goldenFish'; } else if (rand < 0.2) { fishType = 'largeFish'; } else if (rand < 0.5) { fishType = 'mediumFish'; } else { fishType = 'smallFish'; } var speed = 1 + Math.random() * 2 * difficulty; var fish = new Fish(fishType, speed); // Position fish at random height, but from the side fish.y = 200 + Math.random() * 2300; if (Math.random() > 0.5) { fish.x = -50; fish.direction = 1; } else { fish.x = 2098; fish.direction = -1; } fishes.push(fish); game.addChild(fish); } // Spawn an obstacle function spawnObstacle() { var obstacle = new Obstacle(1 + Math.random() * difficulty); obstacle.x = 100 + Math.random() * 1848; obstacle.y = -100; obstacles.push(obstacle); game.addChild(obstacle); } // Spawn a power-up function spawnPowerUp() { var powerUp = new PowerUp(); powerUp.x = 100 + Math.random() * 1848; powerUp.y = -100; powerUps.push(powerUp); game.addChild(powerUp); } // Handle shark collision with fish function handleFishCollision(fish, index) { // Check if shark can eat this fish if (shark.size >= fish.danger) { // Shark eats fish shark.grow(fish.value * 0.05); // Reduce width by 10 and height by 5 when eating golden fish if (fish.type === 'goldenFish') { var sharkGraphics = shark.getChildAt(0); sharkGraphics.width -= 10; sharkGraphics.height -= 5; } LK.setScore(shark.score); scoreText.setText("Score: " + shark.score); // Check if new record achieved if (shark.score > recordScore) { recordScore = shark.score; storage.recordScore = recordScore; recordScoreText.setText('Record: ' + recordScore); // Flash record text to highlight new record LK.effects.flashObject(recordScoreText, 0xFFFF00, 500); } LK.getSound('eat').play(); // Remove fish fish.destroy(); fishes.splice(index, 1); } else { // Fish damages shark shark.takeDamage(5 * fish.danger); } } // Game events game.move = function (x, y, obj) { if (!gameActive || !dragNode) return; // Move shark to touch position dragNode.x = x; dragNode.y = y; // Update shark direction based on movement if (dragNode.x > dragNode.lastX) { dragNode.facing = 1; } else if (dragNode.x < dragNode.lastX) { dragNode.facing = -1; } }; game.down = function (x, y, obj) { if (!gameActive) return; dragNode = shark; game.move(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; }; // Main game update game.update = function () { // If start screen is active, update it if (startScreen) { startScreen.update(); return; } if (!gameActive) return; // Increase difficulty over time difficultyTimer++; if (difficultyTimer >= 600) { // Every 10 seconds difficulty += 0.1; maxFishes = Math.min(20, maxFishes + 1); difficultyTimer = 0; } // Update ocean background if (oceanBackground) { oceanBackground.update(); } // Update shark shark.update(); // Update UI healthBarFill.width = shark.health / 100 * 200; oxygenBarFill.width = shark.oxygen / 100 * 200; // Check if game over if (shark.health <= 0) { gameActive = false; // Check if we need to update the record if (shark.score > recordScore) { recordScore = shark.score; storage.recordScore = recordScore; recordScoreText.setText('Record: ' + recordScore); } LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Spawn new entities spawnTimer++; if (spawnTimer >= 60) { // Every second if (fishes.length < maxFishes) { spawnFish(); } if (Math.random() < 0.2 * difficulty) { spawnObstacle(); } if (Math.random() < 0.05) { spawnPowerUp(); } spawnTimer = 0; } // Handle power-up timer if (powerUpActive) { powerUpTimer--; if (powerUpTimer <= 0) { powerUpActive = false; shark.speed = 5; } } // Update fishes and check collisions for (var i = fishes.length - 1; i >= 0; i--) { var fish = fishes[i]; fish.update(); var id = "fish" + i; var isIntersecting = shark.intersects(fish); // Check collision (transition from not intersecting to intersecting) if (!lastIntersectingFish[id] && isIntersecting) { handleFishCollision(fish, i); continue; // Skip further processing if fish was eaten } lastIntersectingFish[id] = isIntersecting; } // Update obstacles and check collisions for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; obstacle.update(); if (obstacle.shouldRemove) { obstacle.destroy(); obstacles.splice(i, 1); continue; } var id = "obstacle" + i; var isIntersecting = shark.intersects(obstacle); // Check collision (transition from not intersecting to intersecting) if (!lastIntersectingObstacle[id] && isIntersecting) { if (!powerUpActive || powerUpActive && shark.type !== 'invincibility') { shark.takeDamage(obstacle.damage); } } lastIntersectingObstacle[id] = isIntersecting; } // Update power-ups and check collisions for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; powerUp.update(); if (powerUp.shouldRemove) { powerUp.destroy(); powerUps.splice(i, 1); continue; } var id = "powerUp" + i; var isIntersecting = shark.intersects(powerUp); // Check collision (transition from not intersecting to intersecting) if (!lastIntersectingPowerUp[id] && isIntersecting) { // Apply power-up effect powerUpActive = true; powerUpTimer = 300; // 5 seconds if (powerUp.type === 'speed') { shark.speed = 10; } // Increase health by 15 when collecting any power-up shark.health = Math.min(100, shark.health + 15); LK.getSound('powerup').play(); LK.effects.flashObject(shark, 0x00ffff, 500); // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); } lastIntersectingPowerUp[id] = isIntersecting; } }; // Initialize the game initGame();
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
recordScore: 0
});
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fish = Container.expand(function (type, speed) {
var self = Container.call(this);
self.type = type || 'smallFish';
self.speed = speed || 2;
self.value = 1;
self.lastY = 0;
if (self.type === 'smallFish') {
self.value = 1;
self.danger = 0;
} else if (self.type === 'mediumFish') {
self.value = 2;
self.danger = 0.5;
} else if (self.type === 'largeFish') {
self.value = 4;
self.danger = 1;
} else if (self.type === 'goldenFish') {
self.value = 10;
self.danger = 0;
}
var fishGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = Math.random() > 0.5 ? 1 : -1;
fishGraphics.scale.x = self.direction;
self.update = function () {
self.lastY = self.y;
self.x += self.speed * self.direction;
// Wrap around screen
if (self.x < -100 && self.direction < 0) {
self.x = 2148;
} else if (self.x > 2148 && self.direction > 0) {
self.x = -100;
}
};
return self;
});
var Obstacle = Container.expand(function (speed) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = speed || 1;
self.damage = 10;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
// Remove if off screen
if (self.y > 2832) {
self.shouldRemove = true;
}
};
return self;
});
var OceanBackground = Container.expand(function () {
var self = Container.call(this);
// Main ocean background - blue gradient ocean
var bgGraphics = self.attachAsset('oceanBg', {
anchorX: 0,
anchorY: 0
});
bgGraphics.tint = 0x0066cc; // Deep blue ocean color
// Create gradient effect with multiple layers
var deepLayer = self.attachAsset('oceanBg', {
anchorX: 0,
anchorY: 0
});
deepLayer.tint = 0x003366; // Darker blue for depth
deepLayer.alpha = 0.4;
deepLayer.y = 1500;
var midLayer = self.attachAsset('oceanBg', {
anchorX: 0,
anchorY: 0
});
midLayer.tint = 0x0088dd; // Mid blue
midLayer.alpha = 0.3;
midLayer.y = 800;
var topLayer = self.attachAsset('oceanBg', {
anchorX: 0,
anchorY: 0
});
topLayer.tint = 0x66ccff; // Light blue for surface
topLayer.alpha = 0.2;
topLayer.y = 0;
// Ocean floor with sandy texture
var floorGraphics = self.attachAsset('oceanFloor', {
anchorX: 0,
anchorY: 1
});
floorGraphics.y = 2732;
floorGraphics.tint = 0xd2b48c; // Sandy color
// Water surface with transparency and shimmer
var surfaceGraphics = self.attachAsset('waterSurface', {
anchorX: 0,
anchorY: 0
});
surfaceGraphics.y = 0;
surfaceGraphics.alpha = 0.7;
surfaceGraphics.tint = 0x99ddff; // Light blue surface
// Enhanced light rays for underwater god rays effect
var lights = [];
for (var i = 0; i < 6; i++) {
var light = self.attachAsset('lightRay', {
anchorX: 0.5,
anchorY: 0
});
light.x = 200 + Math.random() * 1600;
light.y = 0;
light.alpha = 0.1 + Math.random() * 0.15;
light.scale.set(0.5 + Math.random() * 0.8);
light.tint = 0xffffcc; // Slight yellow tint for sunlight
lights.push(light);
}
// Bubbles with varied sizes and speeds
var bubbles = [];
for (var i = 0; i < 25; i++) {
spawnBubble();
}
function spawnBubble() {
var bubble = self.attachAsset('bubbles', {
anchorX: 0.5,
anchorY: 0.5
});
bubble.tint = 0xffffff;
bubble.x = Math.random() * 2048;
bubble.y = 500 + Math.random() * 2200;
bubble.alpha = 0.3 + Math.random() * 0.5;
bubble.scale.set(0.2 + Math.random() * 0.5);
bubble.speed = 0.5 + Math.random() * 1.5;
bubble.wobbleSpeed = 0.01 + Math.random() * 0.03;
bubble.wobbleAmount = 0 + Math.random() * 30;
bubble.wobbleOffset = Math.random() * Math.PI * 2;
bubbles.push(bubble);
}
// Create small dust particles for realism
var particles = [];
for (var i = 0; i < 40; i++) {
var particle = self.attachAsset('bubbles', {
anchorX: 0.5,
anchorY: 0.5
});
particle.tint = 0xcccccc;
particle.x = Math.random() * 2048;
particle.y = Math.random() * 2732;
particle.alpha = 0.1 + Math.random() * 0.2;
particle.scale.set(0.05 + Math.random() * 0.15);
particle.speed = 0.1 + Math.random() * 0.3;
particle.wobbleSpeed = 0.005 + Math.random() * 0.01;
particle.wobbleOffset = Math.random() * Math.PI * 2;
particles.push(particle);
}
self.update = function () {
// Update bubbles
for (var i = bubbles.length - 1; i >= 0; i--) {
var bubble = bubbles[i];
bubble.y -= bubble.speed;
bubble.x += Math.sin(LK.ticks * bubble.wobbleSpeed + bubble.wobbleOffset) * 0.3;
// If bubble reaches surface, respawn it
if (bubble.y < 100) {
bubble.destroy();
bubbles.splice(i, 1);
spawnBubble();
}
}
// Update dust particles
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
particle.y -= particle.speed;
particle.x += Math.sin(LK.ticks * particle.wobbleSpeed + particle.wobbleOffset) * 0.2;
// Loop particles at the bottom
if (particle.y < 0) {
particle.y = 2732;
particle.x = Math.random() * 2048;
}
}
// Create dynamic water movement
for (var i = 0; i < 4; i++) {
var layer = self.getChildAt(i);
layer.y += Math.sin(LK.ticks * 0.01 + i * 0.5) * 0.2;
}
// Gentle animation for water surface
surfaceGraphics.y = Math.sin(LK.ticks * 0.02) * 5;
surfaceGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.03) * 0.1;
// Animate light rays with movement and intensity changes
for (var i = 0; i < lights.length; i++) {
var light = lights[i];
light.alpha = 0.1 + Math.sin(LK.ticks * 0.01 + i) * 0.1;
light.x += Math.sin(LK.ticks * 0.003 + i * 0.2) * 0.3;
light.width = light.width + Math.sin(LK.ticks * 0.01 + i * 0.5) * 0.4;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() > 0.5 ? 'speed' : 'invincibility';
self.speed = 1;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
// Simple animation
self.rotation += 0.02;
// Remove if off screen
if (self.y > 2832) {
self.shouldRemove = true;
}
};
return self;
});
// Set ocean blue background
var Shark = Container.expand(function () {
var self = Container.call(this);
var sharkGraphics = self.attachAsset('shark', {
anchorX: 0.5,
anchorY: 0.5
});
self.size = 1;
self.speed = 5;
self.health = 100;
self.oxygen = 100;
self.score = 0;
self.lastX = 0;
self.lastY = 0;
self.facing = 1; // 1 = right, -1 = left
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Reduce oxygen when deep in the ocean (upper part of the screen is surface)
if (self.y > 1000) {
self.oxygen -= 0.2;
if (self.oxygen <= 0) {
self.health -= 0.5;
}
} else {
// Replenish oxygen near the surface
self.oxygen = Math.min(100, self.oxygen + 0.5);
}
// Update scale based on size
self.scale.set(self.size);
// Flip shark graphic based on direction
if (self.facing === 1) {
sharkGraphics.scale.x = Math.abs(sharkGraphics.scale.x);
} else {
sharkGraphics.scale.x = -Math.abs(sharkGraphics.scale.x);
}
};
self.grow = function (amount) {
self.size += amount;
self.score += Math.round(amount * 10);
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xff0000, 500);
};
return self;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Create ocean-themed background container
var bgContainer = new Container();
self.addChild(bgContainer);
// Create gradient background
var bgGraphics = self.attachAsset('oceanBg', {
anchorX: 0,
anchorY: 0
});
bgGraphics.tint = 0x0088dd; // Ocean blue
// Create decorative bubbles
var bubbles = [];
for (var i = 0; i < 30; i++) {
var bubble = self.attachAsset('bubbles', {
anchorX: 0.5,
anchorY: 0.5
});
bubble.tint = 0xffffff;
bubble.alpha = 0.2 + Math.random() * 0.6;
bubble.scale.set(0.2 + Math.random() * 0.8);
bubble.x = Math.random() * 2048;
bubble.y = Math.random() * 2732;
bubble.speed = 0.5 + Math.random() * 2;
bubble.wobbleSpeed = 0.01 + Math.random() * 0.04;
bubble.wobbleOffset = Math.random() * Math.PI * 2;
bubbles.push(bubble);
}
// Create title text with shadow
var titleShadow = new Text2('Shark Adventure', {
size: 120,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 2048 / 2 + 6;
titleShadow.y = 600 + 6;
self.addChild(titleShadow);
var titleText = new Text2('Shark Adventure', {
size: 120,
fill: 0x00ccff
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 600;
self.addChild(titleText);
// Create shark image
var sharkImage = self.attachAsset('shark', {
anchorX: 0.5,
anchorY: 0.5
});
sharkImage.x = 2048 / 2;
sharkImage.y = 1000;
sharkImage.scale.set(2);
// Create animated fish in background
var decorativeFish = [];
var fishTypes = ['smallFish', 'mediumFish', 'largeFish', 'goldenFish'];
for (var i = 0; i < 10; i++) {
var fishType = fishTypes[Math.floor(Math.random() * fishTypes.length)];
var fish = self.attachAsset(fishType, {
anchorX: 0.5,
anchorY: 0.5
});
fish.x = Math.random() * 2048;
fish.y = 300 + Math.random() * 1800;
fish.scale.set(0.6 + Math.random() * 0.8);
fish.speed = 1 + Math.random() * 3;
fish.direction = Math.random() > 0.5 ? 1 : -1;
fish.scale.x *= fish.direction;
fish.alpha = 0.7;
decorativeFish.push(fish);
}
// Create start button with gradient effect
var buttonBg = self.attachAsset('oceanBg', {
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.width = 500;
buttonBg.height = 150;
buttonBg.tint = 0x0066aa;
buttonBg.x = 2048 / 2;
buttonBg.y = 1600;
var buttonShadow = new Text2('TAP TO PLAY', {
size: 80,
fill: 0x000000
});
buttonShadow.anchor.set(0.5, 0.5);
buttonShadow.x = 2048 / 2 + 4;
buttonShadow.y = 1600 + 4;
self.addChild(buttonShadow);
var buttonText = new Text2('TAP TO PLAY', {
size: 80,
fill: 0xffffff
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 2048 / 2;
buttonText.y = 1600;
self.addChild(buttonText);
// Display record score
var recordText = new Text2('Record: ' + (storage.recordScore || 0), {
size: 60,
fill: 0xffdd00
});
recordText.anchor.set(0.5, 0.5);
recordText.x = 2048 / 2;
recordText.y = 1800;
self.addChild(recordText);
// Add pulse animation to button
function pulseButton() {
tween(buttonBg.scale, {
x: 1.1,
y: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(buttonBg.scale, {
x: 1.0,
y: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseButton
});
}
});
}
pulseButton();
// Add floating animation to shark
function floatShark() {
tween(sharkImage, {
y: sharkImage.y + 50
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(sharkImage, {
y: sharkImage.y - 50
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: floatShark
});
}
});
}
floatShark();
// Add title animation
tween(titleText.scale, {
x: 1.1,
y: 1.1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText.scale, {
x: 1.0,
y: 1.0
}, {
duration: 2000,
easing: tween.easeInOut
});
}
});
// Handle tap anywhere to start
self.down = function (x, y, obj) {
self.onStartGame && self.onStartGame();
};
self.update = function () {
// Update bubbles
for (var i = 0; i < bubbles.length; i++) {
var bubble = bubbles[i];
bubble.y -= bubble.speed;
bubble.x += Math.sin(LK.ticks * bubble.wobbleSpeed + bubble.wobbleOffset) * 0.5;
// Loop bubbles when they reach the top
if (bubble.y < -50) {
bubble.y = 2732 + 50;
bubble.x = Math.random() * 2048;
}
}
// Update fish swimming
for (var i = 0; i < decorativeFish.length; i++) {
var fish = decorativeFish[i];
fish.x += fish.speed * fish.direction;
// Wrap fish around screen
if (fish.x < -100 && fish.direction < 0) {
fish.x = 2148;
} else if (fish.x > 2148 && fish.direction > 0) {
fish.x = -100;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Black background, ocean handled by OceanBackground class
});
/****
* Game Code
****/
// Background is now handled by the OceanBackground class
// Game variables
var shark;
var fishes = [];
var obstacles = [];
var powerUps = [];
var lastIntersectingFish = {};
var lastIntersectingObstacle = {};
var lastIntersectingPowerUp = {};
var gameActive = false;
var gameStarted = false;
var powerUpActive = false;
var powerUpTimer = 0;
var spawnTimer = 0;
var difficultyTimer = 0;
var difficulty = 1;
var maxFishes = 10;
var dragNode = null;
var oceanBackground;
var startScreen;
var recordScore = storage.recordScore || 0;
// UI elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
scoreText.x = 120;
scoreText.y = 20;
var recordScoreText = new Text2('Record: ' + recordScore, {
size: 40,
fill: 0xFFDD00
});
recordScoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(recordScoreText);
recordScoreText.x = 120;
recordScoreText.y = 200;
var healthBarBg = LK.getAsset('healthBg', {
anchorX: 0,
anchorY: 0.5,
x: 120,
y: 100
});
LK.gui.topLeft.addChild(healthBarBg);
var healthBarFill = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 120,
y: 100
});
LK.gui.topLeft.addChild(healthBarFill);
var oxygenBarBg = LK.getAsset('oxygenBg', {
anchorX: 0,
anchorY: 0.5,
x: 120,
y: 150
});
LK.gui.topLeft.addChild(oxygenBarBg);
var oxygenBarFill = LK.getAsset('oxygen', {
anchorX: 0,
anchorY: 0.5,
x: 120,
y: 150
});
LK.gui.topLeft.addChild(oxygenBarFill);
// Initialize shark
function initGame() {
if (!gameStarted) {
// Show start screen first
startScreen = new StartScreen();
game.addChild(startScreen);
// Set callback for when start button is pressed
startScreen.onStartGame = function () {
// Remove start screen
startScreen.destroy();
startScreen = null;
// Start the actual game
startGame();
};
gameStarted = true;
} else {
// Direct game start (for game restarts)
startGame();
}
}
// Function to start the actual game
function startGame() {
// Create ocean background
oceanBackground = new OceanBackground();
game.addChild(oceanBackground);
// Create shark
shark = new Shark();
shark.x = 2048 / 2;
shark.y = 2732 / 2;
game.addChild(shark);
// Reset variables
fishes = [];
obstacles = [];
powerUps = [];
lastIntersectingFish = {};
lastIntersectingObstacle = {};
lastIntersectingPowerUp = {};
gameActive = true;
powerUpActive = false;
powerUpTimer = 0;
spawnTimer = 0;
difficultyTimer = 0;
difficulty = 1;
LK.setScore(0);
// Get record score from storage
recordScore = storage.recordScore || 0;
recordScoreText.setText('Record: ' + recordScore);
// Spawn initial fish
for (var i = 0; i < 5; i++) {
spawnFish();
}
}
// Spawn a new fish
function spawnFish() {
var fishType;
var rand = Math.random();
if (rand < 0.05) {
fishType = 'goldenFish';
} else if (rand < 0.2) {
fishType = 'largeFish';
} else if (rand < 0.5) {
fishType = 'mediumFish';
} else {
fishType = 'smallFish';
}
var speed = 1 + Math.random() * 2 * difficulty;
var fish = new Fish(fishType, speed);
// Position fish at random height, but from the side
fish.y = 200 + Math.random() * 2300;
if (Math.random() > 0.5) {
fish.x = -50;
fish.direction = 1;
} else {
fish.x = 2098;
fish.direction = -1;
}
fishes.push(fish);
game.addChild(fish);
}
// Spawn an obstacle
function spawnObstacle() {
var obstacle = new Obstacle(1 + Math.random() * difficulty);
obstacle.x = 100 + Math.random() * 1848;
obstacle.y = -100;
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn a power-up
function spawnPowerUp() {
var powerUp = new PowerUp();
powerUp.x = 100 + Math.random() * 1848;
powerUp.y = -100;
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Handle shark collision with fish
function handleFishCollision(fish, index) {
// Check if shark can eat this fish
if (shark.size >= fish.danger) {
// Shark eats fish
shark.grow(fish.value * 0.05);
// Reduce width by 10 and height by 5 when eating golden fish
if (fish.type === 'goldenFish') {
var sharkGraphics = shark.getChildAt(0);
sharkGraphics.width -= 10;
sharkGraphics.height -= 5;
}
LK.setScore(shark.score);
scoreText.setText("Score: " + shark.score);
// Check if new record achieved
if (shark.score > recordScore) {
recordScore = shark.score;
storage.recordScore = recordScore;
recordScoreText.setText('Record: ' + recordScore);
// Flash record text to highlight new record
LK.effects.flashObject(recordScoreText, 0xFFFF00, 500);
}
LK.getSound('eat').play();
// Remove fish
fish.destroy();
fishes.splice(index, 1);
} else {
// Fish damages shark
shark.takeDamage(5 * fish.danger);
}
}
// Game events
game.move = function (x, y, obj) {
if (!gameActive || !dragNode) return;
// Move shark to touch position
dragNode.x = x;
dragNode.y = y;
// Update shark direction based on movement
if (dragNode.x > dragNode.lastX) {
dragNode.facing = 1;
} else if (dragNode.x < dragNode.lastX) {
dragNode.facing = -1;
}
};
game.down = function (x, y, obj) {
if (!gameActive) return;
dragNode = shark;
game.move(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update
game.update = function () {
// If start screen is active, update it
if (startScreen) {
startScreen.update();
return;
}
if (!gameActive) return;
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= 600) {
// Every 10 seconds
difficulty += 0.1;
maxFishes = Math.min(20, maxFishes + 1);
difficultyTimer = 0;
}
// Update ocean background
if (oceanBackground) {
oceanBackground.update();
}
// Update shark
shark.update();
// Update UI
healthBarFill.width = shark.health / 100 * 200;
oxygenBarFill.width = shark.oxygen / 100 * 200;
// Check if game over
if (shark.health <= 0) {
gameActive = false;
// Check if we need to update the record
if (shark.score > recordScore) {
recordScore = shark.score;
storage.recordScore = recordScore;
recordScoreText.setText('Record: ' + recordScore);
}
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Spawn new entities
spawnTimer++;
if (spawnTimer >= 60) {
// Every second
if (fishes.length < maxFishes) {
spawnFish();
}
if (Math.random() < 0.2 * difficulty) {
spawnObstacle();
}
if (Math.random() < 0.05) {
spawnPowerUp();
}
spawnTimer = 0;
}
// Handle power-up timer
if (powerUpActive) {
powerUpTimer--;
if (powerUpTimer <= 0) {
powerUpActive = false;
shark.speed = 5;
}
}
// Update fishes and check collisions
for (var i = fishes.length - 1; i >= 0; i--) {
var fish = fishes[i];
fish.update();
var id = "fish" + i;
var isIntersecting = shark.intersects(fish);
// Check collision (transition from not intersecting to intersecting)
if (!lastIntersectingFish[id] && isIntersecting) {
handleFishCollision(fish, i);
continue; // Skip further processing if fish was eaten
}
lastIntersectingFish[id] = isIntersecting;
}
// Update obstacles and check collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update();
if (obstacle.shouldRemove) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
var id = "obstacle" + i;
var isIntersecting = shark.intersects(obstacle);
// Check collision (transition from not intersecting to intersecting)
if (!lastIntersectingObstacle[id] && isIntersecting) {
if (!powerUpActive || powerUpActive && shark.type !== 'invincibility') {
shark.takeDamage(obstacle.damage);
}
}
lastIntersectingObstacle[id] = isIntersecting;
}
// Update power-ups and check collisions
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
if (powerUp.shouldRemove) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
var id = "powerUp" + i;
var isIntersecting = shark.intersects(powerUp);
// Check collision (transition from not intersecting to intersecting)
if (!lastIntersectingPowerUp[id] && isIntersecting) {
// Apply power-up effect
powerUpActive = true;
powerUpTimer = 300; // 5 seconds
if (powerUp.type === 'speed') {
shark.speed = 10;
}
// Increase health by 15 when collecting any power-up
shark.health = Math.min(100, shark.health + 15);
LK.getSound('powerup').play();
LK.effects.flashObject(shark, 0x00ffff, 500);
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
}
lastIntersectingPowerUp[id] = isIntersecting;
}
};
// Initialize the game
initGame();
realistic pixel shark. In-Game asset. 2d. High contrast. No shadows
realistic pixel gold fish. In-Game asset. 2d. High contrast. No shadows
realistic pixel sea turtle. In-Game asset. 2d. High contrast. No shadows
realistic pixel horizontal jellyfish. In-Game asset. 2d. High contrast. No shadows
Realistic pixel horizontal dolphin. In-Game asset. 2d. High contrast. No shadows
realistic vertical meteor. In-Game asset. 2d. High contrast. No shadows
realistic pixel diver. In-Game asset. 2d. High contrast. No shadows