
BeaRLibFOV - поле зрения
Модератор: Apromix
- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV
Ура! Cfyz прислал мне исходники демки на паскале 

- Вложения
-
- bearlibfov-pascal_demo.7z
- (120.62 КБ) 219 скачиваний
- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV
Также Влад Фомин прислал мне свою реализацию демки на Delphi с использованием тайлов и GDI 

- Вложения
-
- PNG_GDIfin_FOVDLL.RAR
- (275.84 КБ) 215 скачиваний
Re: BeaRLibFOV
А как реализация LOS связана с тайтлами и тем более с GDI 
UPD: А, речь про реализацию демки. Сорри

UPD: А, речь про реализацию демки. Сорри

- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Прямой код из паскалевского примера:
...в Delphi показывает ошибку "Operator not applicable to this operand type" внутри Cell. Как заставить код работать?
Скрытый текст: ПОКАЗАТЬ
- Cfyz
- Сообщения: 776
- Зарегистрирован: 30 ноя 2006, 10:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Если это вопрос ко мне, то, боюсь, вы не по адресу =) Я паскаль знаю на уровне сложения чисел в цикле. Пример набирался методом тыка в досовской версии freepascal. Что именно из того весьма размытого явления, именуемого паскалем, по-своему воспринимает Delphi -- это вопрос к людям, хорошо знающим предметную область. Sizeof возвращает какой-нибудь нехарактерный тип или указатели нельзя складывать с числами со знаком или еще чего в подобном духе. Попробуй это выражение разбить на наэлементарнейшие действия, можно будет хоть сузить область поиска.Apromix писал(а):Прямой код из паскалевского примера <...> в Delphi показывает ошибку "Operator not applicable to this operand type" внутри Cell
Справедливости ради, в C/C++ не лучше. Кросскомпиляция в GCC и MSVC тоже та еще головная боль.
Пытается раскуклиться
- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Эх, жаль
А без каллбеков переписать либу нельзя? Чтоб еще проще было взаимодействие?

- Cfyz
- Сообщения: 776
- Зарегистрирован: 30 ноя 2006, 10:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Не коллбеков, а указателей, обратных вызовов и так там нет. Вообще можно, я уже подумал обойтись вообще функциями:Apromix писал(а):А без каллбеков переписать либу нельзя? Чтоб еще проще было взаимодействие?
* сбросить все
* установить прозрачность ячейки (x, y)
* рассчитать видимость из точки (x, y)
* проверить видимость ячейки (x, y)
Отдав управление памятью полностью на совесть либы. Дешево и сердито.
Пытается раскуклиться
Re: BeaRLibFOV - поле зрения
Дельфя малость построже к типизации чем фпц.
Я переписал вот так, соблюдая сие дело.
Честно говоря, сперва вообще не въехал как такое может быть, но закралось сомнение насчёт типа Cells, полез в хедер - и вправду - pointer )))
Мой-то хедер я писал более типизировано (см. демку из поста Апромикса выше) и у меня там такой фокус без арифметики на указателях работает, а просто доступом к индексам массива в структуре.
У меня кстати ещё такой вопрос - возможно ли добавление в перечисление для клетки флага изменения состояния клетки - т.е. если клетка в результате алгоритма изменила своё состояние - то флаг тру, а если нет - то фолс, в начале работы алгоритма этот флаг всем проставляется в фолс. Объясняю - это для оптимизации - ведь можно не рисовать вообще то , что не изменилось, а брать из предыдущего кадра или ещё как.
Хотя, не отрицаю, к сути дела ФОВ-расчета оно особо не относится и вполне обосновано может быть причиной для отказа ))
Я переписал вот так, соблюдая сие дело.
Код: Выделить всё
Cell := pfov_cell(Integer(map.Cells) + (y*map.Width+x)*SizeOf(FOV_Cell));
Мой-то хедер я писал более типизировано (см. демку из поста Апромикса выше) и у меня там такой фокус без арифметики на указателях работает, а просто доступом к индексам массива в структуре.
У меня кстати ещё такой вопрос - возможно ли добавление в перечисление для клетки флага изменения состояния клетки - т.е. если клетка в результате алгоритма изменила своё состояние - то флаг тру, а если нет - то фолс, в начале работы алгоритма этот флаг всем проставляется в фолс. Объясняю - это для оптимизации - ведь можно не рисовать вообще то , что не изменилось, а брать из предыдущего кадра или ещё как.
Хотя, не отрицаю, к сути дела ФОВ-расчета оно особо не относится и вполне обосновано может быть причиной для отказа ))
- Cfyz
- Сообщения: 776
- Зарегистрирован: 30 ноя 2006, 10:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Да возможно, почему бы и нет. Там этих флагов завались (может показаться, что всего байт, но из-за особенностей выравнивания памяти "зарезервировано" все равно четыре; недоглядел), одним больше, одним меньше.phomm писал(а):возможно ли добавление в перечисление для клетки флага изменения состояния клетки - т.е. если клетка в результате алгоритма изменила своё состояние
Тем более, что в данном случае парадигма использования предполагает хранение реальной информации именно в этом массиве FOV_MAP. Вот если переделать на интерфейс без указателей (указатель на массив структур через C-style API -- мне тоже чем-то неуловимо не нравится), тогда да, там только суть, видно-не видно, а карта с какими угодно флагами хранится у пользователя либы как ему удобно.
Но без указателей будет много-много мелких вызовов функций и это надо еще на производительность протестировать прежде чем бросаться делать.
Пытается раскуклиться
- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Спасибо, вроде работаетphomm писал(а):Cell := pfov_cell(Integer(map.Cells) + (y*map.Width+x)*SizeOf(FOV_Cell));

