/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fish = Container.expand(function (fishType, depth) {
var self = Container.call(this);
var fishGraphics = self.attachAsset(fishType, {
anchorX: 0.5,
anchorY: 0.5
});
self.fishType = fishType;
self.depth = depth;
self.speed = 2;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.value = fishType === 'smallFish' ? 10 : fishType === 'mediumFish' ? 25 : fishType === 'largeFish' ? 50 : 100;
self.caught = false;
self.isBigFish = fishType === 'bigFish';
self.lastEatingTime = 0;
// Set fish speed based on type with random variation
if (fishType === 'smallFish') {
self.speed = 4 + Math.random() * 2; // 4 to 6
} else if (fishType === 'mediumFish') {
self.speed = 3 + Math.random() * 1.5; // 3 to 4.5
} else if (fishType === 'largeFish') {
self.speed = 2 + Math.random() * 1.2; // 2 to 3.2
} else {
self.speed = 1.5 + Math.random() * 1; // 1.5 to 2.5 for big fish
}
self.down = function (x, y, obj) {
if (!self.caught) {
self.caught = true;
// Score points
LK.setScore(LK.getScore() + self.value);
scoreTxt.setText(LK.getScore());
// Remove fish from array and destroy
for (var i = fish.length - 1; i >= 0; i--) {
if (fish[i] === self) {
fish.splice(i, 1);
break;
}
}
self.destroy();
LK.getSound('catch').play();
}
};
self.update = function () {
if (!self.caught) {
// Occasionally change speed for more dynamic movement
if (Math.random() < 0.002) {
// 0.2% chance per frame
var newSpeed;
if (self.fishType === 'smallFish') {
newSpeed = 4 + Math.random() * 2;
} else if (self.fishType === 'mediumFish') {
newSpeed = 3 + Math.random() * 1.5;
} else if (self.fishType === 'largeFish') {
newSpeed = 2 + Math.random() * 1.2;
} else {
newSpeed = 1.5 + Math.random() * 1;
}
tween(self, {
speed: newSpeed
}, {
duration: 1000,
easing: tween.easeInOut
});
}
self.x += self.speed * self.direction;
// Reverse direction if fish goes off screen
if (self.x < -100 || self.x > 2148) {
self.direction *= -1;
}
// Big fish eating behavior
if (self.isBigFish && LK.ticks - self.lastEatingTime > 60) {
for (var i = fish.length - 1; i >= 0; i--) {
var otherFish = fish[i];
if (otherFish !== self && !otherFish.caught && !otherFish.isBigFish) {
var distance = Math.sqrt(Math.pow(self.x - otherFish.x, 2) + Math.pow(self.y - otherFish.y, 2));
if (distance < 80) {
// Eat the fish
otherFish.destroy();
fish.splice(i, 1);
self.lastEatingTime = LK.ticks;
break;
}
}
}
}
}
};
return self;
});
var Octopus = Container.expand(function () {
var self = Container.call(this);
var octopusGraphics = self.attachAsset('octopus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2; // 3 to 5 speed
self.value = 75; // Reduced from 200 to 75
self.caught = false;
self.direction = Math.random() > 0.5 ? 1 : -1; // 1 for down, -1 for up
self.down = function (x, y, obj) {
if (!self.caught) {
self.caught = true;
// Score points
LK.setScore(LK.getScore() + self.value);
scoreTxt.setText(LK.getScore());
// Remove octopus from array and destroy
for (var i = octopi.length - 1; i >= 0; i--) {
if (octopi[i] === self) {
octopi.splice(i, 1);
break;
}
}
self.destroy();
LK.getSound('catch').play();
}
};
self.update = function () {
if (!self.caught) {
// Occasionally change speed for more dynamic movement
if (Math.random() < 0.002) {
var newSpeed = 3 + Math.random() * 2;
tween(self, {
speed: newSpeed
}, {
duration: 1000,
easing: tween.easeInOut
});
}
self.y += self.speed * self.direction;
// Reverse direction if octopus hits water boundaries - keep within water
if (self.y < waterSurface + 50 || self.y > waterSurface + 1700) {
self.direction *= -1;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var fish = [];
var octopi = [];
var waterSurface = 500;
var fishSpawnTimer = 0;
var octopusSpawnTimer = 0;
var lives = 3;
// Create water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 0,
x: 0,
y: waterSurface
}));
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
// Create lives display
var livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(livesTxt);
livesTxt.x = -20;
livesTxt.y = 50;
// Initialize score
scoreTxt.setText(LK.getScore());
// Spawn fish function
function spawnFish() {
var fishTypes = ['smallFish', 'mediumFish', 'largeFish'];
var depths = [200, 400, 600]; // Shallow, medium, deep
var typeIndex = Math.floor(Math.random() * fishTypes.length);
var fishType = fishTypes[typeIndex];
var depth = depths[typeIndex] + Math.random() * 200;
var newFish = new Fish(fishType, depth);
newFish.x = Math.random() > 0.5 ? -50 : 2098;
newFish.y = waterSurface + depth;
newFish.spawnTime = LK.ticks; // Track when fish was spawned
fish.push(newFish);
game.addChild(newFish);
}
// Spawn octopus function
function spawnOctopus() {
var newOctopus = new Octopus();
newOctopus.x = Math.random() * 1848 + 100; // Random X position within game bounds
newOctopus.y = Math.random() > 0.5 ? waterSurface + 100 : waterSurface + 1200; // Start from within water area
newOctopus.spawnTime = LK.ticks; // Track when octopus was spawned
octopi.push(newOctopus);
game.addChild(newOctopus);
}
// Game variables for random spawning
var nextFishSpawnTime = 120 + Math.random() * 120; // Random interval between 2-4 seconds
// Function to calculate spawn interval based on score
function calculateFishSpawnInterval() {
var currentScore = LK.getScore();
var baseInterval = 120; // 2 seconds base
var randomVariation = 60; // 1 second variation
// Reduce spawn time as score increases
var speedMultiplier = Math.max(0.3, 1 - currentScore / 1000); // Gets faster, minimum 0.3x speed
return (baseInterval + Math.random() * randomVariation) * speedMultiplier;
}
// Main game loop
game.update = function () {
// Spawn fish randomly
fishSpawnTimer++;
if (fishSpawnTimer >= nextFishSpawnTime) {
spawnFish();
fishSpawnTimer = 0;
// Set next dynamic spawn time based on score
nextFishSpawnTime = calculateFishSpawnInterval();
}
// Clean up fish that are off screen and check for missed fish
for (var i = fish.length - 1; i >= 0; i--) {
var currentFish = fish[i];
var timeSinceSpawn = LK.ticks - currentFish.spawnTime;
var fiveSecondsInTicks = 300; // 5 seconds * 60 ticks per second
// Check if 5 seconds have passed and fish not caught (except big fish after 500 points)
var shouldTimeout = timeSinceSpawn >= fiveSecondsInTicks && !currentFish.caught;
if (shouldTimeout && !(currentFish.isBigFish && LK.getScore() >= 500)) {
// Fish timeout - lose a life
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
currentFish.destroy();
fish.splice(i, 1);
continue;
}
if (currentFish.x < -200 || currentFish.x > 2248) {
// If fish was not caught and went off screen, lose a life
if (!currentFish.caught) {
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
}
currentFish.destroy();
fish.splice(i, 1);
}
}
// Spawn big fish after 500 points with random intervals
var currentScore = LK.getScore();
if (currentScore >= 500 && Math.random() < 0.001) {
// 0.1% chance per frame (10 times less frequent)
var bigFish = new Fish('bigFish', 300 + Math.random() * 400);
bigFish.x = Math.random() > 0.5 ? -100 : 2148;
bigFish.y = waterSurface + bigFish.depth;
fish.push(bigFish);
game.addChild(bigFish);
}
// Spawn octopi after 250 points with more space between them
if (currentScore >= 250) {
octopusSpawnTimer++;
if (octopusSpawnTimer >= 360) {
// Every 6 seconds (360 ticks) - even more space between octopi
spawnOctopus();
octopusSpawnTimer = 0;
}
}
// Clean up octopi that are off screen and check for timeouts
for (var j = octopi.length - 1; j >= 0; j--) {
var currentOctopus = octopi[j];
var timeSinceSpawn = LK.ticks - currentOctopus.spawnTime;
var fiveSecondsInTicks = 300; // 5 seconds * 60 ticks per second
// Check if 5 seconds have passed and octopus not caught
if (timeSinceSpawn >= fiveSecondsInTicks && !currentOctopus.caught) {
// Octopus timeout - lose a life
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
currentOctopus.destroy();
octopi.splice(j, 1);
continue;
}
if (currentOctopus.y < waterSurface - 100 || currentOctopus.y > waterSurface + 1800) {
// If octopus was not caught and went outside water bounds, lose a life
if (!currentOctopus.caught) {
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
}
currentOctopus.destroy();
octopi.splice(j, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fish = Container.expand(function (fishType, depth) {
var self = Container.call(this);
var fishGraphics = self.attachAsset(fishType, {
anchorX: 0.5,
anchorY: 0.5
});
self.fishType = fishType;
self.depth = depth;
self.speed = 2;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.value = fishType === 'smallFish' ? 10 : fishType === 'mediumFish' ? 25 : fishType === 'largeFish' ? 50 : 100;
self.caught = false;
self.isBigFish = fishType === 'bigFish';
self.lastEatingTime = 0;
// Set fish speed based on type with random variation
if (fishType === 'smallFish') {
self.speed = 4 + Math.random() * 2; // 4 to 6
} else if (fishType === 'mediumFish') {
self.speed = 3 + Math.random() * 1.5; // 3 to 4.5
} else if (fishType === 'largeFish') {
self.speed = 2 + Math.random() * 1.2; // 2 to 3.2
} else {
self.speed = 1.5 + Math.random() * 1; // 1.5 to 2.5 for big fish
}
self.down = function (x, y, obj) {
if (!self.caught) {
self.caught = true;
// Score points
LK.setScore(LK.getScore() + self.value);
scoreTxt.setText(LK.getScore());
// Remove fish from array and destroy
for (var i = fish.length - 1; i >= 0; i--) {
if (fish[i] === self) {
fish.splice(i, 1);
break;
}
}
self.destroy();
LK.getSound('catch').play();
}
};
self.update = function () {
if (!self.caught) {
// Occasionally change speed for more dynamic movement
if (Math.random() < 0.002) {
// 0.2% chance per frame
var newSpeed;
if (self.fishType === 'smallFish') {
newSpeed = 4 + Math.random() * 2;
} else if (self.fishType === 'mediumFish') {
newSpeed = 3 + Math.random() * 1.5;
} else if (self.fishType === 'largeFish') {
newSpeed = 2 + Math.random() * 1.2;
} else {
newSpeed = 1.5 + Math.random() * 1;
}
tween(self, {
speed: newSpeed
}, {
duration: 1000,
easing: tween.easeInOut
});
}
self.x += self.speed * self.direction;
// Reverse direction if fish goes off screen
if (self.x < -100 || self.x > 2148) {
self.direction *= -1;
}
// Big fish eating behavior
if (self.isBigFish && LK.ticks - self.lastEatingTime > 60) {
for (var i = fish.length - 1; i >= 0; i--) {
var otherFish = fish[i];
if (otherFish !== self && !otherFish.caught && !otherFish.isBigFish) {
var distance = Math.sqrt(Math.pow(self.x - otherFish.x, 2) + Math.pow(self.y - otherFish.y, 2));
if (distance < 80) {
// Eat the fish
otherFish.destroy();
fish.splice(i, 1);
self.lastEatingTime = LK.ticks;
break;
}
}
}
}
}
};
return self;
});
var Octopus = Container.expand(function () {
var self = Container.call(this);
var octopusGraphics = self.attachAsset('octopus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2; // 3 to 5 speed
self.value = 75; // Reduced from 200 to 75
self.caught = false;
self.direction = Math.random() > 0.5 ? 1 : -1; // 1 for down, -1 for up
self.down = function (x, y, obj) {
if (!self.caught) {
self.caught = true;
// Score points
LK.setScore(LK.getScore() + self.value);
scoreTxt.setText(LK.getScore());
// Remove octopus from array and destroy
for (var i = octopi.length - 1; i >= 0; i--) {
if (octopi[i] === self) {
octopi.splice(i, 1);
break;
}
}
self.destroy();
LK.getSound('catch').play();
}
};
self.update = function () {
if (!self.caught) {
// Occasionally change speed for more dynamic movement
if (Math.random() < 0.002) {
var newSpeed = 3 + Math.random() * 2;
tween(self, {
speed: newSpeed
}, {
duration: 1000,
easing: tween.easeInOut
});
}
self.y += self.speed * self.direction;
// Reverse direction if octopus hits water boundaries - keep within water
if (self.y < waterSurface + 50 || self.y > waterSurface + 1700) {
self.direction *= -1;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var fish = [];
var octopi = [];
var waterSurface = 500;
var fishSpawnTimer = 0;
var octopusSpawnTimer = 0;
var lives = 3;
// Create water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 0,
x: 0,
y: waterSurface
}));
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
// Create lives display
var livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(livesTxt);
livesTxt.x = -20;
livesTxt.y = 50;
// Initialize score
scoreTxt.setText(LK.getScore());
// Spawn fish function
function spawnFish() {
var fishTypes = ['smallFish', 'mediumFish', 'largeFish'];
var depths = [200, 400, 600]; // Shallow, medium, deep
var typeIndex = Math.floor(Math.random() * fishTypes.length);
var fishType = fishTypes[typeIndex];
var depth = depths[typeIndex] + Math.random() * 200;
var newFish = new Fish(fishType, depth);
newFish.x = Math.random() > 0.5 ? -50 : 2098;
newFish.y = waterSurface + depth;
newFish.spawnTime = LK.ticks; // Track when fish was spawned
fish.push(newFish);
game.addChild(newFish);
}
// Spawn octopus function
function spawnOctopus() {
var newOctopus = new Octopus();
newOctopus.x = Math.random() * 1848 + 100; // Random X position within game bounds
newOctopus.y = Math.random() > 0.5 ? waterSurface + 100 : waterSurface + 1200; // Start from within water area
newOctopus.spawnTime = LK.ticks; // Track when octopus was spawned
octopi.push(newOctopus);
game.addChild(newOctopus);
}
// Game variables for random spawning
var nextFishSpawnTime = 120 + Math.random() * 120; // Random interval between 2-4 seconds
// Function to calculate spawn interval based on score
function calculateFishSpawnInterval() {
var currentScore = LK.getScore();
var baseInterval = 120; // 2 seconds base
var randomVariation = 60; // 1 second variation
// Reduce spawn time as score increases
var speedMultiplier = Math.max(0.3, 1 - currentScore / 1000); // Gets faster, minimum 0.3x speed
return (baseInterval + Math.random() * randomVariation) * speedMultiplier;
}
// Main game loop
game.update = function () {
// Spawn fish randomly
fishSpawnTimer++;
if (fishSpawnTimer >= nextFishSpawnTime) {
spawnFish();
fishSpawnTimer = 0;
// Set next dynamic spawn time based on score
nextFishSpawnTime = calculateFishSpawnInterval();
}
// Clean up fish that are off screen and check for missed fish
for (var i = fish.length - 1; i >= 0; i--) {
var currentFish = fish[i];
var timeSinceSpawn = LK.ticks - currentFish.spawnTime;
var fiveSecondsInTicks = 300; // 5 seconds * 60 ticks per second
// Check if 5 seconds have passed and fish not caught (except big fish after 500 points)
var shouldTimeout = timeSinceSpawn >= fiveSecondsInTicks && !currentFish.caught;
if (shouldTimeout && !(currentFish.isBigFish && LK.getScore() >= 500)) {
// Fish timeout - lose a life
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
currentFish.destroy();
fish.splice(i, 1);
continue;
}
if (currentFish.x < -200 || currentFish.x > 2248) {
// If fish was not caught and went off screen, lose a life
if (!currentFish.caught) {
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
}
currentFish.destroy();
fish.splice(i, 1);
}
}
// Spawn big fish after 500 points with random intervals
var currentScore = LK.getScore();
if (currentScore >= 500 && Math.random() < 0.001) {
// 0.1% chance per frame (10 times less frequent)
var bigFish = new Fish('bigFish', 300 + Math.random() * 400);
bigFish.x = Math.random() > 0.5 ? -100 : 2148;
bigFish.y = waterSurface + bigFish.depth;
fish.push(bigFish);
game.addChild(bigFish);
}
// Spawn octopi after 250 points with more space between them
if (currentScore >= 250) {
octopusSpawnTimer++;
if (octopusSpawnTimer >= 360) {
// Every 6 seconds (360 ticks) - even more space between octopi
spawnOctopus();
octopusSpawnTimer = 0;
}
}
// Clean up octopi that are off screen and check for timeouts
for (var j = octopi.length - 1; j >= 0; j--) {
var currentOctopus = octopi[j];
var timeSinceSpawn = LK.ticks - currentOctopus.spawnTime;
var fiveSecondsInTicks = 300; // 5 seconds * 60 ticks per second
// Check if 5 seconds have passed and octopus not caught
if (timeSinceSpawn >= fiveSecondsInTicks && !currentOctopus.caught) {
// Octopus timeout - lose a life
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
currentOctopus.destroy();
octopi.splice(j, 1);
continue;
}
if (currentOctopus.y < waterSurface - 100 || currentOctopus.y > waterSurface + 1800) {
// If octopus was not caught and went outside water bounds, lose a life
if (!currentOctopus.caught) {
lives--;
livesTxt.setText('Lives: ' + lives);
// Check for game over
if (lives <= 0) {
LK.showGameOver();
}
}
currentOctopus.destroy();
octopi.splice(j, 1);
}
}
};
Rubber Hose Style Blue Fish. In-Game asset. 2d. High contrast. No shadows
Rubber Hose Style Green Medium-Sized fish. In-Game asset. 2d. High contrast. No shadows
Rubber Hose Style Orange Happy Fish. In-Game asset. 2d. High contrast. No shadows
Rubber Hose Style Swimming pose Shark. It's Angry. In-Game asset. 2d. High contrast. No shadows
Rubber Hose Style octopus. In-Game asset. 2d. High contrast. No shadows