User prompt
undo the last transaction you made
User prompt
scroll the Race 1 text to the right in the section where we set the bets
User prompt
hide the Race 1 article in the section where we set the bets
User prompt
Hide the Race 1 post
User prompt
don't let the race 1 post appear
User prompt
delete the race 1 post
User prompt
scroll up the part where we set the bets
User prompt
scroll up the part where we set the bets
User prompt
take the race track down to the start button
User prompt
undo the last transaction you made
User prompt
slide the horses names under the start race section along with the race track start and finish line
User prompt
the names of the horses are slightly shifted to the top
User prompt
slide the horses down little
User prompt
slide the horses down very little
User prompt
you're off to wrap up a little more horses names
User prompt
you're off to wrap up a little more horses names
User prompt
shift the average of the horses' jobs to the horse image on top of the horse
User prompt
name the horses
User prompt
let the sound of horse racing stop when the horses come to the finish
User prompt
slow down the speed of the horse race
User prompt
let the horse race that starts when you press the start race button last 5 seconds
User prompt
set the horse race to drive for 5 seconds,set the horse race sound to drive for 5 seconds
User prompt
activate the horse racing sound when you press start race
User prompt
undo the last transaction you made
User prompt
skips the race track slide down the start and finish line by 1 inch
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Horse class: represents a single horse in a race
var Horse = Container.expand(function () {
var self = Container.call(this);
// Asset: Each horse is a colored ellipse with a number label and name
var horseColor = self.horseColor || 0x888888;
var horseAsset = self.attachAsset('horseShape', {
width: 120,
height: 60,
color: horseColor,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Number label (top left of horse)
var numberText = new Text2(self.horseNumber ? String(self.horseNumber) : '?', {
size: 44,
fill: 0xFFFFFF
});
numberText.anchor.set(0, 0);
numberText.x = -50;
numberText.y = -28;
self.addChild(numberText);
// Name label removed (no name label on horse)
// Horse properties
self.horseNumber = self.horseNumber || 1;
self.odd = self.odd || 2.0;
self.lane = self.lane || 1;
self.speed = 0;
self.progress = 0; // 0 to 1
self.isRacing = false;
self.horseName = ""; // will be set in prepareForRace
// For animation
self.update = function () {
if (self.isRacing) {
// Move horse forward based on speed
self.progress += self.speed;
if (self.progress > 1) self.progress = 1;
// Update x position
self.x = self.startX + (self.finishX - self.startX) * self.progress;
}
};
// Set up for race
self.prepareForRace = function (startX, finishX, laneY, odd, horseNumber, color, horseName) {
self.startX = startX;
self.finishX = finishX;
self.y = laneY;
self.x = startX;
self.progress = 0;
self.odd = odd;
self.horseNumber = horseNumber;
horseAsset.tint = color;
numberText.setText(String(horseNumber));
self.horseColor = color;
self.horseName = horseName || "";
// nameText.setText(self.horseName); // removed, no name label
};
// Start racing
self.startRace = function (speed) {
self.isRacing = true;
self.speed = speed;
};
// Stop racing
self.stopRace = function () {
self.isRacing = false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a3d5c
});
/****
* Game Code
****/
// --- Game Constants ---
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var LANE_COUNT = 5;
var RACE_COUNT = 9;
var HORSE_COLORS = [0xf44336, 0x2196f3, 0x4caf50, 0xffeb3b, 0x9c27b0, 0xff9800, 0x00bcd4, 0x795548, 0x607d8b];
var LANE_HEIGHT = 180;
var TRACK_TOP = 600;
var TRACK_LEFT = 200;
var TRACK_RIGHT = GAME_WIDTH - 200;
var HORSE_SIZE = 120;
var START_BALANCE = 1000;
// --- Track Lines (Start/Finish) ---
var startLine = null;
var finishLine = null;
// --- Game State ---
var currentRace = 1;
var playerBalance = START_BALANCE;
var horses = [];
var raceOdds = [];
var raceResults = [];
var playerBets = [];
var isBettingOpen = true;
var winningHorse = null;
var raceInProgress = false;
var raceFinished = false;
var raceTimer = null;
var betButtons = [];
var betAmountInputs = [];
var betTexts = [];
var infoText = null;
var balanceText = null;
var raceText = null;
var betPanel = null;
var resultPanel = null;
var nextRaceButton = null;
// --- GUI Setup ---
// Balance display
balanceText = new Text2("Balance: $" + playerBalance, {
size: 80,
fill: 0xFFFFFF
});
balanceText.anchor.set(0.5, 0);
LK.gui.top.addChild(balanceText);
// Race number display
raceText = new Text2("Race 1 / " + RACE_COUNT, {
size: 60,
fill: 0xFFFFFF
});
raceText.anchor.set(0.5, 0);
LK.gui.top.addChild(raceText);
raceText.y = 90;
// Info text (centered)
infoText = new Text2("", {
size: 70,
fill: 0xFFFBE6
});
infoText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(infoText);
// --- Helper Functions ---
function getLaneY(lane) {
return TRACK_TOP + (lane - 1) * LANE_HEIGHT;
}
function randomOdd() {
// Odds between 1.5 and 6.0, rounded to 1 decimal
var odd = 1.5 + Math.random() * 4.5;
return Math.round(odd * 10) / 10;
}
function shuffleArray(arr) {
// Fisher-Yates shuffle
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
return arr;
}
function resetBets() {
playerBets = [];
for (var i = 0; i < LANE_COUNT; i++) {
playerBets.push(0);
}
}
function updateBalanceText() {
balanceText.setText("Balance: $" + playerBalance);
}
function updateRaceText() {
raceText.setText("Race " + currentRace + " / " + RACE_COUNT);
}
function showInfo(msg, duration) {
infoText.setText(msg);
infoText.visible = true;
if (duration) {
LK.setTimeout(function () {
infoText.setText("");
infoText.visible = false;
}, duration);
}
}
function showResultPanel(winning, payout) {
if (!resultPanel) {
resultPanel = new Container();
var bg = LK.getAsset('resultBg', {
width: 900,
height: 500,
color: 0x222222,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
resultPanel.addChild(bg);
resultPanel.x = GAME_WIDTH / 2;
resultPanel.y = GAME_HEIGHT / 2;
resultPanel.zIndex = 1000;
resultPanel.visible = false;
game.addChild(resultPanel);
resultPanel.resultText = new Text2("", {
size: 80,
fill: 0xFFFBE6
});
resultPanel.resultText.anchor.set(0.5, 0.5);
resultPanel.resultText.y = -60;
resultPanel.addChild(resultPanel.resultText);
resultPanel.payoutText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
resultPanel.payoutText.anchor.set(0.5, 0.5);
resultPanel.payoutText.y = 60;
resultPanel.addChild(resultPanel.payoutText);
}
resultPanel.resultText.setText("Winner: #" + winning);
if (payout > 0) {
resultPanel.payoutText.setText("You won $" + payout + "!");
} else {
resultPanel.payoutText.setText("No winnings this race.");
}
resultPanel.visible = true;
LK.setTimeout(function () {
resultPanel.visible = false;
}, 1800);
}
// --- Bet Panel Setup ---
function setupBetPanel() {
if (betPanel) {
betPanel.destroy();
betPanel = null;
}
betPanel = new Container();
betPanel.x = GAME_WIDTH / 2;
betPanel.y = TRACK_TOP - 120;
game.addChild(betPanel);
// Title removed: No 'Place Your Bets!' post
// For each horse, show odds, bet amount, and a button to increase bet
betButtons = [];
betAmountInputs = [];
betTexts = [];
for (var i = 0; i < LANE_COUNT; i++) {
(function (idx) {
var laneY = i * 90;
// Horse number and odds
var horseLabel = new Text2("#" + (idx + 1) + " (" + raceOdds[idx] + "x)", {
size: 48,
fill: 0xFFFFFF
});
horseLabel.anchor.set(0, 0.5);
horseLabel.x = -320;
horseLabel.y = laneY;
betPanel.addChild(horseLabel);
// Bet amount text
var betText = new Text2("$" + playerBets[idx], {
size: 48,
fill: 0xFFFBE6
});
betText.anchor.set(0.5, 0.5);
betText.x = 0;
betText.y = laneY;
betPanel.addChild(betText);
betTexts.push(betText);
// Bet + button
var betBtn = LK.getAsset('betBtn', {
width: 90,
height: 60,
color: 0x4caf50,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 180,
y: laneY
});
betPanel.addChild(betBtn);
betButtons.push(betBtn);
// Bet - button
var betMinusBtn = LK.getAsset('betMinusBtn', {
width: 90,
height: 60,
color: 0xf44336,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 90,
y: laneY
});
betPanel.addChild(betMinusBtn);
// + Button event
betBtn.down = function (x, y, obj) {
if (!isBettingOpen) return;
if (playerBalance >= 10) {
playerBets[idx] += 10;
playerBalance -= 10;
betTexts[idx].setText("$" + playerBets[idx]);
updateBalanceText();
}
};
// - Button event
betMinusBtn.down = function (x, y, obj) {
if (!isBettingOpen) return;
if (playerBets[idx] >= 10) {
playerBets[idx] -= 10;
playerBalance += 10;
betTexts[idx].setText("$" + playerBets[idx]);
updateBalanceText();
}
};
})(i);
}
// Start Race button
var startBtn = LK.getAsset('startBtn', {
width: 320,
height: 90,
color: 0x2196f3,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 480
});
betPanel.addChild(startBtn);
var startBtnText = new Text2("Start Race", {
size: 54,
fill: 0xFFFFFF
});
startBtnText.anchor.set(0.5, 0.5);
startBtnText.x = 0;
startBtnText.y = 480;
betPanel.addChild(startBtnText);
startBtn.down = function (x, y, obj) {
if (!isBettingOpen) return;
// Must bet at least on one horse
var totalBet = 0;
for (var i = 0; i < LANE_COUNT; i++) totalBet += playerBets[i];
if (totalBet === 0) {
showInfo("Place a bet to start!", 1200);
return;
}
isBettingOpen = false;
betPanel.visible = false;
// Play horse racing sound
LK.getSound('horserace').play();
startRace();
};
}
// --- Race Setup ---
function setupRace() {
// Remove previous horses
for (var i = 0; i < horses.length; i++) {
horses[i].destroy();
}
horses = [];
// Remove previous lines if they exist
if (startLine) {
startLine.destroy();
startLine = null;
}
if (finishLine) {
finishLine.destroy();
finishLine = null;
}
// --- RACE HEADER & HORSE NAMES ---
// Remove previous race header/names if present
if (game.raceHeader) {
game.raceHeader.destroy();
game.raceHeader = null;
}
if (game.horseNameLabels) {
for (var i = 0; i < game.horseNameLabels.length; i++) {
game.horseNameLabels[i].destroy();
}
game.horseNameLabels = null;
}
// Race header (e.g. "Race 1")
game.raceHeader = new Text2("Race " + currentRace, {
size: 90,
fill: 0xFFFBE6
});
game.raceHeader.anchor.set(0.5, 0.5);
game.raceHeader.x = GAME_WIDTH / 2;
game.raceHeader.y = TRACK_TOP - 180;
game.addChild(game.raceHeader);
// Example horse names (can be replaced with dynamic names if desired)
var HORSE_NAMES = ["Thunderbolt", "Blue Streak", "Green Flash", "Gold Rush", "Purple Haze", "Orange Blaze", "Aqua Jet", "Brown Sugar", "Steel Runner"];
// Draw start line (restored to original position)
startLine = LK.getAsset('betMinusBtn', {
width: 18,
height: LANE_HEIGHT * LANE_COUNT + 40,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0,
x: TRACK_LEFT,
y: TRACK_TOP - 20
});
game.addChild(startLine);
// Draw finish line (restored to original position)
finishLine = LK.getAsset('betBtn', {
width: 18,
height: LANE_HEIGHT * LANE_COUNT + 40,
color: 0xffd700,
shape: 'box',
anchorX: 0.5,
anchorY: 0,
x: TRACK_RIGHT,
y: TRACK_TOP - 20
});
game.addChild(finishLine);
// Generate odds for this race
raceOdds = [];
for (var i = 0; i < LANE_COUNT; i++) {
raceOdds.push(randomOdd());
}
// Shuffle horse colors for variety
var colorOrder = [];
for (var i = 0; i < LANE_COUNT; i++) colorOrder.push(HORSE_COLORS[i % HORSE_COLORS.length]);
shuffleArray(colorOrder);
// Create horses
game.horseNameLabels = [];
for (var i = 0; i < LANE_COUNT; i++) {
var horse = new Horse();
// Slide horses to just above the start line (bottom of the start race section)
var laneY = getLaneY(i + 1);
// Offset horses so their center is just above the start line, and slide down a little more (e.g. +32px)
var horseY = laneY + LANE_HEIGHT / 2 - HORSE_SIZE / 2 + 32;
horse.prepareForRace(TRACK_LEFT, TRACK_RIGHT, horseY, raceOdds[i], i + 1, colorOrder[i], HORSE_NAMES[i] // pass horse name
);
horses.push(horse);
game.addChild(horse);
// Add horse name label under the start race section, aligned horizontally with the horse's lane
var nameLabel = new Text2(HORSE_NAMES[i], {
size: 48,
fill: 0xFFFBE6
});
nameLabel.anchor.set(0.5, 0);
// Place the name label below the start race section, aligned with the start and finish lines
nameLabel.x = TRACK_LEFT + (TRACK_RIGHT - TRACK_LEFT) * i / (LANE_COUNT - 1);
nameLabel.y = TRACK_TOP - 80;
game.addChild(nameLabel);
game.horseNameLabels.push(nameLabel);
}
resetBets();
isBettingOpen = true;
raceInProgress = false;
raceFinished = false;
winningHorse = null;
updateRaceText();
setupBetPanel();
showInfo("Race " + currentRace + ": Place your bets!", 1200);
}
// --- Race Logic ---
function startRace() {
raceInProgress = true;
raceFinished = false;
showInfo("They're off!", 1000);
// Assign random speeds, but ensure one winner
// SLOWER: Reduce base and winner speed
var baseSpeed = 0.003 + Math.random() * 0.001; // All horses move at least this fast (halved)
var winnerIdx = Math.floor(Math.random() * LANE_COUNT);
var winnerSpeed = baseSpeed + 0.001 + Math.random() * 0.001; // winner is also slower
for (var i = 0; i < LANE_COUNT; i++) {
if (i === winnerIdx) {
horses[i].startRace(winnerSpeed);
} else {
// Randomize, but not faster than winner
var s = baseSpeed + Math.random() * (winnerSpeed - baseSpeed - 0.0005);
horses[i].startRace(s);
}
}
winningHorse = winnerIdx + 1;
// Stop the race and sound after 5 seconds
if (raceTimer) {
LK.clearTimeout(raceTimer);
}
raceTimer = LK.setTimeout(function () {
if (raceInProgress && !raceFinished) {
// Stop all horses
for (var i = 0; i < LANE_COUNT; i++) {
horses[i].stopRace();
}
raceInProgress = false;
raceFinished = true;
// Stop the horse race sound
LK.getSound('horserace').stop && LK.getSound('horserace').stop();
// If the winner hasn't crossed, finish the race anyway
finishRace();
}
}, 5000);
}
function finishRace() {
raceInProgress = false;
raceFinished = true;
// Stop all horses
for (var i = 0; i < LANE_COUNT; i++) {
horses[i].stopRace();
}
// Calculate payout
var payout = 0;
if (playerBets[winningHorse - 1] > 0) {
payout = Math.floor(playerBets[winningHorse - 1] * raceOdds[winningHorse - 1]);
playerBalance += payout;
}
updateBalanceText();
showResultPanel(winningHorse, payout);
// Store result
raceResults.push({
race: currentRace,
winner: winningHorse,
odds: raceOdds.slice(),
bets: playerBets.slice(),
payout: payout
});
// Next race or end
if (currentRace < RACE_COUNT) {
LK.setTimeout(function () {
currentRace++;
setupRace();
}, 2000);
} else {
LK.setTimeout(function () {
endGame();
}, 2200);
}
}
function endGame() {
// Show final result
var finalPanel = new Container();
var bg = LK.getAsset('finalBg', {
width: 1100,
height: 700,
color: 0x222222,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
finalPanel.addChild(bg);
finalPanel.x = GAME_WIDTH / 2;
finalPanel.y = GAME_HEIGHT / 2;
finalPanel.zIndex = 2000;
game.addChild(finalPanel);
var title = new Text2("Derby Complete!", {
size: 100,
fill: 0xFFFBE6
});
title.anchor.set(0.5, 0.5);
title.y = -220;
finalPanel.addChild(title);
var bal = new Text2("Final Balance: $" + playerBalance, {
size: 80,
fill: 0xFFFFFF
});
bal.anchor.set(0.5, 0.5);
bal.y = -80;
finalPanel.addChild(bal);
var summary = new Text2("Thanks for playing!", {
size: 60,
fill: 0xFFFBE6
});
summary.anchor.set(0.5, 0.5);
summary.y = 60;
finalPanel.addChild(summary);
// Show "You Win" if balance > start, else "Game Over"
if (playerBalance > START_BALANCE) {
LK.setTimeout(function () {
LK.showYouWin();
}, 1800);
} else {
LK.setTimeout(function () {
LK.showGameOver();
}, 1800);
}
}
// --- Game Update Loop ---
game.update = function () {
if (raceInProgress) {
// Update horses
var finishedCount = 0;
for (var i = 0; i < horses.length; i++) {
horses[i].update();
// Keep the horse name label under the start race section, aligned with the start and finish lines
if (game.horseNameLabels && game.horseNameLabels[i]) {
game.horseNameLabels[i].x = TRACK_LEFT + (TRACK_RIGHT - TRACK_LEFT) * i / (LANE_COUNT - 1);
game.horseNameLabels[i].y = TRACK_TOP - 80;
// Always update the text in case horse names change dynamically
game.horseNameLabels[i].setText(horses[i].horseName || "");
}
if (horses[i].progress >= 1) finishedCount++;
}
// If winner crosses finish, finish race
if (!raceFinished && horses[winningHorse - 1].progress >= 1) {
// Stop the horse race sound immediately when winner finishes
LK.getSound('horserace').stop && LK.getSound('horserace').stop();
finishRace();
}
}
};
// --- Start the first race ---
setupRace();
updateBalanceText();
updateRaceText(); ===================================================================
--- original.js
+++ change.js
@@ -430,17 +430,17 @@
horse.prepareForRace(TRACK_LEFT, TRACK_RIGHT, horseY, raceOdds[i], i + 1, colorOrder[i], HORSE_NAMES[i] // pass horse name
);
horses.push(horse);
game.addChild(horse);
- // Add horse name label centered above each horse image
+ // Add horse name label under the start race section, aligned horizontally with the horse's lane
var nameLabel = new Text2(HORSE_NAMES[i], {
size: 48,
fill: 0xFFFBE6
});
- nameLabel.anchor.set(0.5, 1);
- // Center the name label horizontally above the horse image, and shift it slightly higher
- nameLabel.x = horse.x;
- nameLabel.y = horseY - 28;
+ nameLabel.anchor.set(0.5, 0);
+ // Place the name label below the start race section, aligned with the start and finish lines
+ nameLabel.x = TRACK_LEFT + (TRACK_RIGHT - TRACK_LEFT) * i / (LANE_COUNT - 1);
+ nameLabel.y = TRACK_TOP - 80;
game.addChild(nameLabel);
game.horseNameLabels.push(nameLabel);
}
resetBets();
@@ -580,12 +580,12 @@
// Update horses
var finishedCount = 0;
for (var i = 0; i < horses.length; i++) {
horses[i].update();
- // Move the horse name label to stay above the horse as it moves, and shift it slightly higher
+ // Keep the horse name label under the start race section, aligned with the start and finish lines
if (game.horseNameLabels && game.horseNameLabels[i]) {
- game.horseNameLabels[i].x = horses[i].x;
- game.horseNameLabels[i].y = horses[i].y - 28;
+ game.horseNameLabels[i].x = TRACK_LEFT + (TRACK_RIGHT - TRACK_LEFT) * i / (LANE_COUNT - 1);
+ game.horseNameLabels[i].y = TRACK_TOP - 80;
// Always update the text in case horse names change dynamically
game.horseNameLabels[i].setText(horses[i].horseName || "");
}
if (horses[i].progress >= 1) finishedCount++;
image of a racehorse. In-Game asset. 2d. High contrast. No shadows
pressable round button. In-Game asset. 2d. High contrast. No shadows
blue
green rectangle-shaped pressable button. In-Game asset. 2d. High contrast. No shadows
a line consisting of small squares in black and white is vertical from what happened at the races. In-Game asset. 2d. High contrast. No shadows