146 lines
5.7 KiB
JavaScript
146 lines
5.7 KiB
JavaScript
import { SaveManager } from '../managers/SaveManager.js';
|
|
|
|
export class StoreScene extends Phaser.Scene {
|
|
constructor() { super('StoreScene'); }
|
|
|
|
create() {
|
|
const { width, height } = this.scale;
|
|
const save = this.registry.get('save');
|
|
const packManager = this.registry.get('packManager');
|
|
|
|
this.add.rectangle(width / 2, height / 2, width, height, 0x0d1b2a);
|
|
this.add.text(width / 2, 45, 'Card Store', { fontSize: '42px', color: '#d4af37' }).setOrigin(0.5);
|
|
this.add.text(width / 2, 90, 'Buy packs to expand your collection', {
|
|
fontSize: '20px', color: '#888888'
|
|
}).setOrigin(0.5);
|
|
|
|
this.goldText = this.add.text(width - 20, 20, `Gold: ${save.gold}`, {
|
|
fontSize: '24px', color: '#ffd700'
|
|
}).setOrigin(1, 0);
|
|
|
|
const packs = packManager.getAllPacks();
|
|
packs.forEach((pack, i) => {
|
|
const x = width / 2 + (i - packs.length / 2 + 0.5) * 440;
|
|
this._renderPack(pack, x, 350);
|
|
});
|
|
|
|
this.revealArea = [];
|
|
this._makeBackButton();
|
|
}
|
|
|
|
_renderPack(pack, x, y) {
|
|
// Pack visual
|
|
const packBg = this.add.rectangle(x, y, 380, 340, 0x1a3a5c)
|
|
.setStrokeStyle(3, 0xffd700);
|
|
|
|
// Pack art (procedural)
|
|
this.add.rectangle(x, y - 60, 180, 150, 0x0d2240).setStrokeStyle(1, 0x4488ff);
|
|
this.add.text(x, y - 60, 'PACK', { fontSize: '38px', color: '#4488ff' }).setOrigin(0.5);
|
|
|
|
this.add.text(x, y + 45, pack.name, { fontSize: '24px', color: '#ffffff' }).setOrigin(0.5);
|
|
this.add.text(x, y + 75, `${pack.cardCount} cards per pack`, { fontSize: '18px', color: '#aaaaaa' }).setOrigin(0.5);
|
|
this.add.text(x, y + 100, `Cost: ${pack.cost} Gold`, { fontSize: '20px', color: '#ffd700' }).setOrigin(0.5);
|
|
|
|
// Drop rates display
|
|
const rateLines = Object.entries(pack.dropRates).map(([r, v]) =>
|
|
`${r.charAt(0).toUpperCase() + r.slice(1)}: ${Math.floor(v * 100)}%`
|
|
).join(' ');
|
|
this.add.text(x, y + 128, rateLines, {
|
|
fontSize: '14px', color: '#888888', wordWrap: { width: 360 }, align: 'center'
|
|
}).setOrigin(0.5);
|
|
|
|
const buyBtn = this.add.rectangle(x, y + 170, 240, 55, 0x224422)
|
|
.setInteractive({ useHandCursor: true })
|
|
.setStrokeStyle(2, 0x44aa44);
|
|
const buyTxt = this.add.text(x, y + 170, 'Buy Pack', { fontSize: '22px', color: '#ffffff' }).setOrigin(0.5);
|
|
|
|
buyBtn.on('pointerover', () => buyBtn.setFillStyle(0x336633));
|
|
buyBtn.on('pointerout', () => buyBtn.setFillStyle(0x224422));
|
|
buyBtn.on('pointerdown', () => this._buyPack(pack));
|
|
}
|
|
|
|
_buyPack(pack) {
|
|
const save = this.registry.get('save');
|
|
const packManager = this.registry.get('packManager');
|
|
const { width, height } = this.scale;
|
|
|
|
if (!SaveManager.spendGold(save, pack.cost)) {
|
|
this._showMsg('Not enough gold!', '#ff4444');
|
|
return;
|
|
}
|
|
|
|
const cards = packManager.openPack(pack.id, save);
|
|
if (!cards || cards.length === 0) {
|
|
this._showMsg('Pack is empty!', '#ff8800');
|
|
return;
|
|
}
|
|
cards.forEach(card => SaveManager.addCard(save, card.id));
|
|
this.registry.set('save', save);
|
|
this.goldText.setText(`Gold: ${save.gold}`);
|
|
|
|
// Clear previous reveal
|
|
this.revealArea.forEach(o => o.destroy());
|
|
this.revealArea = [];
|
|
|
|
// Show revealed cards with animation
|
|
const totalW = cards.length * 300 + (cards.length - 1) * 20;
|
|
const startX = width / 2 - totalW / 2 + 140;
|
|
const rarityColors = { common: 0x888888, rare: 0x4488ff, epic: 0xaa44ff, legendary: 0xffaa00 };
|
|
const factionColors = { imperial: 0x2244aa, raider: 0xaa2222 };
|
|
|
|
// Label
|
|
const label = this.add.text(width / 2, 700, 'You received:', {
|
|
fontSize: '22px', color: '#ffffff'
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
this.revealArea.push(label);
|
|
this.tweens.add({ targets: label, alpha: 1, duration: 300 });
|
|
|
|
cards.forEach((card, i) => {
|
|
const x = startX + i * 320;
|
|
const y = 860;
|
|
|
|
const bg = this.add.rectangle(x, y, 280, 210, factionColors[card.faction] || 0x1a3a5c)
|
|
.setStrokeStyle(3, rarityColors[card.rarity] || 0x888888)
|
|
.setAlpha(0);
|
|
const nameT = this.add.text(x, y - 70, card.name, {
|
|
fontSize: '20px', color: '#ffffff', wordWrap: { width: 260 }, align: 'center'
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
const rarityT = this.add.text(x, y - 30, card.rarity.toUpperCase(), {
|
|
fontSize: '16px',
|
|
color: '#' + (rarityColors[card.rarity] || 0x888888).toString(16).padStart(6, '0')
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
const statsT = this.add.text(x, y + 4, `ATK:${card.attack} HP:${card.health} ARM:${card.armor}`, {
|
|
fontSize: '16px', color: '#aaaaff'
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
const skillT = this.add.text(x, y + 34, card.skills.map(s => s.name).join(', '), {
|
|
fontSize: '14px', color: '#ffcc44'
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
const newT = this.add.text(x, y + 65, (save.collection[card.id] || 0) === 1 ? 'NEW!' : `x${save.collection[card.id]}`, {
|
|
fontSize: '16px', color: (save.collection[card.id] || 0) === 1 ? '#44ff44' : '#aaaaaa'
|
|
}).setOrigin(0.5).setAlpha(0);
|
|
|
|
this.revealArea.push(bg, nameT, rarityT, statsT, skillT, newT);
|
|
|
|
this.tweens.add({
|
|
targets: [bg, nameT, rarityT, statsT, skillT, newT],
|
|
alpha: 1, duration: 400, delay: i * 350,
|
|
ease: 'Power2'
|
|
});
|
|
});
|
|
}
|
|
|
|
_showMsg(msg, color) {
|
|
const { width } = this.scale;
|
|
const t = this.add.text(width / 2, 660, msg, { fontSize: '24px', color }).setOrigin(0.5);
|
|
this.time.delayedCall(2000, () => t.destroy());
|
|
}
|
|
|
|
_makeBackButton() {
|
|
const bg = this.add.rectangle(80, 1040, 160, 45, 0x333333)
|
|
.setInteractive({ useHandCursor: true })
|
|
.setStrokeStyle(1, 0x888888);
|
|
this.add.text(80, 1040, 'Back', { fontSize: '18px', color: '#ffffff' }).setOrigin(0.5);
|
|
bg.on('pointerdown', () => this.scene.start('MainMenuScene'));
|
|
}
|
|
}
|