feat(blackjack): enhance betting UI with prompts and fix button interactions
- Add animated betting prompts with pulsing chip buttons and text overlay - Implement delayed start for betting animations after 5 seconds - Refactor chip buttons to use containers for proper hit detection - Update Button component to ensure interactive events work on all child objects - Improve betting UI visibility management with proper show/hide states - Add depth management for betting prompts and chip buttons
This commit is contained in:
parent
48f7ade241
commit
1f1897c8fe
|
|
@ -23,9 +23,9 @@ const DEALER_X = CX;
|
||||||
const DEALER_Y = 420; // ~1/3 down the table ellipse (top ≈190, bottom ≈890)
|
const DEALER_Y = 420; // ~1/3 down the table ellipse (top ≈190, bottom ≈890)
|
||||||
|
|
||||||
const SEAT_POS = [
|
const SEAT_POS = [
|
||||||
{ x: CX, y: 860, portraitR: 72, portraitX: CX - 230, portraitY: 860 }, // Human
|
{ x: CX, y: 860, portraitR: 72, portraitX: CX - 230, portraitY: 860 }, // Human
|
||||||
{ x: 380, y: 775, portraitR: 58, portraitX: 200, portraitY: 650 }, // Opp 1 bottom-left (outside ellipse)
|
{ x: 380, y: 775, portraitR: 58, portraitX: 200, portraitY: 650 }, // Opp 1 bottom-left (outside ellipse)
|
||||||
{ x: 150, y: 490, portraitR: 58 }, // Opp 2 left (already outside ellipse)
|
{ x: 150, y: 490, portraitR: 58 }, // Opp 2 left (already outside ellipse)
|
||||||
{ x: 1770, y: 490, portraitR: 58 }, // Opp 3 right (already outside ellipse)
|
{ x: 1770, y: 490, portraitR: 58 }, // Opp 3 right (already outside ellipse)
|
||||||
{ x: 1540, y: 775, portraitR: 58, portraitX: 1720, portraitY: 650 }, // Opp 4 bottom-right (outside ellipse)
|
{ x: 1540, y: 775, portraitR: 58, portraitX: 1720, portraitY: 650 }, // Opp 4 bottom-right (outside ellipse)
|
||||||
];
|
];
|
||||||
|
|
@ -46,15 +46,15 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
constructor() { super('BlackjackGame'); }
|
constructor() { super('BlackjackGame'); }
|
||||||
|
|
||||||
init(data) {
|
init(data) {
|
||||||
this.gameDef = data.game;
|
this.gameDef = data.game;
|
||||||
this.opponents = data.opponents ?? [];
|
this.opponents = data.opponents ?? [];
|
||||||
this.playfield = data.playfield ?? null;
|
this.playfield = data.playfield ?? null;
|
||||||
this.cardBack = data.cardBack ?? null;
|
this.cardBack = data.cardBack ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async create() {
|
async create() {
|
||||||
this.shoe = buildShoe();
|
this.shoe = buildShoe();
|
||||||
this.gs = null;
|
this.gs = null;
|
||||||
this.animating = false;
|
this.animating = false;
|
||||||
this.pendingBet = 0;
|
this.pendingBet = 0;
|
||||||
this.portraits = [];
|
this.portraits = [];
|
||||||
|
|
@ -72,6 +72,9 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
this.statusBadges = {};
|
this.statusBadges = {};
|
||||||
this.nameTxts = {};
|
this.nameTxts = {};
|
||||||
this.chipTxts = {};
|
this.chipTxts = {};
|
||||||
|
this.bettingPromptGroup = [];
|
||||||
|
this.bettingPromptTimer = null;
|
||||||
|
this.chipPulseTweens = [];
|
||||||
|
|
||||||
this.add.rectangle(CX, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, COLORS.bg).setDepth(D.bg);
|
this.add.rectangle(CX, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, COLORS.bg).setDepth(D.bg);
|
||||||
this.buildPlayfield();
|
this.buildPlayfield();
|
||||||
|
|
@ -165,9 +168,9 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
|
|
||||||
// Semi-transparent backing behind both text lines, depth below portrait images/videos
|
// Semi-transparent backing behind both text lines, depth below portrait images/videos
|
||||||
{
|
{
|
||||||
const maxTW = Math.max(this.nameTxts[seat].width, 130);
|
const maxTW = Math.max(this.nameTxts[seat].width, 130);
|
||||||
const rectW = maxTW + 20;
|
const rectW = maxTW + 20;
|
||||||
const rectH = (chipY - nameY) + 36;
|
const rectH = (chipY - nameY) + 36;
|
||||||
// For right-anchored text the anchor is the RIGHT edge; for left-anchored it's the LEFT edge
|
// For right-anchored text the anchor is the RIGHT edge; for left-anchored it's the LEFT edge
|
||||||
const rectCX = labelAnchorX === 1 ? nameX - maxTW / 2 : nameX + maxTW / 2;
|
const rectCX = labelAnchorX === 1 ? nameX - maxTW / 2 : nameX + maxTW / 2;
|
||||||
const rectCY = (nameY + chipY) / 2;
|
const rectCY = (nameY + chipY) / 2;
|
||||||
|
|
@ -199,15 +202,17 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
// Chip buttons
|
// Chip buttons
|
||||||
CHIP_AMOUNTS.forEach((amt, i) => {
|
CHIP_AMOUNTS.forEach((amt, i) => {
|
||||||
const bx = cx - 120 + i * 80;
|
const bx = cx - 120 + i * 80;
|
||||||
const g = this.add.graphics().setDepth(D.ui + 1);
|
const container = this.add.container(bx, y).setDepth(D.ui + 1);
|
||||||
g.fillStyle(CHIP_COLORS[amt], 1);
|
const g = this.add.graphics();
|
||||||
g.fillCircle(bx, y, 28);
|
|
||||||
g.lineStyle(3, 0xffffff, 0.4);
|
g.lineStyle(3, 0xffffff, 0.4);
|
||||||
g.strokeCircle(bx, y, 28);
|
g.strokeCircle(0, 0, 28);
|
||||||
g.setInteractive(new Phaser.Geom.Circle(bx, y, 28), Phaser.Geom.Circle.Contains);
|
g.fillStyle(CHIP_COLORS[amt], 1);
|
||||||
g.on('pointerdown', () => this.onChipClick(amt));
|
g.fillCircle(0, 0, 28);
|
||||||
g.on('pointerover', () => g.setAlpha(0.8));
|
container.add(g);
|
||||||
g.on('pointerout', () => g.setAlpha(1));
|
container.setInteractive(new Phaser.Geom.Circle(0, 0, 28), Phaser.Geom.Circle.Contains);
|
||||||
|
container.on('pointerdown', () => this.onChipClick(amt));
|
||||||
|
container.on('pointerover', () => container.setAlpha(0.8));
|
||||||
|
container.on('pointerout', () => container.setAlpha(1));
|
||||||
|
|
||||||
const t = this.add.text(bx, y, `$${amt}`, {
|
const t = this.add.text(bx, y, `$${amt}`, {
|
||||||
fontFamily: 'system-ui, sans-serif', fontSize: '13px',
|
fontFamily: 'system-ui, sans-serif', fontSize: '13px',
|
||||||
|
|
@ -238,8 +243,136 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
this.hideBettingUI();
|
this.hideBettingUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
showBettingUI() { for (const o of this.bettingUIGroup) o.setVisible?.(true) || (o.visible = true); }
|
showBettingUI() {
|
||||||
hideBettingUI() { for (const o of this.bettingUIGroup) o.setVisible?.(false) || (o.visible = false); }
|
for (const o of this.bettingUIGroup) o.setVisible?.(true) || (o.visible = true);
|
||||||
|
this.chipBtnGraphics.forEach(g => g.setDepth(D.ui + 1));
|
||||||
|
this.startBettingPrompts();
|
||||||
|
}
|
||||||
|
hideBettingUI() {
|
||||||
|
for (const o of this.bettingUIGroup) o.setVisible?.(false) || (o.visible = false);
|
||||||
|
this.hideBettingPrompts();
|
||||||
|
}
|
||||||
|
|
||||||
|
startBettingPrompts() {
|
||||||
|
this.hideBettingPrompts();
|
||||||
|
|
||||||
|
// Wait 5 seconds before starting any animations
|
||||||
|
this.bettingPromptTimer = this.time.delayedCall(5000, () => {
|
||||||
|
if (!this.scene.isActive('BlackjackGame')) return;
|
||||||
|
if (this.pendingBet > 0) return; // Don't start if already betting
|
||||||
|
|
||||||
|
// Start subtle radius pulsing animation
|
||||||
|
this.chipBtnGraphics.forEach((chip, index) => {
|
||||||
|
const delay = index * 200;
|
||||||
|
const tween = this.tweens.add({
|
||||||
|
targets: chip,
|
||||||
|
scaleX: 1.25,
|
||||||
|
scaleY: 1.25,
|
||||||
|
duration: 1200,
|
||||||
|
ease: 'Sine.easeInOut',
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
delay: delay,
|
||||||
|
});
|
||||||
|
this.chipPulseTweens.push(tween);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show prompt text
|
||||||
|
this.showBettingPrompt();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
showBettingPrompt() {
|
||||||
|
if (this.pendingBet > 0) return; // Don't show if already betting
|
||||||
|
|
||||||
|
const y = GAME_HEIGHT - 160;
|
||||||
|
const cx = CX;
|
||||||
|
|
||||||
|
// Create semi-transparent background
|
||||||
|
const bg = this.add.rectangle(cx + 100, y, 420, 60, 0x000000, 0.7)
|
||||||
|
.setOrigin(0.5, 0.5)
|
||||||
|
.setDepth(D.ui + 10)
|
||||||
|
.setAlpha(0);
|
||||||
|
|
||||||
|
// Create prompt text
|
||||||
|
const text = this.add.text(cx + 100, y, 'Choose an amount to bet and click Deal to begin', {
|
||||||
|
fontFamily: 'system-ui, sans-serif',
|
||||||
|
fontSize: '18px',
|
||||||
|
color: '#ffffff',
|
||||||
|
align: 'center',
|
||||||
|
})
|
||||||
|
.setOrigin(0.5, 0.5)
|
||||||
|
.setDepth(D.ui + 11)
|
||||||
|
.setAlpha(0);
|
||||||
|
|
||||||
|
this.bettingPromptGroup = [bg, text];
|
||||||
|
|
||||||
|
// Fade in
|
||||||
|
this.tweens.add({
|
||||||
|
targets: bg,
|
||||||
|
alpha: 0.7,
|
||||||
|
duration: 300,
|
||||||
|
ease: 'Power2',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: text,
|
||||||
|
alpha: 1,
|
||||||
|
duration: 300,
|
||||||
|
ease: 'Power2',
|
||||||
|
delay: 100,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
hideBettingPrompts() {
|
||||||
|
// Fade out prompt if visible
|
||||||
|
if (this.bettingPromptGroup && this.bettingPromptGroup.length > 0) {
|
||||||
|
this.tweens.add({
|
||||||
|
targets: this.bettingPromptGroup,
|
||||||
|
alpha: 0,
|
||||||
|
duration: 200,
|
||||||
|
ease: 'Power2',
|
||||||
|
onComplete: () => {
|
||||||
|
this.bettingPromptGroup.forEach(obj => obj.destroy());
|
||||||
|
this.bettingPromptGroup = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (this.bettingPromptGroup.length > 0) {
|
||||||
|
this.bettingPromptGroup.forEach(obj => obj.destroy());
|
||||||
|
this.bettingPromptGroup = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop chip pulsing
|
||||||
|
this.chipPulseTweens.forEach(tween => tween.destroy());
|
||||||
|
this.chipPulseTweens = [];
|
||||||
|
this.chipBtnGraphics.forEach(chip => {
|
||||||
|
chip.setScale(1, 1);
|
||||||
|
chip.setAlpha(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear timer
|
||||||
|
if (this.bettingPromptTimer) {
|
||||||
|
this.bettingPromptTimer.remove();
|
||||||
|
this.bettingPromptTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startBettingPromptsIfNoBet() {
|
||||||
|
// Only start prompts if no bet has been placed yet
|
||||||
|
if (this.pendingBet === 0) {
|
||||||
|
this.startBettingPrompts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideBettingUI() {
|
||||||
|
for (const o of this.bettingUIGroup) {
|
||||||
|
o.setVisible?.(false) || (o.visible = false);
|
||||||
|
}
|
||||||
|
this.hideBettingPrompts();
|
||||||
|
// Also hide chip containers from the betting UI
|
||||||
|
this.chipBtnGraphics.forEach(g => g.setVisible?.(false) || (g.visible = false));
|
||||||
|
this.chipBtnGraphics.forEach(g => g.setDepth(-100));
|
||||||
|
}
|
||||||
|
|
||||||
// ── Chip balance ──────────────────────────────────────────────────────────
|
// ── Chip balance ──────────────────────────────────────────────────────────
|
||||||
async loadPlayerChips() {
|
async loadPlayerChips() {
|
||||||
|
|
@ -445,10 +578,10 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
fontFamily: 'system-ui, sans-serif', fontSize: `${sz}px`, color,
|
fontFamily: 'system-ui, sans-serif', fontSize: `${sz}px`, color,
|
||||||
...(bold ? { fontStyle: 'bold' } : {}),
|
...(bold ? { fontStyle: 'bold' } : {}),
|
||||||
});
|
});
|
||||||
container.add(this.add.text(x + 7, y + 5, card.label, style(17, true)));
|
container.add(this.add.text(x + 7, y + 5, card.label, style(17, true)));
|
||||||
container.add(this.add.text(x + 7, y + 23, card.suitSymbol, style(13)));
|
container.add(this.add.text(x + 7, y + 23, card.suitSymbol, style(13)));
|
||||||
container.add(this.add.text(0, 4, card.suitSymbol, style(40)).setOrigin(0.5));
|
container.add(this.add.text(0, 4, card.suitSymbol, style(40)).setOrigin(0.5));
|
||||||
container.add(this.add.text(x + CARD_W - 7, y + CARD_H - 8, card.label, style(17, true)).setOrigin(1, 1));
|
container.add(this.add.text(x + CARD_W - 7, y + CARD_H - 8, card.label, style(17, true)).setOrigin(1, 1));
|
||||||
container.add(this.add.text(x + CARD_W - 7, y + CARD_H - 22, card.suitSymbol, style(13)).setOrigin(1, 1));
|
container.add(this.add.text(x + CARD_W - 7, y + CARD_H - 22, card.suitSymbol, style(13)).setOrigin(1, 1));
|
||||||
} else {
|
} else {
|
||||||
this.addCardBackToContainer(container);
|
this.addCardBackToContainer(container);
|
||||||
|
|
@ -474,11 +607,13 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
if (this.pendingBet + amount > human.chips) return;
|
if (this.pendingBet + amount > human.chips) return;
|
||||||
this.pendingBet += amount;
|
this.pendingBet += amount;
|
||||||
this.updateBetDisplay();
|
this.updateBetDisplay();
|
||||||
|
this.hideBettingPrompts();
|
||||||
}
|
}
|
||||||
|
|
||||||
onClearBet() {
|
onClearBet() {
|
||||||
this.pendingBet = 0;
|
this.pendingBet = 0;
|
||||||
this.updateBetDisplay();
|
this.updateBetDisplay();
|
||||||
|
this.startBettingPromptsIfNoBet();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBetDisplay() {
|
updateBetDisplay() {
|
||||||
|
|
@ -492,6 +627,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
if (this.animating || this.pendingBet < 5) return;
|
if (this.animating || this.pendingBet < 5) return;
|
||||||
this.animating = true;
|
this.animating = true;
|
||||||
this.hideBettingUI();
|
this.hideBettingUI();
|
||||||
|
this.hideBettingPrompts();
|
||||||
|
|
||||||
// Commit human bet
|
// Commit human bet
|
||||||
this.gs = applyBet(this.gs, 0, this.pendingBet);
|
this.gs = applyBet(this.gs, 0, this.pendingBet);
|
||||||
|
|
@ -659,10 +795,10 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
const p = this.gs.players[seat];
|
const p = this.gs.players[seat];
|
||||||
if (!p?.active || !p.result) { onComplete(); return; }
|
if (!p?.active || !p.result) { onComplete(); return; }
|
||||||
|
|
||||||
const result = p.result;
|
const result = p.result;
|
||||||
const pos = SEAT_POS[seat];
|
const pos = SEAT_POS[seat];
|
||||||
const isWin = result === 'win' || result === 'blackjack';
|
const isWin = result === 'win' || result === 'blackjack';
|
||||||
const isLose = result === 'lose' || result === 'bust';
|
const isLose = result === 'lose' || result === 'bust';
|
||||||
|
|
||||||
if (seat > 0 && this.portraits[seat]) {
|
if (seat > 0 && this.portraits[seat]) {
|
||||||
this.portraits[seat].playEmotion?.(isWin ? 'happy' : 'upset');
|
this.portraits[seat].playEmotion?.(isWin ? 'happy' : 'upset');
|
||||||
|
|
@ -670,7 +806,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
|
|
||||||
const LABELS = { win: 'Win!', blackjack: 'Blackjack!', push: 'Push', lose: 'Lose', bust: 'Bust' };
|
const LABELS = { win: 'Win!', blackjack: 'Blackjack!', push: 'Push', lose: 'Lose', bust: 'Bust' };
|
||||||
const COLORS = { win: '#f5d020', blackjack: '#ffe066', push: '#9aa5b4', lose: '#e05c5c', bust: '#e05c5c' };
|
const COLORS = { win: '#f5d020', blackjack: '#ffe066', push: '#9aa5b4', lose: '#e05c5c', bust: '#e05c5c' };
|
||||||
const SIZES = { win: '54px', blackjack: '58px', push: '34px', lose: '48px', bust: '48px' };
|
const SIZES = { win: '54px', blackjack: '58px', push: '34px', lose: '48px', bust: '48px' };
|
||||||
const linger = isWin ? 1500 : isLose ? 1100 : 700;
|
const linger = isWin ? 1500 : isLose ? 1100 : 700;
|
||||||
|
|
||||||
const textY = pos.y - CARD_H / 2 - 60;
|
const textY = pos.y - CARD_H / 2 - 60;
|
||||||
|
|
@ -717,7 +853,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i = 0; i < 4; i++) {
|
||||||
const chip = this.add.graphics().setDepth(D.chips + 5);
|
const chip = this.add.graphics().setDepth(D.chips + 5);
|
||||||
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
||||||
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
||||||
chip.x = betX + (Math.random() - 0.5) * 22;
|
chip.x = betX + (Math.random() - 0.5) * 22;
|
||||||
chip.y = betY;
|
chip.y = betY;
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
|
|
@ -730,12 +866,12 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
|
|
||||||
animateChipsFromDealer(seat, amount) {
|
animateChipsFromDealer(seat, amount) {
|
||||||
if (!amount || amount <= 0) return;
|
if (!amount || amount <= 0) return;
|
||||||
const pos = SEAT_POS[seat];
|
const pos = SEAT_POS[seat];
|
||||||
const count = Math.min(Math.ceil(amount / 25), 7);
|
const count = Math.min(Math.ceil(amount / 25), 7);
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const chip = this.add.graphics().setDepth(D.chips + 5);
|
const chip = this.add.graphics().setDepth(D.chips + 5);
|
||||||
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
||||||
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
||||||
chip.x = DEALER_X + (Math.random() - 0.5) * 50;
|
chip.x = DEALER_X + (Math.random() - 0.5) * 50;
|
||||||
chip.y = DEALER_Y;
|
chip.y = DEALER_Y;
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
|
|
@ -754,7 +890,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
const chip = this.add.graphics().setDepth(D.chips + 5);
|
const chip = this.add.graphics().setDepth(D.chips + 5);
|
||||||
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
chip.fillStyle(CHIP_COLORS[25], 1); chip.fillCircle(0, 0, 14);
|
||||||
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
chip.lineStyle(2, 0xffffff, 0.3); chip.strokeCircle(0, 0, 14);
|
||||||
chip.x = betX + (Math.random() - 0.5) * 20;
|
chip.x = betX + (Math.random() - 0.5) * 20;
|
||||||
chip.y = betY;
|
chip.y = betY;
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
|
|
@ -776,9 +912,9 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
const by = cy - 10 + (Math.random() - 0.5) * 80;
|
const by = cy - 10 + (Math.random() - 0.5) * 80;
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
const angle = (i / 10) * Math.PI * 2 + Math.random() * 0.3;
|
const angle = (i / 10) * Math.PI * 2 + Math.random() * 0.3;
|
||||||
const dist = 65 + Math.random() * 65;
|
const dist = 65 + Math.random() * 65;
|
||||||
const color = palette[Math.floor(Math.random() * palette.length)];
|
const color = palette[Math.floor(Math.random() * palette.length)];
|
||||||
const dot = this.add.graphics().setDepth(D.modal + 5);
|
const dot = this.add.graphics().setDepth(D.modal + 5);
|
||||||
dot.fillStyle(color, 1);
|
dot.fillStyle(color, 1);
|
||||||
dot.fillCircle(0, 0, 4 + Math.random() * 3);
|
dot.fillCircle(0, 0, 4 + Math.random() * 3);
|
||||||
dot.x = bx; dot.y = by;
|
dot.x = bx; dot.y = by;
|
||||||
|
|
@ -891,8 +1027,8 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
const by = GAME_HEIGHT - 80;
|
const by = GAME_HEIGHT - 80;
|
||||||
|
|
||||||
const btns = [
|
const btns = [
|
||||||
new Button(this, CX - 180, by, 'Hit', () => this.onHit(), { width: 120, height: 52, fontSize: 20 }),
|
new Button(this, CX - 180, by, 'Hit', () => this.onHit(), { width: 120, height: 52, fontSize: 20 }),
|
||||||
new Button(this, CX - 50, by, 'Stand', () => this.onStand(), { width: 120, height: 52, fontSize: 20 }),
|
new Button(this, CX - 50, by, 'Stand', () => this.onStand(), { width: 120, height: 52, fontSize: 20 }),
|
||||||
];
|
];
|
||||||
if (canDouble(p)) {
|
if (canDouble(p)) {
|
||||||
btns.push(new Button(this, CX + 80, by, 'Double', () => this.onDouble(), { width: 130, height: 52, fontSize: 20 }));
|
btns.push(new Button(this, CX + 80, by, 'Double', () => this.onDouble(), { width: 130, height: 52, fontSize: 20 }));
|
||||||
|
|
@ -900,6 +1036,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
if (canSplit(p) && p.chips >= p.bet) {
|
if (canSplit(p) && p.chips >= p.bet) {
|
||||||
btns.push(new Button(this, CX + 220, by, 'Split', () => this.onSplit(), { width: 120, height: 52, fontSize: 20 }));
|
btns.push(new Button(this, CX + 220, by, 'Split', () => this.onSplit(), { width: 120, height: 52, fontSize: 20 }));
|
||||||
}
|
}
|
||||||
|
btns.forEach(btn => btn.setDepth(D.ui + 5));
|
||||||
this.actionBtns = btns;
|
this.actionBtns = btns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1129,7 +1266,7 @@ export default class BlackjackGame extends Phaser.Scene {
|
||||||
const sorted = [...active].sort((a, b) => SEAT_POS[b.seat].x - SEAT_POS[a.seat].x);
|
const sorted = [...active].sort((a, b) => SEAT_POS[b.seat].x - SEAT_POS[a.seat].x);
|
||||||
|
|
||||||
let pending = sorted.length;
|
let pending = sorted.length;
|
||||||
const done = () => { if (--pending <= 0) onComplete(); };
|
const done = () => { if (--pending <= 0) onComplete(); };
|
||||||
|
|
||||||
sorted.forEach((p, i) => {
|
sorted.forEach((p, i) => {
|
||||||
this.time.delayedCall(i * 480, () => this.animateSeatResult(p.seat, done));
|
this.time.delayedCall(i * 480, () => this.animateSeatResult(p.seat, done));
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,9 @@ export class Button extends Phaser.GameObjects.Container {
|
||||||
this.add([this.bgRect, this.text]);
|
this.add([this.bgRect, this.text]);
|
||||||
|
|
||||||
this.setSize(width, height);
|
this.setSize(width, height);
|
||||||
this.setInteractive({ useHandCursor: true });
|
this.setInteractive({ useHandCursor: true, hitArea: new Phaser.Geom.Rectangle(0, 0, width, height), hitAreaCallback: Phaser.Geom.Rectangle.Contains });
|
||||||
|
this.bgRect.setInteractive({ hitArea: new Phaser.Geom.Rectangle(0, 0, width, height), hitAreaCallback: Phaser.Geom.Rectangle.Contains });
|
||||||
|
this.text.setInteractive({ hitArea: new Phaser.Geom.Rectangle(0, 0, width, height), hitAreaCallback: Phaser.Geom.Rectangle.Contains });
|
||||||
this.on('pointerover', () => this.bgRect.setFillStyle(bgHover, 1));
|
this.on('pointerover', () => this.bgRect.setFillStyle(bgHover, 1));
|
||||||
this.on('pointerout', () => this.bgRect.setFillStyle(bg, variant === 'ghost' ? 0 : 1));
|
this.on('pointerout', () => this.bgRect.setFillStyle(bg, variant === 'ghost' ? 0 : 1));
|
||||||
this.on('pointerdown', () => this.bgRect.setScale(0.97));
|
this.on('pointerdown', () => this.bgRect.setScale(0.97));
|
||||||
|
|
@ -36,6 +38,20 @@ export class Button extends Phaser.GameObjects.Container {
|
||||||
this.on('pointerupoutside', () => this.bgRect.setScale(1));
|
this.on('pointerupoutside', () => this.bgRect.setScale(1));
|
||||||
if (onClick) this.on('pointerup', onClick);
|
if (onClick) this.on('pointerup', onClick);
|
||||||
|
|
||||||
|
this.bgRect.on('pointerover', () => this.bgRect.setFillStyle(bgHover, 1));
|
||||||
|
this.bgRect.on('pointerout', () => this.bgRect.setFillStyle(bg, variant === 'ghost' ? 0 : 1));
|
||||||
|
this.bgRect.on('pointerdown', () => this.bgRect.setScale(0.97));
|
||||||
|
this.bgRect.on('pointerup', () => this.bgRect.setScale(1));
|
||||||
|
this.bgRect.on('pointerupoutside', () => this.bgRect.setScale(1));
|
||||||
|
if (onClick) this.bgRect.on('pointerup', onClick);
|
||||||
|
|
||||||
|
this.text.on('pointerover', () => this.bgRect.setFillStyle(bgHover, 1));
|
||||||
|
this.text.on('pointerout', () => this.bgRect.setFillStyle(bg, variant === 'ghost' ? 0 : 1));
|
||||||
|
this.text.on('pointerdown', () => this.bgRect.setScale(0.97));
|
||||||
|
this.text.on('pointerup', () => this.bgRect.setScale(1));
|
||||||
|
this.text.on('pointerupoutside', () => this.bgRect.setScale(1));
|
||||||
|
if (onClick) this.text.on('pointerup', onClick);
|
||||||
|
|
||||||
scene.add.existing(this);
|
scene.add.existing(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue