SwiftUI: Wordle 2/2
Привет, в предыдущей части мы создали UI и основу бизнес логики нашей игры, давайте в этой части добавим несколько штрихов, что бы наше приложение выглядело более законченным.
Начнем с состояния загрузки, в классе GameViewModel мы объявили enum GameState с возможными состояниями игры, а в GameView для всех состояний (кроме .play) пока возвращаем EmptyView.
Создадим в папке View папку Shimmers, а в ней ShimmerView:
Тут мы просто берем RoundedRectangle и анимируем параметр opacity, в результате получим:
Отлично, теперь мы можем создать шиммеры для клавиатуры и поля ввода вариантов ответа, создадим в папке Shimmers сперва BoardShimmerView:
А теперь KeyboardShimmerView:
Как видно в BoardShimmerView и KeyboardShimmerView мы просто повторили layout BoardView и KeyboardView и как вариант, мы могли бы не создавать отдельно ShimmerView, а сделать modifier для view, но исторически сложилось так что я сделал отдельными view.
Теперь вернемся к GameView и заменим EmptyView для if viewModel.gameState == .loading на вызов метода shimmers(width: geo.size.width), аналогично тому как мы это сделали для else, реализуем метод:
Отлично! Теперь у нас появилась анимация загрузки, теперь давайте отработаем остальные состояния игры, начнем с .lose.
В папке View создадим файл LoseMsgView:
И получим в результате:
Теперь создадим WinMsgView:
И получим
Вернемся в файл GameView и заменим EmptyView на только что созданные, но если мы не добавим одну небольшую деталь, то новые view будут отображаться просто поверх игрового поля, давайте добавим затемнение бэкграунда при появлении наших view.
Для этого в папке Common создадим HalfTransparentBg modifier:
И применим его для наших view в файле GameView, обновим switch:
Теперь нам остался последний штрих, сделать view которое будет отображать обратный отсчет до появления нового слова для разгадки.
В папке View создадим WaitingForNewRidleView:
И получим:
Как вы видите нам нужно создать viewModel для обновления значения обратного отсчета, давайте это сделаем. В папке ViewModels создадим WaitingForNewRidleViewModel:
Тут думаю все просто, в методе startCountDown мы создаем периодический таймер и каждую секунду высчитываем оставшиеся время.
Не забудьте вызвать timer.invalidate(), так как активный таймер также живет на run loop!
Ну и вернемся в GameView и заменим EmptyView для case .waitingForNewRidle на
И давайте посмотрим на конечный результат нашей работы:
Отлично мы написали свой клон игры Wordle на SwiftUI, конечно неплохо было бы еще поработать над анимациями и добавить настоящий бэк, но это уже совсем другая история.
Проект доступен по ссылке: git.