Как написать «Пятнашки» на Flutter

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Возможно, вы уже читали о конкурсе Flutter Puzzle Hack и думаете о том, как проявить максимум творческих способностей. И мы вам в этом поможем, рассказав о том, как структурирована кодовая база нашего примера головоломки. Подробностями делимся к старту авторского курса по веб-разработке на Python.

Архитектура

В представленном исходном коде многослойная архитектура для управления состоянием реализуется с помощью flutter_bloc. Блоки помогают управлять всем — от игровой логики до настройки тем. 

Все состояния управляются согласованно: чтобы изменить логику головоломки, нужно только найти и обновить соответствующий блок. Кнопки сброса и перемешивания, таймера и обратного отсчёта — тоже отдельные блоки, которые можно расположить по вашей задумке: может быть, сделать песочные часы для таймера? Или шикарно стилизовать перемешивание?

Обратите внимание: вся игровая логика находится в одном блоке PuzzleBloc, который изменяется по таким событиям, как нажатие на один из 15 квадратиков и его перемещение с помощью события TileTapped, а также полный сброс головоломки по событию PuzzleReset. Состояние головоломки изменяется при каждом изменении в игре:

class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> {
  PuzzleBloc(this._size, {this.random}) : super(const PuzzleState() {
    on<PuzzleInitialized>(_onPuzzleInitialized);
    on<TileTapped>(_onTileTapped);
    on<PuzzleReset>(_onPuzzleReset);
  }
  void _onPuzzleInitialized(
    PuzzleInitialized event,
    Emitter<PuzzleState> emit,
  ) {...}
  void _onTileTapped(
    TileTapped event,
    Emitter<PuzzleState> emit,
  ) {...}
  void _onPuzzleReset(
    PuzzleReset event,
    Emitter<PuzzleState> emit,
  ) {...}
}

Настройка темы

В примере кода головоломки есть две темы: Simple и Dashatar. Их можно взять за основу для собственных настроек или начать с нуля — реализация зависит от вас! Творческий подход можно проявить в настройке тем головоломки.

В демо всё происходит в верхней части PuzzlePage. Достаточно поменять элементы темы в одном месте, и изменения будут отражены везде. В обеих темах определяется ряд параметров: фон экрана, меню, логотип, кнопки, цвет текста, отображение таймера (есть в Dashatar, но нет в Simple) и другие. Они находятся в корня репозитория, в директориях dashatar и simple:

/// {@template simple_theme}
/// The simple puzzle theme.
/// {@endtemplate}
class SimpleTheme extends PuzzleTheme {
  /// {@macro simple_theme}
  const SimpleTheme() : super();
  @override
  Color get backgroundColor => PuzzleColors.white;
  @override
  Color get buttonColor => PuzzleColors.primary6;
  @override
  Color get hoverColor => PuzzleColors.primary3;
  @override
  Color get pressedColor => PuzzleColors.primary7;
  ...
}

В каждой теме есть LayoutDelegate, с его помощью вычисляется макет. Новые темы можно создавать, повторно используя одни и те же объекты макета. Останется настроить параметры. 

Для дизайна сложнее можно настроить всю тему LayoutDelegate. Например, чтобы создать пользовательский фон, отображаемый только на большом экране, можно переопределить backgroundBuilder:

@override
Widget backgroundBuilder(PuzzleState state) {
  return Positioned(
    bottom: 74,
    right: 50,
    child: ResponsiveLayoutBuilder(
      small: (_, child) => const SizedBox(),
      medium: (_, child) => const SizedBox(),
      large: (_, child) => const DashatarThemePicker(),
    ),
  );
}

Анимация

Анимация — прекрасный элемент головоломки для изучения. В простой теме Simple нет анимации, зато несколько поэтапных анимаций реализуется в коде Dashatar. Эти анимации управляются одним контроллером, в котором есть Interval для настройки задержки анимации и Tween для определения диапазона значений анимации. 

Это можно увидеть в собранной головоломке, в теме Dashatar, где последовательно отображаются несколько виджетов, анимируя смещение блока и непрозрачность. Похожим образом, используя ту же технику, с каждым тиком медленно растёт, а затем исчезает таймер обратного отсчёта, прежде чем появится следующий таймер:

Большинство анимаций в теме Dashatar неявные: нет необходимости писать всю анимацию самостоятельно — изменения свойств анимируются самими виджетами. Например, виджетом DashatarPuzzleTile анимируется перемещение квадратиков по нажатию на них. Благодаря неявно анимированному AnimatedAlign текущее положение квадрата меняется согласно заданному movementDuration:

class DashatarPuzzleTile extends StatelessWidget {
  ... 
  
  final Tile tile;
  
