UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Day 34 Challenge - Animating Guess the Flag

Forums > 100 Days of SwiftUI

1 and #2 - rotation and opacity challenges - have been tackled. They tackled me more than I tackled them though!

This is my code below - it needs refactoring for sure, because my view modifier has several returns. (Bad Form, I'm guessing!) I'm thinking that I need to figure out a closure to get the combination of degrees and opaciaty and if the user guessed right - and use that closure in the struct, so I can end up with just one return statement.

Here's my bigger issue at the moment though - IF the user chooses the correct flag, that flag spins. As it's supposed to.

But, when the new flags load up for the next quetion - whatever NEW flag that is in that flat ALSO spins. But the debugging print statements I have in there prove (to me) that it shouldn't' be spinning - because the degrees ARE set to 0, and each axis is also set to 0.

Hmm I deleted my code because not all of it copied correctly. I tried surrounding it with backticks - what is the best way to insert code here?

Thanks!

3      

where is your code?????? I don't know how to achieve the challenge two----fade out 20% opcity. So I want your code,but I don't find it.

3      

try this on while ask for next question may help

   DispatchQueue.main.asyncAfter(deadline: .now() + 6){
        askQuestion()
    }

3      

Howdy,

I don't know if you found a solution or not, however the exact same issue was happening for me.

This challenge portion (animation) took us approximately 36 to 45 hours to solve all by itself!

We watched all of the animaiton portions here on #100DaysofSwiftUI again Watched YouTube vidoes on animation Read articles on animation Checked our SwiftUI resource books on animation

Without seeing your code, I am guessig the issue might be the same as mine & if so this may solve the problem.

When you create your buttons I'm guessing you rused a loop of some sort and, as I. understand it, SwiftUI assigns a name to each of them. You then probably use 3dRotation to rotate the button/flag 360 degrees. At some point you then set the rotation to 0.

I did all of the above.

The issue is SwiftUI rotates the button BACK to zero degrees, because it is using the name of the button to identify it...yes, we think of it as a different button...however, SwiftUI identifies it by the name as the same button.

This is part of my code solution...


    @State private var buttonSpin = [0.0, 0.0, 0.0]
    @State private var buttonOpacity = [1.0, 1.0, 1.0]

    // other code in here

ForEach(0..<3) { number in
                        Button(action: {
                            flagTapped(number)
                        }) {
                            Image(countries[number])
                                .renderingMode(.original)
                                .flags()
                                .shadow(color: .black, radius: 5)
                                .rotation3DEffect(
                                    .degrees(buttonSpin[number]),
                                    axis: (x: 0, y: 1, z: 0))
                                .animation(.default)
                                .opacity(buttonOpacity[number])
                        }

4      

I remember having that problem when I was working on this project. I think the problem is that it is animating the rotationAmount going from 0...360, but then it is also animating the rotationAmount going from 360 back to zero. So, you need to make sure that you are only asking for animation during the time that the rotation amount is going from 0 to 360.

This is the way that I did it, although, I used the ternary operator ? which is kind of frowned upon I guess.

ForEach(0..<3) { number in
                    Button(action: {
                        withAnimation {
                            self.flagTapped(number)
                        }
                    }) {
                        FlagImage(flagImageFile: self.countries[number])
                    }
                    .rotation3DEffect(.degrees(number == self.correctAnswer ? self.rotationAmount : 0.0), axis: (x: 0, y: 1, z: 0))
                    .opacity(number != self.correctAnswer ? self.buttonOpacity : 1.0)
                }

This way, I am only asking for animation when the flagTapped funcion is called.

The flagTapped function is called when one of the flag buttons is pressed, and it sets the rotationAmount to 360 and the buttonOpacity to .25, so both of those things will be animated. But, by using the ternary operators, I have ensured that the rotation amount will only be applied to the correct answer, and the opacity will only be applied to the wrong answers.

func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scoreTitle = "Correct!"
            score += 1
            rotationAmount += 360
            buttonOpacity -= 0.75
        } else {
            scoreTitle = "Wrong! That is the flag of \(countries[number])"
            buttonOpacity = 0
        }
        showingScore = true
    }

Then I have a separate function askQuestion for setting up the next question after the alert showing whether the answer was correct or not is dismissed.

func askQuestion() {
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
        rotationAmount = 0
        buttonOpacity = 1
    }

The askQuestion function sets the rotationAmount back to zero, and the buttonOpacity back to 1, but I do not ask for animation when the askQuestion function is called, so it doesn't animate that part.

.alert(isPresented: $showingScore){
            Alert(title: Text(scoreTitle), message: Text("Your score is \(score)"), dismissButton: .default(Text("Continue")) {
                self.askQuestion()
            })
        }

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.