А как будет со скоростью? Нынешний вариант на указателях очень шустрCfyz писал(а):Вообще можно, я уже подумал обойтись вообще функциями. Отдав управление памятью полностью на совесть либы. Дешево и сердито.

- Cfyz
- Сообщения: 776
- Зарегистрирован: 30 ноя 2006, 10:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Два года назад в соседней теме kipar была высказана идея:
В целом, интересная идея. Но предлагаемый вариант требует идеально точного повторения структуры памяти объекта-карты в каждой программе. Это неудобно:
1. Весьма низкоуровнево: должна быть возможность построить объект с именно таким расположением полей, их размером, паддингом и т. д. Полагаю, некоторые динамические и/или скриптовые языки могут вообще не иметь подобного инсрументария.
2. Жесткая привязка к однажды выбранной структуре. Любые последующие изменения, сколь угодно малые, потребуют колоссальных усилий.
Посему имею предложить свой вариант:
Суть заключается в чем: карта хранится где-то там в библиотеке. Предположений о том как именно в общем случае делать не следует. Доступ к карте осуществляется посредством весьма обобщенного интерфейса.
map_alloc: создает объект-карту указанных размеров и структуры, возвращает ее id. Дальнейшая работа осуществляется по этому id. Структура карты описывается строкой, где перечисляются поля (или, в выдуманных мною терминах, слои). Например, map_alloc(80, 25, "flag, int, float"); создаст карту, где каждая клетка имеет одно битовое поле-флаг, одно целочисленное и одно с плавающей запятой.
map_get/map_set: Унифицированный доступ к полям. map_get(id, 10, 10, 0) вернет значение первого поля (в приведенном выше примере — флага) ячейки {10, 10} карты c идентификатором id. Аналогично, map_set(id, 10, 10, 1, 12345) установит значение второго поля той же ячейки. Функции set/get для дробных чисел отдельные, так как в отличие от bool/byte/short/int этот тип так просто к целочисленному не приводится =)
Как же это работает с другими библиотеками? Возьмем, к примеру, FOV:
Глядите, этой функции для работы требуется только id карты, номер поля-слоя с информацией о прозрачности клеток (opacity_layer) и номер поля-слоя куда будет записан результат расчета. Актуальная же структура ячейки может быть любой. Возможно, другой библиотеке требуются еще пара полей помимо прозрачности. Возможно, opacity_layer — это только для FOV и поэтому это только flag. А может быть и так, что игра сама хранит в этой карте данные и opacity_layer это заодно и тип стены. FOV же на это наплевать, ему важно 0 или не 0 в этом поле.
На самом деле, тут еще много места для доработок и оптимизаций. Например, наверняка следует ввести типы данных между битом и четырехбайтным целым — байт и слово, со знаком и без. Может быть даже "цвет". Кроме того, скорость вызова функции на порядки (!) меньше, чем обращения к памяти напрямую. На самом деле все равно очень быстро (порядка 1Е-8 секунды на вызов на Core i3), но тем не менее. Это можно исправить путем получения из библиотеки адресов и смещений и написания врапперов под конкретный язык. Типа на С++ можно быстро, на lua не столь, но интерфейс тот же.
Но общую идею, я думаю, вы уже уловили.
К слову, в экспериментальном FOV есть еще один вызов:
Он позволяет пройтись по FOV коллбеком. В этом случае, очевидно, номер visibility_layer функции не нужен: хочешь — сам выставляй флаг в коллбеке.
Пример обеих библиотек (BearLibMap, BearLibFOV) и демо, которое интенсивно с ними работает (DemoLighting), в собранном под Windows виде и в исходниках есть в архиве по следующей ссылке: BearLib_Cfyz_20130706.zip
Скрытый текст: ПОКАЗАТЬ
1. Весьма низкоуровнево: должна быть возможность построить объект с именно таким расположением полей, их размером, паддингом и т. д. Полагаю, некоторые динамические и/или скриптовые языки могут вообще не иметь подобного инсрументария.
2. Жесткая привязка к однажды выбранной структуре. Любые последующие изменения, сколь угодно малые, потребуют колоссальных усилий.
Посему имею предложить свой вариант:
Код: Выделить всё
int map_alloc(int width, int height, const char* description);
void map_free(int map_id);
int map_copy(int map_id);
int map_assign(int dst_map_id, int src_map_id);
void map_clear(int map_id);
void map_clear_layer(int map_id, int layer);
void map_set(int map_id, int x, int y, int layer, int value);
void map_setf(int map_id, int x, int y, int layer, float value);
int map_get(int map_id, int x, int y, int layer);
float map_getf(int map_id, int x, int y, int layer);
int map_width(int map_id);
int map_height(int map_id);
map_alloc: создает объект-карту указанных размеров и структуры, возвращает ее id. Дальнейшая работа осуществляется по этому id. Структура карты описывается строкой, где перечисляются поля (или, в выдуманных мною терминах, слои). Например, map_alloc(80, 25, "flag, int, float"); создаст карту, где каждая клетка имеет одно битовое поле-флаг, одно целочисленное и одно с плавающей запятой.
map_get/map_set: Унифицированный доступ к полям. map_get(id, 10, 10, 0) вернет значение первого поля (в приведенном выше примере — флага) ячейки {10, 10} карты c идентификатором id. Аналогично, map_set(id, 10, 10, 1, 12345) установит значение второго поля той же ячейки. Функции set/get для дробных чисел отдельные, так как в отличие от bool/byte/short/int этот тип так просто к целочисленному не приводится =)
Как же это работает с другими библиотеками? Возьмем, к примеру, FOV:
Код: Выделить всё
int fov_calc(int map_id, int opacity_layer, int visibility_layer, int x, int y, int radius);
На самом деле, тут еще много места для доработок и оптимизаций. Например, наверняка следует ввести типы данных между битом и четырехбайтным целым — байт и слово, со знаком и без. Может быть даже "цвет". Кроме того, скорость вызова функции на порядки (!) меньше, чем обращения к памяти напрямую. На самом деле все равно очень быстро (порядка 1Е-8 секунды на вызов на Core i3), но тем не менее. Это можно исправить путем получения из библиотеки адресов и смещений и написания врапперов под конкретный язык. Типа на С++ можно быстро, на lua не столь, но интерфейс тот же.
Но общую идею, я думаю, вы уже уловили.
К слову, в экспериментальном FOV есть еще один вызов:
Код: Выделить всё
typedef void (*fov_callback)(int map_id, int x, int y, void* opaque);
int fov_calc_cb(int map_id, int opacity_layer, int x, int y, int radius, fov_callback callback, void* opaque);
Пример обеих библиотек (BearLibMap, BearLibFOV) и демо, которое интенсивно с ними работает (DemoLighting), в собранном под Windows виде и в исходниках есть в архиве по следующей ссылке: BearLib_Cfyz_20130706.zip
Пытается раскуклиться
- Apromix
- Мастер
- Сообщения: 1236
- Зарегистрирован: 04 июл 2011, 10:44
- Откуда: Украина, Черновцы
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Cfyz
А можно как-то эту Lights в отдельную библиотеку вынести? Ну или встроить в терминал?
А можно как-то эту Lights в отдельную библиотеку вынести? Ну или встроить в терминал?
- Cfyz
- Сообщения: 776
- Зарегистрирован: 30 ноя 2006, 10:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: BeaRLibFOV - поле зрения
Apromix, ты говоришь про расчет FOV? Да, его можно отделить от той весьма экспериментальной либы Map и вынести в отдельную маленькую, оставив только коллбеки.
Есть навязчивая идея сделать один универсальный FOV на все случаи жизни -- честно геометрический, рассматривающий карту как набор линий-стен, а не точек-клеток. Разом уйдут все проблемы типа симметричности, артефактов от колонн и черти чего там еще. Шестигранники опять же, у них с FOV/LOS все еще хуже. Есть неплохой шанс, что с применением ряда оптимизаций такой подход будет работать не намного медленнее классического (а в случае небольшого количества ровных комнат -- может еще и обгонит). Но в полный рост встает проблема как донести до библиотеки карту уровня -- коллбеки тут уже не помогут. Можно попытаться развить идею универсального же представления карты (на которой этот тред заглох на пару лет).
По поводу встроить в терминал, тут неочевидно. В минимальном виде (чисто расчет FOV по коллбекам) это такая штука, которая к терминалу не имеет отношения, ее логично отдельно иметь. Терминал и так вон начинает пухнуть от логгирования всякого и хранения опций во внешних файлах. Еще немного и пора будет делать выбор -- или делить на BearLibTerminal, BearLibLog, BearLibConfig и т. п. или переименовываться и эволюционировать в сторону цельного фреймворка.
Есть навязчивая идея сделать один универсальный FOV на все случаи жизни -- честно геометрический, рассматривающий карту как набор линий-стен, а не точек-клеток. Разом уйдут все проблемы типа симметричности, артефактов от колонн и черти чего там еще. Шестигранники опять же, у них с FOV/LOS все еще хуже. Есть неплохой шанс, что с применением ряда оптимизаций такой подход будет работать не намного медленнее классического (а в случае небольшого количества ровных комнат -- может еще и обгонит). Но в полный рост встает проблема как донести до библиотеки карту уровня -- коллбеки тут уже не помогут. Можно попытаться развить идею универсального же представления карты (на которой этот тред заглох на пару лет).
По поводу встроить в терминал, тут неочевидно. В минимальном виде (чисто расчет FOV по коллбекам) это такая штука, которая к терминалу не имеет отношения, ее логично отдельно иметь. Терминал и так вон начинает пухнуть от логгирования всякого и хранения опций во внешних файлах. Еще немного и пора будет делать выбор -- или делить на BearLibTerminal, BearLibLog, BearLibConfig и т. п. или переименовываться и эволюционировать в сторону цельного фреймворка.
Пытается раскуклиться
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость