diff --git a/Memorize.xcodeproj/project.pbxproj b/Memorize.xcodeproj/project.pbxproj index a342639..d5766fb 100644 --- a/Memorize.xcodeproj/project.pbxproj +++ b/Memorize.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 245099F52998EC71000CE9DA /* EmojiMemoryGame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245099F42998EC71000CE9DA /* EmojiMemoryGame.swift */; }; 24E748FC29993782009B5FE8 /* Constans.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E748FB29993781009B5FE8 /* Constans.swift */; }; 24E748FE299944F4009B5FE8 /* AspectVGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E748FD299944F4009B5FE8 /* AspectVGrid.swift */; }; + 24FE51AF299CED6F00798617 /* Pie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FE51AE299CED6F00798617 /* Pie.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -27,6 +28,7 @@ 245099F42998EC71000CE9DA /* EmojiMemoryGame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiMemoryGame.swift; sourceTree = ""; }; 24E748FB29993781009B5FE8 /* Constans.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constans.swift; sourceTree = ""; }; 24E748FD299944F4009B5FE8 /* AspectVGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AspectVGrid.swift; sourceTree = ""; }; + 24FE51AE299CED6F00798617 /* Pie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pie.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -61,6 +63,7 @@ children = ( 240EDC3E2998A3B900A46AC9 /* MemorizeApp.swift */, 240EDC402998A3B900A46AC9 /* EmojiMemoryGameView.swift */, + 24FE51AE299CED6F00798617 /* Pie.swift */, 24E748FD299944F4009B5FE8 /* AspectVGrid.swift */, 24E748FB29993781009B5FE8 /* Constans.swift */, 245099F22998EAD6000CE9DA /* MemoryGame.swift */, @@ -153,6 +156,7 @@ 240EDC412998A3B900A46AC9 /* EmojiMemoryGameView.swift in Sources */, 24E748FE299944F4009B5FE8 /* AspectVGrid.swift in Sources */, 24E748FC29993782009B5FE8 /* Constans.swift in Sources */, + 24FE51AF299CED6F00798617 /* Pie.swift in Sources */, 240EDC3F2998A3B900A46AC9 /* MemorizeApp.swift in Sources */, 245099F52998EC71000CE9DA /* EmojiMemoryGame.swift in Sources */, ); diff --git a/Memorize/AspectVGrid.swift b/Memorize/AspectVGrid.swift index e923210..5bafda7 100644 --- a/Memorize/AspectVGrid.swift +++ b/Memorize/AspectVGrid.swift @@ -11,14 +11,32 @@ struct AspectVGrid: View where ItemView: View, Item: Identifiabl var items: [Item] var aspectRatio: CGFloat var content: (Item) -> ItemView + + init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) { + self.items = items + self.aspectRatio = aspectRatio + self.content = content + } + var body: some View { - let width: CGFloat = 100 - LazyVGrid(columns: [GridItem(.adaptive(minimum: width))]) { - ForEach(items) { - item in content(item).aspectRatio(aspectRatio, contentMode: .fit) + GeometryReader { geometry in + VStack{ + let width: CGFloat = widthThatFits(itemCount: items.count, in: geometry.size, itemAspectRatio: aspectRatio) + LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) { + ForEach(items) { + item in content(item).aspectRatio(aspectRatio, contentMode: .fit) + } + } + Spacer(minLength: 0) } } } + + private func adaptiveGridItem(width: CGFloat) -> GridItem { + var gridItem = GridItem(.adaptive(minimum: width)) + gridItem.spacing = 0 + return gridItem + } private func widthThatFits(itemCount: Int, in size: CGSize, itemAspectRatio: CGFloat) -> CGFloat { var columCount = 1 diff --git a/Memorize/Constans.swift b/Memorize/Constans.swift index 6958ef9..594d84a 100644 --- a/Memorize/Constans.swift +++ b/Memorize/Constans.swift @@ -10,11 +10,14 @@ import SwiftUI struct const { enum DrawingConstants { - static let cornerRadius: CGFloat = 20 + static let cornerRadius: CGFloat = 10 static let lineWidth: CGFloat = 3 - static let fontScale: CGFloat = 0.8 + static let fontScale: CGFloat = 0.7 static let gridWidth: CGFloat = 80 static let gridAspectRatio: CGFloat = 2 / 3 static let matchedCardOpacity: Double = 0 + static let gridPadding: CGFloat = 4 + static let piePadding: CGFloat = 4 + static let pieOpacity: CGFloat = 0.5 } } diff --git a/Memorize/EmojiMemoryGameView.swift b/Memorize/EmojiMemoryGameView.swift index 485f73d..a97410c 100644 --- a/Memorize/EmojiMemoryGameView.swift +++ b/Memorize/EmojiMemoryGameView.swift @@ -9,31 +9,28 @@ import SwiftUI struct EmojiMemoryGameView: View { @ObservedObject var game: EmojiMemoryGame + var body: some View { -// ScrollView { -// LazyVGrid(columns: [GridItem(.adaptive(minimum: const.DrawingConstants.gridWidth))]) { -// ForEach(game.cards) { -// card in CardView(card: card).aspectRatio(const.DrawingConstants.gridAspectRatio, contentMode: .fit) -// .onTapGesture { -// game.choose(card) -// } -// } -// } -// } -// .foregroundColor(/*@START_MENU_TOKEN@*/ .red/*@END_MENU_TOKEN@*/) -// .padding(.horizontal) - AspectVGrid(items: game.cards, aspectRatio: const.DrawingConstants.gridAspectRatio, content: { - card in CardView(card: card).aspectRatio(const.DrawingConstants.gridAspectRatio, contentMode: .fit) - .onTapGesture { - game.choose(card) - } - }) + AspectVGrid(items: game.cards, aspectRatio: const.DrawingConstants.gridAspectRatio) { + card in + if card.isMatched && !card.isFaceUp { + Rectangle().opacity(0) + } else { + CardView(card: card) + .padding(const.DrawingConstants.gridPadding) + .onTapGesture { + game.choose(card) + } + } + } + .foregroundColor(.red) + .padding(.horizontal) } +} struct CardView: View { let card: EmojiMemoryGame.Card - var body: some View { GeometryReader { geometry in ZStack { @@ -41,6 +38,10 @@ struct CardView: View { if card.isFaceUp && !card.isMatched { shape.fill().foregroundColor(.white) shape.strokeBorder(lineWidth: const.DrawingConstants.lineWidth) + Pie(startAngle: Angle(degrees: 270), + endAngle: Angle(degrees: 380)) + .padding(const.DrawingConstants.piePadding) + .opacity(const.DrawingConstants.pieOpacity) Text(card.content).font(font(in: geometry.size)) } else if card.isMatched { shape.opacity(const.DrawingConstants.matchedCardOpacity) @@ -59,9 +60,10 @@ struct CardView: View { struct ContentView_Previews: PreviewProvider { static var previews: some View { let game = EmojiMemoryGame() - EmojiMemoryGameView(game: game) - .preferredColorScheme(.dark) - EmojiMemoryGameView(game: game) + game.choose(game.cards.first!) + return EmojiMemoryGameView(game: game) +// .preferredColorScheme(.dark) +// EmojiMemoryGameView(game: game) .preferredColorScheme(.light) } } diff --git a/Memorize/Pie.swift b/Memorize/Pie.swift new file mode 100644 index 0000000..2c8ef15 --- /dev/null +++ b/Memorize/Pie.swift @@ -0,0 +1,37 @@ +// +// Pie.swift +// Memorize +// +// Created by ching on 2023/2/15. +// + +import SwiftUI + +struct Pie: Shape { + var startAngle: Angle + var endAngle: Angle + var clockwise = false + + func path(in rect: CGRect) -> Path { + let center = CGPoint(x: rect.midX, y: rect.midY) + let radius = min(rect.height, rect.width) / 2 + let start = CGPoint( + x: center.x + radius * CGFloat(cos(startAngle.radians)), + y: center.y + radius * CGFloat(sin(startAngle.radians)) + ) + + var p = Path() + p.move(to: center) + p.addLine(to: start) + p.addArc( + center: center, + radius: radius, + startAngle: startAngle, + endAngle: endAngle, + clockwise: !clockwise + ) + p.addLine(to: center) + + return p + } +}