[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Пара вопросов общего плана
МеховойДата: Вторник, 29.10.2013, 11:32 | Сообщение # 1
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
Всем здрасьте smile Найдётся пять минут для чайника? Я с Пандой пока ещё далёк от близкой дружбы и навскидку не сумел найти ответа на пару вопросов.

Мне нужно сделать игру-старомодный данжен краулер с РП-элементами. Нечто вроде лабиринта с головоломками. Пока что дело у меня дошло только до отрисовки самого лабиринта из тайлов типа "пол", "пол со стенкой", "угол" и так далее. Скрипт даже заработал (чем немало меня удивил) и исправно читает из текстового файла данные на каждый тайл и рисует по ним лабиринт. Вот код:
Код
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. Как определяется.

Заранее благодарен smile

P.S. Архив с накоженным приложил на всякий случай.
Прикрепления: someshit.rar (1.39 Mb)
 
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")
Прикрепления: 4216669.jpg (57.6 Kb)
 
МеховойДата: Вторник, 29.10.2013, 16:48 | Сообщение # 3
Рядовой
Группа: Пользователи
Сообщений: 4
Награды: 0
Репутация: 0
Статус: Offline
Спасибо за советы!

Вы это... Скажите, если я вдруг стану слишком уж навязчивым, потому как вопросов у меня будет МНОГО.  redface Рабочий код я могу сочинить методом научного тыка, но когда я не понимаю, что конкретно делает каждая строчка, мне становится грустно и я начинаю задавать вопросы. С английского не всегда удаётся адекватно понять.

Нанизал все тайлы на общий узел, clearModelNodes() и flattenStrong() к нему применил, впечатлился показанным analyze'ом шести узлам вместо сорока двух. Я правильно понял, он переписал все вершины и их параметры вместо отдельных узлов в один общий, а сами отдельные погрохал? Обращаться к тем NodePath'ам, которые я в списке сохранял, теперь бессмысленно?

Цитата
Проще всего коллизионную геометрию сделать в той же модели. В простых случаях этот же способ будет и самым быстрым по обработке. Для больших территорий разговор отдельный - там для производительности потребуется геометрию октрифицировать.

Сделать коллизионную геометрию в той же модели - это прямо внутри egg'а определить коллайдящие полики, что ли? А как это сделать? Модельки рисовал в Блендере, с ним тоже пока не очень знаком. (( И что означает матерное с виду слово "октрифицировать"?..

Ограничить передвижение математически на самом деле хорошая идея, тем более что у меня планируется передвижение игрока "квадратами", типа шаг на тайл вперёд/шаг на тайл назад без возможности оглядываться мышкой, но я хочу всё-таки коллизиями. Вопрос личных предпочтений, да. Если так и не выйдет - перепишу на расчёт положения по координатам, не проблема.

С коллизинной системой Панды я знаком вроде нормально. Во всяком случае, в цепочке узел-геомформа-траверсер-хэндлер сложностей вроде не вызывает ничего, включая маску-внутрь и маску-наружу. Меня только CollisionRay смущает, я его в виде геометрии представить не могу sad


Сообщение отредактировал Меховой - Вторник, 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
У панды есть несколько отличающихся и в то же время пересекающихся механизмов для задания коллизий, так что если где-то увидишь другой способ - не пугайся )

Цитата Меховой ()
Ограничить передвижение математически на самом деле хорошая идея, тем более что у меня планируется передвижение игрока "квадратами", типа шаг на тайл вперёд/шаг на тайл назад без возможности оглядываться мышкой, но я хочу всё-таки коллизиями. Вопрос личных предпочтений, да. Если так и не выйдет - перепишу на расчёт положения по координатам, не проблема.

Так, я что-то не совсем понял, а зачем тебе тогда вообще коллизии, если у тебя всё настолько жёстко задано, при таком передвижении игрок по-идее вообще не должен стен касаться, или я не так понял? Или тебе вообще для детекта объектов мышкой?

Цитата Меховой ()
я его в виде геометрии представить не могу

Странно, не знаю тогда даже как пояснить ) Ну луч и луч. Представь лазерную указку, только она будет пятно оставлять (детектить) не только на первой стенке, но и на остальных, расположенных дальше, и на обратной стороне стенки тоже.
Прикрепления: 1686735.jpg (27.5 Kb)
 
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
Огромное спасибо за ответы  happy

Добавлено (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 с обращением по имени. Дефолтный по имени не ищется.



Ну и можно варианты комбинировать - часть в блендере, часть - программно
Прикрепления: 1748861.jpg (21.4 Kb)
 
serg-kkzДата: Суббота, 02.11.2013, 00:39 | Сообщение # 11
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
Кстати забыл, но вспомнил когда просмотрел ninth сообщение. В блендере просто повесь тэги с именами текстур, а загрузчик ресов проинструктируй про теги.

ООП  -  
 
  • Страница 1 из 1
  • 1
Поиск: