User prompt
yıldız mekaniğini magic kart oyunundaki sisteme benzer uyarla
User prompt
hp yi 100 e çıkar
User prompt
end turn mekaniğini basılabilir animasyonlu tuş olarak düzenle basınça ses çıksın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
canavar isimlerini, biraz yukarı kaydır
User prompt
canavar isimlerini, biraz yukarı kaydır
User prompt
canavar isimlerini daha okunur yap
User prompt
52 karttaki canavarlara ayrı ayır canavar isimleri ver hiç biri bir birine benzemesin
User prompt
atk ve def rakamlarını daha okunur yap bu rakamların yanındaki mavi işaretleri kaldır
User prompt
kartları barok tarzı çerçeveye al
User prompt
kartların üzerindeki yıldızlarıbiraz sola kaydır ama kartların dışına çıkmasısın ona göre ayarla
User prompt
52 kartın renklerini ayrı ayrı yap hepsi farklrklı 52 renk olsun
User prompt
tüm 52 kartın üzerindeki canavar resimlerini kaldır
User prompt
kartların üzerine yerleştirdiğin canavar görsellerini kaldır
User prompt
daha önce oluşturduğum canavar görsellerini 22,25,26,52 numaralı karların üzerine yerleştir
User prompt
atc def yazılarını ve yanlarında yazan rakamları az büyüt okunmuyolar
User prompt
yazı sığmadı sığacak şekilde düzenle
User prompt
kırmızı rakamların soluna atc,mavi rakamların soluna def yazısı ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kartların üzerindeki def yazısındaki rakamlarda alev görselini atk yazan sayının üzerine al def sayısına mavi kalkan ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
October Oct. 1 to 5 will appear on these 52 monster cards Add stars to the draw randomly in each round the next player will accumulate 1 star how many stars the player has in his hand he can play this card add card burning mechanics the burned card will earn 2 stars let the card be burned. add stars to the card will appear on 1 to 5 monster cards randomly add 1 star to the next player in each round, how many stars the player can play this card ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bu verdiğim kodu oyuna dönştür
User prompt
add 4 generated monster images to 4 cards separately Oct.
User prompt
the game is not being played, make it playable
User prompt
add click animation to monster cards Oct. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
let the monster come to the playing field with the jump animation when the cards are clicked ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Card class: visual and logical representation of a monster card var Card = Container.expand(function () { var self = Container.call(this); // Card properties self.cardId = null; self.cardData = null; self.isInHand = false; self.isPlayable = false; self.isSelected = false; self.owner = null; // "player" or "opponent" // Card visuals var cardWidth = 260; var cardHeight = 380; // Card background var cardBg = self.attachAsset('cardBg_' + self.cardId, { width: cardWidth, height: cardHeight, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Monster illustration (colored ellipse for MVP) var monsterArt = self.attachAsset('monsterArt_' + self.cardId, { width: cardWidth * 0.7, height: cardHeight * 0.35, color: 0xcccccc, shape: 'ellipse', anchorX: 0.5, anchorY: 0.0, y: -cardHeight * 0.18 }); // Card name var nameTxt = new Text2('', { size: 38, fill: 0x222222 }); nameTxt.anchor.set(0.5, 0); nameTxt.y = -cardHeight * 0.45; self.addChild(nameTxt); // Attack/Defense var statsTxt = new Text2('', { size: 32, fill: 0x333333 }); statsTxt.anchor.set(0.5, 0); statsTxt.y = cardHeight * 0.32; self.addChild(statsTxt); // Element var elementTxt = new Text2('', { size: 28, fill: 0x666666 }); elementTxt.anchor.set(0.5, 0); elementTxt.y = -cardHeight * 0.32; self.addChild(elementTxt); // Ability var abilityTxt = new Text2('', { size: 24, fill: 0x444444 }); abilityTxt.anchor.set(0.5, 0); abilityTxt.y = cardHeight * 0.12; self.addChild(abilityTxt); // Set card data self.setCard = function (cardId, owner) { self.cardId = cardId; self.cardData = CARD_DATA[cardId]; self.owner = owner; // Set visuals cardBg.color = 0xffffff; monsterArt.color = self.cardData.color; nameTxt.setText(self.cardData.name); statsTxt.setText("ATK: " + self.cardData.attack + " DEF: " + self.cardData.defense); elementTxt.setText(self.cardData.element); abilityTxt.setText(self.cardData.ability); // For MVP, no evolution/fusion visuals }; // Highlight if playable/selected self.setPlayable = function (playable) { self.isPlayable = playable; cardBg.color = playable ? 0xffe066 : 0xffffff; }; self.setSelected = function (selected) { self.isSelected = selected; cardBg.color = selected ? 0x66ccff : self.isPlayable ? 0xffe066 : 0xffffff; }; // Animate card (e.g. on play) self.animatePlay = function (_onFinish) { tween(self, { scaleX: 1.15, scaleY: 1.15 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeIn, onFinish: _onFinish }); } }); }; // For MVP, no drag/drop, just tap to play self.down = function (x, y, obj) { if (self.isPlayable && self.owner === "player") { playCard(self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x22222a }); /**** * Game Code ****/ // For MVP, we'll define a small sample and generate the rest as placeholders // Card Data: 52 unique monsters with stats, element, and ability // Tween plugin for card animations (e.g. draw, play, evolve) // --- Game State --- var CARD_DATA = [{ id: 0, name: "Pyro Drake", element: "Fire", attack: 7, defense: 4, ability: "Scorch: Deal 2 extra damage on summon.", color: 0xff5733 }, { id: 1, name: "Aqua Serpent", element: "Water", attack: 5, defense: 6, ability: "Tidecall: Heal 2 defense on play.", color: 0x3399ff }, { id: 2, name: "Terra Golem", element: "Earth", attack: 4, defense: 8, ability: "Fortify: Gain +2 defense if not attacked this turn.", color: 0x7cfc00 }, { id: 3, name: "Zephyr Sprite", element: "Air", attack: 6, defense: 3, ability: "Gust: Can attack twice if opponent has no Air monsters.", color: 0xfafad2 }, { id: 4, name: "Shadow Wraith", element: "Dark", attack: 8, defense: 2, ability: "Ambush: Ignores defense on first attack.", color: 0x222244 }]; // Fill up to 52 cards with placeholder monsters for (var i = CARD_DATA.length; i < 52; i++) { CARD_DATA.push({ id: i, name: "Monster #" + (i + 1), element: ["Fire", "Water", "Earth", "Air", "Dark", "Light"][i % 6], attack: 3 + i % 7, defense: 3 + i * 2 % 7, ability: "No special ability.", color: 0x888888 + i * 1000 }); } var playerDeck = []; var opponentDeck = []; var playerHand = []; var opponentHand = []; var playerField = []; var opponentField = []; var playerGrave = []; var opponentGrave = []; var playerHP = 20; var opponentHP = 20; var turn = "player"; // "player" or "opponent" var phase = "draw"; // "draw", "main", "battle", "end" var selectedCard = null; var handY = 2732 - 420; var fieldY = 2732 - 900; var oppHandY = 420; var oppFieldY = 900; var handCardSpacing = 320; var fieldCardSpacing = 400; var maxHand = 5; var maxField = 3; var gameActive = true; // --- GUI Elements --- var playerHpTxt = new Text2("HP: 20", { size: 60, fill: 0xFF4444 }); playerHpTxt.anchor.set(0, 0.5); LK.gui.left.addChild(playerHpTxt); var opponentHpTxt = new Text2("HP: 20", { size: 60, fill: 0x44AAFF }); opponentHpTxt.anchor.set(1, 0.5); LK.gui.right.addChild(opponentHpTxt); var turnTxt = new Text2("Your Turn", { size: 60, fill: "#fff" }); turnTxt.anchor.set(0.5, 0); LK.gui.top.addChild(turnTxt); // --- Utility Functions --- function shuffleDeck(deck) { for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } function drawCard(deck, hand, owner) { if (deck.length === 0 || hand.length >= maxHand) return null; var cardId = deck.pop(); var card = new Card(); card.setCard(cardId, owner); card.isInHand = true; hand.push(card); return card; } function updateHandPositions() { // Player hand for (var i = 0; i < playerHand.length; i++) { var card = playerHand[i]; card.x = 2048 / 2 + (i - (playerHand.length - 1) / 2) * handCardSpacing; card.y = handY; card.scaleX = card.scaleY = 1; card.setPlayable(turn === "player" && phase === "main" && playerField.length < maxField); card.setSelected(selectedCard === card); } // Opponent hand (hidden) for (var i = 0; i < opponentHand.length; i++) { var card = opponentHand[i]; card.x = 2048 / 2 + (i - (opponentHand.length - 1) / 2) * handCardSpacing; card.y = oppHandY; card.scaleX = card.scaleY = 1; card.setPlayable(false); card.setSelected(false); } } function updateFieldPositions() { // Player field for (var i = 0; i < playerField.length; i++) { var card = playerField[i]; card.x = 2048 / 2 + (i - (playerField.length - 1) / 2) * fieldCardSpacing; card.y = fieldY; card.scaleX = card.scaleY = 1.1; card.setPlayable(false); card.setSelected(false); } // Opponent field for (var i = 0; i < opponentField.length; i++) { var card = opponentField[i]; card.x = 2048 / 2 + (i - (opponentField.length - 1) / 2) * fieldCardSpacing; card.y = oppFieldY + 400; card.scaleX = card.scaleY = 1.1; card.setPlayable(false); card.setSelected(false); } } function updateHpText() { playerHpTxt.setText("HP: " + playerHP); opponentHpTxt.setText("HP: " + opponentHP); } function updateTurnText() { turnTxt.setText(turn === "player" ? "Your Turn" : "Opponent Turn"); } // --- Game Setup --- function setupGame() { // Reset state playerDeck = []; opponentDeck = []; playerHand = []; opponentHand = []; playerField = []; opponentField = []; playerGrave = []; opponentGrave = []; playerHP = 20; opponentHP = 20; turn = "player"; phase = "draw"; selectedCard = null; gameActive = true; // Remove all children from game for (var i = game.children.length - 1; i >= 0; i--) { game.children[i].destroy(); } // Build decks (for MVP, both get all 52 cards, shuffled) for (var i = 0; i < 52; i++) { playerDeck.push(i); opponentDeck.push(i); } shuffleDeck(playerDeck); shuffleDeck(opponentDeck); // Draw starting hands (5 cards) for (var i = 0; i < maxHand; i++) { var card = drawCard(playerDeck, playerHand, "player"); if (card) game.addChild(card); var oppCard = drawCard(opponentDeck, opponentHand, "opponent"); if (oppCard) game.addChild(oppCard); } updateHandPositions(); updateFieldPositions(); updateHpText(); updateTurnText(); } setupGame(); // --- Card Play Logic --- function playCard(card) { if (!gameActive) return; if (turn !== "player" || phase !== "main") return; if (!card.isInHand || playerField.length >= maxField) return; // Remove from hand var idx = playerHand.indexOf(card); if (idx !== -1) playerHand.splice(idx, 1); // Add to field card.isInHand = false; playerField.push(card); // Animate play card.animatePlay(function () { updateHandPositions(); updateFieldPositions(); // Ability triggers if (card.cardData.ability.indexOf("Scorch") !== -1) { // Pyro Drake: deal 2 to opponent HP opponentHP -= 2; LK.effects.flashObject(opponentHpTxt, 0xff0000, 500); updateHpText(); } if (card.cardData.ability.indexOf("Tidecall") !== -1) { // Aqua Serpent: heal 2 defense (for MVP, just flash) LK.effects.flashObject(card, 0x3399ff, 500); } // End main phase if field is full if (playerField.length >= maxField) { phase = "battle"; selectedCard = null; updateHandPositions(); updateFieldPositions(); } }); } // --- Battle Phase Logic --- function playerBattlePhase() { // For MVP: Each player monster attacks opponent monsters in order, or directly if none for (var i = 0; i < playerField.length; i++) { var attacker = playerField[i]; var defender = opponentField[i] || null; if (defender) { // Battle: ATK vs DEF var damage = attacker.cardData.attack - defender.cardData.defense; if (attacker.cardData.ability.indexOf("Ambush") !== -1) { // Shadow Wraith: ignore defense damage = attacker.cardData.attack; } if (damage > 0) { opponentHP -= damage; LK.effects.flashObject(opponentHpTxt, 0xff0000, 500); } // Remove defender if damage >= defense if (attacker.cardData.attack >= defender.cardData.defense) { var idx = opponentField.indexOf(defender); if (idx !== -1) { opponentField.splice(idx, 1); defender.destroy(); } } } else { // Direct attack opponentHP -= attacker.cardData.attack; LK.effects.flashObject(opponentHpTxt, 0xff0000, 500); } } updateHpText(); checkGameEnd(); } function opponentBattlePhase() { for (var i = 0; i < opponentField.length; i++) { var attacker = opponentField[i]; var defender = playerField[i] || null; if (defender) { var damage = attacker.cardData.attack - defender.cardData.defense; if (attacker.cardData.ability.indexOf("Ambush") !== -1) { damage = attacker.cardData.attack; } if (damage > 0) { playerHP -= damage; LK.effects.flashObject(playerHpTxt, 0xff0000, 500); } if (attacker.cardData.attack >= defender.cardData.defense) { var idx = playerField.indexOf(defender); if (idx !== -1) { playerField.splice(idx, 1); defender.destroy(); } } } else { playerHP -= attacker.cardData.attack; LK.effects.flashObject(playerHpTxt, 0xff0000, 500); } } updateHpText(); checkGameEnd(); } // --- Turn/Phase Management --- function nextPhase() { if (!gameActive) return; if (turn === "player") { if (phase === "draw") { // Draw phase var card = drawCard(playerDeck, playerHand, "player"); if (card) game.addChild(card); phase = "main"; updateHandPositions(); updateFieldPositions(); } else if (phase === "main") { // End main phase, go to battle phase = "battle"; selectedCard = null; updateHandPositions(); updateFieldPositions(); // Battle playerBattlePhase(); phase = "end"; nextPhase(); } else if (phase === "end") { // End turn turn = "opponent"; phase = "draw"; updateTurnText(); LK.setTimeout(opponentTurn, 900); } } else { // Opponent phases if (phase === "draw") { var card = drawCard(opponentDeck, opponentHand, "opponent"); if (card) game.addChild(card); phase = "main"; updateHandPositions(); updateFieldPositions(); LK.setTimeout(opponentTurn, 700); } else if (phase === "main") { // Play first playable card if field not full if (opponentField.length < maxField && opponentHand.length > 0) { var card = opponentHand[0]; var idx = opponentHand.indexOf(card); if (idx !== -1) opponentHand.splice(idx, 1); card.isInHand = false; opponentField.push(card); card.animatePlay(function () { updateHandPositions(); updateFieldPositions(); LK.setTimeout(opponentTurn, 600); }); // Ability triggers if (card.cardData.ability.indexOf("Scorch") !== -1) { playerHP -= 2; LK.effects.flashObject(playerHpTxt, 0xff0000, 500); updateHpText(); } if (card.cardData.ability.indexOf("Tidecall") !== -1) { LK.effects.flashObject(card, 0x3399ff, 500); } return; } phase = "battle"; LK.setTimeout(opponentTurn, 600); } else if (phase === "battle") { opponentBattlePhase(); phase = "end"; LK.setTimeout(opponentTurn, 600); } else if (phase === "end") { turn = "player"; phase = "draw"; updateTurnText(); updateHandPositions(); updateFieldPositions(); } } } function opponentTurn() { if (!gameActive) return; if (turn !== "opponent") return; nextPhase(); } // --- Game End --- function checkGameEnd() { if (playerHP <= 0) { LK.effects.flashScreen(0xff0000, 1200); LK.showGameOver(); gameActive = false; } else if (opponentHP <= 0) { LK.effects.flashScreen(0x00ff88, 1200); LK.showYouWin(); gameActive = false; } } // --- Input Handling --- game.down = function (x, y, obj) { if (!gameActive) return; if (turn !== "player" || phase !== "main") return; // Deselect if tap outside hand selectedCard = null; updateHandPositions(); }; game.move = function (x, y, obj) { // No drag for MVP }; game.up = function (x, y, obj) { // No drag for MVP }; // --- End Turn Button --- var endTurnBtn = new Text2("End Turn", { size: 60, fill: "#fff", font: "Impact" }); endTurnBtn.anchor.set(0.5, 0.5); endTurnBtn.y = -40; LK.gui.bottom.addChild(endTurnBtn); endTurnBtn.down = function (x, y, obj) { if (!gameActive) return; if (turn === "player" && (phase === "main" || phase === "draw")) { nextPhase(); } }; // --- Game Update Loop --- game.update = function () { // For MVP, no per-frame logic needed }; // --- Card Asset Initialization (for MVP, only shapes) --- for (var i = 0; i < 52; i++) {}
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Card class: visual and logical representation of a monster card
var Card = Container.expand(function () {
var self = Container.call(this);
// Card properties
self.cardId = null;
self.cardData = null;
self.isInHand = false;
self.isPlayable = false;
self.isSelected = false;
self.owner = null; // "player" or "opponent"
// Card visuals
var cardWidth = 260;
var cardHeight = 380;
// Card background
var cardBg = self.attachAsset('cardBg_' + self.cardId, {
width: cardWidth,
height: cardHeight,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Monster illustration (colored ellipse for MVP)
var monsterArt = self.attachAsset('monsterArt_' + self.cardId, {
width: cardWidth * 0.7,
height: cardHeight * 0.35,
color: 0xcccccc,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.0,
y: -cardHeight * 0.18
});
// Card name
var nameTxt = new Text2('', {
size: 38,
fill: 0x222222
});
nameTxt.anchor.set(0.5, 0);
nameTxt.y = -cardHeight * 0.45;
self.addChild(nameTxt);
// Attack/Defense
var statsTxt = new Text2('', {
size: 32,
fill: 0x333333
});
statsTxt.anchor.set(0.5, 0);
statsTxt.y = cardHeight * 0.32;
self.addChild(statsTxt);
// Element
var elementTxt = new Text2('', {
size: 28,
fill: 0x666666
});
elementTxt.anchor.set(0.5, 0);
elementTxt.y = -cardHeight * 0.32;
self.addChild(elementTxt);
// Ability
var abilityTxt = new Text2('', {
size: 24,
fill: 0x444444
});
abilityTxt.anchor.set(0.5, 0);
abilityTxt.y = cardHeight * 0.12;
self.addChild(abilityTxt);
// Set card data
self.setCard = function (cardId, owner) {
self.cardId = cardId;
self.cardData = CARD_DATA[cardId];
self.owner = owner;
// Set visuals
cardBg.color = 0xffffff;
monsterArt.color = self.cardData.color;
nameTxt.setText(self.cardData.name);
statsTxt.setText("ATK: " + self.cardData.attack + " DEF: " + self.cardData.defense);
elementTxt.setText(self.cardData.element);
abilityTxt.setText(self.cardData.ability);
// For MVP, no evolution/fusion visuals
};
// Highlight if playable/selected
self.setPlayable = function (playable) {
self.isPlayable = playable;
cardBg.color = playable ? 0xffe066 : 0xffffff;
};
self.setSelected = function (selected) {
self.isSelected = selected;
cardBg.color = selected ? 0x66ccff : self.isPlayable ? 0xffe066 : 0xffffff;
};
// Animate card (e.g. on play)
self.animatePlay = function (_onFinish) {
tween(self, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeIn,
onFinish: _onFinish
});
}
});
};
// For MVP, no drag/drop, just tap to play
self.down = function (x, y, obj) {
if (self.isPlayable && self.owner === "player") {
playCard(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x22222a
});
/****
* Game Code
****/
// For MVP, we'll define a small sample and generate the rest as placeholders
// Card Data: 52 unique monsters with stats, element, and ability
// Tween plugin for card animations (e.g. draw, play, evolve)
// --- Game State ---
var CARD_DATA = [{
id: 0,
name: "Pyro Drake",
element: "Fire",
attack: 7,
defense: 4,
ability: "Scorch: Deal 2 extra damage on summon.",
color: 0xff5733
}, {
id: 1,
name: "Aqua Serpent",
element: "Water",
attack: 5,
defense: 6,
ability: "Tidecall: Heal 2 defense on play.",
color: 0x3399ff
}, {
id: 2,
name: "Terra Golem",
element: "Earth",
attack: 4,
defense: 8,
ability: "Fortify: Gain +2 defense if not attacked this turn.",
color: 0x7cfc00
}, {
id: 3,
name: "Zephyr Sprite",
element: "Air",
attack: 6,
defense: 3,
ability: "Gust: Can attack twice if opponent has no Air monsters.",
color: 0xfafad2
}, {
id: 4,
name: "Shadow Wraith",
element: "Dark",
attack: 8,
defense: 2,
ability: "Ambush: Ignores defense on first attack.",
color: 0x222244
}];
// Fill up to 52 cards with placeholder monsters
for (var i = CARD_DATA.length; i < 52; i++) {
CARD_DATA.push({
id: i,
name: "Monster #" + (i + 1),
element: ["Fire", "Water", "Earth", "Air", "Dark", "Light"][i % 6],
attack: 3 + i % 7,
defense: 3 + i * 2 % 7,
ability: "No special ability.",
color: 0x888888 + i * 1000
});
}
var playerDeck = [];
var opponentDeck = [];
var playerHand = [];
var opponentHand = [];
var playerField = [];
var opponentField = [];
var playerGrave = [];
var opponentGrave = [];
var playerHP = 20;
var opponentHP = 20;
var turn = "player"; // "player" or "opponent"
var phase = "draw"; // "draw", "main", "battle", "end"
var selectedCard = null;
var handY = 2732 - 420;
var fieldY = 2732 - 900;
var oppHandY = 420;
var oppFieldY = 900;
var handCardSpacing = 320;
var fieldCardSpacing = 400;
var maxHand = 5;
var maxField = 3;
var gameActive = true;
// --- GUI Elements ---
var playerHpTxt = new Text2("HP: 20", {
size: 60,
fill: 0xFF4444
});
playerHpTxt.anchor.set(0, 0.5);
LK.gui.left.addChild(playerHpTxt);
var opponentHpTxt = new Text2("HP: 20", {
size: 60,
fill: 0x44AAFF
});
opponentHpTxt.anchor.set(1, 0.5);
LK.gui.right.addChild(opponentHpTxt);
var turnTxt = new Text2("Your Turn", {
size: 60,
fill: "#fff"
});
turnTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(turnTxt);
// --- Utility Functions ---
function shuffleDeck(deck) {
for (var i = deck.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
function drawCard(deck, hand, owner) {
if (deck.length === 0 || hand.length >= maxHand) return null;
var cardId = deck.pop();
var card = new Card();
card.setCard(cardId, owner);
card.isInHand = true;
hand.push(card);
return card;
}
function updateHandPositions() {
// Player hand
for (var i = 0; i < playerHand.length; i++) {
var card = playerHand[i];
card.x = 2048 / 2 + (i - (playerHand.length - 1) / 2) * handCardSpacing;
card.y = handY;
card.scaleX = card.scaleY = 1;
card.setPlayable(turn === "player" && phase === "main" && playerField.length < maxField);
card.setSelected(selectedCard === card);
}
// Opponent hand (hidden)
for (var i = 0; i < opponentHand.length; i++) {
var card = opponentHand[i];
card.x = 2048 / 2 + (i - (opponentHand.length - 1) / 2) * handCardSpacing;
card.y = oppHandY;
card.scaleX = card.scaleY = 1;
card.setPlayable(false);
card.setSelected(false);
}
}
function updateFieldPositions() {
// Player field
for (var i = 0; i < playerField.length; i++) {
var card = playerField[i];
card.x = 2048 / 2 + (i - (playerField.length - 1) / 2) * fieldCardSpacing;
card.y = fieldY;
card.scaleX = card.scaleY = 1.1;
card.setPlayable(false);
card.setSelected(false);
}
// Opponent field
for (var i = 0; i < opponentField.length; i++) {
var card = opponentField[i];
card.x = 2048 / 2 + (i - (opponentField.length - 1) / 2) * fieldCardSpacing;
card.y = oppFieldY + 400;
card.scaleX = card.scaleY = 1.1;
card.setPlayable(false);
card.setSelected(false);
}
}
function updateHpText() {
playerHpTxt.setText("HP: " + playerHP);
opponentHpTxt.setText("HP: " + opponentHP);
}
function updateTurnText() {
turnTxt.setText(turn === "player" ? "Your Turn" : "Opponent Turn");
}
// --- Game Setup ---
function setupGame() {
// Reset state
playerDeck = [];
opponentDeck = [];
playerHand = [];
opponentHand = [];
playerField = [];
opponentField = [];
playerGrave = [];
opponentGrave = [];
playerHP = 20;
opponentHP = 20;
turn = "player";
phase = "draw";
selectedCard = null;
gameActive = true;
// Remove all children from game
for (var i = game.children.length - 1; i >= 0; i--) {
game.children[i].destroy();
}
// Build decks (for MVP, both get all 52 cards, shuffled)
for (var i = 0; i < 52; i++) {
playerDeck.push(i);
opponentDeck.push(i);
}
shuffleDeck(playerDeck);
shuffleDeck(opponentDeck);
// Draw starting hands (5 cards)
for (var i = 0; i < maxHand; i++) {
var card = drawCard(playerDeck, playerHand, "player");
if (card) game.addChild(card);
var oppCard = drawCard(opponentDeck, opponentHand, "opponent");
if (oppCard) game.addChild(oppCard);
}
updateHandPositions();
updateFieldPositions();
updateHpText();
updateTurnText();
}
setupGame();
// --- Card Play Logic ---
function playCard(card) {
if (!gameActive) return;
if (turn !== "player" || phase !== "main") return;
if (!card.isInHand || playerField.length >= maxField) return;
// Remove from hand
var idx = playerHand.indexOf(card);
if (idx !== -1) playerHand.splice(idx, 1);
// Add to field
card.isInHand = false;
playerField.push(card);
// Animate play
card.animatePlay(function () {
updateHandPositions();
updateFieldPositions();
// Ability triggers
if (card.cardData.ability.indexOf("Scorch") !== -1) {
// Pyro Drake: deal 2 to opponent HP
opponentHP -= 2;
LK.effects.flashObject(opponentHpTxt, 0xff0000, 500);
updateHpText();
}
if (card.cardData.ability.indexOf("Tidecall") !== -1) {
// Aqua Serpent: heal 2 defense (for MVP, just flash)
LK.effects.flashObject(card, 0x3399ff, 500);
}
// End main phase if field is full
if (playerField.length >= maxField) {
phase = "battle";
selectedCard = null;
updateHandPositions();
updateFieldPositions();
}
});
}
// --- Battle Phase Logic ---
function playerBattlePhase() {
// For MVP: Each player monster attacks opponent monsters in order, or directly if none
for (var i = 0; i < playerField.length; i++) {
var attacker = playerField[i];
var defender = opponentField[i] || null;
if (defender) {
// Battle: ATK vs DEF
var damage = attacker.cardData.attack - defender.cardData.defense;
if (attacker.cardData.ability.indexOf("Ambush") !== -1) {
// Shadow Wraith: ignore defense
damage = attacker.cardData.attack;
}
if (damage > 0) {
opponentHP -= damage;
LK.effects.flashObject(opponentHpTxt, 0xff0000, 500);
}
// Remove defender if damage >= defense
if (attacker.cardData.attack >= defender.cardData.defense) {
var idx = opponentField.indexOf(defender);
if (idx !== -1) {
opponentField.splice(idx, 1);
defender.destroy();
}
}
} else {
// Direct attack
opponentHP -= attacker.cardData.attack;
LK.effects.flashObject(opponentHpTxt, 0xff0000, 500);
}
}
updateHpText();
checkGameEnd();
}
function opponentBattlePhase() {
for (var i = 0; i < opponentField.length; i++) {
var attacker = opponentField[i];
var defender = playerField[i] || null;
if (defender) {
var damage = attacker.cardData.attack - defender.cardData.defense;
if (attacker.cardData.ability.indexOf("Ambush") !== -1) {
damage = attacker.cardData.attack;
}
if (damage > 0) {
playerHP -= damage;
LK.effects.flashObject(playerHpTxt, 0xff0000, 500);
}
if (attacker.cardData.attack >= defender.cardData.defense) {
var idx = playerField.indexOf(defender);
if (idx !== -1) {
playerField.splice(idx, 1);
defender.destroy();
}
}
} else {
playerHP -= attacker.cardData.attack;
LK.effects.flashObject(playerHpTxt, 0xff0000, 500);
}
}
updateHpText();
checkGameEnd();
}
// --- Turn/Phase Management ---
function nextPhase() {
if (!gameActive) return;
if (turn === "player") {
if (phase === "draw") {
// Draw phase
var card = drawCard(playerDeck, playerHand, "player");
if (card) game.addChild(card);
phase = "main";
updateHandPositions();
updateFieldPositions();
} else if (phase === "main") {
// End main phase, go to battle
phase = "battle";
selectedCard = null;
updateHandPositions();
updateFieldPositions();
// Battle
playerBattlePhase();
phase = "end";
nextPhase();
} else if (phase === "end") {
// End turn
turn = "opponent";
phase = "draw";
updateTurnText();
LK.setTimeout(opponentTurn, 900);
}
} else {
// Opponent phases
if (phase === "draw") {
var card = drawCard(opponentDeck, opponentHand, "opponent");
if (card) game.addChild(card);
phase = "main";
updateHandPositions();
updateFieldPositions();
LK.setTimeout(opponentTurn, 700);
} else if (phase === "main") {
// Play first playable card if field not full
if (opponentField.length < maxField && opponentHand.length > 0) {
var card = opponentHand[0];
var idx = opponentHand.indexOf(card);
if (idx !== -1) opponentHand.splice(idx, 1);
card.isInHand = false;
opponentField.push(card);
card.animatePlay(function () {
updateHandPositions();
updateFieldPositions();
LK.setTimeout(opponentTurn, 600);
});
// Ability triggers
if (card.cardData.ability.indexOf("Scorch") !== -1) {
playerHP -= 2;
LK.effects.flashObject(playerHpTxt, 0xff0000, 500);
updateHpText();
}
if (card.cardData.ability.indexOf("Tidecall") !== -1) {
LK.effects.flashObject(card, 0x3399ff, 500);
}
return;
}
phase = "battle";
LK.setTimeout(opponentTurn, 600);
} else if (phase === "battle") {
opponentBattlePhase();
phase = "end";
LK.setTimeout(opponentTurn, 600);
} else if (phase === "end") {
turn = "player";
phase = "draw";
updateTurnText();
updateHandPositions();
updateFieldPositions();
}
}
}
function opponentTurn() {
if (!gameActive) return;
if (turn !== "opponent") return;
nextPhase();
}
// --- Game End ---
function checkGameEnd() {
if (playerHP <= 0) {
LK.effects.flashScreen(0xff0000, 1200);
LK.showGameOver();
gameActive = false;
} else if (opponentHP <= 0) {
LK.effects.flashScreen(0x00ff88, 1200);
LK.showYouWin();
gameActive = false;
}
}
// --- Input Handling ---
game.down = function (x, y, obj) {
if (!gameActive) return;
if (turn !== "player" || phase !== "main") return;
// Deselect if tap outside hand
selectedCard = null;
updateHandPositions();
};
game.move = function (x, y, obj) {
// No drag for MVP
};
game.up = function (x, y, obj) {
// No drag for MVP
};
// --- End Turn Button ---
var endTurnBtn = new Text2("End Turn", {
size: 60,
fill: "#fff",
font: "Impact"
});
endTurnBtn.anchor.set(0.5, 0.5);
endTurnBtn.y = -40;
LK.gui.bottom.addChild(endTurnBtn);
endTurnBtn.down = function (x, y, obj) {
if (!gameActive) return;
if (turn === "player" && (phase === "main" || phase === "draw")) {
nextPhase();
}
};
// --- Game Update Loop ---
game.update = function () {
// For MVP, no per-frame logic needed
};
// --- Card Asset Initialization (for MVP, only shapes) ---
for (var i = 0; i < 52; i++) {}
design monsters in different styles for monster card game let there be only 1 monster design in each frame. In-Game asset. 2d. High contrast. No shadows
design monsters in different styles for monster card game let there be only 1 monster design in each frame. In-Game asset. 2d. High contrast. No shadows
Modern App Store icon, high definition, square with rounded corners, for a game. No text on icon! monster card deck
basılabilir tuş görseli dikdörtgen. In-Game asset. 2d. High contrast. No shadows