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