From 101ba08f997bd1912da32abe778cdc3305048380 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 5 Feb 2012 19:42:09 +0300 Subject: Separate map class to map and maplayer. --- src/CMakeLists.txt | 2 + src/Makefile.am | 4 +- src/gui/popupmenu.cpp | 1 + src/gui/socialwindow.cpp | 1 + src/gui/viewport.cpp | 1 + src/gui/widgets/avatarlistbox.cpp | 1 + src/localplayer.cpp | 1 + src/map.cpp | 788 +----------------------------------- src/map.h | 265 ------------- src/maplayer.cpp | 817 ++++++++++++++++++++++++++++++++++++++ src/maplayer.h | 299 ++++++++++++++ src/resources/mapreader.cpp | 1 + 12 files changed, 1129 insertions(+), 1052 deletions(-) create mode 100644 src/maplayer.cpp create mode 100644 src/maplayer.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a52ce41da..96c1eac67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -559,6 +559,8 @@ SET(SRCS main.h map.cpp map.h + maplayer.cpp + maplayer.h opengl1graphics.cpp opengl1graphics.h openglgraphics.cpp diff --git a/src/Makefile.am b/src/Makefile.am index c5fdaeac1..e9af09463 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -564,8 +564,10 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ logger.h \ main.cpp \ main.h \ - map.cpp\ + map.cpp \ map.h \ + maplayer.cpp \ + maplayer.h \ opengl1graphics.cpp\ opengl1graphics.h \ openglgraphics.cpp\ diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 142acc69c..c987843d3 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -35,6 +35,7 @@ #include "localplayer.h" #include "logger.h" #include "map.h" +#include "maplayer.h" #include "party.h" #include "playerinfo.h" #include "playerrelations.h" diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 59ace1685..287089790 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -28,6 +28,7 @@ #include "localplayer.h" #include "logger.h" #include "map.h" +#include "maplayer.h" #include "party.h" #include "playerrelations.h" #include "gui/whoisonline.h" diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 7ff2c8850..2e1e15c92 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -31,6 +31,7 @@ #include "keyboardconfig.h" #include "localplayer.h" #include "map.h" +#include "maplayer.h" #include "textmanager.h" #include "gui/beingpopup.h" diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index 1bf897301..2e3472515 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -26,6 +26,7 @@ #include "graphics.h" #include "guild.h" #include "localplayer.h" +#include "maplayer.h" #include "gui/chatwindow.h" #include "gui/gui.h" diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 27897a486..f50e3440c 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -33,6 +33,7 @@ #include "keyboardconfig.h" #include "logger.h" #include "map.h" +#include "maplayer.h" #include "party.h" #include "particle.h" #include "playerinfo.h" diff --git a/src/map.cpp b/src/map.cpp index 488fb16e9..a9aed4531 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -23,11 +23,10 @@ #include "map.h" #include "actorspritemanager.h" -#include "client.h" #include "configuration.h" -#include "graphics.h" -#include "graphicsvertexes.h" + #include "logger.h" +#include "maplayer.h" #include "particle.h" #include "simpleanimation.h" #include "tileset.h" @@ -37,17 +36,11 @@ #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/gui.h" -#include "gui/palette.h" -#include "gui/sdlfont.h" - #include "gui/widgets/chattab.h" #include "utils/dtor.h" #include "utils/mkdir.h" -#include "utils/stringutils.h" -#include #include #include @@ -123,485 +116,6 @@ void TileAnimation::update(int ticks) } } -MapLayer::MapLayer(int x, int y, int width, int height, bool fringeLayer): - mX(x), mY(y), - mWidth(width), mHeight(height), - mIsFringeLayer(fringeLayer), - mHighlightAttackRange(config.getBoolValue("highlightAttackRange")) -{ - const int size = mWidth * mHeight; - mTiles = new Image*[size]; - - std::fill_n(mTiles, size, static_cast(nullptr)); - - config.addListener("highlightAttackRange", this); -} - -MapLayer::~MapLayer() -{ - config.removeListener("highlightAttackRange", this); - delete[] mTiles; - delete_all(mTempRows); - mTempRows.clear(); -} - -void MapLayer::optionChanged(const std::string &value) -{ - if (value == "highlightAttackRange") - { - mHighlightAttackRange = - config.getBoolValue("highlightAttackRange"); - } -} - -void MapLayer::setTile(int x, int y, Image *img) -{ - mTiles[x + y * mWidth] = img; -} - -void MapLayer::draw(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY, - int debugFlags) const -{ - if (!player_node) - return; - - startX -= mX; - startY -= mY; - endX -= mX; - endY -= mY; - - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - const int dx = (mX * 32) - scrollX; - const int dy = (mY * 32) - scrollY + 32; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - for (int y = startY; y < endY; y++) - { - const int y32 = y * 32; - const int yWidth = y * mWidth; - - const int py0 = y32 + dy; - - Image **tilePtr = mTiles + startX + yWidth; - - for (int x = startX; x < endX; x++, tilePtr++) - { - const int x32 = x * 32; - - int c = 0; - Image *img = *tilePtr; - if (img) - { - const int px = x32 + dx; - const int py = py0 - img->mBounds.h; - if (flag || img->mBounds.h <= 32) - { - int width = 0; - // here need not draw over player position - c = getTileDrawWidth(img, endX - x, width); - - if (!c) - { - graphics->drawImage(img, px, py); - } - else - { - graphics->drawImagePattern(img, px, py, - width, img->mBounds.h); - } - } - } - - x += c; - } - } -} - -void MapLayer::updateSDL(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY, - int debugFlags) -{ - delete_all(mTempRows); - mTempRows.clear(); - - startX -= mX; - startY -= mY; - endX -= mX; - endY -= mY; - - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - const int dx = (mX * 32) - scrollX; - const int dy = (mY * 32) - scrollY + 32; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - for (int y = startY; y < endY; y++) - { - MapRowVertexes *row = new MapRowVertexes(); - mTempRows.push_back(row); - - Image *lastImage = nullptr; - ImageVertexes *imgVert = nullptr; - - const int yWidth = y * mWidth; - const int py0 = y * 32 + dy; - Image **tilePtr = mTiles + startX + yWidth; - - for (int x = startX; x < endX; x++, tilePtr++) - { - Image *img = *tilePtr; - if (img) - { - const int px = x * 32 + dx; - const int py = py0 - img->mBounds.h; - if (flag || img->mBounds.h <= 32) - { - if (lastImage != img) - { - imgVert = new ImageVertexes(); - imgVert->image = img; - row->images.push_back(imgVert); - lastImage = img; - } - graphics->calcTile(imgVert, px, py); - } - } - } - } -} - -void MapLayer::drawSDL(Graphics *graphics) -{ - MapRows::const_iterator rit = mTempRows.begin(); - MapRows::const_iterator rit_end = mTempRows.end(); - while (rit != rit_end) - { - MepRowImages *images = &(*rit)->images; - MepRowImages::const_iterator iit = images->begin(); - MepRowImages::const_iterator iit_end = images->end(); - while (iit != iit_end) - { - graphics->drawTile(*iit); - ++ iit; - } - ++ rit; - } -} - -void MapLayer::updateOGL(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY, - int debugFlags) -{ - delete_all(mTempRows); - mTempRows.clear(); - - startX -= mX; - startY -= mY; - endX -= mX; - endY -= mY; - - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - const int dx = (mX * 32) - scrollX; - const int dy = (mY * 32) - scrollY + 32; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - for (int y = startY; y < endY; y++) - { - MapRowVertexes *row = new MapRowVertexes(); - mTempRows.push_back(row); - - Image *lastImage = nullptr; - ImageVertexes *imgVert = nullptr; - - const int yWidth = y * mWidth; - const int py0 = y * 32 + dy; - std::map imgSet; - - Image **tilePtr = mTiles + startX + yWidth; - for (int x = startX; x < endX; x++, tilePtr++) - { - Image *img = *tilePtr; - if (img) - { - const int px = x * 32 + dx; - const int py = py0 - img->mBounds.h; - if (flag || img->mBounds.h <= 32) - { - if (lastImage != img) - { - if (img->mBounds.w > 32) - imgSet.clear(); - - imgSet[lastImage] = imgVert; - if (imgSet.find(img) != imgSet.end()) - { - imgVert = imgSet[img]; - } - else - { - imgVert = new ImageVertexes(); - imgVert->image = img; - row->images.push_back(imgVert); - } - lastImage = img; - } - graphics->calcTile(imgVert, px, py); - } - } - } - } -} - -void MapLayer::drawOGL(Graphics *graphics) -{ - MapRows::const_iterator rit = mTempRows.begin(); - MapRows::const_iterator rit_end = mTempRows.end(); - while (rit != rit_end) - { - MepRowImages *images = &(*rit)->images; - MepRowImages::const_iterator iit = images->begin(); - MepRowImages::const_iterator iit_end = images->end(); - while (iit != iit_end) - { - graphics->drawTile(*iit); - ++ iit; - } - ++ rit; - } -} - -void MapLayer::drawFringe(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY, - const Actors *actors, int debugFlags, int yFix) const -{ - if (!player_node || !mSpecialLayer || !mTempLayer) - return; - - startX -= mX; - startY -= mY; - endX -= mX; - endY -= mY; - - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - Actors::const_iterator ai = actors->begin(); - - const int dx = (mX * 32) - scrollX; - const int dy = (mY * 32) - scrollY + 32; - - int specialWidth = mSpecialLayer->mWidth; - int specialHeight = mSpecialLayer->mHeight; - - for (int y = startY; y < endY; y++) - { - const int y32 = y * 32; - const int y32s = (y + yFix) * 32; - const int yWidth = y * mWidth; - - // If drawing the fringe layer, make sure all actors above this row of - // tiles have been drawn - while (ai != actors->end() && (*ai)->getPixelY() <= y32s) - { - (*ai)->draw(graphics, -scrollX, -scrollY); - ++ ai; - } - - if (debugFlags == Map::MAP_SPECIAL3 - || debugFlags == Map::MAP_BLACKWHITE) - { - if (y < specialHeight) - { - int ptr = y * specialWidth; - const int py1 = y32 - scrollY; - int endX1 = endX; - if (endX1 > specialWidth) - endX1 = specialWidth; - if (endX1 < 0) - endX1 = 0; - - for (int x = startX; x < endX1; x++) - { - const int px1 = x * 32 - scrollX; - - MapItem *item = mSpecialLayer->mTiles[ptr + x]; - if (item) - item->draw(graphics, px1, py1, 32, 32); - - item = mTempLayer->mTiles[ptr + x]; - if (item) - item->draw(graphics, px1, py1, 32, 32); - } - } - } - else - { - const int py0 = y32 + dy; - const int py1 = y32 - scrollY; - - Image **tilePtr = mTiles + startX + yWidth; - for (int x = startX; x < endX; x++, tilePtr++) - { - const int x32 = x * 32; - - const int px1 = x32 - scrollX; - int c = 0; - Image *img = *tilePtr; - if (img) - { - const int px = x32 + dx; - const int py = py0 - img->mBounds.h; - if ((debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2) - || img->mBounds.h <= 32) - { - int width = 0; - // here need not draw over player position - c = getTileDrawWidth(img, endX - x, width); - - if (!c) - { - graphics->drawImage(img, px, py); - } - else - { - graphics->drawImagePattern(img, px, py, - width, img->mBounds.h); - } - } - } - - if (y < specialHeight) - { - int c1 = c; - if (c1 + x + 1 > specialWidth) - c1 = specialWidth - x - 1; - if (c1 < 0) - c1 = 0; - - int ptr = y * specialWidth + x; - - for (int x1 = 0; x1 < c1 + 1; x1 ++) - { - MapItem *item1 = mSpecialLayer->mTiles[ptr + x1]; - MapItem *item2 = mTempLayer->mTiles[ptr + x1]; - if (item1 || item2) - { - const int px2 = px1 + (x1 * 32); - if (item1 && item1->mType != MapItem::EMPTY) - item1->draw(graphics, px2, py1, 32, 32); - - if (item2 && item2->mType != MapItem::EMPTY) - item2->draw(graphics, px2, py1, 32, 32); - } - } - } - x += c; - } - } - } - - // Draw any remaining actors - if (debugFlags != Map::MAP_SPECIAL3) - { - while (ai != actors->end()) - { - (*ai)->draw(graphics, -scrollX, -scrollY); - ++ai; - } - if (mHighlightAttackRange && player_node) - { - const int px = player_node->getPixelX() - scrollX - 16; - const int py = player_node->getPixelY() - scrollY - 32; - const int attackRange = player_node->getAttackRange() * 32; - - int x = px - attackRange; - int y = py - attackRange; - int w = 2 * attackRange + 32; - int h = w; - if (attackRange <= 32) - { - x -= 16; - y -= 16; - w += 32; - h += 32; - } - - if (userPalette) - { - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ATTACK_RANGE)); - - graphics->fillRectangle(gcn::Rectangle( - x, y, - w, h)); - - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ATTACK_RANGE_BORDER)); - - graphics->drawRectangle(gcn::Rectangle( - x, y, - w, h)); - } - } - } -} - -int MapLayer::getTileDrawWidth(Image *img, int endX, int &width) const -{ - Image *img1 = img; - int c = 0; - if (!img1) - { - width = 0; - return c; - } - width = img1->mBounds.w; - for (int x = 1; x < endX; x++) - { - img ++; - if (img != img1) - break; - c ++; - if (img) - width += img->mBounds.w; - } - return c; -} - Map::Map(int width, int height, int tileWidth, int tileHeight): mWidth(width), mHeight(height), mTileWidth(tileWidth), mTileHeight(tileHeight), @@ -2055,301 +1569,3 @@ void Map::redrawMap() { mRedrawMap = true; } - -SpecialLayer::SpecialLayer(int width, int height, bool drawSprites): - mWidth(width), mHeight(height) -{ - const int size = mWidth * mHeight; - mTiles = new MapItem*[size]; - std::fill_n(mTiles, size, static_cast(nullptr)); - mDrawSprites = drawSprites; -} - -SpecialLayer::~SpecialLayer() -{ - for (int f = 0; f < mWidth * mHeight; f ++) - { - delete mTiles[f]; - mTiles[f] = nullptr; - } - delete[] mTiles; -} - -MapItem* SpecialLayer::getTile(int x, int y) const -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return nullptr; - } - return mTiles[x + y * mWidth]; -} - -void SpecialLayer::setTile(int x, int y, MapItem *item) -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return; - } - - int idx = x + y * mWidth; - delete mTiles[idx]; - if (item) - item->setPos(x, y); - mTiles[idx] = item; -} - -void SpecialLayer::setTile(int x, int y, int type) -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return; - } - - int idx = x + y * mWidth; - if (mTiles[idx]) - mTiles[idx]->setType(type); - else - mTiles[idx] = new MapItem(type); - mTiles[idx]->setPos(x, y); -} - -void SpecialLayer::addRoad(Path road) -{ - for (Path::const_iterator i = road.begin(), i_end = road.end(); - i != i_end; ++i) - { - Position pos = (*i); - MapItem *item = getTile(pos.x, pos.y); - if (!item) - { - item = new MapItem(MapItem::ROAD); - setTile(pos.x, pos.y, item); - } - else - { - item->setType(MapItem::ROAD); - } - } -} - -void SpecialLayer::clean() -{ - if (!mTiles) - return; - - for (int f = 0; f < mWidth * mHeight; f ++) - { - MapItem *item = mTiles[f]; - if (item) - item->setType(MapItem::EMPTY); - } -} - -void SpecialLayer::draw(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY) -{ - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - for (int y = startY; y < endY; y++) - { - for (int x = startX; x < endX; x++) - itemDraw(graphics, x, y, scrollX, scrollY); - } -} - -void SpecialLayer::itemDraw(Graphics *graphics, int x, int y, - int scrollX, int scrollY) -{ - MapItem *item = getTile(x, y); - if (item) - { - const int px = x * 32 - scrollX; - const int py = y * 32 - scrollY; - item->draw(graphics, px, py, 32, 32); - } -} - - -MapItem::MapItem(): - mImage(nullptr), mComment(""), mName(""), mX(-1), mY(-1) -{ - setType(EMPTY); -} - -MapItem::MapItem(int type): - mImage(nullptr), mComment(""), mName(""), mX(-1), mY(-1) -{ - setType(type); -} - -MapItem::MapItem(int type, std::string comment): - mImage(nullptr), mComment(comment), mName(""), mX(-1), mY(-1) -{ - setType(type); -} - -MapItem::MapItem(int type, std::string comment, int x, int y): - mImage(nullptr), mComment(comment), mName(""), mX(x), mY(y) -{ - setType(type); -} - -MapItem::~MapItem() -{ - if (mImage) - { - mImage->decRef(); - mImage = nullptr; - } -} - -void MapItem::setType(int type) -{ - std::string name(""); - mType = type; - if (mImage) - mImage->decRef(); - - switch (type) - { - case ARROW_UP: - name = "graphics/sprites/arrow_up.gif"; - break; - case ARROW_DOWN: - name = "graphics/sprites/arrow_down.gif"; - break; - case ARROW_LEFT: - name = "graphics/sprites/arrow_left.gif"; - break; - case ARROW_RIGHT: - name = "graphics/sprites/arrow_right.gif"; - break; - default: - break; - } - - if (name != "") - { - ResourceManager *resman = ResourceManager::getInstance(); - mImage = resman->getImage(name); - } - else - { - mImage = nullptr; - } -} - -void MapItem::setPos(int x, int y) -{ - mX = x; - mY = y; -} - -void MapItem::draw(Graphics *graphics, int x, int y, int dx, int dy) -{ - if (mImage) - graphics->drawImage(mImage, x, y); - - switch(mType) - { - case ROAD: - case CROSS: - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ROAD_POINT)); - graphics->fillRectangle(gcn::Rectangle(x + dx / 3, y + dy / 3, - dx / 3, dy / 3)); - break; - case HOME: - { - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::HOME_PLACE)); - graphics->fillRectangle(gcn::Rectangle( - x, y, - dx, dy)); - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::HOME_PLACE_BORDER)); - graphics->drawRectangle(gcn::Rectangle( - x, y, - dx, dy)); - break; - } - default: - break; - } - if (!mName.empty() && mType != PORTAL && mType != EMPTY && userPalette) - { - gcn::Font *font = gui->getFont(); - if (font) - { - graphics->setColor(userPalette->getColor(UserPalette::BEING)); - font->drawString(graphics, mName, x, y); - } - } -} - -ObjectsLayer::ObjectsLayer(unsigned width, unsigned height) : - mWidth(width), mHeight(height) -{ - const unsigned size = width * height; - mTiles = new MapObjectList*[size]; - std::fill_n(mTiles, size, static_cast(nullptr)); -} - -ObjectsLayer::~ObjectsLayer() -{ - const unsigned size = mWidth * mHeight; - for (unsigned f = 0; f < size; f ++) - delete mTiles[f]; - - delete [] mTiles; - mTiles = nullptr; -} - -void ObjectsLayer::addObject(std::string name, int type, - unsigned x, unsigned y, - unsigned dx, unsigned dy) -{ - if (!mTiles) - return; - - if (x + dx > mWidth) - dx = mWidth - x; - if (y + dy > mHeight) - dy = mHeight - y; - - for (unsigned y1 = y; y1 < y + dy; y1 ++) - { - unsigned idx1 = x + y1 * mWidth; - unsigned idx2 = idx1 + dx; - - for (unsigned i = idx1; i < idx2; i ++) - { - if (!mTiles[i]) - mTiles[i] = new MapObjectList(); - mTiles[i]->objects.push_back(MapObject(type, name)); - } - } -} - -MapObjectList *ObjectsLayer::getAt(unsigned x, unsigned y) -{ - if (x >= mWidth || y >= mHeight) - return nullptr; - return mTiles[x + y * mWidth]; -} - -MapRowVertexes::~MapRowVertexes() -{ - delete_all(images); - images.clear(); -} diff --git a/src/map.h b/src/map.h index e157628cc..5b79ec8f5 100644 --- a/src/map.h +++ b/src/map.h @@ -28,14 +28,11 @@ #include "position.h" #include "properties.h" -#include #include #include class Animation; class AmbientLayer; -class Graphics; -class GraphicsVertexes; class MapLayer; class Particle; class SimpleAnimation; @@ -44,24 +41,8 @@ class SpecialLayer; class MapItem; class ObjectsLayer; -class ImageVertexes; - typedef std::vector Tilesets; typedef std::vector Layers; -typedef std::vector MepRowImages; - -class MapRowVertexes -{ - public: - MapRowVertexes() - { - images.reserve(30); - } - - ~MapRowVertexes(); - - MepRowImages images; -}; /** * A meta tile stores additional information about a location on a tile map. @@ -87,25 +68,6 @@ struct MetaTile unsigned char blockmask; /**< Blocking properties of this tile */ }; -class MapObject -{ - public: - MapObject(int type0, std::string data0) - { - type = type0; - data = data0; - } - - int type; - std::string data; -}; - -class MapObjectList -{ - public: - std::vector objects; -}; - /** * Animation cycle of a tile image which changes the map accordingly. */ @@ -123,114 +85,6 @@ class TileAnimation Image *mLastImage; }; -/** - * A map layer. Stores a grid of tiles and their offset, and implements layer - * rendering. - */ -class MapLayer: public ConfigListener -{ - public: - friend class Map; - - /** - * Constructor, taking layer origin, size and whether this layer is the - * fringe layer. The fringe layer is the layer that draws the actors. - * There can be only one fringe layer per map. - */ - MapLayer(int x, int y, int width, int height, bool isFringeLayer); - - /** - * Destructor. - */ - ~MapLayer(); - - /** - * Set tile image, with x and y in layer coordinates. - */ - void setTile(int x, int y, Image *img); - - /** - * Set tile image with x + y * width already known. - */ - void setTile(int index, Image *img) - { mTiles[index] = img; } - - /** - * Draws this layer to the given graphics context. The coordinates are - * expected to be in map range and will be translated to local layer - * coordinates and clipped to the layer's dimensions. - * - * The given actors are only drawn when this layer is the fringe - * layer. - */ - void draw(Graphics *graphics, - int startX, int startY, - int endX, int endY, - int scrollX, int scrollY, - int mDebugFlags) const; - - void drawOGL(Graphics *graphics); - - void drawSDL(Graphics *graphics); - - void updateOGL(Graphics *graphics, - int startX, int startY, - int endX, int endY, - int scrollX, int scrollY, - int mDebugFlags); - - void updateSDL(Graphics *graphics, - int startX, int startY, - int endX, int endY, - int scrollX, int scrollY, - int mDebugFlags); - - void drawFringe(Graphics *graphics, - int startX, int startY, - int endX, int endY, - int scrollX, int scrollY, - const Actors *actors, - int mDebugFlags, int yFix) const; - - bool isFringeLayer() const - { return mIsFringeLayer; } - - void setSpecialLayer(SpecialLayer *val) - { mSpecialLayer = val; } - - void setTempLayer(SpecialLayer *val) - { mTempLayer = val; } - - int getWidth() const - { return mWidth; } - - int getHeight() const - { return mHeight; } - -// void setTileInfo(int x, int y, int width, int cnt); - -// void getTileInfo(int x, int y, int &width, int &cnt) const; - - void optionChanged(const std::string &value); - - int getTileDrawWidth(Image *img, int endX, int &width) const; - -// void initTileInfo(); - - private: - int mX, mY; - int mWidth, mHeight; - bool mIsFringeLayer; /**< Whether the actors are drawn. */ - bool mHighlightAttackRange; - Image **mTiles; -// int *mTilesWidth; -// int *mTilesCount; - SpecialLayer *mSpecialLayer; - SpecialLayer *mTempLayer; - typedef std::vector MapRows; - MapRows mTempRows; -}; - /** * A tile map. */ @@ -614,123 +468,4 @@ class Map : public Properties, public ConfigListener bool mBeingOpacity; }; - -class SpecialLayer -{ - public: - friend class Map; - friend class MapLayer; - - SpecialLayer(int width, int height, bool drawSprites = false); - - ~SpecialLayer(); - - void draw(Graphics *graphics, int startX, int startY, - int endX, int endY, int scrollX, int scrollY); - - MapItem* getTile(int x, int y) const; - - void setTile(int x, int y, MapItem* item); - - void setTile(int x, int y, int type); - - void addRoad(Path road); - - void clean(); - - void itemDraw(Graphics *graphics, int x, int y, - int scrollX, int scrollY); - - private: - int mWidth, mHeight; - bool mDrawSprites; - MapItem **mTiles; -}; - -class MapItem -{ - public: - friend class Map; - friend class MapLayer; - - enum ItemType - { - EMPTY = 0, - HOME = 1, - ROAD = 2, - CROSS = 3, - ARROW_UP = 4, - ARROW_DOWN = 5, - ARROW_LEFT = 6, - ARROW_RIGHT = 7, - PORTAL = 8, - MUSIC = 9, - ATTACK = 10, - PRIORITY = 11, - IGNORE_ = 12, - SEPARATOR = 13 - }; - - MapItem(); - - MapItem(int type); - - MapItem(int type, std::string comment); - - MapItem(int type, std::string comment, int x, int y); - - ~MapItem(); - - int getType() const - { return mType; } - - void setType(int type); - - void setPos(int x, int y); - - int getX() const - { return mX; } - - int getY() const - { return mY; } - - std::string &getComment() - { return mComment; } - - void setComment(std::string comment) - { mComment = comment; } - - std::string &getName() - { return mName; } - - void setName(std::string name) - { mName = name; } - - void draw(Graphics *graphics, int x, int y, int dx, int dy); - - private: - int mType; - Image *mImage; - std::string mComment; - std::string mName; - int mX; - int mY; -}; - -class ObjectsLayer -{ - public: - ObjectsLayer(unsigned width, unsigned height); - ~ObjectsLayer(); - - void addObject(std::string name, int type, unsigned x, unsigned y, - unsigned dx, unsigned dy); - - MapObjectList *getAt(unsigned x, unsigned y); - private: - MapObjectList **mTiles; - unsigned mWidth; - unsigned mHeight; -}; - #endif diff --git a/src/maplayer.cpp b/src/maplayer.cpp new file mode 100644 index 000000000..3e9c47968 --- /dev/null +++ b/src/maplayer.cpp @@ -0,0 +1,817 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "maplayer.h" + +#include "configuration.h" + +#include "graphicsvertexes.h" + +#include "logger.h" +#include "localplayer.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include "gui/gui.h" +#include "gui/sdlfont.h" + +#include "utils/dtor.h" + +#include "debug.h" + +MapLayer::MapLayer(int x, int y, int width, int height, bool fringeLayer): + mX(x), mY(y), + mWidth(width), mHeight(height), + mIsFringeLayer(fringeLayer), + mHighlightAttackRange(config.getBoolValue("highlightAttackRange")) +{ + const int size = mWidth * mHeight; + mTiles = new Image*[size]; + + std::fill_n(mTiles, size, static_cast(nullptr)); + + config.addListener("highlightAttackRange", this); +} + +MapLayer::~MapLayer() +{ + config.removeListener("highlightAttackRange", this); + delete[] mTiles; + delete_all(mTempRows); + mTempRows.clear(); +} + +void MapLayer::optionChanged(const std::string &value) +{ + if (value == "highlightAttackRange") + { + mHighlightAttackRange = + config.getBoolValue("highlightAttackRange"); + } +} + +void MapLayer::setTile(int x, int y, Image *img) +{ + mTiles[x + y * mWidth] = img; +} + +void MapLayer::draw(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY, + int debugFlags) const +{ + if (!player_node) + return; + + startX -= mX; + startY -= mY; + endX -= mX; + endY -= mY; + + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + const int dx = (mX * 32) - scrollX; + const int dy = (mY * 32) - scrollY + 32; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + for (int y = startY; y < endY; y++) + { + const int y32 = y * 32; + const int yWidth = y * mWidth; + + const int py0 = y32 + dy; + + Image **tilePtr = mTiles + startX + yWidth; + + for (int x = startX; x < endX; x++, tilePtr++) + { + const int x32 = x * 32; + + int c = 0; + Image *img = *tilePtr; + if (img) + { + const int px = x32 + dx; + const int py = py0 - img->mBounds.h; + if (flag || img->mBounds.h <= 32) + { + int width = 0; + // here need not draw over player position + c = getTileDrawWidth(img, endX - x, width); + + if (!c) + { + graphics->drawImage(img, px, py); + } + else + { + graphics->drawImagePattern(img, px, py, + width, img->mBounds.h); + } + } + } + + x += c; + } + } +} + +void MapLayer::updateSDL(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY, + int debugFlags) +{ + delete_all(mTempRows); + mTempRows.clear(); + + startX -= mX; + startY -= mY; + endX -= mX; + endY -= mY; + + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + const int dx = (mX * 32) - scrollX; + const int dy = (mY * 32) - scrollY + 32; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + for (int y = startY; y < endY; y++) + { + MapRowVertexes *row = new MapRowVertexes(); + mTempRows.push_back(row); + + Image *lastImage = nullptr; + ImageVertexes *imgVert = nullptr; + + const int yWidth = y * mWidth; + const int py0 = y * 32 + dy; + Image **tilePtr = mTiles + startX + yWidth; + + for (int x = startX; x < endX; x++, tilePtr++) + { + Image *img = *tilePtr; + if (img) + { + const int px = x * 32 + dx; + const int py = py0 - img->mBounds.h; + if (flag || img->mBounds.h <= 32) + { + if (lastImage != img) + { + imgVert = new ImageVertexes(); + imgVert->image = img; + row->images.push_back(imgVert); + lastImage = img; + } + graphics->calcTile(imgVert, px, py); + } + } + } + } +} + +void MapLayer::drawSDL(Graphics *graphics) +{ + MapRows::const_iterator rit = mTempRows.begin(); + MapRows::const_iterator rit_end = mTempRows.end(); + while (rit != rit_end) + { + MepRowImages *images = &(*rit)->images; + MepRowImages::const_iterator iit = images->begin(); + MepRowImages::const_iterator iit_end = images->end(); + while (iit != iit_end) + { + graphics->drawTile(*iit); + ++ iit; + } + ++ rit; + } +} + +void MapLayer::updateOGL(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY, + int debugFlags) +{ + delete_all(mTempRows); + mTempRows.clear(); + + startX -= mX; + startY -= mY; + endX -= mX; + endY -= mY; + + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + const int dx = (mX * 32) - scrollX; + const int dy = (mY * 32) - scrollY + 32; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + for (int y = startY; y < endY; y++) + { + MapRowVertexes *row = new MapRowVertexes(); + mTempRows.push_back(row); + + Image *lastImage = nullptr; + ImageVertexes *imgVert = nullptr; + + const int yWidth = y * mWidth; + const int py0 = y * 32 + dy; + std::map imgSet; + + Image **tilePtr = mTiles + startX + yWidth; + for (int x = startX; x < endX; x++, tilePtr++) + { + Image *img = *tilePtr; + if (img) + { + const int px = x * 32 + dx; + const int py = py0 - img->mBounds.h; + if (flag || img->mBounds.h <= 32) + { + if (lastImage != img) + { + if (img->mBounds.w > 32) + imgSet.clear(); + + imgSet[lastImage] = imgVert; + if (imgSet.find(img) != imgSet.end()) + { + imgVert = imgSet[img]; + } + else + { + imgVert = new ImageVertexes(); + imgVert->image = img; + row->images.push_back(imgVert); + } + lastImage = img; + } + graphics->calcTile(imgVert, px, py); + } + } + } + } +} + +void MapLayer::drawOGL(Graphics *graphics) +{ + MapRows::const_iterator rit = mTempRows.begin(); + MapRows::const_iterator rit_end = mTempRows.end(); + while (rit != rit_end) + { + MepRowImages *images = &(*rit)->images; + MepRowImages::const_iterator iit = images->begin(); + MepRowImages::const_iterator iit_end = images->end(); + while (iit != iit_end) + { + graphics->drawTile(*iit); + ++ iit; + } + ++ rit; + } +} + +void MapLayer::drawFringe(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY, + const Actors *actors, int debugFlags, int yFix) const +{ + if (!player_node || !mSpecialLayer || !mTempLayer) + return; + + startX -= mX; + startY -= mY; + endX -= mX; + endY -= mY; + + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + Actors::const_iterator ai = actors->begin(); + + const int dx = (mX * 32) - scrollX; + const int dy = (mY * 32) - scrollY + 32; + + int specialWidth = mSpecialLayer->mWidth; + int specialHeight = mSpecialLayer->mHeight; + + for (int y = startY; y < endY; y++) + { + const int y32 = y * 32; + const int y32s = (y + yFix) * 32; + const int yWidth = y * mWidth; + + // If drawing the fringe layer, make sure all actors above this row of + // tiles have been drawn + while (ai != actors->end() && (*ai)->getPixelY() <= y32s) + { + (*ai)->draw(graphics, -scrollX, -scrollY); + ++ ai; + } + + if (debugFlags == Map::MAP_SPECIAL3 + || debugFlags == Map::MAP_BLACKWHITE) + { + if (y < specialHeight) + { + int ptr = y * specialWidth; + const int py1 = y32 - scrollY; + int endX1 = endX; + if (endX1 > specialWidth) + endX1 = specialWidth; + if (endX1 < 0) + endX1 = 0; + + for (int x = startX; x < endX1; x++) + { + const int px1 = x * 32 - scrollX; + + MapItem *item = mSpecialLayer->mTiles[ptr + x]; + if (item) + item->draw(graphics, px1, py1, 32, 32); + + item = mTempLayer->mTiles[ptr + x]; + if (item) + item->draw(graphics, px1, py1, 32, 32); + } + } + } + else + { + const int py0 = y32 + dy; + const int py1 = y32 - scrollY; + + Image **tilePtr = mTiles + startX + yWidth; + for (int x = startX; x < endX; x++, tilePtr++) + { + const int x32 = x * 32; + + const int px1 = x32 - scrollX; + int c = 0; + Image *img = *tilePtr; + if (img) + { + const int px = x32 + dx; + const int py = py0 - img->mBounds.h; + if ((debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2) + || img->mBounds.h <= 32) + { + int width = 0; + // here need not draw over player position + c = getTileDrawWidth(img, endX - x, width); + + if (!c) + { + graphics->drawImage(img, px, py); + } + else + { + graphics->drawImagePattern(img, px, py, + width, img->mBounds.h); + } + } + } + + if (y < specialHeight) + { + int c1 = c; + if (c1 + x + 1 > specialWidth) + c1 = specialWidth - x - 1; + if (c1 < 0) + c1 = 0; + + int ptr = y * specialWidth + x; + + for (int x1 = 0; x1 < c1 + 1; x1 ++) + { + MapItem *item1 = mSpecialLayer->mTiles[ptr + x1]; + MapItem *item2 = mTempLayer->mTiles[ptr + x1]; + if (item1 || item2) + { + const int px2 = px1 + (x1 * 32); + if (item1 && item1->mType != MapItem::EMPTY) + item1->draw(graphics, px2, py1, 32, 32); + + if (item2 && item2->mType != MapItem::EMPTY) + item2->draw(graphics, px2, py1, 32, 32); + } + } + } + x += c; + } + } + } + + // Draw any remaining actors + if (debugFlags != Map::MAP_SPECIAL3) + { + while (ai != actors->end()) + { + (*ai)->draw(graphics, -scrollX, -scrollY); + ++ai; + } + if (mHighlightAttackRange && player_node) + { + const int px = player_node->getPixelX() - scrollX - 16; + const int py = player_node->getPixelY() - scrollY - 32; + const int attackRange = player_node->getAttackRange() * 32; + + int x = px - attackRange; + int y = py - attackRange; + int w = 2 * attackRange + 32; + int h = w; + if (attackRange <= 32) + { + x -= 16; + y -= 16; + w += 32; + h += 32; + } + + if (userPalette) + { + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ATTACK_RANGE)); + + graphics->fillRectangle(gcn::Rectangle( + x, y, + w, h)); + + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ATTACK_RANGE_BORDER)); + + graphics->drawRectangle(gcn::Rectangle( + x, y, + w, h)); + } + } + } +} + +int MapLayer::getTileDrawWidth(Image *img, int endX, int &width) const +{ + Image *img1 = img; + int c = 0; + if (!img1) + { + width = 0; + return c; + } + width = img1->mBounds.w; + for (int x = 1; x < endX; x++) + { + img ++; + if (img != img1) + break; + c ++; + if (img) + width += img->mBounds.w; + } + return c; +} + +SpecialLayer::SpecialLayer(int width, int height, bool drawSprites): + mWidth(width), mHeight(height) +{ + const int size = mWidth * mHeight; + mTiles = new MapItem*[size]; + std::fill_n(mTiles, size, static_cast(nullptr)); + mDrawSprites = drawSprites; +} + +SpecialLayer::~SpecialLayer() +{ + for (int f = 0; f < mWidth * mHeight; f ++) + { + delete mTiles[f]; + mTiles[f] = nullptr; + } + delete[] mTiles; +} + +MapItem* SpecialLayer::getTile(int x, int y) const +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return nullptr; + } + return mTiles[x + y * mWidth]; +} + +void SpecialLayer::setTile(int x, int y, MapItem *item) +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return; + } + + int idx = x + y * mWidth; + delete mTiles[idx]; + if (item) + item->setPos(x, y); + mTiles[idx] = item; +} + +void SpecialLayer::setTile(int x, int y, int type) +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return; + } + + int idx = x + y * mWidth; + if (mTiles[idx]) + mTiles[idx]->setType(type); + else + mTiles[idx] = new MapItem(type); + mTiles[idx]->setPos(x, y); +} + +void SpecialLayer::addRoad(Path road) +{ + for (Path::const_iterator i = road.begin(), i_end = road.end(); + i != i_end; ++i) + { + Position pos = (*i); + MapItem *item = getTile(pos.x, pos.y); + if (!item) + { + item = new MapItem(MapItem::ROAD); + setTile(pos.x, pos.y, item); + } + else + { + item->setType(MapItem::ROAD); + } + } +} + +void SpecialLayer::clean() +{ + if (!mTiles) + return; + + for (int f = 0; f < mWidth * mHeight; f ++) + { + MapItem *item = mTiles[f]; + if (item) + item->setType(MapItem::EMPTY); + } +} + +void SpecialLayer::draw(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY) +{ + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + for (int y = startY; y < endY; y++) + { + for (int x = startX; x < endX; x++) + itemDraw(graphics, x, y, scrollX, scrollY); + } +} + +void SpecialLayer::itemDraw(Graphics *graphics, int x, int y, + int scrollX, int scrollY) +{ + MapItem *item = getTile(x, y); + if (item) + { + const int px = x * 32 - scrollX; + const int py = y * 32 - scrollY; + item->draw(graphics, px, py, 32, 32); + } +} + + +MapItem::MapItem(): + mImage(nullptr), mComment(""), mName(""), mX(-1), mY(-1) +{ + setType(EMPTY); +} + +MapItem::MapItem(int type): + mImage(nullptr), mComment(""), mName(""), mX(-1), mY(-1) +{ + setType(type); +} + +MapItem::MapItem(int type, std::string comment): + mImage(nullptr), mComment(comment), mName(""), mX(-1), mY(-1) +{ + setType(type); +} + +MapItem::MapItem(int type, std::string comment, int x, int y): + mImage(nullptr), mComment(comment), mName(""), mX(x), mY(y) +{ + setType(type); +} + +MapItem::~MapItem() +{ + if (mImage) + { + mImage->decRef(); + mImage = nullptr; + } +} + +void MapItem::setType(int type) +{ + std::string name(""); + mType = type; + if (mImage) + mImage->decRef(); + + switch (type) + { + case ARROW_UP: + name = "graphics/sprites/arrow_up.gif"; + break; + case ARROW_DOWN: + name = "graphics/sprites/arrow_down.gif"; + break; + case ARROW_LEFT: + name = "graphics/sprites/arrow_left.gif"; + break; + case ARROW_RIGHT: + name = "graphics/sprites/arrow_right.gif"; + break; + default: + break; + } + + if (name != "") + { + ResourceManager *resman = ResourceManager::getInstance(); + mImage = resman->getImage(name); + } + else + { + mImage = nullptr; + } +} + +void MapItem::setPos(int x, int y) +{ + mX = x; + mY = y; +} + +void MapItem::draw(Graphics *graphics, int x, int y, int dx, int dy) +{ + if (mImage) + graphics->drawImage(mImage, x, y); + + switch(mType) + { + case ROAD: + case CROSS: + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ROAD_POINT)); + graphics->fillRectangle(gcn::Rectangle(x + dx / 3, y + dy / 3, + dx / 3, dy / 3)); + break; + case HOME: + { + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::HOME_PLACE)); + graphics->fillRectangle(gcn::Rectangle( + x, y, + dx, dy)); + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::HOME_PLACE_BORDER)); + graphics->drawRectangle(gcn::Rectangle( + x, y, + dx, dy)); + break; + } + default: + break; + } + if (!mName.empty() && mType != PORTAL && mType != EMPTY && userPalette) + { + gcn::Font *font = gui->getFont(); + if (font) + { + graphics->setColor(userPalette->getColor(UserPalette::BEING)); + font->drawString(graphics, mName, x, y); + } + } +} + +ObjectsLayer::ObjectsLayer(unsigned width, unsigned height) : + mWidth(width), mHeight(height) +{ + const unsigned size = width * height; + mTiles = new MapObjectList*[size]; + std::fill_n(mTiles, size, static_cast(nullptr)); +} + +ObjectsLayer::~ObjectsLayer() +{ + const unsigned size = mWidth * mHeight; + for (unsigned f = 0; f < size; f ++) + delete mTiles[f]; + + delete [] mTiles; + mTiles = nullptr; +} + +void ObjectsLayer::addObject(std::string name, int type, + unsigned x, unsigned y, + unsigned dx, unsigned dy) +{ + if (!mTiles) + return; + + if (x + dx > mWidth) + dx = mWidth - x; + if (y + dy > mHeight) + dy = mHeight - y; + + for (unsigned y1 = y; y1 < y + dy; y1 ++) + { + unsigned idx1 = x + y1 * mWidth; + unsigned idx2 = idx1 + dx; + + for (unsigned i = idx1; i < idx2; i ++) + { + if (!mTiles[i]) + mTiles[i] = new MapObjectList(); + mTiles[i]->objects.push_back(MapObject(type, name)); + } + } +} + +MapObjectList *ObjectsLayer::getAt(unsigned x, unsigned y) +{ + if (x >= mWidth || y >= mHeight) + return nullptr; + return mTiles[x + y * mWidth]; +} + +MapRowVertexes::~MapRowVertexes() +{ + delete_all(images); + images.clear(); +} diff --git a/src/maplayer.h b/src/maplayer.h new file mode 100644 index 000000000..861ef1318 --- /dev/null +++ b/src/maplayer.h @@ -0,0 +1,299 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MAPLAYER_H +#define MAPLAYER_H + +#include "actor.h" +#include "configlistener.h" +#include "position.h" +#include "properties.h" + +#include +#include + +class MapItem; +class MapLayer; +class SpecialLayer; +class ImageVertexes; + +typedef std::vector MepRowImages; + +class MapRowVertexes +{ + public: + MapRowVertexes() + { + images.reserve(30); + } + + ~MapRowVertexes(); + + MepRowImages images; +}; + +class MapObject +{ + public: + MapObject(int type0, std::string data0) + { + type = type0; + data = data0; + } + + int type; + std::string data; +}; + +class MapObjectList +{ + public: + std::vector objects; +}; + +/** + * A map layer. Stores a grid of tiles and their offset, and implements layer + * rendering. + */ +class MapLayer: public ConfigListener +{ + public: + friend class Map; + + /** + * Constructor, taking layer origin, size and whether this layer is the + * fringe layer. The fringe layer is the layer that draws the actors. + * There can be only one fringe layer per map. + */ + MapLayer(int x, int y, int width, int height, bool isFringeLayer); + + /** + * Destructor. + */ + ~MapLayer(); + + /** + * Set tile image, with x and y in layer coordinates. + */ + void setTile(int x, int y, Image *img); + + /** + * Set tile image with x + y * width already known. + */ + void setTile(int index, Image *img) + { mTiles[index] = img; } + + /** + * Draws this layer to the given graphics context. The coordinates are + * expected to be in map range and will be translated to local layer + * coordinates and clipped to the layer's dimensions. + * + * The given actors are only drawn when this layer is the fringe + * layer. + */ + void draw(Graphics *graphics, + int startX, int startY, + int endX, int endY, + int scrollX, int scrollY, + int mDebugFlags) const; + + void drawOGL(Graphics *graphics); + + void drawSDL(Graphics *graphics); + + void updateOGL(Graphics *graphics, + int startX, int startY, + int endX, int endY, + int scrollX, int scrollY, + int mDebugFlags); + + void updateSDL(Graphics *graphics, + int startX, int startY, + int endX, int endY, + int scrollX, int scrollY, + int mDebugFlags); + + void drawFringe(Graphics *graphics, + int startX, int startY, + int endX, int endY, + int scrollX, int scrollY, + const Actors *actors, + int mDebugFlags, int yFix) const; + + bool isFringeLayer() const + { return mIsFringeLayer; } + + void setSpecialLayer(SpecialLayer *val) + { mSpecialLayer = val; } + + void setTempLayer(SpecialLayer *val) + { mTempLayer = val; } + + int getWidth() const + { return mWidth; } + + int getHeight() const + { return mHeight; } + +// void setTileInfo(int x, int y, int width, int cnt); + +// void getTileInfo(int x, int y, int &width, int &cnt) const; + + void optionChanged(const std::string &value); + + int getTileDrawWidth(Image *img, int endX, int &width) const; + +// void initTileInfo(); + + private: + int mX, mY; + int mWidth, mHeight; + bool mIsFringeLayer; /**< Whether the actors are drawn. */ + bool mHighlightAttackRange; + Image **mTiles; +// int *mTilesWidth; +// int *mTilesCount; + SpecialLayer *mSpecialLayer; + SpecialLayer *mTempLayer; + typedef std::vector MapRows; + MapRows mTempRows; +}; + +class SpecialLayer +{ + public: + friend class Map; + friend class MapLayer; + + SpecialLayer(int width, int height, bool drawSprites = false); + + ~SpecialLayer(); + + void draw(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY); + + MapItem* getTile(int x, int y) const; + + void setTile(int x, int y, MapItem* item); + + void setTile(int x, int y, int type); + + void addRoad(Path road); + + void clean(); + + void itemDraw(Graphics *graphics, int x, int y, + int scrollX, int scrollY); + + private: + int mWidth, mHeight; + bool mDrawSprites; + MapItem **mTiles; +}; + +class MapItem +{ + public: + friend class Map; + friend class MapLayer; + + enum ItemType + { + EMPTY = 0, + HOME = 1, + ROAD = 2, + CROSS = 3, + ARROW_UP = 4, + ARROW_DOWN = 5, + ARROW_LEFT = 6, + ARROW_RIGHT = 7, + PORTAL = 8, + MUSIC = 9, + ATTACK = 10, + PRIORITY = 11, + IGNORE_ = 12, + SEPARATOR = 13 + }; + + MapItem(); + + MapItem(int type); + + MapItem(int type, std::string comment); + + MapItem(int type, std::string comment, int x, int y); + + ~MapItem(); + + int getType() const + { return mType; } + + void setType(int type); + + void setPos(int x, int y); + + int getX() const + { return mX; } + + int getY() const + { return mY; } + + std::string &getComment() + { return mComment; } + + void setComment(std::string comment) + { mComment = comment; } + + std::string &getName() + { return mName; } + + void setName(std::string name) + { mName = name; } + + void draw(Graphics *graphics, int x, int y, int dx, int dy); + + private: + int mType; + Image *mImage; + std::string mComment; + std::string mName; + int mX; + int mY; +}; + +class ObjectsLayer +{ + public: + ObjectsLayer(unsigned width, unsigned height); + ~ObjectsLayer(); + + void addObject(std::string name, int type, unsigned x, unsigned y, + unsigned dx, unsigned dy); + + MapObjectList *getAt(unsigned x, unsigned y); + private: + MapObjectList **mTiles; + unsigned mWidth; + unsigned mHeight; +}; + +#endif diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 8d71779f2..1ddb74f20 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -25,6 +25,7 @@ #include "configuration.h" #include "logger.h" #include "map.h" +#include "maplayer.h" #include "tileset.h" #include "resources/animation.h" -- cgit v1.2.3-60-g2f50