From 645602b2de8cb7cc5c77e975885ad06eac4d35f9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 26 Dec 2025 12:07:11 -0600 Subject: [PATCH] Signed-off-by: Matt Bruce --- Baccarat/Baccarat/Theme/DesignConstants.swift | 9 ++++ .../Baccarat/Views/Game/GameTableView.swift | 8 +++- .../Views/Table/CardsDisplayArea.swift | 22 +++++++--- .../Views/Table/CompactHandView.swift | 42 ++++++++++++++++--- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/Baccarat/Baccarat/Theme/DesignConstants.swift b/Baccarat/Baccarat/Theme/DesignConstants.swift index 7580337..853424a 100644 --- a/Baccarat/Baccarat/Theme/DesignConstants.swift +++ b/Baccarat/Baccarat/Theme/DesignConstants.swift @@ -50,6 +50,15 @@ enum Design { static let labelFontSize: CGFloat = 14 static let labelRowHeight: CGFloat = 30 } + + // MARK: - Card Deal Animation + + enum DealAnimation { + /// Horizontal offset for card deal (from upper-center, simulating dealer) + static let offsetX: CGFloat = 0 + /// Vertical offset for card deal (from above the table) + static let offsetY: CGFloat = -250 + } } // MARK: - Baccarat App Colors diff --git a/Baccarat/Baccarat/Views/Game/GameTableView.swift b/Baccarat/Baccarat/Views/Game/GameTableView.swift index f30ada8..3a7dab9 100644 --- a/Baccarat/Baccarat/Views/Game/GameTableView.swift +++ b/Baccarat/Baccarat/Views/Game/GameTableView.swift @@ -193,7 +193,9 @@ struct GameTableView: View { bankerValue: state.bankerHandValue, playerIsWinner: playerIsWinner, bankerIsWinner: bankerIsWinner, - isTie: isTie + isTie: isTie, + showAnimations: settings.showAnimations, + dealingSpeed: settings.dealingSpeed ) .frame(maxWidth: maxContentWidth) .padding(.horizontal, Design.Spacing.medium) @@ -274,7 +276,9 @@ struct GameTableView: View { bankerValue: state.bankerHandValue, playerIsWinner: playerIsWinner, bankerIsWinner: bankerIsWinner, - isTie: isTie + isTie: isTie, + showAnimations: settings.showAnimations, + dealingSpeed: settings.dealingSpeed ) .frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity) .padding(.horizontal, Design.Spacing.medium) diff --git a/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift b/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift index c340eef..67348b6 100644 --- a/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift +++ b/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift @@ -19,6 +19,8 @@ struct CardsDisplayArea: View { let playerIsWinner: Bool let bankerIsWinner: Bool let isTie: Bool + let showAnimations: Bool + let dealingSpeed: Double // MARK: - State @@ -147,7 +149,9 @@ struct CardsDisplayArea: View { cards: playerCards, cardsFaceUp: playerCardsFaceUp, isWinner: playerIsWinner, - containerWidth: width + containerWidth: width, + showAnimations: showAnimations, + dealingSpeed: dealingSpeed ) } .frame(width: width) @@ -175,7 +179,9 @@ struct CardsDisplayArea: View { cards: bankerCards, cardsFaceUp: bankerCardsFaceUp, isWinner: bankerIsWinner, - containerWidth: width + containerWidth: width, + showAnimations: showAnimations, + dealingSpeed: dealingSpeed ) } .frame(width: width) @@ -199,7 +205,9 @@ struct CardsDisplayArea: View { bankerValue: 0, playerIsWinner: false, bankerIsWinner: false, - isTie: false + isTie: false, + showAnimations: true, + dealingSpeed: 1.0 ) } } @@ -222,7 +230,9 @@ struct CardsDisplayArea: View { bankerValue: 2, playerIsWinner: true, bankerIsWinner: false, - isTie: false + isTie: false, + showAnimations: true, + dealingSpeed: 1.0 ) } } @@ -247,7 +257,9 @@ struct CardsDisplayArea: View { bankerValue: 8, playerIsWinner: false, bankerIsWinner: true, - isTie: false + isTie: false, + showAnimations: true, + dealingSpeed: 1.0 ) } } diff --git a/Baccarat/Baccarat/Views/Table/CompactHandView.swift b/Baccarat/Baccarat/Views/Table/CompactHandView.swift index 3282f45..cd36a95 100644 --- a/Baccarat/Baccarat/Views/Table/CompactHandView.swift +++ b/Baccarat/Baccarat/Views/Table/CompactHandView.swift @@ -15,11 +15,20 @@ struct CompactHandView: View { let isWinner: Bool /// Container width passed from parent for sizing let containerWidth: CGFloat + /// Whether to show dealing animations + let showAnimations: Bool + /// Speed multiplier for dealing animations + let dealingSpeed: Double // MARK: - Environment @Environment(\.horizontalSizeClass) private var horizontalSizeClass + /// Scaled animation duration based on dealing speed. + private var animationDuration: Double { + Design.Animation.springDuration * dealingSpeed + } + // MARK: - Constants /// Overlap ratio relative to card width (negative = overlap) @@ -90,10 +99,25 @@ struct CompactHandView: View { cardWidth: cardWidth ) .zIndex(Double(index)) + .transition( + showAnimations + ? .asymmetric( + insertion: .offset(x: Design.DealAnimation.offsetX, y: Design.DealAnimation.offsetY) + .combined(with: .opacity) + .combined(with: .scale(scale: Design.Scale.slightShrink)), + removal: .scale.combined(with: .opacity) + ) + : .identity + ) } } } - .animation(nil, value: cards.count) // Prevent size animation during dealing + .animation( + showAnimations + ? .spring(duration: animationDuration, bounce: Design.Animation.springBounce) + : .none, + value: cards.count + ) } private var winnerBorder: some View { @@ -130,7 +154,9 @@ struct CompactHandView: View { cards: [], cardsFaceUp: [], isWinner: false, - containerWidth: 160 + containerWidth: 160, + showAnimations: true, + dealingSpeed: 1.0 ) } } @@ -145,7 +171,9 @@ struct CompactHandView: View { ], cardsFaceUp: [true, true], isWinner: false, - containerWidth: 160 + containerWidth: 160, + showAnimations: true, + dealingSpeed: 1.0 ) } } @@ -161,7 +189,9 @@ struct CompactHandView: View { ], cardsFaceUp: [true, true, true], isWinner: true, - containerWidth: 160 + containerWidth: 160, + showAnimations: true, + dealingSpeed: 1.0 ) } } @@ -176,7 +206,9 @@ struct CompactHandView: View { ], cardsFaceUp: [false, false], isWinner: false, - containerWidth: 160 + containerWidth: 160, + showAnimations: true, + dealingSpeed: 1.0 ) } }