- PVSM.RU - https://www.pvsm.ru -

Возрождение Framework-а (часть 1)

В процессе работы над арканоидом [1], стало становиться понятным, чего именно не хватает Marmalade Framework [2]-у, разработанному ранее, в процессе создания значительно более простой игры. Выяснилось, что не хватает ему практически всего (именно поэтому я не смог его как либо использовать, работая над арканоидом).

Теперь, когда я готов начать обобщать полученный опыт, я приступаю к работе над следующей версией Framework-а. Как и прежде, цель этой разработки — облегчение выполнения рутинных операций при разработке 2D-игр с использованием инструментальной среды Marmalade [3], но теперь, основной упор будет сделан на декларативность. В идеале, в коде не должно оставаться никакой конкретики в отношении используемых ресурсов, позиционирования объектов на экране, локализации и т.п.

В этой статье не будет кода (именно поэтому я не помещаю ее в хабы разработки под iOS и Android). Сегодня, по совету crmMaster [4], я займусь проектированием.

Сердцем нашего проекта будет JSON [5]-описание. Вообще говоря, с тем парсером [6], который мы интегрировали в проект, мы могли-бы использовать YAML [7], но JSON мне нравится больше.

Итак, первое, что будет делать приложение после старта — это загрузка описания из файла main.json. Ниже мы рассмотрим, как будет выглядеть содержимое этого файла.

{ load: state.json,
  ...
}

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

Используя директиву load мы сможем добавить файл в очередь загрузок. Я специально не стал использовать слово include, поскольку оно подразумевает включение некоего ресурса непосредственно в той точке где находится по описанию. В нашем случае, файлы указанные директивой load, в корневой секции описания, будут загружены после завершения загрузки main.json. Также можно будет использовать динамическую загрузку описаний, о которой я расскажу позже.

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

   templates: { some_template: { ...
                               }
              }
   ...
   template: some_template,
   ...

Эта конструкция позволит нам эффективно бороться с копипастом. Используя ее мы сможем определить повторяющиеся именованные шаблоны, чтобы впоследствии использовать их в любом месте описания. Единственным условием такого использования является то, шаблон может быть использован только если он определен ранее в описании (парсер будет однопроходным).

Шаблоны можно будет определять не только в корневом, но и во вложенных разделах. Для чего могут понадобиться подобные локальные шаблоны — отдельная тема. Я собираюсь затронуть ее когда мы перейдем к реализации загрузчика.

  display:    { width:         720,
                orientation:   portrait
              }

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

Можно задать значения width и height, но, как правило будет задаваться только одна из них. В этом случае, все размеры и позиции будут пересчитываться так, чтобы пиксел оставался квадратным при любом соотношении сторон. Также, договоримся, что отрицательные размеры позиций будут означать координаты от правой и нижней сторон экрана, в сторону уменьшения.

Ширина экрана может быть переопределена в любой момент (например в другом файле описания), после чего, все позиции и размеры будут перерассчитываться относительно новой величины.

  devices:  [ { default:     Y,
                width:       720,
                height:      1280,
                path:        1280
              }
            ]

В этом разделе мы описываем соотношения сторон, для которых имеются ресурсы не требующие масштабирования. Строка path будет автоматически добавятся в начало имени любого графического ресурса. Задачей Framework-а будет выбор из имеющегося набора ресурсов того, который обеспечит наименьшие искажения при отображении.

  langs:     [ { id:          16,
                 path:        ru,
                 default:     Y
               }
             ]

Аналогичным образом описываются доступные локализации. Значение id должно соответствовать используемому в Maramalade. Строка path добавляется в имя любого локализованного ресурса (графического или звукового). Framework должен будет определить локализацию, исходя из текущих настроек устройства и приложения.

  resources:  { logo:        { localized:        Y,
                               file:             backgrounds/logo.png
                             },
                ball:        { x:                0,
                               y:                0,
                               width:            10,
                               height:           10,
                               left_margin:      3,                          
                               right_margin:     3,                          
                               top_margin:       3,                          
                               bottom_margin:    3,
                               file:             game/atlas.png
                             }
              }

Таким образом мы будем описывать графические ресурсы. Обязательная настройка file определяет имя файла, в котором содержится ресурс. Настройки x, y используется при работе с текстурными атласами [8]. Они, также как настройки width и height должны соответствовать размеру экрана, определенному в разделе display.

Настройки xxx_margin будут использоваться для изображений с прозрачными фрагментами на краях. Например, стреляющая платформа в арканоиде отрисовывается с двумя пушками по бокам. Фрагмент между пушками — прозрачный и в него может заходить шарик. Используя top_margin, мы можем определить его высоту.

В следующей части я планирую рассказать о разделах scopes и regions, определяющих блоки, из которых будет строиться приложение.

Исходные тексты Framework-а будут выкладываться на GitHub, по мере разработки.

Автор: GlukKazan

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/json/27684

Ссылки в тексте:

[1] арканоидом: http://habrahabr.ru/post/169435/

[2] Marmalade Framework: http://habrahabr.ru/post/161681/

[3] Marmalade: http://www.madewithmarmalade.com/

[4] crmMaster: http://habrahabr.ru/users/crmmaster/

[5] JSON: http://ru.wikipedia.org/wiki/JSON

[6] парсером: http://habrahabr.ru/post/166357/

[7] YAML: http://ru.wikipedia.org/wiki/YAML

[8] текстурными атласами: http://www.gamedev.ru/code/terms/texture_atlas

[9] Источник: http://habrahabr.ru/post/170189/