Este Tutorial muestra como mover y animar SceneNodes. El concepto básico de SceneNodeAnimators es mostrado también como el de movimiento manual de nodos usando el teclado.

El programa que se describe aquí se vera como esto:

Imágen


Empecemos!

Como siempre, Incluimos los archivos de cabecera, el uso del namespace "irr", y le decimos al linker que linkee con el archivo .lib .

#include <stdio.h>
#include <wchar.h>
#include <irrlicht.h>


using namespace irr;

#pragma comment(lib, "Irrlicht.lib")



En este tutorial, uno de nuestros objetivos es mover un nodo de escena usando algunas teclas del teclado. Almacenamos un puntero al nodo de la escena que queremos mover hache.
El otro puntero es un puntero al Irrlicht Device, el cual necesitamos en el EventReceiver para manipular la el nodo de escena y tener la cámara activa.

scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0; 


Para obtener eventos como input de mouse o teclado, o eventos de GUI como "el botón OK a sido clickeado", necesitamos un objeto el cual es derivado del objeto IEventReceiver. Allí solo hay que sobrecargar un método: OnEvent. Este método será llamado por el engine cuando un evento suceda. Usaremos esta entrada para mover el nodo de escena con las teclas W y S.

class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{ 


Si la tecla 'W' o 'S' fue levantada, obtenemos la posición del nodo de la escena, y modificamos su coordenada Y un poquito. Así si presionas 'W', el nodo se mueve hacia arriba, y si presionas 'S' se mueve hacia abajo.

	if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT &&
				!event.KeyInput.PressedDown)
	{
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_W:
			case KEY_KEY_S:
				{
					core::vector3df v = node->getPosition();
					v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
					node->setPosition(v);
				}
				return true;
			}
	}

	return false;
	}
};


El receptor de eventos para mover el nodo de escena esta listo. Así que creemos un Irrlicht Device y el nodo de la escena que queremos que se mueva. También creamos algún nodo de escena adicional, para mostrar que hay diferentes posibilidades de mover y animar nodos de escena.

int main()
{
   MyEventReceiver receiver;
   
  device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480),
       16, false, false, false, &receiver);

   video::IVideoDriver* driver = device->getVideoDriver();
   scene::ISceneManager* smgr = device->getSceneManager();



Creamos el nodo para moverlo con las teclas 'W' y 'S'. Creamos un 'test node', el cual es un cubo incluido en el engine con propósitos de prueba. Situamos el nodo en (0,0,30) y le asignamos una textura a este, para hacer que se vea un poco más interesante.

node = smgr->addTestSceneNode();
node->setPosition(core::vector3df(0,0,30));
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));


Ahora creamos otro nodo, que se moverá usando un "Scene node animators" (N de T: Animador de nodo de escena). Los "Scene node animators" modifican los nodos de la escena y pueden ser atachados a cualquier nodo de escena como nodos de escena mesh, billboards, luces y hasta nodos de escena cámaras.
Los "Scene node animators" no son únicamente para modificar la posición del nodo de escena, ellos también pueden animar texturas de un objeto por ejemplo. Creamos un "test node" de nuevo y lo atachamos un 'fly circle'(N de T: Volar en círculos) dejando a este nodo volando alrededor de nuestro primer nodo de escena.

scene::ISceneNode* n = smgr->addTestSceneNode();
n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));

scene::ISceneNodeAnimator* anim = 
     smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
n->addAnimator(anim);
anim->drop();


El ultimo nodo de escena que agregamos para mas posibilidades de animadores de escena es un modelo md2, el cual usa una animador 'fly straight'(N de T: Volar recto) para correr entre dos puntos.

scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(
		smgr->getMesh("../../media/sydney.md2"));

if (n)
	{
		anim = smgr->createFlyStraightAnimator(core::vector3df(100,0,60), 
			core::vector3df(-100,0,60), 10000, true);
		anms->addAnimator(anim);
		anim->drop();


Para hacer que el modelo se vea mejor, le desactivamos la iluminación (no hemos creado ninguna luz por lo tanto el modelo seria negro), seteamos los frames entre los cuales la animación debe realizar el loop, rota el modelo 180 grados y ajusta la velocidad de la animación y la textura.
Para setear la animación correcta (frames y velocidad), podríamos haber llamado "anms->setMD2Animation(scene::EMAT_RUN)" para la animación 'correr' en lugar de "setFrameLoop" y "setAnimationSpeed", pero esto solo funcionaria con animaciones MD2, y así sabes como comenzar otras animaciones.

   anms->setMaterialFlag(video::EMF_LIGHTING, false);
   anms->setFrameLoop(320, 360);
   anms->setAnimationSpeed(30);
   anms->setRotation(core::vector3df(0,180.0f,0));
   anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.BMP"));
}


Para poder ver y movernos por ahí en esta escena, creamos una cámara estilo "first person shooter" y hacemos que el cursor del mouse se haga invisible.

smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
device->getCursorControl()->setVisible(false); 


Hemos hecho todo, así que vamos a dibujarlo. También escribimos los actuales frames por segundo y el nombre del driver al titulo de la ventana.

int lastFPS = -1;

while(device->run())
{
     driver->beginScene(true, true, video::SColor(255,90,90,156));
     smgr->drawAll();
     driver->endScene();

     int fps = driver->getFPS();

     if (lastFPS != fps)
     {
        wchar_t tmp[1024];
        swprintf(tmp, 1024, L"Movement Example - Irrlicht Engine (%s)(fps:%d)",
        driver->getName(), fps);

       device->setWindowCaption(tmp);
       lastFPS = fps;
     }
}

device->drop();
return 0;
}


Eso es todo. Compila y juega un poco con el programa.