DEV_Larva

HACKING WITH SWIFT - Guess the Flag(2) 본문

SwiftUI & UIKit/Tutorials

HACKING WITH SWIFT - Guess the Flag(2)

NelchuPapa 2022. 9. 3. 15:53
반응형

이번 프로젝트의 경우 전과는 다르게 과제가 주어 지는데 말 그대로 일부만 참고할 문서가 있지만 이후부터는 혼자 search를 한다거나 복습 한 내용에서 심화하는 작업이 이뤄져야 앱이 정상적으로 구동되기 때문에 조금 시간이 오래 걸렸다. 

일단은 오늘도 계속해서 프로젝트를 진행 해보자.

 

 


가장 먼저 앱에 필요한 Assets을 먼저 챙기고 이후에 개발을 하였다. 이미지로는 총 12개국의 국기로 한번 준비해보았다. 이후 이 국기들을 랜덤으로 출력하여 사용자가 문제에서 출제된 나라의 올바른 국기를 고르는 간단한  미니게임이다. 여튼~ 계속해서 진행해보자. 

 

 

 

자 여기까지 다했다면 게임 데이터를 저장할 두가지 속성이 필요하다. 모든 국가 이미지의 배열과 어떤 국가 이미지가 올바른지를 저장하는 정수이다. 

 

@State private var countries = ["에스토니아","스페인", "프랑스", "독일","아일랜드", "이탈리아",
"나이지리아", "폴란드", "러시아", "스페인", "영국", "미국"].shuffled()
    
@State private var correctAnswer = Int.random(in: 0...2)

 

여기서 Int.random(in:)을 이용하여 자동으로 임의의 숫자를 선택하게 된다. 여기서 임의의로 정해진 숫자를 통해 어떤 국기를 탭 해야 하는지 결정할 수 있게 된 것이다.  그리고 마지막. shuffled()를 이용하여 자동으로 배열 순서를 무작위로 처리하게 된다. 

 

 

var body: some View {
    VStack {
        Text("Tap the flag of")
        Text(countries[correctAnswer])
    }
}

 

이제 바로 VStack을 이용하여 국기를 눌러라는 말과 함께 위에서 미리 선언 해둔 국가 배열 중 랜덤으로 나온 하나의 나라가 출력되게끔 하였다.

 

ForEach(0..<3) { number in
    Button {
       
    } label: {
        Image(countries[number])
            .renderingMode(.original)
    }
}

 

이제 VStack내부에 국기 이미지를 넣고 해당 이미지를 버튼과 합쳐 국기를 누를 수 있게끔 만들었다. 여기서는 총 3장의 국기가 출력된다.

여기서.renderingMode(. original)는 Swift에게 다시 원래 이미지 버튼으로 기억하지 않고 랜더링을 하게끔 만드는 수정자 역할이다. 

 

근데 이렇게 다하고 나면 아마 문제가 생기는데 하나의 뷰에 두 가지 뷰를 넣으니 당연히 단일 화면이 아닌 두 개의 화면으로 분리되어 출력되는데 여기서 해결 방법은 아래와 같다. 

//위 2개 코드 섞음

var body: some View {
    VStack(spacing: 30) {
        VStack {
            Text("Tap the flag of")
            // etc
        }

        ForEach(0..<3) { number in
            // etc
        }
    }
}

 

2개의 VStack과 spacing을 통해 간격 조정을 하게 되고 이후 VStack 내부에 현재 보다 많은 Text가 추가될 것이므로 안에도 Vstack을 추가적으로 배치한다. 이렇게 하면 한 화면에 우리가 원하던 모습으로 출력될 것이다. 지금까지의 결과물은 아래와 같다. 

 

아직까지는 이앱이 뭐하는 앱인지도 모르겠다..🤔🤔

 

이제 막 시작했는데 멋있는 앱을 기대하는 건 너무 빠르다.. 여하튼 계속해서 할 건데 이전 시간에 배워보았던 ZStack을 참고하여 이번에는 위 코드들을 ZStack으로 감싼 후에 심심해 보이는 배경 색상도 변경시켜 보자!

 

