src/map/map.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * Monde ou plateau de jeu.
00020  *****************************************************************************/
00021 
00022 #include "map.h"
00023 #include <iostream>
00024 #include "camera.h"
00025 #include "maps_list.h"
00026 #include "wind.h"
00027 #include "../game/config.h"
00028 #include "../game/time.h"
00029 #include "../graphic/surface.h"
00030 #include "../graphic/font.h"
00031 #include "../include/constant.h"
00032 #include "../object/bonus_box.h"
00033 #include "../tool/i18n.h"
00034 #include "../tool/stats.h"
00035 
00036 const double DST_MIN_ENTRE_VERS = 50.0;
00037 
00038 const uint AUTHOR_INFO_TIME = 5000; // ms
00039 const uint AUTHOR_INFO_X = 100;
00040 const uint AUTHOR_INFO_Y = 50;
00041 
00042 Map world;
00043 
00044 Map::Map()
00045 {
00046   dst_min_entre_vers = DST_MIN_ENTRE_VERS;
00047 
00048   to_redraw = new std::list<Rectanglei>;
00049   to_redraw_now = new std::list<Rectanglei>;
00050   to_redraw_particles = new std::list<Rectanglei>;
00051   to_redraw_particles_now = new std::list<Rectanglei>;
00052 }
00053 
00054 Map::~Map()
00055 {
00056   delete to_redraw;
00057   delete to_redraw_now;
00058   delete to_redraw_particles;
00059   delete to_redraw_particles_now;
00060 }
00061 
00062 void Map::Reset()
00063 {
00064   sky.Reset();
00065   ground.Reset();
00066   water.Reset();
00067   wind.Reset();
00068 
00069   // Configure le jeu selon que le terrain soit ouvert ou non
00070   bool ouvert = ground.EstOuvert();
00071   BonusBox::Enable(ouvert);
00072   Config::GetInstance()->SetExterieurMondeVide(  ouvert );
00073 
00074   delete author_info1; author_info1 = NULL;
00075   delete author_info2; author_info2 = NULL;
00076 
00077   to_redraw->clear();
00078   to_redraw_now->clear();
00079   to_redraw_particles->clear();
00080   to_redraw_particles_now->clear();
00081 }
00082 
00083 void Map::Refresh()
00084 {
00085   water.Refresh();
00086   wind.Refresh();
00087 }
00088 
00089 void Map::FreeMem()
00090 {
00091   ground.Free();
00092   sky.Free();
00093   water.Free();
00094 
00095   to_redraw->clear();
00096   to_redraw_now->clear();
00097   to_redraw_particles->clear();
00098   to_redraw_particles_now->clear();
00099 }
00100 
00101 void Map::ToRedrawOnMap(Rectanglei r)
00102 {
00103   to_redraw->push_back(r);
00104 }
00105 
00106 void Map::ToRedrawOnScreen(Rectanglei r)
00107 {
00108   r.SetPosition( r.GetPosition() + camera.GetPosition() );
00109   to_redraw->push_back( r );
00110 }
00111 
00112 void Map::SwitchDrawingCache()
00113 {
00114   std::list<Rectanglei> *tmp = to_redraw_now;
00115   to_redraw_now = to_redraw;
00116   to_redraw = tmp;
00117   to_redraw->clear();
00118 }
00119 
00120 void Map::SwitchDrawingCacheParticles()
00121 {
00122   std::list<Rectanglei> *tmp = to_redraw_particles_now;
00123   to_redraw_particles_now = to_redraw_particles;
00124   to_redraw_particles = tmp;
00125   to_redraw_particles->clear();
00126 }
00127 
00128 void Map::Dig(const Point2i position, const Surface& surface)
00129 {
00130    ground.Dig (position, surface);
00131    to_redraw->push_back(Rectanglei(position, surface.GetSize()));
00132 }
00133 
00134 void Map::Dig(const Point2i center, const uint radius)
00135 {
00136    ground.Dig (center, radius);
00137    to_redraw->push_back(Rectanglei(center - Point2i(radius+EXPLOSION_BORDER_SIZE,radius+EXPLOSION_BORDER_SIZE)
00138                                       , Point2i(2*(radius+EXPLOSION_BORDER_SIZE),2*(radius+EXPLOSION_BORDER_SIZE))));
00139 }
00140 
00141 void Map::PutSprite(const Point2i pos, Sprite* spr)
00142 {
00143    ground.PutSprite (pos, spr);
00144    to_redraw->push_back(Rectanglei(pos, spr->GetSizeMax()));
00145 }
00146 
00147 void Map::MergeSprite(const Point2i pos, Sprite * spr)
00148 {
00149   Surface tmp = spr->GetSurface();
00150   ground.MergeSprite (pos, tmp);
00151   to_redraw->push_back(Rectanglei(pos, spr->GetSizeMax()));
00152 }
00153 
00154 void Map::DrawSky()
00155 {
00156   SwitchDrawingCache();
00157   SwitchDrawingCacheParticles();
00158   
00159   OptimizeCache(*to_redraw_now);
00160 
00161   sky.Draw();
00162 }
00163 
00164 void Map::DrawWater()
00165 { water.Draw(); }
00166 
00167 void Map::Draw()
00168 {
00169   std::list<Rectanglei> *tmp = to_redraw;
00170   to_redraw_particles->clear();
00171   to_redraw = to_redraw_particles;
00172 
00173   wind.DrawParticles();
00174   to_redraw = tmp;
00175 
00176   OptimizeCache(*to_redraw_now);
00177 
00178   ground.Draw();
00179 }
00180 
00181 bool Map::EstHorsMondeX(int x) const{
00182   return (x < 0) || ((int)GetWidth() <= x);
00183 }
00184 
00185 bool Map::EstHorsMondeY(int y) const{
00186   return (y < 0) || ((int)GetHeight() <= y);
00187 }
00188 
00189 bool Map::EstHorsMondeXlarg(int x, uint larg) const{
00190   return (x + (int)larg - 1 < 0) || ((int)GetWidth() <= x);
00191 }
00192 
00193 bool Map::EstHorsMondeYhaut(int y, uint haut) const{
00194   return ((y + (int)haut - 1 < 0) || ((int)GetHeight() <= y));
00195 }
00196 
00197 bool Map::EstHorsMondeXY(int x, int y) const{
00198   return EstHorsMondeX(x) || EstHorsMondeY(y);
00199 }
00200 
00201 bool Map::EstHorsMonde (const Point2i &pos) const{
00202   return EstHorsMondeXY(pos.x, pos.y);
00203 }
00204 
00205 bool Map::EstDansVide(int x, int y){
00206   return ground.IsEmpty(Point2i(x, y));
00207 }
00208 
00209 bool Map::LigneH_EstDansVide (int ox, int y, int width)
00210 {
00211   // Traite une ligne
00212   for (int i=0; i<width; i++)
00213         if (!EstDansVide(ox+i, (uint)y))
00214           return false;
00215 
00216    return true;
00217 }
00218 
00219 // TODO : for consistency, LigneV_EstDansVide should use a 'height' as LigneH does it ...
00220 bool Map::LigneV_EstDansVide (int x, int top, int bottom)
00221 {
00222   assert (top <= bottom);
00223 
00224   // V�ifie qu'on reste dans le monde
00225   if (EstHorsMondeX(x) || EstHorsMondeYhaut(top, bottom-top+1))
00226     return Config::GetInstance()->GetExterieurMondeVide();
00227   if (top < 0) top = 0;
00228   if ((int)GetHeight() <= bottom) bottom = GetHeight()-1;
00229 
00230   // Traite une ligne
00231   for (uint iy=(uint)top; iy<=(uint)bottom; iy++)
00232   {
00233     if (!EstDansVide((uint)x, iy)) return false;
00234   }
00235   return true;
00236 }
00237 
00238 bool Map::RectEstDansVide (const Rectanglei &prect)
00239 {
00240    // only check whether the border touch the ground
00241 
00242    Rectanglei rect(prect);
00243 
00244    // Clip rectangle in the the world area
00245    rect.Clip( Rectanglei(0, 0, GetWidth(), GetHeight()) );
00246 
00247    // Only check the borders of the rectangle
00248    if(rect.GetSizeX()==0 || rect.GetSizeY()==0)
00249      return true;
00250 
00251    if(!LigneH_EstDansVide (rect.GetPositionX(), rect.GetPositionY(), rect.GetSizeX()))
00252      return false;
00253 
00254    if(rect.GetSizeY() > 1)
00255    {
00256      if(!LigneH_EstDansVide (rect.GetPositionX(), rect.GetPositionY() + rect.GetSizeY() - 1, rect.GetSizeX()))
00257        return false;
00258      if(!LigneV_EstDansVide (rect.GetPositionX(), rect.GetPositionY(), rect.GetPositionY() + rect.GetSizeY() -1))
00259        return false;
00260 
00261      if(rect.GetSizeX() > 1)
00262      if(!LigneV_EstDansVide (rect.GetPositionX()+rect.GetSizeX()-1, rect.GetPositionY(), rect.GetPositionY() + rect.GetSizeY() -1))
00263        return false;
00264    }
00265 
00266    return true;
00267 }
00268 
00269 bool Map::ParanoiacRectIsInVacuum(const Rectanglei &prect)
00270 {
00271    // only check whether the rectangle touch the ground pixel by pixel
00272    // Prefere using the method above, as performing a pixel by pixel test is quite slow!
00273 
00274    Rectanglei rect(prect);
00275 
00276    // Clip rectangle in the the world area
00277    rect.Clip( Rectanglei(0, 0, GetWidth(), GetHeight()) );
00278 
00279    // Check line by line
00280    for( int i = rect.GetPositionY(); i < rect.GetPositionY() + rect.GetSizeY(); i++ )
00281      if( !LigneH_EstDansVide (rect.GetPositionX(), i, rect.GetSizeX()) )
00282        return false;
00283 
00284    return true;
00285 }
00286 
00287 bool Map::EstDansVide_haut (const PhysicalObj &obj, int dx, int dy)
00288 {
00289   return LigneH_EstDansVide (obj.GetTestRect().GetPositionX() + dx,
00290                              obj.GetTestRect().GetPositionY() + obj.GetTestRect().GetSizeY() + dy,
00291                              obj.GetTestRect().GetSizeX());
00292 }
00293 
00294 bool Map::EstDansVide_bas (const PhysicalObj &obj, int dx, int dy)
00295 {
00296   return LigneH_EstDansVide (obj.GetTestRect().GetPositionX() + dx,
00297                              obj.GetTestRect().GetPositionY() + dy,
00298                              obj.GetTestRect().GetSizeX());
00299 }
00300 
00301 bool Map::IsInVacuum_left (const PhysicalObj &obj, int dx, int dy)
00302 {
00303   return LigneV_EstDansVide (obj.GetTestRect().GetPositionX() + dx,
00304                              obj.GetTestRect().GetPositionY() + dy,
00305                              obj.GetTestRect().GetPositionY() + obj.GetTestRect().GetSizeY() + dy);
00306 }
00307 
00308 bool Map::IsInVacuum_right (const PhysicalObj &obj, int dx, int dy)
00309 {
00310   return LigneV_EstDansVide (obj.GetTestRect().GetPositionX() + obj.GetTestRect().GetSizeX() + dx,
00311                              obj.GetTestRect().GetPositionY() + dy,
00312                              obj.GetTestRect().GetPositionY() + obj.GetTestRect().GetSizeY() + dy);
00313 }
00314 
00315 void Map::DrawAuthorName()
00316 {
00317   if (AUTHOR_INFO_TIME < Time::GetInstance()->Read()) {
00318     if (author_info1 != NULL) {
00319       delete author_info1;
00320       delete author_info2;
00321       author_info1 = author_info2 = NULL;
00322     }
00323     return;
00324   }
00325 
00326   if (author_info1 == NULL) {
00327     std::string txt;
00328     txt  = Format(_("Map %s, a creation of: "),
00329                   ActiveMap().ReadName().c_str());
00330     author_info1 = new Text(txt, white_color, Font::GetInstance(Font::FONT_SMALL));
00331     txt = ActiveMap().ReadAuthorInfo();
00332     author_info2 = new Text(txt, white_color, Font::GetInstance(Font::FONT_SMALL));
00333   }
00334 
00335   author_info1->DrawTopLeft(AUTHOR_INFO_X,AUTHOR_INFO_Y);
00336   author_info2->DrawTopLeft(AUTHOR_INFO_X,AUTHOR_INFO_Y+(*Font::GetInstance(Font::FONT_SMALL)).GetHeight());
00337 }
00338 
00339 bool CompareRectangle(const Rectanglei& a, const Rectanglei& b)
00340 {
00341   return ( a.GetTopLeftPoint() <= b.GetTopLeftPoint() );
00342 }
00343 
00344 void Map::OptimizeCache(std::list<Rectanglei>& rectangleCache)
00345 {
00346   rectangleCache.sort(CompareRectangle);
00347         
00348   std::list<Rectanglei>::iterator it = rectangleCache.begin(),
00349     jt = rectangleCache.begin(),
00350     end = rectangleCache.end(),
00351     tmp;
00352 
00353   if (jt != end) {
00354     jt++;
00355   }
00356 //  std::cout << "Before: " <<  rectangleCache.size()  << std::endl;
00357 
00358   while (it != end && jt != end) {
00359     if ( (*it).Contains(*jt) ) {
00360     //   std::cout << "X: " << (*jt).GetPositionX() << " ; " << (*jt).GetBottomRightPoint().GetX() << " - " ; 
00361 //       std::cout << "Y: " << (*jt).GetPositionY() << " ; " << (*jt).GetBottomRightPoint().GetY();
00362 //       std::cout << std::endl;
00363       tmp = jt;
00364       ++tmp;
00365       rectangleCache.erase(jt);
00366       jt = tmp;
00367 
00368     } else if ( (*jt).Contains(*it) ) {
00369 //       std::cout << "X: " << (*it).GetPositionX() << " ; " << (*it).GetBottomRightPoint().GetX() << " - " ; 
00370 //       std::cout << "Y: " << (*it).GetPositionY() << " ; " << (*it).GetBottomRightPoint().GetY();
00371 //       std::cout << std::endl;
00372       tmp = it;
00373       --tmp;
00374       rectangleCache.erase(it);      
00375       it = tmp;
00376 
00377     } else {
00378       it++;
00379       jt++;
00380     }
00381   }
00382 //   std::cout << "After : " <<  rectangleCache.size()  << std::endl;
00383 
00384 //   std::cout << "//#############################" <<std::endl;
00385 }

Generated on Mon Jan 1 13:10:58 2007 for Wormux by  doxygen 1.4.7