MS3D model 的Frame count
通常在载入ms3d动画序列后, 无法播放动画或动得极缓慢,调用IAnimatedMesh::getFrameCount()取得的FrameCount也比MilkShape里的FrameCount大很多, 这是为什么呢? 请看"niko"的原话:The reason why the frame number is multiplied is because using only 300 frames, your animation would not be smooth at all. By multiplying the frame number with (for example here 40), it is getting smoother. By the factor 40, in this case. I should add a comment on this in the documentation.
float fFactor = getFrameCount()/effective number of frames of your animation;
所以在setFrameLoop时必须在1*fFactor~RealFrameCounts*fFactor之间, 要不然就有各种怪异的现象.
e.g.
If get total numbers of frames with getFrameCount (ex : 12000)
divide the getFrameCount by the effective number of frames of your animation (ex : 12000/300 = 40)
multiply this factor (40) by the number of the frame you want to display (in your example : 40*1 and 40*31) and you'll get :
Code:
model1->setFrameLoop(40,1240);
That's all...
posted @ 2006-07-23 21:42 安徽飞雪游戏工作室 阅读(310) 评论(0)
编辑
下面创建的是由start0.bmp - start9.bmp 组成的材质动画
// 加载材质
core::array<video::ITexture*> startmovie;
for (int i = 0; i < 10; i++)
{
char path[256];
sprintf(path, "../media/start%d.bmp", i);
video::ITexture* tex = pDriver->getTexture(path);
startmovie.push_back(tex);
}
// 创建动画
anim = pSceneMgr->createTextureAnimator(startmovie, 40);
// someNode 为被渲染的节点
someNode->addAnimator(anim);
posted @ 2006-07-23 21:42 安徽飞雪游戏工作室 阅读(577) 评论(3)
编辑
design question : inherit from IGUIContextMenu(Extend/Custom GUI)
Create GUI out of XML files
Transparent image GUI button
ComboBox -- Opaque Background
General FAQ Page
posted @ 2006-07-23 21:03 安徽飞雪游戏工作室 阅读(2187) 评论(0)
编辑
很多游戏都有Credits show, 如何实现呢 ? 请看:
Easy scrolling credits, just stick this in your main loop and replace ITEXTUREHERE with your itexture pointer, and replace driver and device etc if you use custom-named variables:
| Code: |
u32 time = device->getTimer()->getTime(); driver->draw2DImage(ITEXTUREHERE, position2d<s32>((driver->getScreenSize().Width - ITEXTUREHERE->getOriginalSize().Width)/2, ((time/20)%(driver->getScreenSize().Height+ITEXTUREHERE->getOriginalSize().Height))-ITEXTUREHERE->getOriginalSize().Height)); |
To speed it up or slow it down, decrease (faster) or increase (slower) this part:
posted @ 2006-07-23 21:02 安徽飞雪游戏工作室 阅读(182) 评论(2)
编辑
[http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=12238]
So far my contributions for this community had been rather miserable, so I decided it's time to make up for it by posting piece of code from my own test application. Maybe it's not as decent as I would like it to be, but I nonetheless decided to share it with you. It's a method for moving an entity through the scenery, setting appropiate animation loop and detecting whether it collides with the scenery or not. The method itself goes like this:
Code:
void Character::Walk(float speed, ISceneCollisionManager* colmanger, ITriangleSelector* selector)
{
core::vector3df OriginalPosition;
core::vector3df TranslationVector;
core::triangle3df triout;
bool isfalling = true; //set it to "false" if you want the gravity off
OriginalPosition=this->position;
TranslationVector.X=((float)(cos(this->heading*PI/180))*speed);
TranslationVector.Z=-((float)(sin(this->heading*PI/180))*speed);
this->position = colmanger->getCollisionResultPosition(selector, OriginalPosition, vector3df(10,50,10), TranslationVector, triout, isfalling, 10);
this->model->setPosition(position);
if (this->state!=STATE_WALK)
{
this->state=STATE_WALK;
this->model->setMD2Animation("run");
this->model->setLoopMode(true);
}
}
"This" refers to character type object. "State" is an integer value that indicates in what state the entity is at the moment. For now I've only defined two states, namely STATE_WALK the character is in when walking and STATE_STAND the character type object is in when it's not moving. "Model" is an Irrlicht scene node representing the entity. For stopping characters' movement, I'm using this method:
Code:
void Character::Stop()
{
this->state=STATE_STAND;
this->model->setMD2Animation("stand");
}
I hope this post will be of some help to newcomers who want to create their own Irrlicht-based 3-person type game without resorting to external libraries (like Newton) but don't know where to start.
以上主要是调用ISceneCollisionManager::getCollisionResultPosition来得到人物与3d world碰撞后的新position。
This can be used for moving a character in a 3d world: The character will slide at walls and is able to walk up stairs.
posted @ 2006-07-23 21:01 安徽飞雪游戏工作室 阅读(203) 评论(0)
编辑
在Irrlicht中的人物添加武器 其实相当简单:找到关节然后attach上去就ok了。
scene::IAnimatedMesh* pManMesh = smgr->getMesh("../../media/noblade.ms3d");
scene::IAnimatedMeshSceneNode* pnMan = smgr->addAnimatedMeshSceneNode( pManMesh );
pnMan->setMaterialTexture(0, driver->getTexture("../../media/skin.jpg"));
pnMan->setMaterialFlag(video::EMF_LIGHTING, false);
pnMan->setPosition(core::vector3df(50,50,-60));
pnMan->setScale(core::vector3df(5,5,5));
pnMan->setAnimationSpeed(25*10);
// this is a scene node where we can attach things to joints
scene::ISceneNode* pJointNode = pnMan->getMS3DJointNode("leftWeaponJoint");
if(pJointNode)
{
scene::IAnimatedMesh* pWeapon = smgr->getMesh("../../media/blade.ms3d");
scene::IAnimatedMeshSceneNode* pnWeapon = smgr->addAnimatedMeshSceneNode( pWeapon );
pnWeapon->setScale(core::vector3df(2,2,2));
core::vector3df jointPos = pJointNode->getAbsolutePosition();
//pnWeapon->setPosition(jointPos);
pJointNode->addChild( pnWeapon );
printf("Join weapon to body, x=%d, y=%d, z=%d\n", jointPos.X, jointPos.Y, jointPos.Z);
}

