2quake3map 官方代码 ($sdk)\examples\02.quake3map 这个例子演示了向 irr 引擎中载入一张 quake3 地图文件以及创建一个用户控制的摄象机。它跟上一个例子 helloworld 一样简单,其实应该是更简单。它比上个例子少了 gui 部分,增加了使用压缩文件的方法,剩
2quake3map官方代码($sdk)\examples\02.quake3map
这个例子演示了向irr引擎中载入一张quake3地图文件以及创建一个用户控制的摄象机。它跟上一个例子helloworld一样简单,其实应该是更简单。它比上个例子少了gui部分,增加了使用压缩文件的方法,剩下的内容都是上个例子中已有的。至于多出来渲染方式选择菜单,帧速统计这部分代码,应该可以说跟irr彻底无关,这是任何一门编程语言入门时就练习过的内容。
irr名字空间下有五个子命名空间,core,scene,video,io,gui。在这个例子中,可能引擎作者为了让学习者熟悉各空间的负责什么功能,并没有使用usingnamespace xxx的方式声明使用子名字空间。
下面代码为例子中的选择irr驱动设备代码。在命令行界面中做了个简单的菜单选择界面,通过swicht语句判断选中的驱动类型。
video::e_driver_typedrivertype;
printf(pleaseselect the driver you want for this example:\n\
(a) opengl 1.5\n (b) direct3d 9.0c\n (c) direct3d 8.1\n\
(d) burning's software renderer\n (e) software renderer\n\
(f) nulldevice\n (otherkey) exit\n\n);
chari;
std::cin>> i;
switch(i)
{
case'a': drivertype = video::edt_opengl; break;
case'b': drivertype = video::edt_direct3d9;break;
case'c': drivertype = video::edt_direct3d8;break;
case'd': drivertype = video::edt_burningsvideo;break;
case'e': drivertype = video::edt_software; break;
case'f': drivertype = video::edt_null; break;
default:return 1;
}
该段代码在irr的例子中经常出现,在后面其他例子中,它被封装到driverchoiceconsole函数接口中,头文件driverchoice.h。
下面是使用压缩文件的代码。方法很简单,通过irr的设备指针提供的获取irr文件系统。
irr文件系统中addfilearchive接口提供了访问zip压缩文件的功能。在头文件中能看到该接口的详细说明。
device->getfilesystem()->addfilearchive(../../media/map-20kdm2.pk3);
调用addfilearchive后,解压的文件在irr文件系统中的位置与程序文件在相同目录下,但在操作系统文件系统中看不到。addfilearchive接口中有参数指定解压后的文件目录是否有效,设置无效标记,压缩文件中的文件目录将被忽略,所有解压后的文件都在同一目录下。
scene::ianimatedmesh*mesh = smgr->getmesh(20kdm2.bsp);
这行代码在helloworld中已经出现过,唯一不同的是getmesh中的文件名。20kdm2.bsp文件是从map-20kdm2.pk3文件中解压出来的。因解压后的文件位置与程序文件在同一目录,因此使用相对路径访问,就只需直接给出文件名就行了。
scene::iscenenode*node = 0;
if(mesh)
node= smgr->addoctreescenenode(mesh->getmesh(0), 0, -1, 1024);
这里添加场景节点的方法与helloworld的也很相似,不同是以前用的是addanimatedmeshscenenode添加动画网格场景节点,这次用的是addoctreescenenode添加八叉树场景节点。从节点名称上可以知道,动画网格节点,意味着该节点是会动的。这次的八叉树场景节点,是用八叉树对该节点模型进行优化,它只对静态模型有效。通常地图、地形这类静态模型体积非常大,使用的顶点数极其庞大,同时将所有顶点数据传递给显卡处理,对带宽资源是种浪费,同时也让显卡对不需要显示的部分也进行了大量运算,这是对硬件资源使用的浪费。使用八叉树优化后,通过对八叉树的裁剪,得出每次显示区域的顶点数据,只传送该部分数据给显卡,可以明显提高显示速度。irr通过八叉树节点把这些优化功能全做了。
if(node)
node->setposition(core::vector3df(-1300,-144,-1249));
设置场景节点的位置坐标。这里同样在helloworld中出现过。
smgr->addcamerascenenodefps();
这行看起来很眼熟,就是比原来见到的多了fps这个尾巴。熟悉游戏的人,一看fps就知道只的是什么。因此这行是添加了一个fps视觉的摄像机。玩fps游戏时是如何控制摄像机移动的,这里也一样。只需addcamerascenenodefps这么一句,就已经把fps摄像机及移动方式都解决了。
device->getcursorcontrol()->setvisible(false);
这句,用词霸查出每个单词的意思,连起来一读也就明白。irr设备获取光标控制,设为光标不显示。fps游戏里本来就不需要鼠标光标,这里把鼠标光标关闭,没什么可奇怪的。
intlastfps = -1;
while(device->run())
{
if(device->iswindowactive())
{
driver->beginscene(true,true, video::scolor(255,200,200,200));
smgr->drawall();
driver->endscene();
intfps = driver->getfps();
if(lastfps != fps)
{
core::stringwstr = lirrlicht engine - quake 3 map example [;
str+= driver->getname();
str+= ] fps:;
str+= fps;
device->setwindowcaption(str.c_str());
lastfps= fps;
}
}
else
device->yield();
}
这段代码跟原来见到的仍然很相似,就是中间多了几行。仔细看看多出来的这几行,就是设计了一个计数器,用来记录显示帧速。irr设备提供的getfps()接口可以直接获取当前的显示帧速,因此不再需要用计时器和累加器在循环里进行帧速的计算,这点很方便。 core::stringw字符串类型,看到前面的名字空间,应该知道这是irr自己的字符串类型。为何不用stl字符串?我也觉着奇怪,在后面还不断的发现很多常用的泛型,仍然不是stl而是irr自己的。不过看了它们的代码后,感觉他们比stl的更简洁写,少了一些不常用的东西,也增加了一些stl没有的功能。可能是开始写irr时,stl还没成c++标准的一部分,要么是stl用在游戏引擎中速度方面不够理想。不过irr的字符串类型我挺喜欢的,它可以通过+=运算符,直接将数字、字符串直接加入原有的字符串,而且字符串类型并不区分宽窄,它会在本地字符集和unicode之间自动转换,挺方便的。
将处理好的字符串传递给setwindowcaption,显示在窗口标题栏上。
程序编译好后,就可以进去游览下这个quake3map了,操作完全是fps操作方式,退出时需要按alt+f4。就这么几行代码,就实现了fps游戏的最基本样子,感觉的确有点振奋人心。似乎用它做出自己的游戏并不难。