diff --git a/public/src/games/monopoly/MonopolyGame.js b/public/src/games/monopoly/MonopolyGame.js index 5089823..f619250 100644 --- a/public/src/games/monopoly/MonopolyGame.js +++ b/public/src/games/monopoly/MonopolyGame.js @@ -708,21 +708,56 @@ export default class MonopolyGame extends Phaser.Scene { if (!isHumanTurn && !auctionIsHuman) return; if (inAuction) return; // auction panel handles its own buttons - const btnY0 = this.diceY + 56; const btnW = RP_W - 20; - let yOff = 0; + const BTN_H = 52; + const BTN_GAP = 10; // spacing between buttons (62 = BTN_H + BTN_GAP) + + // First pass: count buttons to determine starting Y + const p = gs.players[this.humanSeat]; + const phase = gs.phase; + let btnCount = 0; + + if (phase === 'preroll' || phase === 'endturn') { + if (phase === 'preroll') { + if (p.jailed) { + if (p.getOutOfJailFree > 0) btnCount++; + btnCount++; + btnCount++; + } else { + btnCount++; + } + } + if (phase === 'endturn') btnCount++; + if (PURCHASABLE.some(idx => + canBuildHouse(gs, this.humanSeat, idx) || canBuildHotel(gs, this.humanSeat, idx))) { + btnCount++; + } + if (PURCHASABLE.some(idx => { + const own = gs.board[idx]; + return own?.owner === this.humanSeat && !own.mortgaged && own.houses === 0 && !own.hotel; + }) || PURCHASABLE.some(idx => { + const own = gs.board[idx]; + return own?.owner === this.humanSeat && own.mortgaged && + p.cash >= Math.ceil(SPACES[idx].mortgage * 1.1); + })) { + btnCount++; + } + } + + // Second pass: draw buttons aligned to board bottom (BT + BS) + const boardBottom = BT + BS; + const totalBtnH = btnCount * BTN_H + (btnCount - 1) * BTN_GAP; + const btnY0 = boardBottom - totalBtnH; + let yOff = 0; const mkBtn = (label, cb, enabled=true, opts={}) => { const btn = new Button(this, RP_X + btnW/2 + 10, btnY0 + yOff, label, cb, - { width: btnW, height: 52, fontSize: 22, ...opts }); + { width: btnW, height: BTN_H, fontSize: 22, ...opts }); btn.setDepth(DEPTH.ui); if (!enabled) btn.setEnabled(false); this.reg(btn); - yOff += 62; + yOff += BTN_H + BTN_GAP; }; - const p = gs.players[this.humanSeat]; - const phase = gs.phase; - if (phase === 'preroll' || phase === 'endturn') { if (phase === 'preroll') { if (p.jailed) { @@ -810,6 +845,8 @@ export default class MonopolyGame extends Phaser.Scene { await this.delay(250); + playSound(this, SFX.MONOPAY); + // Phase 3: Amount arches to receiver's panel (1200 ms), turns green, adds plus amtTxt.setText(`+$${amount.toLocaleString()}`); amtTxt.setColor('#44FF88'); @@ -1478,8 +1515,8 @@ export default class MonopolyGame extends Phaser.Scene { async executeRoll(seat) { const d1 = Math.floor(Math.random() * 6) + 1; const d2 = Math.floor(Math.random() * 6) + 1; + playSound(this, SFX.DICE_ROLL); await this.animateDice(d1, d2); - playSound(this, SFX.diceRoll); const prevPos = this.gs.players[seat].position; const wasJailed = this.gs.players[seat].jailed; this.gs = rollDice(this.gs, seat, d1, d2); @@ -1572,7 +1609,10 @@ export default class MonopolyGame extends Phaser.Scene { pawn.x = inv * inv * start.x + 2 * inv * t * ctrl.x + t * t * ex; pawn.y = inv * inv * start.y + 2 * inv * t * ctrl.y + t * t * ey; }, - onComplete: hopOne, + onComplete: () => { + playSound(this, SFX.PIECE_CLICK); + hopOne(); + }, }); }; diff --git a/public/src/scenes/PreloadScene.js b/public/src/scenes/PreloadScene.js index d0c8338..37211a8 100644 --- a/public/src/scenes/PreloadScene.js +++ b/public/src/scenes/PreloadScene.js @@ -138,6 +138,7 @@ export default class PreloadScene extends Phaser.Scene { this.load.spritesheet('monopoly-cards', '/assets/images/monopoly-cards.png', { frameWidth: 200, frameHeight: 300 }); this.load.audio('sfx-monopoly-purchase', '/assets/fx/monopoly-purchase.mp3'); this.load.audio('sfx-monopoly-expense', '/assets/fx/monopoly-expense.mp3'); + this.load.audio('sfx-monopoly-pay', '/assets/fx/monopoly-pay.mp3'); this.load.audio('sfx-monopoly-paid', '/assets/fx/monopoly-paid.mp3'); } diff --git a/public/src/ui/Sounds.js b/public/src/ui/Sounds.js index c172b95..194a80b 100644 --- a/public/src/ui/Sounds.js +++ b/public/src/ui/Sounds.js @@ -34,6 +34,7 @@ export const SFX = { SCIFI_WOOSH: 'sfx-scifi-woosh', MONOPOLY_PURCHASE: 'sfx-monopoly-purchase', MONOPOLY_EXPENSE: 'sfx-monopoly-expense', + MONOPAY: 'sfx-monopoly-pay', MONOPOLY_PAID: 'sfx-monopoly-paid', };