Advertisement
Auliyaa

tile.h, tile.cpp

Nov 29th, 2013
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.01 KB | None | 0 0
  1. /************************************************
  2. File: tile.h
  3. ************************************************/
  4. #ifndef TILE_H
  5. #define TILE_H
  6.  
  7. #include <QImage>
  8.  
  9. class TileMap;
  10.  
  11. class Tile
  12. {
  13.   QImage _tile;
  14.   TileMap* _map;
  15.   QRgb _innerTileAverageValue;
  16.   QRgb _neighborhoodAverageValue;
  17.  
  18. public:
  19.   enum Direction
  20.   {
  21.     Left,
  22.     Top,
  23.     Right,
  24.     Bottom
  25.   };
  26.  
  27.   int _x;
  28.   int _y;
  29.   Tile(TileMap* map, const QImage& tile, int x, int y);
  30.   QRgb innerTileAverageValue() const { return _innerTileAverageValue; }
  31.   void computeNeightBorhoodAverageValue();
  32.  
  33.   bool hasLeftWall() const;
  34.   bool hasRightWall() const;
  35.   bool hasTopWall() const;
  36.   bool hasBottomWall() const;
  37.  
  38.   bool hasWall(Direction d) const;
  39. };
  40.  
  41. class TileMap
  42. {
  43.   Tile*** _tiles;
  44.   int _wallWidth;
  45.  
  46.   int _width;
  47.   int _height;
  48.  
  49.   int _tileWidth;
  50.   int _tileHeight;
  51.  
  52.   void checkTileExits(int x, int y, QStack<Tile *> &stack, QList<QPair<int, int> > &result, Tile::Direction startExitDirection, Tile::Direction endExitDirection) const;
  53.  
  54. public:
  55.   static int DELTA_WALL;
  56.   static int DELTA_TILE;
  57.  
  58.   static int CONTRAST;
  59.   static int BRIGHTNESS;
  60.  
  61.  
  62.   TileMap(int tileWidth,int tileHeight, int wallWidth, const QImage& source);
  63.  
  64.   int wallWidth() const { return _wallWidth; }
  65.   Tile* tile(int x,int y) const { return _tiles[x][y]; }
  66.  
  67.   int width() const { return _width; }
  68.   int height() const { return _height; }
  69.  
  70.   int tileWidth() const { return _tileWidth; }
  71.   int tileHeight() const { return _tileHeight; }
  72.  
  73.   void highlightWalls(QImage& source) const;
  74.   void highlightExits(QImage& source) const;
  75.  
  76.   QList<QPair<int,int> > exits() const;
  77. };
  78.  
  79.  
  80.  
  81. #endif // TILE_H
  82.  
  83. /************************************************
  84. File: tile.cpp
  85. ************************************************/
  86. #include "tile.h"
  87.  
  88. #include <QPainter>
  89. #include <QDebug>
  90. #include "imagecontrast.h"
  91.  
  92. QString rgbString(QRgb rgb)
  93. {
  94.   return "(" + QString::number(qRed(rgb)) + "," + QString::number(qGreen(rgb)) + "," + QString::number(qBlue(rgb)) + ")";
  95. }
  96.  
  97. int colorDistance(QRgb a, QRgb b)
  98. {
  99.   return (qAbs(qRed(a) - qRed(b)) + qAbs(qGreen(a) - qGreen(b)) + qAbs(qBlue(a) - qBlue(b)));
  100. }
  101.  
  102. QRgb averagePixelsValue(const QImage& img)
  103. {
  104.   qint64 mr=0,mg=0,mb=0;
  105.  
  106.   for (int x=0;x<img.width();++x)
  107.   {
  108.     for (int y=0;y<img.height();++y)
  109.     {
  110.       QRgb rgb = img.pixel(x,y);
  111.       mr+=qRed(rgb);
  112.       mg+=qGreen(rgb);
  113.       mb+=qBlue(rgb);
  114.     }
  115.   }
  116.   qint64 c = img.width()*img.height();
  117.   return qRgb(mr/c,mg/c,mb/c);
  118. }
  119.  
  120. Tile::Tile(TileMap* map, const QImage &tile, int x, int y)
  121.   : _tile(tile), _map(map), _x(x), _y(y)
  122. {
  123.   int ww = _map->wallWidth();
  124.   _innerTileAverageValue = averagePixelsValue(tile.copy(ww,ww,tile.width()-ww*2,tile.height()-ww*2));
  125.   _neighborhoodAverageValue = 0;
  126. }
  127.  
  128. void Tile::computeNeightBorhoodAverageValue()
  129. {
  130.   qint64 mr=0,mg=0,mb=0;
  131.   int mc=0;
  132.   for (int ix=_x-1;ix<=_x+1;++ix)
  133.   {
  134.     for (int iy=_y-1;iy<=_y+1;++iy)
  135.     {
  136.       if (ix < 0 || iy < 0 || ix >= _map->width() || iy >= _map->height()) continue;
  137.       mr+=qRed(_map->tile(ix,iy)->innerTileAverageValue());
  138.       mg+=qGreen(_map->tile(ix,iy)->innerTileAverageValue());
  139.       mb+=qBlue(_map->tile(ix,iy)->innerTileAverageValue());
  140.       ++mc;
  141.     }
  142.   }
  143.   _neighborhoodAverageValue = qRgb(mr/mc,mg/mc,mb/mc);
  144. }
  145.  
  146. bool Tile::hasLeftWall() const
  147. {
  148.   int ww = _map->wallWidth();
  149.   int tw = _map->tileWidth();
  150.   int th = _map->tileHeight();
  151.   QRgb averageWallValue = averagePixelsValue(_tile.copy(0,ww,ww/2,th-ww*2));
  152.   return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
  153. }
  154.  
  155. bool Tile::hasRightWall() const
  156. {
  157.   int ww = _map->wallWidth();
  158.   int tw = _map->tileWidth();
  159.   int th = _map->tileHeight();
  160.   QRgb averageWallValue = averagePixelsValue(_tile.copy(tw-ww,ww,ww/2,th-ww*2));
  161.   return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
  162. }
  163.  
  164. bool Tile::hasTopWall() const
  165. {
  166.   int ww = _map->wallWidth();
  167.   int tw = _map->tileWidth();
  168.   int th = _map->tileHeight();
  169.   QRgb averageWallValue = averagePixelsValue(_tile.copy(ww,0,tw-ww*2,ww/2));
  170.   return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
  171. }
  172.  
  173. bool Tile::hasBottomWall() const
  174. {
  175.   int ww = _map->wallWidth();
  176.   int tw = _map->tileWidth();
  177.   int th = _map->tileHeight();
  178.   QRgb averageWallValue = averagePixelsValue(_tile.copy(ww,th-ww,tw-ww*2,ww/2));
  179.   return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
  180. }
  181.  
  182. bool Tile::hasWall(Tile::Direction d) const
  183. {
  184.   switch (d)
  185.   {
  186.   case Top:
  187.     return hasTopWall();
  188.   case Bottom:
  189.     return hasBottomWall();
  190.   case Left:
  191.     return hasLeftWall();
  192.   case Right:
  193.     return hasRightWall();
  194.   }
  195.  
  196.   return false;
  197. }
  198.  
  199. int TileMap::DELTA_WALL = 14;
  200. int TileMap::DELTA_TILE = 10;
  201. int TileMap::CONTRAST = 500;
  202. int TileMap::BRIGHTNESS = -20;
  203.  
  204. TileMap::TileMap(int tileWidth, int tileHeight, int wallWidth, const QImage &source)
  205.   : _wallWidth(wallWidth), _tileWidth(tileWidth), _tileHeight(tileHeight)
  206. {
  207.   QImage img = changeContrast(changeBrightness(source,BRIGHTNESS),CONTRAST);
  208.  
  209.   _width = img.width()/tileWidth;
  210.   _height = img.height()/tileHeight;
  211.  
  212.   _tiles = new Tile**[_height];
  213.   for (int i=0;i<source.width()/tileWidth;++i)
  214.     _tiles[i] = new Tile*[_width];
  215.  
  216.   for (int x=0;x<_width;++x)
  217.   {
  218.     for (int y=0;y<_height;++y)
  219.     {
  220.       _tiles[x][y] = new Tile(this,img.copy(x*_tileWidth,y*_tileHeight,_tileWidth,_tileHeight),x,y);
  221.     }
  222.   }
  223.   for (int x=0;x<_width;++x)
  224.   {
  225.     for (int y=0;y<_height;++y)
  226.     {
  227.       _tiles[x][y]->computeNeightBorhoodAverageValue();
  228.     }
  229.   }
  230. }
  231.  
  232. void TileMap::highlightWalls(QImage &source) const
  233. {
  234.   QPainter p(&source);
  235.  
  236.   for (int x=0;x<width();++x)
  237.   {
  238.     for (int y=0;y<height();++y)
  239.     {
  240.       Tile* t = tile(x,y);
  241.       if (t->hasTopWall())
  242.       {
  243.         p.setBrush(QColor(255,0,0,100));
  244.         p.drawRect(x*_tileWidth,y*_tileHeight,_tileWidth,_wallWidth);
  245.       }
  246.       if (t->hasBottomWall())
  247.       {
  248.         p.setBrush(QColor(0,255,0,100));
  249.         p.drawRect(x*200,y*200+_tileHeight-_wallWidth,_tileWidth,_wallWidth);
  250.       }
  251.       if (t->hasLeftWall())
  252.       {
  253.         p.setBrush(QColor(0,0,255,100));
  254.         p.drawRect(x*200,y*200,_wallWidth,_tileHeight);
  255.       }
  256.       if (t->hasRightWall())
  257.       {
  258.         p.setBrush(QColor(255,0,255,100));
  259.         p.drawRect(x*200+_tileWidth-_wallWidth,y*200,_wallWidth,_tileHeight);
  260.       }
  261.     }
  262.   }
  263. }
  264.  
  265. void TileMap::highlightExits(QImage &source) const
  266. {
  267.   QPainter p(&source);
  268.   p.setBrush(QColor(255,0,0,100));
  269.   typedef QPair<int,int> coord;
  270.   foreach(const coord& c, exits())
  271.   {
  272.     p.drawRect(c.first*_tileWidth,c.second*_tileHeight,_tileWidth,_tileHeight);
  273.   }
  274. }
  275.  
  276. #include <QStack>
  277.  
  278. void TileMap::checkTileExits(int x,int y,QStack<Tile *> &stack, QList<QPair<int, int> > &result, Tile::Direction startExitDirection, Tile::Direction endExitDirection) const
  279. {
  280.   Tile* t = tile(x,y);
  281.   stack.push(t);
  282.   if (t->hasWall(startExitDirection))
  283.   {
  284.     stack.clear();
  285.   }
  286.   if (t->hasWall(endExitDirection))
  287.   {
  288.     if (!stack.empty()) stack.pop();
  289.     foreach(Tile* ti, stack) result << QPair<int,int>(ti->_x,ti->_y);
  290.   }
  291. }
  292.  
  293. QList<QPair<int, int> > TileMap::exits() const
  294. {
  295.   QList<QPair<int,int> > result;
  296.   QStack<Tile*> stack;
  297.  
  298.   // Top side
  299.   for (int x=0;x<width();++x) checkTileExits(x,0,stack,result,Tile::Right,Tile::Left);
  300.  
  301.   // Right side
  302.   for (int y=0;y<height();++y) checkTileExits(width()-1,y,stack,result,Tile::Bottom,Tile::Top);
  303.  
  304.   // Bottom side
  305.   for (int x=width()-1;x>=0;--x) checkTileExits(x,height()-1,stack,result,Tile::Left,Tile::Right);
  306.  
  307.   // Left Side
  308.   for (int y=height()-1;y>=0;--y) checkTileExits(0,y,stack,result,Tile::Top,Tile::Bottom);
  309.  
  310.   // Top side (A second time to finish eventually opened areas
  311.   for (int x=0;x<width();++x) checkTileExits(x,0,stack,result,Tile::Right,Tile::Left);
  312.  
  313.   // Remove duplicates and re-convert the result to list for further iterations
  314.   return result.toSet().toList();
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement