/****
* 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();
}
};