Коллизия в играх как сделать
Делаю игру на JavaScript на Canvas, сделал передвижение персонажа и гравитацию, но никак не могу сделать правильную коллизию, такую, что она работала при слишком больших/маленьких размерах блока. Также нужна сторона, с которой персонаж коллизит с блоком
Код для определения коллизий:
Код для определения сторон:
Проблема в том что если персонаж 50 на 50 пикс, то при колизии с блоком 200 на 10 пикселей, боковой колизии не происходит.
Вопрос срочный, любая помощь приветствуется.
Требуется уточнение: какие подходы к решению пробовались, и соотв. - что именно в попытках решения не устраивает / не получается? (существует множество способов определения столкновения фигур, и непонятно какой из них тут назван "правильным")
Могу дать ссылку на проект, чтобы вы его посмотрели. В нем работает коллизия и определение сторон, но, во-первых код получается запутанным, во-вторых при слишком маленьких\больших сторонах блока, персонаж просто проваливается
Мне (как и другим участникам, особенно тем кто впоследствии будет искать решение) интересен именно вoпрос и ответы на него, а не какой-то-там проект по ссылке. поэтому, надо добавить конкретики прямо сюда (в вoпрос), и желательно словесным описанием - а не заменять конкретику ссылками на внешние ресурсы которые через некоторое время могут пропасть. В первую очередь, тут очень важным моментом является используемый способ определения столкновений (его можно описать и словами, и формулами, и минимальным кодом - форма не так важна, лишь бы она была понятна).
Чтобы правильно определить сторону коллизии надо еще иметь координаты этих объектов на предыдущем шаге: знать было ли пересечение по осям до коллизии. Если пересечение по Y было, то коллизия могла быть только право-лево, и наоборот. Если пересечений не было вовсе, то коллизия произошла углами - одновременно по сторонам верх-низ и право-лево. Шаг смещения объектов не должен быть больше половины ширины или высоты одного из объектов.
1 ответ 1
Примечательна здесь только функция detectCollision . Все пояснения добавил в комментариях к этой функции. Дополнительно надо иметь в виду, что неточное обнаружение коллизии здесь возможно если дискретный шаг смещения объектов больше половины ширины или высоты одного из объектов. Но эту корректировку можно добавить в код, имея положение на предыдущем шаге.
При коллизии оба объекта меняют направление движения по соответствующей координате. Поэтому если один объект догоняет другой, то эффект выглядит неестественно. Здесь нужны дополнительные доработки.
Для того, чтобы определить каким бортами было соударение можно задать условие if(dx > 0) rect1.sideX = 'left'; .
@yar85 я не понял. Разделить на независимые асинхронные циклы? Смещение объекта равно расстоянию, а кадр и так определяет единицу времени. Это расстояние (sx, sy) и есть скорость. И если объект на пути будет меньше этого шага, то рассматривая результат этого шага, будет непонятно откуда было начато это пересечение (ведь центры объектов могут поменяться местами). В этом случае можно изучить предыдущее положение по заданной оси и согласно им вычислить стороны "вхождения" в пересечение. Однако может быть и такое, что за один шаг оба объекта минуют друг друга если каждый из них меньше шага.
Дробить же шаг каждого кадра по идее не желательно, кадр - минимально возможная и оптимальная единица для вычисления новых координат, обработки проверки и так далее. Можно, конечно, после возникновения пересечения ретроспективно пройтись в цикле, кратном одному пикселю, например, для изучения момента вхождения, но зачем?)))
Плюс, отделение вычислений позволяет оптимизации. Например, далеко не всегда нужен пересчет на каждом кадре (разрядив частоту вычислений можно ощутимо поднять производительность, не жертвуя кадрами). Альтернативно, можно определять пропуск итераций по аргументу коллбэка rAF и времени последнего кадра, но это лишние вычисления: иногда такое допустимо, а иногда нет. имхо, не стоит говорить что добавление вычислений это всегда хорошее решение (лучший код - тот, который не выполняется). Упрощение/сокращение работы кода - то, к чему стоит стремиться, для быстрых и плавных анимаций, имхо.
Изначально модель не имеет никакой физики, через неё можно пройти насквозь. Коллизию добавляют, чтобы ты не мог пройти сквозь модель или упасть под землю, короче физика столкновения с объёктами.
Офигенная аватарка бро XD
Это сложно объяснить, есть текстуры которые видишь и можешь упереться, так вот, если ты проходишь сквозь текстуру то это отсутствие коллизии
Когда говорят что застрял в текстурах это распостраненное заблуждение, на самом деле застрял в коллизии вернее будет, текстуры это всего лишь картинка поверх коллизии
Это такая штука, ты может ходить сквозь текстурки) Например ты на машине едишь и просто сквозь других машин или домов
Для начала следует обозначить пару моментов. Во первых, у вас в сцене должен быть 1 объект и соответственно 1 NiTriShape в NifSkope. Для объектов с большим количеством NiTriShape, данный способ не подходит. Во вторых, не советую начинать с импорта модели через Obj формат, как это показано в оригинале. В этом случае, у вас могут сбиться параметры сглаживания и выйдет не совсем то, чего вы ожидали.
Итак, начнем. Запускаем сцену с вашей моделью в 3Ds Max. У меня пусть будет стол. В начале следует его поставить в начало осей координат. для этого выбираем инструмент Move и значение осей X и Y сбрасываем на 0. Ось Z необходимо отредактировать самим, иначе начало осей координат будет находиться
посередине модели.
После этого можем экспортировать модель в Nif формат. Настойки экспорта:
Далее нам понадобится Nif, содержащий информацию о коллизии и текстурах. Можете взять его отсюда [attachment=14702:CollisionMesh.rar]
Открываем нашу модель и выделяем ветку NiTriShape. Нажимаем ПКМ по ней, далее Block -> Copy Branch.
Затем открываем файл из архива, выделяем BSFadeNode, нажимаем ПКМ, Block -> Paste Branch.
Свой nif файл можете после этого закрыть, далее пойдут работы только с CollisionMesh.nif
Прежде чем продолжить, отредактируйте твою ветку NiTriShape. удалите из неё NiMaterialProperty и BSLightingShaderProperty. Для этого выделите эти ветки и нажмите на Block -> Remove Branch. В итоге в вашем NiTriShape должно остаться только NiTriShapeData.
Далее выделите NiTriShape, промотайте Block Detalis в самый низ и найдите вкладку Property или BSProperty. Разверните её и вместо None в первой вкладке напишите номер дефолтной ветки BSLightingShaderProperty, которая была сразу в файле.
Это действие перенесет правильно настроенную ветку с текстурами к вашей модели. Далее пройдите во вкладку BSShaderTextureSet и пропишите пути к текстурам. Прописывается путь к непосредственно текстуре и нормал мапу - текстура_n. Путь к текстуре должен выглядеть так - textures\[папка вашего мода, если есть]\texture.dds. Удалите лишние строчки. У меня получилось вот так.
Далее перейдем непосредственно к Коллизии. Сохраните свою модель в папку с моделями скайрима. Data\Meshes\[ваша папка].
После этого нажмите ПКМ по модели и выберите Transform -> Scale Verticles. Установите значение на 0.1 и нажмите Scale.
Затем нажмите снова ПКМ по модели и выберите Havok -> Create Convex Shape. Так же установите значение на 0.1.
Это действие создаст ветвь 9 bhkCollisionObject во вкладке 0 BSFadeNode. скопируйте вашу Коллизию, щелкнув по 9 bhkCollisionObject ПКМ и выбрав Block -> Copy Branch. После этого загрузите сохраненный перед созданием коллизии Nif файл.
Удалите из вкладки BSFadeNode bhkCollisionObject
Теперь нажмите на BSFadeNode ПКМ -> Block -> Paste Branch. Далее выберите в окне Block Detalis BSFadeNode найдите строчку Collision Object и вместо None вбейте туда номер строчки вашего колизиона.
Далее кликните ПКМ по модели, выберите flags, в выпадающем меню выберите Continue и нажмите Accept.
Сохраните файл. Во вкладке bhkCollisionObject будет bhkConvexVerticlesShape. Это и есть ваш коллизион. Далее зайдите в конструктор, создайте там новый объект, поместите в игру и зайдите проверить, работает ли коллизия.
Как видите, мой бомжеватый норд вполне вальяжно устроился на столике, значит коллизия в порядке.
В данном уроке мы рассмотрели, как экспортировать в игру статические объекты с адекватным отображением что текстур, что коллизий. На этом урок подошел к концу. Удачи в творчестве, до встречи.
PS.
Данный процесс создания коллизии для Скайрима несколько грязный и ограниченный, но пока что другого и менее геморного варианта не нашел. впоследствии выложу статью по внедрению своего оружия в игру, уже собственного производства. И буду искать варианты по созданию коллизий для статиков с меньшими ограничениями.
Антон Степура запись закреплена
Как работает коллизия 3д персонажей? (лучше видео-руководство)
После провальной 2д игры, решил просто дальше изучать движок уже под 3д. Разобрался более менее с анимацией, включил коллизию на меше и удивился)))
В общем я понял что это не так работает. А как? Банально, если персонаж сел, а капсула торчит и принимает урон, или персонаж упал или лег и т.д. Как сделать через костыли, я уже знаю, весь прошлый проект из них собран) пора учиться правильно.
На запросы, выдает либо коллизию для статичных объектов, либо кучу базовой инфы по анимации. Помогите найти видео урок по коллизии персонажей.
капсула для перемещения
А вот сам персонаж может получать урон, главное просто с каналами коллизии не напутать.
С упал\лег все весьма плохо, так как стандартно капулу не повернешь, а значит ноги\голова будет торчать. Можно конечно стопить его вручную, когда пытается лезть не туда когда надо. Но это тоже слегка костыль
Читайте также: