More host UI refinements, fun logo animations, etc.

This commit is contained in:
Aaron D. Lee 2026-01-26 17:03:30 -05:00
parent c72fe44cfa
commit 23657f6b0c
4 changed files with 78 additions and 20 deletions

View File

@ -840,6 +840,33 @@ class GolfGame {
const previousPlayerId = oldState.current_player_id; const previousPlayerId = oldState.current_player_id;
const wasOtherPlayer = previousPlayerId && previousPlayerId !== this.playerId; const wasOtherPlayer = previousPlayerId && previousPlayerId !== this.playerId;
// Detect which pile opponent drew from and pulse it
if (wasOtherPlayer && discardChanged) {
const oldPlayer = oldState.players.find(p => p.id === previousPlayerId);
const newPlayer = newState.players.find(p => p.id === previousPlayerId);
if (oldPlayer && newPlayer && oldDiscard) {
// Check if any of their cards now matches the old discard top
// This means they took from discard pile
let tookFromDiscard = false;
for (let i = 0; i < 6; i++) {
const newCard = newPlayer.cards[i];
if (newCard?.face_up &&
newCard.rank === oldDiscard.rank &&
newCard.suit === oldDiscard.suit) {
tookFromDiscard = true;
break;
}
}
// Pulse the appropriate pile
this.pulseDrawPile(tookFromDiscard ? 'discard' : 'deck');
} else {
// No old discard or couldn't detect - assume deck
this.pulseDrawPile('deck');
}
}
if (discardChanged && wasOtherPlayer) { if (discardChanged && wasOtherPlayer) {
// Check if the previous player actually SWAPPED (has a new face-up card) // Check if the previous player actually SWAPPED (has a new face-up card)
// vs just discarding the drawn card (no hand change) // vs just discarding the drawn card (no hand change)
@ -886,6 +913,17 @@ class GolfGame {
// The swap animation handles showing the card at the correct position // The swap animation handles showing the card at the correct position
} }
// Pulse animation on deck or discard pile to show where opponent drew from
pulseDrawPile(source) {
const pile = source === 'discard' ? this.discard : this.deck;
pile.classList.remove('draw-pulse');
// Trigger reflow to restart animation
void pile.offsetWidth;
pile.classList.add('draw-pulse');
// Remove class after animation completes
setTimeout(() => pile.classList.remove('draw-pulse'), 600);
}
// Fire animation for discard without swap (card goes deck -> discard) // Fire animation for discard without swap (card goes deck -> discard)
fireDiscardAnimation(discardCard) { fireDiscardAnimation(discardCard) {
const deckRect = this.deck.getBoundingClientRect(); const deckRect = this.deck.getBoundingClientRect();
@ -1546,14 +1584,10 @@ class GolfGame {
// Update player name in header (truncate if needed) // Update player name in header (truncate if needed)
const displayName = me.name.length > 12 ? me.name.substring(0, 11) + '…' : me.name; const displayName = me.name.length > 12 ? me.name.substring(0, 11) + '…' : me.name;
const checkmark = me.all_face_up ? ' ✓' : ''; const checkmark = me.all_face_up ? ' ✓' : '';
// Remove old crown if exists // Update player name span with crown if winner
const existingCrown = this.playerHeader.querySelector('.winner-crown'); const playerNameSpan = this.playerHeader.querySelector('.player-name');
if (existingCrown) existingCrown.remove(); const crownHtml = isRoundWinner ? '<span class="winner-crown">👑</span>' : '';
// Set content - crown goes at the start playerNameSpan.innerHTML = crownHtml + displayName + checkmark;
this.playerHeader.firstChild.textContent = displayName + checkmark;
if (isRoundWinner) {
this.playerHeader.insertAdjacentHTML('afterbegin', '<span class="winner-crown">👑</span>');
}
} }
// Update discard pile (skip if holding a drawn card) // Update discard pile (skip if holding a drawn card)

View File

@ -11,7 +11,7 @@
<!-- Lobby Screen --> <!-- Lobby Screen -->
<div id="lobby-screen" class="screen active"> <div id="lobby-screen" class="screen active">
<h1><span class="golfer-swing">🏌️</span><span class="kicked-ball"></span> <span class="golf-title">Golf</span></h1> <h1><span class="golfer-swing">🏌️</span><span class="kicked-ball"></span> <span class="golf-title">Golf</span></h1>
<p class="subtitle">6-Card Golf Card Game <button id="rules-btn" class="btn btn-link">Rules</button></p> <p class="subtitle">6-Card Golf Card Game <button id="rules-btn" class="btn btn-small btn-rules">Rules</button></p>
<div class="form-group"> <div class="form-group">
<label for="player-name">Your Name</label> <label for="player-name">Your Name</label>
@ -247,7 +247,7 @@
<div class="player-section"> <div class="player-section">
<div class="player-area"> <div class="player-area">
<h4 id="player-header">You<span id="your-score" class="player-showing">0</span></h4> <h4 id="player-header"><span class="player-name">You</span><span id="your-score" class="player-showing">0</span></h4>
<div id="player-cards" class="card-grid"></div> <div id="player-cards" class="card-grid"></div>
</div> </div>
</div> </div>

View File

@ -985,6 +985,24 @@ input::placeholder {
box-shadow: none; box-shadow: none;
} }
/* Pulse animation when opponent draws from a pile */
#deck.draw-pulse,
#discard.draw-pulse {
animation: draw-pulse 0.6s ease-out;
}
@keyframes draw-pulse {
0% {
box-shadow: 0 0 0 0 rgba(244, 164, 96, 0.8);
}
50% {
box-shadow: 0 0 0 12px rgba(244, 164, 96, 0.4);
}
100% {
box-shadow: 0 0 0 20px rgba(244, 164, 96, 0);
}
}
/* Card flip animation for discard pile */ /* Card flip animation for discard pile */
.card-flip-in { .card-flip-in {
animation: cardFlipIn 0.5s ease-out; animation: cardFlipIn 0.5s ease-out;
@ -2555,19 +2573,25 @@ input::placeholder {
color: rgba(255, 255, 255, 0.85); color: rgba(255, 255, 255, 0.85);
} }
/* Rules link button in lobby */ /* Rules button in lobby */
.btn-link { .btn-rules {
background: transparent; background: rgba(244, 164, 96, 0.2);
border: none; border: 1px solid #f4a460;
color: #f4a460; color: #ffb366;
text-decoration: underline;
cursor: pointer; cursor: pointer;
font-size: 0.95rem; font-size: 0.65rem;
margin-bottom: 15px; padding: 2px 8px;
margin-left: 8px;
vertical-align: middle;
border-radius: 3px;
font-weight: 600;
transition: background 0.2s, border-color 0.2s;
} }
.btn-link:hover { .btn-rules:hover {
color: #fbbf24; background: rgba(244, 164, 96, 0.35);
border-color: #ffb366;
color: #ffc880;
} }
/* Select option styling in advanced options */ /* Select option styling in advanced options */

Binary file not shown.