I am creating a simple card game (Set) in SwiftUI. I have a button that will deal X new cards when tapped. Currently, it makes all cards show up at once. I was wondering how I could make them come out one at a time.
Deal works by appending a new card to a Deck array in the model. ContentView displays each card in the grid.
func deal(_ numberOfCards: Int) {
withAnimation(Animation.easeInOut(duration: 1)) {
viewModel.deal()
}
for _ in 1..<numberOfCards {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) {
withAnimation(.easeInOut) {
viewModel.deal()
}
}
}
}
Post
Replies
Boosts
Views
Activity
Creating a simple card game (Set) and I have a function in the model that deals X cards onto the deck. Currently, when I click the deal card button they all show up at once so I added the timer so that they would appear one after another. This gives the error "Escaping closure captures mutating 'self' parameter" Any ideas on what I can fix?
mutating func deal(_ numberOfCards: Int) {
for i in 0..<numberOfCards {
Timer.scheduledTimer(withTimeInterval: 0.3 * Double(i), repeats: false) { _ in
if deck.count > 0 {
dealtCards.append(deck.removeFirst())
}
}
}
}
I am building a card game (Set) and when dealing the cards I am currently using withAnimation{} and .transition(.move(edge: .bottom)
to have the cards animate from the bottom edge of the screen when the user taps the deal button. I want to make it so that the cards 'fly out' of the button and was wondering how I find the location of the button.
Once I find the position of the button I intend to use .offset to have them 'fly' out. Is there a better way?
I know it is possible using geometry reader, but I have not found out how to do so.
Here is my current code
		struct SetGameView: View {
		
		 @ObservedObject var viewModel: SetViewModel = SetViewModel()
		 var location: (CGFloat, CGFloat) = (0.0, 0.0)	
		 var body: some View {
		 VStack {
		 HStack {
		 Label("Score: \(viewModel.score)", systemImage: "face.dashed").font(.title).padding(.leading)
		 Spacer()
		 }
		 Grid(viewModel.dealtCards) { card in
		 CardView(card: card)
		 .transition(.asymmetric(insertion: .move(edge: .bottom), removal: .move(edge: .leading)))
		 .padding()
		 .onTapGesture { withAnimation { viewModel.choose(card) } }
		 } .onAppear { withAnimation(.easeInOut) { deal(12) } }
		 Divider()
		 HStack {
		 CreateNewGameButton(viewModel: viewModel)
		 DealNewCardbutton(viewModel: viewModel, deal: deal)
		 }.padding(.horizontal).frame(maxHeight: 50)
		 }
		 }
		
		 struct DealNewCardbutton: View {
		
		 var viewModel: SetViewModel
		 let deal: (Int) -> Void
		
		 init(viewModel: SetViewModel, deal: @escaping (Int) -> Void) {
		 self.viewModel = viewModel
		 self.deal = deal
		 }
		
		 var body: some View {
		 GeometryReader { geo in
		 Button(action: {
		 deal(3)
		 }){
		 ZStack {
		 RoundedRectangle(cornerRadius: 10.0).foregroundColor(.blue)
		 Text("Deal Three Cards").foregroundColor(.white)
		 }
		 }.onAppear {
		 print(geo.frame(in: .global).midX, geo.frame(in: .global).midY)
		 }
		 }
		 }
		 }
Heres - https://www.icloud.com/iclouddrive/0rJS9eRGgicAcpumvfJiTjd7Q#RPReplay_Final1593385736 a video of how it currently works.
I want the cards to all 'fly out' from the deal button.
I am building a card game (Set) and when dealing the cards I am currently using withAnimation{} and .transition(.move(edge: .bottom)
to have the cards animate from the bottom edge of the screen when the user taps the deal button. I want to make it so that the cards 'fly out' of the button and was wondering how I find the location of the button.
Once I find the position of the button I intend to use .offset to have them 'fly' out. Is there a better way?
I know it is possible using geometry reader, but I have not found out how to do so.
Here is my current code:
struct SetGameView: View {
		
		@ObservedObject var viewModel: SetViewModel = SetViewModel()
		var location: (CGFloat, CGFloat) = (0.0, 0.0)	
		var body: some View {
				VStack {
						HStack {
								Label("Score: \(viewModel.score)", systemImage: "face.dashed").font(.title).padding(.leading)
								Spacer()
						}
						Grid(viewModel.dealtCards) { card in
								CardView(card: card)
										.transition(.asymmetric(insertion: .move(edge: .bottom), removal: .move(edge: .leading)))
										.padding()
										.onTapGesture { withAnimation { viewModel.choose(card) } }
						} .onAppear { withAnimation(.easeInOut) { deal(12) } }
						Divider()
						HStack {
								CreateNewGameButton(viewModel: viewModel)
								DealNewCardbutton(viewModel: viewModel, deal: deal)
						}.padding(.horizontal).frame(maxHeight: 50)
				}
		}
		
		struct DealNewCardbutton: View {
				
				var viewModel: SetViewModel
				let deal: (Int) -> Void
				
				init(viewModel: SetViewModel, deal: @escaping (Int) -> Void) {
						self.viewModel = viewModel
						self.deal = deal
				}
				
				var body: some View {
						GeometryReader { geo in
								Button(action: {
										deal(3)
								}){
										ZStack {
												RoundedRectangle(cornerRadius: 10.0).foregroundColor(.blue)
												Text("Deal Three Cards").foregroundColor(.white)
										}
								}.onAppear {
										print(geo.frame(in: .global).midX, geo.frame(in: .global).midY)
								}
						}
				}
		}
[Here](https://www.icloud.com/iclouddrive/0rJS9eRGgicAcpumvfJiTjd7Q#RPReplay_Final1593385736
https://www.icloud.com/iclouddrive/0rJS9eRGgicAcpumvfJiTjd7Q#RPReplay_Final1593385736) is a video depicting how the animation currently works.
I want the cards to all 'fly out' from the deal button.
Hi,
I was wondering if there was a way to run code with segments of Swift 5.3 code on Swift Playground on Mac or iPad.