Accueil > > > Envi3D/MainWindow.cpp
BASE/MOTEUR 3D EN QT/OPENGL (COMPLET ET FONCTIONNEL!) POUR UN TRÈS PROCHAIN JEU 3D
Envi3D/MainWindow.cpp
Informations sur ce code source
Bonjour à tous,
Voici un moteur 3D gérant les textures tous formats (supporté par QT) et contient un loader de fichier .obj que j'ai écrit personnellement.
Il permet d'illustrer l'utilisation de deux QGLWidget en même temps et comment se servir de
Fichier : Envi3D/MainWindow.cpp
Nombre de lignes : 654 lignes
Afficher ce fichier en plein écran
- #include "MainWindow.h"
- #define AVANCER 0
- #define RECULER 1
- #define GAUCHE 2
- #define DROITE 3
- #define SAUT 4
- #define ACCROUPI 5
- #define VUEPRINCIPALE 0
- #define MINICARTE 1
- MainWindow::MainWindow() : QMainWindow()
- {
- this->setWindowTitle("Envi3D");
- //Le widget generique qui va contenir tous les autres
- zoneCentrale = new QWidget();
- enPause = false;
- rafraichirData = false;
- minicarteActive = true;
- x_ancien = 0; //variable pour le mouvement de la souris
- y_ancien = 0;
- //pour qu'à chaque mouvement de la souris, le repositionnement de cette dernière ne provoque pas un nouvel appel à la fonction qui gere la souris
- anti_repetition = false;
- sourisSurWidget = false;
- //////////////////////////////////////////////////////////////////////////////////////////////////
- //Lecture du fichier listeObjets.txt et creation/chargement des parametres des objets de la scene/
- //////////////////////////////////////////////////////////////////////////////////////////////////
- //les variables dont on va avoir besoin pour stocker et renvoyer aux differentes classes;
- int nbParamParObjet = 0;
- //pour verifier qu'on a bien enregistrer tous les parametres de chaque objet
- int nbParamDefinis = 0;
- QString nomObjet;
- bool isVisible = false;
- Coord3D positionObjet;
- //les collisons sont testé avec des parallelepipedes rectangle autour des objets
- bool possedeCollisionBox = false;
- //la dimension de la boite de collision
- Coord3D diagonaleCollisionBox;
- //pour savoir si il faut tourner la boite de 90°
- bool rotation90degCollisionBox = false;
- Coord3D orientationObjet;
- //le chemin d'accès au mesh .obj de l'objet
- QString fichierMesh;
- QString fichierTexture;
- //la texture est elle une UV-map (chaque point de la texture est lié à une vectrice de l'objet), ou bien juste la meme texture pour chaque face
- bool isTextureUVmap = false;
- float repeatTextX = 0.0; //seulement si il n'y a pas d'UV map (texture pt par pt), cela nous dit cb de fois il faut repeter la texture sur le rectangle
- float repeatTextY = 0.0;
- //les variables que l'on charge pour le joueur (endroit que le joueur regarde, vitesse de dep et sensibilité souris)
- Coord3D cibleCamera;
- float vitesseJoueur = 0;
- float sensivity = 0;
- Coord3D positionCamera; ////Variables pour les cameras
- int typeVue = 0; //vaut VUEPRINCIPALE si cest le widget central, et MINICARTE si c'est la mini carte
- // on ouvre maintenant le fichier qui contient les info de tous les objets (voir dans le listeObjetsMap.txt):
- QFile file("listeObjetsMap.txt");
- if (file.open(QIODevice::ReadOnly) == false) //si il y a une erreur a l'ouverture
- qDebug() << "----->ERREUR 01 ; Chargement du fichier map : FAILED";
- nombreObjets = 0; //on ajoute +1 a chaque nouvel objet cree
- QTextStream fichier(&file); //on commence la lecture du fichier
- while(!fichier.atEnd())
- {
- QString line = fichier.readLine();
- if (line[0] != '#')
- {
- QStringList mots = line.split(('='));
- //if (mots.count()>=2)
- //qDebug() << mots[1];
- if (mots[0]=="tailleTerrainX")
- _tailleTerrainX = mots[1].toInt();
- if (mots[0]=="tailleTerrainY")
- _tailleTerrainY = mots[1].toInt();
- if (mots[0]=="nbParamParObjet")
- nbParamParObjet = mots[1].toInt();;
- if (mots[0]=="!NouvelObjet")
- nbParamDefinis = 0;
- if (mots[0]=="nomObjet")
- {
- nomObjet = mots[1];
- nbParamDefinis++;
- }
- if (mots[0]=="isVisible")
- {
- isVisible = mots[1].toInt();
- nbParamDefinis++;
- }
- if (mots[0]=="posX")
- {
- positionObjet.X=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="posY")
- {
- positionObjet.Y=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="posZ")
- {
- positionObjet.Z=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="orientationX")
- {
- orientationObjet.X=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="orientationY")
- {
- orientationObjet.Y=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="orientationZ")
- {
- orientationObjet.Z=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="possedeCollisionBox")
- {
- possedeCollisionBox=mots[1].toInt();
- nbParamDefinis++;
- }
- if (mots[0]=="diagCollisionBoxX")
- {
- diagonaleCollisionBox.X=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="diagCollisionBoxY")
- {
- diagonaleCollisionBox.Y=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="diagCollisionBoxZ")
- {
- diagonaleCollisionBox.Z=mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="rotation90degCollisionBox")
- {
- rotation90degCollisionBox=mots[1].toInt();
- nbParamDefinis++;
- }
- if (mots[0]=="fichierMesh")
- {
- fichierMesh = mots[1];
- nbParamDefinis++;
- }
- if (mots[0]=="fichierTexture")
- {
- fichierTexture = mots[1];
- nbParamDefinis++;
- }
- if (mots[0]=="isTextureUVmap")
- {
- isTextureUVmap = mots[1].toInt();
- nbParamDefinis++;
- }
- if (mots[0]=="repeatTextX")
- {
- repeatTextX = mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="repeatTextY")
- {
- repeatTextY = mots[1].toFloat();
- nbParamDefinis++;
- }
- if (mots[0]=="cibleCameraX")
- cibleCamera.X = mots[1].toFloat();
- if (mots[0]=="cibleCameraY")
- cibleCamera.Y = mots[1].toFloat();
- if (mots[0]=="cibleCameraZ")
- cibleCamera.Z = mots[1].toFloat();
- if (mots[0]=="vitesseJoueur")
- vitesseJoueur = mots[1].toFloat();
- if (mots[0]=="sensivity")
- sensivity = mots[1].toFloat();
- if (mots[0]=="!FinObjet")
- {
- if (nbParamDefinis == nbParamParObjet)
- {
- //maintenant que l'on a tous les parametres on crée l'objet et on stocke le pointeur dans le tableau listeObjets, que l'on pourra ensuite transmettre au differente fonction si besoin est.
- liste_objets[nombreObjets] = new Objet(isVisible, positionObjet, orientationObjet, possedeCollisionBox, diagonaleCollisionBox, rotation90degCollisionBox, nomObjet, fichierMesh, fichierTexture, isTextureUVmap, repeatTextX,repeatTextY);
- nombreObjets++;
- }
- else
- {
- qDebug() << "Erreur 01 : Erreur chargement Objet, nombre parametre incorrect";
- }
- }
- if (mots[0]=="!FinJoueur")
- {
- //de meme on cree le joueur (qui hérite de la classe Objet), donc juste quelques membres et attributs en plus (voir Personnage.cpp et Objets.cpp)
- joueur = new Personnage(isVisible, positionObjet, cibleCamera, orientationObjet, possedeCollisionBox, diagonaleCollisionBox, rotation90degCollisionBox, vitesseJoueur, sensivity, fichierMesh, fichierTexture, isTextureUVmap);
- }
- }
- }
- //////////////////////////////
- //-----Camera Principale----//
- //////////////////////////////
- typeVue = VUEPRINCIPALE;
- positionCamera = joueur->getPosition();
- positionCamera.Z+=5;//Pour mettre la camera à 5 au dessus du sol
- cibleCamera = joueur->getCibleCamera();
- //On cree le QGLwidget avec pour parametre ; le parent, la largeur, la hauteur, le pointeur vers le joueur (pour que la camera puisse se caler dessus si c'est la vue principale),
- // la position de la camera, la target de la camera, le pointeur vers la liste d'objet, le nombre d'objet, le type et nom de la vue
- //a la fin de ce constructeur sont appelés les fct initializeGL et resizeGL
- vuePrincipal = new OpenGLWidget (zoneCentrale,800,600, joueur, positionCamera, cibleCamera, _tailleTerrainX, _tailleTerrainY, liste_objets, nombreObjets, typeVue, "Vue Principale");
- /////////Fin Camera Principale///////
- //////////////////////////////////////
- ///----Creation Vue minicarte----/////
- //////////////////////////////////////
- typeVue = MINICARTE;
- positionCamera.X = 25; //meme configuration pour la minicarte
- positionCamera.Y = 20;
- positionCamera.Z = 20;
- cibleCamera.X = 41;
- cibleCamera.Y = 29;
- cibleCamera.Z = 0;
- miniCarte = new OpenGLWidget ( zoneCentrale,320,240, joueur, positionCamera, cibleCamera, _tailleTerrainX, _tailleTerrainY, liste_objets, nombreObjets, typeVue, "Minicarte");
- //////////Fin Creation Vue minicarte//////////
- ////////////////////////////////////////////////////////////////////
- ////////////////////Dessin de la fenetre QMainWindows///////////////
- ////////////////////////////////////////////////////////////////////
- QMenu *menuFichier = menuBar()->addMenu ( "&Fichier" );
- QAction *actionNouveau = new QAction("&Nouveau", this);
- menuFichier->addAction(actionNouveau);
- actionNouveau->setEnabled(false);
- QAction *actionQuitter = new QAction("&Quitter", this);
- menuFichier->addAction(actionQuitter);
- connect(actionQuitter, SIGNAL(triggered()), qApp, SLOT (quit()));
- QMenu *menuEdition = menuBar()->addMenu ( "&Edition" );
- QMenu *sousMenuEdition = menuEdition->addMenu ( "&Design" );
- QAction *actionDesignGreen = new QAction("&Texture \"Green\"", this);
- sousMenuEdition->addAction(actionDesignGreen);
- actionDesignGreen->setCheckable(true);
- actionDesignGreen->setChecked(true);
- actionDesignGreen->setEnabled(false);
- QAction *actionDesignMetal = new QAction("&Texture \"Metal\"", this);
- sousMenuEdition->addAction(actionDesignMetal);
- actionDesignMetal->setCheckable(true);
- actionDesignMetal->setChecked(false);
- actionDesignMetal->setEnabled(false);
- QMenu *menuAffichage = menuBar()->addMenu ( "&Affichage" );
- QAction *actionAfficherTexte = new QAction("&Afficher les données", this);
- menuAffichage->addAction(actionAfficherTexte);
- actionAfficherTexte->setCheckable(true);
- actionAfficherTexte->setChecked(true);
- connect (actionAfficherTexte, SIGNAL(toggled(bool)), this, SLOT (affichageDonnee(bool)));
- QAction *actionAfficherFPS = new QAction("&Afficher le FPS", this);
- menuAffichage->addAction(actionAfficherFPS);
- actionAfficherFPS->setCheckable(true);
- actionAfficherFPS->setChecked(true);
- connect (actionAfficherFPS, SIGNAL(toggled(bool)), this, SLOT (affichageLabelFPS(bool)));
- QAction *actionAfficherMinicarte = new QAction("&Afficher la minicarte", this);
- menuAffichage->addAction(actionAfficherMinicarte);
- actionAfficherMinicarte->setCheckable(true);
- actionAfficherMinicarte->setChecked(true);
- connect (actionAfficherMinicarte, SIGNAL(toggled(bool)), this, SLOT (affichageMinicarte(bool)));
- checkBoxMinicarte = new QCheckBox ("Activer la minicarte");
- checkBoxMinicarte->setChecked(true);
- checkBoxMinicarte->setFocusPolicy(Qt::NoFocus);
- connect (checkBoxMinicarte, SIGNAL(toggled(bool)), this, SLOT (affichageMinicarte(bool)));
- labelVitesse = new QLabel ("Vitesse du joueur :");
- barVitesse = new QProgressBar ( zoneCentrale );
- barVitesse->setFixedSize ( 320, 20 );
- barVitesse->setValue (joueur->getVitesse()*100/6 );
- labelVie = new QLabel ("Vie du joueur :");
- barVie = new QProgressBar ( zoneCentrale );
- barVie->setFixedSize ( 320, 20 );
- barVie->setValue (100);
- labelMunitions = new QLabel ("Munitions du joueur :");
- barMunitions = new QProgressBar ( zoneCentrale );
- barMunitions->setFixedSize ( 320, 20 );
- barMunitions->setValue(100);
- labelChargeArme = new QLabel ("Charge de l'arme (clique droit) :");
- barChargeArme = new QProgressBar ( zoneCentrale );
- barChargeArme->setFixedSize ( 320, 20 );
- barChargeArme->setValue(0);
- labelPresFPS = new QLabel ("FPS :");
- labelFPS = new QLabel("0");
- quitter = new QPushButton ( "Quitter" );
- QHBoxLayout *layoutPrincipal = new QHBoxLayout;
- QVBoxLayout *layoutSecondaire = new QVBoxLayout;
- layoutSecondaire->addWidget ( miniCarte );
- layoutSecondaire->addWidget ( checkBoxMinicarte );
- layoutSecondaire->addWidget ( labelVitesse );
- layoutSecondaire->addWidget ( barVitesse );
- layoutSecondaire->addWidget ( labelVie );
- layoutSecondaire->addWidget ( barVie );
- layoutSecondaire->addWidget ( labelMunitions );
- layoutSecondaire->addWidget ( barMunitions );
- layoutSecondaire->addWidget ( labelChargeArme );
- layoutSecondaire->addWidget ( barChargeArme );
- QHBoxLayout *layoutTrois = new QHBoxLayout;
- layoutTrois->addWidget (labelPresFPS );
- layoutTrois->addWidget ( labelFPS );
- layoutSecondaire->addLayout(layoutTrois);
- QSpacerItem *verticalSpacer = new QSpacerItem ( 10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );
- layoutSecondaire->addItem ( verticalSpacer );
- layoutSecondaire->addWidget ( quitter );
- layoutPrincipal->addWidget ( vuePrincipal );
- layoutPrincipal->addLayout ( layoutSecondaire );
- layoutPrincipal->setSpacing ( 20 );
- zoneCentrale->setLayout ( layoutPrincipal );
- setCentralWidget ( zoneCentrale );
- labelPresFPS->setVisible(true);
- labelFPS->setVisible(true);
- quitter->setFocusPolicy(Qt::NoFocus);
- ////////////////////Fin dessin de la fenetre QMainWindows///////////////
- connect ( quitter, SIGNAL ( clicked() ), qApp, SLOT ( quit() ) );
- timerJeu = new QTimer(this);
- connect(timerJeu, SIGNAL(timeout()), this, SLOT(cycleTimerJeu()));
- timerFPS = new QTimer(this);
- connect(timerFPS, SIGNAL(timeout()), this, SLOT(affichageDuFPS()));
- qDebug() << "+ Chargement fenetre principale : OK" ;
- //La fonction qui lance les timers (juste en dessous)
- lancerJeu();
- //affichageMinicarte(false);
- }
- void MainWindow::lancerJeu()
- {
- //On lance le timer de base qui appelle cycleTimerJeu toute les 20ms (juste en dessous)
- timerJeu->start(20);
- //Pour le calcul du FPS, autre timer
- timerFPS->start(1000);
- qDebug() << "+ Lancement de la partie" ;
- }
- void MainWindow::stopperJeu()
- {
- timerJeu->stop();
- timerFPS->stop();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////Boucle principale/////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////
- void MainWindow::cycleTimerJeu()
- {
- //on compte les cycles pour calculer le FPS
- _numCycle++;
- //on lance la gestion du joueur (personnage.cpp), cad son deplacement sur le terrain, collision, saut et orientation du rergard
- joueur->Animate(liste_objets, nombreObjets, _tailleTerrainX, _tailleTerrainY);
- //on lance la gestion de l'arme du joueur (projectile, munitions, chargement de l'arme, angle de rotation des tubes)
- rafraichirData = joueur->gestionArme(liste_objets, nombreObjets);
- //si les données de munition ou de charge ont changé, on rafraichit les progressBar
- if (rafraichirData==true)
- {
- barChargeArme->setValue(joueur->getChargeArme());
- barMunitions->setValue (joueur->getNiveauMunitions());
- }
- //appelle updateGL qui lui-meme appelle directement le paintGL() du QGLWidget, dans lequel toute la scene est dessiné (voir QGLWidget.cpp)
- vuePrincipal->updateGL();
- miniCarte->updateGL();
- }
- ////////////////////////////////Fin boucle principale///////////////////////////////////////////
- void MainWindow::affichageDuFPS()
- {
- QString texte;
- QString fps;
- fps.setNum(_numCycle);
- fps = fps + " img/sec";
- QString perte;
- perte.setNum(50 - _numCycle);
- perte = " (" + perte + " images perdues)";
- texte = fps + perte;
- labelFPS->setText(texte);
- _numCycle = 0;
- }
- void MainWindow::mousePressEvent ( QMouseEvent * event )
- {
- //-----On detecte si l'utilisateur a cliquee sur le qGlwidget principale
- if ( (event->x()>vuePrincipal->x()) && (event->y()>vuePrincipal->y()) && (event->x()<(vuePrincipal->x()+vuePrincipal->geometry().width())) && (event->y()<(vuePrincipal->y()+vuePrincipal->geometry().height()+15)) )
- {
- sourisSurWidget = true;
- oldPosSouris.setX(event->x());
- oldPosSouris.setY(event->y());
- //qDebug() << "Ancien : " << x_ancien << " / " << y_ancien;
- QApplication::setOverrideCursor ( QCursor ( Qt::BlankCursor ) );
- if (event->button() == Qt::RightButton)
- {
- joueur->setToucheArmeActive(true);
- }
- }
- else
- sourisSurWidget = false;
- //---On detecte si le clic est sur la progressBar
- if ( (event->x()>barVitesse->x()) && ((event->y()-25)>barVitesse->y()) && (event->x()<(barVitesse->x()+barVitesse->geometry().width())) && ((event->y()-25)<(barVitesse->y()+barVitesse->geometry().height())) )
- {
- qDebug() << "Ok : " << ((event->x() - barVitesse->x() ));
- barVitesse->setValue( (event->x() - barVitesse->x() )*100/318 );
- joueur->setVitesse(6*barVitesse->value()*0.01);
- qDebug() << "Speed_Theorique =" << (barVitesse->value()*6*0.01);
- }
- }
- void MainWindow::mouseReleaseEvent ( QMouseEvent * event )
- {
- if (event->button() == Qt::RightButton) //c'est tjrs vrai mais ca evite les warnings de "unused parameter"...
- {
- joueur->setToucheArmeActive(false);
- }
- QApplication::restoreOverrideCursor();
- }
- void MainWindow::mouseMoveEvent ( QMouseEvent *event )
- {
- if (event) //juste pour eviter le warning "unused parameter"...
- {}
- if (( anti_repetition == false )&&(sourisSurWidget == true))//on verifie que ce n'est pas la fonction qui se rappelle elle meme (avec setPos) et que la souris est sur le bon widget
- {
- //qDebug() << "Ancien : " << x_ancien << " / " << y_ancien;
- int xrel = ( oldPosSouris.x() - event->x() );
- int yrel = ( oldPosSouris.y() - event->y() );
- //qDebug() << "Mouvement souris : " << xrel << " / " << yrel;
- joueur->mouvementSouris ( xrel, yrel );
- QCursor::setPos(mapToGlobal(oldPosSouris));
- anti_repetition = true;
- }
- else
- {
- anti_repetition = false;
- }
- }
- void MainWindow::wheelEvent ( QWheelEvent *event )
- {
- float vitesseJoueur = joueur->getVitesse();
- if ( event->delta() >= 0 )
- {
- vitesseJoueur += 0.1;
- if (vitesseJoueur > 6)
- vitesseJoueur = 6;
- joueur->setVitesse(vitesseJoueur);
- }
- else
- {
- vitesseJoueur -= 0.1;
- if (vitesseJoueur < 0)
- vitesseJoueur = 0;
- joueur->setVitesse(vitesseJoueur);
- }
- qDebug() << "Speed =" << vitesseJoueur;
- barVitesse->setValue ( vitesseJoueur*100/6 );
- }
- void MainWindow::keyPressEvent ( QKeyEvent *event )
- {
- Coord3D _posi;
- _posi = joueur->getPosition();
- switch ( event->key() )
- {
- case Qt::Key_Escape:
- qApp->exit();
- break;
- case Qt::Key_P:
- if ( enPause == false )
- {
- enPause = true;
- stopperJeu();
- }
- else
- {
- enPause = false;
- lancerJeu();
- }
- break;
- case Qt::Key_Z:
- joueur->deplacement ( AVANCER, true );
- break;
- case Qt::Key_S:
- joueur->deplacement ( RECULER, true );
- break;
- case Qt::Key_Q:
- joueur->deplacement ( GAUCHE, true );
- break;
- case Qt::Key_D:
- joueur->deplacement ( DROITE, true );
- break;
- case Qt::Key_Control:
- qDebug() << "A genou";
- joueur->deplacement ( ACCROUPI, true );
- break;
- case Qt::Key_Space:
- //qDebug() << "Space";
- joueur->deplacement ( SAUT, true );
- break;
- case Qt::Key_Shift:
- qDebug() << "Pos = " << _posi.X << _posi.Y << _posi.Z;
- break;
- }
- }
- void MainWindow::keyReleaseEvent ( QKeyEvent * event ) //Arrete le deplacement
- {
- switch ( event->key() )
- {
- case Qt::Key_Z:
- joueur->deplacement ( AVANCER, false );
- break;
- case Qt::Key_S:
- joueur->deplacement ( RECULER, false );
- break;
- case Qt::Key_Q:
- joueur->deplacement ( GAUCHE, false );
- break;
- case Qt::Key_D:
- joueur->deplacement ( DROITE, false );
- break;
- case Qt::Key_Control:
- qDebug() << "Debout";
- joueur->deplacement ( ACCROUPI, false );
- break;
- }
- }
- void MainWindow::affichageDonnee(bool valeur)
- {
- if (valeur == true)
- {
- labelVitesse->setVisible(true);
- barVitesse->setVisible(true);
- labelVie->setVisible(true);
- barVie->setVisible(true);
- labelMunitions->setVisible(true);
- barMunitions->setVisible(true);
- labelChargeArme->setVisible(true);
- barChargeArme->setVisible(true);
- }
- else
- {
- labelVitesse->setVisible(false);
- barVitesse->setVisible(false);
- labelVie->setVisible(false);
- barVie->setVisible(false);
- labelMunitions->setVisible(false);
- barMunitions->setVisible(false);
- }
- }
- void MainWindow::affichageLabelFPS(bool valeur)
- {
- if (valeur == true)
- {
- labelFPS->setVisible(true);
- labelPresFPS->setVisible(true);
- }
- else
- {
- labelFPS->setVisible(false);
- labelPresFPS->setVisible(false);
- }
- }
- void MainWindow::affichageMinicarte(bool valeur)
- {
- if (valeur == true)
- {
- minicarteActive = true;
- miniCarte->setVueIsActive(true);
- }
- else
- {
- minicarteActive = false;
- miniCarte->setVueIsActive(false);
- }
- }
|