diff options
-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; } |