/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
gold: 0,
gems: 0
});
/****
* Classes
****/
// Card class
var Card = Container.expand(function () {
var self = Container.call(this);
// Card rarities and their properties
var rarities = {
common: {
asset: 'card_common',
color: 0xcccccc,
label: 'Common',
min: 10,
max: 30,
weight: 60
},
rare: {
asset: 'card_rare',
color: 0x4a90e2,
label: 'Rare',
min: 40,
max: 80,
weight: 25
},
epic: {
asset: 'card_epic',
color: 0x9b59b6,
label: 'Epic',
min: 100,
max: 200,
weight: 12
},
legendary: {
asset: 'card_legendary',
color: 0xf1c40f,
label: 'Legendary',
min: 300,
max: 500,
weight: 3
},
mythic: {
asset: 'card_mythic',
// Unique mythic art
color: 0xff44ff,
label: 'Mythic',
min: 1000,
max: 2000,
weight: 0.3 // 10x rarer than legendary
}
};
// Pick rarity if not provided
self.pickRarity = function () {
// Weighted random
var total = 0;
// If oddsHalverActive, halve all weights (rarities become half as likely)
var halved = typeof oddsHalverActive !== "undefined" && oddsHalverActive;
for (var k in rarities) {
total += halved ? rarities[k].weight / 2 : rarities[k].weight;
}
var r = Math.random() * total,
acc = 0;
for (var k in rarities) {
acc += halved ? rarities[k].weight / 2 : rarities[k].weight;
if (r < acc) {
return k;
}
}
return 'common';
};
// Initialize card
self.init = function (rarity) {
self.rarity = rarity || self.pickRarity();
var rdata = rarities[self.rarity];
// Remove previous children if any
while (self.children.length) {
self.removeChild(self.children[0]);
}
// Card background
var cardBg = self.attachAsset(rdata.asset, {
anchorX: 0.5,
anchorY: 0.5
});
// Card label
// (Removed: do not show card name text for any rarity)
// Card value
self.value = rdata.min + Math.floor(Math.random() * (rdata.max - rdata.min + 1));
var valueTxt = new Text2("+" + self.value + " Gold", {
size: 70,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
valueTxt.anchor.set(0.5, 0);
// Position gold text below the card image
valueTxt.y = cardBg.height / 2 + 20;
self.addChild(valueTxt);
};
// Animate reveal
self.reveal = function (onFinish) {
self.scale.x = 0.1;
self.scale.y = 1.2;
tween(self.scale, {
x: 1,
y: 1
}, {
duration: 350,
easing: tween.elasticOut,
onFinish: onFinish
});
};
return self;
});
// Spin Button class
var SpinButton = Container.expand(function () {
var self = Container.call(this);
var btn = self.attachAsset('spin_button', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* Initialize Game
****/
var game = new LK.Game({
// No title, no description
// Always backgroundColor is black
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Mythic reveal sound (unique)
// Mythic card asset (unique art)
// Card shapes for different rarities
// Add background image to the game scene
var bg = LK.getAsset('background_img', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1,
scaleY: 1
});
game.addChild(bg);
bg.zIndex = -1000; // ensure background is behind everything
// State
var currentCard = null;
var canSpin = true;
var gold = storage.gold || 0;
var gems = storage.gems || 0;
var lastSpinGold = 0;
// XP/Level system
var level = storage.level || 1;
var xp = storage.xp || 0;
var xpBar = null;
var xpTxt = null;
var levelTxt = null;
// Rarity checklist state
var rarityList = [{
key: "common",
label: "Common"
}, {
key: "rare",
label: "Rare"
}, {
key: "epic",
label: "Epic"
}, {
key: "legendary",
label: "Legendary"
}, {
key: "mythic",
label: "Mythic"
}];
var rarityObtained = storage.rarityObtained || {
common: false,
rare: false,
epic: false,
legendary: false,
mythic: false
};
var rarityChecklistUI = null;
// XP requirements per level (simple formula: 100 * level)
function xpForLevel(lvl) {
return 100 * lvl;
}
// Gold display
var goldTxt = new Text2("Gold: " + gold, {
size: 70,
fill: 0xFFD700,
stroke: "#000",
strokeThickness: 8
});
goldTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(goldTxt);
// --- Rarity Odds Halver Button (top left, not in 100x100 area) ---
var oddsHalverBtn = new Container();
var oddsHalverAsset = oddsHalverBtn.attachAsset('halver_icon', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 80
});
// No inner icon needed, halver_icon is the button itself
var oddsHalverTxt = new Text2("Halve Odds\n3000 Gold", {
size: 36,
fill: "#fff",
stroke: "#000",
strokeThickness: 7
});
oddsHalverTxt.anchor.set(0.5, 0.5);
oddsHalverBtn.addChild(oddsHalverTxt);
oddsHalverBtn.x = 320; // moved further right, still outside 100x100
oddsHalverBtn.y = 120;
LK.gui.top.addChild(oddsHalverBtn);
var oddsHalverActive = false;
var oddsHalverTimer = null;
var oddsHalverCooldown = 60; // seconds left
function updateOddsHalverBtn() {
if (oddsHalverActive) {
oddsHalverBtn.alpha = 0.7;
oddsHalverTxt.setText("Halved!\n" + oddsHalverCooldown + "s");
} else {
oddsHalverBtn.alpha = 1;
oddsHalverTxt.setText("Halve Odds\n3000 Gold");
}
}
updateOddsHalverBtn();
oddsHalverBtn.down = function () {
LK.getSound('button_press').play();
if (oddsHalverActive) return;
if (gold < 3000) {
resultTxt.setText("Need 3000 gold!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
return;
}
gold -= 3000;
storage.gold = gold;
updateDisplays();
oddsHalverActive = true;
oddsHalverCooldown = 60;
updateOddsHalverBtn();
// Start timer
if (oddsHalverTimer) LK.clearInterval(oddsHalverTimer);
oddsHalverTimer = LK.setInterval(function () {
oddsHalverCooldown--;
if (oddsHalverCooldown <= 0) {
oddsHalverActive = false;
LK.clearInterval(oddsHalverTimer);
oddsHalverTimer = null;
}
updateOddsHalverBtn();
}, 1000);
};
// Gems display
var gemsTxt = new Text2("Gems: " + gems, {
size: 60,
fill: 0x00FFF7,
stroke: "#000",
strokeThickness: 8
});
gemsTxt.anchor.set(0.5, 0);
gemsTxt.y = 80;
LK.gui.top.addChild(gemsTxt);
// Last spin result display
var resultTxt = new Text2("", {
size: 60,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
resultTxt.anchor.set(0.5, 0);
resultTxt.y = 160;
LK.gui.top.addChild(resultTxt);
// Level display (moved to bottom)
levelTxt = new Text2("Level: " + level, {
size: 60,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
levelTxt.anchor.set(0.5, 1);
levelTxt.y = 2732 - 180;
LK.gui.bottom.addChild(levelTxt);
// XP bar background (moved to bottom)
var xpBarBg = new Container();
var xpBarBgRect = xpBarBg.attachAsset('card_common', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 36,
tint: 0x222222
});
xpBarBg.x = 2048 / 2;
xpBarBg.y = 2732 - 110;
LK.gui.bottom.addChild(xpBarBg);
// XP bar foreground (moved to bottom)
xpBar = new Container();
var xpBarRect = xpBar.attachAsset('card_common', {
anchorX: 0.5,
anchorY: 0.5,
width: 590,
height: 28,
tint: 0x44e044
});
xpBar.x = 2048 / 2;
xpBar.y = 2732 - 110;
LK.gui.bottom.addChild(xpBar);
// XP text (moved to bottom)
xpTxt = new Text2("XP: " + xp + " / " + xpForLevel(level), {
size: 36,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
xpTxt.anchor.set(0.5, 1);
xpTxt.y = 2732 - 60;
xpTxt.x = 2048 / 2;
LK.gui.bottom.addChild(xpTxt);
// Center positions
var centerX = 2048 / 2,
centerY = 2732 / 2;
// Rarity checklist UI (left side)
function createRarityChecklistUI() {
if (rarityChecklistUI) {
rarityChecklistUI.destroy();
rarityChecklistUI = null;
}
rarityChecklistUI = new Container();
// Position left, avoid top left 100x100
rarityChecklistUI.x = 60;
rarityChecklistUI.y = 200;
var spacing = 120;
// Add background asset for checklist area
var bgAsset = LK.getAsset('rarity_checklist_bg', {
anchorX: 0,
anchorY: 0,
width: 340,
height: spacing * rarityList.length + 40,
x: -40,
y: -40
});
rarityChecklistUI.addChild(bgAsset);
for (var i = 0; i < rarityList.length; i++) {
var rarity = rarityList[i];
// Show ? if not obtained, else show label
var showLabel = rarityObtained[rarity.key] ? rarity.label : "?";
var label = new Text2(showLabel, {
size: 54,
fill: rarity.key === "mythic" ? "#ff44ff" : "#fff",
stroke: "#000",
strokeThickness: 7
});
label.anchor.set(0, 0.5);
label.x = 0;
label.y = i * spacing;
rarityChecklistUI.addChild(label);
// Checkmark if obtained
if (rarityObtained[rarity.key]) {
var check = new Text2("✓", {
size: 54,
fill: 0x44E044,
stroke: "#000",
strokeThickness: 7
});
check.anchor.set(0, 0.5);
check.x = 200;
check.y = i * spacing;
rarityChecklistUI.addChild(check);
}
}
LK.gui.left.addChild(rarityChecklistUI);
}
// Initial checklist UI
createRarityChecklistUI();
// Spin button
var spinBtn = new SpinButton();
spinBtn.x = centerX;
spinBtn.y = centerY + 400;
game.addChild(spinBtn);
// Convert button (restored to use convert_button asset)
var convertBtn = new Container();
var convertBtnAsset = convertBtn.attachAsset('convert_button', {
anchorX: 0.5,
anchorY: 0.5
});
convertBtn.x = centerX;
convertBtn.y = centerY + 650;
game.addChild(convertBtn);
// Conversion rate
var GOLD_PER_GEM = 500;
// Card display
function showCard() {
if (currentCard) {
currentCard.destroy();
currentCard = null;
}
var card = new Card();
card.init();
card.x = centerX;
card.y = centerY - 100;
card.scale.x = 0.1;
card.scale.y = 1.2;
game.addChild(card);
currentCard = card;
card.reveal(function () {
// Mark rarity as obtained and update checklist UI if new
if (!rarityObtained[card.rarity]) {
rarityObtained[card.rarity] = true;
storage.rarityObtained = rarityObtained;
createRarityChecklistUI();
}
// Play rarity-based sound and effect
if (card.rarity === "mythic") {
// Unique mythic sound
LK.getSound('mythic_reveal').play();
// Havalı efekt: double flash + rainbow border
LK.effects.flashScreen(0xff44ff, 900);
tween(card.scale, {
x: 1.25,
y: 1.25
}, {
duration: 180,
yoyo: true,
repeat: 1,
onFinish: function onFinish() {
LK.effects.flashScreen(0xffffff, 400);
// Rainbow border effect (simulate by tint cycling)
var tints = [0xff44ff, 0x44e0ff, 0x44ff44, 0xffe044, 0xff4444, 0xffffff];
var i = 0;
var borderTween = LK.setInterval(function () {
if (i < tints.length) {
LK.effects.flashObject(card, tints[i], 80);
i++;
} else {
LK.clearInterval(borderTween);
}
}, 80);
}
});
} else if (card.rarity === "legendary") {
LK.getSound('legendary_reveal').play();
LK.effects.flashScreen(0xf1c40f, 900);
} else if (card.rarity === "epic") {
LK.getSound('epic_reveal').play();
LK.effects.flashScreen(0x9b59b6, 700);
} else if (card.rarity === "rare") {
LK.getSound('rare_reveal').play();
LK.effects.flashScreen(0x4a90e2, 500);
} else {
LK.getSound('common_reveal').play();
LK.effects.flashObject(card, 0xcccccc, 350);
}
// Add gold
gold += card.value;
lastSpinGold = card.value;
storage.gold = gold;
// Play gold gain sound
LK.getSound('gold_gain').play();
// XP gain by rarity
var xpGain = 0;
if (card.rarity === "mythic") xpGain = 500;else if (card.rarity === "legendary") xpGain = 50;else if (card.rarity === "epic") xpGain = 25;else if (card.rarity === "rare") xpGain = 10;else xpGain = 3;
xp += xpGain;
LK.getSound('xp_gain').play();
// Level up logic
var leveledUp = false;
while (xp >= xpForLevel(level)) {
xp -= xpForLevel(level);
level += 1;
leveledUp = true;
}
if (leveledUp) {
LK.getSound('level_up').play();
// Animate level up text
resultTxt.setText("LEVEL UP! Now Level " + level + "!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1800
});
}
// Save XP/level
storage.xp = xp;
storage.level = level;
updateDisplays();
// Show result
if (!leveledUp) {
resultTxt.setText("You won " + card.value + " gold!\n+" + xpGain + " XP");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
}
// Allow next spin
canSpin = true;
});
}
// Update gold/gems display
function updateDisplays() {
goldTxt.setText("Gold: " + gold);
gemsTxt.setText("Gems: " + gems);
levelTxt.setText("Level: " + level);
xpTxt.setText("XP: " + xp + " / " + xpForLevel(level));
// Update XP bar width
var percent = Math.min(1, xp / xpForLevel(level));
if (xpBar && xpBar.children.length > 0) {
var bar = xpBar.children[0];
bar.width = 590 * percent;
}
}
// Spin button event
spinBtn.down = function (x, y, obj) {
LK.getSound('button_press').play();
if (!canSpin) {
return;
}
if (gems <= 0) {
// Not enough gems, show info and do not spin
resultTxt.setText("Not enough gems! Get more to spin.");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
return;
}
gems -= 1;
storage.gems = gems;
updateDisplays();
canSpin = false;
// Animate button
tween(spinBtn.scale, {
x: 0.92,
y: 0.92
}, {
duration: 80,
onFinish: function onFinish() {
tween(spinBtn.scale, {
x: 1,
y: 1
}, {
duration: 80
});
}
});
showCard();
};
// Convert button event
convertBtn.down = function (x, y, obj) {
LK.getSound('button_press').play();
if (gold >= GOLD_PER_GEM) {
var gemsGained = Math.floor(gold / GOLD_PER_GEM);
gold -= gemsGained * GOLD_PER_GEM;
gems += gemsGained;
storage.gold = gold;
storage.gems = gems;
updateDisplays();
// Animate gems text
gemsTxt.alpha = 1;
tween(gemsTxt, {
alpha: 0.3
}, {
duration: 600,
onFinish: function onFinish() {
tween(gemsTxt, {
alpha: 1
}, {
duration: 300
});
}
});
// Play gem gain sound
LK.getSound('gem_gain').play();
// Show conversion result
resultTxt.setText("Converted for " + gemsGained + " gem" + (gemsGained > 1 ? "s!" : "!"));
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
} else {
// Not enough gold
resultTxt.setText("Need " + GOLD_PER_GEM + " gold for 1 gem!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
}
};
// Initial card
showCard();
// Timed gem reward button
var gemRewardBtn = null;
var gemRewardTimer = null;
var gemRewardCooldown = 60 * 1000; // 1 minute
var gemRewardAvailable = true;
var gemRewardTxt = null;
function showGemRewardBtn() {
if (gemRewardBtn) {
return;
}
gemRewardBtn = new Container();
var btn = gemRewardBtn.attachAsset('gem_reward_button', {
anchorX: 0.5,
anchorY: 0.5
});
btn.width = 300;
btn.height = 100;
gemRewardBtn.x = centerX + 500;
gemRewardBtn.y = centerY + 400;
var txt = new Text2("Get 100 Gems", {
size: 40,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
txt.anchor.set(0.5, 0.5);
gemRewardBtn.addChild(txt);
gemRewardTxt = txt;
game.addChild(gemRewardBtn);
gemRewardBtn.down = function () {
LK.getSound('button_press').play();
if (!gemRewardAvailable) {
return;
}
gems += 100;
storage.gems = gems;
updateDisplays();
LK.getSound('gem_gain').play();
resultTxt.setText("You received 100 gems!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
gemRewardAvailable = false;
gemRewardTxt.setText("Wait 60s");
var secondsLeft = 60;
gemRewardTimer = LK.setInterval(function () {
secondsLeft--;
if (secondsLeft > 0) {
gemRewardTxt.setText("Wait " + secondsLeft + "s");
} else {
LK.clearInterval(gemRewardTimer);
gemRewardAvailable = true;
gemRewardTxt.setText("Get 100 Gems");
}
}, 1000);
};
}
function hideGemRewardBtn() {
if (gemRewardBtn) {
gemRewardBtn.destroy();
gemRewardBtn = null;
}
}
// Show/hide gem reward button based on gems
function checkGemRewardBtn() {
if (gems <= 0) {
showGemRewardBtn();
} else {
hideGemRewardBtn();
}
}
checkGemRewardBtn();
// Patch updateDisplays to also check gem reward button and update rarity checklist
var _updateDisplays = updateDisplays;
updateDisplays = function updateDisplays() {
_updateDisplays();
checkGemRewardBtn();
createRarityChecklistUI();
if (typeof updateOddsHalverBtn === "function") updateOddsHalverBtn();
};
// No dragging or move events needed for this game
// No update loop needed except for possible future features
game.update = function () {
// No-op for now
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
gold: 0,
gems: 0
});
/****
* Classes
****/
// Card class
var Card = Container.expand(function () {
var self = Container.call(this);
// Card rarities and their properties
var rarities = {
common: {
asset: 'card_common',
color: 0xcccccc,
label: 'Common',
min: 10,
max: 30,
weight: 60
},
rare: {
asset: 'card_rare',
color: 0x4a90e2,
label: 'Rare',
min: 40,
max: 80,
weight: 25
},
epic: {
asset: 'card_epic',
color: 0x9b59b6,
label: 'Epic',
min: 100,
max: 200,
weight: 12
},
legendary: {
asset: 'card_legendary',
color: 0xf1c40f,
label: 'Legendary',
min: 300,
max: 500,
weight: 3
},
mythic: {
asset: 'card_mythic',
// Unique mythic art
color: 0xff44ff,
label: 'Mythic',
min: 1000,
max: 2000,
weight: 0.3 // 10x rarer than legendary
}
};
// Pick rarity if not provided
self.pickRarity = function () {
// Weighted random
var total = 0;
// If oddsHalverActive, halve all weights (rarities become half as likely)
var halved = typeof oddsHalverActive !== "undefined" && oddsHalverActive;
for (var k in rarities) {
total += halved ? rarities[k].weight / 2 : rarities[k].weight;
}
var r = Math.random() * total,
acc = 0;
for (var k in rarities) {
acc += halved ? rarities[k].weight / 2 : rarities[k].weight;
if (r < acc) {
return k;
}
}
return 'common';
};
// Initialize card
self.init = function (rarity) {
self.rarity = rarity || self.pickRarity();
var rdata = rarities[self.rarity];
// Remove previous children if any
while (self.children.length) {
self.removeChild(self.children[0]);
}
// Card background
var cardBg = self.attachAsset(rdata.asset, {
anchorX: 0.5,
anchorY: 0.5
});
// Card label
// (Removed: do not show card name text for any rarity)
// Card value
self.value = rdata.min + Math.floor(Math.random() * (rdata.max - rdata.min + 1));
var valueTxt = new Text2("+" + self.value + " Gold", {
size: 70,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
valueTxt.anchor.set(0.5, 0);
// Position gold text below the card image
valueTxt.y = cardBg.height / 2 + 20;
self.addChild(valueTxt);
};
// Animate reveal
self.reveal = function (onFinish) {
self.scale.x = 0.1;
self.scale.y = 1.2;
tween(self.scale, {
x: 1,
y: 1
}, {
duration: 350,
easing: tween.elasticOut,
onFinish: onFinish
});
};
return self;
});
// Spin Button class
var SpinButton = Container.expand(function () {
var self = Container.call(this);
var btn = self.attachAsset('spin_button', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* Initialize Game
****/
var game = new LK.Game({
// No title, no description
// Always backgroundColor is black
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Mythic reveal sound (unique)
// Mythic card asset (unique art)
// Card shapes for different rarities
// Add background image to the game scene
var bg = LK.getAsset('background_img', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1,
scaleY: 1
});
game.addChild(bg);
bg.zIndex = -1000; // ensure background is behind everything
// State
var currentCard = null;
var canSpin = true;
var gold = storage.gold || 0;
var gems = storage.gems || 0;
var lastSpinGold = 0;
// XP/Level system
var level = storage.level || 1;
var xp = storage.xp || 0;
var xpBar = null;
var xpTxt = null;
var levelTxt = null;
// Rarity checklist state
var rarityList = [{
key: "common",
label: "Common"
}, {
key: "rare",
label: "Rare"
}, {
key: "epic",
label: "Epic"
}, {
key: "legendary",
label: "Legendary"
}, {
key: "mythic",
label: "Mythic"
}];
var rarityObtained = storage.rarityObtained || {
common: false,
rare: false,
epic: false,
legendary: false,
mythic: false
};
var rarityChecklistUI = null;
// XP requirements per level (simple formula: 100 * level)
function xpForLevel(lvl) {
return 100 * lvl;
}
// Gold display
var goldTxt = new Text2("Gold: " + gold, {
size: 70,
fill: 0xFFD700,
stroke: "#000",
strokeThickness: 8
});
goldTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(goldTxt);
// --- Rarity Odds Halver Button (top left, not in 100x100 area) ---
var oddsHalverBtn = new Container();
var oddsHalverAsset = oddsHalverBtn.attachAsset('halver_icon', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 80
});
// No inner icon needed, halver_icon is the button itself
var oddsHalverTxt = new Text2("Halve Odds\n3000 Gold", {
size: 36,
fill: "#fff",
stroke: "#000",
strokeThickness: 7
});
oddsHalverTxt.anchor.set(0.5, 0.5);
oddsHalverBtn.addChild(oddsHalverTxt);
oddsHalverBtn.x = 320; // moved further right, still outside 100x100
oddsHalverBtn.y = 120;
LK.gui.top.addChild(oddsHalverBtn);
var oddsHalverActive = false;
var oddsHalverTimer = null;
var oddsHalverCooldown = 60; // seconds left
function updateOddsHalverBtn() {
if (oddsHalverActive) {
oddsHalverBtn.alpha = 0.7;
oddsHalverTxt.setText("Halved!\n" + oddsHalverCooldown + "s");
} else {
oddsHalverBtn.alpha = 1;
oddsHalverTxt.setText("Halve Odds\n3000 Gold");
}
}
updateOddsHalverBtn();
oddsHalverBtn.down = function () {
LK.getSound('button_press').play();
if (oddsHalverActive) return;
if (gold < 3000) {
resultTxt.setText("Need 3000 gold!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
return;
}
gold -= 3000;
storage.gold = gold;
updateDisplays();
oddsHalverActive = true;
oddsHalverCooldown = 60;
updateOddsHalverBtn();
// Start timer
if (oddsHalverTimer) LK.clearInterval(oddsHalverTimer);
oddsHalverTimer = LK.setInterval(function () {
oddsHalverCooldown--;
if (oddsHalverCooldown <= 0) {
oddsHalverActive = false;
LK.clearInterval(oddsHalverTimer);
oddsHalverTimer = null;
}
updateOddsHalverBtn();
}, 1000);
};
// Gems display
var gemsTxt = new Text2("Gems: " + gems, {
size: 60,
fill: 0x00FFF7,
stroke: "#000",
strokeThickness: 8
});
gemsTxt.anchor.set(0.5, 0);
gemsTxt.y = 80;
LK.gui.top.addChild(gemsTxt);
// Last spin result display
var resultTxt = new Text2("", {
size: 60,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
resultTxt.anchor.set(0.5, 0);
resultTxt.y = 160;
LK.gui.top.addChild(resultTxt);
// Level display (moved to bottom)
levelTxt = new Text2("Level: " + level, {
size: 60,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
levelTxt.anchor.set(0.5, 1);
levelTxt.y = 2732 - 180;
LK.gui.bottom.addChild(levelTxt);
// XP bar background (moved to bottom)
var xpBarBg = new Container();
var xpBarBgRect = xpBarBg.attachAsset('card_common', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 36,
tint: 0x222222
});
xpBarBg.x = 2048 / 2;
xpBarBg.y = 2732 - 110;
LK.gui.bottom.addChild(xpBarBg);
// XP bar foreground (moved to bottom)
xpBar = new Container();
var xpBarRect = xpBar.attachAsset('card_common', {
anchorX: 0.5,
anchorY: 0.5,
width: 590,
height: 28,
tint: 0x44e044
});
xpBar.x = 2048 / 2;
xpBar.y = 2732 - 110;
LK.gui.bottom.addChild(xpBar);
// XP text (moved to bottom)
xpTxt = new Text2("XP: " + xp + " / " + xpForLevel(level), {
size: 36,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
xpTxt.anchor.set(0.5, 1);
xpTxt.y = 2732 - 60;
xpTxt.x = 2048 / 2;
LK.gui.bottom.addChild(xpTxt);
// Center positions
var centerX = 2048 / 2,
centerY = 2732 / 2;
// Rarity checklist UI (left side)
function createRarityChecklistUI() {
if (rarityChecklistUI) {
rarityChecklistUI.destroy();
rarityChecklistUI = null;
}
rarityChecklistUI = new Container();
// Position left, avoid top left 100x100
rarityChecklistUI.x = 60;
rarityChecklistUI.y = 200;
var spacing = 120;
// Add background asset for checklist area
var bgAsset = LK.getAsset('rarity_checklist_bg', {
anchorX: 0,
anchorY: 0,
width: 340,
height: spacing * rarityList.length + 40,
x: -40,
y: -40
});
rarityChecklistUI.addChild(bgAsset);
for (var i = 0; i < rarityList.length; i++) {
var rarity = rarityList[i];
// Show ? if not obtained, else show label
var showLabel = rarityObtained[rarity.key] ? rarity.label : "?";
var label = new Text2(showLabel, {
size: 54,
fill: rarity.key === "mythic" ? "#ff44ff" : "#fff",
stroke: "#000",
strokeThickness: 7
});
label.anchor.set(0, 0.5);
label.x = 0;
label.y = i * spacing;
rarityChecklistUI.addChild(label);
// Checkmark if obtained
if (rarityObtained[rarity.key]) {
var check = new Text2("✓", {
size: 54,
fill: 0x44E044,
stroke: "#000",
strokeThickness: 7
});
check.anchor.set(0, 0.5);
check.x = 200;
check.y = i * spacing;
rarityChecklistUI.addChild(check);
}
}
LK.gui.left.addChild(rarityChecklistUI);
}
// Initial checklist UI
createRarityChecklistUI();
// Spin button
var spinBtn = new SpinButton();
spinBtn.x = centerX;
spinBtn.y = centerY + 400;
game.addChild(spinBtn);
// Convert button (restored to use convert_button asset)
var convertBtn = new Container();
var convertBtnAsset = convertBtn.attachAsset('convert_button', {
anchorX: 0.5,
anchorY: 0.5
});
convertBtn.x = centerX;
convertBtn.y = centerY + 650;
game.addChild(convertBtn);
// Conversion rate
var GOLD_PER_GEM = 500;
// Card display
function showCard() {
if (currentCard) {
currentCard.destroy();
currentCard = null;
}
var card = new Card();
card.init();
card.x = centerX;
card.y = centerY - 100;
card.scale.x = 0.1;
card.scale.y = 1.2;
game.addChild(card);
currentCard = card;
card.reveal(function () {
// Mark rarity as obtained and update checklist UI if new
if (!rarityObtained[card.rarity]) {
rarityObtained[card.rarity] = true;
storage.rarityObtained = rarityObtained;
createRarityChecklistUI();
}
// Play rarity-based sound and effect
if (card.rarity === "mythic") {
// Unique mythic sound
LK.getSound('mythic_reveal').play();
// Havalı efekt: double flash + rainbow border
LK.effects.flashScreen(0xff44ff, 900);
tween(card.scale, {
x: 1.25,
y: 1.25
}, {
duration: 180,
yoyo: true,
repeat: 1,
onFinish: function onFinish() {
LK.effects.flashScreen(0xffffff, 400);
// Rainbow border effect (simulate by tint cycling)
var tints = [0xff44ff, 0x44e0ff, 0x44ff44, 0xffe044, 0xff4444, 0xffffff];
var i = 0;
var borderTween = LK.setInterval(function () {
if (i < tints.length) {
LK.effects.flashObject(card, tints[i], 80);
i++;
} else {
LK.clearInterval(borderTween);
}
}, 80);
}
});
} else if (card.rarity === "legendary") {
LK.getSound('legendary_reveal').play();
LK.effects.flashScreen(0xf1c40f, 900);
} else if (card.rarity === "epic") {
LK.getSound('epic_reveal').play();
LK.effects.flashScreen(0x9b59b6, 700);
} else if (card.rarity === "rare") {
LK.getSound('rare_reveal').play();
LK.effects.flashScreen(0x4a90e2, 500);
} else {
LK.getSound('common_reveal').play();
LK.effects.flashObject(card, 0xcccccc, 350);
}
// Add gold
gold += card.value;
lastSpinGold = card.value;
storage.gold = gold;
// Play gold gain sound
LK.getSound('gold_gain').play();
// XP gain by rarity
var xpGain = 0;
if (card.rarity === "mythic") xpGain = 500;else if (card.rarity === "legendary") xpGain = 50;else if (card.rarity === "epic") xpGain = 25;else if (card.rarity === "rare") xpGain = 10;else xpGain = 3;
xp += xpGain;
LK.getSound('xp_gain').play();
// Level up logic
var leveledUp = false;
while (xp >= xpForLevel(level)) {
xp -= xpForLevel(level);
level += 1;
leveledUp = true;
}
if (leveledUp) {
LK.getSound('level_up').play();
// Animate level up text
resultTxt.setText("LEVEL UP! Now Level " + level + "!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1800
});
}
// Save XP/level
storage.xp = xp;
storage.level = level;
updateDisplays();
// Show result
if (!leveledUp) {
resultTxt.setText("You won " + card.value + " gold!\n+" + xpGain + " XP");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
}
// Allow next spin
canSpin = true;
});
}
// Update gold/gems display
function updateDisplays() {
goldTxt.setText("Gold: " + gold);
gemsTxt.setText("Gems: " + gems);
levelTxt.setText("Level: " + level);
xpTxt.setText("XP: " + xp + " / " + xpForLevel(level));
// Update XP bar width
var percent = Math.min(1, xp / xpForLevel(level));
if (xpBar && xpBar.children.length > 0) {
var bar = xpBar.children[0];
bar.width = 590 * percent;
}
}
// Spin button event
spinBtn.down = function (x, y, obj) {
LK.getSound('button_press').play();
if (!canSpin) {
return;
}
if (gems <= 0) {
// Not enough gems, show info and do not spin
resultTxt.setText("Not enough gems! Get more to spin.");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
return;
}
gems -= 1;
storage.gems = gems;
updateDisplays();
canSpin = false;
// Animate button
tween(spinBtn.scale, {
x: 0.92,
y: 0.92
}, {
duration: 80,
onFinish: function onFinish() {
tween(spinBtn.scale, {
x: 1,
y: 1
}, {
duration: 80
});
}
});
showCard();
};
// Convert button event
convertBtn.down = function (x, y, obj) {
LK.getSound('button_press').play();
if (gold >= GOLD_PER_GEM) {
var gemsGained = Math.floor(gold / GOLD_PER_GEM);
gold -= gemsGained * GOLD_PER_GEM;
gems += gemsGained;
storage.gold = gold;
storage.gems = gems;
updateDisplays();
// Animate gems text
gemsTxt.alpha = 1;
tween(gemsTxt, {
alpha: 0.3
}, {
duration: 600,
onFinish: function onFinish() {
tween(gemsTxt, {
alpha: 1
}, {
duration: 300
});
}
});
// Play gem gain sound
LK.getSound('gem_gain').play();
// Show conversion result
resultTxt.setText("Converted for " + gemsGained + " gem" + (gemsGained > 1 ? "s!" : "!"));
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
} else {
// Not enough gold
resultTxt.setText("Need " + GOLD_PER_GEM + " gold for 1 gem!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
}
};
// Initial card
showCard();
// Timed gem reward button
var gemRewardBtn = null;
var gemRewardTimer = null;
var gemRewardCooldown = 60 * 1000; // 1 minute
var gemRewardAvailable = true;
var gemRewardTxt = null;
function showGemRewardBtn() {
if (gemRewardBtn) {
return;
}
gemRewardBtn = new Container();
var btn = gemRewardBtn.attachAsset('gem_reward_button', {
anchorX: 0.5,
anchorY: 0.5
});
btn.width = 300;
btn.height = 100;
gemRewardBtn.x = centerX + 500;
gemRewardBtn.y = centerY + 400;
var txt = new Text2("Get 100 Gems", {
size: 40,
fill: "#fff",
stroke: "#000",
strokeThickness: 8
});
txt.anchor.set(0.5, 0.5);
gemRewardBtn.addChild(txt);
gemRewardTxt = txt;
game.addChild(gemRewardBtn);
gemRewardBtn.down = function () {
LK.getSound('button_press').play();
if (!gemRewardAvailable) {
return;
}
gems += 100;
storage.gems = gems;
updateDisplays();
LK.getSound('gem_gain').play();
resultTxt.setText("You received 100 gems!");
resultTxt.alpha = 1;
tween(resultTxt, {
alpha: 0
}, {
duration: 1200
});
gemRewardAvailable = false;
gemRewardTxt.setText("Wait 60s");
var secondsLeft = 60;
gemRewardTimer = LK.setInterval(function () {
secondsLeft--;
if (secondsLeft > 0) {
gemRewardTxt.setText("Wait " + secondsLeft + "s");
} else {
LK.clearInterval(gemRewardTimer);
gemRewardAvailable = true;
gemRewardTxt.setText("Get 100 Gems");
}
}, 1000);
};
}
function hideGemRewardBtn() {
if (gemRewardBtn) {
gemRewardBtn.destroy();
gemRewardBtn = null;
}
}
// Show/hide gem reward button based on gems
function checkGemRewardBtn() {
if (gems <= 0) {
showGemRewardBtn();
} else {
hideGemRewardBtn();
}
}
checkGemRewardBtn();
// Patch updateDisplays to also check gem reward button and update rarity checklist
var _updateDisplays = updateDisplays;
updateDisplays = function updateDisplays() {
_updateDisplays();
checkGemRewardBtn();
createRarityChecklistUI();
if (typeof updateOddsHalverBtn === "function") updateOddsHalverBtn();
};
// No dragging or move events needed for this game
// No update loop needed except for possible future features
game.update = function () {
// No-op for now
};
common card. In-Game asset. 2d. High contrast. No shadows
epic card. In-Game asset. 2d. High contrast. No shadows
legendary card. In-Game asset. 2d. High contrast. No shadows
rare card. In-Game asset. 2d. High contrast. No shadows
spin button. In-Game asset. 2d. High contrast. No shadows
convert button. In-Game asset. 2d. High contrast. No shadows
reward. In-Game asset. 2d. High contrast. No shadows
table background for card game. 2d. High contrast. No shadows
luck button. In-Game asset. 2d. High contrast. No shadows
MYTHIC card. In-Game asset. 2d. High contrast. No shadows