Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование игр, графики и искусственного интеллекта > Irrlicht. Коллизии.


Автор: Dronchik 20.6.2008, 15:56
Irrlicht. Коллизии

В этом уроке мы научимся сразу нескольким вещам. Во первых - мы научимся создавать коллизии для наших объектов. Во вторых - мы научимся загружать наши медиа-файлы из архивов zip и pk3. Приступаем! 
Сначала мы должны инициализировать графическое устройство. Это делается функцией createDevice. В предыдущем уроке расписано как провести инициализацию графического устройства с помощью функции createDevice, поэтому в этом уроке я расписывать это не буду. Параметры настраиваются по Вашему выбору. Далее мы получаем указатели на видео-драйвер, менеджер сцены и графический интерфейс. Делаем так же как и в предыдущем уроке. Далее мы должны получить доступ к файлам архива. Это мы делаем функцией addZipFileArchive.

Код

device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");


 После этого мы должны загрузить нашу карту. Карта загружается как обычный объект. 

Код

scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* q3node = 0;
if (q3levelmesh)
    q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0));


Теперь мы должны создать Triangle Selector. Без него мы не сможем создавать коллизии для нашей карты. Создание Triangle Selector делается так:
Код

scene::ITriangleSelector* selector = 0;
if (q3node)
{        
q3node->setPosition(core::vector3df(-1350,-130,-1400));
selector = smgr->createOctTreeTriangleSelector(q3levelmesh->getMesh(0), q3node, 128);
q3node->setTriangleSelector(selector);
}

Теперь устанавливаем камеру от первого лица. Это нужно для того чтобы мы могли передвигаться по карте с видом от первого лица – как в шутерах. Так как мы не установили специальных контролёров, то все передвижения будут осуществляться стрелками клавиатуры.
Код

scene::ICameraSceneNode* camera = 
    smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true);
    camera->setPosition(core::vector3df(-100,50,-150));

О функции addCameraSceneNodeFPS подробнее вы можете прочитать в документации.
Далее мы создаём коллизии. Это делается функцией createCollisionResponseAnimator. У этой функции первый параметр это selector объекта, относительно которого мы создаём коллизии. Второй параметр это то, что мы будем коллизить. В данном случаем это камера. Третий параметр это радиус эллипсоида, определяющий, сколько свободного места в позициях в 3-х мерном пространстве мы будем занимать. Четвёртым параметром устанавливаем гравитацию. Пятым устанавливаем камеру на нужную позицию(желательно камеру приподнимать на некоторое количества позиций, иначе будет эффект ползанья по карте, но ещё количество позиций для поднятия зависит от архитектуры карты). После этого мы очищаем память selector-а, добавляем аниматор для anim и очищаем память anim.
Код

if (selector)
{
    scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
        selector, camera, core::vector3df(30,50,30),
        core::vector3df(0,-3,0), 
        core::vector3df(0,50,0));
    selector->drop();
    camera->addAnimator(anim);
    anim->drop();
}

Теперь скроем курсор чтоб не мешал.
Код

device->getCursorControl()->setVisible(false);

Теперь мы установим освещение сцены. Это делается функцией addLightSceneNode. Первый параметр это родитель. Он у нас не задан, поэтому ставим ноль. Второй параметр это позиция, откуда будет исходить свет.
Код

smgr->addLightSceneNode(0, core::vector3df(-60,100,400),
        video::SColorf(1.0f,1.0f,1.0f,1.0f),
        600.0f);

Теперь для наглядности я покажу как находятся вершины для коллизий. Это не обязательный код, но он наглядно показывает работу нашего примера.
Код

//этот файрболл будет служить указателем
scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
bill->setMaterialTexture(0, driver->getTexture("particle.bmp"));
bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setMaterialFlag(video::EMF_ZBUFFER, false);
bill->setSize(core::dimension2d<f32>(20.0f, 20.0f));
//…

//а вот это мы пишем сразу после функции smgr->drawAll();
core::line3d<f32> line;
line.start = camera->getPosition();
line.end = line.start + (camera->getTarget() - line.start).normalize() * 1000.0f;
core::vector3df intersection;
core::triangle3df tri;
if (smgr->getSceneCollisionManager()->getCollisionPoint(
    line, selector, intersection, tri))
{
bill->setPosition(intersection);
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setMaterial(material);
driver->draw3DTriangle(tri, video::SColor(0,255,0,0));
}
selectedSceneNode = smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera);
if (lastSelectedSceneNode)
    lastSelectedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true);
if (selectedSceneNode == q3node || selectedSceneNode == bill)
    selectedSceneNode = 0;
if (selectedSceneNode)
    selectedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
lastSelectedSceneNode = selectedSceneNode;

На сегодня всё. Компилируйте и бегайте по карте!
ЗЫ: все используемые медиа-файлы являються стандартными медиа-файлами идущим с движком Irrlicht.
Ольшевский Андрей aka Dronchik



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)