16 октября 2016

Мой движок на as3


Сегодня будет код. As3, да. Дело в том, что я тут сидел и чего-то решил немного рассказать о своем велосипеде. Такой движок, который я сейчас использую при разработке новой игры. Пройдемся по основам, чтобы особо не загромождать это сообщение.

Введение. 

На мобильных устройствах рисование флеш-объетов тормозит. При большом количестве объектов прям сильно тормозит. С другой стороны, есть супер-ускорялка рисования для флеша. Называется Starling. Ну круто же! Да есть проблема – мелкие спонсоры, которые покупают сайтлоки, не любят Starling.
Конечно, заморочек много, но кратенько я описал ситуацию. Итак, исходя из вот этой штуковины, целью моего велосипеда было умение выводить графику двумя способами:
  1. через GPU (для хорошей производительности на мобильных девайсах), используя фреймворк Starling 
  2. через CPU (для возможности продавать веб-сайтлоки всяким мелким порталам) 
Связать все это вместе мне сильно помог такой мега-монстр программирования Crash-512. Э-ге-ге-й, ты крут!

Итак, вызов принят. Что дальше?

А дальше все просто. Я отказался от использования в игровом коде от Sprite-объектов. Вместо этого я создал класс GameSprite, который вмещает в себя два объекта – starling.Sprite и flash.Sprite. Выглядит это так:
public class GameSprite extends BaseObject
{
  protected var fGpuSprite: StarlingSprite = null;
  protected var fFlashSprite: FlashSprite = null;
  protected var fParent: GameSprite;
// бла-бла-бла
}

Все операции в игровом коде проходят через этот GameSprite. То есть в игровом коде я использую только GameSprite’ы. Под игровым я здесь понимаю код конкретной игры, который можно полностью отвязать от графического движка. Таким образом я могу вообще не волноваться, каким образом работает графическое ядро – через CPU или GPU.
Минусы? А-то!
Сам GameSprite становится монстром, ведь нужно добавить все необходимые методы. Например:
public function addChild( aGameSprite: GameSprite): void
{
  aGameSprite.parent = this;
  if(CommonConfig.GPU)
    fGpuSprite.addChild( aGameSprite.GetGpuSprite() );
  else 
    fFlashSprite.addChild( aGameSprite.GetFlashSprite() );
 }

Вот такое маньячество. Соответственно, вся магия пропадает, когда становится понятно, что мой велосипед – это обычная обертка над двумя очень похожими движками (Starling и Flash.Graphics)


Начало приложения

Теперь проясняется ситуация с тем, как работает стартовый класс. Упрощенно это выглядит так:
if(CommonConfig.GPU)
  new Starling( Starling_MainClass, aStage, viewPort);
else
{
  fFlash = new Flash_MainClass();
  addChild( fFlash );
}

То есть я создаю либо Starling_MainClass , либо Flash_MainClass. А уже внутри этих монстров я создаю GameClass, наследованный от GameSprite. Заметьте, я создаю GameClass и там, и там. Код почти полностью дублирован. Вот здесь и схлопываются две реальности – GPU и CPU. После этого игровой код един. Ибо GameClass уже не волнует какой режим включен.



Вершина айсберга

Конечно, всегда есть дополнительные сложности. И вопрос отображения спрайта - это всего лишь вершина айсберга. Обертка не заканчивается на единственном GameSprite классе. Ведь мне нужно еще уметь создавать текстуры для Starling-режима, растаскивать их по атласам, сделать дополнительный GameTextField, который будет продолжать идею обертки. Еще есть заморочки с процедурной сменой цвета объектов в разных подходах. Обертка использует либо свойство color у Starling-объектов, либо применяет ColorTransform во Flash-подходе. Далее идет управление. Снова необходим единый механизм, умеющий справляться с различного рода сложностями в обработке событий из разных движков. Но об этом как-нибудь потом.

Игровой код

Главное, о чем хотел рассказать, так это о том, как у меня выглядит игровой код. Реальный пример из реальной игры:

fBack = new GameSprite();
fBack.CreateImageByID( GetBackBitmapID() );
fContent = new GameSprite();
fTextValue = new GameTextField();
fTextValue.CreateByFontID( ConstTexts.FONT_UI_LITTLE);
fContent.addTextChild( fTextValue );
fTextValue.touchable = false;
fTextValue.color = 0x291C23;
fVisual.addChild( fBack );
fVisual.addChild( fContent );
fVisual.touchable = false;


Теперь, придя в CommonConfig, я одним переключателем GPU могу сменить способ отображения графики. И GameSprite после перкомпиляции будет оперировать новыми спрайтами внутри себя. А вот игровой код об этом и не знает. Удобно? Теперь – да, но вот написание обертки отняло много времени… может стоило Unity изучить

Все еще в процессе

Стоит отметить, что движок еще и не закончен. Ни одной игры на его базе не выпущено. Это как ипотека на много-много лет - вроде уже и ввязался, а вроде уже и не нужно, но и бросить не могу :) Зачем тогда я вообще об этом заговорил? Просто решил разбавить свой журнал кодом. Так, для веселья!

В общем, пишите, что вы обо всем этом думаете...

Сообщения, схожие по тематике:

0 коммент.:

Отправить комментарий