Маленький мультиплатформенный 2d движок tengine (android/ios/win32/nix/kolibrios/web(emscripten))

Приветствую всех, кому стало интересно узнать о моем небольшом проекте, которым занимаюсь в свободное от работы время, о своем долгоиграющем проекте под названием «tengine».

Какова же цель этого поста? Ответ простой — я ищу однодумцев. Я верю в то, что есть еще много людей, которым нравится славный и добрый олдскул. В этом и вся миссия — писать удовольствия ради что-то маленькое, но вполне функциональное, платформу для «приставочных» игрушек в стиле 8/16 бит.

tengine DEMO game (web version) управление: клавиши со стрелкам, ctrl. Полноценная концовка.

Главная особенность, отличающая tengine от сотен подобных поделок — не совсем стандартная идеология:
  • архитектура проекта делает упор на минимизацию использования динамической памяти. Если память и выделяется, она выделяется исключительно на инициализации подсистем
  • использовать динамическую память нужно так, как будто не существует операционной системы, постоянно помнить о фрагментации. Удаление памяти происходит в строго обратном порядке создания (за этим следит простой механизм контроля удаляемых указателей)
  • использование сторонних библиотек сведено к минимуму и должно быть аргументировано, зачастую это потенциальный источник фрагментации памяти
  • игровая сцена представляет собою готовую для использования память, сгенерированная редактором уровней
  • работа с объектами сцены игры ведется исключительно через идентификаторы, динамически создать объект невозможно
  • использование fixed point вместо float
  • мультиплатформенность
  • официальный язык проекта — си


Изначально я все это писал под nintendo ds, мою любимую игровую платформу. Но времена меняются и пришлось все переместить в более популярный мир технологий. Так появилась ветка для андроида, которая и стала в последствии основной. win32 версия играет более отладочную роль. По задумке игра пишется и отлаживается на win32, а потом компилится на другие платформы (все это конечно же условно, на win32 весь функционал работает полноценно). С появлением одного очень хорошего энтузиаста, проект обрел еще и NIX платформу, за что ему огромное спасибо. Хоть nintendo ds уже и не поддерживается, я умышленно не убрал платформенный код под ключом препроцессора из проекта. Также остались некоторые нинтендо-специфические архитектурные особенности, такие как поддержка нескольких экранов и логических слоев отрисовки. Все это описано в скудненькой, но все же документации.

