fix(SCOPONE-0011): complete iteration 0 - tune ai and ui
This commit is contained in:
@@ -37,10 +37,11 @@ const CH_A = 645 * CARD_SCALE_AI; // card height for AI ≈ 81
|
||||
const SCOREBAR_H = 54;
|
||||
const AI_MIN_THINK_MS = 1000;
|
||||
const MOVE_OUTCOME_STATUS_MS = 2000;
|
||||
const PLAYED_CARD_TRAVEL_MS = 400;
|
||||
const CAPTURE_COLLAPSE_MS = 480;
|
||||
const PLAYED_CARD_TRAVEL_MS = 320;
|
||||
const CAPTURE_COLLAPSE_MS = 360;
|
||||
const CAPTURE_COLLAPSE_DELAY_MS = 60;
|
||||
const NON_CAPTURE_TABLE_TWEEN_MS = 560;
|
||||
const NON_CAPTURE_TABLE_TWEEN_MS = 420;
|
||||
const RELAYOUT_TWEEN_MS = 120;
|
||||
|
||||
// Player positions:
|
||||
// 0 = South (human, bottom), 1 = West (AI, left, rotated -90°)
|
||||
@@ -93,7 +94,7 @@ export class GameScene extends Phaser.Scene {
|
||||
private thinkBar!: Phaser.GameObjects.Graphics;
|
||||
|
||||
// Player label containers (pulsed on active turn)
|
||||
private playerLabels: Map<PlayerIndex, Phaser.GameObjects.Text> = new Map();
|
||||
private playerLabels: Map<PlayerIndex, Phaser.GameObjects.Container> = new Map();
|
||||
|
||||
// Interaction state
|
||||
private selectedCard: Card | null = null;
|
||||
@@ -388,6 +389,7 @@ export class GameScene extends Phaser.Scene {
|
||||
this.statusText = this.add.text(W / 2, H - CH_H - 36, '', {
|
||||
fontFamily: 'serif', fontSize: '17px', color: '#ffffff',
|
||||
stroke: '#000', strokeThickness: 2,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(10);
|
||||
}
|
||||
|
||||
@@ -524,23 +526,59 @@ export class GameScene extends Phaser.Scene {
|
||||
return `Problema durante la mossa di ${this.state.players[playerIdx].name}.`;
|
||||
}
|
||||
|
||||
private withHiResText(
|
||||
style: Phaser.Types.GameObjects.Text.TextStyle,
|
||||
): Phaser.Types.GameObjects.Text.TextStyle {
|
||||
return {
|
||||
...style,
|
||||
resolution: style.resolution ?? 2,
|
||||
};
|
||||
}
|
||||
|
||||
private createPlayerNameplate(
|
||||
x: number,
|
||||
y: number,
|
||||
text: string,
|
||||
color: string,
|
||||
fillColor: number,
|
||||
strokeColor: number,
|
||||
): Phaser.GameObjects.Container {
|
||||
const label = this.add.text(0, 0, text, this.withHiResText({
|
||||
fontFamily: 'serif',
|
||||
fontSize: '11px',
|
||||
color,
|
||||
stroke: '#000',
|
||||
strokeThickness: 1,
|
||||
align: 'center',
|
||||
})).setOrigin(0.5);
|
||||
|
||||
const padX = 12;
|
||||
const padY = 4;
|
||||
const width = label.width + padX * 2;
|
||||
const height = label.height + padY * 2;
|
||||
const background = this.add.graphics();
|
||||
background.fillStyle(fillColor, 0.92);
|
||||
background.fillRoundedRect(-width / 2, -height / 2, width, height, 9);
|
||||
background.lineStyle(1, strokeColor, 0.7);
|
||||
background.strokeRoundedRect(-width / 2, -height / 2, width, height, 9);
|
||||
|
||||
return this.add.container(x, y, [background, label]).setDepth(18);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Player labels (pulse on active turn)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
private buildPlayerLabels(W: number, H: number): void {
|
||||
const defs: Array<{ idx: PlayerIndex; x: number; y: number; color: string;
|
||||
txt: string; originX: number; originY: number }> = [
|
||||
{ idx: 0, x: W / 2, y: H - CH_H - 28, color: '#aaffaa', txt: 'Tu [Team A]', originX: 0.5, originY: 1 },
|
||||
{ idx: 1, x: CH_A + 20, y: H / 2 + SCOREBAR_H / 2, color: '#ffaaaa', txt: 'AI\nOvest\n[B]', originX: 0, originY: 0.5 },
|
||||
{ idx: 2, x: W / 2, y: SCOREBAR_H + CH_A + 44, color: '#aaffaa', txt: 'Compagno [Team A]', originX: 0.5, originY: 0 },
|
||||
{ idx: 3, x: W - CH_A - 20, y: H / 2 + SCOREBAR_H / 2, color: '#ffaaaa', txt: 'AI\nEst\n[B]', originX: 1, originY: 0.5 },
|
||||
fillColor: number; strokeColor: number; txt: string }> = [
|
||||
{ idx: 0, x: W / 2, y: H - 9, color: '#dfffe5', fillColor: 0x0b2410, strokeColor: 0x4aa86a, txt: 'Tu [Team A]' },
|
||||
{ idx: 1, x: CH_A + 58, y: H / 2 + SCOREBAR_H / 2, color: '#ffe0e0', fillColor: 0x260d0d, strokeColor: 0xb36a6a, txt: 'AI Ovest [B]' },
|
||||
{ idx: 2, x: W / 2, y: SCOREBAR_H + 11, color: '#dfffe5', fillColor: 0x0b2410, strokeColor: 0x4aa86a, txt: 'Compagno [Team A]' },
|
||||
{ idx: 3, x: W - CH_A - 58, y: H / 2 + SCOREBAR_H / 2, color: '#ffe0e0', fillColor: 0x260d0d, strokeColor: 0xb36a6a, txt: 'AI Est [B]' },
|
||||
];
|
||||
for (const d of defs) {
|
||||
const lbl = this.add.text(d.x, d.y, d.txt, {
|
||||
fontFamily: 'serif', fontSize: '12px', color: d.color,
|
||||
stroke: '#000', strokeThickness: 1, align: 'center', resolution: 2,
|
||||
}).setOrigin(d.originX, d.originY).setDepth(2);
|
||||
const lbl = this.createPlayerNameplate(d.x, d.y, d.txt, d.color, d.fillColor, d.strokeColor);
|
||||
this.playerLabels.set(d.idx, lbl);
|
||||
}
|
||||
}
|
||||
@@ -594,7 +632,7 @@ export class GameScene extends Phaser.Scene {
|
||||
const activeLbl = this.playerLabels.get(playerIdx)!;
|
||||
this.tweens.add({
|
||||
targets: activeLbl,
|
||||
scaleX: 1.2, scaleY: 1.2,
|
||||
scaleX: 1.08, scaleY: 1.08,
|
||||
duration: 300, yoyo: true, ease: 'Sine.InOut',
|
||||
});
|
||||
}
|
||||
@@ -929,6 +967,7 @@ export class GameScene extends Phaser.Scene {
|
||||
const btn = this.add.zone(W / 2, y, 360, 28).setInteractive({ useHandCursor: true }).setDepth(21);
|
||||
const txt = this.add.text(W / 2, y, `Prendi: ${label}`, {
|
||||
fontFamily: 'serif', fontSize: '14px', color: color.text,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(21);
|
||||
btn.on('pointerdown', () => this.confirmMove(this.selectedCard!, cap));
|
||||
(bg as any)._captureBtn = true;
|
||||
@@ -1113,7 +1152,15 @@ export class GameScene extends Phaser.Scene {
|
||||
const positions = this.getHandPositions(playerIdx, hand.length);
|
||||
hand.forEach((card, i) => {
|
||||
const img = this.cardImages.get(card.id);
|
||||
if (img) this.tweens.add({ targets: img, x: positions[i].x, y: positions[i].y, duration: 160 });
|
||||
if (img) {
|
||||
this.tweens.add({
|
||||
targets: img,
|
||||
x: positions[i].x,
|
||||
y: positions[i].y,
|
||||
duration: RELAYOUT_TWEEN_MS,
|
||||
ease: 'Cubic.Out',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1123,7 +1170,15 @@ export class GameScene extends Phaser.Scene {
|
||||
const positions = this.getTablePositions(table.length);
|
||||
table.forEach((card, i) => {
|
||||
const img = this.cardImages.get(card.id);
|
||||
if (img?.visible) this.tweens.add({ targets: img, x: positions[i].x, y: positions[i].y, duration: 160 });
|
||||
if (img?.visible) {
|
||||
this.tweens.add({
|
||||
targets: img,
|
||||
x: positions[i].x,
|
||||
y: positions[i].y,
|
||||
duration: RELAYOUT_TWEEN_MS,
|
||||
ease: 'Cubic.Out',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1196,12 +1251,14 @@ export class GameScene extends Phaser.Scene {
|
||||
const txt = this.add.text(W / 2, H / 2, 'SCOPA!', {
|
||||
fontFamily: 'Georgia, serif', fontSize: '108px', color: '#ffd700',
|
||||
stroke: '#000000', strokeThickness: 10,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(50).setAlpha(0).setScale(0.2);
|
||||
|
||||
const sub = this.add.text(W / 2, H / 2 + 110, player.name, {
|
||||
fontFamily: 'serif', fontSize: '32px',
|
||||
color: isTeamA ? '#aaffaa' : '#ffaaaa',
|
||||
stroke: '#000', strokeThickness: 3,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(50).setAlpha(0);
|
||||
|
||||
this.tweens.add({
|
||||
@@ -1257,6 +1314,7 @@ export class GameScene extends Phaser.Scene {
|
||||
const txt = this.add.text(W / 2, H / 2 - 60, '7♦', {
|
||||
fontFamily: 'Georgia, serif', fontSize: '64px', color: '#ffd700',
|
||||
stroke: '#000', strokeThickness: 7,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(50).setAlpha(0).setScale(0.4);
|
||||
|
||||
this.tweens.add({
|
||||
@@ -1497,10 +1555,11 @@ export class GameScene extends Phaser.Scene {
|
||||
];
|
||||
|
||||
lines.forEach(([line, color], i) => {
|
||||
this.add.text(W / 2, H / 2 - 190 + i * 34, line, {
|
||||
this.add.text(W / 2, H / 2 - 190 + i * 34, line, this.withHiResText({
|
||||
fontFamily: i === 0 ? 'Georgia, serif' : 'monospace',
|
||||
fontSize: i === 0 ? '28px' : '16px', color,
|
||||
}).setOrigin(0.5).setDepth(32);
|
||||
fontSize: i === 0 ? '28px' : '16px',
|
||||
color,
|
||||
})).setOrigin(0.5).setDepth(32);
|
||||
});
|
||||
|
||||
const outcome = getMatchOutcome(this.state.teamScores);
|
||||
@@ -1514,6 +1573,7 @@ export class GameScene extends Phaser.Scene {
|
||||
.setInteractive({ useHandCursor: true }).setDepth(33);
|
||||
this.add.text(W / 2, H / 2 + 207, btnLabel, {
|
||||
fontFamily: 'Georgia, serif', fontSize: '20px', color: '#0a2e10',
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(34);
|
||||
|
||||
btnG.on('pointerover', () => { btnG.clear(); btnG.fillStyle(0xffec6e, 1); btnG.fillRoundedRect(W / 2 - 110, H / 2 + 185, 220, 44, 10); });
|
||||
@@ -1556,13 +1616,16 @@ export class GameScene extends Phaser.Scene {
|
||||
this.add.text(W / 2, H / 2 - 110, 'PARTITA CONCLUSA', {
|
||||
fontFamily: 'Georgia, serif', fontSize: '44px', color: '#ffd700',
|
||||
stroke: '#000', strokeThickness: 6,
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(42);
|
||||
this.add.text(W / 2, H / 2 - 30, win ? 'Vince la tua squadra' : 'Vincono gli avversari', {
|
||||
fontFamily: 'serif', fontSize: '26px',
|
||||
color: win ? '#aaffaa' : '#ffaaaa',
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(42);
|
||||
this.add.text(W / 2, H / 2 + 35, `${t0.totalPoints} — ${t1.totalPoints}`, {
|
||||
fontFamily: 'Georgia, serif', fontSize: '50px', color: '#ffd700',
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(42);
|
||||
|
||||
const bz = this.add.zone(W / 2, H / 2 + 115, 230, 48)
|
||||
@@ -1572,6 +1635,7 @@ export class GameScene extends Phaser.Scene {
|
||||
drawBtn(0xffd700);
|
||||
this.add.text(W / 2, H / 2 + 115, 'NUOVA PARTITA', {
|
||||
fontFamily: 'Georgia, serif', fontSize: '21px', color: '#0a2e10',
|
||||
resolution: 2,
|
||||
}).setOrigin(0.5).setDepth(44);
|
||||
bz.on('pointerover', () => drawBtn(0xffec6e));
|
||||
bz.on('pointerout', () => drawBtn(0xffd700));
|
||||
|
||||
Reference in New Issue
Block a user