您的位置:首页 > 其它

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