User prompt
The player's arrow should draw a trail behind itself which remains permanently.
Code edit (1 edits merged)
Please save this source code
User prompt
Stonks Go Up
Initial prompt
This game is called "Stonks Go Up" and it's based on the stonks meme where anything good that happens is called "stonks" and anything bad that happens is called "not stonks". The player controls an arrow going in the direction it's facing. The arrow should face northeast (towards the upper-right corner of the screen when) when the player is not holding on the screen, and the arrow should face southeast (towards the lower-left corner of the screen) when the player is holding on the screen. The further up the player goes, the more points they score. The score is called the "stonk market cap". As the game progresses, more and more obstacles and bonuses will fly in from the right side of the screen towards the left. If the player collides with a bonus, the game will show a "stonks" score bubble graphic and increase the score further. If the player collides with an obstacle, the game will show a "not stonks" score bubble graphic and the game will end. When the game ends, the game will zoom out and display the entire history of that play session drawn out by the player's arrow and offer the player a button to play again or to share their score online.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Arrow = Container.expand(function () { var self = Container.call(this); var arrowGraphics = self.attachAsset('arrow', { anchorX: 0.5, anchorY: 0.5 }); self.direction = "northeast"; // Starting direction self.speed = 10; // Movement speed will be used for object movement self.x = 2048 * (1 / 3); // Fixed position at 1/3 from left (2/3 left on screen) self.y = 2732 * (2 / 3); // Fixed position at 2/3 down on screen self.path = []; // Track arrow's path self.hitboxScale = 0.3; // Make hitbox 30% of the actual size // Override the intersects method to use a smaller hitbox self.originalIntersects = self.intersects; self.intersects = function (otherObject) { // Store original width and height var originalWidth = arrowGraphics.width; var originalHeight = arrowGraphics.height; // Temporarily scale down the width and height for collision detection arrowGraphics.width *= self.hitboxScale; arrowGraphics.height *= self.hitboxScale; // Check collision with smaller hitbox var result = self.originalIntersects.call(self, otherObject); // Restore original width and height arrowGraphics.width = originalWidth; arrowGraphics.height = originalHeight; return result; }; self.update = function () { // Direction changes based on touch state, but arrow doesn't move if (!game.isTouching) { // Not touching - arrow faces northeast self.direction = "northeast"; arrowGraphics.rotation = -Math.PI / 4; // 45 degrees up } else { // Touching - arrow faces southeast self.direction = "southeast"; arrowGraphics.rotation = Math.PI / 4; // 45 degrees down } // Adjust speed based on market cap // Base speed of 10 // Allow scaling up to 500% (speed of 50) var marketCapFactor = Math.max(0, marketCap) / 100; var speedMultiplier; if (marketCapFactor <= 20) { // Up to 300% speed (market cap of 2000) speedMultiplier = marketCapFactor * 0.5; // Original scaling } else { // More gradual scaling after 300% speedMultiplier = 10 + (marketCapFactor - 20) * 0.2; // Slower increase after 300% // Cap at 500% (total multiplier of 40) speedMultiplier = Math.min(speedMultiplier, 40); } self.speed = Math.max(10, Math.min(50, 10 + speedMultiplier)); // Record fixed path for consistency if (game.ticks % 5 === 0) { self.path.push({ x: self.x, y: self.y }); } }; // Direction is now controlled by touch state in update method return self; }); var BackgroundGrid = Container.expand(function () { var self = Container.call(this); var tileSize = 200; // Size of each grid square var gridTiles = []; // Store all grid tiles // Dark blue color for tiles, slightly lighter for outlines var tileColor = 0x003366; // Dark blue var outlineColor = 0x0066aa; // Lighter blue for outline // Create the grid to cover screen with some buffer self.createGrid = function () { // Calculate how many tiles we need to cover the entire screen with buffer var screenWidth = 2748; var screenHeight = 2732; // Add buffer to ensure full coverage when moving var bufferMultiplier = 2; var tilesX = Math.ceil(screenWidth * bufferMultiplier / tileSize) + 2; var tilesY = Math.ceil(screenHeight * bufferMultiplier / tileSize) + 2; // Center position to align with screen center var centerX = screenWidth / 2; var centerY = screenHeight / 2; // Calculate starting position (top-left of grid) var startX = centerX - tilesX * tileSize / 2; var startY = centerY - tilesY * tileSize / 2; // Create grid of square tiles for (var x = 0; x < tilesX; x++) { for (var y = 0; y < tilesY; y++) { // Create tile as a Container var tile = new Container(); // Create tile background var bg = LK.getAsset('background', { anchorX: 0, anchorY: 0, width: tileSize, height: tileSize, tint: tileColor }); // Create tile outline (slightly smaller to create border effect) var outline = LK.getAsset('background', { anchorX: 0, anchorY: 0, width: tileSize - 2, height: tileSize - 2, x: 1, y: 1, tint: outlineColor }); tile.addChild(bg); tile.addChild(outline); // Position tile tile.x = startX + x * tileSize; tile.y = startY + y * tileSize; // Initialize original position tile.origX = tile.x; tile.origY = tile.y; // Store tile gridTiles.push(tile); self.addChild(tile); } } }; // Move grid based on arrow direction and speed self.update = function () { if (!arrow || !arrow.direction) { return; } var moveAmountX = 0; var moveAmountY = 0; // Move opposite to the arrow direction if (arrow.direction === "northeast") { // Move background southwest moveAmountX = -arrow.speed; moveAmountY = arrow.speed; } else { // Move background northwest moveAmountX = -arrow.speed; moveAmountY = -arrow.speed; } // Move all tiles for (var i = 0; i < gridTiles.length; i++) { var tile = gridTiles[i]; tile.x += moveAmountX; tile.y += moveAmountY; // Wrap tiles around when they move too far if (tile.x < -tileSize * 2) { tile.x += gridTiles.length * tileSize / Math.sqrt(gridTiles.length); } else if (tile.x > 2048 + tileSize * 2) { tile.x -= gridTiles.length * tileSize / Math.sqrt(gridTiles.length); } if (tile.y < -tileSize * 2) { tile.y += gridTiles.length * tileSize / Math.sqrt(gridTiles.length); } else if (tile.y > 2732 + tileSize * 2) { tile.y -= gridTiles.length * tileSize / Math.sqrt(gridTiles.length); } } }; return self; }); var Bonus = Container.expand(function () { var self = Container.call(this); var bonusGraphics = self.attachAsset('bonus', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -8; self.collected = false; self.hitboxScale = 0.3; // Make hitbox 30% of the actual size // Override the intersects method to use a smaller hitbox self.originalIntersects = self.intersects; self.intersects = function (otherObject) { // Store original width and height var originalWidth = bonusGraphics.width; var originalHeight = bonusGraphics.height; // Temporarily scale down the width and height for collision detection bonusGraphics.width *= self.hitboxScale; bonusGraphics.height *= self.hitboxScale; // Check collision with smaller hitbox var result = self.originalIntersects.call(self, otherObject); // Restore original width and height bonusGraphics.width = originalWidth; bonusGraphics.height = originalHeight; return result; }; self.update = function () { // Bonuses now move towards the arrow (opposite direction) if (game.isTouching) { // Move opposite to southeast direction self.x -= arrow.speed; self.y -= arrow.speed; } else { // Move opposite to northeast direction self.x -= arrow.speed; self.y += arrow.speed; } // Spin the bonus //bonusGraphics.rotation += 0.05; }; self.collect = function () { self.collected = true; tween(bonusGraphics, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, easing: tween.easeOut }); }; return self; }); var DollarBill = Container.expand(function (direction) { var self = Container.call(this); var color = direction === "northeast" ? 0x00FF00 : 0xFF0000; var dollarGraphics = self.attachAsset('dollar', { anchorX: 0.5, anchorY: 0.5, tint: color }); //dollarGraphics.rotation = Math.random() * Math.PI * 2; // Random rotation dollarGraphics.scale.set(0.8, 0.5); // Make it more bill-shaped // No need for self.speed as we'll use arrow.speed directly self.direction = direction; // Store direction for movement self.update = function () { // Move in the opposite direction of what the arrow would move // Use arrow's current speed for consistent movement if (self.direction === "northeast") { self.x -= arrow.speed; self.y += arrow.speed; } else { self.x -= arrow.speed; self.y -= arrow.speed; } }; return self; }); var Moon = Container.expand(function () { var self = Container.call(this); // Create a white circular shape for the moon var moonGraphics = self.attachAsset('moon', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 300, tint: 0xFFFFFF }); // Set initial position off-screen in the northeast corner self.x = 2548; // Just off-screen to the right self.y = -300; // Just off-screen above // Set slow movement speed self.speed = 2; self.update = function () { // Move slowly from northeast to southwest self.x -= self.speed; self.y += self.speed; // Remove when completely off-screen if (self.x < -400 || self.y > 3132) { self.readyForRemoval = true; } }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -10; self.hitboxScale = 0.2; // Make hitbox 20% of the actual size // Override the intersects method to use a smaller hitbox self.originalIntersects = self.intersects; self.intersects = function (otherObject) { // Store original width and height var originalWidth = obstacleGraphics.width; var originalHeight = obstacleGraphics.height; // Temporarily scale down the width and height for collision detection obstacleGraphics.width *= self.hitboxScale; obstacleGraphics.height *= self.hitboxScale; // Check collision with smaller hitbox var result = self.originalIntersects.call(self, otherObject); // Restore original width and height obstacleGraphics.width = originalWidth; obstacleGraphics.height = originalHeight; return result; }; self.update = function () { // Obstacles now move towards the arrow (opposite direction) // Always use arrow's current speed for consistent movement if (game.isTouching) { // Move opposite to southeast direction self.x -= arrow.speed; self.y -= arrow.speed; } else { // Move opposite to northeast direction self.x -= arrow.speed; self.y += arrow.speed; } }; return self; }); var StonksText = Container.expand(function (message, color) { var self = Container.call(this); var text = new Text2(message || "STONKS!", { size: 100, fill: color || "#00FF00" }); text.anchor.set(0.5, 0.5); self.addChild(text); self.animate = function () { self.alpha = 1; tween(self, { alpha: 0, y: self.y - 200 }, { duration: 1500, easing: tween.easeOut }); tween(self.scale, { x: 2, y: 2 }, { duration: 1500, easing: tween.easeOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0066ff }); /**** * Game Code ****/ // Track if the screen is being touched // Game variables game.isTouching = false; var gameStarted = false; // Track if the game has been started by the first touch // Camera functionality removed as the arrow now stays stationary // and other objects move around it var camera = { update: function update() {} // Empty function to prevent errors }; var arrow; var obstacles = []; var bonuses = []; var stonksTexts = []; var dollarBills = []; var moons = []; var lastObstacleTime = 0; var lastBonusTime = 0; var lastDollarTime = 0; var lastMoonAppearance = 0; var marketCap = 0; var marketCapFactor = 0; var gameActive = true; var moonAppearThreshold = 9000; // Moon appears every 9,000 points var lastMoonCheckPoint = 0; // Tracks the last point at which we checked for moon appearance // Create background grid var backgroundGrid = new BackgroundGrid(); backgroundGrid.createGrid(); game.addChild(backgroundGrid); // Add background reference for backward compatibility var background = { x: 2048 / 2, y: 2732 / 2 }; // Create GUI elements var marketCapText = new Text2("Stonk Market Cap: $0.00", { size: 60, fill: 0xFFFFFF }); marketCapText.anchor.set(0.5, 0); LK.gui.top.addChild(marketCapText); marketCapText.visible = false; // Hide initially // Create startup logo var logoText = new Text2("Stonks Go Up", { size: 150, fill: 0x00FF00 }); logoText.anchor.set(0.5, 1.2); logoText.x = 2048 / 2; logoText.y = 2732 / 2; game.addChild(logoText); // Add tap to start instruction var startInstructionText = new Text2("Tap to Start", { size: 80, fill: 0xFFFFFF }); startInstructionText.anchor.set(0.5, 0.5); startInstructionText.x = 2048 / 2; startInstructionText.y = 2732 / 2 + 200; game.addChild(startInstructionText); // Add high score display to the start screen var highScoreText = new Text2("High Score: $" + storage.highScore + ".00", { size: 60, fill: 0xFFFFFF }); highScoreText.anchor.set(0.5, 0); highScoreText.x = 2048 / 2; highScoreText.y = 2732 - 200; game.addChild(highScoreText); // Make the text pulse tween(startInstructionText.scale, { x: 1.1, y: 1.1 }, { duration: 800, easing: tween.easeInOut, loop: -1, yoyo: true }); // Add stonksguy mascot to lower-left corner var stonksGuy = game.addChild(LK.getAsset('stonksguy', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 2732 - 120 })); stonksGuy.visible = true; // Ensure stonksguy is visible // Create arrow in the center of the screen arrow = new Arrow(); // Arrow position is set in the class constructor game.addChild(arrow); // No camera setup needed since we have a fixed view // Background music will play on first touch, not at initialization // Handle touch events game.down = function (x, y, obj) { if (!gameStarted) { // First touch - start the game gameStarted = true; // Start playing background music now LK.playMusic('bgMusic'); // Hide the logo and instruction tween(logoText, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onComplete: function onComplete() { logoText.destroy(); } }); tween(startInstructionText, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onComplete: function onComplete() { startInstructionText.destroy(); } }); // Show the market cap text marketCapText.visible = true; // Set touch state game.isTouching = true; } else if (gameActive) { game.isTouching = true; } }; game.up = function (x, y, obj) { if (gameActive) { game.isTouching = false; } }; // Generate obstacles function createObstacle() { var obstacle = new Obstacle(); // Since arrow is fixed in center, use fixed screen coordinates var screenWidth = 2048; var screenHeight = 2732; // Randomly decide if this obstacle should be directly in the arrow's path var inPath = Math.random() < 0.4; // 40% chance to spawn in path var spawnRegion = Math.random(); if (inPath) { // Spawn directly in the path of the arrow based on current direction var distanceAhead = 1000 + Math.random() * 500; // Spawn far enough to give player time to react if (arrow.direction === "northeast") { // Position in the northeast path of the arrow obstacle.x = arrow.x + distanceAhead; obstacle.y = arrow.y - distanceAhead; } else { // Position in the southeast path of the arrow obstacle.x = arrow.x + distanceAhead; obstacle.y = arrow.y + distanceAhead; } } else if (spawnRegion < 0.7) { // Spawn directly to the right of the arrow (off-screen) obstacle.x = screenWidth + Math.random() * 200; // Just off-screen to the right obstacle.y = arrow.y; // Aligned with the arrow's y position } else { // Spawn above obstacle.x = screenWidth / 2 + Math.random() * 500; // Spread to the right of center obstacle.y = -200 - Math.random() * 200; // Just above the visible screen } obstacles.push(obstacle); game.addChild(obstacle); } // Generate bonuses function createBonus() { var bonus = new Bonus(); // Since arrow is fixed in center, use fixed screen coordinates var screenWidth = 2048; var screenHeight = 2732; // Spawn bonuses at the upper-right corner of visible screen var spawnRegion = Math.random(); if (spawnRegion < 0.6) { // Spawn to the right bonus.x = screenWidth + Math.random() * 300; // Just off-screen to the right bonus.y = screenHeight / 2 - Math.random() * 600; // Spread around middle height } else { // Spawn above bonus.x = screenWidth / 2 + Math.random() * 600; // Spread to the right of center bonus.y = -200 - Math.random() * 300; // Just above the visible screen } bonuses.push(bonus); game.addChild(bonus); } // Create dollar bill in appropriate direction function createDollarBill() { if (!arrow || !gameActive) { return; } var dollarBill = new DollarBill(arrow.direction); // Position the dollar bill in front of the arrow based on direction // Since the arrow is stationary, we position relative to the center var offsetDistance = 100; if (arrow.direction === "northeast") { dollarBill.x = arrow.x + offsetDistance; dollarBill.y = arrow.y - offsetDistance; dollarBill.rotation = -Math.PI / 4; // 45 degrees up } else { dollarBill.x = arrow.x + offsetDistance; dollarBill.y = arrow.y + offsetDistance; dollarBill.rotation = Math.PI / 4; // 45 degrees down } dollarBills.push(dollarBill); game.addChild(dollarBill); } // Create stonks text popup function createStonksText(isPositive, x, y) { var message = isPositive ? "STONKS!" : "NOT STONKS!"; var color = isPositive ? "#00FF00" : "#FF0000"; var stonksText = new StonksText(message, color); stonksText.x = x; stonksText.y = y; stonksText.animate(); stonksTexts.push(stonksText); game.addChild(stonksText); } // Game update loop game.update = function () { if (!gameStarted || !gameActive) { return; } // Check if we should create a moon (every 20,000 points) // Calculate the current "milestone" we've passed var currentMilestone = Math.floor(marketCap / moonAppearThreshold) * moonAppearThreshold; // If we've crossed a new 20,000 point threshold and we're not at a negative market cap if (currentMilestone > lastMoonCheckPoint && marketCap > 0) { // Create a new moon var moon = new Moon(); moons.push(moon); // Add to game at a lower z-index (behind everything except background) game.addChildAt(moon, game.getChildIndex(backgroundGrid) + 1); // Update the last checkpoint lastMoonCheckPoint = currentMilestone; } // Update the background grid backgroundGrid.update(); // Calculate spawn rate multipliers based on market cap var marketCapFactor = Math.max(0, marketCap) / 100; // Adjust scaling for rates to increase more gradually after 300% var scaleMultiplier; if (marketCapFactor <= 20) { // Up to 300% speed (market cap of 2000) scaleMultiplier = marketCapFactor; } else { // More gradual scaling after 300% scaleMultiplier = 20 + (marketCapFactor - 20) * 0.4; // Slower increase after 300% // Cap at 500% (market cap of 2000 + 5000 = 7000) scaleMultiplier = Math.min(scaleMultiplier, 40); // 40 is the cap for 500% } // Calculate rates with the new scaling var obstacleRate = Math.max(10, 60 - scaleMultiplier * 0.5); // Decrease from 60 down to 12 (500% of initial rate) var bonusRate = Math.max(36, 180 - scaleMultiplier * 1.0); // Decrease from 180 down to 36 (500% of initial rate) var dollarRate = Math.max(6, 30 - scaleMultiplier * 0.25); // Decrease from 30 down to 6 (500% of initial rate) // Scale stonksguy based on the current game speed - increases as the game speeds up // Calculate scale factor based on current speed (10 = normal speed, 50 = 500% speed) var speedScaleFactor = arrow.speed / 10; // 1.0 to 5.0 // Use a more moderate scaling that still shows growth but doesn't become too large var stonksGuyScale = 1.0 + (speedScaleFactor - 1) * 0.2; // Scale from 1.0 to 1.6 (at 500% speed) stonksGuy.scale.set(stonksGuyScale, stonksGuyScale); // Make stonksguy pulse (move up and down) every half second if (!stonksGuy.isPulsing) { var _pulseY = function pulseY() { tween(stonksGuy, { y: stonksGuy.originalY + 20 }, { duration: 483, easing: tween.easeInOut, onFinish: function onFinish() { tween(stonksGuy, { y: stonksGuy.originalY }, { duration: 483, easing: tween.easeInOut, onFinish: _pulseY }); } }); }; stonksGuy.isPulsing = true; stonksGuy.originalY = stonksGuy.y; _pulseY(); } // Create obstacles at dynamic intervals lastObstacleTime = lastObstacleTime + 1; if (lastObstacleTime > obstacleRate) { createObstacle(); lastObstacleTime = 0; } // Create bonuses at dynamic intervals lastBonusTime = lastBonusTime + 1; if (lastBonusTime > bonusRate) { createBonus(); lastBonusTime = 0; } // Create dollar bills at dynamic intervals lastDollarTime = lastDollarTime + 1; if (lastDollarTime > dollarRate) { createDollarBill(); lastDollarTime = 0; } // Update marketCap - increase when going northeast, decrease when going southeast var oldSpeed = arrow.speed; if (arrow.direction === "northeast") { marketCap += 1; } else if (arrow.direction === "southeast") { marketCap -= 1; } // Calculate current and previous spawn rates var prevMarketCapFactor = Math.max(0, marketCap - 1) / 100; var prevDollarRate = Math.max(10, 30 - prevMarketCapFactor * 5); var currentDollarRate = Math.max(10, 30 - marketCapFactor * 5); // Show visual feedback when speed increases significantly if (arrow.speed - oldSpeed > 0.5) { var speedText = new StonksText("SPEED UP!", "#FFFF00"); speedText.x = arrow.x; speedText.y = arrow.y - 100; speedText.animate(); stonksTexts.push(speedText); game.addChild(speedText); } // Show visual feedback when spawn rate increases significantly if (prevDollarRate - currentDollarRate > 0.5 && arrow.direction === "northeast") { var spawnText = new StonksText("SPAWN RATE UP!", "#00FFFF"); spawnText.x = arrow.x + 100; spawnText.y = arrow.y; spawnText.animate(); stonksTexts.push(spawnText); game.addChild(spawnText); } // Check if market cap has reached game-ending threshold of -10 if (marketCap <= -10 && gameActive) { // Game over gameActive = false; createStonksText(false, arrow.x, arrow.y); LK.getSound('crash').play(); // Flash screen red LK.effects.flashScreen(0xFF0000, 1000); // Show game over LK.setTimeout(function () { LK.setScore(marketCap); // Update high score if current market cap is higher if (marketCap > storage.highScore) { storage.highScore = marketCap; } LK.showGameOver(); }, 1500); } // Calculate rate percentages relative to initial rates for display // Cap display at 500% var speedPercentage = Math.min(500, Math.round(arrow.speed / 10 * 100)); var spawnRatePercentage = Math.min(500, Math.round(30 / dollarRate * 100)); marketCapText.setText("Stonk Market Cap: $" + marketCap + ".00"); // Check if obstacles are completely off-screen for (var i = obstacles.length - 1; i >= 0; i--) { // Remove obstacles that have moved off the left side of the screen if (obstacles[i].x < -200) { obstacles[i].destroy(); obstacles.splice(i, 1); } } // Check for bonuses that are off-screen for (var i = bonuses.length - 1; i >= 0; i--) { if (bonuses[i].x < -200 || bonuses[i].collected) { bonuses[i].destroy(); bonuses.splice(i, 1); } } // Remove faded stonks texts for (var i = stonksTexts.length - 1; i >= 0; i--) { if (stonksTexts[i].alpha <= 0) { stonksTexts[i].destroy(); stonksTexts.splice(i, 1); } } // Clean up dollar bills that are off-screen for (var i = dollarBills.length - 1; i >= 0; i--) { if (dollarBills[i].x < -200) { dollarBills[i].destroy(); dollarBills.splice(i, 1); } } // Clean up moons that are ready for removal for (var i = moons.length - 1; i >= 0; i--) { if (moons[i].readyForRemoval) { moons[i].destroy(); moons.splice(i, 1); } } // Check for collisions with obstacles for (var i = 0; i < obstacles.length; i++) { if (arrow.intersects(obstacles[i])) { // Game over gameActive = false; createStonksText(false, arrow.x, arrow.y); LK.getSound('crash').play(); // Stop background music immediately LK.stopMusic(); // Flash screen red LK.effects.flashScreen(0xFF0000, 1000); // Show game over LK.setTimeout(function () { LK.setScore(marketCap); // Update high score if current market cap is higher if (marketCap > storage.highScore) { storage.highScore = marketCap; } LK.showGameOver(); }, 1500); break; } } // Check for collisions with bonuses for (var i = bonuses.length - 1; i >= 0; i--) { if (!bonuses[i].collected && arrow.intersects(bonuses[i])) { // Collect bonus bonuses[i].collect(); LK.getSound('collect').play(); // Add bonus score var bonusValue = Math.floor(Math.random() * 1000) + 500; marketCap += bonusValue; // Show stonks text createStonksText(true, arrow.x, arrow.y); // Flash screen green LK.effects.flashScreen(0x00FF00, 300); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = "northeast"; // Starting direction
self.speed = 10; // Movement speed will be used for object movement
self.x = 2048 * (1 / 3); // Fixed position at 1/3 from left (2/3 left on screen)
self.y = 2732 * (2 / 3); // Fixed position at 2/3 down on screen
self.path = []; // Track arrow's path
self.hitboxScale = 0.3; // Make hitbox 30% of the actual size
// Override the intersects method to use a smaller hitbox
self.originalIntersects = self.intersects;
self.intersects = function (otherObject) {
// Store original width and height
var originalWidth = arrowGraphics.width;
var originalHeight = arrowGraphics.height;
// Temporarily scale down the width and height for collision detection
arrowGraphics.width *= self.hitboxScale;
arrowGraphics.height *= self.hitboxScale;
// Check collision with smaller hitbox
var result = self.originalIntersects.call(self, otherObject);
// Restore original width and height
arrowGraphics.width = originalWidth;
arrowGraphics.height = originalHeight;
return result;
};
self.update = function () {
// Direction changes based on touch state, but arrow doesn't move
if (!game.isTouching) {
// Not touching - arrow faces northeast
self.direction = "northeast";
arrowGraphics.rotation = -Math.PI / 4; // 45 degrees up
} else {
// Touching - arrow faces southeast
self.direction = "southeast";
arrowGraphics.rotation = Math.PI / 4; // 45 degrees down
}
// Adjust speed based on market cap
// Base speed of 10
// Allow scaling up to 500% (speed of 50)
var marketCapFactor = Math.max(0, marketCap) / 100;
var speedMultiplier;
if (marketCapFactor <= 20) {
// Up to 300% speed (market cap of 2000)
speedMultiplier = marketCapFactor * 0.5; // Original scaling
} else {
// More gradual scaling after 300%
speedMultiplier = 10 + (marketCapFactor - 20) * 0.2; // Slower increase after 300%
// Cap at 500% (total multiplier of 40)
speedMultiplier = Math.min(speedMultiplier, 40);
}
self.speed = Math.max(10, Math.min(50, 10 + speedMultiplier));
// Record fixed path for consistency
if (game.ticks % 5 === 0) {
self.path.push({
x: self.x,
y: self.y
});
}
};
// Direction is now controlled by touch state in update method
return self;
});
var BackgroundGrid = Container.expand(function () {
var self = Container.call(this);
var tileSize = 200; // Size of each grid square
var gridTiles = []; // Store all grid tiles
// Dark blue color for tiles, slightly lighter for outlines
var tileColor = 0x003366; // Dark blue
var outlineColor = 0x0066aa; // Lighter blue for outline
// Create the grid to cover screen with some buffer
self.createGrid = function () {
// Calculate how many tiles we need to cover the entire screen with buffer
var screenWidth = 2748;
var screenHeight = 2732;
// Add buffer to ensure full coverage when moving
var bufferMultiplier = 2;
var tilesX = Math.ceil(screenWidth * bufferMultiplier / tileSize) + 2;
var tilesY = Math.ceil(screenHeight * bufferMultiplier / tileSize) + 2;
// Center position to align with screen center
var centerX = screenWidth / 2;
var centerY = screenHeight / 2;
// Calculate starting position (top-left of grid)
var startX = centerX - tilesX * tileSize / 2;
var startY = centerY - tilesY * tileSize / 2;
// Create grid of square tiles
for (var x = 0; x < tilesX; x++) {
for (var y = 0; y < tilesY; y++) {
// Create tile as a Container
var tile = new Container();
// Create tile background
var bg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
width: tileSize,
height: tileSize,
tint: tileColor
});
// Create tile outline (slightly smaller to create border effect)
var outline = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
width: tileSize - 2,
height: tileSize - 2,
x: 1,
y: 1,
tint: outlineColor
});
tile.addChild(bg);
tile.addChild(outline);
// Position tile
tile.x = startX + x * tileSize;
tile.y = startY + y * tileSize;
// Initialize original position
tile.origX = tile.x;
tile.origY = tile.y;
// Store tile
gridTiles.push(tile);
self.addChild(tile);
}
}
};
// Move grid based on arrow direction and speed
self.update = function () {
if (!arrow || !arrow.direction) {
return;
}
var moveAmountX = 0;
var moveAmountY = 0;
// Move opposite to the arrow direction
if (arrow.direction === "northeast") {
// Move background southwest
moveAmountX = -arrow.speed;
moveAmountY = arrow.speed;
} else {
// Move background northwest
moveAmountX = -arrow.speed;
moveAmountY = -arrow.speed;
}
// Move all tiles
for (var i = 0; i < gridTiles.length; i++) {
var tile = gridTiles[i];
tile.x += moveAmountX;
tile.y += moveAmountY;
// Wrap tiles around when they move too far
if (tile.x < -tileSize * 2) {
tile.x += gridTiles.length * tileSize / Math.sqrt(gridTiles.length);
} else if (tile.x > 2048 + tileSize * 2) {
tile.x -= gridTiles.length * tileSize / Math.sqrt(gridTiles.length);
}
if (tile.y < -tileSize * 2) {
tile.y += gridTiles.length * tileSize / Math.sqrt(gridTiles.length);
} else if (tile.y > 2732 + tileSize * 2) {
tile.y -= gridTiles.length * tileSize / Math.sqrt(gridTiles.length);
}
}
};
return self;
});
var Bonus = Container.expand(function () {
var self = Container.call(this);
var bonusGraphics = self.attachAsset('bonus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.collected = false;
self.hitboxScale = 0.3; // Make hitbox 30% of the actual size
// Override the intersects method to use a smaller hitbox
self.originalIntersects = self.intersects;
self.intersects = function (otherObject) {
// Store original width and height
var originalWidth = bonusGraphics.width;
var originalHeight = bonusGraphics.height;
// Temporarily scale down the width and height for collision detection
bonusGraphics.width *= self.hitboxScale;
bonusGraphics.height *= self.hitboxScale;
// Check collision with smaller hitbox
var result = self.originalIntersects.call(self, otherObject);
// Restore original width and height
bonusGraphics.width = originalWidth;
bonusGraphics.height = originalHeight;
return result;
};
self.update = function () {
// Bonuses now move towards the arrow (opposite direction)
if (game.isTouching) {
// Move opposite to southeast direction
self.x -= arrow.speed;
self.y -= arrow.speed;
} else {
// Move opposite to northeast direction
self.x -= arrow.speed;
self.y += arrow.speed;
}
// Spin the bonus
//bonusGraphics.rotation += 0.05;
};
self.collect = function () {
self.collected = true;
tween(bonusGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut
});
};
return self;
});
var DollarBill = Container.expand(function (direction) {
var self = Container.call(this);
var color = direction === "northeast" ? 0x00FF00 : 0xFF0000;
var dollarGraphics = self.attachAsset('dollar', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
//dollarGraphics.rotation = Math.random() * Math.PI * 2; // Random rotation
dollarGraphics.scale.set(0.8, 0.5); // Make it more bill-shaped
// No need for self.speed as we'll use arrow.speed directly
self.direction = direction; // Store direction for movement
self.update = function () {
// Move in the opposite direction of what the arrow would move
// Use arrow's current speed for consistent movement
if (self.direction === "northeast") {
self.x -= arrow.speed;
self.y += arrow.speed;
} else {
self.x -= arrow.speed;
self.y -= arrow.speed;
}
};
return self;
});
var Moon = Container.expand(function () {
var self = Container.call(this);
// Create a white circular shape for the moon
var moonGraphics = self.attachAsset('moon', {
anchorX: 0.5,
anchorY: 0.5,
width: 300,
height: 300,
tint: 0xFFFFFF
});
// Set initial position off-screen in the northeast corner
self.x = 2548; // Just off-screen to the right
self.y = -300; // Just off-screen above
// Set slow movement speed
self.speed = 2;
self.update = function () {
// Move slowly from northeast to southwest
self.x -= self.speed;
self.y += self.speed;
// Remove when completely off-screen
if (self.x < -400 || self.y > 3132) {
self.readyForRemoval = true;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -10;
self.hitboxScale = 0.2; // Make hitbox 20% of the actual size
// Override the intersects method to use a smaller hitbox
self.originalIntersects = self.intersects;
self.intersects = function (otherObject) {
// Store original width and height
var originalWidth = obstacleGraphics.width;
var originalHeight = obstacleGraphics.height;
// Temporarily scale down the width and height for collision detection
obstacleGraphics.width *= self.hitboxScale;
obstacleGraphics.height *= self.hitboxScale;
// Check collision with smaller hitbox
var result = self.originalIntersects.call(self, otherObject);
// Restore original width and height
obstacleGraphics.width = originalWidth;
obstacleGraphics.height = originalHeight;
return result;
};
self.update = function () {
// Obstacles now move towards the arrow (opposite direction)
// Always use arrow's current speed for consistent movement
if (game.isTouching) {
// Move opposite to southeast direction
self.x -= arrow.speed;
self.y -= arrow.speed;
} else {
// Move opposite to northeast direction
self.x -= arrow.speed;
self.y += arrow.speed;
}
};
return self;
});
var StonksText = Container.expand(function (message, color) {
var self = Container.call(this);
var text = new Text2(message || "STONKS!", {
size: 100,
fill: color || "#00FF00"
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
self.animate = function () {
self.alpha = 1;
tween(self, {
alpha: 0,
y: self.y - 200
}, {
duration: 1500,
easing: tween.easeOut
});
tween(self.scale, {
x: 2,
y: 2
}, {
duration: 1500,
easing: tween.easeOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0066ff
});
/****
* Game Code
****/
// Track if the screen is being touched
// Game variables
game.isTouching = false;
var gameStarted = false; // Track if the game has been started by the first touch
// Camera functionality removed as the arrow now stays stationary
// and other objects move around it
var camera = {
update: function update() {} // Empty function to prevent errors
};
var arrow;
var obstacles = [];
var bonuses = [];
var stonksTexts = [];
var dollarBills = [];
var moons = [];
var lastObstacleTime = 0;
var lastBonusTime = 0;
var lastDollarTime = 0;
var lastMoonAppearance = 0;
var marketCap = 0;
var marketCapFactor = 0;
var gameActive = true;
var moonAppearThreshold = 9000; // Moon appears every 9,000 points
var lastMoonCheckPoint = 0; // Tracks the last point at which we checked for moon appearance
// Create background grid
var backgroundGrid = new BackgroundGrid();
backgroundGrid.createGrid();
game.addChild(backgroundGrid);
// Add background reference for backward compatibility
var background = {
x: 2048 / 2,
y: 2732 / 2
};
// Create GUI elements
var marketCapText = new Text2("Stonk Market Cap: $0.00", {
size: 60,
fill: 0xFFFFFF
});
marketCapText.anchor.set(0.5, 0);
LK.gui.top.addChild(marketCapText);
marketCapText.visible = false; // Hide initially
// Create startup logo
var logoText = new Text2("Stonks Go Up", {
size: 150,
fill: 0x00FF00
});
logoText.anchor.set(0.5, 1.2);
logoText.x = 2048 / 2;
logoText.y = 2732 / 2;
game.addChild(logoText);
// Add tap to start instruction
var startInstructionText = new Text2("Tap to Start", {
size: 80,
fill: 0xFFFFFF
});
startInstructionText.anchor.set(0.5, 0.5);
startInstructionText.x = 2048 / 2;
startInstructionText.y = 2732 / 2 + 200;
game.addChild(startInstructionText);
// Add high score display to the start screen
var highScoreText = new Text2("High Score: $" + storage.highScore + ".00", {
size: 60,
fill: 0xFFFFFF
});
highScoreText.anchor.set(0.5, 0);
highScoreText.x = 2048 / 2;
highScoreText.y = 2732 - 200;
game.addChild(highScoreText);
// Make the text pulse
tween(startInstructionText.scale, {
x: 1.1,
y: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
loop: -1,
yoyo: true
});
// Add stonksguy mascot to lower-left corner
var stonksGuy = game.addChild(LK.getAsset('stonksguy', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2732 - 120
}));
stonksGuy.visible = true; // Ensure stonksguy is visible
// Create arrow in the center of the screen
arrow = new Arrow();
// Arrow position is set in the class constructor
game.addChild(arrow);
// No camera setup needed since we have a fixed view
// Background music will play on first touch, not at initialization
// Handle touch events
game.down = function (x, y, obj) {
if (!gameStarted) {
// First touch - start the game
gameStarted = true;
// Start playing background music now
LK.playMusic('bgMusic');
// Hide the logo and instruction
tween(logoText, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onComplete: function onComplete() {
logoText.destroy();
}
});
tween(startInstructionText, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onComplete: function onComplete() {
startInstructionText.destroy();
}
});
// Show the market cap text
marketCapText.visible = true;
// Set touch state
game.isTouching = true;
} else if (gameActive) {
game.isTouching = true;
}
};
game.up = function (x, y, obj) {
if (gameActive) {
game.isTouching = false;
}
};
// Generate obstacles
function createObstacle() {
var obstacle = new Obstacle();
// Since arrow is fixed in center, use fixed screen coordinates
var screenWidth = 2048;
var screenHeight = 2732;
// Randomly decide if this obstacle should be directly in the arrow's path
var inPath = Math.random() < 0.4; // 40% chance to spawn in path
var spawnRegion = Math.random();
if (inPath) {
// Spawn directly in the path of the arrow based on current direction
var distanceAhead = 1000 + Math.random() * 500; // Spawn far enough to give player time to react
if (arrow.direction === "northeast") {
// Position in the northeast path of the arrow
obstacle.x = arrow.x + distanceAhead;
obstacle.y = arrow.y - distanceAhead;
} else {
// Position in the southeast path of the arrow
obstacle.x = arrow.x + distanceAhead;
obstacle.y = arrow.y + distanceAhead;
}
} else if (spawnRegion < 0.7) {
// Spawn directly to the right of the arrow (off-screen)
obstacle.x = screenWidth + Math.random() * 200; // Just off-screen to the right
obstacle.y = arrow.y; // Aligned with the arrow's y position
} else {
// Spawn above
obstacle.x = screenWidth / 2 + Math.random() * 500; // Spread to the right of center
obstacle.y = -200 - Math.random() * 200; // Just above the visible screen
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Generate bonuses
function createBonus() {
var bonus = new Bonus();
// Since arrow is fixed in center, use fixed screen coordinates
var screenWidth = 2048;
var screenHeight = 2732;
// Spawn bonuses at the upper-right corner of visible screen
var spawnRegion = Math.random();
if (spawnRegion < 0.6) {
// Spawn to the right
bonus.x = screenWidth + Math.random() * 300; // Just off-screen to the right
bonus.y = screenHeight / 2 - Math.random() * 600; // Spread around middle height
} else {
// Spawn above
bonus.x = screenWidth / 2 + Math.random() * 600; // Spread to the right of center
bonus.y = -200 - Math.random() * 300; // Just above the visible screen
}
bonuses.push(bonus);
game.addChild(bonus);
}
// Create dollar bill in appropriate direction
function createDollarBill() {
if (!arrow || !gameActive) {
return;
}
var dollarBill = new DollarBill(arrow.direction);
// Position the dollar bill in front of the arrow based on direction
// Since the arrow is stationary, we position relative to the center
var offsetDistance = 100;
if (arrow.direction === "northeast") {
dollarBill.x = arrow.x + offsetDistance;
dollarBill.y = arrow.y - offsetDistance;
dollarBill.rotation = -Math.PI / 4; // 45 degrees up
} else {
dollarBill.x = arrow.x + offsetDistance;
dollarBill.y = arrow.y + offsetDistance;
dollarBill.rotation = Math.PI / 4; // 45 degrees down
}
dollarBills.push(dollarBill);
game.addChild(dollarBill);
}
// Create stonks text popup
function createStonksText(isPositive, x, y) {
var message = isPositive ? "STONKS!" : "NOT STONKS!";
var color = isPositive ? "#00FF00" : "#FF0000";
var stonksText = new StonksText(message, color);
stonksText.x = x;
stonksText.y = y;
stonksText.animate();
stonksTexts.push(stonksText);
game.addChild(stonksText);
}
// Game update loop
game.update = function () {
if (!gameStarted || !gameActive) {
return;
}
// Check if we should create a moon (every 20,000 points)
// Calculate the current "milestone" we've passed
var currentMilestone = Math.floor(marketCap / moonAppearThreshold) * moonAppearThreshold;
// If we've crossed a new 20,000 point threshold and we're not at a negative market cap
if (currentMilestone > lastMoonCheckPoint && marketCap > 0) {
// Create a new moon
var moon = new Moon();
moons.push(moon);
// Add to game at a lower z-index (behind everything except background)
game.addChildAt(moon, game.getChildIndex(backgroundGrid) + 1);
// Update the last checkpoint
lastMoonCheckPoint = currentMilestone;
}
// Update the background grid
backgroundGrid.update();
// Calculate spawn rate multipliers based on market cap
var marketCapFactor = Math.max(0, marketCap) / 100;
// Adjust scaling for rates to increase more gradually after 300%
var scaleMultiplier;
if (marketCapFactor <= 20) {
// Up to 300% speed (market cap of 2000)
scaleMultiplier = marketCapFactor;
} else {
// More gradual scaling after 300%
scaleMultiplier = 20 + (marketCapFactor - 20) * 0.4; // Slower increase after 300%
// Cap at 500% (market cap of 2000 + 5000 = 7000)
scaleMultiplier = Math.min(scaleMultiplier, 40); // 40 is the cap for 500%
}
// Calculate rates with the new scaling
var obstacleRate = Math.max(10, 60 - scaleMultiplier * 0.5); // Decrease from 60 down to 12 (500% of initial rate)
var bonusRate = Math.max(36, 180 - scaleMultiplier * 1.0); // Decrease from 180 down to 36 (500% of initial rate)
var dollarRate = Math.max(6, 30 - scaleMultiplier * 0.25); // Decrease from 30 down to 6 (500% of initial rate)
// Scale stonksguy based on the current game speed - increases as the game speeds up
// Calculate scale factor based on current speed (10 = normal speed, 50 = 500% speed)
var speedScaleFactor = arrow.speed / 10; // 1.0 to 5.0
// Use a more moderate scaling that still shows growth but doesn't become too large
var stonksGuyScale = 1.0 + (speedScaleFactor - 1) * 0.2; // Scale from 1.0 to 1.6 (at 500% speed)
stonksGuy.scale.set(stonksGuyScale, stonksGuyScale);
// Make stonksguy pulse (move up and down) every half second
if (!stonksGuy.isPulsing) {
var _pulseY = function pulseY() {
tween(stonksGuy, {
y: stonksGuy.originalY + 20
}, {
duration: 483,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(stonksGuy, {
y: stonksGuy.originalY
}, {
duration: 483,
easing: tween.easeInOut,
onFinish: _pulseY
});
}
});
};
stonksGuy.isPulsing = true;
stonksGuy.originalY = stonksGuy.y;
_pulseY();
}
// Create obstacles at dynamic intervals
lastObstacleTime = lastObstacleTime + 1;
if (lastObstacleTime > obstacleRate) {
createObstacle();
lastObstacleTime = 0;
}
// Create bonuses at dynamic intervals
lastBonusTime = lastBonusTime + 1;
if (lastBonusTime > bonusRate) {
createBonus();
lastBonusTime = 0;
}
// Create dollar bills at dynamic intervals
lastDollarTime = lastDollarTime + 1;
if (lastDollarTime > dollarRate) {
createDollarBill();
lastDollarTime = 0;
}
// Update marketCap - increase when going northeast, decrease when going southeast
var oldSpeed = arrow.speed;
if (arrow.direction === "northeast") {
marketCap += 1;
} else if (arrow.direction === "southeast") {
marketCap -= 1;
}
// Calculate current and previous spawn rates
var prevMarketCapFactor = Math.max(0, marketCap - 1) / 100;
var prevDollarRate = Math.max(10, 30 - prevMarketCapFactor * 5);
var currentDollarRate = Math.max(10, 30 - marketCapFactor * 5);
// Show visual feedback when speed increases significantly
if (arrow.speed - oldSpeed > 0.5) {
var speedText = new StonksText("SPEED UP!", "#FFFF00");
speedText.x = arrow.x;
speedText.y = arrow.y - 100;
speedText.animate();
stonksTexts.push(speedText);
game.addChild(speedText);
}
// Show visual feedback when spawn rate increases significantly
if (prevDollarRate - currentDollarRate > 0.5 && arrow.direction === "northeast") {
var spawnText = new StonksText("SPAWN RATE UP!", "#00FFFF");
spawnText.x = arrow.x + 100;
spawnText.y = arrow.y;
spawnText.animate();
stonksTexts.push(spawnText);
game.addChild(spawnText);
}
// Check if market cap has reached game-ending threshold of -10
if (marketCap <= -10 && gameActive) {
// Game over
gameActive = false;
createStonksText(false, arrow.x, arrow.y);
LK.getSound('crash').play();
// Flash screen red
LK.effects.flashScreen(0xFF0000, 1000);
// Show game over
LK.setTimeout(function () {
LK.setScore(marketCap);
// Update high score if current market cap is higher
if (marketCap > storage.highScore) {
storage.highScore = marketCap;
}
LK.showGameOver();
}, 1500);
}
// Calculate rate percentages relative to initial rates for display
// Cap display at 500%
var speedPercentage = Math.min(500, Math.round(arrow.speed / 10 * 100));
var spawnRatePercentage = Math.min(500, Math.round(30 / dollarRate * 100));
marketCapText.setText("Stonk Market Cap: $" + marketCap + ".00");
// Check if obstacles are completely off-screen
for (var i = obstacles.length - 1; i >= 0; i--) {
// Remove obstacles that have moved off the left side of the screen
if (obstacles[i].x < -200) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
}
// Check for bonuses that are off-screen
for (var i = bonuses.length - 1; i >= 0; i--) {
if (bonuses[i].x < -200 || bonuses[i].collected) {
bonuses[i].destroy();
bonuses.splice(i, 1);
}
}
// Remove faded stonks texts
for (var i = stonksTexts.length - 1; i >= 0; i--) {
if (stonksTexts[i].alpha <= 0) {
stonksTexts[i].destroy();
stonksTexts.splice(i, 1);
}
}
// Clean up dollar bills that are off-screen
for (var i = dollarBills.length - 1; i >= 0; i--) {
if (dollarBills[i].x < -200) {
dollarBills[i].destroy();
dollarBills.splice(i, 1);
}
}
// Clean up moons that are ready for removal
for (var i = moons.length - 1; i >= 0; i--) {
if (moons[i].readyForRemoval) {
moons[i].destroy();
moons.splice(i, 1);
}
}
// Check for collisions with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (arrow.intersects(obstacles[i])) {
// Game over
gameActive = false;
createStonksText(false, arrow.x, arrow.y);
LK.getSound('crash').play();
// Stop background music immediately
LK.stopMusic();
// Flash screen red
LK.effects.flashScreen(0xFF0000, 1000);
// Show game over
LK.setTimeout(function () {
LK.setScore(marketCap);
// Update high score if current market cap is higher
if (marketCap > storage.highScore) {
storage.highScore = marketCap;
}
LK.showGameOver();
}, 1500);
break;
}
}
// Check for collisions with bonuses
for (var i = bonuses.length - 1; i >= 0; i--) {
if (!bonuses[i].collected && arrow.intersects(bonuses[i])) {
// Collect bonus
bonuses[i].collect();
LK.getSound('collect').play();
// Add bonus score
var bonusValue = Math.floor(Math.random() * 1000) + 500;
marketCap += bonusValue;
// Show stonks text
createStonksText(true, arrow.x, arrow.y);
// Flash screen green
LK.effects.flashScreen(0x00FF00, 300);
}
}
};
arrow pointing to the right like on a stock market ticker. No shadows
cartoonish dollar bill. In-Game asset. 2d. High contrast. No shadows
green stock market chart candle. In-Game asset. 2d. High contrast. No shadows
red stock market chart candle. In-Game asset. 2d. High contrast. No shadows
screen-wrappable repeating blue grid on dark background. In-Game asset. 2d. High contrast. No shadows
white full moon. In-Game asset. 2d. High contrast. No shadows