  @override
  Widget build(BuildContext context) {
    return AnimatedAlign(
      alignment: FractionalOffset(
        (tile.currentPosition.x - 1) / (size - 1),
        (tile.currentPosition.y - 1) / (size - 1),
      ),
      duration: movementDuration,
      curve: Curves.easeInOut,
      child: ResponsiveLayoutBuilder(...),
    );
  }
}

Головоломка для веба

При головоломки создан для веба. Для малого, среднего и большого экранов реализован адаптивный дизайн. Кроме того, есть ResponsiveLayoutBuilder с обёрткой вокруг виджета LayoutBuilder на Flutter, позволяющей указывать разные виджеты на разных контрольных точках.

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

Когда пользователь попадает в игру-головоломку по умолчанию — Simple, файлы для версии Dashatar загружаются в фоновом режиме. Аналогичный подход мы использовали при загрузке всех свойств для I/O Photo Booth (фотобудки ввода-вывода). Так мы гарантируем, что при переходе к теме Dashatar большинство файлов уже загружены.

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

Доступность

При создании «Пятнашек» учитывалась доступность. Взаимодействие с головоломкой возможно с помощью клавиатуры, для этого есть виджет RawKeyboardListener, который использует обратный вызов, когда пользователь нажимает или отпускает клавишу на клавиатуре. 

С приложением можно взаимодействовать через программы чтения с экрана. Это делается с помощью семантических меток. Для некоторых действий есть всплывающие подсказки: используется виджет Tooltip. 

Если вы пишете «Пятнашки» с нуля, настоятельно рекомендуем сделать головоломку доступной для всех пользователей (применяйте стратегии, аналогичные описанным выше).

Другие идеи

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

Из примеров Simple и Dashatar можно позаимствовать идеи настроек или чего-то интересного, что можно сделать самостоятельно. Одна интересная идея — проецировать на квадратики головоломки созданную Феликсом Блашке Flutter Plasma.

Эффект плазмы достигается применением виджета CustomPaint, обёрнутого в виджет Transform и анимированного с помощью AnimationController. Вот пример отрисовки плазмы из демо:

Ещё одна идея — получать изображения или другие данные от API. Например, чтобы сделать «Пятнашки», можно использовать Google Photos API, взяв фотографии одного из альбомов Google Photos. В этом конкурсе нет предела совершенству!

Посмотрите пример кода головоломки здесь. Поделитесь с нами своими творениями в Twitter с помощью хештега #FlutterPuzzleHack. Ждём с нетерпением!

Лицензия кода — MIT, так что его легко использовать в ваших «Пятнашках». А продолжить погружение в IT и прокачать ваши навыки вы сможете на наших курсах:

  • Профессия Data Scientist (24 месяца)

  • Курс «Python для веб-разработки» (9 месяцев)

Выбрать другую востребованную профессию.

Краткий каталог курсов и профессий

Data Science и Machine Learning

  • Профессия Data Scientist

  • Профессия Data Analyst

  • Курс «Математика для Data Science»

  • Курс «Математика и Machine Learning для Data Science»

  • Курс по Data Engineering

  • Курс «Machine Learning и Deep Learning»

  • Курс по Machine Learning

Python, веб-разработка

  • Профессия Fullstack-разработчик на Python

  • Курс «Python для веб-разработки»

  • Профессия Frontend-разработчик

  • Профессия Веб-разработчик

Мобильная разработка

  • Профессия iOS-разработчик

  • Профессия Android-разработчик

Java и C#

  • Профессия Java-разработчик

  • Профессия QA-инженер на JAVA

  • Профессия C#-разработчик

  • Профессия Разработчик игр на Unity

От основ — в глубину

  • Курс «Алгоритмы и структуры данных»

  • Профессия C++ разработчик

  • Профессия Этичный хакер

А также

  • Курс по DevOps

  • Все курсы

Источник: https://habr.com/ru/company/skillfactory/blog/652845/


Интересные статьи

Интересные статьи

Неделю назад OpenAI отменила список ожидания для доступа к нейросети GPT-3. Теперь разработчики из 152 стран, где поддерживается сервис, могут зарегистрироваться и свободно пользова...
Поздравляю, по крайней мере, всех живущих в Сибири с наступлением лета!)))Сегодня довольно непростая тема - навигация.Мы рассмотрим как устроена навигация в Flutter, что ...
Исходные данные и результаты работы программ должны где-то храниться для дальнейшего использования. Их хранение нужно организовать так, чтобы мы могли быстро получить нужную информаци...
Тема автоматизированных систем для торговли на бирже довольно популярна в рунете в последние несколько лет. Однако начинающим инвесторам создать своего торгового робота может быть нелегко. Се...
В Челябинске проходят митапы системных администраторов Sysadminka, и на последнем из них я делал доклад о нашем решении для работы приложений на 1С-Битрикс в Kubernetes. Битрикс, Kubernetes, Сep...