Демо игра "Танки"
|
|
Lunar | Дата: Понедельник, 26.07.2010, 10:56 | Сообщение # 1 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| Всем привет. Чисто ради изучения движка, пытаюсь сделать игру типа "Танки онлайн" http://tankionline.com/ru/ (пока без онлайна :)). После прочтения описания ODE на форуме, решил что для онлайн игры физику надо в минимуме писать самому, для одинакового расчета на разных машинах. То что у меня получилось во вложении. Вот собственно и вопрос: Как сделать так, что-бы танк на наклонной поверхности разворачивал корпус параллельно этой плоскости но естественно учитывал угол H (направление движения). Попытка начала решения есть но, танк по разному наклоняется в зависимости от его вектора движения. По одной поверхности танк нормально подымается, на другую носом роет...
|
|
| |
ninth | Дата: Понедельник, 26.07.2010, 12:27 | Сообщение # 2 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Для начала, лучше перейди от работы с углами к работе с векторами, раз уж связался с самописной физикой ) Похоже, что проблемы в том, как в панде считаются углы (-180;180) а не (0;360) А так, чуть позже более подробно гляну.
|
|
| |
ninth | Дата: Понедельник, 26.07.2010, 12:41 | Сообщение # 3 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Собственно суть в том, что тебе надо расположить корпус танка в некоторой плоскости так чтобы он был максимально параллельно поверхности, но дело в том, что в одной плоскости гарантированно будут лежать только три точки (а не четыре как у тебя), так что основная задача найти эти три точки, после этого строится перпендикуляр к найденной плоскости и в соответствии с этим располагается твой танк.
|
|
| |
Lunar | Дата: Понедельник, 26.07.2010, 17:03 | Сообщение # 4 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| ninth, Ну физика это я громко сказал, легкая имитация... Маленькое уточнение. Четыре сферы отвечают только за коллизию с препятствиями. По Z я двигаю танк только с помощью луча CollisionRay, через него вычисляю Z и через него же вычисляю нормаль, которая выдается в радианах, перевожу в градусы и поворачиваю танк по углам P и R (строки 316-329). Но тут видимо можно как-то повернуть и по H но с учетом поворота танка... Я сделал еще один луч позади танка... Получается что надо сделать три луча?
Сообщение отредактировал Lunar - Понедельник, 26.07.2010, 18:41 |
|
| |
ninth | Дата: Вторник, 27.07.2010, 08:50 | Сообщение # 5 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Мда... посмотрел более внимательно ) Пока всё не зашло слишком далеко, советую пересмотреть подход к структуризации кода - вынеси танк в отдельный класс хотя бы ) Первое, что следует сделать - это работать не с моделью танка, а с пустым узлом, на который навешивать уже модель и всё остальное т.к. при смене масштаба или ориентации модели вероятно придётся корректировать ещё пачку переменных, а если ты будешь работать (вращать, перемещать и т.д.) с пустым узлом единичного масштаба, то на то как сделана модель будет глубоко фиолетово. Второе, если на танке не планируется анимации (имеется ввиду скелетная или вершинная), то использовать Actor не нужно - грузи как обычную модель Третье - теги не предназначены для хранения постоянно обновляемых переменных. Одно преобразование из строк в значения с плавающей запятой и обратно чего стоят, обычно такие переменные хранят как свойства класса. Четвёртое - не стоит использовать try except до финального варианта - это глушит другие ошибки, я так понимаю, ты сделал это для обхода проблемы с пустым списком entries? Тогда сделай if entries: т.к. пустой список == False К вопросу ориентации - попробуй так: n = entries[0].getInto().getNormal() q = Quat() q.setFromAxisAngle(self.a,n) self.tank.setQuat(q) здесь self.a - это переменная - угол поворота танка. Естественно, в другом месте он тогда уже не должен поворачиваться, т.е. setH() у тебя не должно быть задействовано.
|
|
| |
Lunar | Дата: Вторник, 27.07.2010, 11:10 | Сообщение # 6 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| ninth, Спасибо! Про класс пока не думал, решил только набросать, потом раскидывать по классам... такой подход к разработке у меня когда ничего изначально не известно про приложение, а запустить побыстрее хочется :). С пустым узлом это дело хорошее, переделаю. Про Actor отдельное спасибо, а то все время ругался что танк не чарактер. Теги использовал как самый быстрый вариант разработки в данном случае (опять же для теста), try except дело такое как-то сразу появился потом не стал изменять, но предложение твое возьму на вооружение :). И самое главное - ориентация то что я и хотел... щас засяду буду пробовать...
|
|
| |
Lunar | Дата: Вторник, 27.07.2010, 12:57 | Сообщение # 7 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| Ну в общем я сделал поворот как ты рекомендовал остальное не правил... Правда добавил некоторые дебаг сообщения в окне, сферы азимутов и ограничил диапазон угла по H до 360 градусов. Танк стал пытаться повторять поверхность но что-то не очень правдиво у него выходит :). Посмотришь на досуге? Добавлено (27.07.2010, 12:52) --------------------------------------------- Опытным путем выяснил, что если от текущего угла P танка отнимать 15 градусов то на наклонной плоскости танк поворачивается с корректным повторением наклона... но по прямой поверхности естественно заваливается вперед на теже 15 градусов.. откуда эта погрешность вылазит не могу понять... Code n = entries[0].getInto().getNormal() q = Quat() q.setFromAxisAngle(self.a,n) self.tank.setQuat(q) self.tank.setP(self.tank, -15) Добавлено (27.07.2010, 12:57) --------------------------------------------- нашел... надо делать так Code n = entries[0].getInto().getNormal() q = Quat() q.setFromAxisAngle(self.a,n) self.tank.setQuat(q) self.tank.setP(self.tank, -angleP) где -angleP это угол наклона плоскости P по которой ездим... уфф вроде заработало... теперь надо все привести в порядок. Спасибо ninth за алгоритм, очень признателен Выяснил один интересный факт кому может пригодится, такой код тормозит очень сильно (выполняется в обработчике taskMgr) Code ang=(self.hprTank.getHpr()-self.hprPole.getHpr()) ttt=u"Полигон: H=%.2f, P=%.2f, R=%.2f\nТанк: H=%.2f, P=%.2f, R=%.2f\nРазница: %s\nq=%s"%(angleH,angleP,angleR,self.tank.getH(),self.tank.getP(),self.tank.getR(),ang,q) self.textObject.setText(ttt)
Сообщение отредактировал Lunar - Вторник, 27.07.2010, 13:14 |
|
| |
ninth | Дата: Вторник, 27.07.2010, 14:13 | Сообщение # 8 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Насчёт onscreentext - это официально в мануале сказано, что он тяжёлый т.к. каждый раз текст рендерится... можно попробовать перегнать текст в родной формат, но не уверен, что сильно поможет. Ещё можно устанавливать tank.lookAt(tank.getPos()+normal), только тогда ориентацию осей надо менять - поворот по R, а движение по У
|
|
| |
Lunar | Дата: Вторник, 27.07.2010, 14:59 | Сообщение # 9 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| Спасибо за советы. Но пока меня так устраивает как ты посоветовал в начале, надо только плавности добавить и сойдет :). Перепишу это все более культурно и выложуДобавлено (27.07.2010, 14:59) --------------------------------------------- Кстати а посоветуй как сделать так что-бы над моделью (танком) текст располагать, ну типа ник водителя танка.
|
|
| |
ninth | Дата: Вторник, 27.07.2010, 15:39 | Сообщение # 10 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| если хочешь просто как спрайт - можешь посмотреть в сторону billboard если на экране, то нужно делать проекцию танка в экранные координаты
|
|
| |
Lunar | Дата: Среда, 28.07.2010, 11:27 | Сообщение # 11 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| Вот что на данный момент получилось Разбил предварительно на классы, добавил класс бота пустой без физики и логики но с шарами ля коллизий и лучом. Вопрос по поводу Quote (ninth) Первое, что следует сделать - это работать не с моделью танка, а с пустым узлом, на который навешивать уже модель и всё остальное т.к. при смене масштаба или ориентации модели вероятно придётся корректировать ещё пачку переменных, а если ты будешь работать (вращать, перемещать и т.д.) с пустым узлом единичного масштаба, то на то как сделана модель будет глубоко фиолетово. А собственно коллизии привязывать к пустому узлу или все таки к танку. Можно по подробнее, кстати что-то приаттачить один узел к другому у меня не получается, тупо снимаю координаты и позиционирую. Можешь подробнее рассказать или отправить к примеру? Вроде-бы тут был пример с пандой... но там только движение было. Не сочти за труд.
|
|
| |
ninth | Дата: Среда, 28.07.2010, 12:46 | Сообщение # 12 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Коллизии лучше привязывать тоже к узлу. Суть в том, что чайлды повторяют масштаб, позицию и ориентацию родителей и только после этого применяют свою. К примеру, тебе моделер сделал мега танк, но развернул его задом наперёд или вообще боком, так что тебе приходится программно менять поворот танка... и код, отвечающий за движение т.к. теперь у тебя перед не по оси +Х а по оси -Х или вообще по У. А если ты не в том масштабе сделал, то ещё и скорость перемещения придётся корректировать. Пустой же узел всегда имеет один и тот же масштаб и поворот, а прилепленный к нему танк ты можешь вертеть как угодно - хоть на башню поставить и всё равно он будет двигаться за этим "узлом". привязка осуществляется с помощью my_node_path.reparentTo(my_other_nodepath), да-да render тоже является всего лишь узлом сцены. Code mdl1 = loader.loadModel("smiley") mdl2 = loader.loadModel("smiley") mdl2.reparentTo(mdl1) mdl1.reparentTo(render) mdl2.setX(10) mdl1.setZ(20)
|
|
| |
Lunar | Дата: Среда, 28.07.2010, 14:56 | Сообщение # 13 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| Ну вот раскидал все на классы, привязал танки к пустым нодам. Что скажеш. На твоих советах уже нормальная тема получается. А теперь о непонятном - как сделать коллизии между танками, маякни куда копать если не трудно.
|
|
| |
ninth | Дата: Среда, 28.07.2010, 15:41 | Сообщение # 14 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| код позже гляну, коллизии между объектами это setIntoBitMask и setFromBitMask. into - в объект можно врезаться, from - объект сам может врезаться http://panda3d.org.ru/publ/1-1-0-29
|
|
| |
Lunar | Дата: Среда, 28.07.2010, 19:09 | Сообщение # 15 |
Рядовой
Группа: Пользователи
Сообщений: 18
Награды: 0
Репутация: 0
Статус: Offline
| В общем вот что за сегодня получилось. Танки как тараканы бегают по карте. своим танком их можно толкать, но они сами не толкаются между собой. Если кто-то объяснит до конца как это сделать буду счастлив, а то уже мозг сломал не могу допереть какую им маску ставить. И еще из-за просчета колизий, сильно падает FPS смотрел через pstats.exe, тоже нужна помощь а то на нетбуке падает с 150 fps до 16-24. Но вообще я доволен
|
|
| |