ms из функции game_step() вычисляется, измеряя длительность кадра. В этом кадре происходит логика игры и логика движка, тут же вызываются калбеки типа onUpdateObject, все это в одном потоке. Длительность кадра я не могу предсказать, потому я собираю дельты в логике игры, ожидая, пока накопися секунда (>=1000ms). Функция onUpdateObject вызывается перед тем как поместить данные отрисовки в конвеер, потому считается, что новый кадр наступил (пока она не вызывается, рендер рисует буфер последнего кадра, с какой частотой он его рисует мне не очень интересно на этом уровне разработки игры). Поэтому целесообразно посчитать количество вызовов onUpdateObject за секунду, чтобы узнать, нужный мне fps
Возможно вы правы в своей арифметике. Я поступаю проще:
Есть функция, она вызывается вызывается постоянно из движка с дельтой времени.
void game_step(s32 ms)
{
fps_timer += ms;
}
Есть вторая функция, она вызывается калбэком по истечении указанного дизайнером времени (30мс)
void onUpdateObject(u32 layer, s32 iId, BOOL* const oDraw)
{
fps_tick++;
if(fps_timer >= 1000)
{
// вот тут у нас получается ~33fps
fps_tick = fps_timer = 0;
}
}
Раз уж мы следуем букве, в настройках установленно 30мс на кадр. 1000/30 = 33.33… Почему именно так? Это исторически сложилось, геймдизейнер понимает куда более «30 миллисекунд длится один кадр, заказывай художникам анимацию, опираясь на эту цифру». А потом и я привык. Я еще с самого начала говорил, что идеология всего этого проекта немного не стандартная.
Тут все же осмелюсь утверждать, что все относительно. Мне важно знать сколько кадров в секунду отрабатывает логика, а не отрисоовывает видеокарта. Последнее мне куда менее важнее при разработке логики игры. Тут сразу поправлю себя: мы полагаем. что движок написан хорошо и оптимизирован (конечно, в реальности все куда хуже, но сейчас не об этом). По этому нас интересует именно работа той части, которую ми пишем, собственно логику игры.
Люобознательный читатель посморел бы в настройки проекта и понял бы, что там стоит ограничение в 30fps. Это очень полезная настройка для игровой логики, даже если учитывать, что все завязываем на время между тиками.
В мире существуют два подхода для работы с частотой обновления логики игрового мира и скорости отрисовки кадров, посылаемых с конвеера. Один из них как раз основан на так называемой «жесткой fps». Вот именно его я и использую, так как, с моей точки зрения, в данном проекте это целесообразно.
Критика принимается.
Никогда не писал туториалы, потому получилось в виде «на что смотрю — то и пою». Документация проектика — вообще больная тема, времени зачастую хватает только дыры латать. Этот пост — более логическое продолжение первого, чтобы была хоть какая логическая завершенность: описание вообще о проекте и небольшой рассказ в стиле «оно еще и работает».
Вот это самое оно, почему я вдруг вышел из тьмы. Попросту рук не хватает поддерживать все. Ищу однодумцев, которые бы помогли.
Кстати, сейчас ваяю документацию-туториал «как сделать игру» с подробным описанием что где надо жать в редакторе. Вдохновило обилие интереса вокруг моей поделки. Раз уж начал — надо рассказать людям все!
как и обещал, сделал zip-архив с парочкой демок, которые хотя как-то визуально можно воспринимать.
Скачать можно или с моей странички bitbucket в категории «downloads» или по прямой ссылке: https://bitbucket.org/pascualle/tengine/downloads/tengine_samples_bin.zip
(инструкция как запускать прилагается)
Прочитал статью.
Ах, сударь, как же моему проекту не хватает сервера и транспорта…
Очень уважаю людей, которые делают все сами своими руками (если это некоммерческие проекты).
В общем, уважуха!
Я люблю си. Даже больше чем с++. Но тут более прагматичный подход: на tengine запросто можно наваять что-то «современное-кажуальное», например, в примерах есть пример создания игры «найти объекты» с огромными картинками и подгружаемыми анимациями (потому как никакой памяти не хватит для того, чтобы все поместить в память на сцене), но я не забываю про олдскул, мне очень нравятся микродевайсы, тот же самый нинтендо DS, там всего 4МБ оперативки, я слежу, чтобы tengine оставался «маленьким мультиплатформенным 2d движком tengine». Также Си легко переносится в другие языки, любые платформы, например, чтобы портануть на iOS мне не нужно фактически ничего нереписывать, вот она сила СИ!
FreeBSD — это заслуга моего соратника Евгения, он трушный линухоид (в отличии от меня, который в этой платформе полный профан), и я только за то, чтобы платформ было много.
Скорей всего движок реализован только на уровне «медиа». Если применить очень грубое сравнение, то я стараюсь наваять что-то похожее на flash player, где работа с объектами происходит как во флеше с мувиклипами. Сразу же оговорюсь, что не подражаю концепциям адобовцев, но вижу в этом грубом сравнении что-то похожее.
Тут все до примитивного просто. О таких моментах заботится программист. Я не знаю, какие игры будут писаться на движке. Есть объекты и состояния. Больше ничего. Реализовать ваш запрос можно несколькими путями: пули — отдельно, взрывы — отдельно. Разные объекты. При достижении пули до цели ставим объекту взрыва координаты пули, делаем ему PRP_ENABLE = 1 и состояние, в котором проигрывается нужный нам взрыв. Вариант второй. У каждой пули-объекта есть свое состоние смерти. При достижении цели переводим пули в состояние смерти и смотрим анимация взрыва, знаем, что на последнем кадре анимации взрыва мы установили событие «я пуля и я умерла», ловим его и переводим пулю в пул.
[оффтоп]а если биноколь сломался? (с) Л.Подерев'янський
в этом случае ракеты нет, ждем пока пул обретет ракету. Или просим гемдизайнера подкрутить время жизни/скорость ракеты. Или добавляем на карту еще ракету… Выкрутиться можно. Понятное дело, тут вы абсолютно правы, динавически объекты порождать удобнее. Но я таки лучше заплачу цену в ограничение пула и буду спать спокойно.
В tengine понятие «объект» — это объект, обладающий свойствами. Все они есть экземпляры некоторой установленной группы («пуля», «гоблин», «игрок»). У каждой группы есть набор анимаций и состояний, для всех объектов одной группы она едина. Состояние включает в себя определенную анимацию и логическое направление (абстрактное понятие «вверх», «вниз», «вправо» и «влево» может использоваться как угодно, но если объект поставлен на путевые ноды, в моент достижение ноды принимается решение «куда идти дальше»). Объекты могут быть декорациями и «полноценными». Декорации не принимают участие в логике и не имеют свойств, используются по прямому назначению, для всяких украшений.
Тайлы бэкграуда объектами не являются. Они статичны и не изменяемы (вернее можно изменить программно индекс тайла, но это не считается). Они не могут проигрывать анимацию. Но у них есть свойства, которые программист может использовать для смоих нужд. Например указать что некоторая группа тайлов — это вода, или не проходима, или наносит урон.
Немного теории:
У свойств объектов есть несколько предопределенных свойств, которые tengine учитывает в логике.
Это PRP_SPEED и PRP_ENABLE.
Остановимся на PRP_ENABLE. Если оно не равняется 1, объект игнорируется и не рисуется.
Теперь ответ на вопрос:
для этого нужно использовать пулы. Ставим на сцену десять ракет и устанавливаем PRP_ENABLE в 0. Создаем в своей логике пул, и если нам нужно «породить» объект, мы присваиваем любому объекту-ракете, у которого PRP_ENABLE == 0 в PRP_ENABLE = 1. Дальше все обвязывается логикой вашей игры. Есть еще один трюк. Как раз для отрисовки пуль на стенах или копоти после взрывов, посмотрите на функцию drawSingleFrame. Она рисует любой кадр любой группы объектов сколько угодно раз на кадр.
Зачем все так сложно? Отвечаю:
— мы всегда знаем сколько объектов на карте, всегда будем уверены в fps
— мы не фрагментируем память постоянными пересозданиями объектов
Я уже писал про то, что идеология движка немного не стандартная. Но если привыкнуть — можно сделать (почти) все что угодно. Я действительно думал, когда все это создавал. На этой идеологии уже написано около 5 игр, в основном платформеры для j2me (у меня еще была версия для j2me, но я ее забросил). Сейчас хочу когда-то написать на нем что-то в стиле jrpg.
Есть функция, она вызывается вызывается постоянно из движка с дельтой времени.
void game_step(s32 ms)
{
fps_timer += ms;
}
Есть вторая функция, она вызывается калбэком по истечении указанного дизайнером времени (30мс)
void onUpdateObject(u32 layer, s32 iId, BOOL* const oDraw)
{
fps_tick++;
if(fps_timer >= 1000)
{
// вот тут у нас получается ~33fps
fps_tick = fps_timer = 0;
}
}
Кодилось все на Unity3d, но уровни и все, что с ними связано, создавались на me3, описанном выше
Критика принимается.
Обязательно исправлюсь в следующих публикациях.
Не судите строго — для меня еще все ново тут, учимся, набиваем шишки…
В мире существуют два подхода для работы с частотой обновления логики игрового мира и скорости отрисовки кадров, посылаемых с конвеера. Один из них как раз основан на так называемой «жесткой fps». Вот именно его я и использую, так как, с моей точки зрения, в данном проекте это целесообразно.
Никогда не писал туториалы, потому получилось в виде «на что смотрю — то и пою». Документация проектика — вообще больная тема, времени зачастую хватает только дыры латать. Этот пост — более логическое продолжение первого, чтобы была хоть какая логическая завершенность: описание вообще о проекте и небольшой рассказ в стиле «оно еще и работает».
Кстати, сейчас ваяю документацию-туториал «как сделать игру» с подробным описанием что где надо жать в редакторе. Вдохновило обилие интереса вокруг моей поделки. Раз уж начал — надо рассказать людям все!
Скачать можно или с моей странички bitbucket в категории «downloads» или по прямой ссылке:
https://bitbucket.org/pascualle/tengine/downloads/tengine_samples_bin.zip
(инструкция как запускать прилагается)
Насчет LibCanvas — абсолютно справедливо, подтверждаю. Люди, очень рекомендую использовать.
Ах, сударь, как же моему проекту не хватает сервера и транспорта…
Очень уважаю людей, которые делают все сами своими руками (если это некоммерческие проекты).
В общем, уважуха!
FreeBSD — это заслуга моего соратника Евгения, он трушный линухоид (в отличии от меня, который в этой платформе полный профан), и я только за то, чтобы платформ было много.
в этом случае ракеты нет, ждем пока пул обретет ракету. Или просим гемдизайнера подкрутить время жизни/скорость ракеты. Или добавляем на карту еще ракету… Выкрутиться можно. Понятное дело, тут вы абсолютно правы, динавически объекты порождать удобнее. Но я таки лучше заплачу цену в ограничение пула и буду спать спокойно.
В tengine понятие «объект» — это объект, обладающий свойствами. Все они есть экземпляры некоторой установленной группы («пуля», «гоблин», «игрок»). У каждой группы есть набор анимаций и состояний, для всех объектов одной группы она едина. Состояние включает в себя определенную анимацию и логическое направление (абстрактное понятие «вверх», «вниз», «вправо» и «влево» может использоваться как угодно, но если объект поставлен на путевые ноды, в моент достижение ноды принимается решение «куда идти дальше»). Объекты могут быть декорациями и «полноценными». Декорации не принимают участие в логике и не имеют свойств, используются по прямому назначению, для всяких украшений.
Тайлы бэкграуда объектами не являются. Они статичны и не изменяемы (вернее можно изменить программно индекс тайла, но это не считается). Они не могут проигрывать анимацию. Но у них есть свойства, которые программист может использовать для смоих нужд. Например указать что некоторая группа тайлов — это вода, или не проходима, или наносит урон.
У свойств объектов есть несколько предопределенных свойств, которые tengine учитывает в логике.
Это PRP_SPEED и PRP_ENABLE.
Остановимся на PRP_ENABLE. Если оно не равняется 1, объект игнорируется и не рисуется.
Теперь ответ на вопрос:
для этого нужно использовать пулы. Ставим на сцену десять ракет и устанавливаем PRP_ENABLE в 0. Создаем в своей логике пул, и если нам нужно «породить» объект, мы присваиваем любому объекту-ракете, у которого PRP_ENABLE == 0 в PRP_ENABLE = 1. Дальше все обвязывается логикой вашей игры. Есть еще один трюк. Как раз для отрисовки пуль на стенах или копоти после взрывов, посмотрите на функцию drawSingleFrame. Она рисует любой кадр любой группы объектов сколько угодно раз на кадр.
Зачем все так сложно? Отвечаю:
— мы всегда знаем сколько объектов на карте, всегда будем уверены в fps
— мы не фрагментируем память постоянными пересозданиями объектов
Я уже писал про то, что идеология движка немного не стандартная. Но если привыкнуть — можно сделать (почти) все что угодно. Я действительно думал, когда все это создавал. На этой идеологии уже написано около 5 игр, в основном платформеры для j2me (у меня еще была версия для j2me, но я ее забросил). Сейчас хочу когда-то написать на нем что-то в стиле jrpg.