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
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
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
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
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
00166
00167
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 }