#0 

25-05-2013 09:15:33

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

Bonjour.

Je me suis mis, il y a quelques jours, à programmer un petit jeu avec irrlicht. Je me trouve cependant actuellement face à un problème!

Je souhaite déplacer automatiquement plusieurs cubes dans une sorte de labyrinthe (chemin aléatoire unique).

J'ai donc envisagé deux solutions (amenant à deux problèmes différents) pour déplacer mes cubes :

    --Leurs faire suivre un chemin à l'aide d'un followspline (que je privilégie car plus simple),
    --Les faire ce déplacer jusqu'à un mur puis les faire tourner.

La première solution fonctionne pour le déplacement, les cubes suivent correctement le chemin. Cependant, ils sont tous "confondus". J'ai alors ajouté un système de collision entre les cubes mais ceux-ci continuent à ce chevaucher. J'ai comme l'impression que le followspline "annule" le système de collision. Auriez vous une idée pour résoudre ce problème? (je n'utilise pas de moteur physique externe).

Ma deuxième solution ne fonctionne tous simplement pas! Pour faire un test simple, j'ai demandé au programme de déplacer mon cube de 1.0 sur l'axe des x à chaque frame sans autres conditions particulière. Et là, il ne se déplace que lors de la première frame et ne bouge plus ensuite...

Voici donc ma classe "Monstre" :

Code c++ :



class Monstres
{
public:
    Monstres(irr::scene::ISceneManager *sceneManager, irr::video::IVideoDriver *driver, irr::scene::IMetaTriangleSelector* metaSelectorTerrain);
    void Deplacement(irr::scene::ISceneManager *sceneManager, Terrain plateau_de_jeu, double frameDeltaTime);
    Monstres();

private:
   
    irr::scene::IAnimatedMeshSceneNode* m_Monstres[Nombre_Monstres][Nombre_Monstres];
    irr::scene::ITriangleSelector* selector;
    irr::scene::IMetaTriangleSelector* metaSelector;
    std::string Nom_Monstres;
};



Le constructeur et la fonction de déplacement :

Code c++ :



Monstres::Monstres(irr::scene::ISceneManager *sceneManager, irr::video::IVideoDriver *driver, irr::scene::IMetaTriangleSelector* metaSelectorTerrain)
{
    selector = 0;
    scene::IMetaTriangleSelector* metaSelector = sceneManager->createMetaTriangleSelector();

    int i=0,j=0;

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            m_Monstres[i][j] = sceneManager->addAnimatedMeshSceneNode(sceneManager->getMesh ("Ressources/Mesh/Monstres.obj"),0,ID_IsMonster);
            m_Monstres[i][j]->setScale(core::vector3df(0.25f));
            m_Monstres[i][j]->setPosition(irr::core::vector3df(6-Taille_Terrain,0,0));
           
            selector = sceneManager->createTriangleSelector(m_Monstres[i][j]);
            m_Monstres[i][j]->setTriangleSelector(selector);
            metaSelector->addTriangleSelector(selector);

            scene::ISceneNodeAnimator* collision_Monstres = sceneManager->createCollisionResponseAnimator(metaSelector, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));
            scene::ISceneNodeAnimator* collision_Terrain = sceneManager->createCollisionResponseAnimator(metaSelectorTerrain, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));

            if(collision_Monstres && collision_Terrain)
            {
                m_Monstres[i][j]->addAnimator(collision_Monstres);
                collision_Monstres->drop();

                m_Monstres[i][j]->addAnimator(collision_Terrain);
                collision_Terrain->drop();
            }
        }
    }

    selector->drop();
}




void Monstres::Deplacement(irr::scene::ISceneManager *sceneManager, Terrain plateau_de_jeu,  double frameDeltaTime)
{
    int i=0,j=0;
    core::vector3df position_monstre, postition2;
    postition2 = m_Monstres[i][j]->getPosition();

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            if(m_Monstres[i][j] != 0)
            {
                position_monstre = m_Monstres[i][j]->getPosition();

                position_monstre.X += 1.0f * frameDeltaTime;

                m_Monstres[i][j]->setPosition(position_monstre);
            }
        }
    }

}



et l'appel de la fonction déplacement dans le main :

Code c++ :



