diff --git a/client/src/game/scenes/GameScene.js b/client/src/game/scenes/GameScene.js index 9909669..9f5ff3b 100644 --- a/client/src/game/scenes/GameScene.js +++ b/client/src/game/scenes/GameScene.js @@ -111,18 +111,75 @@ export class GameScene extends Phaser.Scene { _buildPlayButton() { const { width, height } = this.scale + const btnY = height - 28 - this.playBtn = this.add.text(width / 2, height - 18, '[ JOUER LA CARTE ]', { - fontSize: '15px', + // Fond du bouton (rectangle arrondi via Graphics) + this.playBtnBg = this.add.graphics() + this._drawBtnBg(false) + + // Texte du bouton + this.playBtn = this.add.text(width / 2, btnY, '✔ CONFIRMER MA CARTE', { + fontSize: '17px', fontFamily: 'Georgia', + fontStyle: 'bold', color: '#1a0a00', - backgroundColor: '#d4a732', - padding: { x: 20, y: 8 } + padding: { x: 28, y: 10 } }) .setOrigin(0.5) - .setAlpha(0.35) + .setAlpha(0.3) + .setDepth(10) .setInteractive({ cursor: 'pointer' }) .on('pointerdown', this._playSelectedCard, this) + .on('pointerover', () => { if (this._canPlay && this.selectedCard) this.playBtn.setScale(1.05) }) + .on('pointerout', () => { this.playBtn.setScale(1) }) + + // Compteur de joueurs prêts (ex: "1 / 2 prêts") + this.readyText = this.add.text(width / 2, btnY + 22, '', { + fontSize: '12px', + fontFamily: 'Georgia', + color: '#a08060' + }).setOrigin(0.5).setDepth(10) + } + + _drawBtnBg(active) { + const { width, height } = this.scale + const btnY = height - 28 + const btnW = 280 + const btnH = 42 + this.playBtnBg.clear() + if (active) { + this.playBtnBg.fillStyle(0xd4a732, 1) + } else { + this.playBtnBg.fillStyle(0x4a3010, 0.5) + } + this.playBtnBg.fillRoundedRect(width / 2 - btnW / 2, btnY - btnH / 2, btnW, btnH, 8) + if (active) { + this.playBtnBg.lineStyle(2, 0xffd700) + this.playBtnBg.strokeRoundedRect(width / 2 - btnW / 2, btnY - btnH / 2, btnW, btnH, 8) + } + this.playBtnBg.setDepth(9) + } + + _activateBtn() { + this._drawBtnBg(true) + this.playBtn.setAlpha(1).setColor('#1a0a00') + // Animation pulse + if (this._pulseTween) this._pulseTween.stop() + this._pulseTween = this.tweens.add({ + targets: this.playBtn, + scaleX: 1.04, + scaleY: 1.04, + duration: 600, + yoyo: true, + repeat: -1, + ease: 'Sine.easeInOut' + }) + } + + _deactivateBtn() { + this._drawBtnBg(false) + this.playBtn.setAlpha(0.3).setColor('#a08060').setScale(1) + if (this._pulseTween) { this._pulseTween.stop(); this._pulseTween = null } } // ─── Main du joueur ────────────────────────────────────────────────────────── @@ -149,13 +206,14 @@ export class GameScene extends Phaser.Scene { } _onCardSelected(card) { + if (!this._canPlay) return // Désélectionner l'ancienne if (this.selectedCard && this.selectedCard !== card) { this.selectedCard.deselect() } this.selectedCard = card this.store.selectCard(card.cardData) - this.playBtn.setAlpha(1) + this._activateBtn() } _playSelectedCard() { @@ -163,6 +221,7 @@ export class GameScene extends Phaser.Scene { // Bloquer immédiatement pour éviter le double clic this._canPlay = false + this._deactivateBtn() this.socket.emit('play-card', { roomId: this.roomId, @@ -172,7 +231,6 @@ export class GameScene extends Phaser.Scene { this.selectedCard.setAlpha(0.4) this.selectedCard = null this.store.clearSelection() - this.playBtn.setAlpha(0.35) this.phaseText.setText('En attente des autres joueurs...') } @@ -279,22 +337,33 @@ export class GameScene extends Phaser.Scene { this._canPlay = true this.resolveObjects.forEach(o => o.destroy()) this.resolveObjects = [] - this.phaseText.setText('Sélectionnez une carte') + this.phaseText.setText('Choisissez une carte puis confirmez') + this.readyText.setText('') + this._deactivateBtn() this._buildHand(state.hand) } if (state.phase === 'waiting') { this._canPlay = false - this.phaseText.setText('En attente des autres joueurs...') + this._deactivateBtn() + this.phaseText.setText('Carte confirmée — en attente des autres...') } if (state.phase === 'resolve' || state.phase === 'end') { this._canPlay = false + this._deactivateBtn() + } + }) + + this.socket.on('players-ready', ({ ready, total }) => { + if (this.readyText) { + this.readyText.setText(`${ready} / ${total} joueurs prêts`) } }) this.socket.on('round-result', ({ playedCards, gains }) => { this.phaseText.setText('Résolution du tour...') + this.readyText.setText('') this._showPlayedCards(playedCards, gains) }) } diff --git a/server/src/index.js b/server/src/index.js index a62a7a5..7511543 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -69,6 +69,12 @@ io.on('connection', (socket) => { return } + // Broadcaster le compteur de joueurs prêts à tous + io.to(roomId).emit('players-ready', { + ready: room.pendingPlays.size, + total: room.playerCount + }) + // Envoyer à chaque joueur son état personnalisé : // - celui qui vient de jouer reçoit phase='waiting' // - les autres restent en phase='selecting'