123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /** Example 004 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 other input than keyboard.
- As always, include the header files, use the irr namespace,
- and tell the linker to link with the .lib file.
- */
- #ifdef _MSC_VER
- #pragma comment(lib, "Irrlicht.lib")
- #endif
- #include <irrlicht.h>
- #include "driverChoice.h"
- #include "exampleHelper.h"
- using namespace irr;
- /*
- To receive events like mouse and keyboard input, or GUI events like
- "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;
- /*
- Always return false by default. If you return true you tell the engine
- that you handled this event completely and the Irrlicht should not
- process it any further. So for example if you return true for all
- EET_KEY_INPUT_EVENT events then Irrlicht would not pass on key-events
- to it's GUI system.
- */
- 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];
- };
- /*
- 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
- create an irr::IrrlichtDevice and the scene node we want to move. We also
- create some additional scene nodes to show 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 the event receiver. Take care that the pointer to it has to
- stay valid as long as the IrrlichtDevice uses it. Event receivers are not
- reference counted.
- */
- MyEventReceiver receiver;
- // create device
- 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();
- const io::path mediaPath = getExampleMediaPath();
- /*
- 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 * sphereNode = smgr->addSphereSceneNode();
- if (sphereNode)
- {
- sphereNode->setPosition(core::vector3df(0,0,30));
- sphereNode->setMaterialTexture(0, driver->getTexture(mediaPath + "wall.bmp"));
- sphereNode->setMaterialFlag(video::EMF_LIGHTING, false);
- }
- /*
- 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* cubeNode = smgr->addCubeSceneNode();
- if (cubeNode)
- {
- cubeNode->setMaterialTexture(0, driver->getTexture(mediaPath + "t351sml.jpg"));
- cubeNode->setMaterialFlag(video::EMF_LIGHTING, false);
- scene::ISceneNodeAnimator* anim =
- smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
- if (anim)
- {
- cubeNode->addAnimator(anim);
- anim->drop();
- }
- }
- /*
- The last scene node we add is a b3d model of a walking ninja. Is shows the
- use of a 'fly straight' animator to move the node between two points.
- */
- scene::IAnimatedMeshSceneNode* ninjaNode =
- smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "ninja.b3d"));
- if (ninjaNode)
- {
- scene::ISceneNodeAnimator* anim =
- smgr->createFlyStraightAnimator(core::vector3df(100,0,60),
- core::vector3df(-100,0,60), 3500, true);
- if (anim)
- {
- ninjaNode->addAnimator(anim);
- anim->drop();
- }
- /*
- 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 correct animation (frames and speed), we
- would also be able to just call
- "ninjaNode->setMD2Animation(scene::EMAT_RUN)" for the 'run'
- animation instead of "setFrameLoop" and "setAnimationSpeed",
- But that only works with MD2 animations, while this can be used to
- start other animations. For MD2 it's usually good advice not to use
- hardcoded frame-numbers...
- */
- ninjaNode->setMaterialFlag(video::EMF_LIGHTING, false);
- ninjaNode->setFrameLoop(0, 13);
- ninjaNode->setAnimationSpeed(15);
- // ninjaNode->setMD2Animation(scene::EMAT_RUN);
- ninjaNode->setScale(core::vector3df(2.f,2.f,2.f));
- ninjaNode->setRotation(core::vector3df(0,-90,0));
- // ninjaNode->setMaterialTexture(0, driver->getTexture(mediaPath + "sydney.bmp"));
- }
- /*
- 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);
- /*
- Add a colorful irrlicht logo
- */
- device->getGUIEnvironment()->addImage(
- driver->getTexture(mediaPath + "irrlichtlogoalpha2.tga"),
- core::position2d<s32>(10,20));
- /*
- Lets draw the scene and 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 movement 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;
- /* Check if keys W, S, A or D are being held down, and move the
- sphere node around respectively. */
- core::vector3df nodePosition = sphereNode->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;
- sphereNode->setPosition(nodePosition);
- driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, 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;
- }
- }
- /*
- In the end, delete the Irrlicht device.
- */
- device->drop();
-
- return 0;
- }
- /*
- That's it. Compile and play around with the program.
- **/
|