diff options
author | Philipp Sehmisch <crush@themanaworld.org> | 2009-12-25 16:06:38 +0100 |
---|---|---|
committer | Philipp Sehmisch <crush@themanaworld.org> | 2009-12-25 16:06:38 +0100 |
commit | a31fce06e41ac33ca6ed12065644b314ceb4bcb3 (patch) | |
tree | fbe96aa70e14522e21223d92e892e1138363e9f5 /src | |
parent | 4f14fde764bf0624700e88f9fa7d5d84d543aaec (diff) | |
download | mana-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.gz mana-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.bz2 mana-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.xz mana-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.zip |
Added support for map background images which work exactly like overlays, just that they are drawn before the tiles instead of afterwards. Renamed overlays to foregrounds (but kept backward compatibility intact)
Diffstat (limited to 'src')
-rw-r--r-- | src/map.cpp | 109 | ||||
-rw-r--r-- | src/map.h | 26 | ||||
-rw-r--r-- | src/resources/ambientlayer.cpp | 103 | ||||
-rw-r--r-- | src/resources/ambientlayer.h | 60 | ||||
-rw-r--r-- | src/resources/mapreader.cpp | 2 |
5 files changed, 270 insertions, 30 deletions
diff --git a/src/map.cpp b/src/map.cpp index ba54dcd1..355b7811 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -31,7 +31,7 @@ #include "sprite.h" #include "tileset.h" -#include "resources/ambientoverlay.h" +#include "resources/ambientlayer.h" #include "resources/image.h" #include "resources/resourcemanager.h" @@ -207,19 +207,54 @@ Map::~Map() } delete_all(mLayers); delete_all(mTilesets); - delete_all(mOverlays); + delete_all(mForegrounds); + delete_all(mBackgrounds); delete_all(mTileAnimations); } -void Map::initializeOverlays() +void Map::initializeAmbientLayers() { ResourceManager *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("foreground" + toString(i) + "image")) + { + name = "foreground" + toString(i); + } + else if (hasProperty("overlay" + toString(i) + "image")) + { + name = "overlay" + toString(i); + } + else { + break; // the FOR loop + } + + Image *img = resman->getImage(getProperty(name + "image")); + const float speedX = getFloatProperty(name + "scrollX"); + const float speedY = getFloatProperty(name + "scrollY"); + const float parallax = getFloatProperty(name + "parallax"); + const bool keepRatio = getBoolProperty(name + "keepratio"); + + if (img) + { + mForegrounds.push_back( + new AmbientLayer(img, parallax, speedX, speedY, keepRatio)); + + // The AmbientLayer takes control over the image. + img->decRef(); + } + } + + + // search for "background*" in map properties for (int i = 0; - hasProperty("overlay" + toString(i) + "image"); + hasProperty("background" + toString(i) + "image"); i++) { - const std::string name = "overlay" + toString(i); + const std::string name = "background" + toString(i); Image *img = resman->getImage(getProperty(name + "image")); const float speedX = getFloatProperty(name + "scrollX"); @@ -229,10 +264,10 @@ void Map::initializeOverlays() if (img) { - mOverlays.push_back( - new AmbientOverlay(img, parallax, speedX, speedY, keepRatio)); + mBackgrounds.push_back( + new AmbientLayer(img, parallax, speedX, speedY, keepRatio)); - // The AmbientOverlay takes control over the image. + // The AmbientLayer takes control over the image. img->decRef(); } } @@ -265,23 +300,29 @@ void Map::update(int ticks) { iAni->second->update(ticks); } + } void Map::draw(Graphics *graphics, int scrollX, int scrollY) { + //Calculate range of tiles which are on-screen int endPixelY = graphics->getHeight() + scrollY + mTileHeight - 1; - - // TODO: Do this per-layer endPixelY += mMaxTileHeight - mTileHeight; - int startX = scrollX / mTileWidth; int startY = scrollY / mTileHeight; int endX = (graphics->getWidth() + scrollX + mTileWidth - 1) / mTileWidth; int endY = endPixelY / mTileHeight; - // Make sure sprites are sorted + // Make sure sprites are sorted ascending by Y-coordinate so that they overlap correctly mSprites.sort(spriteCompare); + // update scrolling of all ambient layers + updateAmbientLayers(scrollX, scrollY); + + // Draw backgrounds + drawAmbientLayers(graphics, BACKGROUND_LAYERS, scrollX, scrollY, + (int) config.getValue("OverlayDetail", 2)); + // draw the game world Layers::const_iterator layeri = mLayers.begin(); for (; layeri != mLayers.end(); ++layeri) @@ -309,7 +350,7 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY) si++; } - drawOverlay(graphics, scrollX, scrollY, + drawAmbientLayers(graphics, FOREGROUND_LAYERS, scrollX, scrollY, (int) config.getValue("OverlayDetail", 2)); } @@ -366,13 +407,9 @@ void Map::drawCollision(Graphics *graphics, int scrollX, int scrollY) } } -void Map::drawOverlay(Graphics *graphics, - float scrollX, float scrollY, int detail) +void Map::updateAmbientLayers(float scrollX, float scrollY) { - static int lastTick = tick_time; - - // Detail 0: no overlays - if (detail <= 0) return; + static int lastTick = tick_time; // static = only initialized at first call if (mLastScrollX == 0.0f && mLastScrollY == 0.0f) { @@ -382,21 +419,47 @@ void Map::drawOverlay(Graphics *graphics, } // Update Overlays - int timePassed = get_elapsed_time(lastTick); float dx = scrollX - mLastScrollX; float dy = scrollY - mLastScrollY; + int timePassed = get_elapsed_time(lastTick); - std::list<AmbientOverlay*>::iterator i; - for (i = mOverlays.begin(); i != mOverlays.end(); i++) + std::list<AmbientLayer*>::iterator i; + for (i = mBackgrounds.begin(); i != mBackgrounds.end(); i++) + { + (*i)->update(timePassed, dx, dy); + } + for (i = mForegrounds.begin(); i != mForegrounds.end(); i++) { (*i)->update(timePassed, dx, dy); } mLastScrollX = scrollX; mLastScrollY = scrollY; lastTick = tick_time; +} + +void Map::drawAmbientLayers(Graphics *graphics, LayerType type, + float scrollX, float scrollY, int detail) +{ + // Detail 0: no overlays + if (detail <= 0) return; + + // find out which layer list to draw + std::list<AmbientLayer*> *layers; + switch (type) + { + case FOREGROUND_LAYERS: + layers = &mForegrounds; + break; + case BACKGROUND_LAYERS: + layers = &mBackgrounds; + break; + default: + assert(false); // you noob, you added a new type of ambient layers without adding it to Map::drawAmbientLayers + break; + } // Draw overlays - for (i = mOverlays.begin(); i != mOverlays.end(); i++) + for (std::list<AmbientLayer*>::iterator i = layers->begin(); i != layers->end(); i++) { (*i)->draw(graphics, graphics->getWidth(), graphics->getHeight()); @@ -29,7 +29,7 @@ #include "properties.h" class Animation; -class AmbientOverlay; +class AmbientLayer; class Graphics; class Image; class MapLayer; @@ -172,10 +172,10 @@ class Map : public Properties ~Map(); /** - * Initialize map overlays. Should be called after all the properties + * Initialize ambient layers. Has to be called after all the properties * are set. */ - void initializeOverlays(); + void initializeAmbientLayers(); /** * Updates animations. Called as needed. @@ -295,10 +295,22 @@ class Map : public Properties TileAnimation *getAnimationForGid(int gid) const; private: + + enum LayerType + { + FOREGROUND_LAYERS, + BACKGROUND_LAYERS + }; + /** - * Draws the overlay graphic to the given graphics output. + * Updates scrolling of ambient layers. Has to be called each game tick. */ - void drawOverlay(Graphics *graphics, float scrollX, float scrollY, + void updateAmbientLayers(float scrollX, float scrollY); + + /** + * Draws the foreground or background layers to the given graphics output. + */ + void drawAmbientLayers(Graphics *graphics, LayerType type, float scrollX, float scrollY, int detail); /** @@ -323,7 +335,8 @@ class Map : public Properties int mOnClosedList, mOnOpenList; // Overlay data - std::list<AmbientOverlay*> mOverlays; + std::list<AmbientLayer*> mBackgrounds; + std::list<AmbientLayer*> mForegrounds; float mLastScrollX; float mLastScrollY; @@ -337,6 +350,7 @@ class Map : public Properties std::list<ParticleEffectData> particleEffects; std::map<int, TileAnimation*> mTileAnimations; + }; #endif diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp new file mode 100644 index 00000000..92895bc2 --- /dev/null +++ b/src/resources/ambientlayer.cpp @@ -0,0 +1,103 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "resources/ambientlayer.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" +#include "graphics.h" + +AmbientLayer::AmbientLayer(Image *img, float parallax, + float speedX, float speedY, bool keepRatio): + mImage(img), mParallax(parallax), + mPosX(0), mPosY(0), + mSpeedX(speedX), mSpeedY(speedY), + mKeepRatio(keepRatio) +{ + + if (keepRatio && !mImage->isAnOpenGLOne() + && defaultScreenWidth != 0 + && defaultScreenHeight != 0 + && graphics->getWidth() != defaultScreenWidth + && graphics->getHeight() != defaultScreenHeight) + { + // Rescale the overlay to keep the ratio as if we were on + // the default resolution... + Image *rescaledOverlay = mImage->SDLgetScaledImage( + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + + if (rescaledOverlay) + { + // Replace the resource with the new one... + std::string idPath = mImage->getIdPath() + "_rescaled"; + ResourceManager::getInstance()->addResource(idPath, rescaledOverlay); + mImage = rescaledOverlay; + } + else + mImage->incRef(); + } + else + mImage->incRef(); +} + +AmbientLayer::~AmbientLayer() +{ + mImage->decRef(); +} + +void AmbientLayer::update(int timePassed, float dx, float dy) +{ + // Self scrolling of the overlay + mPosX -= mSpeedX * timePassed / 10; + mPosY -= mSpeedY * timePassed / 10; + + // Parallax scrolling + mPosX += dx * mParallax; + mPosY += dy * mParallax; + + int imgW = mImage->getWidth(); + int imgH = mImage->getHeight(); + + // Wrap values + while (mPosX > imgW) + mPosX -= imgW; + while (mPosX < 0) + mPosX += imgW; + + while (mPosY > imgH) + mPosY -= imgH; + while (mPosY < 0) + mPosY += imgH; +} + +void AmbientLayer::draw(Graphics *graphics, int x, int y) +{ + if (!mImage->isAnOpenGLOne() || !mKeepRatio) + graphics->drawImagePattern(mImage, + (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY); + else + graphics->drawRescaledImagePattern(mImage, + (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY, + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + +} diff --git a/src/resources/ambientlayer.h b/src/resources/ambientlayer.h new file mode 100644 index 00000000..43801bdb --- /dev/null +++ b/src/resources/ambientlayer.h @@ -0,0 +1,60 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef RESOURCES_AMBIENTOVERLAY_H +#define RESOURCES_AMBIENTOVERLAY_H + +class Graphics; +class Image; + +class AmbientLayer +{ + public: + /** + * Constructor. + * + * @param img the image this overlay displays + * @param parallax scroll factor based on camera position + * @param speedX scrolling speed in x-direction + * @param speedY scrolling speed in y-direction + * @param keepRatio rescale the image to keep + * the same ratio than in 800x600 resolution mode. + */ + AmbientLayer(Image *img, float parallax, + float speedX, float speedY, bool keepRatio = false); + + ~AmbientLayer(); + + void update(int timePassed, float dx, float dy); + + void draw(Graphics *graphics, int x, int y); + + private: + Image *mImage; + float mParallax; + float mPosX; /**< Current layer X position. */ + float mPosY; /**< Current layer Y position. */ + float mSpeedX; /**< Scrolling speed in X direction. */ + float mSpeedY; /**< Scrolling speed in Y direction. */ + bool mKeepRatio; /**< Keep overlay ratio on every resolution */ +}; + +#endif diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 1e0eee50..291dd732 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -280,7 +280,7 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path) } } - map->initializeOverlays(); + map->initializeAmbientLayers(); return map; } |