Забытые проекты, как хорошее вино. Чем дольше тебя не трогают, тем лучше они становятся.

В этой статье вы узнаете, как создать небольшую игру с помощью Elm. Надеюсь, мой пример вдохновит вас попробовать.

Время от времени люблю отдыхать от рутины и занимаюсь своим хобби: создаю казуальные игры. Обычно такие проекты начинаются внезапно, неожиданно приостанавливаются, редко заканчиваются и никогда не выпускаются. Иногда использую ReactNative, иногда - Elm.

Вяз

Elm - это функциональный язык, который компилируется в JavaScript. Elm помогает вам создавать веб-сайты и веб-приложения (скопировано из Introduction to Elm).

Если вы спросите меня, что такое вяз, да, это язык. Но в то же время это еще и каркас. Вы пишете код Elm, и основной его результат - веб-приложение Elm Architecture. Вот почему в конечном итоге Вяз превратился в фреймворк или лонгворк :-)

Что делает Эльм таким сексуальным? Вот мой топ.

Вяз Архитектура

Дизайн - это основа. Elm был разработан с использованием интерактивного шаблона однонаправленного потока данных. Не всякая простая вещь гениальна. Но все гениальное - просто.

Выглядит очень знакомо, правда? Все современные разработчики интерфейсов знают о Flux и Redux, в основе которых лежит концепция, согласно которой состояние управляется единым потоком данных. Верно, потому что ...

Redux был вдохновлен Архитектурой Вяза.

Elm был создан в 2012 году, прекрасном году, когда Bootstrap 2 представил адаптивные сетки с двенадцатью столбцами; Flux появился в 2014 году; Redux в 2015 году.

Тем, кто хочет поиграть с аналогичной концепцией в простом ванильном javascript, я могу порекомендовать изучить библиотеку cycle.js. Низкоуровневый фреймворк на основе реактивных расширений.

Тот факт, что так много фреймворков основано на одной и той же концепции, доказывает, что эта концепция чертовски хороша.

Синтаксис

Вместо моих слов пусть говорит код Вяза. Вы только посмотрите, как не полюбить все эти трубы и стрелы ?!

В этом фрагменте кода я создал собственную реализацию общей функции сокращения. Он может агрегировать целые значения в сумму…

reduce add 0 [ 1, 2, 3 ] => 6

… Или «сократить» список строк.

reduce dashify "" [ "e", "l", "m" ] => "e-l-m"

Мне нравится чистый синтаксис Elm. Если уже интересно - минимальная Синтаксическая документация. Это не займет много времени, поверьте мне

Разработка

Я ленивая задница. Я решил не писать ни одного теста для своей игры. В то же время я хочу получить результат качества космического корабля СССР. По этой причине для меня вяз как рождественский подарок.

Почему? Потому что одна из лучших особенностей Elm - отсутствие исключений во время выполнения. После того, как ваш код Elm будет успешно скомпилирован, он будет работать без исключений во время выполнения вечно.

В любом случае, чтобы предотвратить логические ошибки в вашем приложении, вам все равно нужно писать юнит-тесты. Тесты стандартные, как и везде.

Кроме того, с Elm очень легко разрабатывать и снова и снова реорганизовывать код. Компилятор - лучший друг разработчика Elm. Вы добавляете новую функцию, а компилятор подсказывает вам исправления кода. Чистое удовольствие.

А теперь поговорим о разработчике игр Elm!

Есть не есть

Создание игр - лучший способ выучить вяз. Казуальная игра - хороший выбор - вы можете начать с чего-то действительно простого, например, с игры-памятки или любой математической головоломки.

Моя игра основана на народной игре моего детства: съедобное-несъедобное. Ядро моей игры было создано в начале 2020 года, и только в конце года я закончил игру. Репозиторий игры на GitHub находится здесь.

Как играть?

Вам нужно накормить троих голодных парней. Правила просты: выберите героя и съешьте немного еды в зависимости от пищевых предпочтений героя. Набери как можно больше очков. Будьте осторожны - у вас всего 3 очка здоровья. Нажмите, чтобы играть

Программа

Всю игру можно записать как один файл Main.elm. Моя игра занимала около 800 строк кода. Написание всего приложения в одном файле - классический стиль Elm.

Приложение Elm вашей игры можно встроить в HTML и запустить со стороны js следующим образом:

Флаги - это метод передачи данных из внешнего мира в приложение Elm при запуске приложения. Моя игра предназначена для мобильных телефонов, поэтому я показываю сообщение «Не поддерживается» для широких экранов. Чтобы указать программный размер экрана, я отправил флаг со значением window.screen.width.

В игре два основных экрана: SelectHero - модальное всплывающее окно и экран Play.

МВУ

Программа Elm со скелетом методов Elm Architecture:

Init - считывает флаги (значение Int ширины) и возвращает исходное состояние модели. Просмотр - отображение HTML на основе текущего состояния модели. Обновление - место для обработки событий путем реагирования на Сообщения. Цикл MVU выглядит так:

  • Пользователь взаимодействует с HTML (например, нажмите кнопку)
  • Сообщение отправлено в Обновить
  • Обновить изменить состояние Модель на новое.
  • Просмотр отображает HTML в новом состоянии Модель. … Пользователь снова что-то делает.

Модель

Состояние приложения Elm представлено моделью. В моей игре Модель хранит информацию о следующих вещах:

  • Какой игровой экран показывать
  • Какой герой выбран
  • Какая еда показана
  • Сколько очков и очков здоровья (Hp) у игрока
  • Лучшие результаты игрока для каждого героя

Обновлять

Функция обновления содержит бизнес-логику приложения. Обновление изменяет состояние Модель в зависимости от предстоящих сообщений. Сообщение - это настраиваемый тип, который отправляется в функцию Обновить событиями пользовательского интерфейса (нажатие кнопки, наведение указателя мыши, изменение ввода и т. д.).

Для каждого события приложения вы создаете Сообщение и добавляете обработчик в функцию Обновить.

Я оставил все функции пустыми, чтобы показать вам скелет.

Если вам интересно, как все работает в моей игре - взгляните на этот стиль StateMachine.

Вид

В Elm вы работаете не с HTML напрямую, а с виртуальной DOM через функции.

Когда функция update завершена, Elm выполняет функцию view для визуализации HTML с помощью специальных функций Html. Elm - это все о функциях, помните об этом.

div [] []
=> <div></div>

Функция div с двумя аргументами: список атрибутов и список дочерних узлов.

div [ style "padding" "5px" ]
  [ p [] [ text "1" ]
  , span [] [ text "2" ]
  ]
=> <div style="padding: 5px;"><p>1</p><span>2</span></div>

Бульма

Я не гуру разметки, поэтому смешиваю свой уродливый стиль с замечательным фреймворком CSS под названием Bulma. Он прост в использовании и достаточно мощный, чтобы создавать все макеты, карточки, сетки, типографику и другие вещи для моей игры. 100% рекомендую попробовать, выучить Bulma можно буквально за несколько дней.

Последний пример игры - это функция, которая отправляет массив героев в анонимную функцию для отображения объектов героев в Bulma Cards.

Вот и все!

Это было несложно, правда? Надеюсь, что мой небольшой рассказ - хороший пример того, насколько легко и интересно писать на Elm.

Исходный код ждет вас в репозитории GitHub. Также вы можете поиграть в EatNotEat по этой ссылке и не забудьте оставить в комментариях свой лучший результат как Арнольд.

Clap-clap-clap за долгую жизнь инди-разработке игр Elm!