From ad42810bb9484f4930252ecc34b91d83f37e3293 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 11 May 2014 13:18:07 +0300 Subject: Move map related files into resources/map. --- src/CMakeLists.txt | 16 +- src/Makefile.am | 20 +- src/being/actor.cpp | 2 +- src/being/actorsprite.h | 3 +- src/being/compoundsprite.cpp | 3 +- src/being/localplayer.cpp | 5 +- src/gui/popups/popupmenu.cpp | 3 +- src/gui/viewport.cpp | 3 +- src/gui/widgets/avatarlistbox.cpp | 3 +- src/gui/widgets/tabs/setup_audio.cpp | 3 +- src/gui/widgets/tabs/setup_other.cpp | 3 +- src/gui/windows/socialwindow.cpp | 3 +- src/map.cpp | 1508 --------------------------------- src/map.h | 539 ------------ src/mapheights.cpp | 41 - src/mapheights.h | 48 -- src/maplayer.cpp | 892 -------------------- src/maplayer.h | 328 -------- src/navigationmanager.cpp | 4 +- src/particle/particleemitter.cpp | 3 +- src/properties.h | 135 --- src/resources/ambientlayer.cpp | 2 +- src/resources/db/itemdb.cpp | 2 +- src/resources/iteminfo.cpp | 2 +- src/resources/map/map.cpp | 1509 ++++++++++++++++++++++++++++++++++ src/resources/map/map.h | 540 ++++++++++++ src/resources/map/mapheights.cpp | 41 + src/resources/map/mapheights.h | 48 ++ src/resources/map/maplayer.cpp | 892 ++++++++++++++++++++ src/resources/map/maplayer.h | 328 ++++++++ src/resources/map/properties.h | 135 +++ src/resources/map/tileset.h | 79 ++ src/resources/map/walklayer.cpp | 44 + src/resources/map/walklayer.h | 48 ++ src/resources/mapreader.cpp | 5 +- src/resources/mapreader.h | 4 +- src/resources/resourcemanager.cpp | 3 +- src/resources/spritedef.cpp | 3 +- src/simpleanimation.cpp | 3 +- src/tileset.h | 79 -- src/walklayer.cpp | 44 - src/walklayer.h | 48 -- 42 files changed, 3720 insertions(+), 3704 deletions(-) delete mode 100644 src/map.cpp delete mode 100644 src/map.h delete mode 100644 src/mapheights.cpp delete mode 100644 src/mapheights.h delete mode 100644 src/maplayer.cpp delete mode 100644 src/maplayer.h delete mode 100644 src/properties.h create mode 100644 src/resources/map/map.cpp create mode 100644 src/resources/map/map.h create mode 100644 src/resources/map/mapheights.cpp create mode 100644 src/resources/map/mapheights.h create mode 100644 src/resources/map/maplayer.cpp create mode 100644 src/resources/map/maplayer.h create mode 100644 src/resources/map/properties.h create mode 100644 src/resources/map/tileset.h create mode 100644 src/resources/map/walklayer.cpp create mode 100644 src/resources/map/walklayer.h delete mode 100644 src/tileset.h delete mode 100644 src/walklayer.cpp delete mode 100644 src/walklayer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0cffef1f1..da54502f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -704,12 +704,12 @@ SET(SRCS logger.h main.cpp main.h - map.cpp - map.h - mapheights.cpp - mapheights.h - maplayer.cpp - maplayer.h + resources/map/map.cpp + resources/map/map.h + resources/map/mapheights.cpp + resources/map/mapheights.h + resources/map/maplayer.cpp + resources/map/maplayer.h render/mgl.cpp render/mgl.h render/mobileopenglgraphics.cpp @@ -795,8 +795,8 @@ SET(SRCS variabledata.h vector.cpp vector.h - walklayer.cpp - walklayer.h + resources/map/walklayer.cpp + resources/map/walklayer.h events/actionevent.h listeners/actionlistener.h gui/widgets/basiccontainer.h diff --git a/src/Makefile.am b/src/Makefile.am index 0a77df64a..de93fd832 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,8 +50,8 @@ dyecmd_SOURCES += dyetool/dyemain.cpp \ logger.h \ navigationmanager.cpp \ navigationmanager.h \ - walklayer.cpp \ - walklayer.h \ + resources/map/walklayer.cpp \ + resources/map/walklayer.h \ render/graphics.cpp \ render/graphics.h \ render/renderers.cpp \ @@ -793,12 +793,12 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ logger.h \ main.cpp \ main.h \ - map.cpp \ - map.h \ - mapheights.cpp \ - mapheights.h \ - maplayer.cpp \ - maplayer.h \ + resources/map/map.cpp \ + resources/map/map.h \ + resources/map/mapheights.cpp \ + resources/map/mapheights.h \ + resources/map/maplayer.cpp \ + resources/map/maplayer.h \ render/mgl.cpp \ render/mgl.h \ render/mobileopenglgraphics.cpp \ @@ -882,8 +882,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ variabledata.h \ vector.cpp \ vector.h \ - walklayer.cpp \ - walklayer.h \ + resources/map/walklayer.cpp \ + resources/map/walklayer.h \ winver.h manaplus_SOURCES += \ diff --git a/src/being/actor.cpp b/src/being/actor.cpp index 1416b5481..7ced058d8 100644 --- a/src/being/actor.cpp +++ b/src/being/actor.cpp @@ -21,7 +21,7 @@ #include "being/actor.h" -#include "map.h" +#include "resources/map/map.h" #include "debug.h" diff --git a/src/being/actorsprite.h b/src/being/actorsprite.h index fd90aba09..ed0d328de 100644 --- a/src/being/actorsprite.h +++ b/src/being/actorsprite.h @@ -23,7 +23,8 @@ #define BEING_ACTORSPRITE_H #include "localconsts.h" -#include "map.h" + +#include "resources/map/map.h" #include "being/actor.h" #include "being/compoundsprite.h" diff --git a/src/being/compoundsprite.cpp b/src/being/compoundsprite.cpp index 91da283a4..46baaf2c9 100644 --- a/src/being/compoundsprite.cpp +++ b/src/being/compoundsprite.cpp @@ -28,9 +28,10 @@ #include "main.h" #endif -#include "map.h" #include "sdlshared.h" +#include "resources/map/map.h" + #include "render/surfacegraphics.h" #include "resources/image.h" diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp index 7a364072c..697a31069 100644 --- a/src/being/localplayer.cpp +++ b/src/being/localplayer.cpp @@ -29,12 +29,11 @@ #include "dropshortcut.h" #include "guild.h" #include "item.h" -#include "maplayer.h" #include "party.h" #include "soundconsts.h" #include "soundmanager.h" #include "statuseffect.h" -#include "walklayer.h" +#include "resources/map/walklayer.h" #include "being/playerinfo.h" #include "being/playerrelations.h" @@ -69,6 +68,8 @@ #include "resources/db/emotedb.h" #include "resources/db/weaponsdb.h" +#include "resources/map/maplayer.h" + #include "listeners/updatestatuslistener.h" #include "utils/delete2.h" diff --git a/src/gui/popups/popupmenu.cpp b/src/gui/popups/popupmenu.cpp index 9e6968464..4b84c47b3 100644 --- a/src/gui/popups/popupmenu.cpp +++ b/src/gui/popups/popupmenu.cpp @@ -31,7 +31,6 @@ #include "guild.h" #include "guildmanager.h" #include "item.h" -#include "maplayer.h" #include "party.h" #include "spellmanager.h" @@ -77,6 +76,8 @@ #include "resources/iteminfo.h" +#include "resources/map/maplayer.h" + #include "utils/copynpaste.h" #include "utils/gettext.h" #include "utils/process.h" diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 33690ba39..e2b039fe1 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -25,10 +25,11 @@ #include "actormanager.h" #include "configuration.h" #include "game.h" -#include "maplayer.h" #include "sdlshared.h" #include "textmanager.h" +#include "resources/map/maplayer.h" + #include "being/localplayer.h" #include "being/playerinfo.h" diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index a84ac7c6d..1ff611cab 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -24,7 +24,6 @@ #include "actormanager.h" #include "configuration.h" #include "graphicsvertexes.h" -#include "maplayer.h" #include "being/localplayer.h" @@ -38,6 +37,8 @@ #include "resources/image.h" +#include "resources/map/maplayer.h" + #include "debug.h" int AvatarListBox::instances = 0; diff --git a/src/gui/widgets/tabs/setup_audio.cpp b/src/gui/widgets/tabs/setup_audio.cpp index 707a4f2b9..daf8ed8d2 100644 --- a/src/gui/widgets/tabs/setup_audio.cpp +++ b/src/gui/widgets/tabs/setup_audio.cpp @@ -23,7 +23,8 @@ #include "gui/widgets/tabs/setup_audio.h" #include "main.h" -#include "map.h" + +#include "resources/map/map.h" #include "configuration.h" #include "soundmanager.h" diff --git a/src/gui/widgets/tabs/setup_other.cpp b/src/gui/widgets/tabs/setup_other.cpp index ed8ba11ad..4d648bba1 100644 --- a/src/gui/widgets/tabs/setup_other.cpp +++ b/src/gui/widgets/tabs/setup_other.cpp @@ -29,7 +29,8 @@ #include "gui/widgets/scrollarea.h" #include "configuration.h" -#include "map.h" + +#include "resources/map/map.h" #include "utils/delete2.h" #include "utils/gettext.h" diff --git a/src/gui/windows/socialwindow.cpp b/src/gui/windows/socialwindow.cpp index 34a8bcf12..dbbb9c75d 100644 --- a/src/gui/windows/socialwindow.cpp +++ b/src/gui/windows/socialwindow.cpp @@ -25,9 +25,10 @@ #include "configuration.h" #include "guild.h" #include "guildmanager.h" -#include "maplayer.h" #include "party.h" +#include "resources/map/maplayer.h" + #include "being/localplayer.h" #include "being/playerrelations.h" diff --git a/src/map.cpp b/src/map.cpp deleted file mode 100644 index 1acfdf711..000000000 --- a/src/map.cpp +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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 "map.h" - -#include "client.h" -#include "configuration.h" -#include "render/graphics.h" -#include "mapheights.h" -#include "maplayer.h" -#include "notifications.h" -#include "notifymanager.h" -#include "simpleanimation.h" -#include "tileset.h" -#include "walklayer.h" - -#include "being/localplayer.h" - -#include "particle/particle.h" - -#include "resources/ambientlayer.h" -#include "resources/image.h" -#include "resources/resourcemanager.h" -#include "resources/subimage.h" - -#include "utils/delete2.h" -#include "utils/dtor.h" -#include "utils/mkdir.h" -#include "utils/physfstools.h" -#include "utils/timer.h" - -#include -#include - -#include - -#include "debug.h" - -/** - * A location on a tile map. Used for pathfinding, open list. - */ -struct Location final -{ - /** - * Constructor. - */ - Location(const int px, const int py, MetaTile *const ptile): - x(px), y(py), tile(ptile) - {} - - /** - * Comparison operator. - */ - bool operator< (const Location &loc) const - { - return tile->Fcost > loc.tile->Fcost; - } - - int x, y; - MetaTile *tile; -}; - -class ActorFunctuator final -{ - public: - bool operator()(const Actor *const a, const Actor *const b) const - { - if (!a || !b) - return false; - return a->getSortPixelY() < b->getSortPixelY(); - } -} actorCompare; - -TileAnimation::TileAnimation(Animation *const ani): - mAffected(), - mAnimation(new SimpleAnimation(ani)), - mLastImage(nullptr) -{ -} - -TileAnimation::~TileAnimation() -{ - delete2(mAnimation); -} - -bool TileAnimation::update(const int ticks) -{ - if (!mAnimation) - return false; - - // update animation - if (!mAnimation->update(ticks)) - return false; - - // exchange images - Image *const img = mAnimation->getCurrentImage(); - if (img != mLastImage) - { - FOR_EACH (TilePairVectorCIter, i, mAffected) - { - if (i->first) - i->first->setTile(i->second, img); - } - mLastImage = img; - } - return true; -} - -Map::Map(const int width, const int height, - const int tileWidth, const int tileHeight) : - Properties(), - mWidth(width), mHeight(height), - mTileWidth(tileWidth), mTileHeight(tileHeight), - mMaxTileHeight(height), - mMetaTiles(new MetaTile[mWidth * mHeight]), - mWalkLayer(nullptr), - mLayers(), - mTilesets(), - mActors(), - mHasWarps(false), - mDebugFlags(MAP_NORMAL), - mOnClosedList(1), - mOnOpenList(2), - mBackgrounds(), - mForegrounds(), - mLastAScrollX(0.0F), - mLastAScrollY(0.0F), - mParticleEffects(), - mMapPortals(), - mTileAnimations(), - mOverlayDetail(config.getIntValue("OverlayDetail")), - mOpacity(config.getFloatValue("guialpha")), -#ifdef USE_OPENGL - mOpenGL(intToRenderType(config.getIntValue("opengl"))), -#else - mOpenGL(RENDER_SOFTWARE), -#endif - mPvp(0), - mTilesetsIndexed(false), - mIndexedTilesets(nullptr), - mIndexedTilesetsSize(0), - mActorFixX(0), - mActorFixY(0), - mVersion(0), - mSpecialLayer(new SpecialLayer(width, height)), - mTempLayer(new SpecialLayer(width, height)), - mObjects(new ObjectsLayer(width, height)), - mFringeLayer(nullptr), - mLastX(-1), - mLastY(-1), - mLastScrollX(-1), - mLastScrollY(-1), - mDrawX(-1), - mDrawY(-1), - mDrawScrollX(-1), - mDrawScrollY(-1), - mMask(1), - mAtlas(nullptr), - mHeights(nullptr), - mRedrawMap(true), - mBeingOpacity(false), - mCustom(false) -{ - const int size = mWidth * mHeight; - for (int i = 0; i < NB_BLOCKTYPES; i++) - { - mOccupation[i] = new unsigned[static_cast(size)]; - memset(mOccupation[i], 0, static_cast(size) - * sizeof(unsigned)); - } - - config.addListener("OverlayDetail", this); - config.addListener("guialpha", this); - config.addListener("beingopacity", this); - - if (mOpacity != 1.0F) - mBeingOpacity = config.getBoolValue("beingopacity"); - else - mBeingOpacity = false; -} - -Map::~Map() -{ - config.removeListeners(this); - CHECKLISTENERS - - delete [] mMetaTiles; - for (int i = 0; i < NB_BLOCKTYPES; i++) - delete [] mOccupation[i]; - - if (mWalkLayer) - { - mWalkLayer->decRef(); - mWalkLayer = nullptr; - } - mFringeLayer = nullptr; - delete_all(mLayers); - delete_all(mTilesets); - delete_all(mForegrounds); - delete_all(mBackgrounds); - delete_all(mTileAnimations); - delete2(mSpecialLayer); - delete2(mTempLayer); - delete2(mObjects); - delete_all(mMapPortals); - if (mAtlas) - { - mAtlas->decRef(); - mAtlas = nullptr; - } - delete2(mHeights); -} - -void Map::optionChanged(const std::string &value) -{ - if (value == "OverlayDetail") - { - mOverlayDetail = config.getIntValue("OverlayDetail"); - } - else if (value == "guialpha") - { - mOpacity = config.getFloatValue("guialpha"); - if (mOpacity != 1.0F) - mBeingOpacity = config.getBoolValue("beingopacity"); - else - mBeingOpacity = false; - } - else if (value == "beingopacity") - { - if (mOpacity != 1.0F) - mBeingOpacity = config.getBoolValue("beingopacity"); - else - mBeingOpacity = false; - } -} - -void Map::initializeAmbientLayers() -{ - ResourceManager *const resman = ResourceManager::getInstance(); - - // search for "foreground*" or "overlay*" (old term) in map properties - for (int i = 0; /* terminated by a break */; i++) - { - std::string name; - if (hasProperty(std::string("foreground").append( - toString(i)).append("image"))) - { - name = "foreground" + toString(i); - } - else if (hasProperty(std::string("overlay").append( - toString(i)).append("image"))) - { - name = "overlay" + toString(i); - } - else - { - break; // the FOR loop - } - - Image *const img = resman->getImage(getProperty(name + "image")); - if (img) - { - int mask = atoi(getProperty(name + "mask").c_str()); - if (!mask) - mask = 1; - const float parallax = getFloatProperty(name + "parallax"); - mForegrounds.push_back(new AmbientLayer(img, - getFloatProperty(name + "parallaxX", parallax), - getFloatProperty(name + "parallaxY", parallax), - getFloatProperty(name + "posX"), - getFloatProperty(name + "posY"), - getFloatProperty(name + "scrollX"), - getFloatProperty(name + "scrollY"), - getBoolProperty(name + "keepratio"), - mask)); - - // The AmbientLayer takes control over the image. - img->decRef(); - } - } - - // search for "background*" in map properties - for (int i = 0; hasProperty(std::string("background").append( - toString(i)).append("image")); i ++) - { - const std::string name("background" + toString(i)); - Image *const img = resman->getImage(getProperty(name + "image")); - - if (img) - { - int mask = atoi(getProperty(name + "mask").c_str()); - if (!mask) - mask = 1; - - const float parallax = getFloatProperty(name + "parallax"); - mForegrounds.push_back(new AmbientLayer(img, - getFloatProperty(name + "parallaxX", parallax), - getFloatProperty(name + "parallaxY", parallax), - getFloatProperty(name + "posX"), - getFloatProperty(name + "posY"), - getFloatProperty(name + "scrollX"), - getFloatProperty(name + "scrollY"), - getBoolProperty(name + "keepratio"), - mask)); - - // The AmbientLayer takes control over the image. - img->decRef(); - } - } -} - -void Map::addLayer(MapLayer *const layer) -{ - if (layer) - { - mLayers.push_back(layer); - if (layer->isFringeLayer() && !mFringeLayer) - mFringeLayer = layer; - } -} - -void Map::addTileset(Tileset *const tileset) -{ - if (!tileset) - return; - - mTilesets.push_back(tileset); - const int height = tileset->getHeight(); - if (height > mMaxTileHeight) - mMaxTileHeight = height; -} - -void Map::update(const int ticks) -{ - // Update animated tiles - FOR_EACH (TileAnimationMapCIter, iAni, mTileAnimations) - { - TileAnimation *const tileAni = iAni->second; - if (tileAni && tileAni->update(ticks)) - mRedrawMap = true; - } -} - -void Map::draw(Graphics *const graphics, int scrollX, int scrollY) -{ - if (!player_node) - return; - - BLOCK_START("Map::draw") - // Calculate range of tiles which are on-screen - const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1 - + mMaxTileHeight - mTileHeight; - const int startX = scrollX / mTileWidth - 2; - const int startY = scrollY / mTileHeight; - const int endX = (graphics->mWidth + scrollX + mTileWidth - 1) - / mTileWidth + 1; - const int endY = endPixelY / mTileHeight + 1; - - // Make sure actors are sorted ascending by Y-coordinate - // so that they overlap correctly - BLOCK_START("Map::draw sort") - mActors.sort(actorCompare); - BLOCK_END("Map::draw sort") - - // update scrolling of all ambient layers - updateAmbientLayers(static_cast(scrollX), - static_cast(scrollY)); - - // Draw backgrounds - drawAmbientLayers(graphics, BACKGROUND_LAYERS, mOverlayDetail); - - if (mDebugFlags == MAP_BLACKWHITE && userPalette) - { - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::WALKABLE_HIGHLIGHT)); - - graphics->fillRectangle(Rect(0, 0, - graphics->mWidth, graphics->mHeight)); - } - -#ifdef USE_OPENGL - int updateFlag = 0; - - if (mOpenGL == RENDER_NORMAL_OPENGL || mOpenGL == RENDER_GLES_OPENGL) - { - if (mLastX != startX || mLastY != startY || mLastScrollX != scrollX - || mLastScrollY != scrollY) - { // player moving - mLastX = startX; - mLastY = startY; - mLastScrollX = scrollX; - mLastScrollY = scrollY; - updateFlag = 2; - } - else if (mRedrawMap || startX != mDrawX || startY != mDrawY || - scrollX != mDrawScrollX || scrollY != mDrawScrollY) - { // player mode to new position - mRedrawMap = false; - mDrawX = startX; - mDrawY = startY; - mDrawScrollX = scrollX; - mDrawScrollY = scrollY; - updateFlag = 1; - } - } -#endif - - if (mDebugFlags == MAP_SPECIAL3 || mDebugFlags == MAP_BLACKWHITE) - { - if (mFringeLayer) - { - mFringeLayer->setSpecialLayer(mSpecialLayer); - mFringeLayer->setTempLayer(mTempLayer); - mFringeLayer->drawFringe(graphics, startX, startY, endX, endY, - scrollX, scrollY, &mActors, mDebugFlags, mActorFixY); - } - } - else - { - bool overFringe = false; - - for (LayersCIter layeri = mLayers.begin(), layeri_end = mLayers.end(); - layeri != layeri_end && !overFringe; ++ layeri) - { - MapLayer *const layer = *layeri; - if (!(layer->mMask & mMask)) - continue; - - if (layer->isFringeLayer()) - { - layer->setSpecialLayer(mSpecialLayer); - layer->setTempLayer(mTempLayer); - if (mDebugFlags == MAP_SPECIAL2) - overFringe = true; - - layer->drawFringe(graphics, startX, startY, endX, endY, - scrollX, scrollY, &mActors, mDebugFlags, mActorFixY); - } - else - { -#ifdef USE_OPENGL - if (mOpenGL == RENDER_NORMAL_OPENGL - || mOpenGL == RENDER_GLES_OPENGL) - { - if (updateFlag) - { - layer->updateOGL(graphics, startX, startY, - endX, endY, scrollX, scrollY, mDebugFlags); - } - - layer->drawOGL(graphics); - } - else -#endif - { - layer->draw(graphics, startX, startY, endX, endY, - scrollX, scrollY, mDebugFlags); - } - } - } - } - - // Don't draw if gui opacity == 1 - if (mBeingOpacity && mOpacity != 1.0F) - { - // Draws beings with a lower opacity to make them visible - // even when covered by a wall or some other elements... - ActorsCIter ai = mActors.begin(); - const ActorsCIter ai_end = mActors.end(); - while (ai != ai_end) - { - if (Actor *const actor = *ai) - { - if (mOpenGL == RENDER_SOFTWARE) - { - const int x = actor->getTileX(); - const int y = actor->getTileY(); - if (x < startX || x > endX || y < startY || y > endY) - { - ++ai; - continue; - } - } - // For now, just draw actors with only one layer. - if (actor->getNumberOfLayers() == 1) - { - actor->setAlpha(0.3F); - actor->draw(graphics, -scrollX, -scrollY); - actor->setAlpha(1.0F); - } - } - ++ai; - } - } - - drawAmbientLayers(graphics, FOREGROUND_LAYERS, mOverlayDetail); - BLOCK_END("Map::draw") -} - -#define fillCollision(collision, color) \ - if (x < endX && mMetaTiles[tilePtr].blockmask & collision)\ - {\ - width = mapTileSize;\ - for (int x2 = tilePtr + 1; x < endX; x2 ++)\ - {\ - if (!(mMetaTiles[x2].blockmask & collision))\ - break;\ - width += mapTileSize;\ - x ++;\ - tilePtr ++;\ - }\ - if (width && userPalette)\ - {\ - graphics->setColor(userPalette->getColorWithAlpha(\ - UserPalette::color));\ - graphics->fillRectangle(Rect(\ - x0 * mTileWidth - scrollX, \ - y * mTileHeight - scrollY, \ - width, mapTileSize));\ - }\ - }\ - -void Map::drawCollision(Graphics *const graphics, - const int scrollX, const int scrollY, - const int debugFlags) const -{ - const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1; - int startX = scrollX / mTileWidth; - int startY = scrollY / mTileHeight; - int endX = (graphics->mWidth + scrollX + mTileWidth - 1) / mTileWidth; - int endY = endPixelY / mTileHeight; - - if (startX < 0) - startX = 0; - if (startY < 0) - startY = 0; - if (endX > mWidth) - endX = mWidth; - if (endY > mHeight) - endY = mHeight; - - if (debugFlags < MAP_SPECIAL) - { - graphics->setColor(userPalette->getColorWithAlpha(UserPalette::NET)); - graphics->drawNet( - startX * mTileWidth - scrollX, - startY * mTileHeight - scrollY, - endX * mTileWidth - scrollX, - endY * mTileHeight - scrollY, - mapTileSize, mapTileSize); - } - - for (int y = startY; y < endY; y++) - { - const int yWidth = y * mWidth; - int tilePtr = startX + yWidth; - for (int x = startX; x < endX; x++, tilePtr++) - { - int width = 0; - const int x0 = x; - - fillCollision(BLOCKMASK_WALL, COLLISION_HIGHLIGHT); - fillCollision(BLOCKMASK_AIR, AIR_COLLISION_HIGHLIGHT); - fillCollision(BLOCKMASK_WATER, WATER_COLLISION_HIGHLIGHT); - fillCollision(BLOCKMASK_GROUNDTOP, GROUNDTOP_COLLISION_HIGHLIGHT); - } - } -} - -void Map::updateAmbientLayers(const float scrollX, const float scrollY) -{ - BLOCK_START("Map::updateAmbientLayers") - static int lastTick = tick_time; - - if (mLastAScrollX == 0.0F && mLastAScrollY == 0.0F) - { - // First call - initialisation - mLastAScrollX = scrollX; - mLastAScrollY = scrollY; - } - - // Update Overlays - const float dx = scrollX - mLastAScrollX; - const float dy = scrollY - mLastAScrollY; - const int timePassed = get_elapsed_time(lastTick); - - // need check mask to update or not to update - - FOR_EACH (AmbientLayerVectorIter, i, mBackgrounds) - { - AmbientLayer *const layer = *i; - if (layer && (layer->mMask & mMask)) - layer->update(timePassed, dx, dy); - } - - FOR_EACH (AmbientLayerVectorIter, i, mForegrounds) - { - AmbientLayer *const layer = *i; - if (layer && (layer->mMask & mMask)) - layer->update(timePassed, dx, dy); - } - - mLastAScrollX = scrollX; - mLastAScrollY = scrollY; - lastTick = tick_time; - BLOCK_END("Map::updateAmbientLayers") -} - -void Map::drawAmbientLayers(Graphics *const graphics, const LayerType type, - const int detail) -{ - BLOCK_START("Map::drawAmbientLayers") - // Detail 0 = no ambient effects except background image - if (detail <= 0 && type != BACKGROUND_LAYERS) - { - BLOCK_END("Map::drawAmbientLayers") - return; - } - - // find out which layer list to draw - AmbientLayerVector *layers = nullptr; - switch (type) - { - case FOREGROUND_LAYERS: - layers = &mForegrounds; - break; - case BACKGROUND_LAYERS: - layers = &mBackgrounds; - break; - default: - return; - } - - // Draw overlays - FOR_EACHP (AmbientLayerVectorCIter, i, layers) - { - const AmbientLayer *const layer = *i; - // need check mask to draw or not to draw - if (layer && (layer->mMask & mMask)) - (layer)->draw(graphics, graphics->mWidth, graphics->mHeight); - - // Detail 1: only one overlay, higher: all overlays - if (detail == 1) - break; - } - BLOCK_END("Map::drawAmbientLayers") -} - -const Tileset *Map::getTilesetWithGid(const int gid) const -{ - if (gid >= 0 && gid < mIndexedTilesetsSize) - return mIndexedTilesets[gid]; - else - return nullptr; -} - -void Map::blockTile(const int x, const int y, const BlockType type) -{ - if (type == BLOCKTYPE_NONE || !contains(x, y)) - return; - - const int tileNum = x + y * mWidth; - - if (mOccupation[static_cast(type)][tileNum] < UINT_MAX && - (++mOccupation[static_cast(type)][tileNum]) > 0) - { - switch (type) - { - case BLOCKTYPE_WALL: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_WALL; - break; - case BLOCKTYPE_CHARACTER: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_CHARACTER; - break; - case BLOCKTYPE_MONSTER: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_MONSTER; - break; - case BLOCKTYPE_AIR: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_AIR; - break; - case BLOCKTYPE_WATER: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_WATER; - break; - case BLOCKTYPE_GROUND: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_GROUND; - break; - case BLOCKTYPE_GROUNDTOP: - mMetaTiles[tileNum].blockmask |= BLOCKMASK_GROUNDTOP; - break; - default: - case BLOCKTYPE_NONE: - case NB_BLOCKTYPES: - // Do nothing. - break; - } - } -} - -bool Map::getWalk(const int x, const int y, const unsigned char walkmask) const -{ - // You can't walk outside of the map - if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) - return false; - - // Check if the tile is walkable - return !(mMetaTiles[x + y * mWidth].blockmask & walkmask); -} - -unsigned char Map::getBlockMask(const int x, const int y) const -{ - // You can't walk outside of the map - if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) - return 0; - - // Check if the tile is walkable - return mMetaTiles[x + y * mWidth].blockmask; -} - -void Map::setWalk(const int x, const int y, const bool walkable A_UNUSED) -{ - blockTile(x, y, Map::BLOCKTYPE_GROUNDTOP); -} - -bool Map::contains(const int x, const int y) const -{ - return x >= 0 && y >= 0 && x < mWidth && y < mHeight; -} - -const MetaTile *Map::getMetaTile(const int x, const int y) const -{ - return &mMetaTiles[x + y * mWidth]; -} - -Actors::iterator Map::addActor(Actor *const actor) -{ - mActors.push_front(actor); -// mSpritesUpdated = true; - return mActors.begin(); -} - -void Map::removeActor(const Actors::iterator &iterator) -{ - mActors.erase(iterator); -// mSpritesUpdated = true; -} - -const std::string Map::getMusicFile() const -{ - return getProperty("music"); -} - -const std::string Map::getName() const -{ - if (hasProperty("name")) - return getProperty("name"); - - return getProperty("mapname"); -} - -const std::string Map::getFilename() const -{ - const std::string fileName = getProperty("_filename"); - const size_t lastSlash = fileName.rfind("/") + 1; - return fileName.substr(lastSlash, fileName.rfind(".") - lastSlash); -} - -Path Map::findPath(const int startX, const int startY, - const int destX, const int destY, - const unsigned char walkmask, const int maxCost) -{ - // The basic walking cost of a tile. - static const int basicCost = 100; - const int basicCost2 = 100 * 362 / 256; - const float basicCostF = 100.0 * 362 / 256; - - // Path to be built up (empty by default) - Path path; - - if (startX >= mWidth || startY >= mHeight || startX < 0 || startY < 0) - return path; - - // Return when destination not walkable - if (!getWalk(destX, destY, walkmask)) - return path; - - // Reset starting tile's G cost to 0 - MetaTile *const startTile = &mMetaTiles[startX + startY * mWidth]; - if (!startTile) - return path; - - startTile->Gcost = 0; - - // Declare open list, a list with open tiles sorted on F cost - std::priority_queue openList; - - // Add the start point to the open list - openList.push(Location(startX, startY, startTile)); - - bool foundPath = false; - - // Keep trying new open tiles until no more tiles to try or target found - while (!openList.empty() && !foundPath) - { - // Take the location with the lowest F cost from the open list. - const Location curr = openList.top(); - openList.pop(); - - const MetaTile *const tile = curr.tile; - - // If the tile is already on the closed list, this means it has already - // been processed with a shorter path to the start point (lower G cost) - if (tile->whichList == mOnClosedList) - continue; - - // Put the current tile on the closed list - curr.tile->whichList = mOnClosedList; - - const int curWidth = curr.y * mWidth; - const int tileGcost = tile->Gcost; - - // Check the adjacent tiles - for (int dy = -1; dy <= 1; dy++) - { - const int y = curr.y + dy; - if (y < 0 || y >= mHeight) - continue; - - const int yWidth = y * mWidth; - const int dy1 = std::abs(y - destY); - - for (int dx = -1; dx <= 1; dx++) - { - // Calculate location of tile to check - const int x = curr.x + dx; - - // Skip if if we're checking the same tile we're leaving from, - // or if the new location falls outside of the map boundaries - if ((dx == 0 && dy == 0) || x < 0 || x >= mWidth) - continue; - - MetaTile *const newTile = &mMetaTiles[x + yWidth]; - - // Skip if the tile is on the closed list or is not walkable - // unless its the destination tile - // +++ here need check block must depend on player abilities. - if (newTile->whichList == mOnClosedList || - ((newTile->blockmask & walkmask) - && !(x == destX && y == destY)) - || (newTile->blockmask & BLOCKMASK_WALL)) - { - continue; - } - - // When taking a diagonal step, verify that we can skip the - // corner. - if (dx != 0 && dy != 0) - { - const MetaTile *const t1 = &mMetaTiles[curr.x + - (curr.y + dy) * mWidth]; - const MetaTile *const t2 = &mMetaTiles[curr.x + - dx + curWidth]; - - // +++ here need check block must depend - // on player abilities. - if (((t1->blockmask | t2->blockmask) & BLOCKMASK_WALL)) - continue; - } - - // Calculate G cost for this route, ~sqrt(2) for moving diagonal - int Gcost = tileGcost + (dx == 0 || dy == 0 - ? basicCost : basicCost2); - - /* Demote an arbitrary direction to speed pathfinding by - adding a defect (TODO: change depending on the desired - visual effect, e.g. a cross-product defect toward - destination). - Important: as long as the total defect along any path is - less than the basicCost, the pathfinder will still find one - of the shortest paths! */ - if (dx == 0 || dy == 0) - { - // Demote horizontal and vertical directions, so that two - // consecutive directions cannot have the same Fcost. - ++Gcost; - } - - // It costs extra to walk through a being (needs to be enough - // to make it more attractive to walk around). -// if (occupied(x, y)) -// { -// Gcost += 3 * basicCost; -// } - - // Skip if Gcost becomes too much - // Warning: probably not entirely accurate - if (maxCost > 0 && Gcost > maxCost * basicCost) - continue; - - if (newTile->whichList != mOnOpenList) - { - // Found a new tile (not on open nor on closed list) - - /* Update Hcost of the new tile. The pathfinder does not - work reliably if the heuristic cost is higher than the - real cost. In particular, using Manhattan distance is - forbidden here. */ - const int dx1 = std::abs(x - destX); - newTile->Hcost = std::abs(dx1 - dy1) * basicCost + - std::min(dx1, dy1) * (basicCostF); - - // Set the current tile as the parent of the new tile - newTile->parentX = curr.x; - newTile->parentY = curr.y; - - // Update Gcost and Fcost of new tile - newTile->Gcost = Gcost; - newTile->Fcost = Gcost + newTile->Hcost; - - if (x != destX || y != destY) - { - // Add this tile to the open list - newTile->whichList = mOnOpenList; - openList.push(Location(x, y, newTile)); - } - else - { - // Target location was found - foundPath = true; - } - } - else if (Gcost < newTile->Gcost) - { - // Found a shorter route. - // Update Gcost and Fcost of the new tile - newTile->Gcost = Gcost; - newTile->Fcost = Gcost + newTile->Hcost; - - // Set the current tile as the parent of the new tile - newTile->parentX = curr.x; - newTile->parentY = curr.y; - - // Add this tile to the open list (it's already - // there, but this instance has a lower F score) - openList.push(Location(x, y, newTile)); - } - } - } - } - - // Two new values to indicate whether a tile is on the open or closed list, - // this way we don't have to clear all the values between each pathfinding. - if (mOnOpenList > UINT_MAX - 2) - { - // We reset the list memebers value. - mOnClosedList = 1; - mOnOpenList = 2; - - // Clean up the metaTiles - const int size = mWidth * mHeight; - for (int i = 0; i < size; ++i) - mMetaTiles[i].whichList = 0; - } - else - { - mOnClosedList += 2; - mOnOpenList += 2; - } - - // If a path has been found, iterate backwards using the parent locations - // to extract it. - if (foundPath) - { - int pathX = destX; - int pathY = destY; - - while (pathX != startX || pathY != startY) - { - // Add the new path node to the start of the path list - path.push_front(Position(pathX, pathY)); - - // Find out the next parent - const MetaTile *const tile = &mMetaTiles[pathX + pathY * mWidth]; - pathX = tile->parentX; - pathY = tile->parentY; - } - } - - return path; -} - -void Map::addParticleEffect(const std::string &effectFile, - const int x, const int y, const int w, const int h) -{ - ParticleEffectData newEffect; - newEffect.file = effectFile; - newEffect.x = x; - newEffect.y = y; - newEffect.w = w; - newEffect.h = h; - mParticleEffects.push_back(newEffect); -} - -void Map::initializeParticleEffects(Particle *const engine) -{ - if (!engine) - return; - - if (config.getBoolValue("particleeffects")) - { - for (std::vector::const_iterator - i = mParticleEffects.begin(); - i != mParticleEffects.end(); ++i) - { - Particle *const p = engine->addEffect(i->file, i->x, i->y); - if (p && i->w > 0 && i->h > 0) - p->adjustEmitterSize(i->w, i->h); - } - } -} - -void Map::addExtraLayer() -{ - if (!mSpecialLayer) - { - logger->log1("No special layer"); - return; - } - const std::string mapFileName = getUserMapDirectory().append( - "/extralayer.txt"); - logger->log("loading extra layer: " + mapFileName); - struct stat statbuf; - if (!stat(mapFileName.c_str(), &statbuf) && S_ISREG(statbuf.st_mode)) - { - std::ifstream mapFile; - mapFile.open(mapFileName.c_str(), std::ios::in); - if (!mapFile.is_open()) - { - mapFile.close(); - return; - } - char line[201]; - - while (mapFile.getline(line, 200)) - { - std::string buf; - std::string str = line; - if (!str.empty()) - { - std::string x; - std::string y; - std::string type1; - std::string comment; - std::stringstream ss(str); - ss >> x; - ss >> y; - ss >> type1; - ss >> comment; - while (ss >> buf) - comment.append(" ").append(buf); - - const int type = atoi(type1.c_str()); - - if (comment.empty()) - { - if (type < MapItem::ARROW_UP - || type > MapItem::ARROW_RIGHT) - { - comment = "unknown"; - } - } - if (type == MapItem::PORTAL) - { - updatePortalTile(comment, type, atoi(x.c_str()), - atoi(y.c_str()), false); - } - else if (type == MapItem::HOME) - { - updatePortalTile(comment, type, atoi(x.c_str()), - atoi(y.c_str())); - } - else - { - addPortalTile(comment, type, atoi(x.c_str()), - atoi(y.c_str())); - } - } - } - mapFile.close(); - } -} - -void Map::saveExtraLayer() const -{ - if (!mSpecialLayer) - { - logger->log1("No special layer"); - return; - } - const std::string mapFileName = getUserMapDirectory().append( - "/extralayer.txt"); - logger->log("saving extra layer: " + mapFileName); - - if (mkdir_r(getUserMapDirectory().c_str())) - { - logger->log(strprintf("%s doesn't exist and can't be created! " - "Exiting.", getUserMapDirectory().c_str())); - return; - } - - std::ofstream mapFile; - mapFile.open(mapFileName.c_str(), std::ios::binary); - if (!mapFile.is_open()) - { - logger->log1("Unable to open extralayer.txt for writing"); - return; - } - - const int width = mSpecialLayer->mWidth; - const int height = mSpecialLayer->mHeight; - - for (int x = 0; x < width; x ++) - { - for (int y = 0; y < height; y ++) - { - const MapItem *const item = mSpecialLayer->getTile(x, y); - if (item && item->mType != MapItem::EMPTY - && item->mType != MapItem::HOME) - { - mapFile << x << " " << y << " " - << static_cast(item->mType) << " " - << item->mComment << std::endl; - } - } - } - mapFile.close(); -} - -std::string Map::getUserMapDirectory() const -{ - return client->getServerConfigDirectory() + - dirSeparator + getProperty("_realfilename"); -} - -void Map::addRange(const std::string &name, const int type, - const int x, const int y, const int dx, const int dy) -{ - if (!mObjects) - return; - - mObjects->addObject(name, type, x / mapTileSize, y / mapTileSize, - dx / mapTileSize, dy / mapTileSize); -} - -void Map::addPortal(const std::string &name, const int type, - const int x, const int y, const int dx, const int dy) -{ - addPortalTile(name, type, (x / mapTileSize) + (dx / mapTileSize / 2), - (y / mapTileSize) + (dy / mapTileSize / 2)); -} - -void Map::addPortalTile(const std::string &name, const int type, - const int x, const int y) -{ - if (mSpecialLayer) - mSpecialLayer->setTile(x, y, new MapItem(type, name, x, y)); - - mMapPortals.push_back(new MapItem(type, name, x, y)); -} - -void Map::updatePortalTile(const std::string &name, const int type, - const int x, const int y, const bool addNew) -{ - MapItem *item = findPortalXY(x, y); - if (item) - { - item->mComment = name; - item->setType(type); - item->mX = x; - item->mY = y; - if (mSpecialLayer) - { - item = new MapItem(type, name, x, y); - mSpecialLayer->setTile(x, y, item); - } - } - else if (addNew) - { - addPortalTile(name, type, x, y); - } -} - -MapItem *Map::findPortalXY(const int x, const int y) const -{ - FOR_EACH (std::vector::const_iterator, it, mMapPortals) - { - if (!*it) - continue; - - MapItem *const item = *it; - if (item->mX == x && item->mY == y) - return item; - } - return nullptr; -} - -const TileAnimation *Map::getAnimationForGid(const int gid) const -{ - if (mTileAnimations.empty()) - return nullptr; - - TileAnimationMapCIter i = mTileAnimations.find(gid); - return (i == mTileAnimations.end()) ? nullptr : i->second; -} - -void Map::setPvpMode(const int mode) -{ - const int oldMode = mPvp; - - if (!mode) - mPvp = 0; - else - mPvp |= mode; - - if (mPvp != oldMode && player_node) - { - switch (mPvp) - { - case 0: - NotifyManager::notify(NotifyManager::PVP_OFF_GVG_OFF); - break; - case 1: - NotifyManager::notify(NotifyManager::PVP_ON); - break; - case 2: - NotifyManager::notify(NotifyManager::GVG_ON); - break; - case 3: - NotifyManager::notify(NotifyManager::PVP_ON_GVG_ON); - break; - default: - NotifyManager::notify(NotifyManager::PVP_UNKNOWN); - break; - } - } -} - -std::string Map::getObjectData(const unsigned x, const unsigned y, - const int type) const -{ - if (!mObjects) - return ""; - - MapObjectList *const list = mObjects->getAt(x, y); - if (!list) - return ""; - - std::vector::const_iterator it = list->objects.begin(); - const std::vector::const_iterator it_end = list->objects.end(); - while (it != it_end) - { - if ((*it).type == type) - return (*it).data; - ++ it; - } - - return ""; -} - -void Map::indexTilesets() -{ - if (mTilesetsIndexed) - return; - - mTilesetsIndexed = true; - - const Tileset *s = nullptr; - size_t sSz = 0; - FOR_EACH (Tilesets::const_iterator, it, mTilesets) - { - const size_t sz = (*it)->size(); - if (!s || static_cast(s->getFirstGid()) + sSz - < static_cast((*it)->getFirstGid()) + sz) - { - s = *it; - sSz = sz; - } - } - if (!s) - { - mIndexedTilesetsSize = 0; - mIndexedTilesets = nullptr; - return; - } - - const int size = static_cast(s->getFirstGid()) - + static_cast(s->size()); - mIndexedTilesetsSize = size; - mIndexedTilesets = new Tileset*[static_cast(size)]; - std::fill_n(mIndexedTilesets, size, static_cast(nullptr)); - - FOR_EACH (Tilesets::const_iterator, it, mTilesets) - { - Tileset *const s2 = *it; - if (s2) - { - const int start = s2->getFirstGid(); - const int end = start + static_cast(s2->size()); - for (int f = start; f < end; f ++) - { - if (f < size) - mIndexedTilesets[f] = s2; - } - } - } -} - -void Map::clearIndexedTilesets() -{ - if (!mTilesetsIndexed) - return; - - mTilesetsIndexed = false; - delete [] mIndexedTilesets; - mIndexedTilesetsSize = 0; -} - -void Map::reduce() -{ -#ifdef USE_SDL2 - return; -#else - if (!mFringeLayer || mOpenGL != RENDER_SOFTWARE || - !config.getBoolValue("enableMapReduce")) - { - return; - } - - int cnt = 0; - for (int x = 0; x < mWidth; x ++) - { - for (int y = 0; y < mHeight; y ++) - { - bool correct(true); - bool dontHaveAlpha(false); - - FOR_EACH (LayersCIter, layeri, mLayers) - { - const MapLayer *const layer = *layeri; - if (x >= layer->mWidth || y >= layer->mHeight) - continue; - - Image *const img = layer->mTiles[x + y * layer->mWidth]; - if (img) - { - if (img->hasAlphaChannel() && img->isAlphaCalculated()) - { - if (!img->isAlphaVisible()) - { - dontHaveAlpha = true; - img->setAlphaVisible(false); - } - } - else if (img->mBounds.w > mapTileSize - || img->mBounds.h > mapTileSize) - { - correct = false; - img->setAlphaVisible(true); - break; - } - else if (!img->isHasAlphaChannel()) - { - dontHaveAlpha = true; - img->setAlphaVisible(false); - } - else if (img->hasAlphaChannel()) - { - const uint8_t *const arr = img->SDLgetAlphaChannel(); - if (!arr) - continue; - - bool bad(false); - bool stop(false); - int width; - const SubImage *const subImg - = dynamic_cast(img); - if (subImg) - width = subImg->mInternalBounds.w; - else - width = img->mBounds.w; - - for (int f = img->mBounds.x; - f < img->mBounds.x + img->mBounds.w; f ++) - { - for (int d = img->mBounds.y; - d < img->mBounds.y + img->mBounds.h; d ++) - { - const uint8_t chan = arr[f + d * width]; - if (chan != 255) - { - bad = true; - stop = true; - break; - } - } - if (stop) - break; - } - if (!bad) - { - dontHaveAlpha = true; - img->setAlphaVisible(false); - } - else - { - img->setAlphaVisible(true); - } - } - img->setAlphaCalculated(true); - } - } - if (!correct || !dontHaveAlpha) - continue; - - Layers::reverse_iterator ri = mLayers.rbegin(); - while (ri != mLayers.rend()) - { - const MapLayer *const layer = *ri; - if (x >= layer->mWidth || y >= layer->mHeight) - { - ++ ri; - continue; - } - - const Image *img = layer->mTiles[x + y * layer->mWidth]; - if (img && !img->isAlphaVisible()) - { // removing all down tiles - ++ ri; - while (ri != mLayers.rend()) - { - MapLayer *const layer2 = *ri; - const size_t pos = static_cast( - x + y * layer2->mWidth); - img = layer2->mTiles[pos]; - if (img) - { - layer2->mTiles[pos] = nullptr; - cnt ++; - } - ++ ri; - } - break; - } - ++ ri; - } - } - } - logger->log("tiles reduced: %d", cnt); -#endif -} - -void Map::redrawMap() -{ - mRedrawMap = true; -} - -void Map::addHeights(MapHeights *const heights) -{ - delete mHeights; - mHeights = heights; -} - -uint8_t Map::getHeightOffset(const int x, const int y) const -{ - if (!mHeights) - return 0; - return mHeights->getHeight(x, y); -} - -void Map::setMask(const int mask) -{ - if (mask != mMask) - mRedrawMap = true; - mMask = mask; -} - -void Map::setMusicFile(const std::string &file) -{ - setProperty("music", file); -} diff --git a/src/map.h b/src/map.h deleted file mode 100644 index 0ad048e7e..000000000 --- a/src/map.h +++ /dev/null @@ -1,539 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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 MAP_H -#define MAP_H - -#include "position.h" -#include "properties.h" - -#include "being/actor.h" - -#include "listeners/configlistener.h" - -#include "render/renderers.h" - -#include -#include - -class Animation; -class AmbientLayer; -class Image; -class MapHeights; -class MapItem; -class MapLayer; -class ObjectsLayer; -class Particle; -class Resource; -class SimpleAnimation; -class SpecialLayer; -class Tileset; -class WalkLayer; - -typedef std::vector Tilesets; -typedef std::vector Layers; -typedef Layers::const_iterator LayersCIter; - -typedef std::vector > TilePairVector; -typedef TilePairVector::const_iterator TilePairVectorCIter; - -typedef std::vector AmbientLayerVector; -typedef AmbientLayerVector::const_iterator AmbientLayerVectorCIter; -typedef AmbientLayerVector::iterator AmbientLayerVectorIter; - -static const int mapTileSize = 32; - -/** - * A meta tile stores additional information about a location on a tile map. - * This is information that doesn't need to be repeated for each tile in each - * layer of the map. - */ -struct MetaTile final -{ - /** - * Constructor. - */ - MetaTile() : Fcost(0), Gcost(0), Hcost(0), whichList(0), - parentX(0), parentY(0), blockmask(0) - {} - - A_DELETE_COPY(MetaTile) - - // Pathfinding members - int Fcost; /**< Estimation of total path cost */ - int Gcost; /**< Cost from start to this location */ - int Hcost; /**< Estimated cost to goal */ - unsigned whichList; /**< No list, open list or closed list */ - int parentX; /**< X coordinate of parent tile */ - int parentY; /**< Y coordinate of parent tile */ - unsigned char blockmask; /**< Blocking properties of this tile */ -}; - -/** - * Animation cycle of a tile image which changes the map accordingly. - */ -class TileAnimation final -{ - public: - explicit TileAnimation(Animation *const ani); - - ~TileAnimation(); - - A_DELETE_COPY(TileAnimation) - - bool update(const int ticks = 1); - - void addAffectedTile(MapLayer *const layer, const int index) - { mAffected.push_back(std::make_pair(layer, index)); } - - private: - TilePairVector mAffected; - SimpleAnimation *mAnimation; - Image *mLastImage; -}; - -typedef std::map TileAnimationMap; -typedef TileAnimationMap::const_iterator TileAnimationMapCIter; - -/** - * A tile map. - */ -class Map final : public Properties, public ConfigListener -{ - public: - enum BlockType - { - BLOCKTYPE_NONE = -1, - BLOCKTYPE_WALL, - BLOCKTYPE_CHARACTER, - BLOCKTYPE_MONSTER, - BLOCKTYPE_AIR, - BLOCKTYPE_WATER, - BLOCKTYPE_GROUND, - BLOCKTYPE_GROUNDTOP, - NB_BLOCKTYPES - }; - - enum CollisionTypes - { - COLLISION_EMPTY = 0, // no collision - COLLISION_WALL = 1, // full collison - COLLISION_AIR = 2, // air units can walk - COLLISION_WATER = 3, // water units can walk - COLLISION_GROUNDTOP = 4, // no collision (chair, bed, etc) - COLLISION_MAX = 5 // count index - }; - - enum BlockMask - { - BLOCKMASK_WALL = 0x80, // 1000 0000 - BLOCKMASK_CHARACTER = 0x01, // 0000 0001 - BLOCKMASK_MONSTER = 0x02, // 0000 0010 - BLOCKMASK_AIR = 0x04, // 0000 0100 - BLOCKMASK_WATER = 0x08, // 0000 1000 - BLOCKMASK_GROUND = 0x10, // 0001 0000 - BLOCKMASK_GROUNDTOP = 0x20 // 0010 0000 - }; - - enum DebugType - { - MAP_NORMAL = 0, - MAP_DEBUG = 1, - MAP_SPECIAL = 2, - MAP_SPECIAL2 = 3, - MAP_SPECIAL3 = 4, - MAP_BLACKWHITE = 5 - }; - - /** - * Constructor, taking map and tile size as parameters. - */ - Map(const int width, const int height, - const int tileWidth, const int tileHeight); - - A_DELETE_COPY(Map) - - /** - * Destructor. - */ - ~Map(); - - /** - * Initialize ambient layers. Has to be called after all the properties - * are set. - */ - void initializeAmbientLayers(); - - /** - * Updates animations. Called as needed. - */ - void update(const int ticks = 1); - - /** - * Draws the map to the given graphics output. This method draws all - * layers, actors and overlay effects. - * - * TODO: For efficiency reasons, this method could take into account - * the clipping rectangle set on the Graphics object. However, - * currently the map is always drawn full-screen. - */ - void draw(Graphics *const graphics, int scrollX, int scrollY); - - /** - * Visualizes collision layer for debugging - */ - void drawCollision(Graphics *const graphics, - const int scrollX, const int scrollY, - const int debugFlags) const; - - /** - * Adds a layer to this map. The map takes ownership of the layer. - */ - void addLayer(MapLayer *const layer); - - /** - * Adds a tileset to this map. The map takes ownership of the tileset. - */ - void addTileset(Tileset *const tileset); - - /** - * Finds the tile set that a tile with the given global id is part of. - */ - const Tileset *getTilesetWithGid(const int gid) const A_WARN_UNUSED; - - /** - * Get tile reference. - */ - const MetaTile *getMetaTile(const int x, - const int y) const A_WARN_UNUSED; - - /** - * Marks a tile as occupied. - */ - void blockTile(const int x, const int y, const BlockType type); - - /** - * Gets walkability for a tile with a blocking bitmask. When called - * without walkmask, only blocks against colliding tiles. - */ - bool getWalk(const int x, const int y, - const unsigned char walkmask = BLOCKMASK_WALL - | BLOCKMASK_AIR | BLOCKMASK_WATER) const A_WARN_UNUSED; - - void setWalk(const int x, const int y, const bool walkable); - - unsigned char getBlockMask(const int x, const int y) const; - - /** - * Returns the width of this map in tiles. - */ - int getWidth() const A_WARN_UNUSED - { return mWidth; } - - /** - * Returns the height of this map in tiles. - */ - int getHeight() const A_WARN_UNUSED - { return mHeight; } - - /** - * Returns the tile width of this map. - */ - int getTileWidth() const A_WARN_UNUSED - { return mTileWidth; } - - /** - * Returns the tile height used by this map. - */ - int getTileHeight() const A_WARN_UNUSED - { return mTileHeight; } - - const std::string getMusicFile() const A_WARN_UNUSED; - - void setMusicFile(const std::string &file); - - const std::string getName() const A_WARN_UNUSED; - - /** - * Gives the map id based on filepath (ex: 009-1) - */ - const std::string getFilename() const A_WARN_UNUSED; - - /** - * Find a path from one location to the next. - */ - Path findPath(const int startX, const int startY, - const int destX, const int destY, - const unsigned char walkmask, - const int maxCost = 20) A_WARN_UNUSED; - - /** - * Adds a particle effect - */ - void addParticleEffect(const std::string &effectFile, - const int x, const int y, - const int w = 0, const int h = 0); - - /** - * Initializes all added particle effects - */ - void initializeParticleEffects(Particle *const particleEngine); - - /** - * Adds a tile animation to the map - */ - void addAnimation(const int gid, TileAnimation *const animation) - { mTileAnimations[gid] = animation; } - - void setDebugFlags(const int n) - { mDebugFlags = n; } - - int getDebugFlags() const A_WARN_UNUSED - { return mDebugFlags; } - - void addExtraLayer(); - - void saveExtraLayer() const; - - SpecialLayer *getTempLayer() const A_WARN_UNUSED - { return mTempLayer; } - - SpecialLayer *getSpecialLayer() const A_WARN_UNUSED - { return mSpecialLayer; } - - void setHasWarps(const bool n) - { mHasWarps = n; } - - bool getHasWarps() const A_WARN_UNUSED - { return mHasWarps; } - - std::string getUserMapDirectory() const A_WARN_UNUSED; - - void addPortal(const std::string &name, const int type, - const int x, const int y, const int dx, const int dy); - - void addRange(const std::string &name, const int type, - const int x, const int y, const int dx, const int dy); - - void addPortalTile(const std::string &name, const int type, - const int x, const int y); - - void updatePortalTile(const std::string &name, const int type, - const int x, const int y, - const bool addNew = true); - - const std::vector &getPortals() const A_WARN_UNUSED - { return mMapPortals; } - - /** - * Gets the tile animation for a specific gid - */ - const TileAnimation *getAnimationForGid(const int gid) - const A_WARN_UNUSED; - - void optionChanged(const std::string &value) override final; - - MapItem *findPortalXY(const int x, const int y) const A_WARN_UNUSED; - - int getActorsCount() const A_WARN_UNUSED - { return static_cast(mActors.size()); } - - void setPvpMode(const int mode); - - const ObjectsLayer* getObjectsLayer() const A_WARN_UNUSED - { return mObjects; } - - std::string getObjectData(const unsigned x, const unsigned y, - const int type) const A_WARN_UNUSED; - - void indexTilesets(); - - void clearIndexedTilesets(); - - void setActorsFix(const int x, const int y) - { mActorFixX = x; mActorFixY = y; } - - int getVersion() const A_WARN_UNUSED - { return mVersion; } - - void setVersion(const int n) - { mVersion = n; } - - void reduce(); - - void redrawMap(); - - bool empty() const A_WARN_UNUSED - { return mLayers.empty(); } - - void setCustom(const bool b) - { mCustom = b; } - - bool isCustom() const A_WARN_UNUSED - { return mCustom; } - - const std::map &getTileAnimations() - const A_WARN_UNUSED - { return mTileAnimations; } - - void setAtlas(Resource *const atlas) - { mAtlas = atlas; } - - const MetaTile *getMetaTiles() const - { return mMetaTiles; } - - WalkLayer *getWalkLayer() - { return mWalkLayer; } - - void setWalkLayer(WalkLayer *const layer) - { mWalkLayer = layer; } - - void addHeights(MapHeights *const heights); - - uint8_t getHeightOffset(const int x, const int y) const; - - void setMask(const int mask); - - protected: - friend class Actor; - friend class Minimap; - - /** - * Adds an actor to the map. - */ - Actors::iterator addActor(Actor *const actor); - - /** - * Removes an actor from the map. - */ - void removeActor(const Actors::iterator &iterator); - - private: - enum LayerType - { - FOREGROUND_LAYERS = 0, - BACKGROUND_LAYERS - }; - - /** - * Updates scrolling of ambient layers. Has to be called each game tick. - */ - void updateAmbientLayers(const float scrollX, const float scrollY); - - /** - * Draws the foreground or background layers to the given graphics output. - */ - void drawAmbientLayers(Graphics *const graphics, const LayerType type, - const int detail); - - /** - * Tells whether the given coordinates fall within the map boundaries. - */ - bool contains(const int x, const int y) const A_WARN_UNUSED; - - /** - * Blockmasks for different entities - */ - unsigned *mOccupation[NB_BLOCKTYPES]; - - int mWidth; - int mHeight; - int mTileWidth, mTileHeight; - int mMaxTileHeight; - MetaTile *mMetaTiles; - WalkLayer *mWalkLayer; - Layers mLayers; - Tilesets mTilesets; - Actors mActors; - bool mHasWarps; - - // debug flags - int mDebugFlags; - - // Pathfinding members - unsigned int mOnClosedList; - unsigned int mOnOpenList; - - // Overlay data - AmbientLayerVector mBackgrounds; - AmbientLayerVector mForegrounds; - float mLastAScrollX; - float mLastAScrollY; - - // Particle effect data - struct ParticleEffectData - { - ParticleEffectData() : - file(), - x(0), - y(0), - w(0), - h(0) - { - } - - std::string file; - int x; - int y; - int w; - int h; - }; - std::vector mParticleEffects; - - std::vector mMapPortals; - - std::map mTileAnimations; - - int mOverlayDetail; - float mOpacity; - RenderType mOpenGL; - int mPvp; - bool mTilesetsIndexed; - Tileset** mIndexedTilesets; - int mIndexedTilesetsSize; - int mActorFixX; - int mActorFixY; - int mVersion; - - SpecialLayer *mSpecialLayer; - SpecialLayer *mTempLayer; - ObjectsLayer *mObjects; - MapLayer *mFringeLayer; - - int mLastX; - int mLastY; - int mLastScrollX; - int mLastScrollY; - - int mDrawX; - int mDrawY; - int mDrawScrollX; - int mDrawScrollY; - int mMask; - Resource *mAtlas; - MapHeights *mHeights; - bool mRedrawMap; - bool mBeingOpacity; - bool mCustom; -}; - -#endif // MAP_H diff --git a/src/mapheights.cpp b/src/mapheights.cpp deleted file mode 100644 index 06d71a38a..000000000 --- a/src/mapheights.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2014 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 "mapheights.h" - -#include "debug.h" - -MapHeights::MapHeights(const int width, const int height) : - mWidth(width), - mHeight(height), - mTiles(new uint8_t[mWidth * mHeight]) -{ - memset(mTiles, 0, mWidth * mHeight); -} - -MapHeights::~MapHeights() -{ - delete [] mTiles; -} - -void MapHeights::setHeight(const int x, const int y, const uint8_t height) -{ - mTiles[x + y * mWidth] = height; -} diff --git a/src/mapheights.h b/src/mapheights.h deleted file mode 100644 index a674d2334..000000000 --- a/src/mapheights.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2014 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 MAPHEIGHTS_H -#define MAPHEIGHTS_H - -#include "localconsts.h" - -class MapHeights final -{ - public: - friend class Map; - - MapHeights(const int width, const int height); - - A_DELETE_COPY(MapHeights) - - ~MapHeights(); - - void setHeight(const int x, const int y, const uint8_t height); - - uint8_t getHeight(const int x, const int y) const - { return mTiles[x + y * mWidth]; } - - private: - int mWidth; - int mHeight; - uint8_t *mTiles; -}; - -#endif // MAPHEIGHTS_H diff --git a/src/maplayer.cpp b/src/maplayer.cpp deleted file mode 100644 index 97ecc4f93..000000000 --- a/src/maplayer.cpp +++ /dev/null @@ -1,892 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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" - -#ifndef USE_OPENGL -#include "render/graphics.h" -#endif - -#include "being/localplayer.h" - -#include "render/graphics.h" - -#include "resources/image.h" -#include "resources/resourcemanager.h" - -#include "gui/font.h" -#include "gui/gui.h" - -#include "utils/delete2.h" -#include "utils/dtor.h" - -#include "debug.h" - -MapLayer::MapLayer(const int x, const int y, const int width, const int height, - const bool fringeLayer, const int mask): - mX(x), - mY(y), - mWidth(width), - mHeight(height), - mTiles(new Image*[mWidth * mHeight]), - mSpecialLayer(nullptr), - mTempLayer(nullptr), - mTempRows(), - mMask(mask), - mIsFringeLayer(fringeLayer), - mHighlightAttackRange(config.getBoolValue("highlightAttackRange")) -{ - std::fill_n(mTiles, mWidth * mHeight, static_cast(nullptr)); - - config.addListener("highlightAttackRange", this); -} - -MapLayer::~MapLayer() -{ - config.removeListener("highlightAttackRange", this); - CHECKLISTENERS - delete [] mTiles; - delete_all(mTempRows); - mTempRows.clear(); -} - -void MapLayer::optionChanged(const std::string &value) -{ - if (value == "highlightAttackRange") - { - mHighlightAttackRange = - config.getBoolValue("highlightAttackRange"); - } -} - -void MapLayer::setTile(const int x, const int y, Image *const img) -{ - mTiles[x + y * mWidth] = img; -} - -void MapLayer::draw(Graphics *const graphics, - int startX, int startY, int endX, int endY, - const int scrollX, const int scrollY, - const int debugFlags) const -{ - if (!player_node) - return; - - BLOCK_START("MapLayer::draw") - 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 * mapTileSize) - scrollX; - const int dy = (mY * mapTileSize) - scrollY + mapTileSize; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - for (int y = startY; y < endY; y++) - { - const int y32 = y * mapTileSize; - const int yWidth = y * mWidth; - - const int py0 = y32 + dy; - - Image **tilePtr = mTiles + static_cast(startX + yWidth); - - for (int x = startX; x < endX; x++, tilePtr++) - { - const int x32 = x * mapTileSize; - - int c = 0; - const Image *const img = *tilePtr; - if (img) - { - const int px = x32 + dx; - const int py = py0 - img->mBounds.h; - if (flag || img->mBounds.h <= mapTileSize) - { - 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->drawPattern(img, px, py, - width, img->mBounds.h); - } - } - } - - x += c; - } - } - BLOCK_END("MapLayer::draw") -} - -void MapLayer::drawSDL(Graphics *const graphics) -{ - BLOCK_START("MapLayer::drawSDL") - MapRows::const_iterator rit = mTempRows.begin(); - const MapRows::const_iterator rit_end = mTempRows.end(); - while (rit != rit_end) - { - MepRowImages *const images = &(*rit)->images; - MepRowImages::const_iterator iit = images->begin(); - const MepRowImages::const_iterator iit_end = images->end(); - while (iit != iit_end) - { - graphics->drawTileVertexes(*iit); - ++ iit; - } - ++ rit; - } - BLOCK_END("MapLayer::drawSDL") -} - -#ifdef USE_OPENGL -void MapLayer::updateSDL(const Graphics *const graphics, - int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const int debugFlags) -{ - BLOCK_START("MapLayer::updateSDL") - 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 * mapTileSize) - scrollX; - const int dy = (mY * mapTileSize) - scrollY + mapTileSize; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - for (int y = startY; y < endY; y++) - { - MapRowVertexes *const row = new MapRowVertexes(); - mTempRows.push_back(row); - - const Image *lastImage = nullptr; - ImageVertexes *imgVert = nullptr; - - const int yWidth = y * mWidth; - const int py0 = y * mapTileSize + dy; - Image **tilePtr = mTiles + static_cast(startX + yWidth); - - for (int x = startX; x < endX; x++, tilePtr++) - { - Image *const img = *tilePtr; - if (img) - { - const int px = x * mapTileSize + dx; - const int py = py0 - img->mBounds.h; - if (flag || img->mBounds.h <= mapTileSize) - { - if (lastImage != img) - { - imgVert = new ImageVertexes(); - imgVert->image = img; - row->images.push_back(imgVert); - lastImage = img; - } - graphics->calcTileSDL(imgVert, px, py); - } - } - } - } - BLOCK_END("MapLayer::updateSDL") -} - -void MapLayer::updateOGL(const Graphics *const graphics, - int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const int debugFlags) -{ - BLOCK_START("MapLayer::updateOGL") - 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 * mapTileSize) - scrollX; - const int dy = (mY * mapTileSize) - scrollY + mapTileSize; - const bool flag = (debugFlags != Map::MAP_SPECIAL - && debugFlags != Map::MAP_SPECIAL2); - - MapRowVertexes *const row = new MapRowVertexes(); - mTempRows.push_back(row); - Image *lastImage = nullptr; - ImageVertexes *imgVert = nullptr; - std::map imgSet; - - for (int y = startY; y < endY; y++) - { - const int yWidth = y * mWidth; - const int py0 = y * mapTileSize + dy; - Image **tilePtr = mTiles + static_cast(startX + yWidth); - for (int x = startX; x < endX; x++, tilePtr++) - { - Image *const img = *tilePtr; - if (img) - { - const int px = x * mapTileSize + dx; - const int py = py0 - img->mBounds.h; - const GLuint imgGlImage = img->mGLImage; - if (flag || img->mBounds.h <= mapTileSize) - { - if (!lastImage || lastImage->mGLImage != imgGlImage) - { - if (img->mBounds.w > mapTileSize) - imgSet.clear(); - - if (imgSet.find(imgGlImage) != imgSet.end()) - { - imgVert = imgSet[imgGlImage]; - } - else - { - if (lastImage) - imgSet[lastImage->mGLImage] = imgVert; - imgVert = new ImageVertexes(); - imgVert->ogl.init(); - imgVert->image = img; - row->images.push_back(imgVert); - } - } - lastImage = img; -// if (imgVert->image->mGLImage != lastImage->mGLImage) -// logger->log("wrong image draw"); - graphics->calcTileVertexes(imgVert, lastImage, px, py); - } - } - } - } - BLOCK_END("MapLayer::updateOGL") -} - -void MapLayer::drawOGL(Graphics *const graphics) -{ - BLOCK_START("MapLayer::drawOGL") - MapRows::const_iterator rit = mTempRows.begin(); - const MapRows::const_iterator rit_end = mTempRows.end(); -// int k = 0; - while (rit != rit_end) - { - const MepRowImages *const images = &(*rit)->images; - MepRowImages::const_iterator iit = images->begin(); - const MepRowImages::const_iterator iit_end = images->end(); - while (iit != iit_end) - { - graphics->drawTileVertexes(*iit); - ++ iit; -// k ++; - } - ++ rit; - } - BLOCK_END("MapLayer::drawOGL") -// logger->log("draws: %d", k); -} -#endif - -void MapLayer::drawFringe(Graphics *const graphics, int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const Actors *const actors, - const int debugFlags, const int yFix) const -{ - BLOCK_START("MapLayer::drawFringe") - if (!player_node || !mSpecialLayer || !mTempLayer) - { - BLOCK_END("MapLayer::drawFringe") - 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; - - ActorsCIter ai = actors->begin(); - const ActorsCIter ai_end = actors->end(); - - const int dx = (mX * mapTileSize) - scrollX; - const int dy = (mY * mapTileSize) - scrollY + mapTileSize; - - const int specialWidth = mSpecialLayer->mWidth; - const int specialHeight = mSpecialLayer->mHeight; - - for (int y = startY; y < endY; y++) - { - const int y32 = y * mapTileSize; - const int y32s = (y + yFix) * mapTileSize; - const int yWidth = y * mWidth; - - BLOCK_START("MapLayer::drawFringe drawmobs") - // If drawing the fringe layer, make sure all actors above this row of - // tiles have been drawn - while (ai != ai_end && (*ai)->getSortPixelY() <= y32s) - { - (*ai)->draw(graphics, -scrollX, -scrollY); - ++ ai; - } - BLOCK_END("MapLayer::drawFringe drawmobs") - - if (debugFlags == Map::MAP_SPECIAL3 - || debugFlags == Map::MAP_BLACKWHITE) - { - if (y < specialHeight) - { - const 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 * mapTileSize - scrollX; - - const MapItem *item = mSpecialLayer->mTiles[ptr + x]; - if (item) - { - item->draw(graphics, px1, py1, - mapTileSize, mapTileSize); - } - - item = mTempLayer->mTiles[ptr + x]; - if (item) - { - item->draw(graphics, px1, py1, - mapTileSize, mapTileSize); - } - } - } - } - else - { - const int py0 = y32 + dy; - const int py1 = y32 - scrollY; - - Image **tilePtr = mTiles + static_cast(startX + yWidth); - for (int x = startX; x < endX; x++, tilePtr++) - { - const int x32 = x * mapTileSize; - - const int px1 = x32 - scrollX; - int c = 0; - const Image *const 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 <= mapTileSize) - { - 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->drawPattern(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; - - const int ptr = y * specialWidth + x; - - for (int x1 = 0; x1 < c1 + 1; x1 ++) - { - const MapItem *const item1 - = mSpecialLayer->mTiles[ptr + x1]; - const MapItem *const item2 - = mTempLayer->mTiles[ptr + x1]; - if (item1 || item2) - { - const int px2 = px1 + (x1 * mapTileSize); - if (item1 && item1->mType != MapItem::EMPTY) - { - item1->draw(graphics, px2, py1, - mapTileSize, mapTileSize); - } - - if (item2 && item2->mType != MapItem::EMPTY) - { - item2->draw(graphics, px2, py1, - mapTileSize, mapTileSize); - } - } - } - } - x += c; - } - } - } - - // Draw any remaining actors - if (debugFlags != Map::MAP_SPECIAL3) - { - BLOCK_START("MapLayer::drawFringe drawmobs") - while (ai != ai_end) - { - (*ai)->draw(graphics, -scrollX, -scrollY); - ++ai; - } - BLOCK_END("MapLayer::drawFringe drawmobs") - if (mHighlightAttackRange && player_node) - { - const int px = player_node->getPixelX() - - scrollX - mapTileSize / 2; - const int py = player_node->getPixelY() - scrollY - mapTileSize; - const int attackRange = player_node->getAttackRange() - * mapTileSize; - - int x = px - attackRange; - int y = py - attackRange; - int w = 2 * attackRange + mapTileSize; - int h = w; - if (attackRange <= mapTileSize) - { - x -= mapTileSize / 2; - y -= mapTileSize / 2; - w += mapTileSize; - h += mapTileSize; - } - - if (userPalette) - { - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ATTACK_RANGE)); - graphics->fillRectangle(Rect(x, y, w, h)); - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ATTACK_RANGE_BORDER)); - graphics->drawRectangle(Rect(x, y, w, h)); - } - } - } - BLOCK_END("MapLayer::drawFringe") -} - -int MapLayer::getTileDrawWidth(const Image *img, - const int endX, - int &width) -{ - BLOCK_START("MapLayer::getTileDrawWidth") - const Image *const img1 = img; - int c = 0; - if (!img1) - { - width = 0; - BLOCK_END("MapLayer::getTileDrawWidth") - 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; - } - BLOCK_END("MapLayer::getTileDrawWidth") - return c; -} - -SpecialLayer::SpecialLayer(const int width, const int height) : - mWidth(width), - mHeight(height), - mTiles(new MapItem*[mWidth * mHeight]) -{ - std::fill_n(mTiles, mWidth * mHeight, static_cast(nullptr)); -} - -SpecialLayer::~SpecialLayer() -{ - for (int f = 0; f < mWidth * mHeight; f ++) - delete2(mTiles[f]) - delete [] mTiles; -} - -MapItem* SpecialLayer::getTile(const int x, const int y) const -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return nullptr; - } - return mTiles[x + y * mWidth]; -} - -void SpecialLayer::setTile(const int x, const int y, MapItem *const item) -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return; - } - - const int idx = x + y * mWidth; - delete mTiles[idx]; - if (item) - item->setPos(x, y); - mTiles[idx] = item; -} - -void SpecialLayer::setTile(const int x, const int y, const int type) -{ - if (x < 0 || x >= mWidth || - y < 0 || y >= mHeight) - { - return; - } - - const int idx = x + y * mWidth; - MapItem *const tile = mTiles[idx]; - if (tile) - { - tile->setType(type); - tile->setPos(x, y); - } - else - { - mTiles[idx] = new MapItem(type); - mTiles[idx]->setPos(x, y); - } -} - -void SpecialLayer::addRoad(const Path &road) -{ - FOR_EACH (Path::const_iterator, i, road) - { - const Position &pos = (*i); - MapItem *const item = getTile(pos.x, pos.y); - if (!item) - setTile(pos.x, pos.y, new MapItem(MapItem::ROAD)); - else - item->setType(MapItem::ROAD); - } -} - -void SpecialLayer::clean() const -{ - if (!mTiles) - return; - - for (int f = 0; f < mWidth * mHeight; f ++) - { - MapItem *const item = mTiles[f]; - if (item) - item->setType(MapItem::EMPTY); - } -} - -void SpecialLayer::draw(Graphics *const graphics, int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY) const -{ - BLOCK_START("SpecialLayer::draw") - 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 ++) - { - const int py = y * mapTileSize - scrollY; - const int y2 = y * mWidth; - for (int x = startX; x < endX; x ++) - { - const MapItem *const item = mTiles[x + y2]; - if (item) - { - item->draw(graphics, x * mapTileSize - scrollX, py, - mapTileSize, mapTileSize); - } - } - } - BLOCK_END("SpecialLayer::draw") -} - -MapItem::MapItem(): - mImage(nullptr), - mComment(), - mName(), - mType(EMPTY), - mX(-1), - mY(-1) -{ - setType(EMPTY); -} - -MapItem::MapItem(const int type): - mImage(nullptr), - mComment(), - mName(), - mType(type), - mX(-1), - mY(-1) -{ - setType(type); -} - -MapItem::MapItem(const int type, std::string comment): - mImage(nullptr), - mComment(comment), - mName(), - mType(type), - mX(-1), - mY(-1) -{ - setType(type); -} - -MapItem::MapItem(const int type, std::string comment, - const int x, const int y): - mImage(nullptr), - mComment(comment), - mName(), - mType(type), - mX(x), - mY(y) -{ - setType(type); -} - -MapItem::~MapItem() -{ - if (mImage) - { - mImage->decRef(); - mImage = nullptr; - } -} - -void MapItem::setType(const int type) -{ - std::string name; - mType = type; - if (mImage) - mImage->decRef(); - - switch (type) - { - case ARROW_UP: - name = "graphics/sprites/arrow_up.png"; - break; - case ARROW_DOWN: - name = "graphics/sprites/arrow_down.png"; - break; - case ARROW_LEFT: - name = "graphics/sprites/arrow_left.png"; - break; - case ARROW_RIGHT: - name = "graphics/sprites/arrow_right.png"; - break; - default: - break; - } - - if (!name.empty()) - { - ResourceManager *const resman = ResourceManager::getInstance(); - mImage = resman->getImage(name); - } - else - { - mImage = nullptr; - } -} - -void MapItem::setPos(const int x, const int y) -{ - mX = x; - mY = y; -} - -void MapItem::draw(Graphics *const graphics, const int x, const int y, - const int dx, const int dy) const -{ - BLOCK_START("MapItem::draw") - if (mImage) - graphics->drawImage(mImage, x, y); - - switch (mType) - { - case ROAD: - case CROSS: - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::ROAD_POINT)); - graphics->fillRectangle(Rect(x + dx / 3, y + dy / 3, - dx / 3, dy / 3)); - break; - case HOME: - { - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::HOME_PLACE)); - graphics->fillRectangle(Rect(x, y, dx, dy)); - graphics->setColor(userPalette->getColorWithAlpha( - UserPalette::HOME_PLACE_BORDER)); - graphics->drawRectangle(Rect(x, y, dx, dy)); - break; - } - default: - break; - } - if (!mName.empty() && mType != PORTAL && mType != EMPTY) - { - Font *const font = gui->getFont(); - if (font) - { - graphics->setColor(userPalette->getColor(UserPalette::BEING)); - font->drawString(graphics, mName, x, y); - } - } - BLOCK_END("MapItem::draw") -} - -ObjectsLayer::ObjectsLayer(const unsigned width, const unsigned height) : - mTiles(new MapObjectList*[width * height]), - mWidth(width), - mHeight(height) -{ - std::fill_n(mTiles, width * height, 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(const std::string &name, const int type, - const unsigned x, const 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 ++) - { - const unsigned idx1 = x + y1 * mWidth; - const 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(const unsigned x, const unsigned y) const -{ - 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 deleted file mode 100644 index 19b8f2503..000000000 --- a/src/maplayer.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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 "position.h" -#include "main.h" - -#include "listeners/configlistener.h" - -#include "being/actor.h" - -#include -#include - -class Image; -class MapItem; -class SpecialLayer; -class ImageVertexes; - -typedef std::vector MepRowImages; - -class MapRowVertexes final -{ - public: - MapRowVertexes() : - images() - { - images.reserve(30); - } - - A_DELETE_COPY(MapRowVertexes) - - ~MapRowVertexes(); - - MepRowImages images; -}; - -class MapObject final -{ - public: - MapObject(const int type0, const std::string &data0) : - type(type0), data(data0) - { - } - - int type; - std::string data; -}; - -class MapObjectList final -{ - public: - MapObjectList() : - objects() - { - } - - A_DELETE_COPY(MapObjectList) - - std::vector objects; -}; - -/** - * A map layer. Stores a grid of tiles and their offset, and implements layer - * rendering. - */ -class MapLayer final: public ConfigListener -{ - public: - enum Type - { - TILES = 0, - COLLISION, - HEIGHTS - }; - - 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(const int x, const int y, const int width, const int height, - const bool isFringeLayer, const int mask); - - A_DELETE_COPY(MapLayer) - - /** - * Destructor. - */ - ~MapLayer(); - - /** - * Set tile image, with x and y in layer coordinates. - */ - void setTile(const int x, const int y, Image *const img); - - /** - * Set tile image with x + y * width already known. - */ - void setTile(const int index, Image *const 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 *const graphics, - int startX, int startY, int endX, int endY, - const int scrollX, const int scrollY, - const int mDebugFlags) const; - - void drawSDL(Graphics *const graphics); - -#ifdef USE_OPENGL - void drawOGL(Graphics *const graphics); - - void updateOGL(const Graphics *const graphics, - int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const int mDebugFlags); -#endif - - void updateSDL(const Graphics *const graphics, - int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const int mDebugFlags); - - void drawFringe(Graphics *const graphics, - int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY, - const Actors *const actors, - const int mDebugFlags, const int yFix) const; - - bool isFringeLayer() const A_WARN_UNUSED - { return mIsFringeLayer; } - - void setSpecialLayer(SpecialLayer *const val) - { mSpecialLayer = val; } - - void setTempLayer(SpecialLayer *const val) - { mTempLayer = val; } - - int getWidth() const A_WARN_UNUSED - { return mWidth; } - - int getHeight() const A_WARN_UNUSED - { return mHeight; } - - void optionChanged(const std::string &value) override final; - - static int getTileDrawWidth(const Image *img, - const int endX, - int &width) A_WARN_UNUSED; - - private: - int mX; - int mY; - int mWidth; - int mHeight; - Image **mTiles; - SpecialLayer *mSpecialLayer; - SpecialLayer *mTempLayer; - typedef std::vector MapRows; - MapRows mTempRows; - int mMask; - bool mIsFringeLayer; /**< Whether the actors are drawn. */ - bool mHighlightAttackRange; -}; - -class SpecialLayer final -{ - public: - friend class Map; - friend class MapLayer; - - SpecialLayer(const int width, const int height); - - A_DELETE_COPY(SpecialLayer) - - ~SpecialLayer(); - - void draw(Graphics *const graphics, int startX, int startY, - int endX, int endY, - const int scrollX, const int scrollY) const; - - MapItem* getTile(const int x, const int y) const A_WARN_UNUSED; - - void setTile(const int x, const int y, MapItem *const item); - - void setTile(const int x, const int y, const int type); - - void addRoad(const Path &road); - - void clean() const; - - private: - int mWidth; - int mHeight; - MapItem **mTiles; -}; - -class MapItem final -{ - 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, - PICKUP = 13, - NOPICKUP = 14, - SEPARATOR = 15 - }; - - MapItem(); - - explicit MapItem(const int type); - - MapItem(const int type, std::string comment); - - MapItem(const int type, std::string comment, const int x, const int y); - - A_DELETE_COPY(MapItem) - - ~MapItem(); - - int getType() const A_WARN_UNUSED - { return mType; } - - void setType(const int type); - - void setPos(const int x, const int y); - - int getX() const A_WARN_UNUSED - { return mX; } - - int getY() const A_WARN_UNUSED - { return mY; } - - const std::string &getComment() const A_WARN_UNUSED - { return mComment; } - - void setComment(const std::string &comment) - { mComment = comment; } - - const std::string &getName() const A_WARN_UNUSED - { return mName; } - - void setName(const std::string &name) - { mName = name; } - - void draw(Graphics *const graphics, const int x, const int y, - const int dx, const int dy) const; - - private: - Image *mImage; - std::string mComment; - std::string mName; - int mType; - int mX; - int mY; -}; - -class ObjectsLayer final -{ - public: - ObjectsLayer(const unsigned width, const unsigned height); - - A_DELETE_COPY(ObjectsLayer) - - ~ObjectsLayer(); - - void addObject(const std::string &name, const int type, - const unsigned x, const unsigned y, - unsigned dx, unsigned dy); - - MapObjectList *getAt(const unsigned x, - const unsigned y) const A_WARN_UNUSED; - private: - MapObjectList **mTiles; - unsigned mWidth; - unsigned mHeight; -}; - -#endif // MAPLAYER_H diff --git a/src/navigationmanager.cpp b/src/navigationmanager.cpp index b999fe769..8cbb85667 100644 --- a/src/navigationmanager.cpp +++ b/src/navigationmanager.cpp @@ -20,8 +20,8 @@ #include "navigationmanager.h" -#include "map.h" -#include "walklayer.h" +#include "resources/map/map.h" +#include "resources/map/walklayer.h" static const int walkMask = (Map::BLOCKMASK_WALL | Map::BLOCKMASK_AIR | Map::BLOCKMASK_WATER); diff --git a/src/particle/particleemitter.cpp b/src/particle/particleemitter.cpp index 39550f03d..d9e0a579a 100644 --- a/src/particle/particleemitter.cpp +++ b/src/particle/particleemitter.cpp @@ -23,7 +23,8 @@ #include "particle/particleemitter.h" #include "logger.h" -#include "map.h" + +#include "resources/map/map.h" #include "particle/animationparticle.h" #include "particle/rotationalparticle.h" diff --git a/src/properties.h b/src/properties.h deleted file mode 100644 index 5b9908746..000000000 --- a/src/properties.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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 PROPERTIES_H -#define PROPERTIES_H - -#include "localconsts.h" - -#include -#include -#include - -/** - * A class holding a set of properties. - */ -class Properties -{ - public: - Properties() : - mProperties() - { - } - - /** - * Destructor. - */ - virtual ~Properties() - { } - - /** - * Get a map property. - * - * @param name The name of the property. - * @param def Default value, empty string by default. - * @return the value of the given property or the given default when it - * doesn't exist. - */ - const std::string getProperty(const std::string &name, - const std::string &def = "") - const A_WARN_UNUSED - { - const PropertyMap::const_iterator i = mProperties.find(name); - return (i != mProperties.end()) ? i->second : def; - } - - /** - * Gets a map property as a float. - * - * @param name The name of the property. - * @param def Default value, 0.0F by default. - * @return the value of the given property or the given default when it - * doesn't exist. - */ - float getFloatProperty(const std::string &name, - const float def = 0.0F) const A_WARN_UNUSED - { - const PropertyMap::const_iterator i = mProperties.find(name); - float ret = def; - if (i != mProperties.end()) - { - std::stringstream ss; - ss.str(i->second); - ss >> ret; - } - return ret; - } - - /** - * Gets a map property as a boolean. - * - * @param name The name of the property. - * @param def Default value, false by default. - * @return the value of the given property or the given default when it - * doesn't exist. - */ - bool getBoolProperty(const std::string &name, - const bool def = false) const A_WARN_UNUSED - { - const PropertyMap::const_iterator i = mProperties.find(name); - bool ret = def; - if (i != mProperties.end()) - { - if (i->second == "true") - ret = true; - if (i->second == "false") - ret = false; - } - return ret; - } - - /** - * Returns whether a certain property is available. - * - * @param name The name of the property. - * @return true when a property is defined, - * false otherwise. - */ - bool hasProperty(const std::string &name) const A_WARN_UNUSED - { return (mProperties.find(name) != mProperties.end()); } - - /** - * Set a map property. - * - * @param name The name of the property. - * @param value The value of the property. - */ - void setProperty(const std::string &name, const std::string &value) - { mProperties[name] = value; } - - - private: - typedef std::map PropertyMap; - PropertyMap mProperties; -}; - -#endif // PROPERTIES_H diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index 6f760fe9d..9e0fa24b9 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -21,7 +21,7 @@ #include "resources/ambientlayer.h" -#include "map.h" +#include "resources/map/map.h" #include "render/graphics.h" diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp index 81a153e04..9c8c49fc5 100644 --- a/src/resources/db/itemdb.cpp +++ b/src/resources/db/itemdb.cpp @@ -22,7 +22,7 @@ #include "resources/db/itemdb.h" -#include "map.h" +#include "resources/map/map.h" #include "configuration.h" #include "logger.h" diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 391e546da..911cacef6 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -22,7 +22,7 @@ #include "resources/iteminfo.h" -#include "map.h" +#include "resources/map/map.h" #include "resources/db/colordb.h" #include "resources/db/itemdb.h" diff --git a/src/resources/map/map.cpp b/src/resources/map/map.cpp new file mode 100644 index 000000000..c753b0202 --- /dev/null +++ b/src/resources/map/map.cpp @@ -0,0 +1,1509 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 "resources/map/map.h" + +#include "client.h" +#include "configuration.h" +#include "render/graphics.h" +#include "notifications.h" +#include "notifymanager.h" +#include "simpleanimation.h" + +#include "resources/map/mapheights.h" +#include "resources/map/maplayer.h" +#include "resources/map/tileset.h" +#include "resources/map/walklayer.h" + +#include "being/localplayer.h" + +#include "particle/particle.h" + +#include "resources/ambientlayer.h" +#include "resources/image.h" +#include "resources/resourcemanager.h" +#include "resources/subimage.h" + +#include "utils/delete2.h" +#include "utils/dtor.h" +#include "utils/mkdir.h" +#include "utils/physfstools.h" +#include "utils/timer.h" + +#include +#include + +#include + +#include "debug.h" + +/** + * A location on a tile map. Used for pathfinding, open list. + */ +struct Location final +{ + /** + * Constructor. + */ + Location(const int px, const int py, MetaTile *const ptile): + x(px), y(py), tile(ptile) + {} + + /** + * Comparison operator. + */ + bool operator< (const Location &loc) const + { + return tile->Fcost > loc.tile->Fcost; + } + + int x, y; + MetaTile *tile; +}; + +class ActorFunctuator final +{ + public: + bool operator()(const Actor *const a, const Actor *const b) const + { + if (!a || !b) + return false; + return a->getSortPixelY() < b->getSortPixelY(); + } +} actorCompare; + +TileAnimation::TileAnimation(Animation *const ani): + mAffected(), + mAnimation(new SimpleAnimation(ani)), + mLastImage(nullptr) +{ +} + +TileAnimation::~TileAnimation() +{ + delete2(mAnimation); +} + +bool TileAnimation::update(const int ticks) +{ + if (!mAnimation) + return false; + + // update animation + if (!mAnimation->update(ticks)) + return false; + + // exchange images + Image *const img = mAnimation->getCurrentImage(); + if (img != mLastImage) + { + FOR_EACH (TilePairVectorCIter, i, mAffected) + { + if (i->first) + i->first->setTile(i->second, img); + } + mLastImage = img; + } + return true; +} + +Map::Map(const int width, const int height, + const int tileWidth, const int tileHeight) : + Properties(), + mWidth(width), mHeight(height), + mTileWidth(tileWidth), mTileHeight(tileHeight), + mMaxTileHeight(height), + mMetaTiles(new MetaTile[mWidth * mHeight]), + mWalkLayer(nullptr), + mLayers(), + mTilesets(), + mActors(), + mHasWarps(false), + mDebugFlags(MAP_NORMAL), + mOnClosedList(1), + mOnOpenList(2), + mBackgrounds(), + mForegrounds(), + mLastAScrollX(0.0F), + mLastAScrollY(0.0F), + mParticleEffects(), + mMapPortals(), + mTileAnimations(), + mOverlayDetail(config.getIntValue("OverlayDetail")), + mOpacity(config.getFloatValue("guialpha")), +#ifdef USE_OPENGL + mOpenGL(intToRenderType(config.getIntValue("opengl"))), +#else + mOpenGL(RENDER_SOFTWARE), +#endif + mPvp(0), + mTilesetsIndexed(false), + mIndexedTilesets(nullptr), + mIndexedTilesetsSize(0), + mActorFixX(0), + mActorFixY(0), + mVersion(0), + mSpecialLayer(new SpecialLayer(width, height)), + mTempLayer(new SpecialLayer(width, height)), + mObjects(new ObjectsLayer(width, height)), + mFringeLayer(nullptr), + mLastX(-1), + mLastY(-1), + mLastScrollX(-1), + mLastScrollY(-1), + mDrawX(-1), + mDrawY(-1), + mDrawScrollX(-1), + mDrawScrollY(-1), + mMask(1), + mAtlas(nullptr), + mHeights(nullptr), + mRedrawMap(true), + mBeingOpacity(false), + mCustom(false) +{ + const int size = mWidth * mHeight; + for (int i = 0; i < NB_BLOCKTYPES; i++) + { + mOccupation[i] = new unsigned[static_cast(size)]; + memset(mOccupation[i], 0, static_cast(size) + * sizeof(unsigned)); + } + + config.addListener("OverlayDetail", this); + config.addListener("guialpha", this); + config.addListener("beingopacity", this); + + if (mOpacity != 1.0F) + mBeingOpacity = config.getBoolValue("beingopacity"); + else + mBeingOpacity = false; +} + +Map::~Map() +{ + config.removeListeners(this); + CHECKLISTENERS + + delete [] mMetaTiles; + for (int i = 0; i < NB_BLOCKTYPES; i++) + delete [] mOccupation[i]; + + if (mWalkLayer) + { + mWalkLayer->decRef(); + mWalkLayer = nullptr; + } + mFringeLayer = nullptr; + delete_all(mLayers); + delete_all(mTilesets); + delete_all(mForegrounds); + delete_all(mBackgrounds); + delete_all(mTileAnimations); + delete2(mSpecialLayer); + delete2(mTempLayer); + delete2(mObjects); + delete_all(mMapPortals); + if (mAtlas) + { + mAtlas->decRef(); + mAtlas = nullptr; + } + delete2(mHeights); +} + +void Map::optionChanged(const std::string &value) +{ + if (value == "OverlayDetail") + { + mOverlayDetail = config.getIntValue("OverlayDetail"); + } + else if (value == "guialpha") + { + mOpacity = config.getFloatValue("guialpha"); + if (mOpacity != 1.0F) + mBeingOpacity = config.getBoolValue("beingopacity"); + else + mBeingOpacity = false; + } + else if (value == "beingopacity") + { + if (mOpacity != 1.0F) + mBeingOpacity = config.getBoolValue("beingopacity"); + else + mBeingOpacity = false; + } +} + +void Map::initializeAmbientLayers() +{ + ResourceManager *const resman = ResourceManager::getInstance(); + + // search for "foreground*" or "overlay*" (old term) in map properties + for (int i = 0; /* terminated by a break */; i++) + { + std::string name; + if (hasProperty(std::string("foreground").append( + toString(i)).append("image"))) + { + name = "foreground" + toString(i); + } + else if (hasProperty(std::string("overlay").append( + toString(i)).append("image"))) + { + name = "overlay" + toString(i); + } + else + { + break; // the FOR loop + } + + Image *const img = resman->getImage(getProperty(name + "image")); + if (img) + { + int mask = atoi(getProperty(name + "mask").c_str()); + if (!mask) + mask = 1; + const float parallax = getFloatProperty(name + "parallax"); + mForegrounds.push_back(new AmbientLayer(img, + getFloatProperty(name + "parallaxX", parallax), + getFloatProperty(name + "parallaxY", parallax), + getFloatProperty(name + "posX"), + getFloatProperty(name + "posY"), + getFloatProperty(name + "scrollX"), + getFloatProperty(name + "scrollY"), + getBoolProperty(name + "keepratio"), + mask)); + + // The AmbientLayer takes control over the image. + img->decRef(); + } + } + + // search for "background*" in map properties + for (int i = 0; hasProperty(std::string("background").append( + toString(i)).append("image")); i ++) + { + const std::string name("background" + toString(i)); + Image *const img = resman->getImage(getProperty(name + "image")); + + if (img) + { + int mask = atoi(getProperty(name + "mask").c_str()); + if (!mask) + mask = 1; + + const float parallax = getFloatProperty(name + "parallax"); + mForegrounds.push_back(new AmbientLayer(img, + getFloatProperty(name + "parallaxX", parallax), + getFloatProperty(name + "parallaxY", parallax), + getFloatProperty(name + "posX"), + getFloatProperty(name + "posY"), + getFloatProperty(name + "scrollX"), + getFloatProperty(name + "scrollY"), + getBoolProperty(name + "keepratio"), + mask)); + + // The AmbientLayer takes control over the image. + img->decRef(); + } + } +} + +void Map::addLayer(MapLayer *const layer) +{ + if (layer) + { + mLayers.push_back(layer); + if (layer->isFringeLayer() && !mFringeLayer) + mFringeLayer = layer; + } +} + +void Map::addTileset(Tileset *const tileset) +{ + if (!tileset) + return; + + mTilesets.push_back(tileset); + const int height = tileset->getHeight(); + if (height > mMaxTileHeight) + mMaxTileHeight = height; +} + +void Map::update(const int ticks) +{ + // Update animated tiles + FOR_EACH (TileAnimationMapCIter, iAni, mTileAnimations) + { + TileAnimation *const tileAni = iAni->second; + if (tileAni && tileAni->update(ticks)) + mRedrawMap = true; + } +} + +void Map::draw(Graphics *const graphics, int scrollX, int scrollY) +{ + if (!player_node) + return; + + BLOCK_START("Map::draw") + // Calculate range of tiles which are on-screen + const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1 + + mMaxTileHeight - mTileHeight; + const int startX = scrollX / mTileWidth - 2; + const int startY = scrollY / mTileHeight; + const int endX = (graphics->mWidth + scrollX + mTileWidth - 1) + / mTileWidth + 1; + const int endY = endPixelY / mTileHeight + 1; + + // Make sure actors are sorted ascending by Y-coordinate + // so that they overlap correctly + BLOCK_START("Map::draw sort") + mActors.sort(actorCompare); + BLOCK_END("Map::draw sort") + + // update scrolling of all ambient layers + updateAmbientLayers(static_cast(scrollX), + static_cast(scrollY)); + + // Draw backgrounds + drawAmbientLayers(graphics, BACKGROUND_LAYERS, mOverlayDetail); + + if (mDebugFlags == MAP_BLACKWHITE && userPalette) + { + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::WALKABLE_HIGHLIGHT)); + + graphics->fillRectangle(Rect(0, 0, + graphics->mWidth, graphics->mHeight)); + } + +#ifdef USE_OPENGL + int updateFlag = 0; + + if (mOpenGL == RENDER_NORMAL_OPENGL || mOpenGL == RENDER_GLES_OPENGL) + { + if (mLastX != startX || mLastY != startY || mLastScrollX != scrollX + || mLastScrollY != scrollY) + { // player moving + mLastX = startX; + mLastY = startY; + mLastScrollX = scrollX; + mLastScrollY = scrollY; + updateFlag = 2; + } + else if (mRedrawMap || startX != mDrawX || startY != mDrawY || + scrollX != mDrawScrollX || scrollY != mDrawScrollY) + { // player mode to new position + mRedrawMap = false; + mDrawX = startX; + mDrawY = startY; + mDrawScrollX = scrollX; + mDrawScrollY = scrollY; + updateFlag = 1; + } + } +#endif + + if (mDebugFlags == MAP_SPECIAL3 || mDebugFlags == MAP_BLACKWHITE) + { + if (mFringeLayer) + { + mFringeLayer->setSpecialLayer(mSpecialLayer); + mFringeLayer->setTempLayer(mTempLayer); + mFringeLayer->drawFringe(graphics, startX, startY, endX, endY, + scrollX, scrollY, &mActors, mDebugFlags, mActorFixY); + } + } + else + { + bool overFringe = false; + + for (LayersCIter layeri = mLayers.begin(), layeri_end = mLayers.end(); + layeri != layeri_end && !overFringe; ++ layeri) + { + MapLayer *const layer = *layeri; + if (!(layer->mMask & mMask)) + continue; + + if (layer->isFringeLayer()) + { + layer->setSpecialLayer(mSpecialLayer); + layer->setTempLayer(mTempLayer); + if (mDebugFlags == MAP_SPECIAL2) + overFringe = true; + + layer->drawFringe(graphics, startX, startY, endX, endY, + scrollX, scrollY, &mActors, mDebugFlags, mActorFixY); + } + else + { +#ifdef USE_OPENGL + if (mOpenGL == RENDER_NORMAL_OPENGL + || mOpenGL == RENDER_GLES_OPENGL) + { + if (updateFlag) + { + layer->updateOGL(graphics, startX, startY, + endX, endY, scrollX, scrollY, mDebugFlags); + } + + layer->drawOGL(graphics); + } + else +#endif + { + layer->draw(graphics, startX, startY, endX, endY, + scrollX, scrollY, mDebugFlags); + } + } + } + } + + // Don't draw if gui opacity == 1 + if (mBeingOpacity && mOpacity != 1.0F) + { + // Draws beings with a lower opacity to make them visible + // even when covered by a wall or some other elements... + ActorsCIter ai = mActors.begin(); + const ActorsCIter ai_end = mActors.end(); + while (ai != ai_end) + { + if (Actor *const actor = *ai) + { + if (mOpenGL == RENDER_SOFTWARE) + { + const int x = actor->getTileX(); + const int y = actor->getTileY(); + if (x < startX || x > endX || y < startY || y > endY) + { + ++ai; + continue; + } + } + // For now, just draw actors with only one layer. + if (actor->getNumberOfLayers() == 1) + { + actor->setAlpha(0.3F); + actor->draw(graphics, -scrollX, -scrollY); + actor->setAlpha(1.0F); + } + } + ++ai; + } + } + + drawAmbientLayers(graphics, FOREGROUND_LAYERS, mOverlayDetail); + BLOCK_END("Map::draw") +} + +#define fillCollision(collision, color) \ + if (x < endX && mMetaTiles[tilePtr].blockmask & collision)\ + {\ + width = mapTileSize;\ + for (int x2 = tilePtr + 1; x < endX; x2 ++)\ + {\ + if (!(mMetaTiles[x2].blockmask & collision))\ + break;\ + width += mapTileSize;\ + x ++;\ + tilePtr ++;\ + }\ + if (width && userPalette)\ + {\ + graphics->setColor(userPalette->getColorWithAlpha(\ + UserPalette::color));\ + graphics->fillRectangle(Rect(\ + x0 * mTileWidth - scrollX, \ + y * mTileHeight - scrollY, \ + width, mapTileSize));\ + }\ + }\ + +void Map::drawCollision(Graphics *const graphics, + const int scrollX, const int scrollY, + const int debugFlags) const +{ + const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1; + int startX = scrollX / mTileWidth; + int startY = scrollY / mTileHeight; + int endX = (graphics->mWidth + scrollX + mTileWidth - 1) / mTileWidth; + int endY = endPixelY / mTileHeight; + + if (startX < 0) + startX = 0; + if (startY < 0) + startY = 0; + if (endX > mWidth) + endX = mWidth; + if (endY > mHeight) + endY = mHeight; + + if (debugFlags < MAP_SPECIAL) + { + graphics->setColor(userPalette->getColorWithAlpha(UserPalette::NET)); + graphics->drawNet( + startX * mTileWidth - scrollX, + startY * mTileHeight - scrollY, + endX * mTileWidth - scrollX, + endY * mTileHeight - scrollY, + mapTileSize, mapTileSize); + } + + for (int y = startY; y < endY; y++) + { + const int yWidth = y * mWidth; + int tilePtr = startX + yWidth; + for (int x = startX; x < endX; x++, tilePtr++) + { + int width = 0; + const int x0 = x; + + fillCollision(BLOCKMASK_WALL, COLLISION_HIGHLIGHT); + fillCollision(BLOCKMASK_AIR, AIR_COLLISION_HIGHLIGHT); + fillCollision(BLOCKMASK_WATER, WATER_COLLISION_HIGHLIGHT); + fillCollision(BLOCKMASK_GROUNDTOP, GROUNDTOP_COLLISION_HIGHLIGHT); + } + } +} + +void Map::updateAmbientLayers(const float scrollX, const float scrollY) +{ + BLOCK_START("Map::updateAmbientLayers") + static int lastTick = tick_time; + + if (mLastAScrollX == 0.0F && mLastAScrollY == 0.0F) + { + // First call - initialisation + mLastAScrollX = scrollX; + mLastAScrollY = scrollY; + } + + // Update Overlays + const float dx = scrollX - mLastAScrollX; + const float dy = scrollY - mLastAScrollY; + const int timePassed = get_elapsed_time(lastTick); + + // need check mask to update or not to update + + FOR_EACH (AmbientLayerVectorIter, i, mBackgrounds) + { + AmbientLayer *const layer = *i; + if (layer && (layer->mMask & mMask)) + layer->update(timePassed, dx, dy); + } + + FOR_EACH (AmbientLayerVectorIter, i, mForegrounds) + { + AmbientLayer *const layer = *i; + if (layer && (layer->mMask & mMask)) + layer->update(timePassed, dx, dy); + } + + mLastAScrollX = scrollX; + mLastAScrollY = scrollY; + lastTick = tick_time; + BLOCK_END("Map::updateAmbientLayers") +} + +void Map::drawAmbientLayers(Graphics *const graphics, const LayerType type, + const int detail) +{ + BLOCK_START("Map::drawAmbientLayers") + // Detail 0 = no ambient effects except background image + if (detail <= 0 && type != BACKGROUND_LAYERS) + { + BLOCK_END("Map::drawAmbientLayers") + return; + } + + // find out which layer list to draw + AmbientLayerVector *layers = nullptr; + switch (type) + { + case FOREGROUND_LAYERS: + layers = &mForegrounds; + break; + case BACKGROUND_LAYERS: + layers = &mBackgrounds; + break; + default: + return; + } + + // Draw overlays + FOR_EACHP (AmbientLayerVectorCIter, i, layers) + { + const AmbientLayer *const layer = *i; + // need check mask to draw or not to draw + if (layer && (layer->mMask & mMask)) + (layer)->draw(graphics, graphics->mWidth, graphics->mHeight); + + // Detail 1: only one overlay, higher: all overlays + if (detail == 1) + break; + } + BLOCK_END("Map::drawAmbientLayers") +} + +const Tileset *Map::getTilesetWithGid(const int gid) const +{ + if (gid >= 0 && gid < mIndexedTilesetsSize) + return mIndexedTilesets[gid]; + else + return nullptr; +} + +void Map::blockTile(const int x, const int y, const BlockType type) +{ + if (type == BLOCKTYPE_NONE || !contains(x, y)) + return; + + const int tileNum = x + y * mWidth; + + if (mOccupation[static_cast(type)][tileNum] < UINT_MAX && + (++mOccupation[static_cast(type)][tileNum]) > 0) + { + switch (type) + { + case BLOCKTYPE_WALL: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_WALL; + break; + case BLOCKTYPE_CHARACTER: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_CHARACTER; + break; + case BLOCKTYPE_MONSTER: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_MONSTER; + break; + case BLOCKTYPE_AIR: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_AIR; + break; + case BLOCKTYPE_WATER: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_WATER; + break; + case BLOCKTYPE_GROUND: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_GROUND; + break; + case BLOCKTYPE_GROUNDTOP: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_GROUNDTOP; + break; + default: + case BLOCKTYPE_NONE: + case NB_BLOCKTYPES: + // Do nothing. + break; + } + } +} + +bool Map::getWalk(const int x, const int y, const unsigned char walkmask) const +{ + // You can't walk outside of the map + if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) + return false; + + // Check if the tile is walkable + return !(mMetaTiles[x + y * mWidth].blockmask & walkmask); +} + +unsigned char Map::getBlockMask(const int x, const int y) const +{ + // You can't walk outside of the map + if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) + return 0; + + // Check if the tile is walkable + return mMetaTiles[x + y * mWidth].blockmask; +} + +void Map::setWalk(const int x, const int y, const bool walkable A_UNUSED) +{ + blockTile(x, y, Map::BLOCKTYPE_GROUNDTOP); +} + +bool Map::contains(const int x, const int y) const +{ + return x >= 0 && y >= 0 && x < mWidth && y < mHeight; +} + +const MetaTile *Map::getMetaTile(const int x, const int y) const +{ + return &mMetaTiles[x + y * mWidth]; +} + +Actors::iterator Map::addActor(Actor *const actor) +{ + mActors.push_front(actor); +// mSpritesUpdated = true; + return mActors.begin(); +} + +void Map::removeActor(const Actors::iterator &iterator) +{ + mActors.erase(iterator); +// mSpritesUpdated = true; +} + +const std::string Map::getMusicFile() const +{ + return getProperty("music"); +} + +const std::string Map::getName() const +{ + if (hasProperty("name")) + return getProperty("name"); + + return getProperty("mapname"); +} + +const std::string Map::getFilename() const +{ + const std::string fileName = getProperty("_filename"); + const size_t lastSlash = fileName.rfind("/") + 1; + return fileName.substr(lastSlash, fileName.rfind(".") - lastSlash); +} + +Path Map::findPath(const int startX, const int startY, + const int destX, const int destY, + const unsigned char walkmask, const int maxCost) +{ + // The basic walking cost of a tile. + static const int basicCost = 100; + const int basicCost2 = 100 * 362 / 256; + const float basicCostF = 100.0 * 362 / 256; + + // Path to be built up (empty by default) + Path path; + + if (startX >= mWidth || startY >= mHeight || startX < 0 || startY < 0) + return path; + + // Return when destination not walkable + if (!getWalk(destX, destY, walkmask)) + return path; + + // Reset starting tile's G cost to 0 + MetaTile *const startTile = &mMetaTiles[startX + startY * mWidth]; + if (!startTile) + return path; + + startTile->Gcost = 0; + + // Declare open list, a list with open tiles sorted on F cost + std::priority_queue openList; + + // Add the start point to the open list + openList.push(Location(startX, startY, startTile)); + + bool foundPath = false; + + // Keep trying new open tiles until no more tiles to try or target found + while (!openList.empty() && !foundPath) + { + // Take the location with the lowest F cost from the open list. + const Location curr = openList.top(); + openList.pop(); + + const MetaTile *const tile = curr.tile; + + // If the tile is already on the closed list, this means it has already + // been processed with a shorter path to the start point (lower G cost) + if (tile->whichList == mOnClosedList) + continue; + + // Put the current tile on the closed list + curr.tile->whichList = mOnClosedList; + + const int curWidth = curr.y * mWidth; + const int tileGcost = tile->Gcost; + + // Check the adjacent tiles + for (int dy = -1; dy <= 1; dy++) + { + const int y = curr.y + dy; + if (y < 0 || y >= mHeight) + continue; + + const int yWidth = y * mWidth; + const int dy1 = std::abs(y - destY); + + for (int dx = -1; dx <= 1; dx++) + { + // Calculate location of tile to check + const int x = curr.x + dx; + + // Skip if if we're checking the same tile we're leaving from, + // or if the new location falls outside of the map boundaries + if ((dx == 0 && dy == 0) || x < 0 || x >= mWidth) + continue; + + MetaTile *const newTile = &mMetaTiles[x + yWidth]; + + // Skip if the tile is on the closed list or is not walkable + // unless its the destination tile + // +++ here need check block must depend on player abilities. + if (newTile->whichList == mOnClosedList || + ((newTile->blockmask & walkmask) + && !(x == destX && y == destY)) + || (newTile->blockmask & BLOCKMASK_WALL)) + { + continue; + } + + // When taking a diagonal step, verify that we can skip the + // corner. + if (dx != 0 && dy != 0) + { + const MetaTile *const t1 = &mMetaTiles[curr.x + + (curr.y + dy) * mWidth]; + const MetaTile *const t2 = &mMetaTiles[curr.x + + dx + curWidth]; + + // +++ here need check block must depend + // on player abilities. + if (((t1->blockmask | t2->blockmask) & BLOCKMASK_WALL)) + continue; + } + + // Calculate G cost for this route, ~sqrt(2) for moving diagonal + int Gcost = tileGcost + (dx == 0 || dy == 0 + ? basicCost : basicCost2); + + /* Demote an arbitrary direction to speed pathfinding by + adding a defect (TODO: change depending on the desired + visual effect, e.g. a cross-product defect toward + destination). + Important: as long as the total defect along any path is + less than the basicCost, the pathfinder will still find one + of the shortest paths! */ + if (dx == 0 || dy == 0) + { + // Demote horizontal and vertical directions, so that two + // consecutive directions cannot have the same Fcost. + ++Gcost; + } + + // It costs extra to walk through a being (needs to be enough + // to make it more attractive to walk around). +// if (occupied(x, y)) +// { +// Gcost += 3 * basicCost; +// } + + // Skip if Gcost becomes too much + // Warning: probably not entirely accurate + if (maxCost > 0 && Gcost > maxCost * basicCost) + continue; + + if (newTile->whichList != mOnOpenList) + { + // Found a new tile (not on open nor on closed list) + + /* Update Hcost of the new tile. The pathfinder does not + work reliably if the heuristic cost is higher than the + real cost. In particular, using Manhattan distance is + forbidden here. */ + const int dx1 = std::abs(x - destX); + newTile->Hcost = std::abs(dx1 - dy1) * basicCost + + std::min(dx1, dy1) * (basicCostF); + + // Set the current tile as the parent of the new tile + newTile->parentX = curr.x; + newTile->parentY = curr.y; + + // Update Gcost and Fcost of new tile + newTile->Gcost = Gcost; + newTile->Fcost = Gcost + newTile->Hcost; + + if (x != destX || y != destY) + { + // Add this tile to the open list + newTile->whichList = mOnOpenList; + openList.push(Location(x, y, newTile)); + } + else + { + // Target location was found + foundPath = true; + } + } + else if (Gcost < newTile->Gcost) + { + // Found a shorter route. + // Update Gcost and Fcost of the new tile + newTile->Gcost = Gcost; + newTile->Fcost = Gcost + newTile->Hcost; + + // Set the current tile as the parent of the new tile + newTile->parentX = curr.x; + newTile->parentY = curr.y; + + // Add this tile to the open list (it's already + // there, but this instance has a lower F score) + openList.push(Location(x, y, newTile)); + } + } + } + } + + // Two new values to indicate whether a tile is on the open or closed list, + // this way we don't have to clear all the values between each pathfinding. + if (mOnOpenList > UINT_MAX - 2) + { + // We reset the list memebers value. + mOnClosedList = 1; + mOnOpenList = 2; + + // Clean up the metaTiles + const int size = mWidth * mHeight; + for (int i = 0; i < size; ++i) + mMetaTiles[i].whichList = 0; + } + else + { + mOnClosedList += 2; + mOnOpenList += 2; + } + + // If a path has been found, iterate backwards using the parent locations + // to extract it. + if (foundPath) + { + int pathX = destX; + int pathY = destY; + + while (pathX != startX || pathY != startY) + { + // Add the new path node to the start of the path list + path.push_front(Position(pathX, pathY)); + + // Find out the next parent + const MetaTile *const tile = &mMetaTiles[pathX + pathY * mWidth]; + pathX = tile->parentX; + pathY = tile->parentY; + } + } + + return path; +} + +void Map::addParticleEffect(const std::string &effectFile, + const int x, const int y, const int w, const int h) +{ + ParticleEffectData newEffect; + newEffect.file = effectFile; + newEffect.x = x; + newEffect.y = y; + newEffect.w = w; + newEffect.h = h; + mParticleEffects.push_back(newEffect); +} + +void Map::initializeParticleEffects(Particle *const engine) +{ + if (!engine) + return; + + if (config.getBoolValue("particleeffects")) + { + for (std::vector::const_iterator + i = mParticleEffects.begin(); + i != mParticleEffects.end(); ++i) + { + Particle *const p = engine->addEffect(i->file, i->x, i->y); + if (p && i->w > 0 && i->h > 0) + p->adjustEmitterSize(i->w, i->h); + } + } +} + +void Map::addExtraLayer() +{ + if (!mSpecialLayer) + { + logger->log1("No special layer"); + return; + } + const std::string mapFileName = getUserMapDirectory().append( + "/extralayer.txt"); + logger->log("loading extra layer: " + mapFileName); + struct stat statbuf; + if (!stat(mapFileName.c_str(), &statbuf) && S_ISREG(statbuf.st_mode)) + { + std::ifstream mapFile; + mapFile.open(mapFileName.c_str(), std::ios::in); + if (!mapFile.is_open()) + { + mapFile.close(); + return; + } + char line[201]; + + while (mapFile.getline(line, 200)) + { + std::string buf; + std::string str = line; + if (!str.empty()) + { + std::string x; + std::string y; + std::string type1; + std::string comment; + std::stringstream ss(str); + ss >> x; + ss >> y; + ss >> type1; + ss >> comment; + while (ss >> buf) + comment.append(" ").append(buf); + + const int type = atoi(type1.c_str()); + + if (comment.empty()) + { + if (type < MapItem::ARROW_UP + || type > MapItem::ARROW_RIGHT) + { + comment = "unknown"; + } + } + if (type == MapItem::PORTAL) + { + updatePortalTile(comment, type, atoi(x.c_str()), + atoi(y.c_str()), false); + } + else if (type == MapItem::HOME) + { + updatePortalTile(comment, type, atoi(x.c_str()), + atoi(y.c_str())); + } + else + { + addPortalTile(comment, type, atoi(x.c_str()), + atoi(y.c_str())); + } + } + } + mapFile.close(); + } +} + +void Map::saveExtraLayer() const +{ + if (!mSpecialLayer) + { + logger->log1("No special layer"); + return; + } + const std::string mapFileName = getUserMapDirectory().append( + "/extralayer.txt"); + logger->log("saving extra layer: " + mapFileName); + + if (mkdir_r(getUserMapDirectory().c_str())) + { + logger->log(strprintf("%s doesn't exist and can't be created! " + "Exiting.", getUserMapDirectory().c_str())); + return; + } + + std::ofstream mapFile; + mapFile.open(mapFileName.c_str(), std::ios::binary); + if (!mapFile.is_open()) + { + logger->log1("Unable to open extralayer.txt for writing"); + return; + } + + const int width = mSpecialLayer->mWidth; + const int height = mSpecialLayer->mHeight; + + for (int x = 0; x < width; x ++) + { + for (int y = 0; y < height; y ++) + { + const MapItem *const item = mSpecialLayer->getTile(x, y); + if (item && item->mType != MapItem::EMPTY + && item->mType != MapItem::HOME) + { + mapFile << x << " " << y << " " + << static_cast(item->mType) << " " + << item->mComment << std::endl; + } + } + } + mapFile.close(); +} + +std::string Map::getUserMapDirectory() const +{ + return client->getServerConfigDirectory() + + dirSeparator + getProperty("_realfilename"); +} + +void Map::addRange(const std::string &name, const int type, + const int x, const int y, const int dx, const int dy) +{ + if (!mObjects) + return; + + mObjects->addObject(name, type, x / mapTileSize, y / mapTileSize, + dx / mapTileSize, dy / mapTileSize); +} + +void Map::addPortal(const std::string &name, const int type, + const int x, const int y, const int dx, const int dy) +{ + addPortalTile(name, type, (x / mapTileSize) + (dx / mapTileSize / 2), + (y / mapTileSize) + (dy / mapTileSize / 2)); +} + +void Map::addPortalTile(const std::string &name, const int type, + const int x, const int y) +{ + if (mSpecialLayer) + mSpecialLayer->setTile(x, y, new MapItem(type, name, x, y)); + + mMapPortals.push_back(new MapItem(type, name, x, y)); +} + +void Map::updatePortalTile(const std::string &name, const int type, + const int x, const int y, const bool addNew) +{ + MapItem *item = findPortalXY(x, y); + if (item) + { + item->mComment = name; + item->setType(type); + item->mX = x; + item->mY = y; + if (mSpecialLayer) + { + item = new MapItem(type, name, x, y); + mSpecialLayer->setTile(x, y, item); + } + } + else if (addNew) + { + addPortalTile(name, type, x, y); + } +} + +MapItem *Map::findPortalXY(const int x, const int y) const +{ + FOR_EACH (std::vector::const_iterator, it, mMapPortals) + { + if (!*it) + continue; + + MapItem *const item = *it; + if (item->mX == x && item->mY == y) + return item; + } + return nullptr; +} + +const TileAnimation *Map::getAnimationForGid(const int gid) const +{ + if (mTileAnimations.empty()) + return nullptr; + + TileAnimationMapCIter i = mTileAnimations.find(gid); + return (i == mTileAnimations.end()) ? nullptr : i->second; +} + +void Map::setPvpMode(const int mode) +{ + const int oldMode = mPvp; + + if (!mode) + mPvp = 0; + else + mPvp |= mode; + + if (mPvp != oldMode && player_node) + { + switch (mPvp) + { + case 0: + NotifyManager::notify(NotifyManager::PVP_OFF_GVG_OFF); + break; + case 1: + NotifyManager::notify(NotifyManager::PVP_ON); + break; + case 2: + NotifyManager::notify(NotifyManager::GVG_ON); + break; + case 3: + NotifyManager::notify(NotifyManager::PVP_ON_GVG_ON); + break; + default: + NotifyManager::notify(NotifyManager::PVP_UNKNOWN); + break; + } + } +} + +std::string Map::getObjectData(const unsigned x, const unsigned y, + const int type) const +{ + if (!mObjects) + return ""; + + MapObjectList *const list = mObjects->getAt(x, y); + if (!list) + return ""; + + std::vector::const_iterator it = list->objects.begin(); + const std::vector::const_iterator it_end = list->objects.end(); + while (it != it_end) + { + if ((*it).type == type) + return (*it).data; + ++ it; + } + + return ""; +} + +void Map::indexTilesets() +{ + if (mTilesetsIndexed) + return; + + mTilesetsIndexed = true; + + const Tileset *s = nullptr; + size_t sSz = 0; + FOR_EACH (Tilesets::const_iterator, it, mTilesets) + { + const size_t sz = (*it)->size(); + if (!s || static_cast(s->getFirstGid()) + sSz + < static_cast((*it)->getFirstGid()) + sz) + { + s = *it; + sSz = sz; + } + } + if (!s) + { + mIndexedTilesetsSize = 0; + mIndexedTilesets = nullptr; + return; + } + + const int size = static_cast(s->getFirstGid()) + + static_cast(s->size()); + mIndexedTilesetsSize = size; + mIndexedTilesets = new Tileset*[static_cast(size)]; + std::fill_n(mIndexedTilesets, size, static_cast(nullptr)); + + FOR_EACH (Tilesets::const_iterator, it, mTilesets) + { + Tileset *const s2 = *it; + if (s2) + { + const int start = s2->getFirstGid(); + const int end = start + static_cast(s2->size()); + for (int f = start; f < end; f ++) + { + if (f < size) + mIndexedTilesets[f] = s2; + } + } + } +} + +void Map::clearIndexedTilesets() +{ + if (!mTilesetsIndexed) + return; + + mTilesetsIndexed = false; + delete [] mIndexedTilesets; + mIndexedTilesetsSize = 0; +} + +void Map::reduce() +{ +#ifdef USE_SDL2 + return; +#else + if (!mFringeLayer || mOpenGL != RENDER_SOFTWARE || + !config.getBoolValue("enableMapReduce")) + { + return; + } + + int cnt = 0; + for (int x = 0; x < mWidth; x ++) + { + for (int y = 0; y < mHeight; y ++) + { + bool correct(true); + bool dontHaveAlpha(false); + + FOR_EACH (LayersCIter, layeri, mLayers) + { + const MapLayer *const layer = *layeri; + if (x >= layer->mWidth || y >= layer->mHeight) + continue; + + Image *const img = layer->mTiles[x + y * layer->mWidth]; + if (img) + { + if (img->hasAlphaChannel() && img->isAlphaCalculated()) + { + if (!img->isAlphaVisible()) + { + dontHaveAlpha = true; + img->setAlphaVisible(false); + } + } + else if (img->mBounds.w > mapTileSize + || img->mBounds.h > mapTileSize) + { + correct = false; + img->setAlphaVisible(true); + break; + } + else if (!img->isHasAlphaChannel()) + { + dontHaveAlpha = true; + img->setAlphaVisible(false); + } + else if (img->hasAlphaChannel()) + { + const uint8_t *const arr = img->SDLgetAlphaChannel(); + if (!arr) + continue; + + bool bad(false); + bool stop(false); + int width; + const SubImage *const subImg + = dynamic_cast(img); + if (subImg) + width = subImg->mInternalBounds.w; + else + width = img->mBounds.w; + + for (int f = img->mBounds.x; + f < img->mBounds.x + img->mBounds.w; f ++) + { + for (int d = img->mBounds.y; + d < img->mBounds.y + img->mBounds.h; d ++) + { + const uint8_t chan = arr[f + d * width]; + if (chan != 255) + { + bad = true; + stop = true; + break; + } + } + if (stop) + break; + } + if (!bad) + { + dontHaveAlpha = true; + img->setAlphaVisible(false); + } + else + { + img->setAlphaVisible(true); + } + } + img->setAlphaCalculated(true); + } + } + if (!correct || !dontHaveAlpha) + continue; + + Layers::reverse_iterator ri = mLayers.rbegin(); + while (ri != mLayers.rend()) + { + const MapLayer *const layer = *ri; + if (x >= layer->mWidth || y >= layer->mHeight) + { + ++ ri; + continue; + } + + const Image *img = layer->mTiles[x + y * layer->mWidth]; + if (img && !img->isAlphaVisible()) + { // removing all down tiles + ++ ri; + while (ri != mLayers.rend()) + { + MapLayer *const layer2 = *ri; + const size_t pos = static_cast( + x + y * layer2->mWidth); + img = layer2->mTiles[pos]; + if (img) + { + layer2->mTiles[pos] = nullptr; + cnt ++; + } + ++ ri; + } + break; + } + ++ ri; + } + } + } + logger->log("tiles reduced: %d", cnt); +#endif +} + +void Map::redrawMap() +{ + mRedrawMap = true; +} + +void Map::addHeights(MapHeights *const heights) +{ + delete mHeights; + mHeights = heights; +} + +uint8_t Map::getHeightOffset(const int x, const int y) const +{ + if (!mHeights) + return 0; + return mHeights->getHeight(x, y); +} + +void Map::setMask(const int mask) +{ + if (mask != mMask) + mRedrawMap = true; + mMask = mask; +} + +void Map::setMusicFile(const std::string &file) +{ + setProperty("music", file); +} diff --git a/src/resources/map/map.h b/src/resources/map/map.h new file mode 100644 index 000000000..f0712be76 --- /dev/null +++ b/src/resources/map/map.h @@ -0,0 +1,540 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 RESOURCES_MAP_MAP_H +#define RESOURCES_MAP_MAP_H + +#include "position.h" + +#include "being/actor.h" + +#include "resources/map/properties.h" + +#include "listeners/configlistener.h" + +#include "render/renderers.h" + +#include +#include + +class Animation; +class AmbientLayer; +class Image; +class MapHeights; +class MapItem; +class MapLayer; +class ObjectsLayer; +class Particle; +class Resource; +class SimpleAnimation; +class SpecialLayer; +class Tileset; +class WalkLayer; + +typedef std::vector Tilesets; +typedef std::vector Layers; +typedef Layers::const_iterator LayersCIter; + +typedef std::vector > TilePairVector; +typedef TilePairVector::const_iterator TilePairVectorCIter; + +typedef std::vector AmbientLayerVector; +typedef AmbientLayerVector::const_iterator AmbientLayerVectorCIter; +typedef AmbientLayerVector::iterator AmbientLayerVectorIter; + +static const int mapTileSize = 32; + +/** + * A meta tile stores additional information about a location on a tile map. + * This is information that doesn't need to be repeated for each tile in each + * layer of the map. + */ +struct MetaTile final +{ + /** + * Constructor. + */ + MetaTile() : Fcost(0), Gcost(0), Hcost(0), whichList(0), + parentX(0), parentY(0), blockmask(0) + {} + + A_DELETE_COPY(MetaTile) + + // Pathfinding members + int Fcost; /**< Estimation of total path cost */ + int Gcost; /**< Cost from start to this location */ + int Hcost; /**< Estimated cost to goal */ + unsigned whichList; /**< No list, open list or closed list */ + int parentX; /**< X coordinate of parent tile */ + int parentY; /**< Y coordinate of parent tile */ + unsigned char blockmask; /**< Blocking properties of this tile */ +}; + +/** + * Animation cycle of a tile image which changes the map accordingly. + */ +class TileAnimation final +{ + public: + explicit TileAnimation(Animation *const ani); + + ~TileAnimation(); + + A_DELETE_COPY(TileAnimation) + + bool update(const int ticks = 1); + + void addAffectedTile(MapLayer *const layer, const int index) + { mAffected.push_back(std::make_pair(layer, index)); } + + private: + TilePairVector mAffected; + SimpleAnimation *mAnimation; + Image *mLastImage; +}; + +typedef std::map TileAnimationMap; +typedef TileAnimationMap::const_iterator TileAnimationMapCIter; + +/** + * A tile map. + */ +class Map final : public Properties, public ConfigListener +{ + public: + enum BlockType + { + BLOCKTYPE_NONE = -1, + BLOCKTYPE_WALL, + BLOCKTYPE_CHARACTER, + BLOCKTYPE_MONSTER, + BLOCKTYPE_AIR, + BLOCKTYPE_WATER, + BLOCKTYPE_GROUND, + BLOCKTYPE_GROUNDTOP, + NB_BLOCKTYPES + }; + + enum CollisionTypes + { + COLLISION_EMPTY = 0, // no collision + COLLISION_WALL = 1, // full collison + COLLISION_AIR = 2, // air units can walk + COLLISION_WATER = 3, // water units can walk + COLLISION_GROUNDTOP = 4, // no collision (chair, bed, etc) + COLLISION_MAX = 5 // count index + }; + + enum BlockMask + { + BLOCKMASK_WALL = 0x80, // 1000 0000 + BLOCKMASK_CHARACTER = 0x01, // 0000 0001 + BLOCKMASK_MONSTER = 0x02, // 0000 0010 + BLOCKMASK_AIR = 0x04, // 0000 0100 + BLOCKMASK_WATER = 0x08, // 0000 1000 + BLOCKMASK_GROUND = 0x10, // 0001 0000 + BLOCKMASK_GROUNDTOP = 0x20 // 0010 0000 + }; + + enum DebugType + { + MAP_NORMAL = 0, + MAP_DEBUG = 1, + MAP_SPECIAL = 2, + MAP_SPECIAL2 = 3, + MAP_SPECIAL3 = 4, + MAP_BLACKWHITE = 5 + }; + + /** + * Constructor, taking map and tile size as parameters. + */ + Map(const int width, const int height, + const int tileWidth, const int tileHeight); + + A_DELETE_COPY(Map) + + /** + * Destructor. + */ + ~Map(); + + /** + * Initialize ambient layers. Has to be called after all the properties + * are set. + */ + void initializeAmbientLayers(); + + /** + * Updates animations. Called as needed. + */ + void update(const int ticks = 1); + + /** + * Draws the map to the given graphics output. This method draws all + * layers, actors and overlay effects. + * + * TODO: For efficiency reasons, this method could take into account + * the clipping rectangle set on the Graphics object. However, + * currently the map is always drawn full-screen. + */ + void draw(Graphics *const graphics, int scrollX, int scrollY); + + /** + * Visualizes collision layer for debugging + */ + void drawCollision(Graphics *const graphics, + const int scrollX, const int scrollY, + const int debugFlags) const; + + /** + * Adds a layer to this map. The map takes ownership of the layer. + */ + void addLayer(MapLayer *const layer); + + /** + * Adds a tileset to this map. The map takes ownership of the tileset. + */ + void addTileset(Tileset *const tileset); + + /** + * Finds the tile set that a tile with the given global id is part of. + */ + const Tileset *getTilesetWithGid(const int gid) const A_WARN_UNUSED; + + /** + * Get tile reference. + */ + const MetaTile *getMetaTile(const int x, + const int y) const A_WARN_UNUSED; + + /** + * Marks a tile as occupied. + */ + void blockTile(const int x, const int y, const BlockType type); + + /** + * Gets walkability for a tile with a blocking bitmask. When called + * without walkmask, only blocks against colliding tiles. + */ + bool getWalk(const int x, const int y, + const unsigned char walkmask = BLOCKMASK_WALL + | BLOCKMASK_AIR | BLOCKMASK_WATER) const A_WARN_UNUSED; + + void setWalk(const int x, const int y, const bool walkable); + + unsigned char getBlockMask(const int x, const int y) const; + + /** + * Returns the width of this map in tiles. + */ + int getWidth() const A_WARN_UNUSED + { return mWidth; } + + /** + * Returns the height of this map in tiles. + */ + int getHeight() const A_WARN_UNUSED + { return mHeight; } + + /** + * Returns the tile width of this map. + */ + int getTileWidth() const A_WARN_UNUSED + { return mTileWidth; } + + /** + * Returns the tile height used by this map. + */ + int getTileHeight() const A_WARN_UNUSED + { return mTileHeight; } + + const std::string getMusicFile() const A_WARN_UNUSED; + + void setMusicFile(const std::string &file); + + const std::string getName() const A_WARN_UNUSED; + + /** + * Gives the map id based on filepath (ex: 009-1) + */ + const std::string getFilename() const A_WARN_UNUSED; + + /** + * Find a path from one location to the next. + */ + Path findPath(const int startX, const int startY, + const int destX, const int destY, + const unsigned char walkmask, + const int maxCost = 20) A_WARN_UNUSED; + + /** + * Adds a particle effect + */ + void addParticleEffect(const std::string &effectFile, + const int x, const int y, + const int w = 0, const int h = 0); + + /** + * Initializes all added particle effects + */ + void initializeParticleEffects(Particle *const particleEngine); + + /** + * Adds a tile animation to the map + */ + void addAnimation(const int gid, TileAnimation *const animation) + { mTileAnimations[gid] = animation; } + + void setDebugFlags(const int n) + { mDebugFlags = n; } + + int getDebugFlags() const A_WARN_UNUSED + { return mDebugFlags; } + + void addExtraLayer(); + + void saveExtraLayer() const; + + SpecialLayer *getTempLayer() const A_WARN_UNUSED + { return mTempLayer; } + + SpecialLayer *getSpecialLayer() const A_WARN_UNUSED + { return mSpecialLayer; } + + void setHasWarps(const bool n) + { mHasWarps = n; } + + bool getHasWarps() const A_WARN_UNUSED + { return mHasWarps; } + + std::string getUserMapDirectory() const A_WARN_UNUSED; + + void addPortal(const std::string &name, const int type, + const int x, const int y, const int dx, const int dy); + + void addRange(const std::string &name, const int type, + const int x, const int y, const int dx, const int dy); + + void addPortalTile(const std::string &name, const int type, + const int x, const int y); + + void updatePortalTile(const std::string &name, const int type, + const int x, const int y, + const bool addNew = true); + + const std::vector &getPortals() const A_WARN_UNUSED + { return mMapPortals; } + + /** + * Gets the tile animation for a specific gid + */ + const TileAnimation *getAnimationForGid(const int gid) + const A_WARN_UNUSED; + + void optionChanged(const std::string &value) override final; + + MapItem *findPortalXY(const int x, const int y) const A_WARN_UNUSED; + + int getActorsCount() const A_WARN_UNUSED + { return static_cast(mActors.size()); } + + void setPvpMode(const int mode); + + const ObjectsLayer* getObjectsLayer() const A_WARN_UNUSED + { return mObjects; } + + std::string getObjectData(const unsigned x, const unsigned y, + const int type) const A_WARN_UNUSED; + + void indexTilesets(); + + void clearIndexedTilesets(); + + void setActorsFix(const int x, const int y) + { mActorFixX = x; mActorFixY = y; } + + int getVersion() const A_WARN_UNUSED + { return mVersion; } + + void setVersion(const int n) + { mVersion = n; } + + void reduce(); + + void redrawMap(); + + bool empty() const A_WARN_UNUSED + { return mLayers.empty(); } + + void setCustom(const bool b) + { mCustom = b; } + + bool isCustom() const A_WARN_UNUSED + { return mCustom; } + + const std::map &getTileAnimations() + const A_WARN_UNUSED + { return mTileAnimations; } + + void setAtlas(Resource *const atlas) + { mAtlas = atlas; } + + const MetaTile *getMetaTiles() const + { return mMetaTiles; } + + WalkLayer *getWalkLayer() + { return mWalkLayer; } + + void setWalkLayer(WalkLayer *const layer) + { mWalkLayer = layer; } + + void addHeights(MapHeights *const heights); + + uint8_t getHeightOffset(const int x, const int y) const; + + void setMask(const int mask); + + protected: + friend class Actor; + friend class Minimap; + + /** + * Adds an actor to the map. + */ + Actors::iterator addActor(Actor *const actor); + + /** + * Removes an actor from the map. + */ + void removeActor(const Actors::iterator &iterator); + + private: + enum LayerType + { + FOREGROUND_LAYERS = 0, + BACKGROUND_LAYERS + }; + + /** + * Updates scrolling of ambient layers. Has to be called each game tick. + */ + void updateAmbientLayers(const float scrollX, const float scrollY); + + /** + * Draws the foreground or background layers to the given graphics output. + */ + void drawAmbientLayers(Graphics *const graphics, const LayerType type, + const int detail); + + /** + * Tells whether the given coordinates fall within the map boundaries. + */ + bool contains(const int x, const int y) const A_WARN_UNUSED; + + /** + * Blockmasks for different entities + */ + unsigned *mOccupation[NB_BLOCKTYPES]; + + int mWidth; + int mHeight; + int mTileWidth, mTileHeight; + int mMaxTileHeight; + MetaTile *mMetaTiles; + WalkLayer *mWalkLayer; + Layers mLayers; + Tilesets mTilesets; + Actors mActors; + bool mHasWarps; + + // debug flags + int mDebugFlags; + + // Pathfinding members + unsigned int mOnClosedList; + unsigned int mOnOpenList; + + // Overlay data + AmbientLayerVector mBackgrounds; + AmbientLayerVector mForegrounds; + float mLastAScrollX; + float mLastAScrollY; + + // Particle effect data + struct ParticleEffectData + { + ParticleEffectData() : + file(), + x(0), + y(0), + w(0), + h(0) + { + } + + std::string file; + int x; + int y; + int w; + int h; + }; + std::vector mParticleEffects; + + std::vector mMapPortals; + + std::map mTileAnimations; + + int mOverlayDetail; + float mOpacity; + RenderType mOpenGL; + int mPvp; + bool mTilesetsIndexed; + Tileset** mIndexedTilesets; + int mIndexedTilesetsSize; + int mActorFixX; + int mActorFixY; + int mVersion; + + SpecialLayer *mSpecialLayer; + SpecialLayer *mTempLayer; + ObjectsLayer *mObjects; + MapLayer *mFringeLayer; + + int mLastX; + int mLastY; + int mLastScrollX; + int mLastScrollY; + + int mDrawX; + int mDrawY; + int mDrawScrollX; + int mDrawScrollY; + int mMask; + Resource *mAtlas; + MapHeights *mHeights; + bool mRedrawMap; + bool mBeingOpacity; + bool mCustom; +}; + +#endif // RESOURCES_MAP_MAP_H diff --git a/src/resources/map/mapheights.cpp b/src/resources/map/mapheights.cpp new file mode 100644 index 000000000..1f93a0a84 --- /dev/null +++ b/src/resources/map/mapheights.cpp @@ -0,0 +1,41 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2014 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 "resources/map/mapheights.h" + +#include "debug.h" + +MapHeights::MapHeights(const int width, const int height) : + mWidth(width), + mHeight(height), + mTiles(new uint8_t[mWidth * mHeight]) +{ + memset(mTiles, 0, mWidth * mHeight); +} + +MapHeights::~MapHeights() +{ + delete [] mTiles; +} + +void MapHeights::setHeight(const int x, const int y, const uint8_t height) +{ + mTiles[x + y * mWidth] = height; +} diff --git a/src/resources/map/mapheights.h b/src/resources/map/mapheights.h new file mode 100644 index 000000000..89fc6a5c2 --- /dev/null +++ b/src/resources/map/mapheights.h @@ -0,0 +1,48 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2014 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 RESOURCES_MAP_MAPHEIGHTS_H +#define RESOURCES_MAP_MAPHEIGHTS_H + +#include "localconsts.h" + +class MapHeights final +{ + public: + friend class Map; + + MapHeights(const int width, const int height); + + A_DELETE_COPY(MapHeights) + + ~MapHeights(); + + void setHeight(const int x, const int y, const uint8_t height); + + uint8_t getHeight(const int x, const int y) const + { return mTiles[x + y * mWidth]; } + + private: + int mWidth; + int mHeight; + uint8_t *mTiles; +}; + +#endif // RESOURCES_MAP_MAPHEIGHTS_H diff --git a/src/resources/map/maplayer.cpp b/src/resources/map/maplayer.cpp new file mode 100644 index 000000000..dae071565 --- /dev/null +++ b/src/resources/map/maplayer.cpp @@ -0,0 +1,892 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 "resources/map/maplayer.h" + +#include "configuration.h" +#include "graphicsvertexes.h" + +#ifndef USE_OPENGL +#include "render/graphics.h" +#endif + +#include "being/localplayer.h" + +#include "render/graphics.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include "gui/font.h" +#include "gui/gui.h" + +#include "utils/delete2.h" +#include "utils/dtor.h" + +#include "debug.h" + +MapLayer::MapLayer(const int x, const int y, const int width, const int height, + const bool fringeLayer, const int mask): + mX(x), + mY(y), + mWidth(width), + mHeight(height), + mTiles(new Image*[mWidth * mHeight]), + mSpecialLayer(nullptr), + mTempLayer(nullptr), + mTempRows(), + mMask(mask), + mIsFringeLayer(fringeLayer), + mHighlightAttackRange(config.getBoolValue("highlightAttackRange")) +{ + std::fill_n(mTiles, mWidth * mHeight, static_cast(nullptr)); + + config.addListener("highlightAttackRange", this); +} + +MapLayer::~MapLayer() +{ + config.removeListener("highlightAttackRange", this); + CHECKLISTENERS + delete [] mTiles; + delete_all(mTempRows); + mTempRows.clear(); +} + +void MapLayer::optionChanged(const std::string &value) +{ + if (value == "highlightAttackRange") + { + mHighlightAttackRange = + config.getBoolValue("highlightAttackRange"); + } +} + +void MapLayer::setTile(const int x, const int y, Image *const img) +{ + mTiles[x + y * mWidth] = img; +} + +void MapLayer::draw(Graphics *const graphics, + int startX, int startY, int endX, int endY, + const int scrollX, const int scrollY, + const int debugFlags) const +{ + if (!player_node) + return; + + BLOCK_START("MapLayer::draw") + 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 * mapTileSize) - scrollX; + const int dy = (mY * mapTileSize) - scrollY + mapTileSize; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + for (int y = startY; y < endY; y++) + { + const int y32 = y * mapTileSize; + const int yWidth = y * mWidth; + + const int py0 = y32 + dy; + + Image **tilePtr = mTiles + static_cast(startX + yWidth); + + for (int x = startX; x < endX; x++, tilePtr++) + { + const int x32 = x * mapTileSize; + + int c = 0; + const Image *const img = *tilePtr; + if (img) + { + const int px = x32 + dx; + const int py = py0 - img->mBounds.h; + if (flag || img->mBounds.h <= mapTileSize) + { + 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->drawPattern(img, px, py, + width, img->mBounds.h); + } + } + } + + x += c; + } + } + BLOCK_END("MapLayer::draw") +} + +void MapLayer::drawSDL(Graphics *const graphics) +{ + BLOCK_START("MapLayer::drawSDL") + MapRows::const_iterator rit = mTempRows.begin(); + const MapRows::const_iterator rit_end = mTempRows.end(); + while (rit != rit_end) + { + MepRowImages *const images = &(*rit)->images; + MepRowImages::const_iterator iit = images->begin(); + const MepRowImages::const_iterator iit_end = images->end(); + while (iit != iit_end) + { + graphics->drawTileVertexes(*iit); + ++ iit; + } + ++ rit; + } + BLOCK_END("MapLayer::drawSDL") +} + +#ifdef USE_OPENGL +void MapLayer::updateSDL(const Graphics *const graphics, + int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const int debugFlags) +{ + BLOCK_START("MapLayer::updateSDL") + 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 * mapTileSize) - scrollX; + const int dy = (mY * mapTileSize) - scrollY + mapTileSize; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + for (int y = startY; y < endY; y++) + { + MapRowVertexes *const row = new MapRowVertexes(); + mTempRows.push_back(row); + + const Image *lastImage = nullptr; + ImageVertexes *imgVert = nullptr; + + const int yWidth = y * mWidth; + const int py0 = y * mapTileSize + dy; + Image **tilePtr = mTiles + static_cast(startX + yWidth); + + for (int x = startX; x < endX; x++, tilePtr++) + { + Image *const img = *tilePtr; + if (img) + { + const int px = x * mapTileSize + dx; + const int py = py0 - img->mBounds.h; + if (flag || img->mBounds.h <= mapTileSize) + { + if (lastImage != img) + { + imgVert = new ImageVertexes(); + imgVert->image = img; + row->images.push_back(imgVert); + lastImage = img; + } + graphics->calcTileSDL(imgVert, px, py); + } + } + } + } + BLOCK_END("MapLayer::updateSDL") +} + +void MapLayer::updateOGL(const Graphics *const graphics, + int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const int debugFlags) +{ + BLOCK_START("MapLayer::updateOGL") + 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 * mapTileSize) - scrollX; + const int dy = (mY * mapTileSize) - scrollY + mapTileSize; + const bool flag = (debugFlags != Map::MAP_SPECIAL + && debugFlags != Map::MAP_SPECIAL2); + + MapRowVertexes *const row = new MapRowVertexes(); + mTempRows.push_back(row); + Image *lastImage = nullptr; + ImageVertexes *imgVert = nullptr; + std::map imgSet; + + for (int y = startY; y < endY; y++) + { + const int yWidth = y * mWidth; + const int py0 = y * mapTileSize + dy; + Image **tilePtr = mTiles + static_cast(startX + yWidth); + for (int x = startX; x < endX; x++, tilePtr++) + { + Image *const img = *tilePtr; + if (img) + { + const int px = x * mapTileSize + dx; + const int py = py0 - img->mBounds.h; + const GLuint imgGlImage = img->mGLImage; + if (flag || img->mBounds.h <= mapTileSize) + { + if (!lastImage || lastImage->mGLImage != imgGlImage) + { + if (img->mBounds.w > mapTileSize) + imgSet.clear(); + + if (imgSet.find(imgGlImage) != imgSet.end()) + { + imgVert = imgSet[imgGlImage]; + } + else + { + if (lastImage) + imgSet[lastImage->mGLImage] = imgVert; + imgVert = new ImageVertexes(); + imgVert->ogl.init(); + imgVert->image = img; + row->images.push_back(imgVert); + } + } + lastImage = img; +// if (imgVert->image->mGLImage != lastImage->mGLImage) +// logger->log("wrong image draw"); + graphics->calcTileVertexes(imgVert, lastImage, px, py); + } + } + } + } + BLOCK_END("MapLayer::updateOGL") +} + +void MapLayer::drawOGL(Graphics *const graphics) +{ + BLOCK_START("MapLayer::drawOGL") + MapRows::const_iterator rit = mTempRows.begin(); + const MapRows::const_iterator rit_end = mTempRows.end(); +// int k = 0; + while (rit != rit_end) + { + const MepRowImages *const images = &(*rit)->images; + MepRowImages::const_iterator iit = images->begin(); + const MepRowImages::const_iterator iit_end = images->end(); + while (iit != iit_end) + { + graphics->drawTileVertexes(*iit); + ++ iit; +// k ++; + } + ++ rit; + } + BLOCK_END("MapLayer::drawOGL") +// logger->log("draws: %d", k); +} +#endif + +void MapLayer::drawFringe(Graphics *const graphics, int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const Actors *const actors, + const int debugFlags, const int yFix) const +{ + BLOCK_START("MapLayer::drawFringe") + if (!player_node || !mSpecialLayer || !mTempLayer) + { + BLOCK_END("MapLayer::drawFringe") + 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; + + ActorsCIter ai = actors->begin(); + const ActorsCIter ai_end = actors->end(); + + const int dx = (mX * mapTileSize) - scrollX; + const int dy = (mY * mapTileSize) - scrollY + mapTileSize; + + const int specialWidth = mSpecialLayer->mWidth; + const int specialHeight = mSpecialLayer->mHeight; + + for (int y = startY; y < endY; y++) + { + const int y32 = y * mapTileSize; + const int y32s = (y + yFix) * mapTileSize; + const int yWidth = y * mWidth; + + BLOCK_START("MapLayer::drawFringe drawmobs") + // If drawing the fringe layer, make sure all actors above this row of + // tiles have been drawn + while (ai != ai_end && (*ai)->getSortPixelY() <= y32s) + { + (*ai)->draw(graphics, -scrollX, -scrollY); + ++ ai; + } + BLOCK_END("MapLayer::drawFringe drawmobs") + + if (debugFlags == Map::MAP_SPECIAL3 + || debugFlags == Map::MAP_BLACKWHITE) + { + if (y < specialHeight) + { + const 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 * mapTileSize - scrollX; + + const MapItem *item = mSpecialLayer->mTiles[ptr + x]; + if (item) + { + item->draw(graphics, px1, py1, + mapTileSize, mapTileSize); + } + + item = mTempLayer->mTiles[ptr + x]; + if (item) + { + item->draw(graphics, px1, py1, + mapTileSize, mapTileSize); + } + } + } + } + else + { + const int py0 = y32 + dy; + const int py1 = y32 - scrollY; + + Image **tilePtr = mTiles + static_cast(startX + yWidth); + for (int x = startX; x < endX; x++, tilePtr++) + { + const int x32 = x * mapTileSize; + + const int px1 = x32 - scrollX; + int c = 0; + const Image *const 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 <= mapTileSize) + { + 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->drawPattern(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; + + const int ptr = y * specialWidth + x; + + for (int x1 = 0; x1 < c1 + 1; x1 ++) + { + const MapItem *const item1 + = mSpecialLayer->mTiles[ptr + x1]; + const MapItem *const item2 + = mTempLayer->mTiles[ptr + x1]; + if (item1 || item2) + { + const int px2 = px1 + (x1 * mapTileSize); + if (item1 && item1->mType != MapItem::EMPTY) + { + item1->draw(graphics, px2, py1, + mapTileSize, mapTileSize); + } + + if (item2 && item2->mType != MapItem::EMPTY) + { + item2->draw(graphics, px2, py1, + mapTileSize, mapTileSize); + } + } + } + } + x += c; + } + } + } + + // Draw any remaining actors + if (debugFlags != Map::MAP_SPECIAL3) + { + BLOCK_START("MapLayer::drawFringe drawmobs") + while (ai != ai_end) + { + (*ai)->draw(graphics, -scrollX, -scrollY); + ++ai; + } + BLOCK_END("MapLayer::drawFringe drawmobs") + if (mHighlightAttackRange && player_node) + { + const int px = player_node->getPixelX() + - scrollX - mapTileSize / 2; + const int py = player_node->getPixelY() - scrollY - mapTileSize; + const int attackRange = player_node->getAttackRange() + * mapTileSize; + + int x = px - attackRange; + int y = py - attackRange; + int w = 2 * attackRange + mapTileSize; + int h = w; + if (attackRange <= mapTileSize) + { + x -= mapTileSize / 2; + y -= mapTileSize / 2; + w += mapTileSize; + h += mapTileSize; + } + + if (userPalette) + { + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ATTACK_RANGE)); + graphics->fillRectangle(Rect(x, y, w, h)); + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ATTACK_RANGE_BORDER)); + graphics->drawRectangle(Rect(x, y, w, h)); + } + } + } + BLOCK_END("MapLayer::drawFringe") +} + +int MapLayer::getTileDrawWidth(const Image *img, + const int endX, + int &width) +{ + BLOCK_START("MapLayer::getTileDrawWidth") + const Image *const img1 = img; + int c = 0; + if (!img1) + { + width = 0; + BLOCK_END("MapLayer::getTileDrawWidth") + 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; + } + BLOCK_END("MapLayer::getTileDrawWidth") + return c; +} + +SpecialLayer::SpecialLayer(const int width, const int height) : + mWidth(width), + mHeight(height), + mTiles(new MapItem*[mWidth * mHeight]) +{ + std::fill_n(mTiles, mWidth * mHeight, static_cast(nullptr)); +} + +SpecialLayer::~SpecialLayer() +{ + for (int f = 0; f < mWidth * mHeight; f ++) + delete2(mTiles[f]) + delete [] mTiles; +} + +MapItem* SpecialLayer::getTile(const int x, const int y) const +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return nullptr; + } + return mTiles[x + y * mWidth]; +} + +void SpecialLayer::setTile(const int x, const int y, MapItem *const item) +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return; + } + + const int idx = x + y * mWidth; + delete mTiles[idx]; + if (item) + item->setPos(x, y); + mTiles[idx] = item; +} + +void SpecialLayer::setTile(const int x, const int y, const int type) +{ + if (x < 0 || x >= mWidth || + y < 0 || y >= mHeight) + { + return; + } + + const int idx = x + y * mWidth; + MapItem *const tile = mTiles[idx]; + if (tile) + { + tile->setType(type); + tile->setPos(x, y); + } + else + { + mTiles[idx] = new MapItem(type); + mTiles[idx]->setPos(x, y); + } +} + +void SpecialLayer::addRoad(const Path &road) +{ + FOR_EACH (Path::const_iterator, i, road) + { + const Position &pos = (*i); + MapItem *const item = getTile(pos.x, pos.y); + if (!item) + setTile(pos.x, pos.y, new MapItem(MapItem::ROAD)); + else + item->setType(MapItem::ROAD); + } +} + +void SpecialLayer::clean() const +{ + if (!mTiles) + return; + + for (int f = 0; f < mWidth * mHeight; f ++) + { + MapItem *const item = mTiles[f]; + if (item) + item->setType(MapItem::EMPTY); + } +} + +void SpecialLayer::draw(Graphics *const graphics, int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY) const +{ + BLOCK_START("SpecialLayer::draw") + 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 ++) + { + const int py = y * mapTileSize - scrollY; + const int y2 = y * mWidth; + for (int x = startX; x < endX; x ++) + { + const MapItem *const item = mTiles[x + y2]; + if (item) + { + item->draw(graphics, x * mapTileSize - scrollX, py, + mapTileSize, mapTileSize); + } + } + } + BLOCK_END("SpecialLayer::draw") +} + +MapItem::MapItem(): + mImage(nullptr), + mComment(), + mName(), + mType(EMPTY), + mX(-1), + mY(-1) +{ + setType(EMPTY); +} + +MapItem::MapItem(const int type): + mImage(nullptr), + mComment(), + mName(), + mType(type), + mX(-1), + mY(-1) +{ + setType(type); +} + +MapItem::MapItem(const int type, std::string comment): + mImage(nullptr), + mComment(comment), + mName(), + mType(type), + mX(-1), + mY(-1) +{ + setType(type); +} + +MapItem::MapItem(const int type, std::string comment, + const int x, const int y): + mImage(nullptr), + mComment(comment), + mName(), + mType(type), + mX(x), + mY(y) +{ + setType(type); +} + +MapItem::~MapItem() +{ + if (mImage) + { + mImage->decRef(); + mImage = nullptr; + } +} + +void MapItem::setType(const int type) +{ + std::string name; + mType = type; + if (mImage) + mImage->decRef(); + + switch (type) + { + case ARROW_UP: + name = "graphics/sprites/arrow_up.png"; + break; + case ARROW_DOWN: + name = "graphics/sprites/arrow_down.png"; + break; + case ARROW_LEFT: + name = "graphics/sprites/arrow_left.png"; + break; + case ARROW_RIGHT: + name = "graphics/sprites/arrow_right.png"; + break; + default: + break; + } + + if (!name.empty()) + { + ResourceManager *const resman = ResourceManager::getInstance(); + mImage = resman->getImage(name); + } + else + { + mImage = nullptr; + } +} + +void MapItem::setPos(const int x, const int y) +{ + mX = x; + mY = y; +} + +void MapItem::draw(Graphics *const graphics, const int x, const int y, + const int dx, const int dy) const +{ + BLOCK_START("MapItem::draw") + if (mImage) + graphics->drawImage(mImage, x, y); + + switch (mType) + { + case ROAD: + case CROSS: + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::ROAD_POINT)); + graphics->fillRectangle(Rect(x + dx / 3, y + dy / 3, + dx / 3, dy / 3)); + break; + case HOME: + { + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::HOME_PLACE)); + graphics->fillRectangle(Rect(x, y, dx, dy)); + graphics->setColor(userPalette->getColorWithAlpha( + UserPalette::HOME_PLACE_BORDER)); + graphics->drawRectangle(Rect(x, y, dx, dy)); + break; + } + default: + break; + } + if (!mName.empty() && mType != PORTAL && mType != EMPTY) + { + Font *const font = gui->getFont(); + if (font) + { + graphics->setColor(userPalette->getColor(UserPalette::BEING)); + font->drawString(graphics, mName, x, y); + } + } + BLOCK_END("MapItem::draw") +} + +ObjectsLayer::ObjectsLayer(const unsigned width, const unsigned height) : + mTiles(new MapObjectList*[width * height]), + mWidth(width), + mHeight(height) +{ + std::fill_n(mTiles, width * height, 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(const std::string &name, const int type, + const unsigned x, const 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 ++) + { + const unsigned idx1 = x + y1 * mWidth; + const 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(const unsigned x, const unsigned y) const +{ + if (x >= mWidth || y >= mHeight) + return nullptr; + return mTiles[x + y * mWidth]; +} + +MapRowVertexes::~MapRowVertexes() +{ + delete_all(images); + images.clear(); +} diff --git a/src/resources/map/maplayer.h b/src/resources/map/maplayer.h new file mode 100644 index 000000000..2c3fc23f1 --- /dev/null +++ b/src/resources/map/maplayer.h @@ -0,0 +1,328 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 RESOURCES_MAP_MAPLAYER_H +#define RESOURCES_MAP_MAPLAYER_H + +#include "position.h" +#include "main.h" + +#include "listeners/configlistener.h" + +#include "being/actor.h" + +#include +#include + +class Image; +class MapItem; +class SpecialLayer; +class ImageVertexes; + +typedef std::vector MepRowImages; + +class MapRowVertexes final +{ + public: + MapRowVertexes() : + images() + { + images.reserve(30); + } + + A_DELETE_COPY(MapRowVertexes) + + ~MapRowVertexes(); + + MepRowImages images; +}; + +class MapObject final +{ + public: + MapObject(const int type0, const std::string &data0) : + type(type0), data(data0) + { + } + + int type; + std::string data; +}; + +class MapObjectList final +{ + public: + MapObjectList() : + objects() + { + } + + A_DELETE_COPY(MapObjectList) + + std::vector objects; +}; + +/** + * A map layer. Stores a grid of tiles and their offset, and implements layer + * rendering. + */ +class MapLayer final: public ConfigListener +{ + public: + enum Type + { + TILES = 0, + COLLISION, + HEIGHTS + }; + + 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(const int x, const int y, const int width, const int height, + const bool isFringeLayer, const int mask); + + A_DELETE_COPY(MapLayer) + + /** + * Destructor. + */ + ~MapLayer(); + + /** + * Set tile image, with x and y in layer coordinates. + */ + void setTile(const int x, const int y, Image *const img); + + /** + * Set tile image with x + y * width already known. + */ + void setTile(const int index, Image *const 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 *const graphics, + int startX, int startY, int endX, int endY, + const int scrollX, const int scrollY, + const int mDebugFlags) const; + + void drawSDL(Graphics *const graphics); + +#ifdef USE_OPENGL + void drawOGL(Graphics *const graphics); + + void updateOGL(const Graphics *const graphics, + int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const int mDebugFlags); +#endif + + void updateSDL(const Graphics *const graphics, + int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const int mDebugFlags); + + void drawFringe(Graphics *const graphics, + int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY, + const Actors *const actors, + const int mDebugFlags, const int yFix) const; + + bool isFringeLayer() const A_WARN_UNUSED + { return mIsFringeLayer; } + + void setSpecialLayer(SpecialLayer *const val) + { mSpecialLayer = val; } + + void setTempLayer(SpecialLayer *const val) + { mTempLayer = val; } + + int getWidth() const A_WARN_UNUSED + { return mWidth; } + + int getHeight() const A_WARN_UNUSED + { return mHeight; } + + void optionChanged(const std::string &value) override final; + + static int getTileDrawWidth(const Image *img, + const int endX, + int &width) A_WARN_UNUSED; + + private: + int mX; + int mY; + int mWidth; + int mHeight; + Image **mTiles; + SpecialLayer *mSpecialLayer; + SpecialLayer *mTempLayer; + typedef std::vector MapRows; + MapRows mTempRows; + int mMask; + bool mIsFringeLayer; /**< Whether the actors are drawn. */ + bool mHighlightAttackRange; +}; + +class SpecialLayer final +{ + public: + friend class Map; + friend class MapLayer; + + SpecialLayer(const int width, const int height); + + A_DELETE_COPY(SpecialLayer) + + ~SpecialLayer(); + + void draw(Graphics *const graphics, int startX, int startY, + int endX, int endY, + const int scrollX, const int scrollY) const; + + MapItem* getTile(const int x, const int y) const A_WARN_UNUSED; + + void setTile(const int x, const int y, MapItem *const item); + + void setTile(const int x, const int y, const int type); + + void addRoad(const Path &road); + + void clean() const; + + private: + int mWidth; + int mHeight; + MapItem **mTiles; +}; + +class MapItem final +{ + 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, + PICKUP = 13, + NOPICKUP = 14, + SEPARATOR = 15 + }; + + MapItem(); + + explicit MapItem(const int type); + + MapItem(const int type, std::string comment); + + MapItem(const int type, std::string comment, const int x, const int y); + + A_DELETE_COPY(MapItem) + + ~MapItem(); + + int getType() const A_WARN_UNUSED + { return mType; } + + void setType(const int type); + + void setPos(const int x, const int y); + + int getX() const A_WARN_UNUSED + { return mX; } + + int getY() const A_WARN_UNUSED + { return mY; } + + const std::string &getComment() const A_WARN_UNUSED + { return mComment; } + + void setComment(const std::string &comment) + { mComment = comment; } + + const std::string &getName() const A_WARN_UNUSED + { return mName; } + + void setName(const std::string &name) + { mName = name; } + + void draw(Graphics *const graphics, const int x, const int y, + const int dx, const int dy) const; + + private: + Image *mImage; + std::string mComment; + std::string mName; + int mType; + int mX; + int mY; +}; + +class ObjectsLayer final +{ + public: + ObjectsLayer(const unsigned width, const unsigned height); + + A_DELETE_COPY(ObjectsLayer) + + ~ObjectsLayer(); + + void addObject(const std::string &name, const int type, + const unsigned x, const unsigned y, + unsigned dx, unsigned dy); + + MapObjectList *getAt(const unsigned x, + const unsigned y) const A_WARN_UNUSED; + private: + MapObjectList **mTiles; + unsigned mWidth; + unsigned mHeight; +}; + +#endif // RESOURCES_MAP_MAPLAYER_H diff --git a/src/resources/map/properties.h b/src/resources/map/properties.h new file mode 100644 index 000000000..7d3ff6ebf --- /dev/null +++ b/src/resources/map/properties.h @@ -0,0 +1,135 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 RESOURCES_MAP_PROPERTIES_H +#define RESOURCES_MAP_PROPERTIES_H + +#include "localconsts.h" + +#include +#include +#include + +/** + * A class holding a set of properties. + */ +class Properties +{ + public: + Properties() : + mProperties() + { + } + + /** + * Destructor. + */ + virtual ~Properties() + { } + + /** + * Get a map property. + * + * @param name The name of the property. + * @param def Default value, empty string by default. + * @return the value of the given property or the given default when it + * doesn't exist. + */ + const std::string getProperty(const std::string &name, + const std::string &def = "") + const A_WARN_UNUSED + { + const PropertyMap::const_iterator i = mProperties.find(name); + return (i != mProperties.end()) ? i->second : def; + } + + /** + * Gets a map property as a float. + * + * @param name The name of the property. + * @param def Default value, 0.0F by default. + * @return the value of the given property or the given default when it + * doesn't exist. + */ + float getFloatProperty(const std::string &name, + const float def = 0.0F) const A_WARN_UNUSED + { + const PropertyMap::const_iterator i = mProperties.find(name); + float ret = def; + if (i != mProperties.end()) + { + std::stringstream ss; + ss.str(i->second); + ss >> ret; + } + return ret; + } + + /** + * Gets a map property as a boolean. + * + * @param name The name of the property. + * @param def Default value, false by default. + * @return the value of the given property or the given default when it + * doesn't exist. + */ + bool getBoolProperty(const std::string &name, + const bool def = false) const A_WARN_UNUSED + { + const PropertyMap::const_iterator i = mProperties.find(name); + bool ret = def; + if (i != mProperties.end()) + { + if (i->second == "true") + ret = true; + if (i->second == "false") + ret = false; + } + return ret; + } + + /** + * Returns whether a certain property is available. + * + * @param name The name of the property. + * @return true when a property is defined, + * false otherwise. + */ + bool hasProperty(const std::string &name) const A_WARN_UNUSED + { return (mProperties.find(name) != mProperties.end()); } + + /** + * Set a map property. + * + * @param name The name of the property. + * @param value The value of the property. + */ + void setProperty(const std::string &name, const std::string &value) + { mProperties[name] = value; } + + + private: + typedef std::map PropertyMap; + PropertyMap mProperties; +}; + +#endif // RESOURCES_MAP_PROPERTIES_H diff --git a/src/resources/map/tileset.h b/src/resources/map/tileset.h new file mode 100644 index 000000000..312896c62 --- /dev/null +++ b/src/resources/map/tileset.h @@ -0,0 +1,79 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 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 RESOURCES_MAP_TILESET_H +#define RESOURCES_MAP_TILESET_H + +#include "resources/imageset.h" + +#include + +/** + * A tileset, which is basically just an image set but it stores a firstgid. + */ +class Tileset final : public ImageSet +{ + public: + /** + * Constructor. + */ + Tileset(Image *const img, const int w, const int h, const int firstGid, + const int margin, const int spacing): + ImageSet(img, w, h, margin, spacing), + mFirstGid(firstGid), + mProperties() + { + } + + A_DELETE_COPY(Tileset) + + /** + * Returns the first gid. + */ + int getFirstGid() const A_WARN_UNUSED + { return mFirstGid; } + + /** + * Set tileset property. + */ + void setProperties(const std::map &props) + { mProperties = props; } + + /** + * Returns property value. + */ + std::string getProperty(const std::string &name) A_WARN_UNUSED + { + const std::map::const_iterator + it = mProperties.find(name); + if (it == mProperties.end()) + return ""; + return mProperties[name]; + } + + private: + int mFirstGid; + + std::map mProperties; +}; + +#endif // RESOURCES_MAP_TILESET_H diff --git a/src/resources/map/walklayer.cpp b/src/resources/map/walklayer.cpp new file mode 100644 index 000000000..88f2fe8ef --- /dev/null +++ b/src/resources/map/walklayer.cpp @@ -0,0 +1,44 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2014 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 "resources/map/walklayer.h" + +#include "debug.h" + +WalkLayer::WalkLayer(const int width, const int height) : + Resource(), + mWidth(width), + mHeight(height), + mTiles(new int[width * height]) +{ + std::fill_n(mTiles, width * height, 0); +} + +WalkLayer::~WalkLayer() +{ + delete [] mTiles; +} + +int WalkLayer::getDataAt(const int x, const int y) const +{ + if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) + return 0; + return mTiles[x + y * mWidth]; +} diff --git a/src/resources/map/walklayer.h b/src/resources/map/walklayer.h new file mode 100644 index 000000000..a55cab434 --- /dev/null +++ b/src/resources/map/walklayer.h @@ -0,0 +1,48 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2014 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 RESOURCES_MAP_WALKLAYER_H +#define RESOURCES_MAP_WALKLAYER_H + +#include "resources/resource.h" + +#include "localconsts.h" + +class WalkLayer final : public Resource +{ + public: + WalkLayer(const int width, const int height); + + A_DELETE_COPY(WalkLayer) + + ~WalkLayer(); + + int *getData() + { return mTiles; } + + int getDataAt(const int x, const int y) const; + + private: + int mWidth; + int mHeight; + int *mTiles; +}; + +#endif // RESOURCES_MAP_WALKLAYER_H diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 44fc5f447..cf443ab16 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -26,8 +26,9 @@ #include "graphicsmanager.h" #include "logger.h" #include "main.h" -#include "map.h" -#include "tileset.h" + +#include "resources/map/map.h" +#include "resources/map/tileset.h" #include "resources/animation.h" #include "resources/beingcommon.h" diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h index 27cbd665b..fac78de18 100644 --- a/src/resources/mapreader.h +++ b/src/resources/mapreader.h @@ -25,8 +25,8 @@ #include "utils/xml.h" -#include "mapheights.h" -#include "maplayer.h" +#include "resources/map/mapheights.h" +#include "resources/map/maplayer.h" #include diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 8ed5d52f1..9c6e3bbb6 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -26,7 +26,8 @@ #include "configuration.h" #include "logger.h" #include "navigationmanager.h" -#include "walklayer.h" + +#include "resources/map/walklayer.h" #include "resources/atlasmanager.h" #include "resources/dye.h" diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp index 5265a1a96..77561d11c 100644 --- a/src/resources/spritedef.cpp +++ b/src/resources/spritedef.cpp @@ -23,7 +23,8 @@ #include "resources/spritedef.h" #include "logger.h" -#include "map.h" + +#include "resources/map/map.h" #include "resources/action.h" #include "resources/animation.h" diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp index b067a6de6..71832f559 100644 --- a/src/simpleanimation.cpp +++ b/src/simpleanimation.cpp @@ -23,7 +23,8 @@ #include "simpleanimation.h" #include "logger.h" -#include "map.h" + +#include "resources/map/map.h" #include "render/graphics.h" diff --git a/src/tileset.h b/src/tileset.h deleted file mode 100644 index 05508658a..000000000 --- a/src/tileset.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2014 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 TILESET_H -#define TILESET_H - -#include "resources/imageset.h" - -#include - -/** - * A tileset, which is basically just an image set but it stores a firstgid. - */ -class Tileset final : public ImageSet -{ - public: - /** - * Constructor. - */ - Tileset(Image *const img, const int w, const int h, const int firstGid, - const int margin, const int spacing): - ImageSet(img, w, h, margin, spacing), - mFirstGid(firstGid), - mProperties() - { - } - - A_DELETE_COPY(Tileset) - - /** - * Returns the first gid. - */ - int getFirstGid() const A_WARN_UNUSED - { return mFirstGid; } - - /** - * Set tileset property. - */ - void setProperties(const std::map &props) - { mProperties = props; } - - /** - * Returns property value. - */ - std::string getProperty(const std::string &name) A_WARN_UNUSED - { - const std::map::const_iterator - it = mProperties.find(name); - if (it == mProperties.end()) - return ""; - return mProperties[name]; - } - - private: - int mFirstGid; - - std::map mProperties; -}; - -#endif // TILESET_H diff --git a/src/walklayer.cpp b/src/walklayer.cpp deleted file mode 100644 index 5ca6e4c71..000000000 --- a/src/walklayer.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2014 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 "walklayer.h" - -#include "debug.h" - -WalkLayer::WalkLayer(const int width, const int height) : - Resource(), - mWidth(width), - mHeight(height), - mTiles(new int[width * height]) -{ - std::fill_n(mTiles, width * height, 0); -} - -WalkLayer::~WalkLayer() -{ - delete [] mTiles; -} - -int WalkLayer::getDataAt(const int x, const int y) const -{ - if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) - return 0; - return mTiles[x + y * mWidth]; -} diff --git a/src/walklayer.h b/src/walklayer.h deleted file mode 100644 index 0c5110f48..000000000 --- a/src/walklayer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2014 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 WALKLAYER_H -#define WALKLAYER_H - -#include "resources/resource.h" - -#include "localconsts.h" - -class WalkLayer final : public Resource -{ - public: - WalkLayer(const int width, const int height); - - A_DELETE_COPY(WalkLayer) - - ~WalkLayer(); - - int *getData() - { return mTiles; } - - int getDataAt(const int x, const int y) const; - - private: - int mWidth; - int mHeight; - int *mTiles; -}; - -#endif // WALKLAYER_H -- cgit v1.2.3-70-g09d2