/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bag = Container.expand(function () {
var self = Container.call(this);
// Create bag graphics
var bagBody = self.attachAsset('bag', {
anchorX: 0.5,
anchorY: 1
});
var bagHandle = self.attachAsset('bagHandle', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -100
});
// Store fish in bag
self.fishInventory = [];
self.addFish = function (fishType, points) {
self.fishInventory.push({
type: fishType,
points: points,
price: Math.floor(points / 2)
});
};
self.down = function () {
showInventory();
};
return self;
});
var Bait = Container.expand(function (type) {
var self = Container.call(this);
self.baitType = type || 'basic';
var baitAsset;
if (self.baitType === 'basic') {
baitAsset = self.attachAsset('basicBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 10;
self.catchChance = 1.0;
self.name = 'Basic Bait';
} else if (self.baitType === 'premium') {
baitAsset = self.attachAsset('premiumBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 25;
self.catchChance = 1.5;
self.name = 'Premium Bait';
} else if (self.baitType === 'golden') {
baitAsset = self.attachAsset('goldenBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 50;
self.catchChance = 2.0;
self.name = 'Golden Bait';
}
return self;
});
var Boat = Container.expand(function () {
var self = Container.call(this);
// Create boat hull
var boatHull = self.attachAsset('boat', {
anchorX: 0.5,
anchorY: 0.5
});
// Array to hold caught fish
self.caughtFish = [];
// Boat movement properties
self.speed = 3;
self.isMoving = false;
self.targetX = 0;
// Method to add fish to boat
self.addFish = function (fish) {
// Position fish in boat
var fishInBoat = self.addChild(fish);
var offset = self.caughtFish.length * 25 - 50; // Spread fish across boat
fishInBoat.x = offset;
fishInBoat.y = -20;
fishInBoat.scaleX = 0.6;
fishInBoat.scaleY = 0.6;
self.caughtFish.push(fishInBoat);
};
// Method to move boat to target position
self.moveTo = function (targetX) {
if (targetX < 100) targetX = 100;
if (targetX > 1948) targetX = 1948;
self.targetX = targetX;
self.isMoving = true;
};
self.update = function () {
if (self.isMoving) {
var distance = self.targetX - self.x;
if (Math.abs(distance) > self.speed) {
self.x += distance > 0 ? self.speed : -self.speed;
} else {
self.x = self.targetX;
self.isMoving = false;
}
}
};
return self;
});
var Bubble = Container.expand(function () {
var self = Container.call(this);
// Random bubble type
var bubbleTypes = ['bubble1', 'bubble2', 'bubble3'];
var bubbleType = bubbleTypes[Math.floor(Math.random() * bubbleTypes.length)];
var bubbleGraphics = self.attachAsset(bubbleType, {
anchorX: 0.5,
anchorY: 0.5
});
// Bubble properties
self.speed = 0.5 + Math.random() * 1.5; // Slow floating speed
self.sideSpeed = (Math.random() - 0.5) * 0.5; // Gentle side drift
self.alpha = 0.6 + Math.random() * 0.4; // Semi-transparent
self.update = function () {
// Float upward slowly
self.y -= self.speed;
// Gentle side movement
self.x += self.sideSpeed;
// Remove when reaching surface
if (self.y < waterSurface) {
self.destroy();
}
// Keep within lake bounds horizontally
if (self.x < 50) {
self.x = 50;
self.sideSpeed = Math.abs(self.sideSpeed);
}
if (self.x > 1998) {
self.x = 1998;
self.sideSpeed = -Math.abs(self.sideSpeed);
}
};
return self;
});
var Cabin = Container.expand(function () {
var self = Container.call(this);
// Cabin structure
var cabin = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 1
});
var roof = self.attachAsset('cabinRoof', {
anchorX: 0.5,
anchorY: 1,
y: -180
});
var door = self.attachAsset('cabinDoor', {
anchorX: 0.5,
anchorY: 1,
y: -50
});
// Bait displays
self.basicBaitDisplay = self.addChild(new Bait('basic'));
self.basicBaitDisplay.x = -60;
self.basicBaitDisplay.y = -140;
self.premiumBaitDisplay = self.addChild(new Bait('premium'));
self.premiumBaitDisplay.x = -20;
self.premiumBaitDisplay.y = -140;
self.goldenBaitDisplay = self.addChild(new Bait('golden'));
self.goldenBaitDisplay.x = 20;
self.goldenBaitDisplay.y = -140;
// Make baits interactive
self.basicBaitDisplay.down = function () {
purchaseBait('basic');
};
self.premiumBaitDisplay.down = function () {
purchaseBait('premium');
};
self.goldenBaitDisplay.down = function () {
purchaseBait('golden');
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Random cloud type
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5
});
// Cloud properties
self.speed = 0.3 + Math.random() * 0.5; // Slow floating speed
self.alpha = 0.7 + Math.random() * 0.3; // Semi-transparent
self.originalScale = 0.8 + Math.random() * 0.4; // Random size
cloudGraphics.scaleX = self.originalScale;
cloudGraphics.scaleY = self.originalScale;
// Gentle floating animation properties
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.01 + Math.random() * 0.02;
self.floatRange = 10 + Math.random() * 15;
self.update = function () {
// Move cloud slowly across sky
self.x += self.speed;
// Gentle floating motion
self.floatOffset += self.floatSpeed;
self.y += Math.sin(self.floatOffset) * 0.2;
// Reset cloud position when it goes off screen
if (self.x > 2200) {
self.x = -200;
// Randomize properties when resetting
self.speed = 0.3 + Math.random() * 0.5;
self.alpha = 0.7 + Math.random() * 0.3;
}
};
return self;
});
var Fish = Container.expand(function (type) {
var self = Container.call(this);
self.fishType = type || 'small';
var fishAsset;
if (self.fishType === 'small') {
fishAsset = self.attachAsset('smallFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1 + Math.random() * 2;
self.points = 10;
} else if (self.fishType === 'medium') {
fishAsset = self.attachAsset('mediumFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5 + Math.random() * 1.5;
self.points = 25;
} else if (self.fishType === 'tropical') {
fishAsset = self.attachAsset('tropicalFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5 + Math.random() * 2;
self.points = 35;
} else if (self.fishType === 'rare') {
fishAsset = self.attachAsset('rareFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.2 + Math.random() * 0.8;
self.points = 100;
} else if (self.fishType === 'angel') {
fishAsset = self.attachAsset('angelFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.8 + Math.random() * 1.2;
self.points = 45;
} else if (self.fishType === 'clown') {
fishAsset = self.attachAsset('clownFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.2 + Math.random() * 1.8;
self.points = 30;
} else if (self.fishType === 'surgeon') {
fishAsset = self.attachAsset('surgeonFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.0 + Math.random() * 1.5;
self.points = 40;
} else if (self.fishType === 'parrot') {
fishAsset = self.attachAsset('parrotFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.7 + Math.random() * 1.3;
self.points = 55;
} else if (self.fishType === 'butterfly') {
fishAsset = self.attachAsset('butterflyFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.3 + Math.random() * 1.7;
self.points = 38;
} else if (self.fishType === 'mandarin') {
fishAsset = self.attachAsset('mandarin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.9 + Math.random() * 1.4;
self.points = 65;
} else if (self.fishType === 'lion') {
fishAsset = self.attachAsset('lionFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.4 + Math.random() * 0.9;
self.points = 80;
} else if (self.fishType === 'grouper') {
fishAsset = self.attachAsset('grouper', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.2 + Math.random() * 0.7;
self.points = 120;
} else {
fishAsset = self.attachAsset('largeFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.3 + Math.random() * 1;
self.points = 50;
}
self.directionX = Math.random() > 0.5 ? 1 : -1;
self.directionY = (Math.random() - 0.5) * 0.5;
self.startX = self.x;
self.swimDistance = 300 + Math.random() * 400;
self.update = function () {
self.x += self.speed * self.directionX;
self.y += self.speed * self.directionY;
// Turn around if swam too far
if (Math.abs(self.x - self.startX) > self.swimDistance) {
self.directionX *= -1;
fishAsset.scaleX = self.directionX;
self.startX = self.x;
}
// Keep fish in water bounds
if (self.x < 50) {
self.x = 50;
self.directionX = 1;
fishAsset.scaleX = 1;
}
if (self.x > 1998) {
self.x = 1998;
self.directionX = -1;
fishAsset.scaleX = -1;
}
if (self.y < waterSurface + 100) {
self.y = waterSurface + 100;
self.directionY = Math.abs(self.directionY);
}
if (self.y > waterSurface + 1200) {
self.y = waterSurface + 1200;
self.directionY = -Math.abs(self.directionY);
}
};
return self;
});
var FishingLine = Container.expand(function () {
var self = Container.call(this);
self.lineGraphics = self.attachAsset('fishingLine', {
anchorX: 0.5,
anchorY: 0
});
self.hook = self.addChild(new Container());
self.hookGraphics = self.hook.attachAsset('hook', {
anchorX: 0.5,
anchorY: 0.5
});
self.bobber = self.addChild(new Container());
self.bobberGraphics = self.bobber.attachAsset('bobber', {
anchorX: 0.5,
anchorY: 0.5
});
self.isVisible = false;
self.visible = false;
self.showLine = function (startX, startY, endX, endY) {
self.x = startX;
self.y = startY;
var distance = Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));
var angle = Math.atan2(endY - startY, endX - startX);
self.lineGraphics.height = distance;
self.lineGraphics.rotation = angle + Math.PI / 2;
self.hook.x = 0;
self.hook.y = distance;
self.bobber.x = 0;
self.bobber.y = distance - 20;
self.isVisible = true;
self.visible = true;
};
self.hideLine = function () {
self.isVisible = false;
self.visible = false;
};
return self;
});
var Pebble = Container.expand(function () {
var self = Container.call(this);
var pebbleGraphics = self.attachAsset('pebble', {
anchorX: 0.5,
anchorY: 0.5
});
// Random tint for variation
var grayTones = [0x8B7355, 0x696969, 0x708090, 0x778899];
pebbleGraphics.tint = grayTones[Math.floor(Math.random() * grayTones.length)];
// Subtle movement properties
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.005 + Math.random() * 0.01;
self.maxSway = 2 + Math.random() * 3;
self.update = function () {
self.waveOffset += self.waveSpeed;
var sway = Math.sin(self.waveOffset) * self.maxSway;
pebbleGraphics.x = sway * 0.05; // Very minimal horizontal movement
};
return self;
});
var Rock = Container.expand(function (size) {
var self = Container.call(this);
self.rockSize = size || 'small';
var rockAsset = self.rockSize === 'large' ? 'largeRock' : 'smallRock';
var rockGraphics = self.attachAsset(rockAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Random tint and scale for variation
var rockTones = [0x696969, 0x2F4F4F, 0x708090, 0x556B2F];
rockGraphics.tint = rockTones[Math.floor(Math.random() * rockTones.length)];
rockGraphics.scaleX = 0.8 + Math.random() * 0.4;
rockGraphics.scaleY = 0.8 + Math.random() * 0.4;
// Very subtle movement for rocks
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.003 + Math.random() * 0.005;
self.update = function () {
self.waveOffset += self.waveSpeed;
// Barely visible movement for realism
rockGraphics.alpha = 0.9 + Math.sin(self.waveOffset) * 0.1;
};
return self;
});
var RodShop = Container.expand(function () {
var self = Container.call(this);
// Shop background
var shopBg = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 3
});
self.visible = false;
self.isOpen = false;
// Create title
var titleText = new Text2('Rod Shop', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -300;
self.addChild(titleText);
// Create 8 rod options
self.rodOptions = [];
for (var i = 0; i < 8; i++) {
var rodContainer = self.addChild(new Container());
rodContainer.x = i % 4 * 200 - 300;
rodContainer.y = Math.floor(i / 4) * 150 - 100;
// Rod graphic
var rodGraphic = rodContainer.attachAsset('fishingRod', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
// Rod level text
var levelText = new Text2('Level ' + (i + 1), {
size: 30,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.y = 60;
rodContainer.addChild(levelText);
// Rod price text
var price = 500 + i * 200;
var priceText = new Text2('$' + price, {
size: 35,
fill: 0xFFD700
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 90;
rodContainer.addChild(priceText);
self.rodOptions.push({
container: rodContainer,
level: i + 1,
price: price,
priceText: priceText
});
// Make rod clickable
rodContainer.rodIndex = i;
rodContainer.down = function () {
var targetLevel = this.rodIndex + 1;
var rodPrice = 500 + this.rodIndex * 200;
if (targetLevel === currentRodLevel + 1 && playerMoney >= rodPrice) {
playerMoney -= rodPrice;
storage.playerMoney = playerMoney;
currentRodLevel = targetLevel;
storage.rodLevel = currentRodLevel;
moneyTxt.setText('Money: ' + playerMoney);
if (currentRodLevel >= 8) {
rodLevelTxt.setText('Rod Level: Maks.');
} else {
rodLevelTxt.setText('Rod Level: ' + currentRodLevel);
}
// Clear existing fish and spawn new types
for (var f = fish.length - 1; f >= 0; f--) {
game.removeChild(fish[f]);
fish.splice(f, 1);
}
for (var newF = 0; newF < 8; newF++) {
spawnFish();
}
self.close();
instructionTxt.setText('Rod upgraded to level ' + currentRodLevel + '!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
} else if (targetLevel !== currentRodLevel + 1) {
instructionTxt.setText('Must buy rods in order!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
} else {
instructionTxt.setText('Not enough money for this rod!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
}
};
}
// Close button
var closeBtn = self.addChild(LK.getAsset('cabinDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 250,
scaleX: 0.8,
scaleY: 0.5
}));
var closeText = new Text2('Close', {
size: 40,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.y = 250;
self.addChild(closeText);
closeBtn.down = function () {
self.close();
};
self.open = function () {
self.visible = true;
self.isOpen = true;
game.isPaused = true;
};
self.close = function () {
self.visible = false;
self.isOpen = false;
game.isPaused = false;
};
return self;
});
var Seaweed = Container.expand(function () {
var self = Container.call(this);
var seaweedGraphics = self.attachAsset('seaweed', {
anchorX: 0.5,
anchorY: 1
});
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.02 + Math.random() * 0.03;
self.maxSway = 15 + Math.random() * 10;
self.update = function () {
self.waveOffset += self.waveSpeed * 0.3; // Slower wave movement
var sway = Math.sin(self.waveOffset) * self.maxSway * 0.2; // Much gentler sway
seaweedGraphics.rotation = sway * 0.02; // Minimal rotation
seaweedGraphics.x = sway * 0.1; // Minimal horizontal movement
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
// Shop background
var shopBg = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 2.5
});
self.visible = false;
self.isOpen = false;
self.fishingRods = [];
for (var i = 0; i < 15; i++) {
self.fishingRods.push({
level: i + 1,
price: 50 + i * 25,
catchBonus: 1 + i * 0.1
});
}
// Create current rod display
var currentRodDisplay = self.addChild(LK.getAsset('fishingRod', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: -100,
scaleX: 0.5,
scaleY: 0.5
}));
var currentRodText = new Text2('Current Rod: Level ' + currentRodLevel, {
size: 30,
fill: 0xFFFFFF
});
currentRodText.anchor.set(0.5, 0.5);
currentRodText.x = 100;
currentRodText.y = -50;
self.addChild(currentRodText);
self.open = function () {
self.visible = true;
self.isOpen = true;
game.isPaused = true;
// Update current rod display
currentRodText.setText('Current Rod: Level ' + currentRodLevel);
};
self.close = function () {
self.visible = false;
self.isOpen = false;
game.isPaused = false;
};
self.down = function (x, y) {
if (x > 0) {
// Right side - buy rods and bait
var rodIndex = Math.floor((y + 200) / 50);
if (rodIndex >= 0 && rodIndex < 15) {
var rod = self.fishingRods[rodIndex];
if (playerMoney >= rod.price) {
playerMoney -= rod.price;
storage.playerMoney = playerMoney;
currentRodLevel = rod.level;
storage.rodLevel = currentRodLevel;
moneyTxt.setText('Money: ' + playerMoney);
}
}
} else {
// Left side - sell fish
if (inventoryBag.fishInventory.length > 0) {
var fish = inventoryBag.fishInventory.pop();
playerMoney += fish.price;
storage.playerMoney = playerMoney;
moneyTxt.setText('Money: ' + playerMoney);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var waterSurface = 600;
var fish = [];
var isCasting = false;
var isReeling = false;
var castStartX = 0;
var castStartY = 0;
var hookedFish = null;
var reelProgress = 0;
var clickCount = 0;
var lastClickX = 0;
var lastClickY = 0;
var targetCastX = 0;
var targetCastY = 0;
var clickTimeout = null;
// Bait system variables
var playerMoney = storage.playerMoney || 100;
var currentBait = 'basic';
var baitCount = {
basic: storage.basicBait || 5,
premium: storage.premiumBait || 0,
golden: storage.goldenBait || 0
};
var currentRodLevel = storage.rodLevel || 1;
var inventoryOpen = false;
var shopOpen = false;
// Create water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 0,
x: 0,
y: waterSurface
}));
// Create seaweed patches at bottom corners of the lake
var seaweeds = [];
// Create bubbles array
var bubbles = [];
// Create clouds array
var clouds = [];
// Create pebbles and rocks arrays
var pebbles = [];
var rocks = [];
// Bottom left corner seaweed - more dense
for (var s = 0; s < 15; s++) {
var seaweed = game.addChild(new Seaweed());
seaweed.x = 50 + Math.random() * 400;
seaweed.y = waterSurface + 1000 + Math.random() * 500;
seaweeds.push(seaweed);
}
// Bottom right corner seaweed - more dense
for (var s = 0; s < 15; s++) {
var seaweed = game.addChild(new Seaweed());
seaweed.x = 1650 + Math.random() * 400;
seaweed.y = waterSurface + 1000 + Math.random() * 500;
seaweeds.push(seaweed);
}
// Create boat
var boat = game.addChild(new Boat());
boat.x = 1024;
boat.y = waterSurface - 30;
// Create player on boat
var player = boat.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -30
}));
// Create fishing rod on boat
var fishingRod = boat.addChild(LK.getAsset('fishingRod', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -20
}));
// Create fishing line
var fishingLine = game.addChild(new FishingLine());
// Create cabin on the right side
var cabin = game.addChild(new Cabin());
cabin.x = 1600;
cabin.y = waterSurface;
// Create inventory bag at bottom of screen
var inventoryBag = game.addChild(new Bag());
inventoryBag.x = 1024;
inventoryBag.y = 2732;
// Create shop interface
var shop = game.addChild(new Shop());
shop.x = 1024;
shop.y = 1366;
// Create rod shop interface
var rodShop = game.addChild(new RodShop());
rodShop.x = 1024;
rodShop.y = 1366;
// Create UI
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
// Fish catch notification
var catchNotificationTxt = new Text2('', {
size: 80,
fill: 0xFFD700
});
catchNotificationTxt.anchor.set(0.5, 0.5);
catchNotificationTxt.x = 1024;
catchNotificationTxt.y = 1366;
catchNotificationTxt.visible = false;
game.addChild(catchNotificationTxt);
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionTxt = new Text2('Tap on lake to cast your line!', {
size: 40,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0);
instructionTxt.y = 80;
LK.gui.top.addChild(instructionTxt);
var moneyTxt = new Text2('Money: ' + playerMoney, {
size: 50,
fill: 0xFFD700
});
moneyTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(moneyTxt);
var baitTxt = new Text2('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')', {
size: 40,
fill: 0xFFFFFF
});
baitTxt.anchor.set(1, 0);
baitTxt.y = 60;
LK.gui.topRight.addChild(baitTxt);
var cabinInfoTxt = new Text2('Visit cabin to buy baits!\nBasic: 10 Premium: 25 Golden: 50', {
size: 30,
fill: 0xFFFFFF
});
cabinInfoTxt.anchor.set(0, 1);
cabinInfoTxt.y = -20;
LK.gui.bottomLeft.addChild(cabinInfoTxt);
var rodLevelTxt = new Text2(currentRodLevel >= 8 ? 'Rod Level: Maks.' : 'Rod Level: ' + currentRodLevel, {
size: 40,
fill: 0xFFD700
});
rodLevelTxt.anchor.set(0, 0);
rodLevelTxt.y = 120;
LK.gui.topLeft.addChild(rodLevelTxt);
// Rod upgrade button
var rodUpgradeBtn = new Text2('🎣 Upgrade Rod', {
size: 35,
fill: 0xFFFFFF
});
rodUpgradeBtn.anchor.set(0, 0);
rodUpgradeBtn.y = 170;
LK.gui.topLeft.addChild(rodUpgradeBtn);
// Purchase bait function
function purchaseBait(baitType) {
var bait = new Bait(baitType);
if (playerMoney >= bait.price) {
playerMoney -= bait.price;
baitCount[baitType] += 1;
// Save to storage
storage.playerMoney = playerMoney;
storage[baitType + 'Bait'] = baitCount[baitType];
// Update UI
moneyTxt.setText('Money: ' + playerMoney);
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
instructionTxt.setText('Bought ' + bait.name + '!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 1500);
} else {
instructionTxt.setText('Not enough money!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 1500);
}
}
// Inventory display elements array for proper cleanup
var inventoryDisplayElements = [];
// Show inventory function
function showInventory() {
if (inventoryOpen) return;
inventoryOpen = true;
// Clear previous display elements
inventoryDisplayElements = [];
// Create inventory display
var inventoryBg = game.addChild(LK.getAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 4,
scaleY: 3
}));
inventoryDisplayElements.push(inventoryBg);
var inventoryTitle = new Text2('Fish Inventory', {
size: 60,
fill: 0xFFFFFF
});
inventoryTitle.anchor.set(0.5, 0.5);
inventoryTitle.x = 1024;
inventoryTitle.y = 800;
game.addChild(inventoryTitle);
inventoryDisplayElements.push(inventoryTitle);
// Display only fish names in bag
for (var i = 0; i < inventoryBag.fishInventory.length; i++) {
var fish = inventoryBag.fishInventory[i];
var fishText = new Text2(fish.type.charAt(0).toUpperCase() + fish.type.slice(1) + ' Fish', {
size: 40,
fill: 0xFFFFFF
});
fishText.anchor.set(0.5, 0.5);
fishText.x = 1024;
fishText.y = 900 + i * 60;
game.addChild(fishText);
inventoryDisplayElements.push(fishText);
}
// Close button
var closeBtn = game.addChild(LK.getAsset('bag', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800
}));
inventoryDisplayElements.push(closeBtn);
closeBtn.down = function () {
// Remove all inventory display elements
for (var i = 0; i < inventoryDisplayElements.length; i++) {
game.removeChild(inventoryDisplayElements[i]);
}
inventoryDisplayElements = [];
inventoryOpen = false;
};
}
// Show shop function
function showShop() {
if (shopOpen) return;
shopOpen = true;
shop.open();
}
// Switch bait function
function switchBait() {
var baitTypes = ['basic', 'premium', 'golden'];
var currentIndex = baitTypes.indexOf(currentBait);
for (var i = 1; i <= baitTypes.length; i++) {
var nextIndex = (currentIndex + i) % baitTypes.length;
var nextBait = baitTypes[nextIndex];
if (baitCount[nextBait] > 0) {
currentBait = nextBait;
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
break;
}
}
}
// Fish types available by rod level
var fishTypesByLevel = {
1: ['tropical'],
2: ['tropical', 'clown'],
3: ['tropical', 'clown', 'butterfly'],
4: ['tropical', 'angel', 'clown', 'butterfly'],
5: ['tropical', 'large', 'angel', 'surgeon'],
6: ['tropical', 'large', 'parrot', 'angel', 'surgeon'],
7: ['tropical', 'large', 'rare', 'parrot', 'mandarin', 'lion'],
8: ['tropical', 'large', 'rare', 'mandarin', 'lion', 'grouper']
};
// Spawn initial fish
function spawnFish() {
var availableFishTypes = fishTypesByLevel[currentRodLevel] || ['small'];
var fishType = availableFishTypes[Math.floor(Math.random() * availableFishTypes.length)];
var newFish = game.addChild(new Fish(fishType));
newFish.x = Math.random() * 1948 + 50;
newFish.y = waterSurface + 150 + Math.random() * 1000;
newFish.startX = newFish.x;
fish.push(newFish);
}
// Spawn initial fish
for (var i = 0; i < 8; i++) {
spawnFish();
}
// Create clouds in the sky
for (var c = 0; c < 6; c++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = 100 + Math.random() * 300; // Position clouds in sky area
clouds.push(cloud);
}
// Create pebbles at the very bottom of the lake
for (var p = 0; p < 40; p++) {
var pebble = game.addChild(new Pebble());
pebble.x = 80 + Math.random() * 1888; // Spread across lake width
pebble.y = waterSurface + 1500 + Math.random() * 100; // Very bottom area only
pebbles.push(pebble);
}
// Create small rocks at the very bottom of lake
for (var r = 0; r < 15; r++) {
var smallRock = game.addChild(new Rock('small'));
smallRock.x = 100 + Math.random() * 1848;
smallRock.y = waterSurface + 1450 + Math.random() * 150; // Very bottom area
rocks.push(smallRock);
}
// Create large rocks at the very bottom of lake
for (var lr = 0; lr < 8; lr++) {
var largeRock = game.addChild(new Rock('large'));
largeRock.x = 150 + Math.random() * 1748;
largeRock.y = waterSurface + 1400 + Math.random() * 200; // Very bottom area
rocks.push(largeRock);
}
// Cast fishing line
function castLine(targetX, targetY) {
if (isCasting || isReeling) return;
if (baitCount[currentBait] <= 0) {
instructionTxt.setText('No bait! Visit the cabin to buy more.');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
return;
}
isCasting = true;
// Use bait
baitCount[currentBait] -= 1;
storage[currentBait + 'Bait'] = baitCount[currentBait];
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
var rodTipX = boat.x + fishingRod.x;
var rodTipY = boat.y + fishingRod.y - 180;
fishingLine.showLine(rodTipX, rodTipY, targetX, targetY);
LK.getSound('cast').play();
// Animate casting
tween(fishingRod, {
rotation: Math.PI / 6
}, {
duration: 200
});
LK.setTimeout(function () {
LK.getSound('splash').play();
// Check if hook is near any fish
checkForFish(targetX, targetY);
LK.setTimeout(function () {
if (!hookedFish) {
reelIn();
}
}, 2000);
}, 300);
}
// Check if hook caught a fish
function checkForFish(hookX, hookY) {
var bait = new Bait(currentBait);
var catchRadius = 60 * bait.catchChance;
for (var i = 0; i < fish.length; i++) {
var currentFish = fish[i];
var distance = Math.sqrt((currentFish.x - hookX) * (currentFish.x - hookX) + (currentFish.y - hookY) * (currentFish.y - hookY));
if (distance < catchRadius) {
// Better bait increases chance of catching rare fish
var catchChance = Math.random() * bait.catchChance;
if (catchChance > 0.5 || currentFish.fishType !== 'rare') {
hookedFish = currentFish;
reelProgress = 0;
isReeling = true;
LK.getSound('catch').play();
instructionTxt.setText('Tap rapidly to reel in!');
// Flash the hooked fish
LK.effects.flashObject(hookedFish, 0xFFFF00, 500);
break;
}
}
}
}
// Reel in the line
function reelIn() {
if (hookedFish) {
// Increase score
LK.setScore(LK.getScore() + hookedFish.points);
scoreTxt.setText('Score: ' + LK.getScore());
// Give money based on fish value
var moneyEarned = Math.floor(hookedFish.points / 2);
playerMoney += moneyEarned;
storage.playerMoney = playerMoney;
moneyTxt.setText('Money: ' + playerMoney);
// Show fish catch notification
var fishPrice = Math.floor(hookedFish.points / 2);
catchNotificationTxt.setText(hookedFish.fishType.charAt(0).toUpperCase() + hookedFish.fishType.slice(1) + ' Fish - $' + fishPrice);
catchNotificationTxt.visible = true;
// Hide notification after 4 seconds
LK.setTimeout(function () {
catchNotificationTxt.visible = false;
}, 4000);
// Add fish directly to bag (don't add to boat)
var caughtFish = null;
for (var i = fish.length - 1; i >= 0; i--) {
if (fish[i] === hookedFish) {
caughtFish = fish[i];
fish.splice(i, 1);
break;
}
}
if (caughtFish) {
// Remove fish from game container
game.removeChild(caughtFish);
// Add to inventory bag directly (skip boat)
inventoryBag.addFish(caughtFish.fishType, caughtFish.points);
}
// Spawn new fish
spawnFish();
hookedFish = null;
reelProgress = 0;
}
// Reset fishing state
fishingLine.hideLine();
tween(fishingRod, {
rotation: 0
}, {
duration: 300
});
isCasting = false;
isReeling = false;
instructionTxt.setText('Tap on lake to cast your line!');
}
// Game events
game.down = function (x, y, obj) {
if (isReeling && hookedFish) {
reelProgress += 20;
if (reelProgress >= 100) {
reelIn();
}
return;
}
// Check if clicking on rod upgrade button (top left area)
if (x >= 0 && x <= 200 && y >= 170 && y <= 210) {
if (!rodShop.isOpen) {
rodShop.open();
}
return;
}
// Check if boat is near cabin for shop interaction
if (!isCasting && !isReeling && Math.abs(boat.x - cabin.x) < 100 && x > 1400 && x < 1800 && y < waterSurface + 100) {
showShop();
return;
}
// Switch bait on tap (when not casting or reeling)
if (!isCasting && !isReeling && x > 1500) {
switchBait();
return;
}
if (!isCasting && !isReeling) {
// Check if click is in water area (entire lake surface)
if (y > waterSurface && x >= 0 && x <= 2048) {
// Cast line directly to clicked location
castLine(x, y);
} else {
// Move boat towards clicked position when clicking anywhere else
boat.moveTo(x);
}
}
};
game.up = function (x, y, obj) {
// Removed drag-to-cast functionality - now using 3-tap system
};
// Timer-based fish spawning system
var fishSpawnTimer = 0;
var timedFishSpawn = {
timer: 0,
interval: 3600,
// 60 seconds at 60fps
fishTypeIndex: 0
};
game.update = function () {
// Update boat
boat.update();
// Update all fish
for (var i = 0; i < fish.length; i++) {
fish[i].update();
}
// Update seaweed wave movement
for (var s = 0; s < seaweeds.length; s++) {
seaweeds[s].update();
}
// Update clouds floating in sky
for (var c = 0; c < clouds.length; c++) {
clouds[c].update();
}
// Update pebbles on lake bottom
for (var p = 0; p < pebbles.length; p++) {
pebbles[p].update();
}
// Update rocks on lake bottom
for (var r = 0; r < rocks.length; r++) {
rocks[r].update();
}
// Update bubbles
for (var b = bubbles.length - 1; b >= 0; b--) {
var bubble = bubbles[b];
bubble.update();
// Remove destroyed bubbles from array
if (bubble.y < waterSurface) {
game.removeChild(bubble);
bubbles.splice(b, 1);
}
}
// Spawn bubbles randomly from lake bottom
if (Math.random() < 0.02) {
// 2% chance each frame
var newBubble = game.addChild(new Bubble());
newBubble.x = 100 + Math.random() * 1848; // Random x position in lake
newBubble.y = waterSurface + 1300 + Math.random() * 200; // Near bottom
bubbles.push(newBubble);
}
// Spawn new fish occasionally (reduced frequency)
fishSpawnTimer++;
if (fishSpawnTimer > 1200 && fish.length < 8) {
// Every 20 seconds at 60fps, reduced max fish count
spawnFish();
fishSpawnTimer = 0;
}
// Timed fish spawning - spawn all fish types every minute
timedFishSpawn.timer++;
if (timedFishSpawn.timer >= timedFishSpawn.interval) {
var availableFishTypes = fishTypesByLevel[currentRodLevel] || ['tropical'];
// Spawn one of each fish type available for current rod level
for (var f = 0; f < availableFishTypes.length; f++) {
var fishType = availableFishTypes[f];
var newFish = game.addChild(new Fish(fishType));
newFish.x = Math.random() * 1948 + 50;
newFish.y = waterSurface + 150 + Math.random() * 1000;
newFish.startX = newFish.x;
fish.push(newFish);
}
timedFishSpawn.timer = 0;
}
// Move hooked fish towards rod
if (hookedFish && isReeling) {
var targetX = boat.x + fishingRod.x;
var targetY = boat.y + fishingRod.y - 100;
var moveSpeed = 0.02;
hookedFish.x += (targetX - hookedFish.x) * moveSpeed;
hookedFish.y += (targetY - hookedFish.y) * moveSpeed;
// Auto-reel if fish gets close enough
var distance = Math.sqrt((hookedFish.x - targetX) * (hookedFish.x - targetX) + (hookedFish.y - targetY) * (hookedFish.y - targetY));
if (distance < 50) {
reelIn();
}
}
};
// Play ambient music
LK.playMusic('ambience'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bag = Container.expand(function () {
var self = Container.call(this);
// Create bag graphics
var bagBody = self.attachAsset('bag', {
anchorX: 0.5,
anchorY: 1
});
var bagHandle = self.attachAsset('bagHandle', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -100
});
// Store fish in bag
self.fishInventory = [];
self.addFish = function (fishType, points) {
self.fishInventory.push({
type: fishType,
points: points,
price: Math.floor(points / 2)
});
};
self.down = function () {
showInventory();
};
return self;
});
var Bait = Container.expand(function (type) {
var self = Container.call(this);
self.baitType = type || 'basic';
var baitAsset;
if (self.baitType === 'basic') {
baitAsset = self.attachAsset('basicBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 10;
self.catchChance = 1.0;
self.name = 'Basic Bait';
} else if (self.baitType === 'premium') {
baitAsset = self.attachAsset('premiumBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 25;
self.catchChance = 1.5;
self.name = 'Premium Bait';
} else if (self.baitType === 'golden') {
baitAsset = self.attachAsset('goldenBait', {
anchorX: 0.5,
anchorY: 0.5
});
self.price = 50;
self.catchChance = 2.0;
self.name = 'Golden Bait';
}
return self;
});
var Boat = Container.expand(function () {
var self = Container.call(this);
// Create boat hull
var boatHull = self.attachAsset('boat', {
anchorX: 0.5,
anchorY: 0.5
});
// Array to hold caught fish
self.caughtFish = [];
// Boat movement properties
self.speed = 3;
self.isMoving = false;
self.targetX = 0;
// Method to add fish to boat
self.addFish = function (fish) {
// Position fish in boat
var fishInBoat = self.addChild(fish);
var offset = self.caughtFish.length * 25 - 50; // Spread fish across boat
fishInBoat.x = offset;
fishInBoat.y = -20;
fishInBoat.scaleX = 0.6;
fishInBoat.scaleY = 0.6;
self.caughtFish.push(fishInBoat);
};
// Method to move boat to target position
self.moveTo = function (targetX) {
if (targetX < 100) targetX = 100;
if (targetX > 1948) targetX = 1948;
self.targetX = targetX;
self.isMoving = true;
};
self.update = function () {
if (self.isMoving) {
var distance = self.targetX - self.x;
if (Math.abs(distance) > self.speed) {
self.x += distance > 0 ? self.speed : -self.speed;
} else {
self.x = self.targetX;
self.isMoving = false;
}
}
};
return self;
});
var Bubble = Container.expand(function () {
var self = Container.call(this);
// Random bubble type
var bubbleTypes = ['bubble1', 'bubble2', 'bubble3'];
var bubbleType = bubbleTypes[Math.floor(Math.random() * bubbleTypes.length)];
var bubbleGraphics = self.attachAsset(bubbleType, {
anchorX: 0.5,
anchorY: 0.5
});
// Bubble properties
self.speed = 0.5 + Math.random() * 1.5; // Slow floating speed
self.sideSpeed = (Math.random() - 0.5) * 0.5; // Gentle side drift
self.alpha = 0.6 + Math.random() * 0.4; // Semi-transparent
self.update = function () {
// Float upward slowly
self.y -= self.speed;
// Gentle side movement
self.x += self.sideSpeed;
// Remove when reaching surface
if (self.y < waterSurface) {
self.destroy();
}
// Keep within lake bounds horizontally
if (self.x < 50) {
self.x = 50;
self.sideSpeed = Math.abs(self.sideSpeed);
}
if (self.x > 1998) {
self.x = 1998;
self.sideSpeed = -Math.abs(self.sideSpeed);
}
};
return self;
});
var Cabin = Container.expand(function () {
var self = Container.call(this);
// Cabin structure
var cabin = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 1
});
var roof = self.attachAsset('cabinRoof', {
anchorX: 0.5,
anchorY: 1,
y: -180
});
var door = self.attachAsset('cabinDoor', {
anchorX: 0.5,
anchorY: 1,
y: -50
});
// Bait displays
self.basicBaitDisplay = self.addChild(new Bait('basic'));
self.basicBaitDisplay.x = -60;
self.basicBaitDisplay.y = -140;
self.premiumBaitDisplay = self.addChild(new Bait('premium'));
self.premiumBaitDisplay.x = -20;
self.premiumBaitDisplay.y = -140;
self.goldenBaitDisplay = self.addChild(new Bait('golden'));
self.goldenBaitDisplay.x = 20;
self.goldenBaitDisplay.y = -140;
// Make baits interactive
self.basicBaitDisplay.down = function () {
purchaseBait('basic');
};
self.premiumBaitDisplay.down = function () {
purchaseBait('premium');
};
self.goldenBaitDisplay.down = function () {
purchaseBait('golden');
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Random cloud type
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5
});
// Cloud properties
self.speed = 0.3 + Math.random() * 0.5; // Slow floating speed
self.alpha = 0.7 + Math.random() * 0.3; // Semi-transparent
self.originalScale = 0.8 + Math.random() * 0.4; // Random size
cloudGraphics.scaleX = self.originalScale;
cloudGraphics.scaleY = self.originalScale;
// Gentle floating animation properties
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.01 + Math.random() * 0.02;
self.floatRange = 10 + Math.random() * 15;
self.update = function () {
// Move cloud slowly across sky
self.x += self.speed;
// Gentle floating motion
self.floatOffset += self.floatSpeed;
self.y += Math.sin(self.floatOffset) * 0.2;
// Reset cloud position when it goes off screen
if (self.x > 2200) {
self.x = -200;
// Randomize properties when resetting
self.speed = 0.3 + Math.random() * 0.5;
self.alpha = 0.7 + Math.random() * 0.3;
}
};
return self;
});
var Fish = Container.expand(function (type) {
var self = Container.call(this);
self.fishType = type || 'small';
var fishAsset;
if (self.fishType === 'small') {
fishAsset = self.attachAsset('smallFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1 + Math.random() * 2;
self.points = 10;
} else if (self.fishType === 'medium') {
fishAsset = self.attachAsset('mediumFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5 + Math.random() * 1.5;
self.points = 25;
} else if (self.fishType === 'tropical') {
fishAsset = self.attachAsset('tropicalFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5 + Math.random() * 2;
self.points = 35;
} else if (self.fishType === 'rare') {
fishAsset = self.attachAsset('rareFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.2 + Math.random() * 0.8;
self.points = 100;
} else if (self.fishType === 'angel') {
fishAsset = self.attachAsset('angelFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.8 + Math.random() * 1.2;
self.points = 45;
} else if (self.fishType === 'clown') {
fishAsset = self.attachAsset('clownFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.2 + Math.random() * 1.8;
self.points = 30;
} else if (self.fishType === 'surgeon') {
fishAsset = self.attachAsset('surgeonFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.0 + Math.random() * 1.5;
self.points = 40;
} else if (self.fishType === 'parrot') {
fishAsset = self.attachAsset('parrotFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.7 + Math.random() * 1.3;
self.points = 55;
} else if (self.fishType === 'butterfly') {
fishAsset = self.attachAsset('butterflyFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.3 + Math.random() * 1.7;
self.points = 38;
} else if (self.fishType === 'mandarin') {
fishAsset = self.attachAsset('mandarin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.9 + Math.random() * 1.4;
self.points = 65;
} else if (self.fishType === 'lion') {
fishAsset = self.attachAsset('lionFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.4 + Math.random() * 0.9;
self.points = 80;
} else if (self.fishType === 'grouper') {
fishAsset = self.attachAsset('grouper', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.2 + Math.random() * 0.7;
self.points = 120;
} else {
fishAsset = self.attachAsset('largeFish', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.3 + Math.random() * 1;
self.points = 50;
}
self.directionX = Math.random() > 0.5 ? 1 : -1;
self.directionY = (Math.random() - 0.5) * 0.5;
self.startX = self.x;
self.swimDistance = 300 + Math.random() * 400;
self.update = function () {
self.x += self.speed * self.directionX;
self.y += self.speed * self.directionY;
// Turn around if swam too far
if (Math.abs(self.x - self.startX) > self.swimDistance) {
self.directionX *= -1;
fishAsset.scaleX = self.directionX;
self.startX = self.x;
}
// Keep fish in water bounds
if (self.x < 50) {
self.x = 50;
self.directionX = 1;
fishAsset.scaleX = 1;
}
if (self.x > 1998) {
self.x = 1998;
self.directionX = -1;
fishAsset.scaleX = -1;
}
if (self.y < waterSurface + 100) {
self.y = waterSurface + 100;
self.directionY = Math.abs(self.directionY);
}
if (self.y > waterSurface + 1200) {
self.y = waterSurface + 1200;
self.directionY = -Math.abs(self.directionY);
}
};
return self;
});
var FishingLine = Container.expand(function () {
var self = Container.call(this);
self.lineGraphics = self.attachAsset('fishingLine', {
anchorX: 0.5,
anchorY: 0
});
self.hook = self.addChild(new Container());
self.hookGraphics = self.hook.attachAsset('hook', {
anchorX: 0.5,
anchorY: 0.5
});
self.bobber = self.addChild(new Container());
self.bobberGraphics = self.bobber.attachAsset('bobber', {
anchorX: 0.5,
anchorY: 0.5
});
self.isVisible = false;
self.visible = false;
self.showLine = function (startX, startY, endX, endY) {
self.x = startX;
self.y = startY;
var distance = Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));
var angle = Math.atan2(endY - startY, endX - startX);
self.lineGraphics.height = distance;
self.lineGraphics.rotation = angle + Math.PI / 2;
self.hook.x = 0;
self.hook.y = distance;
self.bobber.x = 0;
self.bobber.y = distance - 20;
self.isVisible = true;
self.visible = true;
};
self.hideLine = function () {
self.isVisible = false;
self.visible = false;
};
return self;
});
var Pebble = Container.expand(function () {
var self = Container.call(this);
var pebbleGraphics = self.attachAsset('pebble', {
anchorX: 0.5,
anchorY: 0.5
});
// Random tint for variation
var grayTones = [0x8B7355, 0x696969, 0x708090, 0x778899];
pebbleGraphics.tint = grayTones[Math.floor(Math.random() * grayTones.length)];
// Subtle movement properties
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.005 + Math.random() * 0.01;
self.maxSway = 2 + Math.random() * 3;
self.update = function () {
self.waveOffset += self.waveSpeed;
var sway = Math.sin(self.waveOffset) * self.maxSway;
pebbleGraphics.x = sway * 0.05; // Very minimal horizontal movement
};
return self;
});
var Rock = Container.expand(function (size) {
var self = Container.call(this);
self.rockSize = size || 'small';
var rockAsset = self.rockSize === 'large' ? 'largeRock' : 'smallRock';
var rockGraphics = self.attachAsset(rockAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Random tint and scale for variation
var rockTones = [0x696969, 0x2F4F4F, 0x708090, 0x556B2F];
rockGraphics.tint = rockTones[Math.floor(Math.random() * rockTones.length)];
rockGraphics.scaleX = 0.8 + Math.random() * 0.4;
rockGraphics.scaleY = 0.8 + Math.random() * 0.4;
// Very subtle movement for rocks
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.003 + Math.random() * 0.005;
self.update = function () {
self.waveOffset += self.waveSpeed;
// Barely visible movement for realism
rockGraphics.alpha = 0.9 + Math.sin(self.waveOffset) * 0.1;
};
return self;
});
var RodShop = Container.expand(function () {
var self = Container.call(this);
// Shop background
var shopBg = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 3
});
self.visible = false;
self.isOpen = false;
// Create title
var titleText = new Text2('Rod Shop', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -300;
self.addChild(titleText);
// Create 8 rod options
self.rodOptions = [];
for (var i = 0; i < 8; i++) {
var rodContainer = self.addChild(new Container());
rodContainer.x = i % 4 * 200 - 300;
rodContainer.y = Math.floor(i / 4) * 150 - 100;
// Rod graphic
var rodGraphic = rodContainer.attachAsset('fishingRod', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
// Rod level text
var levelText = new Text2('Level ' + (i + 1), {
size: 30,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.y = 60;
rodContainer.addChild(levelText);
// Rod price text
var price = 500 + i * 200;
var priceText = new Text2('$' + price, {
size: 35,
fill: 0xFFD700
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 90;
rodContainer.addChild(priceText);
self.rodOptions.push({
container: rodContainer,
level: i + 1,
price: price,
priceText: priceText
});
// Make rod clickable
rodContainer.rodIndex = i;
rodContainer.down = function () {
var targetLevel = this.rodIndex + 1;
var rodPrice = 500 + this.rodIndex * 200;
if (targetLevel === currentRodLevel + 1 && playerMoney >= rodPrice) {
playerMoney -= rodPrice;
storage.playerMoney = playerMoney;
currentRodLevel = targetLevel;
storage.rodLevel = currentRodLevel;
moneyTxt.setText('Money: ' + playerMoney);
if (currentRodLevel >= 8) {
rodLevelTxt.setText('Rod Level: Maks.');
} else {
rodLevelTxt.setText('Rod Level: ' + currentRodLevel);
}
// Clear existing fish and spawn new types
for (var f = fish.length - 1; f >= 0; f--) {
game.removeChild(fish[f]);
fish.splice(f, 1);
}
for (var newF = 0; newF < 8; newF++) {
spawnFish();
}
self.close();
instructionTxt.setText('Rod upgraded to level ' + currentRodLevel + '!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
} else if (targetLevel !== currentRodLevel + 1) {
instructionTxt.setText('Must buy rods in order!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
} else {
instructionTxt.setText('Not enough money for this rod!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
}
};
}
// Close button
var closeBtn = self.addChild(LK.getAsset('cabinDoor', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 250,
scaleX: 0.8,
scaleY: 0.5
}));
var closeText = new Text2('Close', {
size: 40,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.y = 250;
self.addChild(closeText);
closeBtn.down = function () {
self.close();
};
self.open = function () {
self.visible = true;
self.isOpen = true;
game.isPaused = true;
};
self.close = function () {
self.visible = false;
self.isOpen = false;
game.isPaused = false;
};
return self;
});
var Seaweed = Container.expand(function () {
var self = Container.call(this);
var seaweedGraphics = self.attachAsset('seaweed', {
anchorX: 0.5,
anchorY: 1
});
self.waveOffset = Math.random() * Math.PI * 2;
self.waveSpeed = 0.02 + Math.random() * 0.03;
self.maxSway = 15 + Math.random() * 10;
self.update = function () {
self.waveOffset += self.waveSpeed * 0.3; // Slower wave movement
var sway = Math.sin(self.waveOffset) * self.maxSway * 0.2; // Much gentler sway
seaweedGraphics.rotation = sway * 0.02; // Minimal rotation
seaweedGraphics.x = sway * 0.1; // Minimal horizontal movement
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
// Shop background
var shopBg = self.attachAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 2.5
});
self.visible = false;
self.isOpen = false;
self.fishingRods = [];
for (var i = 0; i < 15; i++) {
self.fishingRods.push({
level: i + 1,
price: 50 + i * 25,
catchBonus: 1 + i * 0.1
});
}
// Create current rod display
var currentRodDisplay = self.addChild(LK.getAsset('fishingRod', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: -100,
scaleX: 0.5,
scaleY: 0.5
}));
var currentRodText = new Text2('Current Rod: Level ' + currentRodLevel, {
size: 30,
fill: 0xFFFFFF
});
currentRodText.anchor.set(0.5, 0.5);
currentRodText.x = 100;
currentRodText.y = -50;
self.addChild(currentRodText);
self.open = function () {
self.visible = true;
self.isOpen = true;
game.isPaused = true;
// Update current rod display
currentRodText.setText('Current Rod: Level ' + currentRodLevel);
};
self.close = function () {
self.visible = false;
self.isOpen = false;
game.isPaused = false;
};
self.down = function (x, y) {
if (x > 0) {
// Right side - buy rods and bait
var rodIndex = Math.floor((y + 200) / 50);
if (rodIndex >= 0 && rodIndex < 15) {
var rod = self.fishingRods[rodIndex];
if (playerMoney >= rod.price) {
playerMoney -= rod.price;
storage.playerMoney = playerMoney;
currentRodLevel = rod.level;
storage.rodLevel = currentRodLevel;
moneyTxt.setText('Money: ' + playerMoney);
}
}
} else {
// Left side - sell fish
if (inventoryBag.fishInventory.length > 0) {
var fish = inventoryBag.fishInventory.pop();
playerMoney += fish.price;
storage.playerMoney = playerMoney;
moneyTxt.setText('Money: ' + playerMoney);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var waterSurface = 600;
var fish = [];
var isCasting = false;
var isReeling = false;
var castStartX = 0;
var castStartY = 0;
var hookedFish = null;
var reelProgress = 0;
var clickCount = 0;
var lastClickX = 0;
var lastClickY = 0;
var targetCastX = 0;
var targetCastY = 0;
var clickTimeout = null;
// Bait system variables
var playerMoney = storage.playerMoney || 100;
var currentBait = 'basic';
var baitCount = {
basic: storage.basicBait || 5,
premium: storage.premiumBait || 0,
golden: storage.goldenBait || 0
};
var currentRodLevel = storage.rodLevel || 1;
var inventoryOpen = false;
var shopOpen = false;
// Create water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 0,
x: 0,
y: waterSurface
}));
// Create seaweed patches at bottom corners of the lake
var seaweeds = [];
// Create bubbles array
var bubbles = [];
// Create clouds array
var clouds = [];
// Create pebbles and rocks arrays
var pebbles = [];
var rocks = [];
// Bottom left corner seaweed - more dense
for (var s = 0; s < 15; s++) {
var seaweed = game.addChild(new Seaweed());
seaweed.x = 50 + Math.random() * 400;
seaweed.y = waterSurface + 1000 + Math.random() * 500;
seaweeds.push(seaweed);
}
// Bottom right corner seaweed - more dense
for (var s = 0; s < 15; s++) {
var seaweed = game.addChild(new Seaweed());
seaweed.x = 1650 + Math.random() * 400;
seaweed.y = waterSurface + 1000 + Math.random() * 500;
seaweeds.push(seaweed);
}
// Create boat
var boat = game.addChild(new Boat());
boat.x = 1024;
boat.y = waterSurface - 30;
// Create player on boat
var player = boat.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -30
}));
// Create fishing rod on boat
var fishingRod = boat.addChild(LK.getAsset('fishingRod', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -20
}));
// Create fishing line
var fishingLine = game.addChild(new FishingLine());
// Create cabin on the right side
var cabin = game.addChild(new Cabin());
cabin.x = 1600;
cabin.y = waterSurface;
// Create inventory bag at bottom of screen
var inventoryBag = game.addChild(new Bag());
inventoryBag.x = 1024;
inventoryBag.y = 2732;
// Create shop interface
var shop = game.addChild(new Shop());
shop.x = 1024;
shop.y = 1366;
// Create rod shop interface
var rodShop = game.addChild(new RodShop());
rodShop.x = 1024;
rodShop.y = 1366;
// Create UI
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
// Fish catch notification
var catchNotificationTxt = new Text2('', {
size: 80,
fill: 0xFFD700
});
catchNotificationTxt.anchor.set(0.5, 0.5);
catchNotificationTxt.x = 1024;
catchNotificationTxt.y = 1366;
catchNotificationTxt.visible = false;
game.addChild(catchNotificationTxt);
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionTxt = new Text2('Tap on lake to cast your line!', {
size: 40,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0);
instructionTxt.y = 80;
LK.gui.top.addChild(instructionTxt);
var moneyTxt = new Text2('Money: ' + playerMoney, {
size: 50,
fill: 0xFFD700
});
moneyTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(moneyTxt);
var baitTxt = new Text2('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')', {
size: 40,
fill: 0xFFFFFF
});
baitTxt.anchor.set(1, 0);
baitTxt.y = 60;
LK.gui.topRight.addChild(baitTxt);
var cabinInfoTxt = new Text2('Visit cabin to buy baits!\nBasic: 10 Premium: 25 Golden: 50', {
size: 30,
fill: 0xFFFFFF
});
cabinInfoTxt.anchor.set(0, 1);
cabinInfoTxt.y = -20;
LK.gui.bottomLeft.addChild(cabinInfoTxt);
var rodLevelTxt = new Text2(currentRodLevel >= 8 ? 'Rod Level: Maks.' : 'Rod Level: ' + currentRodLevel, {
size: 40,
fill: 0xFFD700
});
rodLevelTxt.anchor.set(0, 0);
rodLevelTxt.y = 120;
LK.gui.topLeft.addChild(rodLevelTxt);
// Rod upgrade button
var rodUpgradeBtn = new Text2('🎣 Upgrade Rod', {
size: 35,
fill: 0xFFFFFF
});
rodUpgradeBtn.anchor.set(0, 0);
rodUpgradeBtn.y = 170;
LK.gui.topLeft.addChild(rodUpgradeBtn);
// Purchase bait function
function purchaseBait(baitType) {
var bait = new Bait(baitType);
if (playerMoney >= bait.price) {
playerMoney -= bait.price;
baitCount[baitType] += 1;
// Save to storage
storage.playerMoney = playerMoney;
storage[baitType + 'Bait'] = baitCount[baitType];
// Update UI
moneyTxt.setText('Money: ' + playerMoney);
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
instructionTxt.setText('Bought ' + bait.name + '!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 1500);
} else {
instructionTxt.setText('Not enough money!');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 1500);
}
}
// Inventory display elements array for proper cleanup
var inventoryDisplayElements = [];
// Show inventory function
function showInventory() {
if (inventoryOpen) return;
inventoryOpen = true;
// Clear previous display elements
inventoryDisplayElements = [];
// Create inventory display
var inventoryBg = game.addChild(LK.getAsset('cabin', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 4,
scaleY: 3
}));
inventoryDisplayElements.push(inventoryBg);
var inventoryTitle = new Text2('Fish Inventory', {
size: 60,
fill: 0xFFFFFF
});
inventoryTitle.anchor.set(0.5, 0.5);
inventoryTitle.x = 1024;
inventoryTitle.y = 800;
game.addChild(inventoryTitle);
inventoryDisplayElements.push(inventoryTitle);
// Display only fish names in bag
for (var i = 0; i < inventoryBag.fishInventory.length; i++) {
var fish = inventoryBag.fishInventory[i];
var fishText = new Text2(fish.type.charAt(0).toUpperCase() + fish.type.slice(1) + ' Fish', {
size: 40,
fill: 0xFFFFFF
});
fishText.anchor.set(0.5, 0.5);
fishText.x = 1024;
fishText.y = 900 + i * 60;
game.addChild(fishText);
inventoryDisplayElements.push(fishText);
}
// Close button
var closeBtn = game.addChild(LK.getAsset('bag', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800
}));
inventoryDisplayElements.push(closeBtn);
closeBtn.down = function () {
// Remove all inventory display elements
for (var i = 0; i < inventoryDisplayElements.length; i++) {
game.removeChild(inventoryDisplayElements[i]);
}
inventoryDisplayElements = [];
inventoryOpen = false;
};
}
// Show shop function
function showShop() {
if (shopOpen) return;
shopOpen = true;
shop.open();
}
// Switch bait function
function switchBait() {
var baitTypes = ['basic', 'premium', 'golden'];
var currentIndex = baitTypes.indexOf(currentBait);
for (var i = 1; i <= baitTypes.length; i++) {
var nextIndex = (currentIndex + i) % baitTypes.length;
var nextBait = baitTypes[nextIndex];
if (baitCount[nextBait] > 0) {
currentBait = nextBait;
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
break;
}
}
}
// Fish types available by rod level
var fishTypesByLevel = {
1: ['tropical'],
2: ['tropical', 'clown'],
3: ['tropical', 'clown', 'butterfly'],
4: ['tropical', 'angel', 'clown', 'butterfly'],
5: ['tropical', 'large', 'angel', 'surgeon'],
6: ['tropical', 'large', 'parrot', 'angel', 'surgeon'],
7: ['tropical', 'large', 'rare', 'parrot', 'mandarin', 'lion'],
8: ['tropical', 'large', 'rare', 'mandarin', 'lion', 'grouper']
};
// Spawn initial fish
function spawnFish() {
var availableFishTypes = fishTypesByLevel[currentRodLevel] || ['small'];
var fishType = availableFishTypes[Math.floor(Math.random() * availableFishTypes.length)];
var newFish = game.addChild(new Fish(fishType));
newFish.x = Math.random() * 1948 + 50;
newFish.y = waterSurface + 150 + Math.random() * 1000;
newFish.startX = newFish.x;
fish.push(newFish);
}
// Spawn initial fish
for (var i = 0; i < 8; i++) {
spawnFish();
}
// Create clouds in the sky
for (var c = 0; c < 6; c++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = 100 + Math.random() * 300; // Position clouds in sky area
clouds.push(cloud);
}
// Create pebbles at the very bottom of the lake
for (var p = 0; p < 40; p++) {
var pebble = game.addChild(new Pebble());
pebble.x = 80 + Math.random() * 1888; // Spread across lake width
pebble.y = waterSurface + 1500 + Math.random() * 100; // Very bottom area only
pebbles.push(pebble);
}
// Create small rocks at the very bottom of lake
for (var r = 0; r < 15; r++) {
var smallRock = game.addChild(new Rock('small'));
smallRock.x = 100 + Math.random() * 1848;
smallRock.y = waterSurface + 1450 + Math.random() * 150; // Very bottom area
rocks.push(smallRock);
}
// Create large rocks at the very bottom of lake
for (var lr = 0; lr < 8; lr++) {
var largeRock = game.addChild(new Rock('large'));
largeRock.x = 150 + Math.random() * 1748;
largeRock.y = waterSurface + 1400 + Math.random() * 200; // Very bottom area
rocks.push(largeRock);
}
// Cast fishing line
function castLine(targetX, targetY) {
if (isCasting || isReeling) return;
if (baitCount[currentBait] <= 0) {
instructionTxt.setText('No bait! Visit the cabin to buy more.');
LK.setTimeout(function () {
instructionTxt.setText('Tap on lake to cast your line!');
}, 2000);
return;
}
isCasting = true;
// Use bait
baitCount[currentBait] -= 1;
storage[currentBait + 'Bait'] = baitCount[currentBait];
baitTxt.setText('Bait: ' + currentBait.charAt(0).toUpperCase() + currentBait.slice(1) + ' (' + baitCount[currentBait] + ')');
var rodTipX = boat.x + fishingRod.x;
var rodTipY = boat.y + fishingRod.y - 180;
fishingLine.showLine(rodTipX, rodTipY, targetX, targetY);
LK.getSound('cast').play();
// Animate casting
tween(fishingRod, {
rotation: Math.PI / 6
}, {
duration: 200
});
LK.setTimeout(function () {
LK.getSound('splash').play();
// Check if hook is near any fish
checkForFish(targetX, targetY);
LK.setTimeout(function () {
if (!hookedFish) {
reelIn();
}
}, 2000);
}, 300);
}
// Check if hook caught a fish
function checkForFish(hookX, hookY) {
var bait = new Bait(currentBait);
var catchRadius = 60 * bait.catchChance;
for (var i = 0; i < fish.length; i++) {
var currentFish = fish[i];
var distance = Math.sqrt((currentFish.x - hookX) * (currentFish.x - hookX) + (currentFish.y - hookY) * (currentFish.y - hookY));
if (distance < catchRadius) {
// Better bait increases chance of catching rare fish
var catchChance = Math.random() * bait.catchChance;
if (catchChance > 0.5 || currentFish.fishType !== 'rare') {
hookedFish = currentFish;
reelProgress = 0;
isReeling = true;
LK.getSound('catch').play();
instructionTxt.setText('Tap rapidly to reel in!');
// Flash the hooked fish
LK.effects.flashObject(hookedFish, 0xFFFF00, 500);
break;
}
}
}
}
// Reel in the line
function reelIn() {
if (hookedFish) {
// Increase score
LK.setScore(LK.getScore() + hookedFish.points);
scoreTxt.setText('Score: ' + LK.getScore());
// Give money based on fish value
var moneyEarned = Math.floor(hookedFish.points / 2);
playerMoney += moneyEarned;
storage.playerMoney = playerMoney;
moneyTxt.setText('Money: ' + playerMoney);
// Show fish catch notification
var fishPrice = Math.floor(hookedFish.points / 2);
catchNotificationTxt.setText(hookedFish.fishType.charAt(0).toUpperCase() + hookedFish.fishType.slice(1) + ' Fish - $' + fishPrice);
catchNotificationTxt.visible = true;
// Hide notification after 4 seconds
LK.setTimeout(function () {
catchNotificationTxt.visible = false;
}, 4000);
// Add fish directly to bag (don't add to boat)
var caughtFish = null;
for (var i = fish.length - 1; i >= 0; i--) {
if (fish[i] === hookedFish) {
caughtFish = fish[i];
fish.splice(i, 1);
break;
}
}
if (caughtFish) {
// Remove fish from game container
game.removeChild(caughtFish);
// Add to inventory bag directly (skip boat)
inventoryBag.addFish(caughtFish.fishType, caughtFish.points);
}
// Spawn new fish
spawnFish();
hookedFish = null;
reelProgress = 0;
}
// Reset fishing state
fishingLine.hideLine();
tween(fishingRod, {
rotation: 0
}, {
duration: 300
});
isCasting = false;
isReeling = false;
instructionTxt.setText('Tap on lake to cast your line!');
}
// Game events
game.down = function (x, y, obj) {
if (isReeling && hookedFish) {
reelProgress += 20;
if (reelProgress >= 100) {
reelIn();
}
return;
}
// Check if clicking on rod upgrade button (top left area)
if (x >= 0 && x <= 200 && y >= 170 && y <= 210) {
if (!rodShop.isOpen) {
rodShop.open();
}
return;
}
// Check if boat is near cabin for shop interaction
if (!isCasting && !isReeling && Math.abs(boat.x - cabin.x) < 100 && x > 1400 && x < 1800 && y < waterSurface + 100) {
showShop();
return;
}
// Switch bait on tap (when not casting or reeling)
if (!isCasting && !isReeling && x > 1500) {
switchBait();
return;
}
if (!isCasting && !isReeling) {
// Check if click is in water area (entire lake surface)
if (y > waterSurface && x >= 0 && x <= 2048) {
// Cast line directly to clicked location
castLine(x, y);
} else {
// Move boat towards clicked position when clicking anywhere else
boat.moveTo(x);
}
}
};
game.up = function (x, y, obj) {
// Removed drag-to-cast functionality - now using 3-tap system
};
// Timer-based fish spawning system
var fishSpawnTimer = 0;
var timedFishSpawn = {
timer: 0,
interval: 3600,
// 60 seconds at 60fps
fishTypeIndex: 0
};
game.update = function () {
// Update boat
boat.update();
// Update all fish
for (var i = 0; i < fish.length; i++) {
fish[i].update();
}
// Update seaweed wave movement
for (var s = 0; s < seaweeds.length; s++) {
seaweeds[s].update();
}
// Update clouds floating in sky
for (var c = 0; c < clouds.length; c++) {
clouds[c].update();
}
// Update pebbles on lake bottom
for (var p = 0; p < pebbles.length; p++) {
pebbles[p].update();
}
// Update rocks on lake bottom
for (var r = 0; r < rocks.length; r++) {
rocks[r].update();
}
// Update bubbles
for (var b = bubbles.length - 1; b >= 0; b--) {
var bubble = bubbles[b];
bubble.update();
// Remove destroyed bubbles from array
if (bubble.y < waterSurface) {
game.removeChild(bubble);
bubbles.splice(b, 1);
}
}
// Spawn bubbles randomly from lake bottom
if (Math.random() < 0.02) {
// 2% chance each frame
var newBubble = game.addChild(new Bubble());
newBubble.x = 100 + Math.random() * 1848; // Random x position in lake
newBubble.y = waterSurface + 1300 + Math.random() * 200; // Near bottom
bubbles.push(newBubble);
}
// Spawn new fish occasionally (reduced frequency)
fishSpawnTimer++;
if (fishSpawnTimer > 1200 && fish.length < 8) {
// Every 20 seconds at 60fps, reduced max fish count
spawnFish();
fishSpawnTimer = 0;
}
// Timed fish spawning - spawn all fish types every minute
timedFishSpawn.timer++;
if (timedFishSpawn.timer >= timedFishSpawn.interval) {
var availableFishTypes = fishTypesByLevel[currentRodLevel] || ['tropical'];
// Spawn one of each fish type available for current rod level
for (var f = 0; f < availableFishTypes.length; f++) {
var fishType = availableFishTypes[f];
var newFish = game.addChild(new Fish(fishType));
newFish.x = Math.random() * 1948 + 50;
newFish.y = waterSurface + 150 + Math.random() * 1000;
newFish.startX = newFish.x;
fish.push(newFish);
}
timedFishSpawn.timer = 0;
}
// Move hooked fish towards rod
if (hookedFish && isReeling) {
var targetX = boat.x + fishingRod.x;
var targetY = boat.y + fishingRod.y - 100;
var moveSpeed = 0.02;
hookedFish.x += (targetX - hookedFish.x) * moveSpeed;
hookedFish.y += (targetY - hookedFish.y) * moveSpeed;
// Auto-reel if fish gets close enough
var distance = Math.sqrt((hookedFish.x - targetX) * (hookedFish.x - targetX) + (hookedFish.y - targetY) * (hookedFish.y - targetY));
if (distance < 50) {
reelIn();
}
}
};
// Play ambient music
LK.playMusic('ambience');
yeşil balık. In-Game asset. 2d. High contrast. No shadows
gri balık sinirli. In-Game asset. 2d. High contrast. No shadows
olta. In-Game asset. 2d. High contrast. No shadows
mavi hamsi. In-Game asset. 2d. High contrast. No shadows
sarı balık. In-Game asset. 2d. High contrast. No shadows
gri büyük balık. In-Game asset. 2d. High contrast. No shadows
kayık. In-Game asset. 2d. High contrast. No shadows
çanta. In-Game asset. 2d. High contrast. No shadows
çatısız kulübe ama dümdüz ekrana bakan. In-Game asset. 2d. High contrast. No shadows
ahşap çatı ama dümdüz ekrana bakan. In-Game asset. 2d. High contrast. No shadows
palyaço balığı. In-Game asset. 2d. High contrast. No shadows
melek balığı. In-Game asset. 2d. High contrast. No shadows
yosun. In-Game asset. 2d. High contrast. No shadows
baloncuk açık renk. In-Game asset. 2d. High contrast. No shadows
bulut. In-Game asset. 2d. High contrast. No shadows
balıkçı ama elinde hiç bir şey olmasın. In-Game asset. 2d. High contrast. No shadows
çakıl taşı. In-Game asset. 2d. High contrast. No shadows