04 декабря 2012

ZenGL: введение

Наступает зима, красивые узоры на окнах, белое покрывало на земле. Обычно зимой хочется греться дома, сидеть за компьютером, неспешно работать и читать различные статьи. Правда у нас за окном пока слякоть, а падающий снег тает уже к утру... Но я, впадая в зимнюю спячку, решил немного размяться, почитать про всякого рода вкусности в области игр, попрограммировать какие-нибудь мелочи, одним словом - отдохнуть! И в своих поисках "интересных вещей" я снова и снова натыкаюсь на кроссплатформенную разработку: здесь запустили игру под Android, там злые птицы аннонсируют свой апдейт под iOS, да и в казуальном мире игры под Mac уже не новость. Что же делать со всем этим практически бунтом против PC? На ум приходит одна фраза: "если не получается подавить бунт, то нужно стать его предводителем".
В итоге я решил немного размяться, вспомнить паскалевидные языки и попробовать собрать какую-нибудь демку под ZenGL+Lazarus+Windows. Да, пока вот такая простенькая связка, но ведь начинать нужно всегда с простого, верно?
Итак, создаем новое приложение, без формы, только код, в Lazarus'е такой проект можно создать вот так: Файл->Создать...->Программа (в папке Проект). Теперь все удаляем и начинаем накручивать ZenGL. В секции begin-end добавляем регистрацию своих функций:

  zgl_Reg( SYS_LOAD, @Init );
  zgl_Reg( SYS_DRAW, @Draw );
  zgl_Reg( SYS_EXIT, @Quit );

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

  wnd_SetCaption( 'Lampogolovii demo: Simple explosion' );
  wnd_ShowCursor( TRUE );
  scr_SetOptions( 500, 400, REFRESH_MAXIMUM, FALSE, FALSE );

Вроде все прозрачно. Установили надпись заголовка окна, показываем курсор и устанавливаем размеры и стиль самого окна. Круто? Ну тогда вызываем:

  zgl_Init();  

И в путь! Конечно, такое у нас не скопилируется, ведь мы не описали функции Init, Draw, Quit. Сегодня не будем зацикливаться на этом, а просто абстрактно подумаем над тем, что вообще здесь происходит. В принципе понятно, что сначала мы что-то регистрируем, затем устанавливаем параметры приложения и в конце запускаем нашу программу "крутиться" в цикле.
Но давайте разберем все это более детально.

Регистрация обработчиков
Подобный подход используется повсеместно, но вот оборачивание всего кода в функции OnInit, OnDraw и т.д. - лично для меня ново. Но мне это нравится, потому что таким образом я снимаю с себя ответственность за многие вещи... Например, в обработчике SYS_LOAD я точно знаю, что окно уже создано, разрешение окна и его состояние заданы, графика проинициализирована, да и вообще все хорошо. Удобно!
Если заглянуть в zgl_main.pas, то можно увидеть довольно большое количество событий, на которые можно подписаться с помощью функции zgl_Reg(), вот некоторые из них:

// несколько базовых
SYS_LOAD
SYS_DRAW
SYS_UPDATE
SYS_EXIT

// а вот некоторые для работы с мышью

INPUT_MOUSE_MOVE
INPUT_MOUSE_PRESS
INPUT_MOUSE_RELEASE

// о-о-о, и айОС не обошли стороной
INPUT_TOUCH_MOVE
INPUT_TOUCH_PRESS
INPUT_TOUCH_RELEASE

То есть все нормально, можно добраться до большинства необходимых событий.

Установка параметров окна и приложения в целом
В модуле zgl_screen.pas есть несколько полезных функций, позволяющих установить необходимые нам параметры окна. Что обычно делают игры? Ну, разворачиваются в полноэкранный режим, разрешая при этом сворачиваться в окно да и устанавливают необходимое разрешение. Еще хорошо бы отлавливать сворачивания окна и уход фокуса, чтобы ставить игровой процесс на паузу. В общем-то играм больше и нечего делать со своими окнами. При инициализации приложения, достаточно вызвать scr_SetOptions(), объявление которого выглядит вот так:

function  scr_SetOptions( Width, Height, Refresh : Word; FullScreen, VSync : Boolean ) : Boolean;

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

Запуск на инициализацию
Ну вот и все, теперь со спокойной совестью можно выполнить

zgl_Init();

В этой функции установятся все наши ранее выбранные параметры окна, проинициализируется лог, а также звуковой драйвер Vorbis (для проигрывания ogg-файлов), создасться контекст OpenGL и много чего другого. В общем, стартует наша программа! Там же зукручивается наш бесконечный цикл жизни приложения.
Разобрав основы, самые азы ZenGL, я немного напишу о своих эмоциях, возникших при знакомстве с ним. Постараюсь их систематизировать и выразить в плюсах и минусах.

Недостатки
Начну с минусов.
  • Мне показалось жутким написание всяких zgl_ или scr_ вначале каждой функции... Первое желание - обернуть однотипные функции в классы. Я так и не понял, почему автор не пожелал этого сделать.
  • Очень мало саппорт-классов и функций. Вроде текстуры есть, а вот библиотеки текстур нет. Вернее она есть, но назвать ее "библиотекой" язык не поворачивается. Даже сказав "список", я сильно преувеличу возможности zglTTextureManager'а. Звуки есть, а вот звуковой менеджер такой же, как и с текстурами - минималистичный, урезанный, "лишь бы был". Конечно, это не главное, но все же.
  • Как я ни крутил исходники, пока от меня скрылась тайна - как пользоваться загрузкой текстур в отдельном потоке? То есть аргументы вроде resUseThreaded присутствуют, а вот как с этим быть на деле - не ясно. В вики тоже не нашел (правда я и искал недолго). Хотя в достоинствах движка это указано как фича, значит нужно искать дальше. Непрозрачность некоторых решений - довольно значительный минус.
