Irrlicht学习笔记(4)--Movement
2016-07-04 21:12
393 查看
1.说明:
这个例子展示:1.wasd手动操控(某个物体)移动;
2.让场景节点独立移动(也就是某个物体).
3.场景节点动画器(SceneNodeAnimators)能让我们移动的时候保持自己的独立移动.
2.MyEventReceiver
为了接收鼠标键盘以及GUI事件,需要继承接口:irr::IEventReceiver来获取和处理消息.IEventReceiver就一个方法需要重写,
OnEvent(),此方法在引擎获得用户输入消息时会被调用.
MyEventReceiver继承字IEventReceiver,
含有一个数组成员(记录当前每一个按键的状态):
bool KeyIsDown[KEY_KEY_CODES_COUNT];//0xff
重写OnEvent:
virtual bool OnEvent(const SEvent& event)
{
if(event.EventType = irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return false;
}
事件类型是由枚举类型:EEVENT_TYPE记录,比如EET_GUI_EVENT =0;
SEvent类包含一下类:
SGUIEvent:GUI事件
SMouseInput://鼠标事件
SkeyInput://键盘输入事件
SJoystickEvent:游戏手柄事件
SLogEvent://log事件
SUserEvent://任何种类的用户事件
SKeyInput:
struct SKeyInput
{
wchar_t Char;
EKEY_CODE key;
bool PressedDown:1;//false:起
bool Shift:1;//用于组合键
bool Control:1;
};
为了获取wasd按键的状态,写一个函数:
virtual bool IsKeyDown(EKEY_CODE keyCode)const
{
return KeyIsDown[keyCode];
}
3.
1)创建一个需要移动的球体节点在ISceneManager有相应方法创建简单几何体.
scene::ISceneNode* node1 = smgr->addSphereSceneNode();
然后设置属性:位置,纹理,关闭灯光.
2)创建一个做参照的立方体节点
scene::ISceneNode* node2 = smgr->addCubeSceneNode();
初始化它的纹理,关闭光照,
至于位置,给node2绑定一个动画,让它一直旋转.
scene::ISeneNodeAnimator* anim = smgr->createFlyCircleAnimator(
core::vector3df(0,0,30),20);
node2->addAnimator(anim);
anim->drop();
4.额外展示:
1)添加一个带奔跑动画的b3d模型,让他在两个点间来回奔跑,模型:ninja.b3d内部包含一套动作,跑,死,攻击,跳跃等.
模型默认朝向是+z,run整数是:0-13,
scene::IAnimatedMeshSceneNode* anims =
smgr->addAnimatedMeshSceneNode(smgr->getMesh("../media/ninja.b3d");
设置模型属性:
添加移动动画(这个动画是指物体移动),为了更有意义,设置它为+x->-x
关闭光照,
设置模型循环帧数(因为只需要跑的动作):setFrameLoop(0,13)
旋转-90度:移动方向为-x,与模型的跑步动作朝向(+z)不一致:setRotation(core::vector3df(0,0,0))
设置动画速度:setAnimationSpeed(15)
scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(
core::vector3df(100,0,0),//开始位置
core::vector3df(-100,0,0),//结束位置
3500,//每秒节点要移动的距离
true);
anims->addAnimator(anim);
anim->drop();
2)添加一个log和静态文本框
guie->addImage(driver->getTextrue("../media/irrlichtlogoalph2.tga"),
core::position2d<s32>(10,20));
//静态文本框,写"Movement"
gui::IGUIStaticText* stext = guie->addStaticText(
L"Movement",core::rect<s32>(10,10,400,20),true);
将字体颜色设置为黄色:
stext->setOverrideColor(video::SColor(255,255,255,0);
5.实现wasd控制球移动
基于时间的物体移动,需要在while循环内基于时间改变球位置位置参数设置:node1->setPositoin(nodePostion);
需要获得当前的nodePostion: = node1->getPostion()+改变量
获得改变量:
比如Y方向,需要根据当前W,S按键状态决定
if(receiver.IsKeyDown(irr::KEY_KEY_W)
nodePosition.Y+=MOVEMENT_SPEED*frameDeltaTime;
frameDeltaTime是时间改变量.
const u32 now = device->getTimer()->getTime() ;
frameDeltaTime = (f32)(now - then)/1000.0f;
then = now;
6.完整代码:
#ifdef _MSC_VER #pragma comment(lib,"Irrlicht.lib") #endif #include <irrlicht.h> using namespace irr; class MyEventReceiver :public IEventReceiver { bool KeyIsDown[KEY_KEY_CODES_COUNT]; public: virtual bool OnEvent(const SEvent& event) { if (event.EventType == irr::EET_KEY_INPUT_EVENT) KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; return false; } virtual bool IsKeyDown(EKEY_CODE keyCode) const { return KeyIsDown[keyCode]; } MyEventReceiver() { for (u32 i = 0; i < KEY_KEY_CODES_COUNT; i++) KeyIsDown[i] = false; } }; int main(int argc, char** argv) { MyEventReceiver receiver; IrrlichtDevice* device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(720, 455), 16, false, false, false, &receiver); if (!device) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* guie = device->getGUIEnvironment(); //分别添加一个球体和一个立方体 scene::ISceneNode* node1 = smgr->addSphereSceneNode(); //设置球体的属性:位置,纹理,关闭材质灯光(没设置灯源) if (node1) { node1->setPosition(core::vector3df(0, 0, 40)); node1->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); node1->setMaterialFlag(video::EMF_LIGHTING, false); } scene::ISceneNode* node2 = smgr->addCubeSceneNode(); // if (node2) { node2->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); node2->setMaterialFlag(video::EMF_LIGHTING, false); //为cube创建和添加一个动画 scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0, 0, 30),20); node2->addAnimator(anim); anim->drop(); } //添加一个在两个点间奔跑的b3d模型 scene::IAnimatedMeshSceneNode* anims = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../media/ninja.b3d")); //设置属性:添加动画 if (anims) { scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(core::vector3df(100, 0, 0), core::vector3df(-100, 0, 0), 3500, true); //添加 if (anim) { anims->addAnimator(anim); anim->drop(); } //为了跟合理的显示动画,需要设置:关闭灯光,添加纹理,设置动作帧范围(只需要run动作),动作时间,因为动作帧包含了所有动作, //对应MD2格式的动画,只需要调用:anims->setMD2Animation(scene::EMAT_RUN); anims->setFrameLoop(0, 13); anims->setAnimationSpeed(15); anims->setScale(core::vector3df(2.0, 2.0, 2.0)); anims->setRotation(core::vector3df(0, 0, 0));//如果没有这一行,模型是倒着走的 //anims->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp")); anims->setMaterialFlag(video::EMF_LIGHTING, false); } //添加一个log //gui::IGUIEnvironment* guie = device->getGUIEnvironment()->addImage( driver->getTexture("../media/irrlichtlogoalpha2.tga"), core::position2d<s32>(10, 20)); gui::IGUIStaticText* diagnostics = device->getGUIEnvironment()->addStaticText( L"hello", core::rect<s32>(10, 10, 400, 20),true); diagnostics->setOverrideColor(video::SColor(255, 255, 255, 0)); //设置摄像机 smgr->addCameraSceneNodeFPS(); u32 lastFPS = -1; u32 then = device->getTimer()->getTime(); const f32 MOVEMENT_SPEED = 5.f; while (device->run()) { const u32 now = device->getTimer()->getTime(); const f32 frameDeltaTime = (f32)(now - then) / 1000.0f; then = now; //wasd core::vector3df nodePosition = node1->getPosition(); if (receiver.IsKeyDown(irr::KEY_KEY_W)) nodePosition.Y += MOVEMENT_SPEED*frameDeltaTime; else if (receiver.IsKeyDown(irr::KEY_KEY_S)) nodePosition.Y -= MOVEMENT_SPEED*frameDeltaTime; if (receiver.IsKeyDown(irr::KEY_KEY_A)) nodePosition.X -= MOVEMENT_SPEED*frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_D)) nodePosition.X += MOVEMENT_SPEED*frameDeltaTime; node1->setPosition(nodePosition); driver->beginScene(true, true, video::SColor(255, 0, 100, 100)); smgr->drawAll(); // guie->drawAll(); device->getGUIEnvironment()->drawAll(); driver->endScene(); u32 fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"Movement ["); tmp += driver->getName(); tmp += L"] fps:"; tmp += fps; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } device->drop(); return 0; }
相关文章推荐
- 向量的倒影 公式推导
- 在irrlicht中播放视频
- irrlicht的显示原理
- Irrlicht引擎在Windows的安装和使用
- Irrlicht引擎在Linux的安装和使用
- Irrlicht学习之载入网格(mesh)文件
- Irrlicht学习之创建GUI界面
- Irrlicht学习之添加中文的支持
- Irrlicht学习之摄像机的探究
- Irrlicht学习之光照的研究
- 使用CopperCube(IrrEdit)创建Irrlicht场景
- Irrlicht学习之载入irr文件和自定义场景节点
- Irrlicht学习之粒子系统的研究
- Irrlicht学习之水波特效的研究
- Irrlicht学习之使用着色器
- 使用VS2010构建CEGUI0.8.3
- 将CEGUI整合进Irrlicht
- Irrlicht 移植到 Android
- 文档翻译之irrlicht1.8-- irr::scene:IMeshLoader
- irrlicht渲染的一帧(可以把irrlicht修改为纯opengl es实现)