.ignoresSafeArea()를 이용하여 안전 영역을 무시한 상태로 모든 영역에 색을 입혀 보았고 이후 ZStack내부는 Gradients를 이용하여 배경의 퀄리티를 높여 볼 계획이었다.  

Text("Tap the flag of")
    .foregroundColor(.white)

Text(countries[correctAnswer])
    .foregroundColor(.white)

그리고 앞선 코드에서. foregroundColor를 이용하여 텍스트의 색상을 변경하여 배경색에 영향을 최소한으로 받게 바꿔보았다. 

 

 

 


Gradients.

 

여기서 background 색상이 맘에 들지 않아서 Gradients를 이용하여 다시 디자인해보기로 했다. 

이전 시간에 간단하게 실습해보았던 Gradient 중 원뿔형, 각도 그라디언트라고 알려진 AngularGradient을 이용해보았다. 

 RoundedRectangle(cornerRadius: 20)
         .fill(AngularGradient(gradient: Gradient(colors: [Color.purple, Color.yellow]),
         center: .topLeading,angle: .degrees(180 + 45)))

AngularGradient를 만들 때는 전체 각도를 사용하거나 부분 회전 각도로 만들 수 있게 된다. 자세한 내용은 Apple의 공식문서를 통해 확인해보자!

 

 

https://developer.apple.com/documentation/swiftui/angulargradient

 

Apple Developer Documentation

 

developer.apple.com

이제 위 코드에 대한 결과를 확인해보면???

degree를 조정하거나 색 조합을 달리하여 자신이 원하는 색상을 만들어 볼 수도있다.

 

 


 

Alert.

앞서 미니게임의 전체적인 UI를 코딩했다면 이제 게임이 작동되게끔 해야 한다. 아직은 국기를 누르거나 하더라도 아무 일이 일어나지 않고 말 그대로 껍데기만 있는 상태이다. 여기서 경고 표시를 통해 국기를 눌렀을 때 진행 상황이 어떻게 흘러가고 있는지 사용자에게 알려주는 alert를 만들어 보자!

 

@State private var showingScore = false
@State private var scoreTitle = ""

해당 부분들은 경고 표시 여부를 저장하는 부분과 경고 안에 표시될 내용을 저장한다. 

 

그래서 이 두 가지를 통해 탭이 된 버튼의 수를 받아들이고 정답과 비교하고, 사용자에게 의미 있는 경고를 표시할 수 있도록 설정한 것이다. 

 

이제 바로 아래 코드를 body속성 뒤에 추가한다. 

이미 number는 ForEach를 통해 앞에서 받아 왔기 때문에 flagTapper()에 전달만 하면 된다. 

그래서 그 해당 결과를 보면 만약 사용자가 고른 것이 정답이라면 경고창 내부 내용을 저장하는 scoreTitle은 Correct라는 텍스트를 출력하게 된다. 만약 다르다면 당연히 Wrong을 출력할 것이다. 

 

func flagTapped(_ number: Int) {
    if number == correctAnswer {
        scoreTitle = "Correct"
    } else {
        scoreTitle = "Wrong"
    }

    showingScore = true
}

 

경고가 이제 정상적으로 출력된다면 경고가 해제될 떼 어떤 일이 발생하는지에 대해서도 생각을 해야 한다. 예를 들면 한판 하자마자 게임이 끝나버린다거나, 경고가 출력된 이후 아무 일이 일어나지 않는 다면 게임은 의미가 없어진다. 

 

따라서 askQuestion()이라는 메서드를 통해 국가를 섞고 새로운 정답을 선택하여 게임을 재설정하는 방법을 설정해볼 것이다.

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

근데 아마 이렇게 하면 분명히 오류가 날것이다. 왜냐?? @State로 표시되지 않은 뷰의 속성을 변경하려고 했기 때문이다.

