/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { coins: 100 }); /**** * Classes ****/ var Button = Container.expand(function (text, width, height) { var self = Container.call(this); var background = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: width || 200, height: height || 80 }); var label = new Text2(text || 'Button', { size: 36, fill: 0xFFFFFF }); label.anchor.set(0.5, 0.5); self.addChild(label); self.disabled = false; self.setText = function (newText) { label.setText(newText); return self; }; self.disable = function () { self.disabled = true; background.alpha = 0.5; return self; }; self.enable = function () { self.disabled = false; background.alpha = 1.0; return self; }; self.down = function (x, y, obj) { if (!self.disabled) { background.alpha = 0.7; } }; self.up = function (x, y, obj) { if (!self.disabled) { background.alpha = 1.0; } }; return self; }); var Lever = Container.expand(function () { var self = Container.call(this); self.isDown = false; self.isAnimating = false; self.onPullComplete = null; var base = self.attachAsset('leverBase', { anchorX: 0.5, anchorY: 1.0 }); var handle = self.attachAsset('leverHandle', { anchorX: 0.5, anchorY: 1.0, y: -50 }); var knob = self.attachAsset('leverKnob', { anchorX: 0.5, anchorY: 0.5, y: -275 }); self.down = function (x, y, obj) { if (!self.isAnimating && !self.isDown) { self.isDown = true; self.pullDown(); } }; self.pullDown = function () { self.isAnimating = true; LK.getSound('leverPull').play(); // Animate the lever down tween(handle, { rotation: Math.PI / 3 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { // Pull complete, trigger callback if (self.onPullComplete) { self.onPullComplete(); } // Return to original position after delay LK.setTimeout(function () { tween(handle, { rotation: 0 }, { duration: 500, easing: tween.elasticOut, onFinish: function onFinish() { self.isAnimating = false; self.isDown = false; } }); }, 500); } }); }; return self; }); var Reel = Container.expand(function () { var self = Container.call(this); self.isSpinning = false; self.spinSpeed = 0; self.spinTime = 0; self.maxSpinTime = 0; self.finalSymbol = 0; self.onStopCallback = null; var background = self.attachAsset('reelBackground', { anchorX: 0.5, anchorY: 0.5 }); var symbols = []; var symbolPositions = [-140, 0, 140]; for (var i = 0; i < 3; i++) { var symbol = new SymbolDisplay(); symbol.setSymbol(Math.floor(Math.random() * 3) + 1); symbol.y = symbolPositions[i]; symbols.push(symbol); self.addChild(symbol); } self.getCurrentSymbol = function () { // The middle symbol is the active one return symbols[1].symbolValue; }; self.spin = function (duration, finalSymbolValue, callback) { self.isSpinning = true; self.spinSpeed = 80; // Increase speed for long rolling effect self.spinTime = 0; self.maxSpinTime = duration; self.finalSymbol = finalSymbolValue; self.onStopCallback = callback; return self; }; self.update = function () { if (!self.isSpinning) { return; } self.spinTime += 1 / 60; // assuming 60 FPS // Move symbols down for (var i = 0; i < symbols.length; i++) { symbols[i].y += self.spinSpeed; // If a symbol goes beyond the visible area, move it to the top if (symbols[i].y > 280) { symbols[i].y = -280; // Randomize symbols during spin if (self.spinTime < self.maxSpinTime - 0.5) { symbols[i].setSymbol(Math.floor(Math.random() * 3) + 1); } else { // When approaching end, set to final values var offset = i - 1; var targetSymbol = (self.finalSymbol + offset) % 3 + 1; symbols[i].setSymbol(targetSymbol); } } } // Slow down and stop at the right time if (self.spinTime >= self.maxSpinTime) { self.isSpinning = false; // Ensure the middle symbol is exactly at y=0 for (var j = 0; j < symbols.length; j++) { symbols[j].y = symbolPositions[j]; } LK.getSound('reelStop').play(); if (self.onStopCallback) { self.onStopCallback(); } } else if (self.spinTime > self.maxSpinTime - 0.5) { // Slow down gradually self.spinSpeed = Math.max(5, self.spinSpeed * 0.98); // Adjust slow down rate for long rolling effect } }; return self; }); var SymbolDisplay = Container.expand(function () { var self = Container.call(this); self.symbolValue = 0; self.symbolGraphic = null; self.setSymbol = function (symbolId) { if (self.symbolGraphic) { self.removeChild(self.symbolGraphic); } self.symbolValue = symbolId; var assetId = 'symbol' + symbolId; self.symbolGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); return self; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Bar // Lemon // Cherry // Game state var coins = storage.coins || 100; var betAmount = 10; var isSpinning = false; var spinResults = [0, 0, 0]; var reels = []; var activeReels = 0; // Constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var REEL_SPACING = 200; var SYMBOL_VALUES = { "1-1-1": 30, // Reduce win amount for three cherries "2-2-2": 60, // Reduce win amount for three lemons "3-3-3": 120, // Reduce win amount for three bars (jackpot) "1-1-2": 15, // Two cherries and a lemon "1-1-3": 15, // Two cherries and a bar "2-2-1": 15, // Two lemons and a cherry "2-2-3": 15, // Two lemons and a bar "1-2-3": 5 // One of each }; // Create main slot machine components var slotMachine = new Container(); game.addChild(slotMachine); slotMachine.x = GAME_WIDTH / 2; slotMachine.y = GAME_HEIGHT / 2 - 196; // Background var background = slotMachine.addChild(LK.getAsset('slotBackground', { anchorX: 0.5, anchorY: 0.5 })); // Main frame var frame = slotMachine.addChild(LK.getAsset('slotFrame', { anchorX: 0.5, anchorY: 0.5, y: -98 })); // Add 3 reels for (var i = 0; i < 3; i++) { var reel = new Reel(); reel.x = (i - 1) * REEL_SPACING * 1.96; reel.y = -98; slotMachine.addChild(reel); reels.push(reel); } // Payline indicators var leftIndicator = slotMachine.addChild(LK.getAsset('paylineIndicator', { anchorX: 0.5, anchorY: 0.5, x: -686, y: -98 })); var rightIndicator = slotMachine.addChild(LK.getAsset('paylineIndicator', { anchorX: 0.5, anchorY: 0.5, x: 686, y: -98 })); // Lever var lever = new Lever(); lever.x = 784; lever.y = 294; slotMachine.addChild(lever); // Set up lever callback lever.onPullComplete = function () { if (!isSpinning && coins >= betAmount) { startSpin(); } }; // Create UI elements var coinsDisplay = new Text2("Coins: " + coins, { size: 60, fill: 0xFFD700 }); coinsDisplay.anchor.set(0.5, 0.5); LK.gui.top.addChild(coinsDisplay); coinsDisplay.y = 196; var betButton = new Button("Bet: " + betAmount, 200, 80); betButton.x = GAME_WIDTH / 2; betButton.y = GAME_HEIGHT - 588; game.addChild(betButton); var cashOutButton = new Button("Cash Out", 200, 80); cashOutButton.x = GAME_WIDTH / 2 + 490; cashOutButton.y = GAME_HEIGHT - 588; game.addChild(cashOutButton); var spinButton = new Button("SPIN", 200, 80); spinButton.x = GAME_WIDTH / 2 - 490; spinButton.y = GAME_HEIGHT - 588; game.addChild(spinButton); var winText = new Text2("", { size: 70, fill: 0xFFD700 }); winText.anchor.set(0.5, 0.5); winText.y = GAME_HEIGHT / 2 + 490; winText.x = GAME_WIDTH / 2; game.addChild(winText); // Button event handlers spinButton.down = function (x, y, obj) { this.down.call(this, x, y, obj); if (!isSpinning && coins >= betAmount) { startSpin(); } }; betButton.down = function (x, y, obj) { this.down.call(this, x, y, obj); if (!isSpinning) { cycleBet(); } }; cashOutButton.down = function (x, y, obj) { this.down.call(this, x, y, obj); if (!isSpinning) { storage.coins = coins; LK.showYouWin(); } }; // Game functions function updateCoinsDisplay() { coinsDisplay.setText("Coins: " + coins); storage.coins = coins; } function cycleBet() { var betOptions = [5, 10, 25, 50, 100]; var currentIndex = betOptions.indexOf(betAmount); var nextIndex = (currentIndex + 1) % betOptions.length; betAmount = betOptions[nextIndex]; // Don't allow bets higher than current coins if (betAmount > coins) { betAmount = betOptions[0]; } betButton.setText("Bet: " + betAmount); } function startSpin() { if (isSpinning) { return; } // Deduct coins for the bet coins -= betAmount; updateCoinsDisplay(); // Clear any previous win display winText.setText(""); // Disable buttons during spin spinButton.disable(); betButton.disable(); isSpinning = true; activeReels = 0; LK.getSound('reelSpin').play(); // Generate random results for each reel for (var i = 0; i < 3; i++) { spinResults[i] = Math.floor(Math.random() * 4) + 1; // Increase range to reduce winning probability if (spinResults[i] > 3) { spinResults[i] = 1; } // Map any value greater than 3 back to 1 } // Spin each reel with staggered timing for (var i = 0; i < reels.length; i++) { var spinDuration = 5 + i * 1.0; // Further increase duration for an even longer rolling effect reels[i].spin(spinDuration, spinResults[i], function () { activeReels++; if (activeReels >= 3) { spinCompleted(); } }); } } function spinCompleted() { isSpinning = false; // Enable buttons again spinButton.enable(); betButton.enable(); // Check for winning combinations var combination = spinResults.join('-'); var winAmount = 0; // Check exact combinations if (SYMBOL_VALUES[combination]) { winAmount = SYMBOL_VALUES[combination] * betAmount / 10; } else { // Check for pairs (same symbol in first two positions) if (spinResults[0] === spinResults[1]) { winAmount = 2 * betAmount / 10; } else if (spinResults[1] === spinResults[2]) { winAmount = 2 * betAmount / 10; } else if (spinResults[0] === spinResults[2]) { winAmount = 2 * betAmount / 10; } } if (winAmount > 0) { // Award winnings coins += winAmount; updateCoinsDisplay(); // Display win message winText.setText("WIN: " + winAmount + " COINS!"); // Play appropriate sound if (combination === "3-3-3") { // Jackpot win! LK.getSound('jackpot').play(); LK.effects.flashScreen(0xFFD700, 1000); // Gold flash for jackpot } else { LK.getSound('win').play(); } } // Check if player is out of coins if (coins <= 0) { LK.setTimeout(function () { LK.showGameOver(); }, 2000); } } // Start background music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Update function game.update = function () { // Update all reels for (var i = 0; i < reels.length; i++) { reels[i].update(); } // Disable spin button if not enough coins if (coins < betAmount && !spinButton.disabled) { spinButton.disable(); } else if (coins >= betAmount && spinButton.disabled && !isSpinning) { spinButton.enable(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
coins: 100
});
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 200,
height: height || 80
});
var label = new Text2(text || 'Button', {
size: 36,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.disabled = false;
self.setText = function (newText) {
label.setText(newText);
return self;
};
self.disable = function () {
self.disabled = true;
background.alpha = 0.5;
return self;
};
self.enable = function () {
self.disabled = false;
background.alpha = 1.0;
return self;
};
self.down = function (x, y, obj) {
if (!self.disabled) {
background.alpha = 0.7;
}
};
self.up = function (x, y, obj) {
if (!self.disabled) {
background.alpha = 1.0;
}
};
return self;
});
var Lever = Container.expand(function () {
var self = Container.call(this);
self.isDown = false;
self.isAnimating = false;
self.onPullComplete = null;
var base = self.attachAsset('leverBase', {
anchorX: 0.5,
anchorY: 1.0
});
var handle = self.attachAsset('leverHandle', {
anchorX: 0.5,
anchorY: 1.0,
y: -50
});
var knob = self.attachAsset('leverKnob', {
anchorX: 0.5,
anchorY: 0.5,
y: -275
});
self.down = function (x, y, obj) {
if (!self.isAnimating && !self.isDown) {
self.isDown = true;
self.pullDown();
}
};
self.pullDown = function () {
self.isAnimating = true;
LK.getSound('leverPull').play();
// Animate the lever down
tween(handle, {
rotation: Math.PI / 3
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Pull complete, trigger callback
if (self.onPullComplete) {
self.onPullComplete();
}
// Return to original position after delay
LK.setTimeout(function () {
tween(handle, {
rotation: 0
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
self.isAnimating = false;
self.isDown = false;
}
});
}, 500);
}
});
};
return self;
});
var Reel = Container.expand(function () {
var self = Container.call(this);
self.isSpinning = false;
self.spinSpeed = 0;
self.spinTime = 0;
self.maxSpinTime = 0;
self.finalSymbol = 0;
self.onStopCallback = null;
var background = self.attachAsset('reelBackground', {
anchorX: 0.5,
anchorY: 0.5
});
var symbols = [];
var symbolPositions = [-140, 0, 140];
for (var i = 0; i < 3; i++) {
var symbol = new SymbolDisplay();
symbol.setSymbol(Math.floor(Math.random() * 3) + 1);
symbol.y = symbolPositions[i];
symbols.push(symbol);
self.addChild(symbol);
}
self.getCurrentSymbol = function () {
// The middle symbol is the active one
return symbols[1].symbolValue;
};
self.spin = function (duration, finalSymbolValue, callback) {
self.isSpinning = true;
self.spinSpeed = 80; // Increase speed for long rolling effect
self.spinTime = 0;
self.maxSpinTime = duration;
self.finalSymbol = finalSymbolValue;
self.onStopCallback = callback;
return self;
};
self.update = function () {
if (!self.isSpinning) {
return;
}
self.spinTime += 1 / 60; // assuming 60 FPS
// Move symbols down
for (var i = 0; i < symbols.length; i++) {
symbols[i].y += self.spinSpeed;
// If a symbol goes beyond the visible area, move it to the top
if (symbols[i].y > 280) {
symbols[i].y = -280;
// Randomize symbols during spin
if (self.spinTime < self.maxSpinTime - 0.5) {
symbols[i].setSymbol(Math.floor(Math.random() * 3) + 1);
} else {
// When approaching end, set to final values
var offset = i - 1;
var targetSymbol = (self.finalSymbol + offset) % 3 + 1;
symbols[i].setSymbol(targetSymbol);
}
}
}
// Slow down and stop at the right time
if (self.spinTime >= self.maxSpinTime) {
self.isSpinning = false;
// Ensure the middle symbol is exactly at y=0
for (var j = 0; j < symbols.length; j++) {
symbols[j].y = symbolPositions[j];
}
LK.getSound('reelStop').play();
if (self.onStopCallback) {
self.onStopCallback();
}
} else if (self.spinTime > self.maxSpinTime - 0.5) {
// Slow down gradually
self.spinSpeed = Math.max(5, self.spinSpeed * 0.98); // Adjust slow down rate for long rolling effect
}
};
return self;
});
var SymbolDisplay = Container.expand(function () {
var self = Container.call(this);
self.symbolValue = 0;
self.symbolGraphic = null;
self.setSymbol = function (symbolId) {
if (self.symbolGraphic) {
self.removeChild(self.symbolGraphic);
}
self.symbolValue = symbolId;
var assetId = 'symbol' + symbolId;
self.symbolGraphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
return self;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Bar
// Lemon
// Cherry
// Game state
var coins = storage.coins || 100;
var betAmount = 10;
var isSpinning = false;
var spinResults = [0, 0, 0];
var reels = [];
var activeReels = 0;
// Constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var REEL_SPACING = 200;
var SYMBOL_VALUES = {
"1-1-1": 30,
// Reduce win amount for three cherries
"2-2-2": 60,
// Reduce win amount for three lemons
"3-3-3": 120,
// Reduce win amount for three bars (jackpot)
"1-1-2": 15,
// Two cherries and a lemon
"1-1-3": 15,
// Two cherries and a bar
"2-2-1": 15,
// Two lemons and a cherry
"2-2-3": 15,
// Two lemons and a bar
"1-2-3": 5 // One of each
};
// Create main slot machine components
var slotMachine = new Container();
game.addChild(slotMachine);
slotMachine.x = GAME_WIDTH / 2;
slotMachine.y = GAME_HEIGHT / 2 - 196;
// Background
var background = slotMachine.addChild(LK.getAsset('slotBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
// Main frame
var frame = slotMachine.addChild(LK.getAsset('slotFrame', {
anchorX: 0.5,
anchorY: 0.5,
y: -98
}));
// Add 3 reels
for (var i = 0; i < 3; i++) {
var reel = new Reel();
reel.x = (i - 1) * REEL_SPACING * 1.96;
reel.y = -98;
slotMachine.addChild(reel);
reels.push(reel);
}
// Payline indicators
var leftIndicator = slotMachine.addChild(LK.getAsset('paylineIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: -686,
y: -98
}));
var rightIndicator = slotMachine.addChild(LK.getAsset('paylineIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 686,
y: -98
}));
// Lever
var lever = new Lever();
lever.x = 784;
lever.y = 294;
slotMachine.addChild(lever);
// Set up lever callback
lever.onPullComplete = function () {
if (!isSpinning && coins >= betAmount) {
startSpin();
}
};
// Create UI elements
var coinsDisplay = new Text2("Coins: " + coins, {
size: 60,
fill: 0xFFD700
});
coinsDisplay.anchor.set(0.5, 0.5);
LK.gui.top.addChild(coinsDisplay);
coinsDisplay.y = 196;
var betButton = new Button("Bet: " + betAmount, 200, 80);
betButton.x = GAME_WIDTH / 2;
betButton.y = GAME_HEIGHT - 588;
game.addChild(betButton);
var cashOutButton = new Button("Cash Out", 200, 80);
cashOutButton.x = GAME_WIDTH / 2 + 490;
cashOutButton.y = GAME_HEIGHT - 588;
game.addChild(cashOutButton);
var spinButton = new Button("SPIN", 200, 80);
spinButton.x = GAME_WIDTH / 2 - 490;
spinButton.y = GAME_HEIGHT - 588;
game.addChild(spinButton);
var winText = new Text2("", {
size: 70,
fill: 0xFFD700
});
winText.anchor.set(0.5, 0.5);
winText.y = GAME_HEIGHT / 2 + 490;
winText.x = GAME_WIDTH / 2;
game.addChild(winText);
// Button event handlers
spinButton.down = function (x, y, obj) {
this.down.call(this, x, y, obj);
if (!isSpinning && coins >= betAmount) {
startSpin();
}
};
betButton.down = function (x, y, obj) {
this.down.call(this, x, y, obj);
if (!isSpinning) {
cycleBet();
}
};
cashOutButton.down = function (x, y, obj) {
this.down.call(this, x, y, obj);
if (!isSpinning) {
storage.coins = coins;
LK.showYouWin();
}
};
// Game functions
function updateCoinsDisplay() {
coinsDisplay.setText("Coins: " + coins);
storage.coins = coins;
}
function cycleBet() {
var betOptions = [5, 10, 25, 50, 100];
var currentIndex = betOptions.indexOf(betAmount);
var nextIndex = (currentIndex + 1) % betOptions.length;
betAmount = betOptions[nextIndex];
// Don't allow bets higher than current coins
if (betAmount > coins) {
betAmount = betOptions[0];
}
betButton.setText("Bet: " + betAmount);
}
function startSpin() {
if (isSpinning) {
return;
}
// Deduct coins for the bet
coins -= betAmount;
updateCoinsDisplay();
// Clear any previous win display
winText.setText("");
// Disable buttons during spin
spinButton.disable();
betButton.disable();
isSpinning = true;
activeReels = 0;
LK.getSound('reelSpin').play();
// Generate random results for each reel
for (var i = 0; i < 3; i++) {
spinResults[i] = Math.floor(Math.random() * 4) + 1; // Increase range to reduce winning probability
if (spinResults[i] > 3) {
spinResults[i] = 1;
} // Map any value greater than 3 back to 1
}
// Spin each reel with staggered timing
for (var i = 0; i < reels.length; i++) {
var spinDuration = 5 + i * 1.0; // Further increase duration for an even longer rolling effect
reels[i].spin(spinDuration, spinResults[i], function () {
activeReels++;
if (activeReels >= 3) {
spinCompleted();
}
});
}
}
function spinCompleted() {
isSpinning = false;
// Enable buttons again
spinButton.enable();
betButton.enable();
// Check for winning combinations
var combination = spinResults.join('-');
var winAmount = 0;
// Check exact combinations
if (SYMBOL_VALUES[combination]) {
winAmount = SYMBOL_VALUES[combination] * betAmount / 10;
} else {
// Check for pairs (same symbol in first two positions)
if (spinResults[0] === spinResults[1]) {
winAmount = 2 * betAmount / 10;
} else if (spinResults[1] === spinResults[2]) {
winAmount = 2 * betAmount / 10;
} else if (spinResults[0] === spinResults[2]) {
winAmount = 2 * betAmount / 10;
}
}
if (winAmount > 0) {
// Award winnings
coins += winAmount;
updateCoinsDisplay();
// Display win message
winText.setText("WIN: " + winAmount + " COINS!");
// Play appropriate sound
if (combination === "3-3-3") {
// Jackpot win!
LK.getSound('jackpot').play();
LK.effects.flashScreen(0xFFD700, 1000); // Gold flash for jackpot
} else {
LK.getSound('win').play();
}
}
// Check if player is out of coins
if (coins <= 0) {
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
}
// Start background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Update function
game.update = function () {
// Update all reels
for (var i = 0; i < reels.length; i++) {
reels[i].update();
}
// Disable spin button if not enough coins
if (coins < betAmount && !spinButton.disabled) {
spinButton.disable();
} else if (coins >= betAmount && spinButton.disabled && !isSpinning) {
spinButton.enable();
}
};