----------------------------
RESOLU, merci Capry
----(solution en bas)-----
Bonjour (c'est mon premier message, je me suis retenu le plus possible je vous assure !),
Je fais appel à vous car j'ai un problème (et oui sinon je ne posterai pas xD) :
- Cela fait X temps (2 jours plus ou moins) que je ne parviens pas à faire bouger ma petite Sydney (fox ?) comme il le faudrait, elle ne suit pas la direction de ma souris, si je regarde au nord-est et que j'appuie sur la touche avancer, ça ira tout droit et non au nord-est.
Je sais que cette question à déjà été posée et que vous devez en avoir raz la casquette de voir défiler des débutants en quete du FPS fabuleux, mais ce n'est pas mon cas, je veux apprendre et ce problème est un frein à mon imagination ^^.
Ca fait 3 jours que j'utilise Irrlicht (avant je faisais du PHP/JS/C++/Qt), donc c'est tout nouveau, je ne me suis pas encore bien familiarisé avec ce merveilleux outil
Ce qui veut dire aussi que mon code est surement mal fichu et faux, mais je vous le donne quand même (Il fonctionne parfaitement à l'heure actuelle)
main.cpp (utile ?..)
int main(void) { Demo demo(false); demo.initWorld(); demo.initPerso(); demo.initCamera(); demo.initLumiere(); demo.startGame(); return 0; }
demo.h
#ifndef H_DEMO #define H_DEMO #include "FollowingCamera.h" #include <irr/irrlicht.h> class Demo { public : Demo(bool fullscreenc); ~Demo(); void initWorld(); // Initialisation de l'environnement void initPerso(); // Initialisation des acteurs void initCamera(); // Initialisation de la camera void initLumiere(); // Initialisation de la lumière void initKeys(); // Initialisation des commandes void startGame(); // Lancement du jeu void changeView(); bool cam_thirdPerson; //virtual bool OnEvent(const SEvent& event); IrrlichtDevice* device; irr::scene::IAnimatedMeshSceneNode* Nmodele; FollowingCamera* MaCamera; ITriangleSelector* selector; ITriangleSelector* selector2; ITerrainSceneNode* terrain; private : bool fullscreen; scene::ICameraSceneNode* camera; video::IVideoDriver* driver; scene::ISceneManager *sceneManager; scene::IAnimatedMesh *room; ISceneNode* q3node; ISceneNode* q3node2; irr::scene::IAnimatedMeshMD2* modele; scene::ILightSceneNode* lumiere; irr::SKeyMap keyMap[5]; }; #endif
demo.cpp
#include "Demo.h" #include "CEventReceiver.h" #include "FollowingCamera.h" #include <iostream> using namespace irr; using namespace std; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; Demo::Demo(bool f) : fullscreen(f) { cam_thirdPerson = true; // Vue 1ère personne (false) | 3ème personne (true) } Demo::~Demo() { } void Demo::initWorld() { //Device, driver et graphe de scene device = irr::createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800,600),32,fullscreen,false,false); driver = device->getVideoDriver (); sceneManager = device->getSceneManager (); //On rend invisible le curseur device->getCursorControl ()-> setVisible (true); ICursorControl* myCursor = device->getCursorControl(); device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3"); room = sceneManager->getMesh("20kdm2.bsp"); if(cam_thirdPerson) { // COLLISION CAMERA q3node = 0; if (room) q3node = sceneManager->addOctTreeSceneNode(room->getMesh(0)); selector = 0; if (q3node) { q3node->setPosition(vector3df(-1370,-130,-1400)); selector = sceneManager->createOctTreeTriangleSelector(room->getMesh(0), q3node, 128); q3node->setTriangleSelector(selector); selector->drop(); } } if (room == 0) { std::cout << "--> Probleme de chargement de la salle" << std::endl; } } void Demo::startGame() { CEventReceiver receiver(Nmodele); device->setEventReceiver(&receiver); while (device->run()) { sceneManager->getActiveCamera(); driver->beginScene(true, true, video::SColor(0,200,200,200)); if(cam_thirdPerson) { if(MaCamera) {MaCamera->Update();} receiver.majPosMesh(*MaCamera->getCam(), true); } else { receiver.majPosMesh(*camera); Nmodele->setRotation(vector3df(0,(camera->getRotation().Y - 90),0)); // Ne bouge que de gauche à droite le perso } sceneManager->drawAll (); driver->endScene (); } device->drop (); } void Demo::initPerso() { //Sydney modele = (irr::scene::IAnimatedMeshMD2*)sceneManager->getMesh("sydney.md2"); Nmodele = sceneManager->addAnimatedMeshSceneNode(modele); if(Nmodele) { //On modifie les proprietes de Sydney Nmodele->setMaterialFlag(irr::video::EMF_LIGHTING, false); Nmodele->setFrameLoop(0, 0); Nmodele->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); Nmodele->setPosition(vector3df(0,0,0)); Nmodele->setRotation(vector3df(0,0,0)); // dos a la camera } // COLLISION PERSONNAGE q3node2 = 0; if (room) q3node2 = sceneManager->addOctTreeSceneNode(room->getMesh(0)); selector2 = 0; if (q3node2) { q3node2->setPosition(vector3df(-1370,-130,-1400)); selector2 = sceneManager->createOctTreeTriangleSelector(room->getMesh(0), q3node2, 128); q3node2->setTriangleSelector(selector2); selector2->drop(); } ISceneNodeAnimator* CollisionCamera = sceneManager->createCollisionResponseAnimator( selector2, Nmodele, core::vector3df(10,30,10), vector3df(0,0,0), vector3df(0,0,0)); Nmodele->addAnimator(CollisionCamera); CollisionCamera->drop(); } void Demo::initCamera() { //La camera if(cam_thirdPerson) { MaCamera = new FollowingCamera(Nmodele, sceneManager, true, // Pour utiliser une position initiale. selector, // Pour les collisions. 100, // Distance. 50, // Hauteur. 30, // Delta cible. vector3df(-50,200,-120)); // Position initiale. sceneManager->setActiveCamera( MaCamera->getCam() ); } else { if(camera=sceneManager->addCameraSceneNodeFPS (0, 100.0f, 300.0f, -1, false, 5, false, 0.4)) { cout << "--> Camera chargee" << endl; //camera->setPosition(vector3df(0,20,-30)); //camera->setParent(Nmodele); camera->setPosition(vector3df(0,0,0) + core::vector3df(0,25,0)); camera->setRotation(vector3df(0,90,0)); } else cout << "--> Erreur lors du chargement de la camera" << endl; } } void Demo::initLumiere() { /* if(lumiere = sceneManager->addLightSceneNode(Nmodele, core::vector3df(150,210,250),video::SColorf(0.4f, 0.4f, 0.4f, 0.4f), 30.0f)) cout << "--> Lumiere ambiante ok" << endl; else cout << "--> Erreur lors du chargement de la lumiere ambiante" << endl; */ } void Demo::changeView() { cam_thirdPerson = true; }
Comme vous pouvez le constater j'utilise la classe FollowingCamera (pour avoir la vue à la 3ème personne), mais c'est juste pour tester, elle ne sert strictement à rien
Pendant ces deux jours j'ai essayé tout et n'importe quoi et je suis à bout ...
Si quelqu'un pouvait me donner un indice, ça m'aiderait énormément.
Cordialement moi
Dernière modification par NeoCrysis (20-02-2009 12:43:07)
Hors ligne
Je ne vois pas l'endroit où tu définit les touches.
Dans le .h il y a bien une fonction "void initKeys()" mais tu ne la définie pas dans le .cpp .
Sinon pour faire la camera qui suit le perso je ne pense pas que tu t'y prennes bien, je pencherai plutot pour faire un truc comme ça (je peux me tromper) :
-> création du modèle (appelons le noeud "Nmodele")
-> création de la caméra FPS (appelons-là "camera")
-> dans la boucle de rendu on met : " camera->setTarget(Nmodele); " et positionne la camera derrière le perso;
-> puis on crée une classe d'évenements qui gère l'appuie d'une touche pour avancer (ou reculer) et qui va changer la rotation de "m_Nmodele" (que l'on passera en argument pour le constructeur de la classe) de -.1 quand la souris va à gauche et .1 quand la souris va à droite.
Je fais ça au réveil donc je peux peut-être faire une énorme erreur, mais si tu as besoin du code je peux te le donner si tu veux...
Hors ligne
EDIT : Il semblerait que j'ai trouvé une solution (un code que j'ai trouvé sur siteduzero.com), si ça fonctionne bien, je posterai mon code (ne pas tenir compte de la suite)
Merci de m'avoir répondu Capry
J'ai effectivement la fonction initKeys, que j'ai supprimé dans le .cpp car que je la laisse ou je la supprime je pouvais toujours bouger. (une bourde ?)
J'ai bien compris ton idée mais un petit bout de code me rassurerai
Je viens de voir que je n'ai pas donné tout le code !
Voici le CEventReceiver.cpp (et .h) manquant : (c'est de la grosse bidouille, je n'ai pas cherché à optimiser en faisant des boucles ou des tableaux pour les touches, j'ai fais au plus simple)
CEventReceiver.cpp
#include "CEventReceiver.h" #include "Demo.h" #include <iostream> using namespace std; using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; CEventReceiver::CEventReceiver(scene::IAnimatedMeshSceneNode* Nmodele) { cout << "--> Construction evenement" << endl; //On pointe le mesh passe en parametre. m_Nmodele = Nmodele; //Par defaut on ne bouge pas m_isMoving = false; } bool CEventReceiver::OnEvent(const irr::SEvent &event) { if(m_Nmodele != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown == true) { // Recherche de la touche associee if(m_isMoving == false) { switch(event.KeyInput.Key) { case irr::KEY_KEY_Z: touche = irr::KEY_KEY_Z; break; case irr::KEY_KEY_S: touche = irr::KEY_KEY_S; break; case irr::KEY_KEY_Q: touche = irr::KEY_KEY_Q; break; case irr::KEY_KEY_D: touche = irr::KEY_KEY_D; break; case irr::KEY_SPACE: touche = irr::KEY_SPACE; break; case irr::KEY_CONTROL: touche = irr::KEY_CONTROL; break; default:; } m_isMoving = true; // Mouvement detecte } return true; } // Event non traite return false; } void CEventReceiver::majPosMesh(irr::scene::ICameraSceneNode &camera, bool thirdPerson) { if(m_Nmodele != 0 && m_isMoving == true) { // Mouvement en cours core::vector3df v = m_Nmodele->getPosition(); // Recuperation position actuelle switch(touche) { // Valeur deplacement case irr::KEY_KEY_Z: v.X += 2.0f; break; case irr::KEY_KEY_S: v.X -= 2.0f; break; case irr::KEY_KEY_D: v.Z -= 2.0f; break; case irr::KEY_KEY_Q: v.Z += 2.0f; break; case irr::KEY_SPACE: v.Y += 5.0f; break; case irr::KEY_CONTROL: v.Y -= 5.0f; break; default:; } m_isMoving = false; core::vector3df direction = m_Nmodele->getRotation().rotationToDirection(v); //m_Nmodele->setPosition(m_Nmodele->getPosition() + direction); m_Nmodele->setPosition(v); // On renvoie la nouvelle position if(!thirdPerson) camera.setPosition(m_Nmodele->getPosition() + core::vector3df(0,25,0)); cout << "Mouvement" << endl; } }
CEventReceiver.h
#ifndef H_EVENT #define H_EVENT #include <irr/irrlicht.h> #include "Demo.h" class CEventReceiver : public irr::IEventReceiver { public : //Le constructeur. CEventReceiver(irr::scene::IAnimatedMeshSceneNode* Nmodele); //Capte automatiquement les events. bool OnEvent(const irr::SEvent &event); //Met a jour la position du mesh. void majPosMesh(irr::scene::ICameraSceneNode &camera, bool thirdPerson = false); private : //Le modele qu'on va controler. irr::scene::IAnimatedMeshSceneNode* m_Nmodele; char touche; //Indique si on est deja en mouvement ou pas. bool m_isMoving; }; #endif
Dernière modification par NeoCrysis (20-02-2009 12:24:23)
Hors ligne
Voila le seul élèment que j'ai modifié :
CEventReceiver.cpp
void CEventReceiver::majPosMesh(irr::scene::ICameraSceneNode &camera, bool thirdPerson) { if(m_Nmodele != 0 && m_isMoving == true) { // Mouvement en cours core::vector3df c = m_Nmodele->getPosition(); // Position du modele core::vector3df d = m_Nmodele->getRotation(); // Rotation du modele float diry = ((d.Y+90)*3.14)/180; if (touche == irr::KEY_KEY_Z) // Si on veut avancer { c.X += speed * cos((d.Y) * 3.14 / 180); c.Z -= speed * sin((d.Y) * 3.14 / 180); } if (touche == irr::KEY_KEY_S) // Si on veut reculer { c.X -= speed * cos((d.Y) * 3.14 / 180); c.Z += speed * sin((d.Y) * 3.14 / 180); } if (touche == irr::KEY_KEY_Q) // Si on va a gauche { //d.Y -= 0.1; c.Z += speed * cos((d.Y) * 3.14 / 180); c.X += speed * sin((d.Y) * 3.14 / 180); } if (touche == irr::KEY_KEY_D) // Si on va a droite { //d.Y += 0.1; c.Z -= speed * cos((d.Y) * 3.14 / 180); c.X -= speed * sin((d.Y) * 3.14 / 180); } m_Nmodele->setRotation(d); int xf = (c.X-sin(diry)*125); int yf = (c.Z-cos(diry)*125); int zf = 100; m_Nmodele->setPosition(c); m_isMoving = false; if(!thirdPerson) camera.setPosition(m_Nmodele->getPosition() + core::vector3df(0,25,0)); } }
Tous les mouvements fonctionnent ainsi (avancer,reculer,gauche,droite selon la position du curseur de la souris).
Merci Capry, je risque de revenir bientôt pour d'autres problèmes ^^
Bonne journée
Hors ligne
Aucun problème ^^. Moi aussi j'ai des problèmes avec la caméra...
Hors ligne
Ah, je ne pense pas être la meilleure personne pour t'aider
J'ai viré la 3ème personne, je me concentre sur l'utile !
J'ai éclaircis un peu le code, je reposte si jamais ça interesse des débutants qui auront autant merdouillé que moi ^^
Ne pas tenir compte de la fonction pour avoir Sydney qui court, c'est en cours ...
CEventReceiver.h
#ifndef H_EVENT #define H_EVENT #include <irr/irrlicht.h> #include "Demo.h" class CEventReceiver : public irr::IEventReceiver { public : //Le constructeur. CEventReceiver(irr::scene::IAnimatedMeshSceneNode* Nmodele); //Capte automatiquement les events. bool OnEvent(const irr::SEvent &event); //Met a jour la position du mesh. void majPosMesh(irr::scene::ICameraSceneNode &camera); void majAnimMesh(); //On met à jour l'animation du mesh , si besoin est private : //Le modele qu'on va controler. irr::scene::IAnimatedMeshSceneNode* m_Nmodele; char touche; //Indique si on est deja en mouvement ou pas. bool m_isMoving; bool m_animrun; struct SCamKeyMap { SCamKeyMap() {}; SCamKeyMap(s32 a, EKEY_CODE k) : action(a), keycode(k) {} s32 action; EKEY_CODE keycode; }; core::array<SCamKeyMap> KeyMap; bool CursorKeys[6]; }; #endif
CEventReceiver.cpp
#include "CEventReceiver.h" #include "Demo.h" #include <iostream> using namespace std; using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; int speed = 5; CEventReceiver::CEventReceiver(scene::IAnimatedMeshSceneNode* Nmodele) { cout << "--> Construction evenement" << endl; //On pointe le mesh passe en parametre. m_Nmodele = Nmodele; //Par defaut on ne bouge pas m_isMoving = false; m_animrun = false; KeyMap.push_back(SCamKeyMap(0, irr::KEY_KEY_Z)); KeyMap.push_back(SCamKeyMap(1, irr::KEY_KEY_S)); KeyMap.push_back(SCamKeyMap(2, irr::KEY_KEY_Q)); KeyMap.push_back(SCamKeyMap(3, irr::KEY_KEY_D)); KeyMap.push_back(SCamKeyMap(4, irr::KEY_SPACE)); KeyMap.push_back(SCamKeyMap(5, irr::KEY_CONTROL)); KeyMap.push_back(SCamKeyMap(6, irr::KEY_ESCAPE)); } bool CEventReceiver::OnEvent(const irr::SEvent &event) { if(m_Nmodele != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT) { // Recherche de la touche associee s32 cnt = (s32)KeyMap.size(); // nombre de touches enregistrees for (s32 i=0; i<cnt; ++i) if (KeyMap[i].keycode == event.KeyInput.Key) // si la touche est enregistree { CursorKeys[KeyMap[i].action] = event.KeyInput.PressedDown; // on enregistre la pression m_isMoving = true; // mouvement detecte return event.KeyInput.PressedDown; // on renvoie la pression } return false; } else return false; } void CEventReceiver::majPosMesh(irr::scene::ICameraSceneNode &camera) { if(m_Nmodele != 0 && m_isMoving == true) { // Mouvement en cours core::vector3df c = m_Nmodele->getPosition(); // Position du modele core::vector3df d = m_Nmodele->getRotation(); // Rotation du modele float diry = ((d.Y+90)*3.14)/180; if (CursorKeys[0]) // Si on veut avancer { c.X += speed * cos((d.Y) * 3.14 / 180); c.Z -= speed * sin((d.Y) * 3.14 / 180); } if (CursorKeys[1]) // Si on veut reculer { c.X -= speed * cos((d.Y) * 3.14 / 180); c.Z += speed * sin((d.Y) * 3.14 / 180); } if (CursorKeys[2]) // Si on va a gauche { //d.Y -= 0.1; c.Z += speed * cos((d.Y) * 3.14 / 180); c.X += speed * sin((d.Y) * 3.14 / 180); } if (CursorKeys[3]) // Si on va a droite { //d.Y += 0.1; c.Z -= speed * cos((d.Y) * 3.14 / 180); c.X -= speed * sin((d.Y) * 3.14 / 180); } if (CursorKeys[4]) // Si on veut monter { c.Y += 5.0f; } if (CursorKeys[5]) // Si on veut monter { c.Y -= 5.0f; } m_Nmodele->setRotation(d); int xf = (c.X-sin(diry)*125); int yf = (c.Z-cos(diry)*125); int zf = 100; m_Nmodele->setPosition(c); m_isMoving = false; //camera.setPosition(m_Nmodele->getPosition() + core::vector3df(0,25,0)); } } void CEventReceiver::majAnimMesh()//Ici , on met à jour l'animation { cout << "m_isMoving="<< m_isMoving << " || m_animrun="<< m_animrun << endl; if(m_isMoving == true && m_animrun == false) //Si le pointeur vers le mesh est ok , si l'on bouge et si l'on n'a pas encore mis à jour l'animation ... { m_Nmodele->setMD2Animation(EMAT_RUN);//on passe à l'animation "courir" m_animrun=true;//on declare que l'animation courir est bien en trainde se derouler } if(m_isMoving == false && m_animrun == true) //Si le pointeur vers le mesh est ok , si l'on ne bouge plus et si l'on n'a pas encore mis à jour l'animation ... { m_Nmodele->setMD2Animation(EMAT_STAND);//on passe à l'animation "rester en place" m_animrun=false;//et on declare que l'animation courir ne se deroule plus , du coup } }
Hors ligne