Voila je vous présente un code d'essai des collisions.
fichier main.cpp
#include <irrlicht.h>
#include "MyEventReceiver.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
int main(int argc, char** argv)
{
IrrlichtDevice* device = createDevice( video::EDT_OPENGL, core::dimension2d<s32>(1000, 800),32, false, false, false);
device->setWindowCaption(L"Collisions");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setFrameLoop(0, 0);
node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );
}
scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0);
camera->setPosition(core::vector3df(0, 55, -30));
// ajout du terrain
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
"../../media/terrain-heightmap.bmp",
0, // parent node
-1, // node id
core::vector3df(-1000.f, -500.f, -1000.f), // position
core::vector3df(0.f, 0.f, 0.f), // rotation
core::vector3df(40.f, 4.4f, 40.f), // scale
video::SColor ( 255, 255, 255, 255 ), // vertexColor,
5, // maxLOD
scene::ETPS_17, // patchSize
4 // smoothFactor
);
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
// création du selector du terrain
scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
// create collision response animator and attach it to the camera
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(60,50,60),
core::vector3df(0,0,0),
core::vector3df(0,50,0));
//création de l'animator et l'attache au mesh de sydney
scene::ISceneNodeAnimator* anim2 = smgr->createCollisionResponseAnimator(
selector, node, core::vector3df(30,50,30),
core::vector3df(0,-100,0));
selector->drop();
camera->addAnimator(anim);
node->addAnimator(anim2);
anim->drop();
anim2->drop();
MyEventReceiver receiver(node);
device->setEventReceiver(&receiver);
bool bouje;
bool boujeActif;
while (device->run())
{
driver->beginScene(true, true, SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
receiver.majPosMesh();
}
device->drop();
return 0;
}
fichier MyEventReceiver.h
#ifndef DEF_MYEVENTRECEIVER
#define DEF_MYEVENTRECEIVER
#include <irrlicht.h>
class MyEventReceiver : public irr::IEventReceiver
{
public:
MyEventReceiver(irr::scene::IAnimatedMeshSceneNode* );
virtual bool OnEvent(const irr::SEvent& );
//met à jour la position de l'objet
void majPosMesh();
private :
//Le modele qu'on va controler.
irr::scene::IAnimatedMeshSceneNode* m_Nmodele;
//va permettre de changer la position de l'objet par rapport à son axe
irr::core::matrix4 Mat;
//Indique si l'objet est en mouvement
bool m_isMoving;
//reçoit la valeur de la touche enfoncée
char *myKeyPressed;
};
#endif
fichier MyEventReceiver.cpp
#include <irrlicht.h>
#include "MyEventReceiver.h"
using namespace irr;
MyEventReceiver::MyEventReceiver(scene::IAnimatedMeshSceneNode* Nmodele )
{
//On pointe le mesh passe en parametre.
m_Nmodele = Nmodele;
//Par defaut on ne bouge pas
m_isMoving = false;
myKeyPressed = NULL;
}
bool MyEventReceiver::OnEvent(const SEvent& event)
{
//Si l'objet existe et qu'une touche est préssé
if (m_Nmodele != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT
&& (event.KeyInput.Key == irr::KEY_KEY_Z
||event.KeyInput.Key == irr::KEY_KEY_S
||event.KeyInput.Key == irr::KEY_KEY_Q
||event.KeyInput.Key == irr::KEY_KEY_D))
{
//gère les différent cas suivant la touche
switch (event.KeyInput.Key)
{
case irr::KEY_KEY_Z:
//On y ajoute la valeur de déplacement
myKeyPressed="Z";
//On renvoie la nouvelle position
break;
case irr::KEY_KEY_S:
myKeyPressed="S";
break;
case irr::KEY_KEY_Q:
myKeyPressed="Q";
break;
case irr::KEY_KEY_D:
myKeyPressed="D";
break;
default :
break;
}
m_isMoving = event.KeyInput.PressedDown;
return true;
}
return false;
}
void MyEventReceiver::majPosMesh()
{
//faire tomber un mesh
//sans cette ligne, le mesh ne tombe pas et donc ne suivra plus le terrain en descente
//faite un test sans cette ligne vous comprendrez
m_Nmodele->setPosition(m_Nmodele->getPosition() - core::vector3df(0.0, 0.05, 0.0));
//On vérifie que le pointeur vers le mesh est
//ok et que la touche est enfoncée
if (m_Nmodele != 0 && m_isMoving == true)
{
//On commence par récupérer la position actuelle
core::vector3df v = m_Nmodele->getPosition();
//et sa rotation pour que l'objet bouge en se basant sur son axe
core::vector3df r = m_Nmodele->getRotation();
if (myKeyPressed=="Z")
{
//On y ajoute la valeur de deplacement
Mat.setRotationDegrees(m_Nmodele->getRotation());
core::vector3df Target(0.2,0,0);
Mat.transformVect(Target);
core::vector3df NewPos=m_Nmodele->getPosition();
NewPos += Target;
m_Nmodele->setPosition(NewPos);
}
else if (myKeyPressed=="S")
{
Mat.setRotationDegrees(m_Nmodele->getRotation());
core::vector3df Target(-0.2,0,0);
Mat.transformVect(Target);
core::vector3df NewPos=m_Nmodele->getPosition();
NewPos += Target;
m_Nmodele->setPosition(NewPos);
}
if (myKeyPressed=="Q")
{
r.Y-= 0.1;
m_Nmodele->setRotation(r);
}
else if (myKeyPressed=="D")
{
r.Y+= 0.1;
m_Nmodele->setRotation(r);
}
}
}
C'est un code à améliorer mais au moins ca donne une base.
Je suis persuadé de la fonction smgr->createCollisionResponseAnimator(); n'est pas adapté à une sceneNode mais bon... j'ai pas trouvé mieux pour l'instant !
Si quelqu'un avait une idée...