Page principale | Hiérarchie des classes | Liste des classes | Liste des fichiers | Membres de classe | Membres de fichier

ctrl_entite.cpp

Aller à la documentation de ce fichier.
00001 00002 // Shoot(r) 00009 00010 #include "ctrl_entite.h" 00011 #include "ctrl_fenetre.h" 00012 #include "ctrl_jeu.h" 00013 #include "entite_arme.h" 00014 #include "entite_bonus.h" 00015 #include "entite_ennemi.h" 00016 #include "entite_joueur.h" 00017 00018 CEntityManager* CEntityManager::m_pInstance = 0; 00019 00020 // Construction du gestionnaire d'entités 00021 CEntityManager::CEntityManager () 00022 { 00023 // On initialise le pointeur sur l'instance a 0 pour indiquer à la fonction Instance, qu'elle doit créer une instance 00024 m_pInstance = 0; 00025 00026 // On initialise les statisques du jeu 00027 m_Statistique.m_uiEnnemiCree = 0; 00028 m_Statistique.m_uiEnnemiDetruit = 0; 00029 m_Statistique.m_uiEnnemiCreeTotal = 0; 00030 m_Statistique.m_uiEnnemiDetruitTotal = 0; 00031 00032 // On initialise le tableau de pointeurs sur entités pour vérifier si de la mémoire a été alloué pour chaque entrée 00033 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00034 m_pEntite[i] = 0; 00035 } 00036 00037 // Destruction du gestionnaire d'entités 00038 // On prend soit de libérer la mémoire réservée pour les entités 00039 CEntityManager::~CEntityManager () 00040 { 00041 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00042 if (m_pEntite[i]) 00043 Kill (i); 00044 } 00045 00046 // Creation ou récupération de l'instance du gestionnaire d'entités 00047 // Si l'instance n'existe pas (m_pEntityManager == 0), on la créé. 00048 CEntityManager* CEntityManager::Instance () 00049 { 00050 if (m_pInstance == 0) 00051 m_pInstance = new CEntityManager; 00052 return m_pInstance; 00053 } 00054 00055 // Destruction de l'instance de gestionnaire d'entités si elle existe 00056 void CEntityManager::Kill () 00057 { 00058 if (m_pInstance != 0) 00059 { 00060 delete m_pInstance; 00061 m_pInstance = 0; 00062 } 00063 } 00064 00065 // Création d'une instance d'entité arme s'il existe un index d'entité libre 00066 CEntiteArme* CEntityManager::CreateArme () 00067 { 00068 int iIndex = GetIndexLibre (); 00069 return static_cast<CEntiteArme*> (iIndex != -1 ? m_pEntite[iIndex] = new CEntiteArme () : 0); 00070 } 00071 00072 // Création d'une instance d'entité bonus s'il existe un index d'entité libre 00073 CEntiteBonus* CEntityManager::CreateBonus () 00074 { 00075 int iIndex = GetIndexLibre (); 00076 return static_cast<CEntiteBonus*> (iIndex != -1 ? m_pEntite[iIndex] = new CEntiteBonus () : 0); 00077 } 00078 00079 // Création d'une instance d'entité ennemi s'il existe un index d'entité libre 00080 CEntiteEnnemi* CEntityManager::CreateEnnemi () 00081 { 00082 m_Statistique.m_uiEnnemiCree++; 00083 int iIndex = GetIndexLibre (); 00084 return static_cast<CEntiteEnnemi*> (iIndex != -1 ? m_pEntite[iIndex] = new CEntiteEnnemi () : 0); 00085 } 00086 00087 // Création d'une instance de joueur s'il existe un index d'entité libre 00088 CEntiteJoueur* CEntityManager::CreateJoueur () 00089 { 00090 int iIndex = GetIndexLibre (); 00091 return static_cast<CEntiteJoueur*> (iIndex != -1 ? m_pEntite[iIndex] = new CEntiteJoueur () : 0); 00092 } 00093 00094 // Seule cette fonction est autorisée a détruire une instance d'entités 00095 void CEntityManager::Kill (unsigned int uiIndex) 00096 { 00097 delete m_pEntite[uiIndex]; 00098 m_pEntite[uiIndex] = 0; 00099 } 00100 00101 // Mise à jour des statistiques de création et desctruction des entités de type ennemi 00102 void CEntityManager::Init () 00103 { 00104 m_Statistique.m_uiEnnemiCreeTotal += m_Statistique.m_uiEnnemiCree; 00105 m_Statistique.m_uiEnnemiDetruitTotal += m_Statistique.m_uiEnnemiDetruit; 00106 m_Statistique.m_uiEnnemiCree = 0; 00107 m_Statistique.m_uiEnnemiDetruit = 0; 00108 } 00109 00110 // Recherche d'une entrée libre dans la table des entités 00111 int CEntityManager::GetIndexLibre () const 00112 { 00113 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00114 if (m_pEntite[i] == 0) 00115 return i; 00116 return -1; 00117 } 00118 00119 // Détermine si un objet rond centrée sur Position est dans l'écran de jeu 00120 // /!\ L'écran de jeu est plus grand que la résolution de l'écran car il faut 00121 // une zone pour l'apparision (le spawn) des entités 00122 bool CEntityManager::EstDansEcran (CVecteur Position, float fTaille) const 00123 { 00124 if (Position (gtl::X) < (0 - fTaille)) 00125 return false; 00126 if (Position (gtl::X) > (FENETRE_LARGEUR + fTaille)) 00127 return false; 00128 if (Position (gtl::Y) < (0 - fTaille)) 00129 return false; 00130 if (Position (gtl::Y) > (FENETRE_HAUTEUR + fTaille + 128)) 00131 return false; 00132 return true; 00133 } 00134 00135 // Quand un propriétaire en détruit il est important de l'indiquer 00136 // à toutes les entités qu'il possède, afin qu’elle ne tente pas 00137 // de communiquer avec une instance qui n'existe plus ... 00138 bool CEntityManager::AnnulerProprietaire (CEntite* pEntite) 00139 { 00140 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00141 { 00142 if (!m_pEntite[i]) 00143 continue; 00144 00145 if (m_pEntite[i]->GetType () == ENTITE_ARME) 00146 { 00147 CEntiteArme* pArme = static_cast <CEntiteArme*> (m_pEntite[i]); 00148 if (pArme->GetProprietaire () == pEntite) 00149 pArme->SetProprietaire (0); 00150 } 00151 } 00152 return false; 00153 } 00154 00155 // La mise à jour des entités est effectué en deux temps : 00156 // - Détection de collisions 00157 // - Création et suppression des entités 00158 void CEntityManager::Update () 00159 { 00160 GererCollision (); 00161 UpdateEntite (); 00162 } 00163 00164 // Détection des collisions 00165 void CEntityManager::GererCollision () 00166 { 00167 // On parcours tous les entités, 2 fois ! C'est donc un algorithme en O(n²) ce qui est particulièrement long 00168 // Il faut essayé de l'optimiser au mieux en "brisant" les boucles le plus tôt possible 00169 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00170 { 00171 // L'entrée est null, on passe à l'entité suivante 00172 if (!m_pEntite[i]) 00173 continue; 00174 00175 // Les réactions aux collisions dépendant du type des unités 00176 switch (m_pEntite[i]->GetType ()) 00177 { 00178 default: 00179 break; 00180 // L'entité 1 est un joueur 00181 case ENTITE_JOUEUR: 00182 for (int j = 0; j < CTRL_ENTITE_NOMBRE; j++) 00183 { 00184 if (!m_pEntite[j]) 00185 continue; 00186 00187 // L'entité 2 est un ennemi 00188 if (m_pEntite[j]->GetType () == ENTITE_ENNEMI) 00189 { 00190 // On détermine la distance entre les entités 1 et 2 00191 CVecteur Distance = m_pEntite[i]->GetPosition () - m_pEntite[j]->GetPosition (); 00192 // Si la distance est trop petite alors on applique des dommages au 2 entités et on déplace l'entité 2 00193 if (sqrt (SQR(Distance (gtl::X)) + SQR(Distance (gtl::Y))) < (m_pEntite[i]->GetTaille () + m_pEntite[j]->GetTaille () / 2) * 0.75f) 00194 { 00195 m_pEntite[i]->AddDommage (m_pEntite[j]->GetDommage ()); 00196 m_pEntite[j]->AddDommage (m_pEntite[i]->GetDommage ()); 00197 m_pEntite[j]->Deplacer (-Distance.GetNormalize () * 8); 00198 break; 00199 } 00200 } 00201 } 00202 break; 00203 case ENTITE_BONUS: 00204 for (int j = 0; j < CTRL_ENTITE_NOMBRE; j++) 00205 { 00206 if (!m_pEntite[j]) 00207 continue; 00208 00209 // Seules les joueurs peuvent entrer en collision avec bonus 00210 if (m_pEntite[j]->GetType () == ENTITE_JOUEUR) 00211 { 00212 // On détermine la distance entre les 2 entités 00213 CVecteur Distance = m_pEntite[i]->GetPosition () - m_pEntite[j]->GetPosition (); 00214 // Si la distance est suffissament petite alors le joueur prend le bonus 00215 if (sqrt (SQR(Distance (gtl::X)) + SQR(Distance (gtl::Y))) < (m_pEntite[i]->GetTaille () / 2 + m_pEntite[j]->GetTaille ()) * 0.75f) 00216 { 00217 static_cast<CEntiteBonus *>(m_pEntite[i])->Contact (m_pEntite[j]); 00218 break; 00219 } 00220 } 00221 } 00222 break; 00223 case ENTITE_ARME: 00224 for (int j = 0; j < CTRL_ENTITE_NOMBRE; j++) 00225 { 00226 if (!m_pEntite[j]) 00227 continue; 00228 00229 // Une arme peu entrée en collision avec les ennemis, les joueurs, d'autres armes 00230 switch (m_pEntite[j]->GetType ()) 00231 { 00232 default: 00233 break; 00234 case ENTITE_ENNEMI: 00235 // On vérifie que le propriétaire de l'arme est un joueur 00236 if (static_cast<CEntiteArme*> (m_pEntite[i])->GetTypeProprietaire () == ENTITE_JOUEUR) 00237 { 00238 // On détermine la distance entre les 2 entités 00239 CVecteur Distance = m_pEntite[i]->GetPosition () - m_pEntite[j]->GetPosition (); 00240 if (sqrt (SQR(Distance (gtl::X)) + SQR(Distance (gtl::Y))) < (m_pEntite[i]->GetTaille () / 2 + m_pEntite[j]->GetTaille () / 2) * 0.75) 00241 { 00242 // on applique les dommages 00243 m_pEntite[i]->AddDommage (m_pEntite[j]->GetDommage ()); 00244 m_pEntite[j]->AddDommage (m_pEntite[i]->GetDommage ()); 00245 // Si l'ennemi est détruit alors le joueur qui a détruit l'ennemi marque des points 00246 if (m_pEntite[j]->GetBouclier () <= 0) 00247 { 00248 CEntiteJoueur* pJoueur = static_cast<CEntiteJoueur*> (static_cast<CEntiteArme*> (m_pEntite[i])->GetProprietaire ()); 00249 CEntiteEnnemi* pEnnemi = static_cast<CEntiteEnnemi*> (m_pEntite[j]); 00250 pJoueur->AjouterPoint (pEnnemi->GetPoint ()); 00251 } 00252 break; 00253 } 00254 } 00255 break; 00256 case ENTITE_JOUEUR: 00257 // On vérifie que le propriétaire de l'arme est un ennemi 00258 if (static_cast<CEntiteArme*> (m_pEntite[i])->GetTypeProprietaire () == ENTITE_ENNEMI) 00259 { 00260 CVecteur Distance = m_pEntite[i]->GetPosition () - m_pEntite[j]->GetPosition (); 00261 if (sqrt (SQR(Distance (gtl::X)) + SQR(Distance (gtl::Y))) < (m_pEntite[i]->GetTaille () / 2 + m_pEntite[j]->GetTaille ()) * 0.75f) 00262 { 00263 m_pEntite[i]->AddDommage (m_pEntite[j]->GetDommage ()); 00264 m_pEntite[j]->AddDommage (m_pEntite[i]->GetDommage ()); 00265 } 00266 } 00267 break; 00268 case ENTITE_ARME: 00269 // Si les deux armes ont des propriétaires de types différents alors on vérifie s'il y a collision 00270 if (((static_cast<CEntiteArme*> (m_pEntite[i])->GetTypeProprietaire () == ENTITE_ENNEMI) 00271 && (static_cast<CEntiteArme*> (m_pEntite[j])->GetTypeProprietaire () == ENTITE_JOUEUR)) 00272 ||((static_cast<CEntiteArme*> (m_pEntite[i])->GetTypeProprietaire () == ENTITE_JOUEUR) 00273 && (static_cast<CEntiteArme*> (m_pEntite[j])->GetTypeProprietaire () == ENTITE_ENNEMI))) 00274 { 00275 CVecteur Distance = m_pEntite[i]->GetPosition () - m_pEntite[j]->GetPosition (); 00276 if (sqrt (SQR(Distance (gtl::X)) + SQR(Distance (gtl::Y))) < (m_pEntite[i]->GetTaille () / 2 + m_pEntite[j]->GetTaille () / 2) * 0.75f) 00277 { 00278 m_pEntite[i]->AddDommage (m_pEntite[j]->GetDommage ()); 00279 m_pEntite[j]->AddDommage (m_pEntite[i]->GetDommage ()); 00280 } 00281 } 00282 break; 00283 } 00284 } 00285 break; 00286 } 00287 } 00288 } 00289 00290 // Mise à jour des entités 00291 void CEntityManager::UpdateEntite () 00292 { 00293 // La mise à jour des entités s'effectues entité par entité 00294 // On parcours donc toutes les entités ! 00295 for (int i = 0; i < CTRL_ENTITE_NOMBRE; i++) 00296 { 00297 // On vérifi que le pointeur n'est pas null, c'est à dire qu'il pointe vers une instance d'entité. 00298 if (m_pEntite[i]) 00299 { 00300 // On actualise l'entité 00301 m_pEntite[i]->Update (); 00302 00303 // Si l'entité n'est plus dans l'écran de jeu ou n'a plus de vie alors on la détruit 00304 if (!EstDansEcran (m_pEntite[i]->GetPosition (), m_pEntite[i]->GetTaille ()) 00305 || m_pEntite[i]->GetBouclier () <= 0) 00306 { 00307 switch (m_pEntite[i]->GetType ()) 00308 { 00309 default: 00310 break; 00311 case ENTITE_ENNEMI: 00312 // Indique à chaque entité dont l'ennemi est le propriétaire que son propriétaire a été détruit 00313 AnnulerProprietaire (m_pEntite[i]); 00314 m_Statistique.m_uiEnnemiDetruit++; 00315 break; 00316 case ENTITE_JOUEUR: 00317 // Indique à chaque entité dont le jour est le propriétaire que son propriétaire a été détruit 00318 AnnulerProprietaire (m_pEntite[i]); 00319 CGameManager::Instance ()->InitJoueur (static_cast<CEntiteJoueur*> (m_pEntite[i])); 00320 break; 00321 case ENTITE_BONUS: 00322 break; 00323 case ENTITE_ARME: 00324 break; 00325 } 00326 00327 Kill (i); 00328 // l'entité est détruite, on passe à l'entité suivante 00329 continue; 00330 } 00331 00332 // Commande aux entités de type ennemi de tirer 00333 if (m_pEntite[i]->GetType () == ENTITE_ENNEMI) 00334 static_cast<CEntiteEnnemi*> (m_pEntite[i])->Action (); 00335 00336 // Commande aux entités de type joueur de tirer 00337 if (m_pEntite[i]->GetType () == ENTITE_JOUEUR) 00338 static_cast<CEntiteJoueur*> (m_pEntite[i])->Action (); 00339 } 00340 } 00341 } 00342 00343 // Offre un accès aux entités. On prend bien garde à ce que les entités 00344 // ne soit pas modifier à l'aide du qualificateur const 00345 const CEntite* const CEntityManager::GetEntiteParIndex (unsigned int uiIndex) const 00346 { 00347 // On prend soit de vérifier la valeur de l'index afin déviter l'exception out_of_range. 00348 if (uiIndex < CTRL_ENTITE_NOMBRE) 00349 return m_pEntite[uiIndex]; 00350 return 0; 00351 } 00352

Généré le Sun Sep 26 11:36:46 2004 pour Shoot(r) par doxygen 1.3.8