posted @ 2006-07-23 21:00 安徽飞雪游戏工作室 阅读(452) 评论(1)
编辑
假设我们要使某一24位色的Texture(不带Alpha)对应的特定颜色在render时透明,可以先调用makeColorKeyTexture创建一个 1 bit alpha channel of the texture,然后把MaterialType设为EMT_TRANSPARENT_ALPHA_CHANNEL就搞定了。废话不多说了, 请看代码:
scene::IAnimatedMesh* meshRabbit = smgr->getMesh("../../media/mouse22.ms3d");
scene::IAnimatedMeshSceneNode* anodeRabbit = smgr->addAnimatedMeshSceneNode(meshRabbit);
if(anodeRabbit)
{
driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT ,true);
irr::video::ITexture* pTexture = driver->getTexture("../../media/wenli.jpg");
driver->makeColorKeyTexture(pTexture, core::position2d< s32 >(300,30));
anodeRabbit->setMaterialTexture(0, pTexture);
anodeRabbit->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL );
anodeRabbit->setPosition(core::vector3df(70,20,-60));
anodeRabbit->setMaterialFlag(video::EMF_LIGHTING, false);
anodeRabbit->setRotation(core::vector3df(0,180.0f,0));
anodeRabbit->setAnimationSpeed(25*30);
}
当然如果Texture本身就带alpha channel的话就不需要再makeColorKeyTexture了,另外还有两种模式可以尝试: EMT_TRANSPARENT_ADD_COLOR 和 EMT_TRANSPARENT_ALPHA_CHANNEL_REF。
posted @ 2006-07-23 20:59 安徽飞雪游戏工作室 阅读(254) 评论(0)
编辑
irrlicht有自己的ui系统,不用再去找其他的ui系统来挂载了.下面介绍一下irrlicht
UI系统的基本使用方法.我用一个hello world的工程来讲解.因为代码量并不多,就将所有的代码都贴出来了.
#include <windows.h>
#include <irrlicht.h>
//头函数,因为将调用GetWindowsDirectory()函数获得系统目录所以包含了<windows.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
//名字空间,不用每次都用irr::等来声明
IGUIEditBox *edtName = 0;
IGUIButton *pbtn = 0;
CGUITTFont *pFont;
IGUIListBox* listbox = 0;
IGUISkin* skin;
IrrlichtDevice *Device;
//用到的几个全局变量,CGUITTFont是从IGUIFont派生出的类,非irrlicht自带.用于中文支持.不用中文的话,定义为IGUIFont即可
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(SEvent event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
switch(event.GUIEvent.EventType)
{
case EGET_BUTTON_CLICKED://这里只处理了按钮点击的消息
if (id == 101)
{
listbox->addItem(edtName->getText());
//点发送按钮时,把editbox里的内容加到listbox中;
return true;
}
break;
}
}
return false;
}
};
//自定义的消息处理类,重载了OnEvent()函数,demo将用这个类来出理消息.注意后面会调用一个setEventReceiver()函数来设定消息处理类.
int main()
{
Device =createDevice( video::EDT_DIRECT3D9, dimension2d<s32>(640,480), 16,false, false, false, 0);
//main函数开始,创设备.
Device->setWindowCaption(L"鬼火引擎,第一个例子");
IVideoDriver* driver = Device->getVideoDriver();
ISceneManager* smgr = Device->getSceneManager();
IGUIEnvironment* guienv = Device->getGUIEnvironment();
smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
//添加了一个摄像机,位置和观察点分别为(0,30,-40),(0,5,0).
MyEventReceiver receiver;
Device->setEventReceiver(&receiver);
//指定消息处理类
skin = guienv->getSkin();
c8 tmp[512];
GetWindowsDirectory(tmp,511);
strcat(tmp,"
\\fonts\\simhei.ttf");
pFont = (CGUITTFont *)guienv->getFont(tmp,15);//获得ttf字体
skin->setFont(pFont);//设置字体
//得到系统目录fonts下的simhei.ttf字体,并设置为当前使用的字体.
edtName = guienv->addEditBox(L"岁月无声",rect<s32>(350,400,530,430));
edtName->setOverrideColor(SColor(0,0,0,255));
//添加一个EditBox,并将字体颜色设成蓝色.也可以这样调用类指定自己的字体:
edtName->setOverrideFont(pFont),pFont要另行加载.
pbtn = guienv->addButton(rect<s32>(540,400,590,430), 0, 101, L"发送");
listbox = guienv->addListBox(rect<s32>(350, 300, 590, 380));
//添加了一个按钮和一个列表框
IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation ( scene::EMAT_STAND );
node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );
}
//场景太单调了,还是留下原来的这个md2 "美女"模型
while(Device->run())
{
/*
Anything can be drawn between a beginScene() and an endScene()
call. The beginScene clears the screen with a color and also the
depth buffer if wanted. Then we let the Scene Manager and the
GUI Environment draw their content. With the endScene() call
everything is presented on the screen.
*/
driver->beginScene(true, true, SColor(255,100,102,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
//游戏循环
Device->drop();
return 0;
}
//main函数结束.
呵呵,挺简单的吧,irrlicht好像还有ui编辑器哦,这样就不用我们自己算坐标了,用起来就更方便了.好了,看看我们的成果吧.
posted @ 2006-07-23 20:58 安徽飞雪游戏工作室 阅读(2045) 评论(6)
编辑
中国在国际上的地位日益提高,不知为什么好像对这些写引擎的大牛们没什么影响,ogre,Irrlicht都不能直接支持中文,在一个前辈irrlicht0.9支持中文的基础上将1.0版本的中文支持基本搞定了.我使用的freetype是2.2.1版本.修改后也使引擎对freetype产生了依赖.中文输入暂时还不支持清华紫光等在中文状态按回车输入英文的功能.如果实在需要可考虑再行改动.对引擎重新编译发现用vc6.0不可编译dx9.0的相关文件,说是用6.0会产生不好解决的链接错.不过我发现用dx9.0 2005 april 的版本编译好像没什么问题.更高版本的dx9sdk应该也不会有问题.
将irrcompileconfig.h文件最后的编译条件注释掉就可以了.
/*
#if (_MSC_VER < 1300 && !defined(__GNUC__))
#undef _IRR_COMPILE_WITH_DIRECT3D_9_
#pragma message("Compiling Irrlicht with Visual Studio 6.0, support for DX9 is disabled.")
#endif
*/
由于改动的代码比较多就不在此列出来了.看看工作成果吧,原来demo是支持小日本文的,我改成中文了.
posted @ 2006-07-23 20:57 安徽飞雪游戏工作室 阅读(658) 评论(3)
编辑
让Irrlicht支持中文后,编程过程中不免经常会用到char* 到wchar_t*的转换,看了上次转载的那篇关于L"xx"的文章,写了个小函数供使用.
#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (s))
#define xfree(p) HeapFree (GetProcessHeap(), 0, (p))
wchar_t *str2wstrptr(const char *pStr)
{
PSTR pMultiByteStr = (PSTR)pStr;
PWSTR pWideCharStr;
int nLenOfWideCharStr;
// 利用API函数MultiByteToWideChar()来把a转化成unicode字符
nLenOfWideCharStr = MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1, NULL, 0);
pWideCharStr = (PWSTR)xmalloc(nLenOfWideCharStr * sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1, pWideCharStr, nLenOfWideCharStr );
return pWideCharStr;
}
调用str2wstrptr后用xfree释放xmalloc申请到的空间.
示例:
char name[] = "岁月无声";
wchar_t* pmyname= str2wstrptr(name);
转换后就可以在irrlicht用了:
ITextSceneNode *bill = Scene->addTextSceneNode(fonts[1],pmyname);
xfree(pmyname);
可以不用Scene->addTextSceneNode(fonts[1],L"岁月无声");了.
posted @ 2006-07-23 20:55 安徽飞雪游戏工作室 阅读(150) 评论(0)
编辑
《The C++ Programming Language 3rd》中有这么两段话:
from 4.3:
A type wchar_ t is provided to hold characters of a larger character set such as Unicode. It is a distinct type. The size of wchar_t is implementation-defined and large enough to hold the largest character set supported by the implementation’s locale (see §21.7, §C.3.3). The strange name is a leftover from C. In C, wchar_t is a typedef (§4.9.7) rather than a builtin type. The suffix _ t was added to distinguish standard typedefs.
from 4.3.1:
Wide character literals are of the form L碼b, where the number of characters between the quotes and their meanings is implementation-defined to match the wchar_t type. A wide character literal has type wchar_t.
这两段话中有两个要点是我们关心的:
1〉wchar_t的长度是由实现决定的;
2〉L'ab'的含义是由实现决定的。
那么GNU g++和VC6.0/7.0各是怎么实现的呢?看下面代码:
//author: **.Zhou
#include
#include
#include
void prt( const void* padd, size_t n )
{
const unsigned char* p = static_cast<const unsigned char*>( padd );
const unsigned char* pe = p + n;
for( ; p<pe; ++p ) printf( " %02X", *p ); printf( "\n" );
}
int main()
{
char a[] = "VC知识库";
wchar_t b[] = L"VC知识库";
prt( a, sizeof(a) );
prt( b, sizeof(b) );
system( "Pause" );
// 说明:
// Dev-CPP4990 显示为:
// 56 43 D6 AA CA B6 BF E2 00
// 56 00 43 00 D6 00 AA 00 CA 00 B6 00 BF 00 E2 00 00 00
// VC++6.0 和 VC.net2003 显示为:
// 56 43 D6 AA CA B6 BF E2 00
// 56 00 43 00 E5 77 C6 8B 93 5E 00 00
// 可见,Dev-CPP中的L""不是unicode编码,只是简单的扩充,汉字需要4bytes存储
HWND h = FindWindow( NULL, "计算器" );
SetWindowTextA( h, a );
system( "Pause" );
SetWindowTextW( h, b );
system( "Pause" );
// 说明:
// VC++6.0 和 VC.net2003 都能成功将标题改为"VC知识库"
// 而 Dev-CPP4990 只有 SetWindowTextA 显示正确,而 SetWindowTextW 显示的是乱码
}
这段代码说明了,g++(Dev-CPP用的是MingGW编译器)中L"xx"解释为把作为non-wide-char的"xx"扩展为作为wide-char的wchar_t,不足则在高位补0;而VC6.0的L"xx"解释为把作为MBCS的"xx"转换为作为unicode的WCHAR,目前的MBCS是以char为一个存储单元的,而WCHAR在winnt.h中定义为typedef wchar_t WCHAR。在win平台上,只要是超过0~127范围内的char型字符,都被视为MBCS,它由1到2个字节组成,MBCS字符集跟它的地区代码页号有关。在某个特定的win平台,默认的代码页号可以在控制面板-〉区域选项中设定。
关于上述结论可以有下面这个程序来验证:
//author: smileonce
#include
#include
#include
#include
void prt( const void* padd, size_t n )
{
const unsigned char* p = static_cast<const unsigned char*>( padd );
const unsigned char* pe = p + n;
for( ; p<pe; ++p ) printf( " %02X", *p ); printf( "\n" );
}
int main()
{
char a[] = "VC知识库";
wchar_t b[] = L"VC知识库";
prt( a, sizeof(a) );
prt( b, sizeof(b) );
PSTR pMultiByteStr = (PSTR)a;
PWSTR pWideCharStr;
int nLenOfWideCharStr;
// 利用API函数MultiByteToWideChar()来把a转化成unicode字符
nLenOfWideCharStr = MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1, NULL, 0);
pWideCharStr = (PWSTR)HeapAlloc( GetProcessHeap(), 0, nLenOfWideCharStr * sizeof(WCHAR) );
assert( pWideCharStr );
MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1, pWideCharStr, nLenOfWideCharStr );
prt( pWideCharStr, nLenOfWideCharStr * sizeof(WCHAR) );
system( "Pause" );
// // 说明:
// 56 43 D6 AA CA B6 BF E2 00 //char a[] = "VC知识库";
// 56 00 43 00 E5 77 C6 8B 93 5E 00 00 //wchar_t b[] = L"VC知识库";
// 56 00 43 00 E5 77 C6 8B 93 5E 00 00 //用MultiByteToWideChar()把a转换为unicode
// // 可见,b[]的字符代码就是unicode代码
return 0;
}
呵呵,问题已经明了,总结一下:
1> ISO C中wchar_t是一个typedef,ISO C++中wchar_t是语言内建的数据类型,L'xx'是ISO C/C++语言内建的表示wchar_t的文本量的语法;
2> wchar_t的长度是由实现决定的;
3> L'xx'的意义是由实现决定的;
4> 默认的'xx'是non-wide-char,其每个元素数据的类型是char;与其想对应的L'xx'是wide-char,其每个元素数据的类型是wchar_t。
为什么C/C++语言把L'xx'定义为由实现决定的呢?这显然是为了C/C++的普适性、可移植性。Bjarne的观点认为,C++的方式是允许程序员使用任何字符集作为串的字符类型。另外,unicode编码已经发展了若干版本了,是否能永久适合下去也不得而知。有关unicode的详细论述以及和其它字符集的比较,我推荐你看《无废话xml》 。
posted @ 2006-07-23 20:54 安徽飞雪游戏工作室 阅读(182) 评论(0)
编辑
一、 引言
Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。通过使用Direct3D(Windows平台),OpenGL 1.2或它自己的软件着色程序,可以实现该引擎的完全跨平台。尽管是开源的,该Irrlicht库提供了可以在商业级的3D引擎上具有的艺术特性,例如动态的阴影,粒子系统,角色动画,室内和室外技术以及碰撞检测等(见图1)。
Irrlicht是一个德国神话故事中的一种动物的名字,它能够发光和飞翔,可以在大部分的沼泽地附近发现它。单词"Irrlicht"是两个德国单词("irr"意思是疯狂的;而"Licht"意思是光)的组合。在英语中,它被译为"鬼火"。
Irrlicht十分幸运地为一个巨大的活跃的开发团队以大量的工程所支持。然而,因为Irrlicht主要由游戏名家Nikolaus Gebhardt所设计,所以该游戏在设计上十分连贯。你可以在网上到处发现有Irrlicht的增强程序,如可选用的地形生成器,入口生成器,输出器,world层生成器,相关教程和编辑器等。而且,它独立地创建了到Java,Perl,Ruby,BASIC,Python,LUA甚至更多种语言的绑定。而最为重要的是,它是完全自由的。
二、 Irrlicht特性 在深入分析API之前,请让我更具体地介绍一下Irrlicht提供给了3D游戏开发者哪些功能:
·一个可以运行于Linux以及Windows 98,ME,NT,2000和XP(MacOS在计划之中)等操作系统之上的引擎
·针对Direct3D 8生成器或Direct3D 9生成器(可选)提供了Anti-aliasing支持
·可换肤的GUI环境(包括一个很酷的具有金属质地的带阴影的皮肤),给一些老式的对话框加上漂亮的外观
·场景管理系统,它允许无缝的室内/室外过渡
·角色动画系统,带有骨骼和变形目标动画功能
·一个特殊的效果系统,包括粒子效果(雨,烟,火,雪,等等),告示板,灯光贴图,环境,地图,模板缓冲区阴影,雾,纹理动画,视差贴图,凹凸贴图,还有更多
·内建的材质支持,包括支持Pixel and Vertex Shaders版本1.1到3.0,ARB Fragment and Vertex程序以及HLSL(GLSL正在计划中)
·.NET语言绑定,这使得引擎可用于所有的.NET语言例如C#,Visual Basic.NET以及Delphi.NET
·一内建的平台独立的软件生成器,特性有:z-缓冲,Gouraud阴影,alpha混合和透明性,还有快速的2D绘图(见图2)
·你久已期待的2D绘图功能,例如alpha混合,基于关键色的位图复制,字体绘制,以及混合3D与2D图形
·能直接导入常见的建模文件格式:Maya,3DStudio Max,COLLADA,DeleD,Milkshape,Quake 3 levels,Quake2 models,DirectX,Pulsar,My3DTools,FSRad以及Cartography Shop
·能直接从BMP,PNG,Photoshop,JPEG,Targa和PCX导入纹理
·快速而易用的碰撞检测与响应
·为快速的3D运算和容器模板库进行了优化处理
·直接读取档案(可能是压缩的,如.zip文件)
·集成了快速的XML分析器
·为实现容易的本地化开发提供Unicode支持
图2:基于Irrlicht的游戏Yet Another Space Shooter(YASS),这里显示的是一个静态游戏帧中的令人吃惊的着色效果
三、 在Irrlicht中的特殊效果
在本文的例子中,我将向你展示怎样使用模板缓冲区影子技术,还有粒子系统,告示板,动态光以及水表面场景结点等技术。参见图3。
Irrlicht引擎自动地检查是否你的硬件支持模板缓冲;而如果不支持,则不启动阴影。在这个演示程序中,在方法createDevice()中的’shadows’标志被置位,以产生从一个动画角色投下的动态影子。如果这个实例程序在你的PC上运行太慢,可以把这个标志设置为false或者干脆再买一块更好些的图形加速卡。
为能够使用Irrlicht.DLL文件,你需要链接到Irrlicht.lib库文件。你可以在工程设置对话框中设置这个选项;但是为了容易实现,你可以使用一个pragma预编译注释命令。方法createDevice()负责实例化根对象-它使用引擎完成一切事情。参数如下:
·deviceType:设备类型。当前你可选取Null设备以及软设备,如DirectX8,DirectX9或OpenGL。
·windowSize:要创建的窗口的大小或全屏幕模式。这个例子中使用512x384。
·bits:每像素位数(当在全屏幕情况时)。仅允许值为16或者32。
·fullscreen:指定是否你想使设备运行于全屏幕方式。
·stencilbuffer:指定是否你想使用模板缓冲区以用于绘制阴影。
·vsync:指定是否你想启动vsync(仅在全屏幕情况),可选。
·eventReceiver:一个接收事件的对象,可选。
为适合于本实例环境,你将装载一个3D Studio Max文件(一幢房子)。该房子看起来并没有什么特别的,但是Irrlicht引擎能为你创建一个相当酷的纹理贴图。只需使用造型操纵器并为之创建一个planar纹理贴图即可:
#include <irrlicht.h> #include <iostream> using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { //让我们假定用户在本例中使用OpenGL //当然,也可以指定DirectX 8, 9, 等等. video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; //创建设备,如果创建失败立即退出。 IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, true); if (device == 0) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager();
|
我对从这个导入文件产生的发射光线颜色的效果并不满意。下列代码显示怎样实现这些步骤:
scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds"); smgr->getMeshManipulator()->makePlanarTextureMapping( mesh->getMesh(0), 0.008f); scene::ISceneNode* node = 0; node = smgr->addAnimatedMeshSceneNode(mesh); node->setMaterialTexture(0, driver->getTexture("wall.jpg")); node->getMaterial(0).EmissiveColor.set(0,0,0,0); |
四、 水动画 你将添加的第一个特殊的效果是水动画。为此,WaterSurfaceSceneNode导入一个造型文件并使之象水表面一样地波动。如果你让这个场景结点使用一种相当好的材质如MT_REFLECTION_2_LAYER,那么它看起来相当酷:
mesh = smgr->addHillPlaneMesh("myHill", core::dimension2d(20,20), core::dimension2d(40,40), 0, 0, core::dimension2d(0,0), core::dimension2d(10,10)); node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30); node->setPosition(core::vector3df(0,7,0)); node->setMaterialTexture(0,driver->getTexture("water.jpg")); node->setMaterialTexture(1,driver->getTexture("stones.jpg")); node->setMaterialType(video::EMT_REFLECTION_2_LAYER); |
作为输入造型,你可以创建一个陡峭的平面造型,但是你也可以为此使用任何其它的造型。你甚至能重用room.3ds输入文件(它看上去确实很奇怪)。该实例还用一个普通的石头纹理模型来绘制所有另外的表面。
五、透明的告示板和灯光 第二个特殊的效果是很基本的但是非常有用:一个透明的告示板,伴之有一个动态的灯光。为产生这种效果,你只需要产生一个灯光场景结点,并让它四处飞行;而且,为了让它看起来更酷一些,可以把一个告示板场景结点依附到它上面:
//创建灯光 node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f); scene::ISceneNodeAnimator* anim = 0; anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),250.0f); node->addAnimator(anim); anim->drop(); // 把告示板依附到灯光 node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50)); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp")); |
六、 粒子系统
下面介绍的这个特别效果更有趣:一个粒子系统。在Irrlicht引擎中,粒子系统既是组件化的,也是可扩展的,但是仍然易于使用。你只需要简单地把粒子发射器放到一个粒子系统场景结点,这样以来粒子看上去没有产生源。这些发射器可以据需要进行灵活配置,并经常带有许多参数,如粒子方向,粒子数量,以及粒子颜色等。
当然,发射器类型有区别(例如,一个点发射器能够使粒子从一个固定的点上发出粒子)。如果该引擎提供的粒子发射器还不能满足你的要求,你可以容易地创建你自己的发射器。这只需简单地从IParticleEmitter接口派生一个新类并使用setEmitter()方法把它依附到粒子系统上去即可。
下一个实例将创建一个盒子粒子发射器。你可能已经猜出,它从一个跳跃的盒中随机生成粒子。由参数来定义盒子,粒子的方向,每秒产生粒子的最小和最大数目,颜色以及粒子的最小和最大生命周期。
一个完全由发射器组成的粒子系统将是令人生厌的,因为缺乏真实感。因此,Irrlicht支持粒子影响器-它负责在粒子到处飞扬时予以修整。一旦添加到粒子系统上,它们就能模仿另外的更真实的效果,象重力或风。在本例中的粒子影响器只是简单地修改粒子的颜色来产生一种淡出效果。
可能你已经猜出,粒子影响器是通过派生IParticleAffector接口实现的,然后通过使用addAffector()方法把它添加到粒子系统上去。在你为该粒子系统设置了一种好看的材质后,你就有了一个看上去相当酷的野外宿营火的效果。通过调整材质,纹理,粒子发射器,还有影响器参数,你能容易地创建烟雾,下雨,爆炸,下雪等效果:
scene::IParticleSystemSceneNode* ps = 0; ps = smgr->addParticleSystemSceneNode(false); ps->setPosition(core::vector3df(-70,60,40)); ps->setScale(core::vector3df(2,2,2)); ps->setParticleSize(core::dimension2d(20.0f, 10.0f)); scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.03f,0.0f), 80,100, video::SColor(0,255,255,255), video::SColor(0,255,255,255), 800,2000); ps->setEmitter(em); em->drop(); scene::IParticleAffector* paf =ps->createFadeOutParticleAffector(); ps->addAffector(paf); paf->drop(); ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialTexture(0, driver->getTexture,"particle.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA); |
七、 影子投射 最后但也不容忽视一个问题是,你需要为一个动画角色产生一个动态的影子。为此,你装载一个Quake2.md2模型文件并把它放到你的world上去。为了创建影子,你只需要调用方法addShadowVolumeSceneNode()。你可能通过调用ISceneManager::setShadowColor()来控制影子的颜色;注意,这仅是全局可调整的,并影响所有的影子。好,下面就是你的产生动态影子效果的代码:
mesh = smgr->getMesh("../../media/faerie.md2"); scene::IAnimatedMeshSceneNode* anode = 0; anode = smgr->addAnimatedMeshSceneNode(mesh); anode->setPosition(core::vector3df(-50,45,-60)); anode->setMD2Animation(scene::EMAT_STAND); anode->setMaterialTexture(0, driver->getTexture("../../media/Faerie5.BMP")); anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(220,0,0,0)); |
八、 游戏循环 最后,你能进入由device->run()方法控制的游戏循环。该循环将不断运行,直到通过获取一个关闭窗口事件(例如在Windows操作系统下的ALT-F4击键)来退出设备。你必须在一个beginScene()和endScene()命令对之间绘制每样东西。beginScene()用指定的一种颜色清屏,如果需要的话,可以同时清除深度缓冲区。然后你就可以让场景管理器和GUI环境来绘制它们的内容。随着调用endScene(),每一样东西都被绘制到屏幕上去。在本例中,你还可以动态地在标题栏上显示帧每秒(FPS)数,这对于严肃的游戏开发者是十分重要的事情:
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-50,50,-150)); int lastFPS = -1; while(device->run()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Campfire FX example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); |
结束循环后,你必须删除先前用createDevice()方法创建的Irrlicht设备。通过使用Irrlicht引擎,你应该删除所有你用以’create’开头的方法或函数创建的所有对象。你可以通过简单地调用device->drop()来删除该设备对象。
九、你可能喜欢的Irrlicht插件 正如在前面所介绍的,Irrlicht有一群勤奋的独立开发人员并为之产生了大量的插件,也用之开发了相当多的游戏。这些开发者中提出的许多的改进被再次集成到Irrlicht的随后的发行版本中。下面我列举其中的几个例子,我想这会吸引许多颇有前程的开发者感兴趣:
·OCTTools,是一套用于Irrlicht的工具,由Murphy McCauley所创建,用于操作OCT文件相关的:输出器,加载器,甚至更多。
·ICE(Irrlicht通用引擎)是一个开发框架,它提供了一个工程的轮廓实现,从而加快了新工程的开发。
·MIM,由Murphy McCauley所创建,是一个非常有用的基于XML的文件格式,可用于Irrlicht的加载器,转换器及其各种工具。
·My3D是一个开发工具包,它能够使你把来自于各种3D包(3DStudio MAX,Giles,等等)中的灯光贴图场景直接输出到Irrlicht中。
·Dusty引擎允许程序员创建"任务"-这些"任务"可以完成程序员想做的任何事情。之后,这些任务被添加到一棵普通的任务树上去,而每个任务可以有它们希望数目的孩子任务。任务"组"允许游戏设计者在一棵完整的树上执行普通的操作,例如暂停,继续或破坏等。
·Irrlicht RPG(Erring Light)是一个3D 绕行走游戏引擎,最初是针对RPG类游戏开发的。
·2D 图像和精灵类组成了一个很有用的库,它扩展了Irrlicht的2D能力。
·Zenprogramming站点,提供第一个针对Irrlicht的非正式的外部地形生成器,此处也提供很多相关的教程。
posted @ 2006-07-23 20:51 安徽飞雪游戏工作室 阅读(474) 评论(0)
编辑
几经周折,还是把blog搬到了这里,欢迎大家经常光顾。一起学习交流Irrlicht和游戏开发技术。
posted @ 2006-07-23 20:49 安徽飞雪游戏工作室 阅读(1003) 评论(4)
编辑