따라서 countries와 correctAnswer를 선언하였던 처음 위치로 가서 @State private var 형태로 한번 바꿔보자. 

 

이제 경고를 표시할 준비는 다 끝났다. 바로 경고를 표시해보자!!

.alert(scoreTitle, isPresented: $showingScore) {
    Button("Continue", action: askQuestion)
} message: {
    Text("Your score is ???")
}

 

. alert를 사용하여 showingScore가 참일 때 경고를 표시하도록 하였으며, scoreTitle에는 설정한 내용을 표시하도록 하였다. Correct가 아니면 Wrong으로 출력될 것이다. 그리고 계속하기 버튼을 누르면 askQuestion()을 호출하는 해제 버튼을 추가하였다. 그렇게 되면 바로 위에서 언급한 askQuestion()이 작동하면서 국기 배열의 순서가 변할 것이다.

 

현재까지의 내용을 결과로 확인해보면 다음과 같다. 경고 창도 정확히 출력되고 내부 메시지 또한 잘 출력된다. 캡처 이미지에서는 못 보지만 저기서 계속하기를 누르면 뒤쪽에 있던 국기 배열들과 문제로 나오는 나라의 이름 배열 또한 모두 랜덤으로 다시 바뀌게 된다. 

 

 

위쪽 코드와 다른 부분은 영어로 되어 있는것을 한국어로 변경 한것 말고는 따로 없다.

 


 

clipShape.

위쪽 국기의 모양을 보면 기존 모서리가 90도로 딱 떨어지던 모양에서 약간 끝이 뭉툭하게 자연스럽게 표현하였다. 이건 어떻게 할까??

이건 clipShape()를 이용하면 원하는 대로 표현할 수 있게 된다. 

 

 

여기서 어떤 게 깔끔하고 종류도 알아보려고 search를 해보았고 clipShape의 속성 값으로는 3개지로 RoundedRectangle, 

Capsule, Circle로 예제 파일로 먼저 확인해보고 골라보았다. 

 

 

지금 예시 화면에서는 텍스트가 들어가 있지만 프로젝트에서는 국기가 들어갈 것이다. 국기의 경우 capule이나 circle로 하면 일부분이 가려지거나 국기를 표현하기에는 부적절하다고 느껴져 나의 경우 RoundedRectangle로 선택하였다.

 

 

모서리가 확실히 몽퉁하다!

여기서 뒷배경과 메인 박스의 확실한 구분을 위해 국기들 뒤쪽으로 또 다른 하나의 배경을 추가해보자!

.frame(maxWidth: .infinity)
.padding(.vertical, 20)
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 20))

뷰는 원래 자신의 콘텐츠와 자신이 이미 속해 있는 레이아웃에 따라서 자동으로 그 크기를 조절한다. 자동으로 조절하는 것이 아닌

자신이 커스텀 하고 싶다면? frame() 수정자를 사용하면 뷰의 크기나 영역을 조절할 수 있게 된다. 해당 코드를 보면 infinity. 말 그대로 무한대를 의미한다. 그리고 여기서는 국기와 동일하게. clipShape의 값은 여전히 RoundedRectangle로 설정해두고 배경 색상은 약간 반투명한 재질을 뜻하는 regularMaterial로 설정한다. 

 

 

 


이번 시간은 이렇게 마무리하고 다음 시간에 바로 이어서 구현이 안된 기능과 업그레이드시킬 수 있는 기능에 대해서 최종적으로 정리하면서 두 번째 프로젝트를 마무리하겠습니다~ 

 

learning by repetition

반응형

'SwiftUI & UIKit > Tutorials' 카테고리의 다른 글

HACKING WITH SWIFT - CoreML사용  (0) 2022.09.13
HACKING WITH SWIFT - Guess the Flag(3)  (0) 2022.09.03
HACKING WITH SWIFT - Guess the Flag  (0) 2022.08.31
HACKING WITH SWIFT - WeSplit(3)  (0) 2022.08.23
HACKING WITH SWIFT - WeSplit(2)  (0) 2022.08.18