D:/Development/Projects/X-Clone/X-Clone/trunk/Map.cpp

Go to the documentation of this file.
00001 #include "Map.h"
00002 #include "Display.h"
00003 #include "Input.h"
00004 #include "Wall.h"
00005 #include "MapTile.h"
00006 #include "Terrain.h"
00007 
00008 #define TILE_MOUSE_MAP "images/tile_mousemap.png"
00009 
00010 map<string, TerrainType> Map::terrainMap;
00011 
00012 Map::Map() :
00013    _width(0),
00014    _height(0)
00015 {
00016    static bool mapped = false;
00017    if (!mapped) 
00018    {
00019       terrainMap["grass"] = GRASS;
00020       terrainMap["water"] = WATER;
00021 
00022       mapped = true;
00023    }
00024    _tileMouseMap = Display::instance().loadImage(TILE_MOUSE_MAP, false);
00025 }
00026 
00027 Map::~Map()
00028 {
00029    SDL_FreeSurface(_tileMouseMap);
00030 }
00031 
00032 spMapTile Map::getTile(int x, int y) const
00033 {
00034    unsigned int index = x + (y * _width);
00035    if (index < _mapTiles.size() && x >= 0 && x < _width && y >= 0 && y < _height)
00036    {
00037       return _mapTiles[index];
00038    }
00039    else
00040    {
00041       return spMapTile();
00042    }
00043 }
00044 
00045 spMapTile Map::getMouseOverTile()
00046 {
00047    return _mouseOverTile;
00048 }
00049 
00050 void Map::updateMouseOverTile(Point offset)
00051 {
00052    Point mouse = Input::instance().getMousePosition();
00053    _mouseOverTile = getTile(mouse, offset);
00054 }
00055 
00056 spMapTile Map::getTile(Point position, Point offset)
00057 {
00058    static Point size(MapTile::getWidth(), MapTile::getHeight());
00059    int x = position.x + offset.x;
00060    int y = position.y + offset.y;
00061 
00062    vector<spMapTile>::iterator iter;
00063 
00064    for (iter = _mapTiles.begin(); iter != _mapTiles.end(); ++iter)
00065    {
00066       Point origin((*iter)->getScreenX(), (*iter)->getScreenY());
00067       if (x > origin.x && x < origin.x + size.x && y > origin.y && y < origin.y + size.y)
00068       {
00069          // difference from pixel to origin of image
00070          Point diff(x - origin.x, y - origin.y);
00071 
00072          if (SDL_MUSTLOCK(_tileMouseMap))
00073          {
00074             SDL_LockSurface(_tileMouseMap);
00075          }
00076  
00077          Uint16* pixels = static_cast<Uint16*>(_tileMouseMap->pixels);
00078          Uint16 pix = pixels[diff.x + diff.y*_tileMouseMap->w];
00079 
00080          Uint16 red = pix & _tileMouseMap->format->Rmask;
00081          Uint16 green = pix & _tileMouseMap->format->Gmask;
00082          Uint16 blue = pix & _tileMouseMap->format->Bmask;
00083 
00084          if (SDL_MUSTLOCK(_tileMouseMap))
00085          {
00086             SDL_UnlockSurface(_tileMouseMap);
00087          }
00088          
00089          // offset from current image to actual MapTile
00090          Point offset;
00091 
00092          if (red && !green && !blue) 
00093          {
00094             offset.y = -1;
00095          }
00096          else if (!red && green && !blue)
00097          {
00098             offset.x = -1;
00099          }
00100          else if (!red && !green && blue)
00101          {
00102             offset.x = 1;
00103          }
00104          else if (red && green && !blue)
00105          {
00106             offset.y = 1;
00107          }
00108 
00109          Point coords((*iter)->getX() + offset.x, (*iter)->getY() + offset.y);
00110          if (coords.x >= 0 && coords.x < _width && coords.y >= 0 && coords.y < _height)
00111          {
00112             return getTile(coords.x, coords.y);
00113          }
00114       }
00115    }
00116 
00117    return spMapTile();
00118 }
00119 
00120 bool Map::load(istream& data)
00121 {
00122    string line;
00123    bool firstLine = true;
00124 
00125    // empty the current map
00126    _mapTiles.resize(0);
00127 
00128    int x = 0;
00129    int y = 0;
00130 
00131    while(data >> line)
00132    {
00133       if (firstLine)
00134       {
00135          string width(line.begin(), line.begin() + line.find(","));
00136          _width = atoi(width.c_str());
00137 
00138          string height(line.begin() + line.find(",") + 1, line.end());
00139          _height = atoi(height.c_str());
00140 
00141          // make enough room for the current map size to avoid reallocations
00142          int num = _width * _height;
00143          _mapTiles.reserve(_width * _height);
00144 
00145          firstLine = false;
00146       }
00147       else
00148       {
00149          if (x >= _width)
00150          {
00151             x = 0;
00152             y++;
00153          }
00154          string terrain;
00155          int wall = 0;
00156          if (line.find(":") != string::npos)
00157          {
00158             terrain = string(line.begin(), line.begin() + line.find(":"));
00159             wall = std::atoi (string(line.begin() + line.find(":") + 1, line.end()).c_str());
00160          }
00161          else
00162          {
00163             terrain = line;
00164          }
00165          //string terrain(line.begin(), line.begin() + line.find(":"));
00166          // it has to be a wall so the next line isn't needed currently
00167          //string extra(line.begin() + line.find(":") + 1, line.end();
00168          spMapTile tile = MapTile::makeMapTile(terrainMap[terrain], x, y);
00169 
00170          populateTileNeighbors(tile);
00171 
00172          _mapTiles.push_back(tile);
00173 
00174          if (wall & NE)
00175             tile->addObject(spMapObject(new Wall(Direction::NE)));
00176          if (wall & NW)
00177             tile->addObject(spMapObject(new Wall(Direction::NW)));
00178          if (wall & SE)
00179             tile->addObject(spMapObject(new Wall(Direction::SE)));
00180          if (wall & SW)
00181             tile->addObject(spMapObject(new Wall(Direction::SW)));
00182          x++;
00183       }
00184    }
00185    return true;
00186 }
00187 
00188 void Map::populateTileNeighbors(spMapTile tile)
00189 {
00190    int x = tile->getX();
00191    int y = tile->getY();
00192 
00193    vector<const Direction*> directions = Direction::getAllDirections();
00194 
00195    vector<const Direction*>::const_iterator iter;
00196    for (iter = directions.begin(); iter != directions.end(); ++iter)
00197    {
00198       spMapTile t = getTile(x + (*iter)->offset().x, y + (*iter)->offset().y);
00199       if (t.get())
00200       {
00201          tile->addTileInDirection( t, *(*iter) );
00202       }
00203    }
00204 }
00205 
00206 void Map::drawTerrainLayer(Point offset)
00207 {
00208    for (int i=0; i < _height; i++)
00209    {
00210       for (int j=0; j < _width; j++)
00211       {
00212          getTile(j, i)->drawTerrain(offset);
00213       }
00214    }
00215 }
00216 
00217 void Map::drawObjectLayer(Point offset)
00218 {
00219    for (int i=0; i < _height; i++)
00220    {
00221       for (int j=0; j < _width; j++)
00222       {
00223          getTile(j, i)->drawObjects(offset);
00224       }
00225    }
00226 }
00227 
00228 void Map::drawMinimap()
00229 {
00230     int minimapTileSize = 4;
00231     int minimapScreenMargin = 10;
00232     Display& d = Display::instance();
00233     SDL_Rect border = { minimapScreenMargin, d.getScreenHeight()-minimapTileSize*_height-2 - minimapScreenMargin, _width*minimapTileSize+2, _height*minimapTileSize+2 };
00234     SDL_Color white = { 0xFF, 0xFF, 0xFF };
00235     SDL_Color green = { 0x00, 0x79, 0x1B };
00236     SDL_Color blue = { 0x00, 0x71, 0xFE };
00237     SDL_Color red = { 0xFF, 0x00, 0x00 };
00238     SDL_Color gray = { 0x74, 0x74, 0x74 };
00239     Display::instance().drawRect( &border, &white );
00240     for ( int i = 0; i < _height; ++i )
00241     {
00242         for ( int j = 0; j < _width; ++j )
00243         {
00244             SDL_Rect tile = { border.x + 1 + minimapTileSize*j, border.y + 1 + minimapTileSize*i, minimapTileSize, minimapTileSize };
00245             if ( getTile(i,j)->hasUnit() )
00246                 d.drawRect( &tile, &red );
00247             else if ( getTile(i,j)->getTerrainType() == GRASS )
00248             {
00249                 if ( getTile(i, j)->isPassable() )
00250                     d.drawRect( &tile, &green );
00251                 else
00252                     d.drawRect( &tile, &gray );
00253             }
00254             else if ( getTile(i,j)->getTerrainType() == WATER )
00255                 d.drawRect( &tile, &blue );
00256         }
00257     }
00258 
00259 }
00260 
00261 void Map::highlightMouseOverTile(Point offset)
00262 {
00263    if (_mouseOverTile.get())
00264    {
00265       _mouseOverTile->highlight(offset);
00266    }
00267 }
00268 
00269 int Map::getHeight() const
00270 {
00271    return _height;
00272 }
00273 
00274 int Map::getWidth() const
00275 {
00276    return _width;
00277 }

Generated on Fri Sep 22 06:00:26 2006 for X-CLONE by  doxygen 1.4.7