while (device->run() && driver)
    {                         
        // 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;

        driver->beginScene(true, true, irr::video::SColor(255,255,255,255)); // demarre le rendu // clear back-buffer  // clear z-buffer // fond blanc
       
        Entity_Monstres.Deplacement(sceneManager,plateau_de_jeu, frameDeltaTime);

        sceneManager->drawAll();                    // calcule le rendu
        driver->endScene();                         // affiche le rendu
       
        int fps = driver->getFPS();

        if (lastFPS != fps)
        {
            core::stringw tmp(L"Ressources/Mesh/Monstres.obj");
            tmp += driver->getName();
            tmp += L"Movement Example - Irrlicht Engine [";
            tmp += fps;

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



Par exemple, il commence à (-44,0,0), vas arriver en (-43,0,0) et ne plus bouger alors que la fonction est bien appeler et que normalement la position du cube est mise à jour...

Je ne comprends pas pourquoi mon cube ne bouge pas! Mon problème vient-il du constructeur de ma classe (appelé plus tôt dans le programme, avant la boucle de rendu) ou de ma fonction de déplacement?

J'espère que vous pourrez m'aider!

Bonne prog!

Super-Vlan

Hors ligne


#1 

25-05-2013 19:30:22

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Il y a quelque trucs qui me dérange dans ton code et qui serait potentiellement problématique.
1/ Ton "selector->drop();" dans le constructeur de classe est à l'extérieur de ta boucle. Il devrait être juste après "metaSelector->addTriangleSelector(selector);".
2/ Dans ta boucle de rendu, tu créé des variables et c'est pas top (allocation et désallocation de la mémoire à chaque frame).
3/ Tu mets ton temps en secondes pour le re-multiplier lors du calcul de déplacement, c'est pas optimal.

En gros, je ferais ça :

Code c++ :


Monstres::Monstres(irr::scene::ISceneManager *sceneManager, irr::video::IVideoDriver *driver, irr::scene::IMetaTriangleSelector* metaSelectorTerrain)
{
    selector = 0;
    scene::IMetaTriangleSelector* metaSelector = sceneManager->createMetaTriangleSelector();

    int i=0,j=0;

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            m_Monstres[i][j] = sceneManager->addAnimatedMeshSceneNode(sceneManager->getMesh ("Ressources/Mesh/Monstres.obj"),0,ID_IsMonster);
            m_Monstres[i][j]->setScale(core::vector3df(0.25f));
            m_Monstres[i][j]->setPosition(irr::core::vector3df(6-Taille_Terrain,0,0));
           
            selector = sceneManager->createTriangleSelector(m_Monstres[i][j]);
            m_Monstres[i][j]->setTriangleSelector(selector);
            metaSelector->addTriangleSelector(selector);
            selector->drop(); ///////////////////////////////////////  drop pour chaque selector créé

            scene::ISceneNodeAnimator* collision_Monstres = sceneManager->createCollisionResponseAnimator(metaSelector, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));
            scene::ISceneNodeAnimator* collision_Terrain = sceneManager->createCollisionResponseAnimator(metaSelectorTerrain, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));

            if(collision_Monstres && collision_Terrain)
            {
                m_Monstres[i][j]->addAnimator(collision_Monstres);
                collision_Monstres->drop();

                m_Monstres[i][j]->addAnimator(collision_Terrain);
                collision_Terrain->drop();
            }
        }
    }
}




void Monstres::Deplacement(irr::scene::ISceneManager *sceneManager, Terrain plateau_de_jeu,  double frameDeltaTime)
{
    int i=0,j=0;
    core::vector3df position_monstre, postition2;
    postition2 = m_Monstres[i][j]->getPosition();

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            if(m_Monstres[i][j] != 0)
            {
                position_monstre = m_Monstres[i][j]->getPosition();

                position_monstre.X += 0.001f * frameDeltaTime; //////////////////////////////// coefficient modifié

                m_Monstres[i][j]->setPosition(position_monstre);
            }
        }
    }
}

// boucle de rendu

s32 fps=0; ///////////////////////////  variables à l'extérieur de la boucle
u32 now=0;
f32 frameDeltaTime=0.f;

while (device->run() && driver)
    {                         
        // Calcul le temps delta d'une image.
        now = device->getTimer()->getTime();
        frameDeltaTime = now - then; // Temps en secondes
        then = now;

        driver->beginScene(true, true, irr::video::SColor(255,255,255,255)); // demarre le rendu // clear back-buffer  // clear z-buffer // fond blanc
       
        Entity_Monstres.Deplacement(sceneManager,plateau_de_jeu, frameDeltaTime);

        sceneManager->drawAll();                    // calcule le rendu
        driver->endScene();                         // affiche le rendu
       
        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;
        }
       
    }



