Code edit (19 edits merged)
Please save this source code
User prompt
I added a `background` parameter to the button config, this is the asset id for the button background, this is also the asset id for the pressed button background, just prefix 'Pressed'.
Code edit (1 edits merged)
Please save this source code
Code edit (8 edits merged)
Please save this source code
User prompt
Remove the level number at max level
User prompt
When `maxValue` or `maxLevel` is reached, disable the button, and display that it is max level.
Code edit (11 edits merged)
Please save this source code
User prompt
fix fishRateShop calculateValue
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (14 edits merged)
Please save this source code
User prompt
Make the fish rate decrease a lot at the beginning, but the higher the level the less it decrease.
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: self.getValue is not a function' in or related to this line: 'gameStatus[config.value] = self.getValue();' Line Number: 146
User prompt
Fix the NaN in the shopButton.cost
Code edit (9 edits merged)
Please save this source code
User prompt
Store the shop level in the gameStatus, this will make saving the game easier later on.
User prompt
Please fix the bug: 'self.getCost is not a function' in or related to this line: 'self.costText = new Text2("Cost: " + formatMoney(self.getCost()), {' Line Number: 101
User prompt
Rework the `shopButton` to tie the value and cost to the `shopButton` level rather than increasing the value and cost directly.
Code edit (1 edits merged)
Please save this source code
Code edit (6 edits merged)
Please save this source code
User prompt
Add the label and cost to the button, make the label text smaller, and use `Text2`.
Code edit (12 edits merged)
Please save this source code
User prompt
Make `ButtonShop` cost money (`config.baseCost`) to increase the gameStatus variable (`gameStatus[config.value]`), then call `config.increaseCost` to increase the cost, we want a modular system.
Code edit (1 edits merged)
Please save this source code
/**** * 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; } var textSize = Math.max(buttonWidth, buttonHeight); var background = self.attachAsset('buttonBackground', { width: buttonWidth, height: buttonHeight }); var backgroundPressed = self.attachAsset('buttonBackgroundPressed', { visible: false, width: buttonWidth, height: buttonHeight }); self.text = config.text; var buttonText = new Text2(self.text, { size: textSize / 5, fill: 0xFFFFFF, weight: 700 }); buttonText.anchor.set(0.5, 0.5); buttonText.x = buttonWidth / 2; buttonText.y = buttonHeight / 2; self.addChild(buttonText); self.down = function (x, y, obj) { if (self.disable) { return; } if (self.onPress) { // If onPress return false, then don't press down the button if (!self.onPress(self)) { return; } } self.isPressed = true; background.visible = false; backgroundPressed.visible = true; currentButton = self; }; self.up = function (x, y, obj) { self.isPressed = false; background.visible = true; backgroundPressed.visible = false; }; self.setDisable = function (disable) { self.disable = disable; background.tint = disable ? 0xAAAAAA : 0xFFFFFF; buttonText.tint = disable ? 0xAAAAAA : 0xFFFFFF; }; return self; }); var ButtonShop = Button.expand(function (value) { var self = Button.call(this, function () { value++; return true; }, { width: 818, height: 335 }); 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) { 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; }); 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.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.addChildAt(moneyText, 0); }; self.updateMoney(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x83C7FF }); /**** * Game Code ****/ 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; var gameStatus = new GameStatus(); var tabLayout = {}; var fishTypes = ['blueFish', 'greenFish', 'pinkFish', 'redFish']; function addFish(fish) { gameStatus.caughtFish.scaleX = 1; gameStatus.caughtFish.scaleY = 1; 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); } function randomFish(value, rate) { if (value === undefined) { var r = 0; var v = 0; } else { var r = normalRandom(rate / 1.1, rate * 1.1); var v = Number(normalRandom(value / 2, value * 2).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() { game.removeChild(gameStatus.caughtFish); shine.destroy(); shine2.destroy(); fishText.destroy(); castLayer.visible = false; } var keepButton = new Button(function () { hideCast(); gameStatus.caughtFish.hasAI = true; addFish(gameStatus.caughtFish); castLayer.visible = false; gameStatus.caughtFish = undefined; }, { text: "Keep", width: 818, height: 335 }); keepButton.x = 2048 / 2 - 818 - 50; 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", width: 818, height: 335 }); sellButton.x = 2048 / 2 + 50; sellButton.y = 2732 / 2 + 900; castLayer.addChild(sellButton); var closeButton = new Button(hideCast, { size: 150, text: "X" }); 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"); } 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 refreshFishesDisplay() { 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(); // Refresh the fishes display refreshFishesDisplay(); return true; }; }(i), { text: "Sell", width: 250, height: 90 }); sellFishButton.x = 600; sellFishButton.y = yOffset + fishIcon.height / 2 - 60; 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; } if (currTab) { tabLayout[currTab].visible = false; } currTab = button.id; tabLayout[button.id].visible = true; if (gameStatus.bait <= 0) { castButton.setDisable(true); } if (currTab == 'fishes') { refreshFishesDisplay(); } 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, 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 b = new ButtonShop(gameStatus.value); b.x = (946 - 818) / 2; b.y = 70; tabLayout.shop.addChild(b); 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, { size: 300, text: "cast", id: "cast" }); castTab.x = 2048 - 325 * 3; castTab.y = 2732 - 325; tabLayer.addChild(castTab); var fishesTab = new Button(tabPressed, { size: 300, text: "fishes", id: "fishes" }); fishesTab.x = 2048 - 325 * 2; fishesTab.y = 2732 - 325; tabLayer.addChild(fishesTab); var shopTab = new Button(tabPressed, { size: 300, text: "shop", id: "shop" }); shopTab.x = 2048 - 325; shopTab.y = 2732 - 325; 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); // 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(); } };
/****
* 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;
}
var textSize = Math.max(buttonWidth, buttonHeight);
var background = self.attachAsset('buttonBackground', {
width: buttonWidth,
height: buttonHeight
});
var backgroundPressed = self.attachAsset('buttonBackgroundPressed', {
visible: false,
width: buttonWidth,
height: buttonHeight
});
self.text = config.text;
var buttonText = new Text2(self.text, {
size: textSize / 5,
fill: 0xFFFFFF,
weight: 700
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = buttonWidth / 2;
buttonText.y = buttonHeight / 2;
self.addChild(buttonText);
self.down = function (x, y, obj) {
if (self.disable) {
return;
}
if (self.onPress) {
// If onPress return false, then don't press down the button
if (!self.onPress(self)) {
return;
}
}
self.isPressed = true;
background.visible = false;
backgroundPressed.visible = true;
currentButton = self;
};
self.up = function (x, y, obj) {
self.isPressed = false;
background.visible = true;
backgroundPressed.visible = false;
};
self.setDisable = function (disable) {
self.disable = disable;
background.tint = disable ? 0xAAAAAA : 0xFFFFFF;
buttonText.tint = disable ? 0xAAAAAA : 0xFFFFFF;
};
return self;
});
var ButtonShop = Button.expand(function (value) {
var self = Button.call(this, function () {
value++;
return true;
}, {
width: 818,
height: 335
});
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) {
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;
});
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.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.addChildAt(moneyText, 0);
};
self.updateMoney();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x83C7FF
});
/****
* Game Code
****/
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;
var gameStatus = new GameStatus();
var tabLayout = {};
var fishTypes = ['blueFish', 'greenFish', 'pinkFish', 'redFish'];
function addFish(fish) {
gameStatus.caughtFish.scaleX = 1;
gameStatus.caughtFish.scaleY = 1;
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);
}
function randomFish(value, rate) {
if (value === undefined) {
var r = 0;
var v = 0;
} else {
var r = normalRandom(rate / 1.1, rate * 1.1);
var v = Number(normalRandom(value / 2, value * 2).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() {
game.removeChild(gameStatus.caughtFish);
shine.destroy();
shine2.destroy();
fishText.destroy();
castLayer.visible = false;
}
var keepButton = new Button(function () {
hideCast();
gameStatus.caughtFish.hasAI = true;
addFish(gameStatus.caughtFish);
castLayer.visible = false;
gameStatus.caughtFish = undefined;
}, {
text: "Keep",
width: 818,
height: 335
});
keepButton.x = 2048 / 2 - 818 - 50;
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",
width: 818,
height: 335
});
sellButton.x = 2048 / 2 + 50;
sellButton.y = 2732 / 2 + 900;
castLayer.addChild(sellButton);
var closeButton = new Button(hideCast, {
size: 150,
text: "X"
});
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");
}
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 refreshFishesDisplay() {
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();
// Refresh the fishes display
refreshFishesDisplay();
return true;
};
}(i), {
text: "Sell",
width: 250,
height: 90
});
sellFishButton.x = 600;
sellFishButton.y = yOffset + fishIcon.height / 2 - 60;
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;
}
if (currTab) {
tabLayout[currTab].visible = false;
}
currTab = button.id;
tabLayout[button.id].visible = true;
if (gameStatus.bait <= 0) {
castButton.setDisable(true);
}
if (currTab == 'fishes') {
refreshFishesDisplay();
}
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,
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 b = new ButtonShop(gameStatus.value);
b.x = (946 - 818) / 2;
b.y = 70;
tabLayout.shop.addChild(b);
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, {
size: 300,
text: "cast",
id: "cast"
});
castTab.x = 2048 - 325 * 3;
castTab.y = 2732 - 325;
tabLayer.addChild(castTab);
var fishesTab = new Button(tabPressed, {
size: 300,
text: "fishes",
id: "fishes"
});
fishesTab.x = 2048 - 325 * 2;
fishesTab.y = 2732 - 325;
tabLayer.addChild(fishesTab);
var shopTab = new Button(tabPressed, {
size: 300,
text: "shop",
id: "shop"
});
shopTab.x = 2048 - 325;
shopTab.y = 2732 - 325;
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);
// 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();
}
};