Пара вопросов общего плана
|
|
Меховой | Дата: Вторник, 29.10.2013, 11:32 | Сообщение # 1 |
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
| Всем здрасьте Найдётся пять минут для чайника? Я с Пандой пока ещё далёк от близкой дружбы и навскидку не сумел найти ответа на пару вопросов.
Мне нужно сделать игру-старомодный данжен краулер с РП-элементами. Нечто вроде лабиринта с головоломками. Пока что дело у меня дошло только до отрисовки самого лабиринта из тайлов типа "пол", "пол со стенкой", "угол" и так далее. Скрипт даже заработал (чем немало меня удивил) и исправно читает из текстового файла данные на каждый тайл и рисует по ним лабиринт. Вот код: Код class locDrawer(): ingame_tile_table=[] def __init__(self,path): self.floor=loader.loadModel("/c/someshit/floortile.egg") self.wall=loader.loadModel("/c/someshit/wallleft.egg") self.hallway=loader.loadModel("/c/someshit/twowalls.egg") self.corner=loader.loadModel("/c/someshit/tileangle.egg") self.deadend=loader.loadModel("/c/someshit/deadend.egg") self.start(path) def start(self,path): self.loc_file=open(path,'r') while True: line=self.loc_file.readline() if not line: break if line[0]=="#": continue tile_data=line.split(';') self.draw(tile_data) self.loc_file.close() def draw(self,data): self.dnp=render.attachNewNode("tile_" + data[0]) self.posX=float(data[2])*4 self.posY=float(data[3])*4 self.hOrientDegree=float(data[4]) if data[1]=='floor': self.floor.instanceTo(self.dnp) elif data[1]=='wall': self.wall.instanceTo(self.dnp) elif data[1]=='corner': self.corner.instanceTo(self.dnp) elif data[1]=='hallway': self.hallway.instanceTo(self.dnp) elif data[1]=='deadend': self.deadend.instanceTo(self.dnp) self.dnp.setPos(render,self.posX,self.posY,0) self.dnp.setH(self.hOrientDegree) self.ingame_tile_table.append({'index':data[0], 'tileNodePath':self.dnp, 'tilePosX':self.posX, 'tilePosY':self.posY}) Собственно, у меня для каждого тайла делается свой NodePath и на него потом инстансится нужная модель. А теперь вопрос - как мне ко всему этому присобачить коллизии? Чтобы тыкаться в стены и не проходить сквозь пол. Дополнительно цеплять к каждому NodePath'у по коллизионному узлу или есть способ попроще/получше/поумнее? И как вообще сказывается на производительности такое количество узлов в сцене?
И да, поясните, плиз, на пальцах, что за фигня такая CollisionRay. Как определяется.
Заранее благодарен
P.S. Архив с накоженным приложил на всякий случай.
|
|
| |
ninth | Дата: Вторник, 29.10.2013, 13:34 | Сообщение # 2 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Добро пожаловать в сообщество )
По производительности - рекомендованное количество узлов в сцене < 300. Поэтому стоит выделить геометрию которая не будет меняться (стены, пол, статичные объекты), собрать это всё под один узел с применением clearModelNodes(), а затем запустить flattenMedium() или flattenStrong() на этом узле. Если уровень планируется большой, то узлов сборки можно сделать несколько привязав их к определённой территории. Для того чтобы рендер мог откинуть и не обрабатывать те, которые не будут видны.
Теперь по коллизиям. Проще всего коллизионную геометрию сделать в той же модели. В простых случаях этот же способ будет и самым быстрым по обработке. Для больших территорий разговор отдельный - там для производительности потребуется геометрию октрифицировать. Можно конечно и процедурно генерировать коллизионную геометрию, но имхо овчинка выделки не стоит. Если лестниц у тебя не планируется, то на весь пол лучше просто положить одну коллизионную плоскость. Если столкновения нужно считать только с полом и стенами, то возможно стоит вообще от системы коллизий отказаться и ограничить перемещения математически, хотя это скорее вопрос личных предпочтений.
Если будешь делать коллизионную геометрию - не повторяй один в один уровень, а упрощай и делай фаски - см. картинку. Игроков очень раздражает цепляние за выступающие углы и колонны, да и обрабатываться быстрее будет.
CollisionRay - один из стандартных объектов для коллизии. Луч заданный точкой и вектором. Определяет всю коллизионную геометрию в направлении вектора. Чтобы объяснить на пальцах надо знать насколько ты вообще знаком с пандовской системой определения коллизий )
Ещё совет - используй абсолютный путь к файлам и не пиши расширение для модели. Т.е. в твоём случае вместо self.floor=loader.loadModel("/c/someshit/floortile.egg") лучше написать self.floor=loader.loadModel("floortile")
|
|
| |
Меховой | Дата: Вторник, 29.10.2013, 16:48 | Сообщение # 3 |
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
| Спасибо за советы!
Вы это... Скажите, если я вдруг стану слишком уж навязчивым, потому как вопросов у меня будет МНОГО. Рабочий код я могу сочинить методом научного тыка, но когда я не понимаю, что конкретно делает каждая строчка, мне становится грустно и я начинаю задавать вопросы. С английского не всегда удаётся адекватно понять.
Нанизал все тайлы на общий узел, clearModelNodes() и flattenStrong() к нему применил, впечатлился показанным analyze'ом шести узлам вместо сорока двух. Я правильно понял, он переписал все вершины и их параметры вместо отдельных узлов в один общий, а сами отдельные погрохал? Обращаться к тем NodePath'ам, которые я в списке сохранял, теперь бессмысленно?
Цитата Проще всего коллизионную геометрию сделать в той же модели. В простых случаях этот же способ будет и самым быстрым по обработке. Для больших территорий разговор отдельный - там для производительности потребуется геометрию октрифицировать. Сделать коллизионную геометрию в той же модели - это прямо внутри egg'а определить коллайдящие полики, что ли? А как это сделать? Модельки рисовал в Блендере, с ним тоже пока не очень знаком. (( И что означает матерное с виду слово "октрифицировать"?..
Ограничить передвижение математически на самом деле хорошая идея, тем более что у меня планируется передвижение игрока "квадратами", типа шаг на тайл вперёд/шаг на тайл назад без возможности оглядываться мышкой, но я хочу всё-таки коллизиями. Вопрос личных предпочтений, да. Если так и не выйдет - перепишу на расчёт положения по координатам, не проблема.
С коллизинной системой Панды я знаком вроде нормально. Во всяком случае, в цепочке узел-геомформа-траверсер-хэндлер сложностей вроде не вызывает ничего, включая маску-внутрь и маску-наружу. Меня только CollisionRay смущает, я его в виде геометрии представить не могу
Сообщение отредактировал Меховой - Вторник, 29.10.2013, 16:59 |
|
| |
ninth | Дата: Вторник, 29.10.2013, 23:57 | Сообщение # 4 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Цитата Меховой ( ) Скажите, если я вдруг стану слишком уж навязчивым Обязательно ) Но последнее время у нас тут активность небольшая, так что время отвечать на вопросы найдётся )
Цитата Меховой ( ) Нанизал все тайлы на общий узел, clearModelNodes() и flattenStrong() к нему применил, впечатлился показанным analyze'ом шести узлам вместо сорока двух. Я правильно понял, он переписал все вершины и их параметры вместо отдельных узлов в один общий, а сами отдельные погрохал? Суть понял правильно. Есть некоторые нюансы, но это в процессе работы увидишь, а может оно тебе и вообще не потребуется.
Цитата Меховой ( ) Обращаться к тем NodePath'ам, которые я в списке сохранял, теперь бессмысленно? Да. Ссылки будут либо пустые либо все ссылаться на общий узел. На память не скажу точно, но думаю легко проверить если надо. Поэтому я и говорил, что это нужно проделывать со статической геометрией которую ты в дальнейшем менять не планируешь.
Цитата Меховой ( ) Сделать коллизионную геометрию в той же модели - это прямо внутри egg'а определить коллайдящие полики, что ли? А как это сделать? Модельки рисовал в Блендере, с ним тоже пока не очень знаком. Именно. Здесь есть два варианта: Плохой, но быстрый в плане рисования модельки: делать видимую геометрию одновременно и коллизионной Хороший, но требует немного больше трудозатрат: делать колизионную отдельно от видимой (но в той же модели) На скрине вариант номер 2. Коллизионная геометрия показана полупрозрачным.
Как её задать зависит от того чем пользуешься для экспорта. Универсальный вариант не зависящий от редактора и экспортёра - руками вписать в egg нужный параметр. Код .... <Group> Cube.001 { <Collide> { Polyset descend } <Transform> { .... здесь <Collide> { Polyset descend } означает, что данная группа полигонов является невидимой колизионной. Собственно <Collide> что это коллизии. Polyset говорит, что в качестве объектов для коллизий используются полигоны группы. descend означает, что это свойство будет распространено ниже по иерархии, т.е. на дочерние узлы/группы. Можно сделать <Collide> { Polyset keep descend }. keep говорит о том, что полигоны должны оставаться видимыми. Описание ключевых слов для коллизий http://www.panda3d.org/manual/index.php/Egg_Syntax#Collide У панды есть несколько отличающихся и в то же время пересекающихся механизмов для задания коллизий, так что если где-то увидишь другой способ - не пугайся )
Цитата Меховой ( ) Ограничить передвижение математически на самом деле хорошая идея, тем более что у меня планируется передвижение игрока "квадратами", типа шаг на тайл вперёд/шаг на тайл назад без возможности оглядываться мышкой, но я хочу всё-таки коллизиями. Вопрос личных предпочтений, да. Если так и не выйдет - перепишу на расчёт положения по координатам, не проблема. Так, я что-то не совсем понял, а зачем тебе тогда вообще коллизии, если у тебя всё настолько жёстко задано, при таком передвижении игрок по-идее вообще не должен стен касаться, или я не так понял? Или тебе вообще для детекта объектов мышкой?
Цитата Меховой ( ) я его в виде геометрии представить не могу Странно, не знаю тогда даже как пояснить ) Ну луч и луч. Представь лазерную указку, только она будет пятно оставлять (детектить) не только на первой стенке, но и на остальных, расположенных дальше, и на обратной стороне стенки тоже.
|
|
| |
ninth | Дата: Среда, 30.10.2013, 00:17 | Сообщение # 5 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| К слову о коллизиях. Несмотря на название они сами по себе не означают, что объекты отталкиваются. Коллизии лишь определяют, что объекты пересеклись, а дальнейшее поведение уже определяется хэндлером
|
|
| |
Меховой | Дата: Среда, 30.10.2013, 10:43 | Сообщение # 6 |
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
| Спасибо )) Добавление коллайда к группе своё дело сделало. )))
Цитата ninth ( ) Так, я что-то не совсем понял, а зачем тебе тогда вообще коллизии, если у тебя всё настолько жёстко задано, при таком передвижении игрок по-идее вообще не должен стен касаться, или я не так понял? Или тебе вообще для детекта объектов мышкой?
При таком перемещении персонаж стен касаться в общем случае не будет, но игрок сам может попробовать направить персонажа в стенку. Вот я и хочу, чтобы его в этом случае об эту стенку лбом приложило и обратно в середину тайла поставило, да и с коллизиями поближе познакомиться хотелось. Мне так в принципе даже поверхности-фаски расставлять не надо, при строго линейном движении углы он всё равно не зацепит. Ну а детект объектов мышкой - история отдельная, по этой части я и в мануале, и на оф-форуме видел несколько упоминаний. Как дойду до изготовления этого куска, буду разбираться. ))
Цитата ninth ( ) Странно, не знаю тогда даже как пояснить ) Ну луч и луч. Представь лазерную указку, только она будет пятно оставлять (детектить) не только на первой стенке, но и на остальных, расположенных дальше, и на обратной стороне стенки тоже.
Я уже разобрался, спасибо ))) Затыка была в том, чтобы представить направление вектора по его координатам. Курение соответствующего кусочка аналитической геометрии помогло.
Ещё вопрос, вроде пока последний, про огонь. Если я правильно себе это представляю, огонь в игре можно сделать либо попроще, но понекрасивее на партикловом рендере самой Панды, либо посимпатичнее, но с геморроем на шейдерах. Так? И где в таком случае можно получить средней углублённости представление о шейдерах и их построении?
|
|
| |
ninth | Дата: Среда, 30.10.2013, 18:06 | Сообщение # 7 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| В 3D без векторов никуда, это тот самый костяк на котором 3D держится )
Частицы довольно универсальный инструмент для всяких эффектов если с ними разобраться. Вариант олдскул и немного попроще - анимированный спрайт, в стандартных примерах было. Чисто шейдерный огонь - это тот ещё матан, да и пригоден он на текущий момент больше для демонстрации крутизны. В реальных играх сейчас навешивают шейдерные эффекты поверх одного из предыдущих вариантов. Я здесь в примерах выкладывал - на огонь из частиц наложено шейдерное искажение для имитации дрожания разогретого воздуха.
Шейдеры - это отдельна большая тема. Обще представление получать можно из любой статьи для начинающих и из базовых примеров. Вещи, касающиеся конкретно панды типа подключения, передачи данных и т.д. есть в оф.мануале. А вот углубленное изучение обычно связано с конкретной техникой и тут изучать придётся больше саму технику/способ реализации чем непосредственно шейдеры.
|
|
| |
Меховой | Дата: Четверг, 31.10.2013, 13:04 | Сообщение # 8 |
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
| Огромное спасибо за ответы Добавлено (31.10.2013, 13:04) --------------------------------------------- О, и ещё вопрос. Если к одной модельке присобачены две текстуры, как работать с одной, не трогая другую? Скейл там поменять или вообще другую на её место подгрузить.
В результате гугления у меня в голове осело представление, что нужно внутри модельки определить два TextureStage'а, на каждый присобачить по текстуре и работать потом со Stage'ами. Что нужно для этого в egg'е прописать, помимо <Scalar> stage-name? Или как это сделать в Блендере, чтобы ваш YABEE потом это экспортировал?
|
|
| |
serg-kkz | Дата: Четверг, 31.10.2013, 21:53 | Сообщение # 9 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Ни чего в модели прописывать не надо. Развертку делаешь в редакторе и все, экспортировать можешь даже без текстуры. Проще потом программно назначит и менять тоже.
ООП -
|
|
| |
ninth | Дата: Пятница, 01.11.2013, 09:00 | Сообщение # 10 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Да, руление мультитекстурой осуществляется через TextureStage.
Один вариант назвал serg-kkz.
Вот другой: В Блендере одному материалу можно назначить несколько текстурных слотов - это и будут твои TS. Не забудь указать, что они используют UV Найти можно так: default_ts = TextureStage.getDefault() Это первый слот, который всегда ставится как default
all_ts = model.findAllTextureStages() Это все TS - обращаться к ним по индексу типа all_ts[0], all_ts[1] и т.д. Хочу заметить, что здесь порядок индексов обратный, т.е. то что в блендере идёт первым - здесь будет последним.
my_ts = model.findTextureStage('My_texture_slot_name') Это конкретный TS с обращением по имени. Дефолтный по имени не ищется.
Ну и можно варианты комбинировать - часть в блендере, часть - программно
|
|
| |
serg-kkz | Дата: Суббота, 02.11.2013, 00:39 | Сообщение # 11 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Кстати забыл, но вспомнил когда просмотрел ninth сообщение. В блендере просто повесь тэги с именами текстур, а загрузчик ресов проинструктируй про теги.
ООП -
|
|
| |