Je ne sais pas si ça changera quelque chose, le frameDeltaTime était peut-être tronqué. Moi j'aurais fait "f32(now - then)/1000.f" parce qu'il me semble que faire (f32)(now - then) fait une réinterprétation et non pas une conversion.
Si je ne me trompe pas "(f32)(now - then)", c'est comme faire "reinterpret_cast<f32>(now - then);". Ce qui fait qu'il te renvoyait un zéro au lieu de la valeur attendue.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#2 

26-05-2013 10:19:21

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

Merci pour ta réponse!

Malheureusement, ça ne fonctionne toujours pas. J'ai effectué un nouveau test et je retrouve le même résultat étonnant : la position de l'objet est bien mise a jour mais c'est comme-ci le programme oubliait cette mise à jour et laissait le cube à ça place!
Une image parle peut-être mieux :


Ici, position 2 est la position du cube avant le déplacement, position_monstres est la variable de déplacement, position 1 est la position du cube après déplacement. On peut remarquer que position 2 ne change pas entre 2frames alors que position_monstre et position 1 changent et sont d'ailleurs égales ce qui signifie que la position à bien été mise à jour... Je suis donc complètement perdu surtout que ça marche une fois au début (le cube commence à X = -44,0). (les deux frames sont consécutives)

Sinon, y aurait-t-il une solution pour faire accepter les collision lors d'un follow spline? (parce qu'au moins avec le followspline les cubes bougent smile ) J'ai eu beau chercher, je n'ai absolument rien trouvé là dessus!

Bonne prog!

Super-Vlan

PS : j'ai réduit la vitesse de déplacement pour être sur de voir quelque chose et que ce ne soit pas trop rapide (mais le même test avec une vitesse de déplacement plus élevé donne exactement le même résultat)!

Hors ligne


#3 

26-05-2013 10:46:23

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

C'est tes animators de collision qui doivent remettre le node dans son ancienne position entre le moment ou tu bouges et celui ou tu affiches.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#4 

26-05-2013 11:08:46

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

Eh oui!!!

Je suis bête! En y regardant de plus près, les cubes n'étaient en collision qu'avec eux-même du coup il ne bougeait pas!

Merci beaucoup! Maintenant, ça marche!

Dernière modification par Super-Vlan (26-05-2013 11:09:06)

Hors ligne


#5 

27-05-2013 07:56:12

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

Je profite d'avoir ouvert ce sujet pour vous posez une autre question.

Comment puis-je savoir qu'une collision à lieu entre l'un des cubes et le terrain avec le code que j'ai écrit?
Mon problème est que tous les tutos et morceaux de code que j'ai pus trouver sur le collisionOccurred ou getCollisionPoint n'utilise qu'un seul objet et tout est dans le main donc l'animator est facilement accessible! Mais là, mon animator est dans une autre fonction et il est remis à zéro après chaque assignation à un cube...

Auriez-vous une solution à mon problème où faut-il que je change radicalement de méthodes? (Encore faut-il que je trouve une autre méthode =/ )

Super-Vlan

Hors ligne


#6 

27-05-2013 17:43:16

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

Hors ligne


#7 

27-05-2013 18:57:55

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

Je ne vois malheureusement pas comment utiliser le IMetaTriangleSelector!
J'ai tenté de créer un nouveau ISceneNodeAnimatorCollisionResponse entre le IMetaTriangleSelector du Terrain (je souhaite, pour le moment, m'attarder uniquement sur le comportement des cubes lors d'une collision avec le terrain), et le cube dans la fonction de déplacement mais le collisionOccurred reste faux (peut-être est-il nécessaire d'attacher le nouveau animator au cube mais dans ce cas le programme en ajoute un à chaque frame est j'ai pus vérifier que ce n'était pas bon du tout!).

Pourrais-tu préciser quelques peu ta solution car je ne comprends pas vraiment comment faire?

Super-Vlan

Hors ligne


#8 

27-05-2013 21:47:42

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Code c++ :


IMetaTriangleSelector *metaselector = smgr->createMetaTriangleSelector();

ITriangleSelector *montriangleselector1 = ...;
ITriangleSelector *montriangleselector2 = ...;

metaselector->addTriangleSelector( montriangleselector1 );
metaselector->addTriangleSelector( montriangleselector2 );

core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#9 

27-05-2013 22:54:05

Super-Vlan
Membre
Date d'inscription: 28-06-2012
Messages: 10
Site web

J'ai réglé mon problème! Celui-ci provenait de la création des cubes. En effet, chacun étaient un mesh unique auquel j'assignais le même animator légèrement modifié ce qui m'empêchais de le réutiliser dans une autre fonction.

Mon ancien code de création des cubes:

