Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /************************************************
- File: tile.h
- ************************************************/
- #ifndef TILE_H
- #define TILE_H
- #include <QImage>
- class TileMap;
- class Tile
- {
- QImage _tile;
- TileMap* _map;
- QRgb _innerTileAverageValue;
- QRgb _neighborhoodAverageValue;
- public:
- enum Direction
- {
- Left,
- Top,
- Right,
- Bottom
- };
- int _x;
- int _y;
- Tile(TileMap* map, const QImage& tile, int x, int y);
- QRgb innerTileAverageValue() const { return _innerTileAverageValue; }
- void computeNeightBorhoodAverageValue();
- bool hasLeftWall() const;
- bool hasRightWall() const;
- bool hasTopWall() const;
- bool hasBottomWall() const;
- bool hasWall(Direction d) const;
- };
- class TileMap
- {
- Tile*** _tiles;
- int _wallWidth;
- int _width;
- int _height;
- int _tileWidth;
- int _tileHeight;
- void checkTileExits(int x, int y, QStack<Tile *> &stack, QList<QPair<int, int> > &result, Tile::Direction startExitDirection, Tile::Direction endExitDirection) const;
- public:
- static int DELTA_WALL;
- static int DELTA_TILE;
- static int CONTRAST;
- static int BRIGHTNESS;
- TileMap(int tileWidth,int tileHeight, int wallWidth, const QImage& source);
- int wallWidth() const { return _wallWidth; }
- Tile* tile(int x,int y) const { return _tiles[x][y]; }
- int width() const { return _width; }
- int height() const { return _height; }
- int tileWidth() const { return _tileWidth; }
- int tileHeight() const { return _tileHeight; }
- void highlightWalls(QImage& source) const;
- void highlightExits(QImage& source) const;
- QList<QPair<int,int> > exits() const;
- };
- #endif // TILE_H
- /************************************************
- File: tile.cpp
- ************************************************/
- #include "tile.h"
- #include <QPainter>
- #include <QDebug>
- #include "imagecontrast.h"
- QString rgbString(QRgb rgb)
- {
- return "(" + QString::number(qRed(rgb)) + "," + QString::number(qGreen(rgb)) + "," + QString::number(qBlue(rgb)) + ")";
- }
- int colorDistance(QRgb a, QRgb b)
- {
- return (qAbs(qRed(a) - qRed(b)) + qAbs(qGreen(a) - qGreen(b)) + qAbs(qBlue(a) - qBlue(b)));
- }
- QRgb averagePixelsValue(const QImage& img)
- {
- qint64 mr=0,mg=0,mb=0;
- for (int x=0;x<img.width();++x)
- {
- for (int y=0;y<img.height();++y)
- {
- QRgb rgb = img.pixel(x,y);
- mr+=qRed(rgb);
- mg+=qGreen(rgb);
- mb+=qBlue(rgb);
- }
- }
- qint64 c = img.width()*img.height();
- return qRgb(mr/c,mg/c,mb/c);
- }
- Tile::Tile(TileMap* map, const QImage &tile, int x, int y)
- : _tile(tile), _map(map), _x(x), _y(y)
- {
- int ww = _map->wallWidth();
- _innerTileAverageValue = averagePixelsValue(tile.copy(ww,ww,tile.width()-ww*2,tile.height()-ww*2));
- _neighborhoodAverageValue = 0;
- }
- void Tile::computeNeightBorhoodAverageValue()
- {
- qint64 mr=0,mg=0,mb=0;
- int mc=0;
- for (int ix=_x-1;ix<=_x+1;++ix)
- {
- for (int iy=_y-1;iy<=_y+1;++iy)
- {
- if (ix < 0 || iy < 0 || ix >= _map->width() || iy >= _map->height()) continue;
- mr+=qRed(_map->tile(ix,iy)->innerTileAverageValue());
- mg+=qGreen(_map->tile(ix,iy)->innerTileAverageValue());
- mb+=qBlue(_map->tile(ix,iy)->innerTileAverageValue());
- ++mc;
- }
- }
- _neighborhoodAverageValue = qRgb(mr/mc,mg/mc,mb/mc);
- }
- bool Tile::hasLeftWall() const
- {
- int ww = _map->wallWidth();
- int tw = _map->tileWidth();
- int th = _map->tileHeight();
- QRgb averageWallValue = averagePixelsValue(_tile.copy(0,ww,ww/2,th-ww*2));
- return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
- }
- bool Tile::hasRightWall() const
- {
- int ww = _map->wallWidth();
- int tw = _map->tileWidth();
- int th = _map->tileHeight();
- QRgb averageWallValue = averagePixelsValue(_tile.copy(tw-ww,ww,ww/2,th-ww*2));
- return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
- }
- bool Tile::hasTopWall() const
- {
- int ww = _map->wallWidth();
- int tw = _map->tileWidth();
- int th = _map->tileHeight();
- QRgb averageWallValue = averagePixelsValue(_tile.copy(ww,0,tw-ww*2,ww/2));
- return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
- }
- bool Tile::hasBottomWall() const
- {
- int ww = _map->wallWidth();
- int tw = _map->tileWidth();
- int th = _map->tileHeight();
- QRgb averageWallValue = averagePixelsValue(_tile.copy(ww,th-ww,tw-ww*2,ww/2));
- return colorDistance(averageWallValue,_neighborhoodAverageValue) >= TileMap::DELTA_WALL;
- }
- bool Tile::hasWall(Tile::Direction d) const
- {
- switch (d)
- {
- case Top:
- return hasTopWall();
- case Bottom:
- return hasBottomWall();
- case Left:
- return hasLeftWall();
- case Right:
- return hasRightWall();
- }
- return false;
- }
- int TileMap::DELTA_WALL = 14;
- int TileMap::DELTA_TILE = 10;
- int TileMap::CONTRAST = 500;
- int TileMap::BRIGHTNESS = -20;
- TileMap::TileMap(int tileWidth, int tileHeight, int wallWidth, const QImage &source)
- : _wallWidth(wallWidth), _tileWidth(tileWidth), _tileHeight(tileHeight)
- {
- QImage img = changeContrast(changeBrightness(source,BRIGHTNESS),CONTRAST);
- _width = img.width()/tileWidth;
- _height = img.height()/tileHeight;
- _tiles = new Tile**[_height];
- for (int i=0;i<source.width()/tileWidth;++i)
- _tiles[i] = new Tile*[_width];
- for (int x=0;x<_width;++x)
- {
- for (int y=0;y<_height;++y)
- {
- _tiles[x][y] = new Tile(this,img.copy(x*_tileWidth,y*_tileHeight,_tileWidth,_tileHeight),x,y);
- }
- }
- for (int x=0;x<_width;++x)
- {
- for (int y=0;y<_height;++y)
- {
- _tiles[x][y]->computeNeightBorhoodAverageValue();
- }
- }
- }
- void TileMap::highlightWalls(QImage &source) const
- {
- QPainter p(&source);
- for (int x=0;x<width();++x)
- {
- for (int y=0;y<height();++y)
- {
- Tile* t = tile(x,y);
- if (t->hasTopWall())
- {
- p.setBrush(QColor(255,0,0,100));
- p.drawRect(x*_tileWidth,y*_tileHeight,_tileWidth,_wallWidth);
- }
- if (t->hasBottomWall())
- {
- p.setBrush(QColor(0,255,0,100));
- p.drawRect(x*200,y*200+_tileHeight-_wallWidth,_tileWidth,_wallWidth);
- }
- if (t->hasLeftWall())
- {
- p.setBrush(QColor(0,0,255,100));
- p.drawRect(x*200,y*200,_wallWidth,_tileHeight);
- }
- if (t->hasRightWall())
- {
- p.setBrush(QColor(255,0,255,100));
- p.drawRect(x*200+_tileWidth-_wallWidth,y*200,_wallWidth,_tileHeight);
- }
- }
- }
- }
- void TileMap::highlightExits(QImage &source) const
- {
- QPainter p(&source);
- p.setBrush(QColor(255,0,0,100));
- typedef QPair<int,int> coord;
- foreach(const coord& c, exits())
- {
- p.drawRect(c.first*_tileWidth,c.second*_tileHeight,_tileWidth,_tileHeight);
- }
- }
- #include <QStack>
- void TileMap::checkTileExits(int x,int y,QStack<Tile *> &stack, QList<QPair<int, int> > &result, Tile::Direction startExitDirection, Tile::Direction endExitDirection) const
- {
- Tile* t = tile(x,y);
- stack.push(t);
- if (t->hasWall(startExitDirection))
- {
- stack.clear();
- }
- if (t->hasWall(endExitDirection))
- {
- if (!stack.empty()) stack.pop();
- foreach(Tile* ti, stack) result << QPair<int,int>(ti->_x,ti->_y);
- }
- }
- QList<QPair<int, int> > TileMap::exits() const
- {
- QList<QPair<int,int> > result;
- QStack<Tile*> stack;
- // Top side
- for (int x=0;x<width();++x) checkTileExits(x,0,stack,result,Tile::Right,Tile::Left);
- // Right side
- for (int y=0;y<height();++y) checkTileExits(width()-1,y,stack,result,Tile::Bottom,Tile::Top);
- // Bottom side
- for (int x=width()-1;x>=0;--x) checkTileExits(x,height()-1,stack,result,Tile::Left,Tile::Right);
- // Left Side
- for (int y=height()-1;y>=0;--y) checkTileExits(0,y,stack,result,Tile::Top,Tile::Bottom);
- // Top side (A second time to finish eventually opened areas
- for (int x=0;x<width();++x) checkTileExits(x,0,stack,result,Tile::Right,Tile::Left);
- // Remove duplicates and re-convert the result to list for further iterations
- return result.toSet().toList();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement