/****
* 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