На самом деле ругать бесплатную кроссплатформенную библиотеку на Pascal'е не хочется. Это также, как если бы вы увидели пегаса (лошадку с громадными крыльями, позволяющими летать) на улице и, отвернувшись, пробурчали "всю дорогу перегородил, негодник"...

Достоинства
Перейдем к положительным сторонам!
  • Кроссплатформенность... даже не знаю, что и добавить! Это чудо какое-то, что на Lazarus'е можно собрать игру под разнообразное количество девайсов!
  • Движок изначально затачивается под игры. То есть мы тут же можем найти поддержку бесплатного ogg-формата звуков, частицы, спрайты со слоями, поддержку мультиязычности текстов, джойстик, отзывчивость на тапы в айОС.
  • Множество демок. Как еще изучать движок? Конечно, рассматривая демонстрации его работы. Хотя сами демки могли бы быть и покрасочнее, но и то, что идет в стандартной поставке с сайта - уже замечательно!
  • Минималистичность во всем. Сомнительный плюс, согласен, но все же. Вы, наверно, удивитесь, но даже exe-шник, собранный в Lazarus'е весит всего 300-400Kb! Минимальные демки с GlScene весят в три-четыре раза больше!
  • Если я пойму, как пользоваться многопоточной загрзкой текстур (я уверен, что это уже имеется, просто я никак не догоню, как этим пользоваться), то этот плюс станет весомым достоинством движка для меня!
  • Выпущенные игры! Да-да, этот плюс перекрывает любые недостатки, замеченные в ZenGL. Именно выпущенные игры на BigFishGames говорят о том, что движок стоящий и к нему следует приглядеться всеми имеющимися глазами!
Итого
Вот и все, начало положено... Теперь осталось собрать несколько демок и разобраться, насколько просто делать игры на ZenGL.
Поздравляю всех с зимой!

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

7 коммент.:

  1. И тебя с зимой)
    не тяни с демками, уже жду)

    ОтветитьУдалить
    Ответы
    1. ок, постараюсь в начале следующей недели подготовить первую :)

      Удалить
  2. Раз уж я наткнулся на сей пост в гугле, то пожалуй отвечу :)
    - ZenGL изначально разрабатывался for fun в духе C style, аки процедурное программирование. В классы всё это оборачивает уже каждый как хочет(например MondoZenGL со странички extra, а некоторые проекты используют свои внутренние наработки скрещивая с PhoenixLib)
    - саппорт классы и функции действительно сведены к разумному минимуму, и библиотека предоставляет собой больше ядро, чем решение на все случаи жизни для ленивых
    - многопоточная загрузка ресурсов описана в стандартной демке "02 - Resources". Wiki, к сожалению, наполнять жутко скучно и сейчас уже некогда...
    - appMinimized исключительно для внутреннего пользования. Словить можно только потерю фокуса(что происходит и при сворачивании) посредством SYS_ACTIVATE(регистрируется процедура с параметром activate : Boolean). Ну и приложение само уйдёт на паузу, отключить это можно флагом APP_USE_AUTOPAUSE с zgl_Disable

    ОтветитьУдалить
    Ответы
    1. ух ты! невероятно, что ты наткнулся на этот пост!
      я сейчас себя чувствую как старушка, на кухню к которой зашел президент... все ли убрано? чем накормить? я нормально выгляжу?
      большое спасибо за развернутые ответы! конечно, я понимаю, что времени на все не хватает! просто я описываю со своей стороны, размышляя над тем, что уже готово, а что придется допиливать под себя...

      отдельное спасибо за напутствие ко второй демке! разобрался, все шикарно! в одном из следующих сообщений обязательно распишу об этом!

      планируешь какие-то доработки/усовершенствования движка? или ближайшее время расписано по часам?
      еще раз спасибо!

      Удалить
    2. Иногда гуглю от скуки, и попадаю на перлы, вроде недавних корейских статей по совмещению Pascal с Android и в частности ZenGL( http://blog.naver.com/simonsayz/120174013310 ), так что ничего невероятного, коммунити у Pascal'я подходит под фразу "мир тесен" больше остальных.

      >> просто я описываю со своей стороны, размышляя над тем, что уже готово, а что придется допиливать под себя...
      да это понятно. Да и библиотеку есть за что ругать, так что feel free, демагогию я в блоге устраивать не буду и надеюсь никак не повлияю тутошним появлением на дальнейшие посты :)

      >> планируешь какие-то доработки/усовершенствования движка?
      Эх, всех интересует этот вопрос, всё чаще и чаще... :) В движке много моментов просится на переделку или полировку, но в этом году по возможности буду только поддерживать stable версию исправлениями критических/мелких проблем, если таковые объявляются(кое-чего накопилось в svn'е, всё никак релиз не соберу). А там посмотрим.

      Удалить
  3. только хотел сказать, что Андрей вполне может найти сей пост и оставить комментарии, как пролистал к комментам и понял что это уже случилось!

    ...интересно это =)

    ОтветитьУдалить
  4. Как там твой квадратик-нинзя?

    ОтветитьУдалить