Сейчас tengine представляет собой:
  • готовый мультиплатформенных функционал для android ndk, ios, win32, nix, kolibriOS, Emscripten (был еще функционал для nitro-sdk (nintendo ds), но я решил не продолжать развитие этой ветки из-за нехватки времени, вероятность, что кому-то сейчас интересен nitro очень мала)
  • браузерная версия js/html на основе Emscripten (https://github.com/kripken/emscripten/wiki), хорошая работоспособность даже на ie11
  • использование памяти по принципу frame allocator (удаление памяти в строго обратном порядке созданию)
  • архитектурное ограничение создания динамических объектов, что позволило отказаться от использования скриптовых языков
  • использование openGL es 1.x/2.0 а так же самописного блиттера для рендеринга
  • использование openAL (openSL es для android NDK) для звука
  • поддержка мультитача, dpad, клавиатуры
  • поддержка многопоточности на основе pthread (подгрузка потоковой анимации, работа с файлами, звук)
  • функционал для работы с сетью на начальной стадии
  • (примитивная) система партиклов
  • конвертер графических ресурсов (r5g5b5a1 основной и r8g8b8a8 вспомогательный)
  • простой интерфейс для работы с игровыми объектами: позиции, свойства, состояния
  • события (окончание анимации, достижение ноды и т.д.)
  • поддержка применения базовых афинных преобразований для кадров анимации игровых объектов
  • возможность попиксельной проверки границ игрового объекта сложной формы
  • поддержка тайловой карты
  • поддержка полупрозрачности
  • поддержка смешивание данных изображения с указанным цветом
  • поддержка логики путевых нод (по которым могут двигаться объекты)
  • (частично реализованная) система коллижн-линий, с помощью которых можно задавать границы или места «проходимости» под произвольным углом
  • эмулятор для win32/nix, упрощающий разработку и отладку приложения
  • базовая документация

В дополнение ко всему этому есть подсистема gui, являющаяся надстройкой над tengine. Основная идея: все элементы gui — обычные игровые объекты, которые при инициализации обретают уже предустановленный функционал элементов gui таких как, например, «кнопка». Достаточно зарегистрировать любой игровой объект в gui контейнере и указать какое поведение от него ожидается. Все остальное надстройка берет на себя.

Редактор уровней (me3) представляет собою утилиту для создания «уровней» для tengine и включает в себя:
  • подсистему работы с графическими ресурсами
  • подсистему создания сложной покадровой анимации, включая коллижн-зоны, пользовательские события, точки прикрепления (для динамического прикрепления других игровых объектов, например оружие к руке)
  • подсистему создания тайловой карты бэкграунда
  • подсистему триггеров, с помощью которых можно менять свойства объектов по определенным условиям
  • подсистему путевых нод
  • подсистему создания коллижн-линий
  • подсистему создания логических состояний объектов, завязывание их на анимацию
  • подсистему создания свойств объектов и работы с ними
  • менеджер объектов
  • отладка готовой карты, отслеживание работы триггеров, пользовательских событий
  • поддержка шрифтов, текстовых полей (текстовые объекты), внутренний текстовый редактор
  • поддержка функционала для локализации текстов на разные языки
  • создание готовых бинарных файлов с данными для tengine, экспорт в xml

Разобраться с редактором немного трудновато поначалу, я его писал специально под своего знакомого геймдизайнера. Но есть примеры в папке samples а также интерфейс на русском, который, как по мне, довольно интуитивен. Документацию, к сожалению, пока не осилил написать.

Кому все еще интересно, все доступно на https://bitbucket.org/pascualle/tengine

Как бонус, совсем не давно спортировал verlet библиотечку, описанную в посте habrahabr.ru/post/178135. Пока она стоит немного особнячком, но уже проверена на работоспособность (смотрите пример в samples/spider)

Читайте также небольшой туториал (внимание, он без картинок!) «Создание небольшой игры с помощью tengine» habrahabr.ru/post/180443
Share post

Similar posts

Comments 26

    +2
    Все очень интересно, но демку какую-нибудь бы, на битбакет есть примеры, но бинарей нет(
      –4
      Милый человек, ну это же культивация лени, поправьте, если это не так.
      Visual Studio Express качается бесплатно, *.vcxproj в самплах рабочий и проверен. Остается только нажать f7…
        +1
        Я веб-кодер, никогда VS в руках не держал, эх, ну ладно…
          0
          ой, пардон, забываю, что в мире есть другие программеры…
          Обещаю на днях выложить архив (а еще лучше, добавьте в Issues запрос, чтобы глаза музолило). Хотя честно признаюсь — там нечего смотреть, примитивный програмер арт + полигоны для экспериментов. Там более код ля примера, как начать что-то ваять свое да примеры использования подсистем.
            +8
            Когда я захожу на страницу проекта, всегда ожидаю увидеть блок «Demo» или «Example». Думаю, у многих такой же ход мыслей. Надеюсь, это поможет привлечь разработчиков.
              +1
              как и обещал, сделал zip-архив с парочкой демок, которые хотя как-то визуально можно воспринимать.
              Скачать можно или с моей странички bitbucket в категории «downloads» или по прямой ссылке:
              https://bitbucket.org/pascualle/tengine/downloads/tengine_samples_bin.zip
              (инструкция как запускать прилагается)
                0
                Посмотрел, красивая демка, жаль интерактива мало, вторая похожа на поле игры dune. Мне кажется, отличная идея — параллельно пилить игру где будут использованные все возможности движка.
                  0
                  Вот это самое оно, почему я вдруг вышел из тьмы. Попросту рук не хватает поддерживать все. Ищу однодумцев, которые бы помогли.

                  Кстати, сейчас ваяю документацию-туториал «как сделать игру» с подробным описанием что где надо жать в редакторе. Вдохновило обилие интереса вокруг моей поделки. Раз уж начал — надо рассказать людям все!
        0
        для любителей заминусовать, не прочитав ветки до конца — бинари уже есть
        0
        Что думаете по поводу других кроссплатформенных движков вроде cocos2d-x и moai?
          0
          думаю я о них хорошо, не даром же они популярны.

          у каждого инструмента — свое применение. Все же рекомендую посмотреть в сторону мармелада (http://www.madewithmarmalade.com), если планируете писать что-то «серьезное».

          А я никоим образом не пытаюсь быть круче или даже тягаться с коммерцией, да и миссия иная — все должно быть очень маленькое и запускаться на любом ведре с парой мегабайтов оперативки на борту (я не о андроиде или iOS говорю, это частности).
            0
            а я бы посоветовал посмотреть cocos2dx+marmalade, в плане их связки вместе. очень интересно получается
            0
            Увидев tengine в заголовке подумал что речь идет об этом веб сервере
              0
              Я тоже когда увидел спустя годы однофамильца улыбнулся. Но я был первым, первые упоминания о моем tengine датируются где-то так 2004 годом.
              0
              > динамически создать объект невозможно

              Поясните, пожалуйста, о каких объектах идет речь — о чем-то, относящемся к сцене (типа всяких стен, сундуков и прочего), или об игровых объектах типа «пуля», «гоблин», «игрок»?
              Если второе — то как предполагается это использовать, если заранее неизвестно, какие объекты будут созданы (скажем, игрок может 10 раз выстрелить из базуки, что потребует 10 объектов «ракета», или два раза кинут фаербол, что потребует двух фаерболов).
                0
                Немного теории:
                У свойств объектов есть несколько предопределенных свойств, которые tengine учитывает в логике.
                Это PRP_SPEED и PRP_ENABLE.
                Остановимся на PRP_ENABLE. Если оно не равняется 1, объект игнорируется и не рисуется.

                Теперь ответ на вопрос:
                для этого нужно использовать пулы. Ставим на сцену десять ракет и устанавливаем PRP_ENABLE в 0. Создаем в своей логике пул, и если нам нужно «породить» объект, мы присваиваем любому объекту-ракете, у которого PRP_ENABLE == 0 в PRP_ENABLE = 1. Дальше все обвязывается логикой вашей игры. Есть еще один трюк. Как раз для отрисовки пуль на стенах или копоти после взрывов, посмотрите на функцию drawSingleFrame. Она рисует любой кадр любой группы объектов сколько угодно раз на кадр.

                Зачем все так сложно? Отвечаю:
                — мы всегда знаем сколько объектов на карте, всегда будем уверены в fps
                — мы не фрагментируем память постоянными пересозданиями объектов

                Я уже писал про то, что идеология движка немного не стандартная. Но если привыкнуть — можно сделать (почти) все что угодно. Я действительно думал, когда все это создавал. На этой идеологии уже написано около 5 игр, в основном платформеры для j2me (у меня еще была версия для j2me, но я ее забросил). Сейчас хочу когда-то написать на нем что-то в стиле jrpg.
                  0
                  А как хендлится ситуация, когда в пуле не хватает объектов? Есть 10 ракет в пуле, а игроки вот так поднатужились и пустили разом 11?
                    0
                    [оффтоп]а если биноколь сломался? (с) Л.Подерев'янський

                    в этом случае ракеты нет, ждем пока пул обретет ракету. Или просим гемдизайнера подкрутить время жизни/скорость ракеты. Или добавляем на карту еще ракету… Выкрутиться можно. Понятное дело, тут вы абсолютно правы, динавически объекты порождать удобнее. Но я таки лучше заплачу цену в ограничение пула и буду спать спокойно.
                  0
                  Теперь о объектах.

                  В tengine понятие «объект» — это объект, обладающий свойствами. Все они есть экземпляры некоторой установленной группы («пуля», «гоблин», «игрок»). У каждой группы есть набор анимаций и состояний, для всех объектов одной группы она едина. Состояние включает в себя определенную анимацию и логическое направление (абстрактное понятие «вверх», «вниз», «вправо» и «влево» может использоваться как угодно, но если объект поставлен на путевые ноды, в моент достижение ноды принимается решение «куда идти дальше»). Объекты могут быть декорациями и «полноценными». Декорации не принимают участие в логике и не имеют свойств, используются по прямому назначению, для всяких украшений.

                  Тайлы бэкграуда объектами не являются. Они статичны и не изменяемы (вернее можно изменить программно индекс тайла, но это не считается). Они не могут проигрывать анимацию. Но у них есть свойства, которые программист может использовать для смоих нужд. Например указать что некоторая группа тайлов — это вода, или не проходима, или наносит урон.
                    0
                    А разделение логических классов и графических классов как у вас реализовано?
                    Пример: объекты логического класса «пуля от пистолета» (летит, сталкивается, дамажит) и «разрывная пуля от спец-ружья» (летит, сталкивается, взрывается) отрисовываться должны одним и тем же классом графических объектов «простая_пуля_01».

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

                    В своем движке первый случай я решил опустить, как редко используемый, а вот второй был довольно частый, как в моем примере с пулей.
                      0
                      Тут все до примитивного просто. О таких моментах заботится программист. Я не знаю, какие игры будут писаться на движке. Есть объекты и состояния. Больше ничего. Реализовать ваш запрос можно несколькими путями: пули — отдельно, взрывы — отдельно. Разные объекты. При достижении пули до цели ставим объекту взрыва координаты пули, делаем ему PRP_ENABLE = 1 и состояние, в котором проигрывается нужный нам взрыв. Вариант второй. У каждой пули-объекта есть свое состоние смерти. При достижении цели переводим пули в состояние смерти и смотрим анимация взрыва, знаем, что на последнем кадре анимации взрыва мы установили событие «я пуля и я умерла», ловим его и переводим пулю в пул.
                        0
                        Да нет, я понимаю, что реализовать можно по-разному, я просто спрашиваю, чтобы понять, что у вас в движке сделано, а что вовне передается.

                        То есть, по большому счету, у вас движок больше относится к… эм… медиа, чем к логике? То есть отрисовка, анимации, звуки. И говоря «объекты» вы, скорее, имеете в виду именно те самые «медиа объекты»?

                        В моем движке просто было похоже сделано, особенно, с учетом того, что вся логика считалась на сервере, а клиенты только рисовали.
                        Был класс MediaObjects — это клиентское представление, контейнер для, собственно графических обжектов (чья реализация уже зависела от рендерера), для звуковых объектов и т.п. Они как раз представляли отрисовываемую единицу типа «пуля_вида_1», «зеленая_ракета» — такого плана.

                        А были серверные GameObjects, которые представляли логику и разные GO могли быть отображены одним и тем же MO.

                        Кстати, в процессе разработки того движка понял, что просто декомпозиция GO на классы — путь в никуда. Дерево классов становится неподъемным, трудноизменяемым, с кучей неоднозначностей и адского наследования.
                        Пошел по другому пути и реализовал компонентный подход. Вздохнул с облегчением, возможности — просто невероятные.
                          0
                          Скорей всего движок реализован только на уровне «медиа». Если применить очень грубое сравнение, то я стараюсь наваять что-то похожее на flash player, где работа с объектами происходит как во флеше с мувиклипами. Сразу же оговорюсь, что не подражаю концепциям адобовцев, но вижу в этом грубом сравнении что-то похожее.
                            0
                            Понятно. А, если не секрет, почему такой выбор языка и платформ? Как-то удивила в списке FreeBSD)

                            Я свой движок писал на шарпе, вот статья о нем http://habrahabr.ru/post/147431/
                            Для вывода используется OpenGL, OpenAL. Изначально был на С++, но, честно — осточертело) Приходилось столько рутины реализовывать, которая на шарпе уже на уровне архитектуры заложена…
                              0
                              Я люблю си. Даже больше чем с++. Но тут более прагматичный подход: на tengine запросто можно наваять что-то «современное-кажуальное», например, в примерах есть пример создания игры «найти объекты» с огромными картинками и подгружаемыми анимациями (потому как никакой памяти не хватит для того, чтобы все поместить в память на сцене), но я не забываю про олдскул, мне очень нравятся микродевайсы, тот же самый нинтендо DS, там всего 4МБ оперативки, я слежу, чтобы tengine оставался «маленьким мультиплатформенным 2d движком tengine». Также Си легко переносится в другие языки, любые платформы, например, чтобы портануть на iOS мне не нужно фактически ничего нереписывать, вот она сила СИ!

                              FreeBSD — это заслуга моего соратника Евгения, он трушный линухоид (в отличии от меня, который в этой платформе полный профан), и я только за то, чтобы платформ было много.
                                0
                                Прочитал статью.
                                Ах, сударь, как же моему проекту не хватает сервера и транспорта…
                                Очень уважаю людей, которые делают все сами своими руками (если это некоммерческие проекты).
                                В общем, уважуха!

                  Only users with full accounts can post comments. Log in, please.