From 327d3d70198e4368bfc565aa7af8c2bc9f63e0b7 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Thu, 21 May 2026 00:04:21 -0600 Subject: [PATCH] feat: animate AI chip placement in Craps Adds a staggered slide-and-fade animation for AI bets in Craps, making chips appear to fly from each player's seat to the felt. Updates `renderAiBets` to accept an `animate` flag and triggers the effect only during the betting phase. Removes the call from `beginRound` to avoid redundant rendering. --- public/src/games/craps/CrapsGame.js | 32 +++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/public/src/games/craps/CrapsGame.js b/public/src/games/craps/CrapsGame.js index a500b41..e978f9b 100644 --- a/public/src/games/craps/CrapsGame.js +++ b/public/src/games/craps/CrapsGame.js @@ -523,7 +523,7 @@ export default class CrapsGame extends Phaser.Scene { return { x, y: z.center.y + jitter.dy }; } - renderAiBets() { + renderAiBets(animate = false) { for (const o of this.aiBetObjs) o.destroy(); this.aiBetObjs = []; @@ -546,27 +546,44 @@ export default class CrapsGame extends Phaser.Scene { const base = this.boxChipPos(number, slot); entries.forEach((e, idx) => { const dx = n > 1 ? (idx - (n - 1) / 2) * 22 : 0; + const finalX = base.x + dx; + const finalY = base.y; const label = `$${e.bet.amount}`; - const shortN = e.pi < this.gs.players.length + const shortN = this.gs.players[e.pi] ? (this.gs.players[e.pi].name.length > 6 ? this.gs.players[e.pi].name.slice(0, 5) + '…' : this.gs.players[e.pi].name) : ''; - this.aiBetObjs.push(this.drawAiChip(base.x + dx, base.y, e.pi, label, shortN)); + const chip = this.drawAiChip(finalX, finalY, e.pi, label, shortN); + if (animate) this.animateChipFromSeat(chip, e.pi, finalX, finalY, idx); + this.aiBetObjs.push(chip); }); } else { const z = this.zones[key]; if (!z) continue; entries.forEach((e, idx) => { - const { x, y } = this.chipSidePos(z, key, idx, n, e.pi); + const { x: finalX, y: finalY } = this.chipSidePos(z, key, idx, n, e.pi); const label = `$${e.bet.amount}`; - const shortN = e.pi < this.gs.players.length + const shortN = this.gs.players[e.pi] ? (this.gs.players[e.pi].name.length > 6 ? this.gs.players[e.pi].name.slice(0, 5) + '…' : this.gs.players[e.pi].name) : ''; - this.aiBetObjs.push(this.drawAiChip(x, y, e.pi, label, shortN)); + const chip = this.drawAiChip(finalX, finalY, e.pi, label, shortN); + if (animate) this.animateChipFromSeat(chip, e.pi, finalX, finalY, idx); + this.aiBetObjs.push(chip); }); } } } + animateChipFromSeat(chip, pi, finalX, finalY, betIdx) { + const delay = (pi - 1) * 90 + betIdx * 35; + chip.setPosition(SEAT_X[pi] ?? CX, SEAT_Y).setAlpha(0).setScale(0.4); + if (betIdx === 0) this.time.delayedCall(delay, () => playChipBet(this)); + this.tweens.add({ + targets: chip, x: finalX, y: finalY, + alpha: 1, scaleX: 1, scaleY: 1, + duration: 400, ease: 'Quad.Out', delay, + }); + } + updateBalances() { const human = this.gs.players[0]; this.balanceText.setText(`Balance $${human.chips.toLocaleString()}`); @@ -641,7 +658,6 @@ export default class CrapsGame extends Phaser.Scene { : `Come-out roll — ${this.gs.players[this.gs.shooterIndex].name} is shooting. Place your bets.`); this.renderHumanBets(); this.renderAiWagers(); - this.renderAiBets(); this.updateBalances(); this.refreshControls(); } @@ -655,7 +671,7 @@ export default class CrapsGame extends Phaser.Scene { } } this.renderAiWagers(); - this.renderAiBets(); + this.renderAiBets(true); } onShoot() {