| 8 listopada 2009 | Tutorial 2. Quake3Map |
![]() |
#include <irrlicht.h> #include <iostream> Tak jak jest już napisane w przykładzie HelloWorld w silniku irrlicht wszystko może być znalezione w przestrzeni nazw 'irr'. Żeby się pozbyć 'irr::' na początku każdej klasy mówimy kompilatorowi, że od tej chwili używamy tejk przestrzeni nazw i wtedy nie będziemy musieli ciągle pisać 'irr::'. Jest 5 innych pod przestrzeni (namespaców) 'core', 'scene', 'video', 'io' i 'gui'. W tym przykładzie jednak nie używamy 'using namespace' dla 5 innych namespaców jak zrobiliśmy to w przykładzie HelloWorld, ponieważ w ten sposób zobaczysz co można znaleść w każdym namespace. Ale jeśli chcesz możesz dodać namespace tak jak w poprzednim przykładzie. using namespace irr; Znów, żeby być w stanie użyc pliku Irrlicht.DLL musimy połączyć go z Irrlicht.lib. Możemy ustawić to w opcjach ustawień projektu, ale żeby to uprościć używamy pragmy comment lib. #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif Ok, zacznijmy więc. Znów, używamy metody main() jako początek, a nie WinMain(). int main()
{ Tak jak w przykładzie HelloWorld, tworzymy IrrlichtDevice za pomocą createDevice(). Z tą jednak różnicą, że teraz pytamy użytkownika by wybrał sterownik video jakiego chce uzywać. Urządzenie softwarowe może być za wolne, żeby narysować wielką mape Quake 3, ale dla zabawy, możemy udostępnić i taką opcję. // ask user for driver
video::E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}
// create device and exit if creation failed
IrrlichtDevice *device =
createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0)
return 1; // could not create selected driver. Weź wskaźnik do sterownika video i SceneManager żebyśmy nie musieli ciągle wzywac 'irr::IrrlichtDevice::getVideoDriver()' i 'irr::IrrlichtDevice::getSceneManager()'. video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager(); Żeby wyświetlić mapę Quake 3, najpierw musimy ją załadować. Mapy Quake 3 są zapakowane w pliki .pk3, które są niczym innym jak plikami .zip. Więc dodajemy plik .pk3 to naszego 'irr::io::IFileSystem'. Gdy już go dodamy, będziemy mogli przeczytać z plików w tych archiwach tak jakby były u nas na dysku. device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");Teraz możemy załadować mesh przez wezwanie 'irr::scene::ISceneManager::getMesh()'. Do 'irr::scene::IAnimatedMesh' powraca wskaźnik. Jak już może wiesz, mapy Quake 3 nie są na prawde zanimowane, mają jednak ogromny kawał statycznej geometrii z dołaczonymi pewnymi materiałami. Stąd 'IAnimatedMesh' zawiera jedynie ramkę, więc mamy 'first frame' animacji, która jest naszym poziomem quake i tworzy OctTree scene node z tym, używając 'irr::scene::ISceneManager::addOctTreeSceneNode()'. OctTree optymalizuje scenę, starając sie narysować tylko geometrię, która jest obecnie widoczna. Alternatywą do OctTree byłby 'irr::scene::IMeshSceneNode', który zawsze rysuje kompletną geometrie mesha bez optymalizacji. Wypróbuj tego: Użyj 'irr::scene::ISceneManager::addMeshSceneNode()' zamiast addOctTreeSceneNode() i porównaj figury proste narysowane przez sterownik video. (Jest metoda 'irr::video::IVideoDriver::getPrimitiveCountDrawn()' w klasie 'irr::video::IVideoDriver'.) Zauważ, że ta optymalizacja z OctTree jest przydatna przy rysowaniu ogromnych meshy zawierających dużo geometrii. scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
// node = smgr->addMeshSceneNode(mesh->getMesh(0));Ponieważ poziom nie był zmodelowany wokół pochodzenia (0,0,0), przetłumaczymy troszke cały poziom. To jest do zrobienia na poziomie 'irr::scene::ISceneNode' używającego metod 'irr::scene::ISceneNode::setPosition()' (w tym wypadku), 'irr::scene::ISceneNode::setRotation()', i 'irr::scene::ISceneNode::setScale()'. if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));Teraz musimy tylko ustawić kamerę żeby patrzyła na mapę Quake 3. Chcemy utworzyć kamerę kontrolowaną przez użytkownika. W silniku Irrlicht jest dostępne kilka kamer. Na przykład MayaCamera która może być kontrolowana jak kamera w Maya: Obracanie przy przyciśniętym lewym klawiszu myszki, Zoom przy przyciśniętych obu klawiszy myszki, tłumacznie z przyciśniętym prawym klawiszem myszki. To może być stworzone z 'irr::scene::ISceneManager::addCameraSceneNodeMaya()'. Ale w tym przykładzie, chcemy utworzyć kamerę , która zachowuje się tak jak w pierwszej osobie strzelanki (FPS) i dlatego uzywamy 'irr::scene::ISceneManager::addCameraSceneNodeFPS()'. smgr->addCameraSceneNodeFPS(); Kursor myszy nie musi być widoczny, więc chowamy go przez 'irr::IrrlichtDevice::ICursorControl'. device->getCursorControl()->setVisible(false); Zrobiliśmy już wszystko, więc narysujmy to. Piszemy także obecne ramki na sekundę i figury proste narysowane w nagłówku okna. Test dla 'irr::IrrlichtDevice::isWindowActive()' jest opcjonalny, ale zapobiega problemowi łapania kursora myszki przez silnik po zmianie zadań gdy inne programy są aktywne. Wezwanie 'irr::IrrlichtDevice::yield()' zapobiegnie pochłonięciu wszystkich zasobów procesora gdy okno nie będzie aktywne. int lastFPS = -1;
while(device->run())
{
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255,200,200,200));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
else
device->yield();
} Na końcu, usuwamy urządzenie Irrlicht. device->drop();
return 0;
} I to by było na tyle. Skompiluj i baw się programem. |