/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function (onPress, config) {
var self = Container.call(this);
self.onPress = onPress;
self.isPressed = false;
self.id = config.id;
self.disable = false;
if (config.size) {
var buttonWidth = config.size;
var buttonHeight = config.size;
} else {
var buttonWidth = config.width;
var buttonHeight = config.height;
}
self.textSize = config.textSize | Math.max(buttonWidth, buttonHeight) / 5;
// Use custom background if provided, otherwise use default
var backgroundAsset = config.background || 'buttonBackground';
var backgroundPressedAsset = backgroundAsset + 'Pressed';
var background = self.attachAsset(backgroundAsset, {
width: buttonWidth,
height: buttonHeight
});
var backgroundPressed = self.attachAsset(backgroundPressedAsset, {
visible: false,
width: buttonWidth,
height: buttonHeight
});
self.text = config.text || "";
var buttonText = new Text2(self.text, {
size: self.textSize,
fill: 0xFFFFFF,
weight: 700
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = buttonWidth / 2;
buttonText.y = buttonHeight / 2 - (backgroundAsset === 'buttonBackground' ? 0 : 23);
self.addChild(buttonText);
self.icon = config.icon;
if (self.icon) {
var buttonIcon = self.attachAsset(self.icon, {});
}
self.down = function (x, y, obj) {
if (self.disable) {
return;
}
LK.getSound('click').play();
if (self.onPress) {
// If onPress return false, then the button won't do the animation
if (!self.onPress(self)) {
return;
}
}
self.isPressed = true;
background.visible = false;
backgroundPressed.visible = true;
currentButton = self;
if (buttonIcon) {
buttonIcon.y = 46;
}
buttonText.y = buttonHeight / 2 + 23;
};
self.up = function (x, y, obj) {
self.isPressed = false;
background.visible = true;
backgroundPressed.visible = false;
if (buttonIcon) {
buttonIcon.y = 0;
}
buttonText.y = buttonHeight / 2 - 23;
};
self.setDisable = function (disable) {
self.disable = disable;
self.tint = disable ? 0xAAAAAA : 0xFFFFFF;
};
return self;
});
// ButtonShop width and height is fixed.
var ButtonShop = Button.expand(function (config) {
var self = Button.call(this, null, {
background: 'rectButtonBackground',
width: 818,
height: 335
});
self.config = config;
// Initialize shop level in gameStatus if not exists
if (!gameStatus.shopLevel[config.value]) {
gameStatus.shopLevel[config.value] = 1;
}
// Get current cost based on level
self.calculateCost = function () {
var cost = config.baseCost;
for (var i = 1; i < gameStatus.shopLevel[config.value]; i++) {
if (config.calculateCost) {
cost = config.calculateCost(i);
} else {
cost = Math.ceil(cost * 1.5);
}
}
return cost;
};
// Get current value based on level
self.calculateValue = function () {
var isMaxLevel = config.maxLevel && gameStatus.shopLevel[config.value] >= config.maxLevel;
var isMaxValue = config.maxValue && gameStatus[config.value] >= config.maxValue;
if (config.calculateValue) {
return config.calculateValue(gameStatus.shopLevel[config.value], isMaxLevel || isMaxValue);
}
return gameStatus.shopLevel[config.value];
};
// Create label text
self.labelText = new Text2(config.label + " LV: ", {
size: 60,
fill: 0xFFFFFF,
weight: 700
});
self.labelText.anchor.set(0.5, 0.5);
self.labelText.x = 818 / 2;
self.addChild(self.labelText);
// Calculate initial cost before creating cost text
self.cost = self.calculateCost();
// Create cost text
self.costText = new Text2("Cost: " + formatMoney(self.cost), {
size: 100,
fill: 0xC7FFC7,
weight: 700
});
self.costText.anchor.set(0.5, 0.5);
self.costText.x = 818 / 2;
self.addChild(self.costText);
self.updateDisplay = function () {
var isMaxLevel = config.maxLevel && gameStatus.shopLevel[config.value] >= config.maxLevel;
var isMaxValue = config.maxValue && gameStatus[config.value] >= config.maxValue;
if (isMaxLevel || isMaxValue) {
self.costText.setText("MAX LEVEL");
self.labelText.setText(config.label + ": MAX");
} else {
var costText = formatMoney(self.cost);
self.costText.setText("Cost: " + costText);
self.labelText.setText(config.label + ": LV " + gameStatus.shopLevel[config.value]);
}
};
self.onPress = function () {
var currentCost = self.cost;
if (gameStatus.money >= currentCost) {
gameStatus.save();
gameStatus.money -= currentCost;
gameStatus.shopLevel[config.value]++;
// Update the game status value based on the new level
gameStatus[config.value] = self.calculateValue();
self.cost = self.calculateCost();
console.log(gameStatus[config.value]);
gameStatus.updateMoney();
self.updateDisplay();
// Check if we've reached max level or max value and disable button
var isMaxLevel = config.maxLevel && gameStatus.shopLevel[config.value] >= config.maxLevel;
var isMaxValue = config.maxValue && gameStatus[config.value] >= config.maxValue;
if (isMaxLevel || isMaxValue) {
self.setDisable(true);
}
}
return true;
};
self.update = function () {
if (self.isPressed) {
self.labelText.y = 335 / 2 - 70 + 28;
self.costText.y = 335 / 2 + 40 + 28;
} else {
self.labelText.y = 335 / 2 - 70;
self.costText.y = 335 / 2 + 40;
}
};
// Initialize game status value
gameStatus[config.value] = self.calculateValue();
// Check if already at max level/value and disable if needed
var isMaxLevel = config.maxLevel && gameStatus.shopLevel[config.value] >= config.maxLevel;
var isMaxValue = config.maxValue && gameStatus[config.value] >= config.maxValue;
if (isMaxLevel || isMaxValue) {
self.setDisable(true);
}
self.updateDisplay();
return self;
});
var Fish = Container.expand(function (fishType) {
var self = Container.call(this);
// Store fish type
if (fishType) {
self.fishType = fishType;
} else {
throw "You must add a fish type.";
}
// Create fish visual
var fishGraphics = self.attachAsset(self.fishType, {
anchorX: 0.5,
anchorY: 0.5
});
// Swimming properties
self.speed = 2 + Math.random() * 3; // Random speed between 2-5
self.direction = Math.random() * Math.PI * 2; // Random initial direction
self.turnSpeed = 0.02 + Math.random() * 0.03; // How fast fish can turn
self.targetDirection = self.direction;
self.wobbleAmount = 0.1 + Math.random() * 0.2; // Slight wobble for natural movement
self.wobbleSpeed = 0.05 + Math.random() * 0.05;
self.wobbleOffset = Math.random() * Math.PI * 2;
// Boundaries with margin
self.margin = 100;
// Initialize position
self.randomPosition = function () {
self.x = self.margin + Math.random() * (2048 - self.margin * 2);
self.y = self.margin + Math.random() * (2732 - self.margin * 2);
};
self.format = function () {
if (self.rate.toFixed(2) <= 0.5) {
var rate = "frame";
} else {
var rate = formatTime(self.rate, 2);
}
return formatMoney(self.value) + " every " + rate;
};
self.destroy = function () {
if (self.incomeTimer) {
LK.clearInterval(self.incomeTimer);
self.incomeTimer = null;
}
Container.prototype.destroy.call(self);
self = undefined;
};
self.update = function () {
if (!self.hasAI) {
return;
}
// Add wobble to movement
var wobble = Math.sin(LK.ticks * self.wobbleSpeed + self.wobbleOffset) * self.wobbleAmount;
// Gradually turn towards target direction
var directionDiff = self.targetDirection - self.direction;
// Normalize angle difference to -PI to PI
while (directionDiff > Math.PI) {
directionDiff -= Math.PI * 2;
}
while (directionDiff < -Math.PI) {
directionDiff += Math.PI * 2;
}
self.direction += directionDiff * self.turnSpeed;
// Move fish
self.x += Math.cos(self.direction + wobble) * self.speed;
self.y += Math.sin(self.direction + wobble) * self.speed;
// Face the direction of movement
fishGraphics.rotation = self.direction;
// Check boundaries and change direction
var turnAwayForce = 0.1;
var boundaryDistance = 200;
if (self.x < self.margin + boundaryDistance) {
self.targetDirection = 0; // Turn right
} else if (self.x > 2048 - self.margin - boundaryDistance) {
self.targetDirection = Math.PI; // Turn left
}
if (self.y < self.margin + boundaryDistance) {
self.targetDirection = Math.PI / 2; // Turn down
} else if (self.y > 2732 - self.margin - boundaryDistance - 200) {
self.targetDirection = -Math.PI / 2; // Turn up
}
// Occasionally change direction randomly
if (Math.random() < 0.005) {
// 0.5% chance per frame
self.targetDirection = Math.random() * Math.PI * 2;
}
// Keep fish within bounds (hard limit)
self.x = Math.max(self.margin, Math.min(2048 - self.margin, self.x));
self.y = Math.max(self.margin, Math.min(2732 - self.margin, self.y));
};
return self;
});
// Anything stored in GameStatus will be saved
var GameStatus = Container.expand(function () {
var self = Container.call(this);
self.money = 0;
self.fishes = [];
self.bait = 20;
self.baitTimer = 300;
self.fishValue = 1;
self.fishMax = 3;
self.fishRate = 3.6e+6;
self.shopLevel = {};
self.tutorial = true;
// storage.hasSaved = false;
if (storage.hasSaved) {
self.money = storage.money || 0;
var deserializedFishes = deserializeFish(storage.fishes || "");
self.fishes = deserializedFishes;
self.bait = storage.bait || 20;
self.baitTimer = storage.baitTimer || 300;
self.fishValue = storage.fishValue || 1;
self.fishMax = storage.fishMax || 3;
self.fishRate = storage.fishRate || 3.6e+6;
self.shopLevel = storage.shopLevel || {};
self.tutorial = storage.tutorial || storage.tutorial !== false;
var dt = Date.now() - storage.time;
// dt = 1000*3600*8
var t = 0;
self.fishes.forEach(function (fish, i) {
if (fish.rate === 0) {
var earning = Math.floor(dt / 40, dt) * fish.value;
} else {
var earning = Math.floor(dt / fish.rate, dt) * fish.value;
}
t += earning;
self.money += earning;
console.log("".concat(fish.fishType, ": ").concat(formatMoney(earning), ", ").concat(dt));
});
console.log("Total: ".concat(formatMoney(t)));
if (self.bait < 20) {
self.bait += Math.floor(dt / (300 * 1000));
self.baitTimer -= Math.floor(dt % (300 * 1000) / 1000);
if (self.baitTimer < 0) {
self.baitTimer = trueMod(self.baitTimer, 300);
self.bait++;
}
if (self.bait >= 20) {
self.bait = 20;
}
}
}
self.fishesAtCapacity = function () {
return self.fishes.length >= self.fishMax;
};
self.formatMoney = function () {
if (self.money === Infinity) {
return "$Infinity";
}
var str = "$";
if (self.money >= 1000) {
suffixes = ["K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "De"];
var digits = countNumber(self.money);
var sf = suffixes[Math.floor((digits - 1) / 3) - 1];
if (sf === undefined) {
str += String(self.money.toExponential(2));
} else {
str += (self.money / Math.pow(10, Math.floor((digits - 1) / 3) * 3)).toFixed(2) + sf;
}
} else {
str += self.money.toFixed(2);
}
return str;
};
self.updateMoney = function () {
if (self.children.length > 0) {
self.removeChildAt(0);
}
var moneyText = new Text2(self.formatMoney(), {
size: 125,
fill: 0xD7FFD7,
weight: 750
});
moneyText.y = 50;
moneyText.x = 50;
self.save();
self.addChildAt(moneyText, 0);
};
self.save = function () {
storage.hasSaved = true;
storage.version = 0;
storage.time = Date.now();
storage.money = self.money;
var array = [];
self.fishes.forEach(function (obj) {
var fishData = obj.fishType + "|" + obj.value + "|" + obj.rate;
array.push(fishData);
});
storage.fishes = array.join("\n");
storage.bait = self.bait;
storage.baitTimer = self.baitTimer;
storage.fishValue = self.fishValue;
storage.fishMax = self.fishMax;
storage.fishRate = self.fishRate;
storage.shopLevel = self.shopLevel;
storage.tutorial = self.tutorial;
};
self.updateMoney();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x83C7FF
});
/****
* Game Code
****/
function trueMod(a, b) {
return (a % b + b) % b;
}
function countNumber(number) {
return Math.floor(Math.log10(Math.abs(number))) + 1;
}
function formatTime(time, point) {
time = time / 1000;
var str = "";
if (time > 3600) {
str += String((time / 3600).toFixed(point)) + " hour";
} else if (time > 60) {
str += String((time / 60).toFixed(point)) + " minute";
} else {
str += String(time.toFixed(point)) + " second";
}
if (time != 1) {
str += "s";
}
return str;
}
function formatMoney(money) {
if (money === Infinity) {
return "$Infinity";
}
var str = "$";
if (money >= 1000) {
var suffixes = ["K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "De"];
var digits = countNumber(money);
var sf = suffixes[Math.floor((digits - 1) / 3) - 1];
if (sf === undefined) {
str += String(money.toExponential(2));
} else {
str += (money / Math.pow(10, Math.floor((digits - 1) / 3) * 3)).toFixed(2) + sf;
}
} else {
str += money.toFixed(2);
}
return str;
}
function normalRandom(min, max, skew) {
skew = skew | 1;
var u = 0,
v = 0;
while (u === 0) {
u = Math.random();
}
while (v === 0) {
v = Math.random();
}
var num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
num = num / 10.0 + 0.5;
if (num > 1 || num < 0) {
num = normalRandom(min, max, skew);
} else {
num = Math.pow(num, skew);
num *= max - min;
num += min;
}
return num;
}
var shine;
var shine2;
function deserializeFish(fishDataString) {
if (!fishDataString || fishDataString.trim() === "") {
return [];
}
var fishArray = [];
var fishLines = fishDataString.split("\n");
for (var i = 0; i < fishLines.length; i++) {
var line = fishLines[i].trim();
if (line === "") {
continue;
}
var parts = line.split("|");
if (parts.length === 3) {
var fishType = parts[0];
var value = parseFloat(parts[1]);
var rate = parseFloat(parts[2]);
// Create new fish with deserialized data
var fish = new Fish(fishType);
fish.scale.set(2);
fish.value = value;
fish.rate = rate;
fish.hasAI = true;
fishArray.push(fish);
}
}
return fishArray;
}
var gameStatus = new GameStatus();
var tabLayout = {};
var fishTypes = ['blueFish', 'greenFish', 'pinkFish', 'redFish'];
function addFish(fish) {
gameStatus.caughtFish.scaleX = 2;
gameStatus.caughtFish.scaleY = 2;
fish.randomPosition();
gameStatus.fishes.push(fish);
fishLayer.addChild(fish);
// Add interval timer for this fish
fish.incomeTimer = LK.setInterval(function () {
gameStatus.money += fish.value;
gameStatus.updateMoney();
}, fish.rate);
gameStatus.save();
}
function randomFish(value, rate) {
if (value === undefined) {
var r = 0;
var v = 0;
} else {
var r = normalRandom(rate / 1.5, rate * 1.5);
var v = Number(normalRandom(value / 1.5, value * 1.5).toFixed(2));
if (r < 0) {
r = 0;
}
}
var randomType = fishTypes[Math.floor(Math.random() * fishTypes.length)];
var fish = new Fish(randomType);
fish.value = v;
fish.rate = r;
return fish;
}
// Initialise the cast screen
var castLayer = new Container();
castLayer.visible = false;
castLayer.attachAsset('castBackground', {
alpha: 0.5
});
var text = new Text2("You caught a fish!", {
size: 150,
fill: 0xFFFFFF,
weight: 700
});
text.x = 2048 / 2 - text.width / 2;
text.y = 2732 / 2 - 900;
castLayer.addChild(text);
var fishText;
function hideCast() {
castLayer.removeChild(gameStatus.caughtFish);
shine.destroy();
shine2.destroy();
fishText.destroy();
castLayer.visible = false;
}
var keepButton = new Button(function () {
hideCast();
gameStatus.save();
gameStatus.caughtFish.hasAI = true;
addFish(gameStatus.caughtFish);
castLayer.visible = false;
gameStatus.caughtFish = undefined;
}, {
text: "Keep",
background: 'rectButtonBackground',
width: 818,
height: 335
});
keepButton.y = 2732 / 2 + 900;
castLayer.addChild(keepButton);
var sellButton = new Button(function () {
hideCast();
gameStatus.money += gameStatus.caughtFish.value;
gameStatus.updateMoney();
gameStatus.caughtFish = undefined;
}, {
text: "Sell",
background: 'rectButtonBackground',
width: 818,
height: 335
});
sellButton.x = 2048 / 2 + 50;
sellButton.y = 2732 / 2 + 900;
castLayer.addChild(sellButton);
var closeButton = new Button(hideCast, {
size: 150,
icon: 'closeIcon'
});
closeButton.x = 2048 - 250;
closeButton.y = 50;
castLayer.addChild(closeButton);
var passiveIncome = new Text2("Passive Income:", {
size: 125,
fill: 0xFFFFFF,
weight: 700
});
passiveIncome.x = 2048 / 2;
passiveIncome.y = 2732 / 2 - 800 + text.height;
passiveIncome.anchor.set(0.5, 0);
castLayer.addChild(passiveIncome);
game.addChild(castLayer);
function cast() {
if (gameStatus.caughtFish === undefined) {
gameStatus.bait--;
gameStatus.caughtFish = randomFish(gameStatus.fishValue, gameStatus.fishRate);
// Update bait counter
baitText.setText("Bait: " + gameStatus.bait + "/20");
}
if (gameStatus.tutorial && gameStatus.fishes.length == 2) {
gameStatus.tutorial = false;
}
sellButton.visible = !gameStatus.tutorial;
if (gameStatus.tutorial) {
keepButton.x = 2048 / 2 - 818 / 2;
} else {
keepButton.x = 2048 / 2 - 818 - 50;
}
keepButton.setDisable(gameStatus.fishesAtCapacity());
shine = LK.getAsset('shine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
alpha: 0.7
});
shine.x = 2048 / 2;
shine.y = 2732 / 2 + 300;
shine.rotation = 0;
castLayer.addChild(shine);
shine2 = LK.getAsset('shine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.5
});
shine2.x = 2048 / 2;
shine2.y = 2732 / 2 + 300;
shine2.rotation = 0;
castLayer.addChild(shine2);
// Render fish on cast screen
gameStatus.caughtFish.x = 2048 / 2;
gameStatus.caughtFish.y = 2732 / 2 + 300;
gameStatus.caughtFish.scaleX = 2;
gameStatus.caughtFish.scaleY = 2;
gameStatus.caughtFish.hasAI = false;
castLayer.addChild(gameStatus.caughtFish);
fishText = new Text2(gameStatus.caughtFish.format(), {
size: 125,
fill: 0xC7FFC7,
weight: 750
});
fishText.x = 2048 / 2;
fishText.y = 2732 / 2 - 790 + passiveIncome.height + text.height;
fishText.anchor.set(0.5, 0);
castLayer.addChild(fishText);
// Display the cast screen
castLayer.visible = true;
hideTab();
}
function hideTab() {
tabBackground.visible = false;
if (currTab) {
tabLayout[currTab].visible = false;
currTab = null;
}
}
function updateFishesDisplay() {
if (currTab !== 'fishes') {
return;
}
fishesHeader.setText('Capacity: ' + gameStatus.fishes.length + '/' + gameStatus.fishMax);
fishesHeader.x = (946 - fishesHeader.width) / 2;
// Clear previous fish display - properly destroy assets first
while (tabLayout.fishes.children.length > 1) {
var childToRemove = tabLayout.fishes.children[tabLayout.fishes.children.length - 1];
if (childToRemove.destroy) {
childToRemove.destroy();
} else {
tabLayout.fishes.removeChildAt(tabLayout.fishes.children.length - 1);
}
}
// Display each fish
var yOffset = 230;
for (var i = 0; i < gameStatus.fishes.length; i++) {
var fish = gameStatus.fishes[i];
// Fish icon
var fishIcon = LK.getAsset(fish.fishType, {});
fishIcon.scale.set(0.75);
fishIcon.x = 100;
fishIcon.y = yOffset;
tabLayout.fishes.addChild(fishIcon);
// Fish info text
var fishInfo = new Text2(fish.format(), {
size: 60,
fill: 0xFFFFFF,
weight: 600
});
fishInfo.anchor.set(0, 0.5);
fishInfo.x = 100;
fishInfo.y = yOffset + fishIcon.height + 22;
tabLayout.fishes.addChild(fishInfo);
// Sell button for this fish
var sellFishButton = new Button(function (fishIndex) {
return function () {
var fishToSell = gameStatus.fishes[fishIndex];
// Add money from selling
gameStatus.money += fishToSell.value;
gameStatus.updateMoney();
// Remove fish from array and destroy
gameStatus.fishes.splice(fishIndex, 1);
fishToSell.destroy();
// Update the fishes display
updateFishesDisplay();
gameStatus.save();
return true;
};
}(i), {
text: "Sell",
width: 250,
height: 90
});
sellFishButton.x = 600;
sellFishButton.y = yOffset + fishIcon.height / 2 - 60;
if (!gameStatus.tutorial) {
tabLayout.fishes.addChild(sellFishButton);
}
yOffset += fishIcon.height + fishInfo.height + 25;
// Add separator
if (i < gameStatus.fishes.length - 1) {
var separator = LK.getAsset('separator', {});
separator.x = 85;
separator.y = yOffset;
tabLayout.fishes.addChild(separator);
yOffset += separator.height + 20;
}
}
}
var currTab;
function tabPressed(button) {
if (castLayer.visible) {
return false;
}
tabBackground.visible = true;
if (currTab == button.id) {
return true;
}
if (currTab) {
tabLayout[currTab].visible = false;
}
currTab = button.id;
tabLayout[button.id].visible = true;
if (gameStatus.bait <= 0) {
castButton.setDisable(true);
}
if (currTab == 'fishes') {
updateFishesDisplay();
}
return true;
}
var tabLayer = new Container();
var tabBackground = new Container();
var tabElements = new Container();
tabLayout.cast = tabElements.addChild(new Container());
tabLayout.cast.visible = false;
tabLayout.fishes = tabElements.addChild(new Container());
tabLayout.fishes.visible = false;
tabLayout.shop = tabElements.addChild(new Container());
tabLayout.shop.visible = false;
var baitText = new Text2("Bait: " + gameStatus.bait + "/20", {
size: 100,
fill: 0xFFFFFF,
weight: 700
});
baitText.x = (946 - baitText.width) / 2;
baitText.y = 70;
tabLayout.cast.addChild(baitText);
var baitTimerText = new Text2("", {
size: 80,
fill: 0xFFFFFF,
weight: 600
});
baitTimerText.x = (946 - baitTimerText.width) / 2;
baitTimerText.y = baitText.y + baitText.height + 10;
tabLayout.cast.addChild(baitTimerText);
var castButton = new Button(cast, {
width: 818,
height: 335,
background: 'rectButtonBackground',
text: "Cast"
});
castButton.x = (946 - 818) / 2;
castButton.y = 95 + baitText.height;
tabLayout.cast.addChild(castButton);
var fishesHeader = new Text2('Capacity: ', {
size: 100,
fill: 0xFFFFFF,
weight: 700
});
fishesHeader.x = (946 - fishesHeader.width) / 2;
fishesHeader.y = 70;
tabLayout.fishes.addChild(fishesHeader);
var fishValueShop = new ButtonShop({
value: 'fishValue',
baseCost: 1,
label: 'Caught Fish Value'
});
fishValueShop.x = (946 - 818) / 2;
fishValueShop.y = 70;
var fishValueShop = new ButtonShop({
value: 'fishValue',
baseCost: 1,
label: 'Caught Fish Value'
});
fishValueShop.x = (946 - 818) / 2;
fishValueShop.y = 70;
tabLayout.shop.addChild(fishValueShop);
var fishRateShop = new ButtonShop({
value: 'fishRate',
baseCost: 100,
label: 'Caught Fish Rate',
maxLevel: 195,
calculateValue: function calculateValue(level, isMax) {
if (isMax) {
return 0;
}
// Use exponential decay: rate decreases a lot at first, then less at higher levels
// Lower rate = faster income generation (better for player)
var baseRate = 3.6e+6;
var decayRate = 0.95;
var currentRate = baseRate * Math.pow(decayRate, level - 1);
return currentRate;
}
});
fishRateShop.x = (946 - 818) / 2;
fishRateShop.y = 70 + 25 + 335 * 1;
tabLayout.shop.addChild(fishRateShop);
var fishMaxShop = new ButtonShop({
value: 'fishMax',
baseCost: 2500,
label: 'Fish Capacity',
maxValue: 8,
calculateValue: function calculateValue(level) {
return Math.min(8, level * 3);
},
calculateCost: function calculateCost(level) {
return level * 2500 * 1000;
}
});
fishMaxShop.x = (946 - 818) / 2;
fishMaxShop.y = 70 + (335 + 25) * 2;
tabLayout.shop.addChild(fishMaxShop);
tabLayer.addChild(tabBackground);
tabLayer.addChild(tabElements);
tabBackground.x = 2048 - 976;
tabBackground.y = 25;
tabElements.x = 2048 - 976;
tabElements.y = 25;
tabBackground.visible = false;
tabBackground.attachAsset('tabBackgroundTL', {});
tabBackground.attachAsset('tabBackgroundBL', {
y: 1155
});
tabBackground.attachAsset('tabBackgroundBR', {
x: 473,
y: 1155
});
tabBackground.attachAsset('tabBackgroundTR', {
x: 473
});
var castTab = new Button(tabPressed, {
width: 300,
height: 346,
background: "tabButtonBackground",
icon: 'castIcon',
id: "cast"
});
castTab.x = 2048 - 325 * 3;
castTab.y = 2732 - 350;
tabLayer.addChild(castTab);
var fishesTab = new Button(tabPressed, {
width: 300,
height: 346,
background: "tabButtonBackground",
icon: "fishesIcon",
id: "fishes"
});
fishesTab.x = 2048 - 325 * 2;
fishesTab.y = 2732 - 350;
tabLayer.addChild(fishesTab);
var shopTab = new Button(tabPressed, {
width: 300,
height: 346,
background: "tabButtonBackground",
icon: "shopIcon",
id: "shop"
});
shopTab.x = 2048 - 325;
shopTab.y = 2732 - 350;
tabLayer.addChild(shopTab);
var fishLayer = new Container();
game.addChild(fishLayer);
var fishes = [];
game.attachAsset('waterBackground', {});
game.addChild(fishLayer);
game.addChild(gameStatus);
game.addChild(tabLayer);
game.addChild(castLayer);
// Load saved fishes and add them to the game
for (var i = 0; i < gameStatus.fishes.length; i++) {
var fish = gameStatus.fishes[i];
fish.randomPosition();
fishLayer.addChild(fish);
// Add interval timer for this fish
fish.incomeTimer = LK.setInterval(function (fishInstance) {
return function () {
gameStatus.money += fishInstance.value;
gameStatus.updateMoney();
};
}(fish), fish.rate);
}
// Bait regeneration timer
LK.setInterval(function () {
// Only decrease timer if bait is not at maximum
if (gameStatus.bait < 20) {
gameStatus.baitTimer--;
// When timer reaches 0, increase bait and reset timer
if (gameStatus.baitTimer <= 0) {
gameStatus.bait++;
gameStatus.baitTimer = 300;
// Update bait display
baitText.setText("Bait: " + gameStatus.bait + "/20");
// Re-enable cast button if we have bait now
if (gameStatus.bait > 0) {
castButton.setDisable(false);
}
}
// Update timer display
var minutes = Math.floor(gameStatus.baitTimer / 60);
var seconds = gameStatus.baitTimer % 60;
var timerString = minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
baitTimerText.setText("Next bait in: " + timerString);
baitTimerText.x = (946 - baitTimerText.width) / 2;
castButton.y = 95 + baitText.height + baitTimerText.height;
}
if (gameStatus.bait >= 20) {
// Hide timer when bait is at maximum
baitTimerText.setText("");
castButton.y = 95 + baitText.height;
}
}, 1000); // Run every 1000ms (1 second)
game.update = function () {
// Rotate shine clockwise if visible
if (shine) {
shine.rotation += 0.01; // Rotate clockwise
}
if (shine2) {
shine2.rotation -= 0.0075; // Rotate anti-clockwise, slower
}
};
game.down = function (x, y, obj) {
if (tabBackground.x > x) {
hideTab();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -291,17 +291,17 @@
// storage.hasSaved = false;
if (storage.hasSaved) {
self.money = storage.money || 0;
var deserializedFishes = deserializeFish(storage.fishes || "");
- self.fishes = [];
+ self.fishes = deserializedFishes;
self.bait = storage.bait || 20;
self.baitTimer = storage.baitTimer || 300;
self.fishValue = storage.fishValue || 1;
self.fishMax = storage.fishMax || 3;
self.fishRate = storage.fishRate || 3.6e+6;
self.shopLevel = storage.shopLevel || {};
self.tutorial = storage.tutorial || storage.tutorial !== false;
- // var dt = Date.now() - storage.time;
+ var dt = Date.now() - storage.time;
// dt = 1000*3600*8
var t = 0;
self.fishes.forEach(function (fish, i) {
if (fish.rate === 0) {
@@ -310,16 +310,16 @@
var earning = Math.floor(dt / fish.rate, dt) * fish.value;
}
t += earning;
self.money += earning;
- console.log("".concat(fish.name, ": ").concat(formatMoney(earning), ", ").concat(dt));
+ console.log("".concat(fish.fishType, ": ").concat(formatMoney(earning), ", ").concat(dt));
});
console.log("Total: ".concat(formatMoney(t)));
if (self.bait < 20) {
self.bait += Math.floor(dt / (300 * 1000));
self.baitTimer -= Math.floor(dt % (300 * 1000) / 1000);
if (self.baitTimer < 0) {
- self.baitTimer = self.baitTimer.mod(300);
+ self.baitTimer = trueMod(self.baitTimer, 300);
self.bait++;
}
if (self.bait >= 20) {
self.bait = 20;
@@ -394,9 +394,11 @@
/****
* Game Code
****/
-var clickSound = LK.getSound('click');
+function trueMod(a, b) {
+ return (a % b + b) % b;
+}
function countNumber(number) {
return Math.floor(Math.log10(Math.abs(number))) + 1;
}
function formatTime(time, point) {