/***************************************************************************** * * Copyright (C) 2003 Cédric Brégardis * * This file is part of BRIQUOLO * * BRIQUOLO is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * BRIQUOLO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with BRIQUOLO; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *****************************************************************************/ #include "TableauJeu.h" #include "BonusFast.h" #include "BonusSlow.h" #include "BonusPetit.h" #include "BonusGros.h" #include "BonusPetitPlateau.h" #include "BonusGrosPlateau.h" #include "BonusDoubleBalle.h" #include "BonusSuperPuissance.h" #include "BonusVueSubjective.h" #include "ExplosionBrique.h" #include "BibliothequeSon.h" #include "Option.h" #include TableauJeu::TableauJeu(MOGL_Fenetre * p_Fenetre) : TableauBase(p_Fenetre), _ProbaBonus(0.2f), _FinTableau(false), _NombreVie(5), _VibrationX(0), _VibrationY(0), _CummulDep(0) { Plateau * _Plateau=new Plateau; _Plateau->SetPosition(20, 1); AjouterPlateau(_Plateau); _Camera=new Camera(_Plateau); _Univers->SetCamera(_Camera->GetMOGLCamera()); _TemporisationFinTableau=new MOGL_Temporisation(3, false, false); _TemporisationFinTableau->FinTemporisation.Connecter(this, &TableauJeu::_OnFinTemporisation); _Univers->AjouterElement(_TemporisationFinTableau); _TemporisationDepartBalle=new MOGL_Temporisation(3, false, false); _TemporisationDepartBalle->FinTemporisation.Connecter(this, &TableauJeu::_OnDepartBalle); _Univers->AjouterElement(_TemporisationDepartBalle); _NombreVie--; DepartTableau(); } TableauJeu::~TableauJeu() { for(Set_Balle::iterator itBa=_SetBalle.begin(); itBa!=_SetBalle.end(); itBa++) { delete (*itBa); } for(Set_Plateau::iterator itPla=_SetPlateau.begin(); itPla!=_SetPlateau.end(); itPla++) { delete (*itPla); } for(Set_Bonus::iterator itBo=_SetBonus.begin(); itBo!=_SetBonus.end(); itBo++) { delete (*itBo); } Set_Generateur::iterator itGe; for(itGe=_SetGenerateur.begin(); itGe!=_SetGenerateur.end(); itGe++) { _Univers->RetirerElement(*itGe); delete (*itGe); } for(itGe=_SetGenerateurADetruire.begin(); itGe!=_SetGenerateurADetruire.end(); itGe++) { _Univers->RetirerElement(*itGe); delete (*itGe); } delete _Camera; delete _TemporisationDepartBalle; delete _TemporisationFinTableau; } void TableauJeu::DepartTableau() { _Camera->SetVueSubjective(false); for(Set_Balle::iterator itBa=_SetBalle.begin(); itBa!=_SetBalle.end(); itBa++) { _Univers->RetirerElement((*itBa)->GetElementArbreMOGL()); delete (*itBa); } _SetBalle.clear(); for(Set_Plateau::iterator itPla=_SetPlateau.begin(); itPla!=_SetPlateau.end(); itPla++) { (*itPla)->SetPosition(20, 1); (*itPla)->SetTaille(5); } if (_NombreVie>=0) { ElementTableau::SetDerniereCollision(NULL, NULL); Balle * balle=new Balle; balle->SetTaille(1.5); AjouterBalle(balle); _BallePartie=false; _TemporisationDepartBalle->Demarrer(); balle->SetPosition((*_SetPlateau.begin())->GetPositionX(), (*_SetPlateau.begin())->GetPositionY() + (*_SetPlateau.begin())->GetTailleY()/2 + balle->GetRayon()); } else { FinBalle.Emettre(); } // RAZ du cumul de déplacement _CummulDep = 0; } void TableauJeu::AjouterBalle(Balle * p_Balle) { _SetBalle.insert(p_Balle); _Univers->AjouterElement(p_Balle->GetElementArbreMOGL()); } bool TableauJeu::RetirerBalle(Balle * p_Balle) { Set_Balle::iterator it=_SetBalle.find(p_Balle); if (it!=_SetBalle.end()) { _Univers->RetirerElement(p_Balle->GetElementArbreMOGL()); delete (*it); _SetBalle.erase(it); return true; } else { return false; } } void TableauJeu::AjouterPlateau(Plateau * p_Plateau) { p_Plateau->SetMinX(_XMin); p_Plateau->SetMaxX(_XMax); _SetPlateau.insert(p_Plateau); _Univers->AjouterElement(p_Plateau->GetElementArbreMOGL()); } bool TableauJeu::RetirerPlateau(Plateau * p_Plateau) { Set_Plateau::iterator it=_SetPlateau.find(p_Plateau); if (it!=_SetPlateau.end()) { _Univers->RetirerElement(p_Plateau->GetElementArbreMOGL()); _SetPlateau.erase(it); return true; } else { return false; } } void TableauJeu::Maj() { Set_Balle setBalleADetruire; if (!_FinTableau) { // On détruit les générateur de particules for(Set_Generateur::iterator itGenerateur=_SetGenerateurADetruire.begin(); itGenerateur!=_SetGenerateurADetruire.end(); itGenerateur++) { _Univers->RetirerElement(*itGenerateur); delete (*itGenerateur); } _SetGenerateurADetruire.clear(); // On regarde les bonus pour voir si on en attrape Set_Bonus setBonusADetruire; Set_Bonus::iterator itBonus; for(itBonus=_SetBonus.begin(); itBonus!=_SetBonus.end(); itBonus++) { for(Set_Plateau::iterator itPlat=_SetPlateau.begin(); itPlat!=_SetPlateau.end(); itPlat++) { if ((*itBonus)->Mouvement(*itPlat, this) || (*itBonus)->GetPositionY()+(*itBonus)->GetTailleY()/2<_YMin) { setBonusADetruire.insert(*itBonus); break; } } } for(itBonus=setBonusADetruire.begin(); itBonus!=setBonusADetruire.end(); itBonus++) { _Univers->RetirerElement((*itBonus)->GetElementArbreMOGL()); //delete (*itBonus); Set_Bonus::iterator it=_SetBonus.find(*itBonus); if (it!=_SetBonus.end()) { delete (*it); _SetBonus.erase(it); } } // On fait une mise à jour des élément du tableau for(Set_ElementTableau::iterator itElem=_SetElementTableau.begin(); itElem!=_SetElementTableau.end(); itElem++) { (*itElem)->Maj(); } // Mise à jour de la vibration _VibrationX -= MOGL_Temps::GetVariationTemps(); if (_VibrationX < 0) { _VibrationX = 0; } _VibrationY -= MOGL_Temps::GetVariationTemps(); if (_VibrationY < 0) { _VibrationY = 0; } float offx = cosf(_VibrationX * 20000) * 0.2 * _VibrationX; float offy = sinf(_VibrationY * 20000) * 0.2 * _VibrationY; _Camera->SetOffset(offx, offy); // On s'occupe de la collision de la balle Set_Balle::iterator itBalle; for(itBalle=_SetBalle.begin(); itBalle!=_SetBalle.end(); itBalle++) { (*itBalle)->MajVitesse(); float remainingTime = MOGL_Temps::GetVariationTemps(); while (remainingTime>0) { (*itBalle)->SetTempsMax(remainingTime); // ####################### // ## On regarde tous les trucs sur lesquels il peut y avoir collision // ####################### Struct_Collision collision, collisionTemps; collision.TempsCollision=(*itBalle)->GetTempsMax(); //ElementTableau * element=NULL; bool collisionElementTableau=false; //(*itBalle)->PreparerDeplacement(facteur); // On regarde tous les plateaux if (_BallePartie) { for(Set_Plateau::iterator itPlat=_SetPlateau.begin(); itPlat!=_SetPlateau.end(); itPlat++) { if ((*itPlat)->IsDerniereCollisionOk(*itBalle)) { collisionTemps=(*itPlat)->TesterCollision(*itBalle); if (collisionTemps.TempsCollision < collision.TempsCollision) { collision=collisionTemps; collisionElementTableau=true; collision.ResponsableCollision = *itPlat; } } } } // On regarde les bords collisionTemps=_CollisionBord(*itBalle); if (collisionTemps.TempsCollision < collision.TempsCollision) { collision=collisionTemps; } // On regarde tous les éléments du tableau for(Set_ElementTableau::iterator itElem=_SetElementTableau.begin(); itElem!=_SetElementTableau.end(); itElem++) { if ((*itElem)->IsDerniereCollisionOk(*itBalle)) { collisionTemps=(*itElem)->TesterCollision(*itBalle); if (collisionTemps.TempsCollision < collision.TempsCollision) { collision=collisionTemps; collisionElementTableau=true; collision.ResponsableCollision = *itElem; } } } // ####################### // Parmis les différentes collisions on regarde cel // ####################### // MAJ vitesse déplacement des plateaux selon le déplacement // cumulé DeplacerPlateaux(_CummulDep); // RAZ du cumul de déplacement _CummulDep = 0; // On déplace les plateaux for(Set_Plateau::iterator itPlat=_SetPlateau.begin(); itPlat!=_SetPlateau.end(); itPlat++) { (*itPlat)->Deplacer(collision.TempsCollision); } // On déplace la balle (*itBalle)->Deplacer(collision.TempsCollision); // La structure de collision indique un temps inférieur au temps max de placement. // Cela signifie qu'une collision a eu lieu if (collision.TempsCollisionSetVitesse(collision.VitesseX, collision.VitesseY); // Si c'est un élément on lui dit qu'il a été touché bool detruire=false; if (collisionElementTableau) { detruire=collision.ResponsableCollision->Toucher(*itBalle, collision.TempsCollision); } else { // C'est pas une brique donc on joue le son du rebond standard BibliothequeSon::SonRebond->Jouer(false); } // On fait apparaitre un système de particules ? if (collisionElementTableau) { Generateur * generateur=collision.ResponsableCollision->CreerGenerateurParticules(); if (generateur!=NULL) { AjouterGenerateur(generateur); } } // On stocke ce qui a causé la collision if (collisionElementTableau) { ElementCollision::SetDerniereCollision(collision.ResponsableCollision, *itBalle); } else { ElementCollision::SetDerniereCollision(NULL, NULL); } if (detruire) { // Il faut détruire l'élément de la collision // On fait apparaitre un bonus ? Point pt = collision.ResponsableCollision->GetVisualCenter(); CreerBonus(pt.x, pt.y); // On efface l'élément ElementTableau * elem = dynamic_cast(collision.ResponsableCollision); if (elem != NULL) { RetirerElementTableau(elem); } delete collision.ResponsableCollision; } if (!detruire || !(*itBalle)->GetSuperPuissance()) { (*itBalle)->SetPosition(collision.PositionX, collision.PositionY); (*itBalle)->SetVitesseTotale(collision.VitesseX, collision.VitesseY); (*itBalle)->AddAcceleration(collision.AddFacteurCollision); } } else { // Il n'y a pas eu collision //(*itBalle)->SetPosition((*itBalle)->GetArriveeX(), (*itBalle)->GetArriveeY()); //(*itBalle)->Deplacer(remainingTime); } // On regarde si la balle disparait if ((*itBalle)->GetPositionY()<_YMin) { setBalleADetruire.insert(*itBalle); } remainingTime -= collision.TempsCollision; } } for(itBalle=setBalleADetruire.begin(); itBalle!=setBalleADetruire.end(); itBalle++) { RetirerBalle(*itBalle); } // On regarde si il reste des éléments à détruire unsigned int nbElemReste=0; for(Set_ElementTableau::iterator itElem2=_SetElementTableau.begin(); itElem2!=_SetElementTableau.end(); itElem2++) { if (!(*itElem2)->EstDecors()) { nbElemReste++; } } if (nbElemReste==0) { _FinTableau=true; _TemporisationFinTableau->Demarrer(); } if (_SetBalle.size()==0) { _NombreVie--; DepartTableau(); for(Set_Bonus::iterator itBo=_SetBonus.begin(); itBo!=_SetBonus.end(); itBo++) { _Univers->RetirerElement((*itBo)->GetElementArbreMOGL()); delete (*itBo); } _SetBonus.clear(); } } _Camera->Maj(); } Struct_Collision TableauJeu::_CollisionBord(Balle * p_Balle) { Struct_Collision collision; collision.TempsCollision=p_Balle->GetTempsMax(); collision.VitesseX=p_Balle->GetVitesseTotaleX(); collision.VitesseY=p_Balle->GetVitesseTotaleY(); /* collision.VitesseX=p_Balle->GetVitesseX(); collision.VitesseY=p_Balle->GetVitesseY(); */ float rayon=p_Balle->GetRayon(); if (p_Balle->GetPositionX()<_XMin+rayon)// && tGetTempsMax(); collision.PositionX=_XMin+rayon+0.001; collision.PositionY= p_Balle->GetPositionY();//t*(p_Balle->GetArriveeY()-p_Balle->GetPositionY())+p_Balle->GetPositionY(); collision.VitesseX=-p_Balle->GetVitesseTotaleX(); collision.VitesseY=p_Balle->GetVitesseTotaleY(); } // t=(_XMax-rayon-p_Balle->GetPositionX())/(p_Balle->GetArriveeX()-p_Balle->GetPositionX()); if (p_Balle->GetPositionX()>_XMax-rayon)// && tGetTempsMax(); collision.PositionX=_XMax-rayon-0.001; collision.PositionY= p_Balle->GetPositionY(); // t*(p_Balle->GetArriveeY()-p_Balle->GetPositionY())+p_Balle->GetPositionY(); collision.VitesseX=-p_Balle->GetVitesseTotaleX(); collision.VitesseY=p_Balle->GetVitesseTotaleY(); } // t=(_YMax-rayon-p_Balle->GetPositionY())/(p_Balle->GetArriveeY()-p_Balle->GetPositionY()); if (p_Balle->GetPositionY()>_YMax-rayon)// && tGetTempsMax(); collision.PositionY=_YMax-rayon; collision.PositionX=p_Balle->GetPositionX(); //t*(p_Balle->GetArriveeX()-p_Balle->GetPositionX())+p_Balle->GetPositionX(); collision.VitesseY=-p_Balle->GetVitesseTotaleY(); collision.VitesseX=p_Balle->GetVitesseTotaleX(); } return collision; } void TableauJeu::DeplacerPlateaux(float p_Distance) { // On regarde tous les plateaux for(Set_Plateau::iterator itPlat=_SetPlateau.begin(); itPlat!=_SetPlateau.end(); itPlat++) { if (MOGL_Temps::GetVariationTemps() != 0) { (*itPlat)->SetVitesse(p_Distance/MOGL_Temps::GetVariationTemps()); } } /* // On déplace les plateaux for(Set_Plateau::iterator itPlat=_SetPlateau.begin(); itPlat!=_SetPlateau.end(); itPlat++) { (*itPlat)->Deplacer(p_Distance); } */ } TableauJeu::Set_ElementTableau * TableauJeu::GetSetElementTableau() { return &_SetElementTableau; } TableauJeu::Set_Balle * TableauJeu::GetSetBalle() { return &_SetBalle; } TableauJeu::Set_Plateau * TableauJeu::GetSetPlateau() { return &_SetPlateau; } TableauJeu::Set_Bonus * TableauJeu::GetSetBonus() { return &_SetBonus; } TableauJeu::Set_Generateur * TableauJeu::GetSetGenerateur() { return &_SetGenerateur; } void TableauJeu::CreerBonus(float p_X, float p_Y) { // Il faut détruire l'élément de la collision // On fait apparaitre un bonus ? if (rand()/static_cast(RAND_MAX)<_ProbaBonus) { Bonus * bonus=_CreerBonus(); bonus->SetPosition(p_X, p_Y); _SetBonus.insert(bonus); _Univers->AjouterElement(bonus->GetElementArbreMOGL()); } } void TableauJeu::AjouterGenerateur(Generateur * p_Generateur) { _SetGenerateur.insert(p_Generateur); p_Generateur->FinGenerateur.Connecter(this, &TableauJeu::OnFinGenerateur); _Univers->AjouterElement(p_Generateur); } void TableauJeu::OnFinGenerateur(Generateur * p_Generateur) { Set_Generateur::iterator it=_SetGenerateur.find(p_Generateur); if (it!=_SetGenerateur.end()) { _SetGenerateur.erase(it); } _SetGenerateurADetruire.insert(p_Generateur); } Bonus * TableauJeu::_CreerBonus() { unsigned int nbBonus=9; float valInd=1.0/nbBonus; float al=rand()/static_cast(RAND_MAX); if (alsym) { case SDLK_c : { _Camera->ChangerVue(); break; } case SDLK_SPACE : { _OnDepartBalle(); break; } default: break; } } void TableauJeu::ClavierDown(SDL_keysym * key) { switch (key->sym) { case SDLK_LEFT : { _CummulDep = MOGL_Temps::GetVariationDistance(Option::VitesseClavier.GetValeur() * -10); if (!_BallePartie) { for(Set_Balle::iterator it=_SetBalle.begin(); it!=_SetBalle.end(); it++) { (*it)->SetPosition((*_SetPlateau.begin())->GetPositionX(), (*_SetPlateau.begin())->GetPositionY() + (*_SetPlateau.begin())->GetTailleY()/2 + (*it)->GetRayon()); } } break; } case SDLK_RIGHT : { _CummulDep = MOGL_Temps::GetVariationDistance(Option::VitesseClavier.GetValeur() * 10); if (!_BallePartie) { for(Set_Balle::iterator it=_SetBalle.begin(); it!=_SetBalle.end(); it++) { (*it)->SetPosition((*_SetPlateau.begin())->GetPositionX(), (*_SetPlateau.begin())->GetPositionY() + (*_SetPlateau.begin())->GetTailleY()/2 + (*it)->GetRayon()); } } break; } default: break; } } void TableauJeu::DeplacementSouris(SDL_MouseMotionEvent * p_Event) { static bool bNotFirstDep = false; if (bNotFirstDep) { int val=p_Event->xrel; _CummulDep += val * Option::VitesseSouris.GetValeur()/50.0; } else { bNotFirstDep = true; _CummulDep = 0; } if (!_BallePartie) { for(Set_Balle::iterator it=_SetBalle.begin(); it!=_SetBalle.end(); it++) { (*it)->SetPosition((*_SetPlateau.begin())->GetPositionX(), (*_SetPlateau.begin())->GetPositionY() + (*_SetPlateau.begin())->GetTailleY()/2 + (*it)->GetRayon()); } } } void TableauJeu::_OnFinTemporisation() { FinTableau.Emettre(); _FinTableau=false; } void TableauJeu::_OnDepartBalle() { if (!_BallePartie) { _TemporisationDepartBalle->Arreter(); for(Set_Balle::iterator it=_SetBalle.begin(); it!=_SetBalle.end(); it++) { (*it)->SetVitesseTotale(5,35); } _BallePartie=true; } } void TableauJeu::BoutonSourisDown(SDL_MouseButtonEvent * p_Event) { _OnDepartBalle(); } int TableauJeu::GetNombreVie() const { return _NombreVie; } void TableauJeu::SetNombreVie(int p_NombreVie) { _NombreVie=p_NombreVie; } void TableauJeu::SetVibration(float pVibrationX, float pVibrationY) { _VibrationX = pVibrationX; _VibrationY = pVibrationY; }