00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
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
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
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
00220 bool Map::LigneV_EstDansVide (int x, int top, int bottom)
00221 {
00222 assert (top <= bottom);
00223
00224
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
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
00241
00242 Rectanglei rect(prect);
00243
00244
00245 rect.Clip( Rectanglei(0, 0, GetWidth(), GetHeight()) );
00246
00247
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
00272
00273
00274 Rectanglei rect(prect);
00275
00276
00277 rect.Clip( Rectanglei(0, 0, GetWidth(), GetHeight()) );
00278
00279
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
00357
00358 while (it != end && jt != end) {
00359 if ( (*it).Contains(*jt) ) {
00360
00361
00362
00363 tmp = jt;
00364 ++tmp;
00365 rectangleCache.erase(jt);
00366 jt = tmp;
00367
00368 } else if ( (*jt).Contains(*it) ) {
00369
00370
00371
00372 tmp = it;
00373 --tmp;
00374 rectangleCache.erase(it);
00375 it = tmp;
00376
00377 } else {
00378 it++;
00379 jt++;
00380 }
00381 }
00382
00383
00384
00385 }