SwiftUI: Wordle 1/2

Vladislav Zhukov
4 min readJun 2, 2022

--

main image

Всем привет, думаю вы уже слышали об завирусившейся игре wordle, ну и предлагаю не долго думая написать свой клон!

Запускаем Xcode, далее File>New>Project и выбираем iOS app (в целом можно выбрать Multiplatform, но в рамках статьи я буду говорить только про iOS) и SwiftUI в меню Interface.

Давайте начнем с первого кирпичика игры, view которое будет отбражать введеную букву. Создадим папку view, а в ней файл CharView.swift и сразу создаим для view модель. Создадим папку models и файл Char.swift.

Тут думаю все просто, Char состоит из 2 полей, title в котором мы будем хранить введеный символ и highlight для выбора подсветки поля.

Теперь, когда у нас есть модель, давайте вернемся к файлу CharView.swift и пропишем код:

Не забывайте добавлять import SwiftUI!

И если мы все сделали верно, то в previews увидим:

Preview для view символа

Итак, мы можем отобразить введенный символ, теперь давайте создадим view, которое будет отвечать за слово целиком, для этого создадим в папке Models файл Word.swift:

Тут все просто слово состоит из букв, а поле wrongAnswerCounter нам нужно будет для анимаций, к нему вернемся позже. Таке сразу создадим 2 метода инициализации, один просто принимает массив букв, а вот второй принимает параметр numberOfChars по значению которого просто создает массив и “пустых символов”.

Теперь перейдем ко view, в папке View создадим WordView.swift:

И в preview увидим:

Вернемся к параметру wrongAnswerCounter из структуры Word, при вводе неверной догадки мы будем “трясти наше слово”, для этого во view model мы будем увеличивать значение wrongAnswerCounter. Для работы анимации мы добавили 2 строчки modifier и animation, давайте разберем их. Начнем с animation, данный метод указывает при изменении какого значения необходимо запускать анимацию, в данном случае мы передаем wrongAnswerCounter. Второй метод modifier в который мы передаем свою кастомную анимацию. Давайте ее реализуем, создадим папку Common, а в ней файл Shake.swift:

Реализацию анимации я подсмотрел тут, поэтому в рамках статьи не буду разбирать ее подробно.

Теперь, когда мы можем отображать слово целиком, пора сделать view с игровым полем, в папке View создадим файл BoardView.swift:

Тут, я думаю все понятно, мы просто объеденили несколько WordView в вертикальный стек. Давайте посмотрим что получилось:

Отлично, теперь остался последний шаг, нам нужна клавиатура!

Для этого в папке Models созадим 2 файла: KeysRow.swift и Keys.swift

Разберем их, KeysRow это просто массив из Char и является вспомогательным для Keys. Я изначально хотел сделать клавиатуру универсальной, для любого языка, поэтому структура Keys нужна для указания символов клавиатуры, в методе defaultKeys вы можете увидеть пример инициализации, мы должны просто передать строки с символами в правильном порядке, а метод initFrom(keysStrs: [String]) разобьет каждую строку на символы. Думаю идея понятна, вернемся к UI.

В папке View создадим KeyboardView.swift:

И сразу посмотрим что у нас получилось:

В результате у нас получилась клавиатура, похожая на нативную. Думаю по коду все понятно, за исключением парамера width, он нам нужен для расчета размера клавиш, а передаем мы его из вне, для того чтобы отказаться от использования GeometryReader внутри KeyboardView, так как GeometryReader имеет ряд неудобных моментов, при работе с ним, поэтому лучше использовать его на root view.

Теперь когда у нас есть поле для ввода символов и клавиатура, давайте объединим все это!

Создадим папку ViewModels, а в ней файл GameViewModel.swift

Теперь давайте создадим модель для нашего загаданого слова — Ridle, в папке Models создадим Ridle.swift:

Так же нам нужно создать 2 сервиса RidleProvider и LastRidleIdStore. Первый будет имитировать получение загаданного слова по сети, а второй будет отвечать за хранение id последнего отгаданного слова. Давайте создадим папку Services а в ней файлы RidleProvider.swift и LastRidleIdStore.swift:

Тут мы просто через 1 секунду возвращаем рандомное слово, для того что бы в рамках одной сессии пользователь получал одно и тоже слово, используем статическую переменную riddle (в оригинальной игре вы можете отгадывать только 1 загадку в день)

Тут мы просто храним id последнего отгаданного слова в UserDefaults.

Теперь, когда у нас есть все необходимое, в папке View создадим ContentView.swift:

Запустим и посмотрим что получилось!

На этой ноте предлагаю закончить эту часть, в следующей части мы заменим все EmptyView() и добавим шиммеры!

Продолжение в части 2

--

--