Tutoriel Irrlicht 4

Mouvement

Ce tutoriel est une traduction de l'anglais des tutoriels officiels d'Irrlicht.

Il montre comment déplacer et animer un nœud de scène. Nous parlerons aussi bien des bases de SceneNodeAnimators que du déplacement manuel des nœuds à l'aide du clavier. Nous allons créer un mouvement indépendant du nombre d'images, ce qui signifie que la distance lors d'un déplacement dépendra de la durée du dernier tour de la boucle Irrlicht.

Vous pouvez aussi regarder les autres exemples d'Irrlicht, l'exemple 19. Souris et Joystick montre comment traiter ces différents types d'entrée.

Commentez Donner une note à l'article (5)

Article lu   fois.

Les deux auteur et traducteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Receveur d'événements

Image non disponible

Comme toujours, j'inclus les fichiers d'en-têtes, j'utilise le namespace « irr », et je dis à l'éditeur de liens de lier le fichier .lib.

 
Sélectionnez
#ifdef _MSC_VER
// Nous définissons aussi ceci pour ne plus voir l'avertissement de MSVC lors du sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif
 
#include <irrlicht.h>
#include "driverChoice.h"
 
using namespace irr;

Pour recevoir des événements tels que les entrées souris ou clavier, voire des événements GUI comme « le bouton OK a été cliqué », nous avons besoin d'un objet héritant de irr::IEventReceiver. Il n'y a qu'une seule méthode à surcharger : irr::IEventReceiver::OnEvent(). Cette méthode sera appelée par le moteur à chaque événement qui surviendra. Mais ce qui nous intéresse, c'est de savoir si une touche est maintenue enfoncée ou non, nous allons donc enregistrer l'état de chaque touche.

 
Sélectionnez
class MyEventReceiver : public IEventReceiver
{
public:
    // Ceci est la méthode que nous devons implémenter
    virtual bool OnEvent(const SEvent& event)
    {
        // Se souvient si la touche est enfoncée ou relâchée
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
        return false;
    }
 
    // Ceci est utilisé pour vérifier si une touche est enfoncée
    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:
    // Nous utilisons ce tableau pour stocker l'état de chaque touche.
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

Le receveur d'événements pour conserver les touches pressées est prêt, la réponse actuelle sera faite dans la boucle de rendu, juste avant de dessiner la scène.

II. Création des nœuds

Créons donc un irr::IrrlichtDevice et le nœud de scène que nous voulons bouger. Nous créons aussi d'autres nœuds de scène supplémentaires pour montrer qu'il y a différentes possibilités de déplacement et d'animation pour les nœuds de scène.

 
Sélectionnez
int main()
{
    // demande un pilote à l'utilisateur
    video::E_DRIVER_TYPE driverType=driverChoiceConsole();
    if (driverType==video::EDT_COUNT)
        return 1;
 
    // créer le moteur
    MyEventReceiver receiver;
 
    IrrlichtDevice* device = createDevice(driverType,
            core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);
 
    if (device == 0)
        return 1; // on ne peut pas créer le pilote sélectionné.
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();

Créons le nœud qui sera déplacé avec les touches WSAD. Nous créons un nœud sphère qui est une des primitives géométriques du moteur. Nous plaçons le nœud à (0,0,30) et nous lui assignons une texture pour le rendre un peu plus intéressant à regarder. Parce que nous n'avons pas de lumière dynamique dans cette scène, nous désactivons l'éclairage pour chaque modèle (sinon les modèles seraient noirs).

 
Sélectionnez
    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);
    }

Maintenant, nous créons un autre nœud, déplaçable en utilisant un animateur de nœuds de scène. Ce dernier modifie le nœud de scène et peut être attaché à n'importe quel nœud de scène comme un nœud de scène de mesh, un panneau, une lumière et même un nœud de scène de caméra. Les animateurs ne sont pas seulement capables de modifier la position d'un nœud de scène, ils peuvent aussi, par exemple, animer les textures d'un objet. Nous créons un nœud de scène de cube et nous l'attachons à l'animateur « fly circle », faisons ensuite voler ce nœud autour de notre nœud de scène de sphère.

 
Sélectionnez
    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();
        }
    }

Le dernier nœud de scène que nous ajoutons pour montrer les possibilités des animateurs de nœuds de scène est un modèle b3b, qui utilise un animateur « fly straight » pour courir entre différents points.

 
Sélectionnez
    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();
        }

III. Animation des nœuds

Pour rendre le modèle plus correct, nous désactivons la lumière, définissons les étapes par lesquelles l'animation devra passer, nous tournons le modèle d'environ 180 degrés et ajustons la vitesse d'animation et la texture. Pour mettre la bonne animation (étapes et vitesse), nous devrions appeler anms->setMD2Animation(scene::EMAT_RUN) pour l'animation de « course », au lieu de setFrameLoop et setAnimationSpeed, mais ceci ne fonctionne qu'avec les animations MD2, or vous devez aussi savoir comment démarrer d'autres animations. Mais il est préférable de ne pas utiliser des nombres magiques(1) pour les paramètres des étapes.

 
Sélectionnez
        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"));
 
    }

Pour être capable de regarder la scène et de s'y déplacer, nous créons une caméra style FPS et nous cachons le curseur de la souris.

 
Sélectionnez
    smgr->addCameraSceneNodeFPS();
    device->getCursorControl()->setVisible(false);

Ajoutons un logo Irrlicht coloré.

 
Sélectionnez
    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));

Nous avons tout fait, dessinons le tout. Nous écrivons aussi le nombre d'images par seconde et le nom du pilote dans le titre de la fenêtre.

 
Sélectionnez
    int lastFPS = -1;
 
    // Pour créer un mouvement indépendant du nombre d'images par seconde, nous devons savoir
    // combien de temps s'est écoulé depuis la dernière image.
    u32 then = device->getTimer()->getTime();
 
    // Ceci est la vitesse de mouvement en unités par seconde.
    const f32 MOVEMENT_SPEED = 5.f;
 
    while(device->run())
    {
        // Calcul le temps delta d'une image.
        const u32 now = device->getTimer()->getTime();
        const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Temps en secondes
        then = now;

Vérifions que les touches W, S, A, D sont maintenues enfoncées et déplaçons le nœud de sphère.

 
Sélectionnez
        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(); // dessine la scene 3d
        device->getGUIEnvironment()->drawAll(); // dessine l'environnement gui (le 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;
        }
    }

À la fin, supprimons le moteur Irrlicht.

 
Sélectionnez
    device->drop();
 
    return 0;
}

Voilà, compilons et testons le programme.

IV. Conclusion

Vous pouvez désormais déplacer et animer vos nœuds de scène en utilisant Irrlicht.

Dans le prochain tutoriel « Interface Utilisateur », nous verrons comment créer et utiliser une interface utilisateur avec des fenêtres, des boutons, etc.

V. Remerciements

Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.

Merci à LittleWhite pour sa relecture technique ainsi qu'à ClaudeLELOUP pour sa relecture orthographique.


Nombre écrit en dur dans le code source d'un programme.

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 Neckara. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.