summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}