Loading...
Searching...
No Matches
Tutorial 4: Movement

This Tutorial shows how to move and animate SceneNodes. The basic concept of SceneNodeAnimators is shown as well as manual movement of nodes using the keyboard. We'll demonstrate framerate independent movement, which means moving by an amount dependent on the duration of the last run of the Irrlicht loop.

Example 19.MouseAndJoystick shows how to handle those kinds of input.

As always, I include the header files, use the irr namespace, and tell the linker to link with the .lib file.

#ifdef _MSC_VER
// We'll also define this to stop MSVC complaining about sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif
#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
driverChoice.h
irrlicht.h
Main header file of the irrlicht, the only file needed to include.
irr
Everything in the Irrlicht Engine can be found in this namespace.
Definition aabbox3d.h:13

To receive events like mouse and keyboard input, or GUI events like "the OK button has been clicked", we need an object which is derived from the irr::IEventReceiver object. There is only one method to override: irr::IEventReceiver::OnEvent(). This method will be called by the engine once when an event happens. What we really want to know is whether a key is being held down, and so we will remember the current state of each key.

class MyEventReceiver : public IEventReceiver
{
public:
// This is the one method that we have to implement
virtual bool OnEvent(const SEvent& event)
{
// Remember whether each key is down or up
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return false;
}
// This is used to check whether a key is being held down
virtual bool IsKeyDown(EKEY_CODE keyCode) const
{
return KeyIsDown[keyCode];
}
MyEventReceiver()
{
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = false;
}
private:
// We use this array to store the current state of each key
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
irr::IEventReceiver
Interface of an object which can receive events.
Definition IEventReceiver.h:434
irr::EKEY_CODE
EKEY_CODE
Definition Keycodes.h:12
irr::KEY_KEY_CODES_COUNT
@ KEY_KEY_CODES_COUNT
Definition Keycodes.h:168
irr::EET_KEY_INPUT_EVENT
@ EET_KEY_INPUT_EVENT
A key input event.
Definition IEventReceiver.h:35
irr::SEvent
SEvents hold information about an event. See irr::IEventReceiver for details on event handling.
Definition IEventReceiver.h:263
irr::SEvent::EventType
EEVENT_TYPE EventType
Definition IEventReceiver.h:414

The event receiver for keeping the pressed keys is ready, the actual responses will be made inside the render loop, right before drawing the scene. So lets just create an irr::IrrlichtDevice and the scene node we want to move. We also create some other additional scene nodes, to show that there are also some different possibilities to move and animate scene nodes.

int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
// create device
MyEventReceiver receiver;
IrrlichtDevice* device = createDevice(driverType,
core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
irr::IrrlichtDevice
The Irrlicht device. You can create it with createDevice() or createDeviceEx().
Definition IrrlichtDevice.h:44
irr::IrrlichtDevice::getSceneManager
virtual scene::ISceneManager * getSceneManager()=0
Provides access to the scene manager.
irr::IrrlichtDevice::getVideoDriver
virtual video::IVideoDriver * getVideoDriver()=0
Provides access to the video driver for drawing 3d and 2d geometry.
irr::core::dimension2d
Specifies a 2 dimensional size.
Definition dimension2d.h:21
irr::scene::ISceneManager
The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff.
Definition ISceneManager.h:151
irr::video::IVideoDriver
Interface to driver which is able to perform 2d and 3d graphics functions.
Definition IVideoDriver.h:257
irr::video::E_DRIVER_TYPE
E_DRIVER_TYPE
An enum for all types of drivers the Irrlicht Engine supports.
Definition EDriverTypes.h:15
irr::video::EDT_COUNT
@ EDT_COUNT
No driver, just for counting the elements.
Definition EDriverTypes.h:56
irr::createDevice
IRRLICHT_API IrrlichtDevice *IRRCALLCONV createDevice(video::E_DRIVER_TYPE deviceType=video::EDT_SOFTWARE, const core::dimension2d< u32 > &windowSize=(core::dimension2d< u32 >(640, 480)), u32 bits=16, bool fullscreen=false, bool stencilbuffer=false, bool vsync=false, IEventReceiver *receiver=0)
Creates an Irrlicht device. The Irrlicht device is the root object for using the engine.

Create the node which will be moved with the WSAD keys. We create a sphere node, which is a built-in geometry primitive. We place the node at (0,0,30) and assign a texture to it to let it look a little bit more interesting. Because we have no dynamic lights in this scene we disable lighting for each model (otherwise the models would be black).

scene::ISceneNode * node = smgr->addSphereSceneNode();
if (node)
{
node->setPosition(core::vector3df(0,0,30));
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
}
irr::scene::ISceneManager::addSphereSceneNode
virtual IMeshSceneNode * addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode *parent=0, s32 id=-1, const core::vector3df &position=core::vector3df(0, 0, 0), const core::vector3df &rotation=core::vector3df(0, 0, 0), const core::vector3df &scale=core::vector3df(1.0f, 1.0f, 1.0f))=0
Adds a sphere scene node of the given radius and detail.
irr::scene::ISceneNode
Scene node interface.
Definition ISceneNode.h:41
irr::scene::ISceneNode::setMaterialTexture
void setMaterialTexture(u32 textureLayer, video::ITexture *texture)
Sets the texture of the specified layer in all materials of this scene node to the new texture.
Definition ISceneNode.h:436
irr::scene::ISceneNode::setPosition
virtual void setPosition(const core::vector3df &newpos)
Sets the position of the node relative to its parent.
Definition ISceneNode.h:507
irr::scene::ISceneNode::setMaterialFlag
void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
Sets all material flags at once to a new value.
Definition ISceneNode.h:425
irr::video::IVideoDriver::getTexture
virtual ITexture * getTexture(const io::path &filename)=0
Get access to a named texture.
irr::core::vector3df
vector3d< f32 > vector3df
Typedef for a f32 3d vector.
Definition vector3d.h:445
irr::video::EMF_LIGHTING
@ EMF_LIGHTING
Will this material be lighted? Default: true.
Definition EMaterialFlags.h:26

Now we create another node, movable using a scene node animator. Scene node animators modify scene nodes and can be attached to any scene node like mesh scene nodes, billboards, lights and even camera scene nodes. Scene node animators are not only able to modify the position of a scene node, they can also animate the textures of an object for example. We create a cube scene node and attach a 'fly circle' scene node animator to it, letting this node fly around our sphere scene node.

scene::ISceneNode* n = smgr->addCubeSceneNode();
if (n)
{
n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
n->setMaterialFlag(video::EMF_LIGHTING, false);
scene::ISceneNodeAnimator* anim =
smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
if (anim)
{
n->addAnimator(anim);
anim->drop();
}
}
irr::IReferenceCounted::drop
bool drop() const
Drops the object. Decrements the reference counter by one.
Definition IReferenceCounted.h:116
irr::scene::ISceneManager::addCubeSceneNode
virtual IMeshSceneNode * addCubeSceneNode(f32 size=10.0f, ISceneNode *parent=0, s32 id=-1, const core::vector3df &position=core::vector3df(0, 0, 0), const core::vector3df &rotation=core::vector3df(0, 0, 0), const core::vector3df &scale=core::vector3df(1.0f, 1.0f, 1.0f))=0
Adds a cube scene node.
irr::scene::ISceneManager::createFlyCircleAnimator
virtual ISceneNodeAnimator * createFlyCircleAnimator(const core::vector3df &center=core::vector3df(0.f, 0.f, 0.f), f32 radius=100.f, f32 speed=0.001f, const core::vector3df &direction=core::vector3df(0.f, 1.f, 0.f), f32 startPosition=0.f, f32 radiusEllipsoid=0.f)=0
Creates a fly circle animator, which lets the attached scene node fly around a center.
irr::scene::ISceneNodeAnimator
Animates a scene node. Can animate position, rotation, material, and so on.
Definition ISceneNodeAnimator.h:31
irr::scene::ISceneNode::addAnimator
virtual void addAnimator(ISceneNodeAnimator *animator)
Adds an animator which should animate this node.
Definition ISceneNode.h:348

The last scene node we add to show possibilities of scene node animators is a b3d model, which uses a 'fly straight' animator to run between to points.

scene::IAnimatedMeshSceneNode* anms =
smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d"));
if (anms)
{
scene::ISceneNodeAnimator* anim =
smgr->createFlyStraightAnimator(core::vector3df(100,0,60),
core::vector3df(-100,0,60), 3500, true);
if (anim)
{
anms->addAnimator(anim);
anim->drop();
}
irr::scene::IAnimatedMeshSceneNode
Scene node capable of displaying an animated mesh and its shadow.
Definition IAnimatedMeshSceneNode.h:54
irr::scene::ISceneManager::getMesh
virtual IAnimatedMesh * getMesh(const io::path &filename)=0
Get pointer to an animateable mesh. Loads the file if not loaded already.
irr::scene::ISceneManager::addAnimatedMeshSceneNode
virtual IAnimatedMeshSceneNode * addAnimatedMeshSceneNode(IAnimatedMesh *mesh, ISceneNode *parent=0, s32 id=-1, const core::vector3df &position=core::vector3df(0, 0, 0), const core::vector3df &rotation=core::vector3df(0, 0, 0), const core::vector3df &scale=core::vector3df(1.0f, 1.0f, 1.0f), bool alsoAddIfMeshPointerZero=false)=0
Adds a scene node for rendering an animated mesh model.
irr::scene::ISceneManager::createFlyStraightAnimator
virtual ISceneNodeAnimator * createFlyStraightAnimator(const core::vector3df &startPoint, const core::vector3df &endPoint, u32 timeForWay, bool loop=false, bool pingpong=false)=0
Creates a fly straight animator, which lets the attached scene node fly or move along a line between ...

To make the model look right we disable lighting, set the frames between which the animation should loop, rotate the model around 180 degrees, and adjust the animation speed and the texture. To set the right animation (frames and speed), we would also be able to just call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation instead of "setFrameLoop" and "setAnimationSpeed", but this only works with MD2 animations, and so you know how to start other animations. But a good advice is to not use hardcoded frame-numbers...

anms->setMaterialFlag(video::EMF_LIGHTING, false);
anms->setFrameLoop(0, 13);
anms->setAnimationSpeed(15);
// anms->setMD2Animation(scene::EMAT_RUN);
anms->setScale(core::vector3df(2.f,2.f,2.f));
anms->setRotation(core::vector3df(0,-90,0));
// anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));
}
irr::scene::IAnimatedMeshSceneNode::setAnimationSpeed
virtual void setAnimationSpeed(f32 framesPerSecond)=0
Sets the speed with which the animation is played.
irr::scene::IAnimatedMeshSceneNode::setFrameLoop
virtual bool setFrameLoop(s32 begin, s32 end)=0
Sets the frame numbers between the animation is looped.
irr::scene::ISceneNode::setScale
virtual void setScale(const core::vector3df &scale)
Sets the relative scale of the scene node.
Definition ISceneNode.h:468
irr::scene::ISceneNode::setRotation
virtual void setRotation(const core::vector3df &rotation)
Sets the rotation of the node relative to its parent.
Definition ISceneNode.h:488

To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible.

smgr->addCameraSceneNodeFPS();
device->getCursorControl()->setVisible(false);
irr::IrrlichtDevice::getCursorControl
virtual gui::ICursorControl * getCursorControl()=0
Provides access to the cursor control.
irr::gui::ICursorControl::setVisible
virtual void setVisible(bool visible)=0
Changes the visible state of the mouse cursor.
irr::scene::ISceneManager::addCameraSceneNodeFPS
virtual ICameraSceneNode * addCameraSceneNodeFPS(ISceneNode *parent=0, f32 rotateSpeed=100.0f, f32 moveSpeed=0.5f, s32 id=-1, SKeyMap *keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed=0.f, bool invertMouse=false, bool makeActive=true)=0
Adds a camera scene node with an animator which provides mouse and keyboard control appropriate for f...

Add a colorful irrlicht logo

device->getGUIEnvironment()->addImage(
driver->getTexture("../../media/irrlichtlogoalpha2.tga"),
core::position2d<s32>(10,20));
gui::IGUIStaticText* diagnostics = device->getGUIEnvironment()->addStaticText(
L"", core::rect<s32>(10, 10, 400, 20));
diagnostics->setOverrideColor(video::SColor(255, 255, 255, 0));
irr::IrrlichtDevice::getGUIEnvironment
virtual gui::IGUIEnvironment * getGUIEnvironment()=0
Provides access to the 2d user interface environment.
irr::core::rect
Rectangle template.
Definition rect.h:27
irr::gui::IGUIEnvironment::addImage
virtual IGUIImage * addImage(video::ITexture *image, core::position2d< s32 > pos, bool useAlphaChannel=true, IGUIElement *parent=0, s32 id=-1, const wchar_t *text=0)=0
Adds an image element.
irr::gui::IGUIEnvironment::addStaticText
virtual IGUIStaticText * addStaticText(const wchar_t *text, const core::rect< s32 > &rectangle, bool border=false, bool wordWrap=true, IGUIElement *parent=0, s32 id=-1, bool fillBackground=false)=0
Adds a static text.
irr::gui::IGUIStaticText
Multi or single line text label.
Definition IGUIStaticText.h:19
irr::gui::IGUIStaticText::setOverrideColor
virtual void setOverrideColor(video::SColor color)=0
Sets another color for the text.
irr::video::SColor
Class representing a 32 bit ARGB color.
Definition SColor.h:202

We have done everything, so lets draw it. We also write the current frames per second and the name of the driver to the caption of the window.

int lastFPS = -1;
// In order to do framerate independent movement, we have to know
// how long it was since the last frame
u32 then = device->getTimer()->getTime();
// This is the movemen speed in units per second.
const f32 MOVEMENT_SPEED = 5.f;
while(device->run())
{
// Work out a frame delta time.
const u32 now = device->getTimer()->getTime();
const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
then = now;
irr::ITimer::getTime
virtual u32 getTime() const =0
Returns current virtual time in milliseconds.
irr::IrrlichtDevice::run
virtual bool run()=0
Runs the device.
irr::IrrlichtDevice::getTimer
virtual ITimer * getTimer()=0
Provides access to the engine's timer.
irr::f32
float f32
32 bit floating point variable.
Definition irrTypes.h:104
irr::u32
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.h:58

Check if keys W, S, A or D are being held down, and move the sphere node around respectively.

core::vector3df nodePosition = node->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;
node->setPosition(nodePosition);
driver->beginScene(true, true, video::SColor(255,113,113,133));
smgr->drawAll(); // draw the 3d scene
device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo)
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw tmp(L"Movement Example - Irrlicht Engine [");
tmp += driver->getName();
tmp += L"] fps: ";
tmp += fps;
device->setWindowCaption(tmp.c_str());
lastFPS = fps;
}
}
irr::IrrlichtDevice::setWindowCaption
virtual void setWindowCaption(const wchar_t *text)=0
Sets the caption of the window.
irr::core::vector3d::X
T X
X coordinate of the vector.
Definition vector3d.h:408
irr::core::vector3d::Y
T Y
Y coordinate of the vector.
Definition vector3d.h:411
irr::gui::IGUIEnvironment::drawAll
virtual void drawAll()=0
Draws all gui elements by traversing the GUI environment starting at the root node.
irr::scene::ISceneManager::drawAll
virtual void drawAll()=0
Draws all the scene nodes.
irr::scene::ISceneNode::getPosition
virtual const core::vector3df & getPosition() const
Gets the position of the node relative to its parent.
Definition ISceneNode.h:498
irr::video::IVideoDriver::beginScene
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255, 0, 0, 0), const SExposedVideoData &videoData=SExposedVideoData(), core::rect< s32 > *sourceRect=0)=0
Applications must call this method before performing any rendering.
irr::video::IVideoDriver::getFPS
virtual s32 getFPS() const =0
Returns current frames per second value.
irr::video::IVideoDriver::getName
virtual const wchar_t * getName() const =0
Gets name of this video driver.
irr::video::IVideoDriver::endScene
virtual bool endScene()=0
Presents the rendered image to the screen.
irr::core::stringw
string< wchar_t > stringw
Typedef for wide character strings.
Definition irrString.h:1361
irr::KEY_KEY_A
@ KEY_KEY_A
Definition Keycodes.h:66
irr::KEY_KEY_D
@ KEY_KEY_D
Definition Keycodes.h:69
irr::KEY_KEY_S
@ KEY_KEY_S
Definition Keycodes.h:84
irr::KEY_KEY_W
@ KEY_KEY_W
Definition Keycodes.h:88

In the end, delete the Irrlicht device.

device->drop();
return 0;
}

That's it. Compile and play around with the program.

- Irrlicht Engine Documentation © 2003-2012 by Nikolaus Gebhardt. Generated on for Irrlicht 3D Engine by Doxygen 1.15.0