При написании мобильной игры немаловажной частою разработки является написание графического интерфейса. Если выбранный для разработки игры инструментарий уже имеет все необходимое — это просто чудесно. В обратном случае придется потратить довольно много времени на разработку кода ответственного за GUI. Особенно это отягощается необходимостью проектировать под разные девайсы с разным dpi, разрешениями и пропорциями экранов. Рассмотрим один из подходов для решения этой проблемы.
Самый простой подход — совсем проигнорировать проблему и писать все под один экран (очень просто в разработке, ужасно в результате). Чтобы как-то сгладить ситуацию, полученное финальное изображение можно масштабировать, чтобы оно нормально поместилось на экран, однако при этом теряются детали и четкость интерфейса (линия в один пиксель может стать размытой на несколько пикселей, ну и вместо попиксельных движений получим скачки через несколько пикселей).
Или можно рассчитывать все координаты в условных единицах, например дюймах. Тогда можно гарантировать что нарисованная кнопка будет иметь одинаковый физический размер даже на совсем разных экранах. Все необходимые детали будут иметь именно ту четкость, которую ми зададим, ну и останутся попиксельные анимации. Однако это не отменяет того, что контролы могут не помещаться на некоторых экранах, что создает сложности при проектировании интерфейса.
Справа изображен тот же экран с тем же разрешением что и слева на картинке, только большим dpi (т.е. с меньшим физическим размером экрана). Такие ситуации приходиться решать алгоритмическим путем в коде.
Мною был выбран вариант где-то между этими двумя подходами. При разработке выбирается константный проектируемый размер экрана, в координатах которого и происходит добавление всех контролов. Сам GUI движок гарантирует что этот проектируемый размер полностью отобразиться на экране девайса (с помощью предварительного масштабирования). При добавлении контрола указывается позиция (в проектируемых координатах) и якоря (anchors) — желаемое изменение позиции/размера контрола при несоответствии размера реального экрана к проектируемому. По сути эти два параметра (позиция в проектируемом экране + якоря) позволяют движку GUI определить где должен размещаться контрол (уже в реальных пикселях) учитывая разрешение экрана и отличия в пропорциях, хотя при разработке все рассчитывается в фиксированных координатах. Например вот так может выглядеть один и тот же экран при разных разрешениях:
Рассмотрим более детально как это работает. К примеру мы проектируем экран для разрешения 320х480. При этом разрешение экрана девайса на котором запускается игра составляет 480х800. Чтобы полностью поместить проектируемый экран на реальный, необходимо использовать масштаб равный х1.5 (координаты всех контролов при добавлении автоматически умножаются на этот коэффициент). Кроме того реальный экран имеет другие пропорции, так что просто применив масштаб мы получим лишнее свободное место по краям. Как раз здесь отыгрывают свою роль якоря. Так кнопка 7 имеет правый нижний якорь, в результате чего будет выравнена по правому нижнему углу экрана.
В коде добавление кнопки 7 выглядит таким образом:
rc.SetRect(280, 440, 310, 470);
AddItem(btn, rc, cAnchorRight or cAnchorBottom);
Реальные же координаты этой кнопки после добавления (прогона по масштабу и механизму якорей) составляют (420, 740, 465, 785). Примерно такая же ситуация и с другими кнопками (там только заданы другие якоря и координаты).
Как видим, такой подход относительно простой при проектировании интерфейса и дает хороший результат на разных девайсах. К тому же правильно спроектированный интерфейс сможет нормально работать как в ландшафтном, так и в портретном режиме без использования избыточного дублирующего кода. Исходный код GUI движка что у меня получился можно скачать по этой ссылке. По правде сказать этот код занял примерно 80% времени от разработки всей игры.
Автор: Corwal