summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Sehmisch <crush@themanaworld.org>2009-01-06 14:33:20 +0100
committerPhilipp Sehmisch <crush@themanaworld.org>2009-01-06 16:40:46 +0100
commit6b60673b0805fbab747924d1a0b6d9c66fc96f64 (patch)
treee40cc55a4d952bfb9bc89a41c3205c1d7bd90616
parent090b4893a57a1b7e9c83f7db043843d35016fcff (diff)
downloadmana-6b60673b0805fbab747924d1a0b6d9c66fc96f64.tar.gz
mana-6b60673b0805fbab747924d1a0b6d9c66fc96f64.tar.bz2
mana-6b60673b0805fbab747924d1a0b6d9c66fc96f64.tar.xz
mana-6b60673b0805fbab747924d1a0b6d9c66fc96f64.zip
Added support for animated tiles.
-rw-r--r--src/map.cpp51
-rw-r--r--src/map.h40
-rw-r--r--src/resources/mapreader.cpp90
-rw-r--r--src/utils/gettext.h44
4 files changed, 199 insertions, 26 deletions
diff --git a/src/map.cpp b/src/map.cpp
index 6170adef..abe87dfd 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -62,6 +62,34 @@ struct Location
MetaTile *tile;
};
+TileAnimation::TileAnimation(Animation *ani):
+ mAnimation(ani),
+ mLastUpdate(tick_time),
+ mLastImage(NULL)
+{
+}
+
+void TileAnimation::update()
+{
+ //update animation
+ mAnimation.update(tick_time - mLastUpdate);
+ mLastUpdate = tick_time;
+
+ // exchange images
+ Image *img = mAnimation.getCurrentImage();
+ if (img != mLastImage)
+ {
+ for (std::list<std::pair<MapLayer*, int> >::iterator i = mAffected.begin();
+ i != mAffected.end();
+ i++)
+ {
+ i->first->setTile(i->second, img);
+ }
+ mLastImage = img;
+ }
+
+}
+
MapLayer::MapLayer(int x, int y, int width, int height, bool isFringeLayer):
mX(x), mY(y),
mWidth(width), mHeight(height),
@@ -79,7 +107,7 @@ MapLayer::~MapLayer()
void MapLayer::setTile(int x, int y, Image *img)
{
- mTiles[x + y * mWidth] = img;
+ setTile(x + y * mWidth, img);
}
Image* MapLayer::getTile(int x, int y) const
@@ -155,6 +183,7 @@ Map::~Map()
delete_all(mLayers);
delete_all(mTilesets);
delete_all(mOverlays);
+ delete_all(mTileAnimations);
}
void Map::initializeOverlays()
@@ -216,6 +245,15 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY)
// Make sure sprites are sorted
mSprites.sort(spriteCompare);
+ //update animated tiles
+ for (std::map<int, TileAnimation*>::iterator iAni = mTileAnimations.begin();
+ iAni != mTileAnimations.end();
+ iAni++)
+ {
+ iAni->second->update();
+ }
+
+ // draw the game world
Layers::const_iterator layeri = mLayers.begin();
for (; layeri != mLayers.end(); ++layeri) {
(*layeri)->draw(graphics,
@@ -516,3 +554,14 @@ void Map::initializeParticleEffects(Particle* particleEngine)
particleEngine->addEffect(i->file, i->x, i->y);
}
}
+
+TileAnimation* Map::getAnimationForGid(int gid)
+{
+ std::map<int, TileAnimation*>::iterator i = mTileAnimations.find(gid);
+ if (i == mTileAnimations.end())
+ {
+ return NULL;
+ } else {
+ return i->second;
+ }
+}
diff --git a/src/map.h b/src/map.h
index 56183abf..81d0b629 100644
--- a/src/map.h
+++ b/src/map.h
@@ -28,6 +28,8 @@
#include "position.h"
#include "properties.h"
+#include "simpleanimation.h"
+
class AmbientOverlay;
class Graphics;
class Image;
@@ -64,6 +66,23 @@ struct MetaTile
};
/**
+ * Animation cycle of a tile image which changes the map accordingly.
+ */
+class TileAnimation
+{
+ public:
+ TileAnimation(Animation *ani);
+ void update();
+ void addAffectedTile(MapLayer *layer, int index)
+ { mAffected.push_back(std::make_pair(layer, index)); }
+ private:
+ std::list<std::pair<MapLayer*, int> > mAffected;
+ SimpleAnimation mAnimation;
+ int mLastUpdate;
+ Image* mLastImage;
+};
+
+/**
* A map layer. Stores a grid of tiles and their offset, and implements layer
* rendering.
*/
@@ -88,6 +107,11 @@ class MapLayer
void setTile(int x, int y, Image *img);
/**
+ * Set tile image with x + y * width already known.
+ */
+ void setTile(int index, Image *img) { mTiles[index] = img; }
+
+ /**
* Get tile image, with x and y in layer coordinates.
*/
Image *getTile(int x, int y) const;
@@ -225,8 +249,18 @@ class Map : public Properties
/**
* Initializes all added particle effects
*/
- void
- initializeParticleEffects(Particle* particleEngine);
+ void initializeParticleEffects(Particle* particleEngine);
+
+ /**
+ * Adds a tile animation to the map
+ */
+ void addAnimation(int gid, TileAnimation *animation)
+ { mTileAnimations[gid] = animation; }
+
+ /**
+ * Gets the tile animation for a specific gid
+ */
+ TileAnimation *getAnimationForGid(int gid);
private:
/**
@@ -270,6 +304,8 @@ class Map : public Properties
int y;
};
std::list<ParticleEffectData> particleEffects;
+
+ std::map<int, TileAnimation*> mTileAnimations;
};
#endif
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 835e52b3..4e116889 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -304,7 +304,8 @@ void MapReader::readProperties(xmlNodePtr node, Properties *props)
static void setTile(Map *map, MapLayer *layer, int x, int y, int gid)
{
const Tileset * const set = map->getTilesetWithGid(gid);
- if (layer) {
+ if (layer)
+ {
// Set regular tile on a layer
Image * const img = set ? set->get(gid - set->getFirstGid()) : 0;
layer->setTile(x, y, img);
@@ -407,6 +408,12 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
setTile(map, layer, x, y, gid);
+ TileAnimation* ani = map->getAnimationForGid(gid);
+ if (ani)
+ {
+ ani->addAffectedTile(layer, x + y * w);
+ }
+
x++;
if (x == w) {
x = 0; y++;
@@ -452,10 +459,12 @@ Tileset *MapReader::readTileset(xmlNodePtr node,
const std::string &path,
Map *map)
{
+ Tileset *set = NULL;
+
if (xmlHasProp(node, BAD_CAST "source"))
{
logger->log("Warning: External tilesets not supported yet.");
- return NULL;
+ return set;
}
const int firstGid = XML::getProperty(node, "firstgid", 0);
@@ -464,34 +473,69 @@ Tileset *MapReader::readTileset(xmlNodePtr node,
for_each_xml_child_node(childNode, node)
{
- if (!xmlStrEqual(childNode->name, BAD_CAST "image"))
- continue;
+ if (xmlStrEqual(childNode->name, BAD_CAST "image"))
+ {
+ const std::string source = XML::getProperty(childNode, "source", "");
- const std::string source = XML::getProperty(childNode, "source", "");
+ if (!source.empty())
+ {
+ std::string sourceStr = source;
+ sourceStr.erase(0, 3); // Remove "../"
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ Image* tilebmp = resman->getImage(sourceStr);
- if (!source.empty())
+ if (tilebmp)
+ {
+ set = new Tileset(tilebmp, tw, th, firstGid);
+ tilebmp->decRef();
+ }
+ else {
+ logger->log("Warning: Failed to load tileset (%s)",
+ source.c_str());
+ }
+ }
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "tile"))
{
- std::string sourceStr = source;
- sourceStr.erase(0, 3); // Remove "../"
+ for_each_xml_child_node(tileNode, childNode)
+ {
+ if (!xmlStrEqual(tileNode->name, BAD_CAST "properties")) continue;
- ResourceManager *resman = ResourceManager::getInstance();
- Image* tilebmp = resman->getImage(sourceStr);
+ int tileGID = firstGid + XML::getProperty(childNode, "id", 0);
- if (tilebmp)
- {
- Tileset *set = new Tileset(tilebmp, tw, th, firstGid);
- tilebmp->decRef();
- return set;
- }
- else {
- logger->log("Warning: Failed to load tileset (%s)",
- source.c_str());
+ // read tile properties to a map for simpler handling
+ std::map<std::string, int> tileProperties;
+ for_each_xml_child_node(propertyNode, tileNode)
+ {
+ if (!xmlStrEqual(propertyNode->name, BAD_CAST "property")) continue;
+ std::string name = XML::getProperty(propertyNode, "name", "");
+ int value = XML::getProperty(propertyNode, "value", 0);
+ tileProperties[name] = value;
+ logger->log("Tile Prop of %d \"%s\" = \"%d\"", tileGID, name.c_str(), value);
+ }
+
+ // create animation
+ if (!set) continue;
+
+ Animation *ani = new Animation();
+ for (int i = 0; ;i++)
+ {
+ std::map<std::string, int>::iterator iFrame, iDelay;
+ iFrame = tileProperties.find("animation-frame" + toString(i));
+ iDelay = tileProperties.find("animation-delay" + toString(i));
+ if (iFrame != tileProperties.end() && iDelay != tileProperties.end())
+ {
+ ani->addFrame(set->get(iFrame->second), iDelay->second, 0, 0);
+ } else {
+ break;
+ }
+ }
+ map->addAnimation(tileGID, new TileAnimation(ani));
+ logger->log("Animation length: %d", ani->getLength());
}
}
-
- // Only one image element expected
- break;
}
- return NULL;
+ return set;
}
diff --git a/src/utils/gettext.h b/src/utils/gettext.h
new file mode 100644
index 00000000..0cd9114b
--- /dev/null
+++ b/src/utils/gettext.h
@@ -0,0 +1,44 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_UTILS_GETTEXT_H
+#define _TMW_UTILS_GETTEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if ENABLE_NLS
+
+#include <libintl.h>
+
+#define _(s) ((char const *)gettext(s))
+#define N_(s) ((char const *)s)
+
+#else
+
+#define gettext(s) ((char const *)s)
+#define _(s) ((char const *)s)
+#define N_(s) ((char const *)s)
+
+#endif
+
+#endif