summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Sehmisch <crush@themanaworld.org>2009-12-25 16:06:38 +0100
committerPhilipp Sehmisch <crush@themanaworld.org>2009-12-25 16:06:38 +0100
commita31fce06e41ac33ca6ed12065644b314ceb4bcb3 (patch)
treefbe96aa70e14522e21223d92e892e1138363e9f5
parent4f14fde764bf0624700e88f9fa7d5d84d543aaec (diff)
downloadmana-client-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.gz
mana-client-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.bz2
mana-client-a31fce06e41ac33ca6ed12065644b314ceb4bcb3.tar.xz
mana-client-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)
-rw-r--r--src/map.cpp109
-rw-r--r--src/map.h26
-rw-r--r--src/resources/ambientlayer.cpp103
-rw-r--r--src/resources/ambientlayer.h60
-rw-r--r--src/resources/mapreader.cpp2
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());
diff --git a/src/map.h b/src/map.h
index b4a8c7af..f69d3d33 100644
--- a/src/map.h
+++ b/src/map.h
@@ -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;
}