Code c++ :



Monstres::Monstres(irr::scene::ISceneManager *sceneManager, irr::video::IVideoDriver *driver, irr::scene::IMetaTriangleSelector* metaSelectorTerrain)
{
    selector = 0;
    scene::IMetaTriangleSelector* metaSelector = sceneManager->createMetaTriangleSelector();

    int i=0,j=0, k=0,h=0;

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            m_Monstres[i][j] = sceneManager->addAnimatedMeshSceneNode(sceneManager->getMesh ("Ressources/Mesh/Monstres.obj"),0,ID_IsMonster);
            m_Monstres[i][j]->setScale(core::vector3df(0.25f));
            m_Monstres[i][j]->setPosition(irr::core::vector3df(-Taille_Terrain,0,0));
        }
    }

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {

            for (k=0; k<Nombre_Monstres; k++)
            {
                for (h=0; h<Nombre_Monstres; h++)
                {
                    if(k!=i && h!=j && m_Monstres[k][h] != 0)
                    {
                        selector = sceneManager->createTriangleSelector(m_Monstres[k][h]);
                        m_Monstres[k][h]->setTriangleSelector(selector);
                        metaSelector->addTriangleSelector(selector);
                        selector->drop();
                        selector = 0;
                    }
                }
            }

            scene::ISceneNodeAnimator* collision_Monstres = sceneManager->createCollisionResponseAnimator(metaSelector, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));
            scene::ISceneNodeAnimator* collision_Terrain = sceneManager->createCollisionResponseAnimator(metaSelectorTerrain, m_Monstres[i][j], core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));


            metaSelector->drop();

            if(collision_Monstres && collision_Terrain)
            {
                m_Monstres[i][j]->addAnimator(collision_Monstres);
                collision_Monstres->drop();

                m_Monstres[i][j]->addAnimator(collision_Terrain);
                collision_Terrain->drop();


            }
        }
    }

}



Mon nouveau code qui me permet de récupérer le CollisionResponse du terrain!

Code c++ :



Monstres::Monstres(irr::scene::ISceneManager *sceneManager, irr::video::IVideoDriver *driver, irr::scene::IMetaTriangleSelector* metaSelectorTerrain)
{
    selector = 0;
    scene::IMetaTriangleSelector* metaSelector = sceneManager->createMetaTriangleSelector();

    int i=0,j=0,h=0,k=0;

    Monstre = sceneManager->addAnimatedMeshSceneNode(sceneManager->getMesh ("Ressources/Mesh/Monstres.obj"),0,ID_IsMonster);

    if (Monstre != 0)
    {
        Monstre->setScale(core::vector3df(0.25f));
        m_Collision_Terrain_Monstres = sceneManager->createCollisionResponseAnimator(metaSelectorTerrain,Monstre,core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));
        Monstre->addAnimator(m_Collision_Terrain_Monstres);
    }

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {
            m_Monstres[i][j] = Monstre;
            m_Monstres[i][j]->setPosition(irr::core::vector3df(6-Taille_Terrain,0,0));
        }
    }

    for (i=0; i<Nombre_Monstres; i++)
    {
        for (j=0; j<Nombre_Monstres; j++)
        {

            for (k=0; k<Nombre_Monstres; k++)
            {
                for (h=0; h<Nombre_Monstres; h++)
                {
                    if(k!=i && h!=j && m_Monstres[k][h] != 0)
                    {
                        selector = sceneManager->createTriangleSelector(m_Monstres[k][h]);
                        m_Monstres[k][h]->setTriangleSelector(selector);
                        metaSelector->addTriangleSelector(selector);
                        selector->drop();
                        selector = 0;
                    }
                }
            }
   
            scene::ISceneNodeAnimator* collision_Monstres = sceneManager->createCollisionResponseAnimator(selector, Monstre, core::vector3df(0.25,0.25,0.25), core::vector3df(0,0,0));

            if(collision_Monstres && m_Monstres[i][j] != 0)
            {
                m_Monstres[i][j]->addAnimator(collision_Monstres);
                collision_Monstres->drop();
            }
        }
    }

}



@Magun & johnplayer : Je vous remercie pour votre aide mais le problème n'était pas dans la création du gestionnaire de collision mais dans son utilisation dans une autre fonction! Je pense que je me suis mal expliqué et j'essaierais d'être plus clair la prochaine fois!

Merci encore!

Super-Vlan

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
883 membres
1429 sujets
11121 messages
Dernier membre inscrit: Saidov17
53 invités en ligne
Aucun membre connecté
RSS Feed