1st attempt of roation
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
8c35899c38
commit
fa016047c2
@ -518,6 +518,13 @@ final class GameState {
|
||||
return bet.amount < minBet
|
||||
}
|
||||
|
||||
/// Which main bet is placed - nil if no main bet, true if Player, false if Banker.
|
||||
/// Used to determine card layout ordering (betted hand appears on bottom).
|
||||
var bettedOnPlayer: Bool? {
|
||||
guard let bet = mainBet else { return nil }
|
||||
return bet.type == .player
|
||||
}
|
||||
|
||||
/// Amount needed to reach the minimum bet.
|
||||
var amountNeededForMinimum: Int {
|
||||
guard let bet = mainBet else { return minBet }
|
||||
|
||||
@ -37,21 +37,11 @@ struct GameTableView: View {
|
||||
isLandscape ? Design.Spacing.medium : Design.Spacing.xSmall
|
||||
}
|
||||
|
||||
/// Minimum spacer height - smaller in landscape to fit content
|
||||
private var minSpacerHeight: CGFloat {
|
||||
isLandscape ? 0 : Design.Spacing.xSmall
|
||||
}
|
||||
|
||||
/// Smaller spacer height - reduced in landscape
|
||||
private var smallSpacerHeight: CGFloat {
|
||||
isLandscape ? Design.Spacing.xxSmall : Design.Spacing.small
|
||||
}
|
||||
|
||||
/// Medium spacer height - reduced in landscape
|
||||
private var mediumSpacerHeight: CGFloat {
|
||||
isLandscape ? Design.Spacing.xSmall : Design.Spacing.medium
|
||||
}
|
||||
|
||||
/// Maximum width for game content on large screens
|
||||
private var maxContentWidth: CGFloat {
|
||||
isLandscape ? CasinoDesign.Size.maxContentWidthLandscape : CasinoDesign.Size.maxContentWidthPortrait
|
||||
@ -73,6 +63,11 @@ struct GameTableView: View {
|
||||
state.lastResult == .tie
|
||||
}
|
||||
|
||||
/// Whether we're in a dealing/result phase (vertical layout) vs betting phase (horizontal)
|
||||
private var isDealing: Bool {
|
||||
state.currentPhase != .betting
|
||||
}
|
||||
|
||||
// Use global debug flag from Design constants
|
||||
private var showDebugBorders: Bool { Design.showDebugBorders }
|
||||
|
||||
@ -195,7 +190,9 @@ struct GameTableView: View {
|
||||
bankerIsWinner: bankerIsWinner,
|
||||
isTie: isTie,
|
||||
showAnimations: settings.showAnimations,
|
||||
dealingSpeed: settings.dealingSpeed
|
||||
dealingSpeed: settings.dealingSpeed,
|
||||
bettedOnPlayer: state.bettedOnPlayer,
|
||||
isDealing: isDealing
|
||||
)
|
||||
.frame(maxWidth: maxContentWidth)
|
||||
.padding(.horizontal, Design.Spacing.medium)
|
||||
@ -264,7 +261,7 @@ struct GameTableView: View {
|
||||
.safeAreaPadding(.bottom, Design.Spacing.small)
|
||||
}
|
||||
|
||||
/// Portrait layout with RoadMap inline
|
||||
/// Portrait layout - vertical card layout, no RoadMap (shown only in landscape)
|
||||
private var portraitLayout: some View {
|
||||
VStack(spacing: 0) {
|
||||
// Top bar with balance and info (from CasinoKit)
|
||||
@ -278,7 +275,7 @@ struct GameTableView: View {
|
||||
)
|
||||
.debugBorder(showDebugBorders, color: .cyan, label: "TopBar")
|
||||
|
||||
// Cards display area
|
||||
// Cards display area - animates from horizontal to vertical when dealing
|
||||
CardsDisplayArea(
|
||||
playerCards: state.visiblePlayerCards,
|
||||
bankerCards: state.visibleBankerCards,
|
||||
@ -290,25 +287,16 @@ struct GameTableView: View {
|
||||
bankerIsWinner: bankerIsWinner,
|
||||
isTie: isTie,
|
||||
showAnimations: settings.showAnimations,
|
||||
dealingSpeed: settings.dealingSpeed
|
||||
dealingSpeed: settings.dealingSpeed,
|
||||
bettedOnPlayer: state.bettedOnPlayer,
|
||||
isDealing: isDealing
|
||||
)
|
||||
.frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity)
|
||||
.padding(.horizontal, Design.Spacing.medium)
|
||||
.debugBorder(showDebugBorders, color: .red, label: "CardsArea")
|
||||
|
||||
Spacer(minLength: minSpacerHeight)
|
||||
.debugBorder(showDebugBorders, color: .yellow, label: "Spacer2")
|
||||
|
||||
// Road map history
|
||||
if settings.showHistory {
|
||||
RoadMapView(results: state.recentResults)
|
||||
.frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity)
|
||||
.padding(.horizontal, Design.Spacing.medium)
|
||||
.debugBorder(showDebugBorders, color: .orange, label: "RoadMap")
|
||||
}
|
||||
|
||||
Spacer(minLength: smallSpacerHeight)
|
||||
.debugBorder(showDebugBorders, color: .yellow, label: "Spacer3")
|
||||
.debugBorder(showDebugBorders, color: .yellow, label: "Spacer2")
|
||||
|
||||
// Betting table
|
||||
BettingTableView(
|
||||
|
||||
@ -3,12 +3,16 @@
|
||||
// Baccarat
|
||||
//
|
||||
// The cards display area showing both Player and Banker hands.
|
||||
// Defaults to side-by-side during betting, animates to vertical during dealing
|
||||
// with the betted hand on bottom.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import CasinoKit
|
||||
|
||||
/// The cards display area showing both hands.
|
||||
/// - Betting phase: Horizontal side-by-side layout (Player | Banker)
|
||||
/// - Dealing/Result phases: Vertical layout with betted hand on bottom
|
||||
struct CardsDisplayArea: View {
|
||||
let playerCards: [Card]
|
||||
let bankerCards: [Card]
|
||||
@ -21,6 +25,11 @@ struct CardsDisplayArea: View {
|
||||
let isTie: Bool
|
||||
let showAnimations: Bool
|
||||
let dealingSpeed: Double
|
||||
/// Which main bet is placed - nil if no main bet, true if Player, false if Banker.
|
||||
/// Determines layout ordering in vertical mode: betted hand appears on bottom.
|
||||
let bettedOnPlayer: Bool?
|
||||
/// Whether the game is in dealing/result phase (vertical layout) or betting phase (horizontal).
|
||||
let isDealing: Bool
|
||||
|
||||
// MARK: - State
|
||||
|
||||
@ -50,9 +59,22 @@ struct CardsDisplayArea: View {
|
||||
isLargeScreen ? 40 : Design.Size.labelRowHeight
|
||||
}
|
||||
|
||||
/// Spacing between PLAYER and BANKER hands - reduced on smaller screens
|
||||
/// Spacing between hands
|
||||
private var handsSpacing: CGFloat {
|
||||
isLargeScreen ? Design.Spacing.xxxLarge : Design.Spacing.large
|
||||
if isDealing {
|
||||
return isLargeScreen ? Design.Spacing.large : Design.Spacing.medium
|
||||
} else {
|
||||
return isLargeScreen ? Design.Spacing.xxxLarge : Design.Spacing.large
|
||||
}
|
||||
}
|
||||
|
||||
/// Card section width - larger in vertical mode (more horizontal space)
|
||||
private var handSectionWidth: CGFloat {
|
||||
if isDealing {
|
||||
return containerWidth * 0.7
|
||||
} else {
|
||||
return (containerWidth - handsSpacing) / 2
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Accessibility
|
||||
@ -89,22 +111,50 @@ struct CardsDisplayArea: View {
|
||||
return visibleCards.joined(separator: ", ") + ". " + String(format: format, bankerValue)
|
||||
}
|
||||
|
||||
/// Calculate hand section width from total container width
|
||||
private var handSectionWidth: CGFloat {
|
||||
(containerWidth - handsSpacing) / 2
|
||||
/// Whether Player hand should be on bottom (true) or top (false) in vertical mode.
|
||||
/// Defaults to Player on bottom if no bet placed.
|
||||
private var playerOnBottom: Bool {
|
||||
bettedOnPlayer ?? true
|
||||
}
|
||||
|
||||
/// The layout to use - HStack for horizontal, VStack for vertical
|
||||
private var layout: AnyLayout {
|
||||
isDealing ? AnyLayout(VStackLayout(spacing: handsSpacing)) : AnyLayout(HStackLayout(spacing: handsSpacing))
|
||||
}
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: handsSpacing) {
|
||||
// Player side
|
||||
layout {
|
||||
// First position: Player in horizontal, or top hand in vertical
|
||||
if isDealing && !playerOnBottom {
|
||||
// Vertical mode, player on top
|
||||
playerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .blue, label: "Player")
|
||||
|
||||
// Banker side
|
||||
} else if isDealing && playerOnBottom {
|
||||
// Vertical mode, banker on top
|
||||
bankerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .red, label: "Banker")
|
||||
} else {
|
||||
// Horizontal mode - player always on left
|
||||
playerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .blue, label: "Player")
|
||||
}
|
||||
|
||||
// Second position: Banker in horizontal, or bottom hand in vertical
|
||||
if isDealing && !playerOnBottom {
|
||||
// Vertical mode, banker on bottom
|
||||
bankerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .red, label: "Banker")
|
||||
} else if isDealing && playerOnBottom {
|
||||
// Vertical mode, player on bottom
|
||||
playerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .blue, label: "Player")
|
||||
} else {
|
||||
// Horizontal mode - banker always on right
|
||||
bankerHandSection(width: handSectionWidth)
|
||||
.debugBorder(showDebugBorders, color: .red, label: "Banker")
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, Design.Spacing.medium)
|
||||
@ -126,6 +176,8 @@ struct CardsDisplayArea: View {
|
||||
.accessibilityHidden(true)
|
||||
)
|
||||
.debugBorder(showDebugBorders, color: .mint, label: "HandsContainer")
|
||||
.animation(.spring(duration: 0.5, bounce: 0.2), value: isDealing)
|
||||
.animation(.spring(duration: 0.4, bounce: 0.15), value: playerOnBottom)
|
||||
}
|
||||
|
||||
// MARK: - Private Views
|
||||
@ -193,7 +245,7 @@ struct CardsDisplayArea: View {
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
#Preview("Empty Hands") {
|
||||
#Preview("Horizontal - Betting Phase") {
|
||||
ZStack {
|
||||
TableBackgroundView()
|
||||
CardsDisplayArea(
|
||||
@ -207,12 +259,14 @@ struct CardsDisplayArea: View {
|
||||
bankerIsWinner: false,
|
||||
isTie: false,
|
||||
showAnimations: true,
|
||||
dealingSpeed: 1.0
|
||||
dealingSpeed: 1.0,
|
||||
bettedOnPlayer: nil,
|
||||
isDealing: false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview("Player Wins") {
|
||||
#Preview("Vertical - Dealing (Bet on Player)") {
|
||||
ZStack {
|
||||
TableBackgroundView()
|
||||
CardsDisplayArea(
|
||||
@ -232,12 +286,14 @@ struct CardsDisplayArea: View {
|
||||
bankerIsWinner: false,
|
||||
isTie: false,
|
||||
showAnimations: true,
|
||||
dealingSpeed: 1.0
|
||||
dealingSpeed: 1.0,
|
||||
bettedOnPlayer: true,
|
||||
isDealing: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview("Banker Wins with 3 Cards") {
|
||||
#Preview("Vertical - Dealing (Bet on Banker)") {
|
||||
ZStack {
|
||||
TableBackgroundView()
|
||||
CardsDisplayArea(
|
||||
@ -254,13 +310,14 @@ struct CardsDisplayArea: View {
|
||||
playerCardsFaceUp: [true, true, true],
|
||||
bankerCardsFaceUp: [true, true, true],
|
||||
playerValue: 9,
|
||||
bankerValue: 8,
|
||||
bankerValue: 9,
|
||||
playerIsWinner: false,
|
||||
bankerIsWinner: true,
|
||||
isTie: false,
|
||||
showAnimations: true,
|
||||
dealingSpeed: 1.0
|
||||
dealingSpeed: 1.0,
|
||||
bettedOnPlayer: false,
|
||||
isDealing: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ enum Design {
|
||||
// MARK: - Debug
|
||||
|
||||
/// Set to true to show layout debug borders on views
|
||||
static let showDebugBorders = true
|
||||
static let showDebugBorders = false
|
||||
|
||||
/// Set to true to show debug log statements
|
||||
static let showDebugLogs = false
|
||||
|
||||
Loading…
Reference in New Issue
Block a user