diff options
Diffstat (limited to 'src/resources/mapreader.cpp')
-rw-r--r-- | src/resources/mapreader.cpp | 155 |
1 files changed, 109 insertions, 46 deletions
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index b812b2ce..c4cb7447 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -1,39 +1,39 @@ /* * The Mana World - * Copyright 2004 The Mana World Development Team + * Copyright (C) 2004 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 + * 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. * - * The Mana World is distributed in the hope that it will be useful, + * 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 The Mana World; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mapreader.h" - #include <cassert> #include <iostream> #include <zlib.h> -#include "resourcemanager.h" +#include "animation.h" #include "image.h" +#include "mapreader.h" +#include "resourcemanager.h" #include "../log.h" #include "../map.h" #include "../tileset.h" #include "../utils/base64.h" -#include "../utils/tostring.h" +#include "../utils/stringutils.h" #include "../utils/xml.h" const unsigned int DEFAULT_TILE_WIDTH = 32; @@ -205,14 +205,11 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path) // Take the filename off the path const std::string pathDir = path.substr(0, path.rfind("/") + 1); - //xmlChar *prop = xmlGetProp(node, BAD_CAST "version"); - //xmlFree(prop); - const int w = XML::getProperty(node, "width", 0); const int h = XML::getProperty(node, "height", 0); - const int tw = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); - const int th = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); - Map *map = new Map(w, h, tw, th); + const int tilew = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); + const int tileh = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); + Map *map = new Map(w, h, tilew, tileh); for_each_xml_child_node(childNode, node) { @@ -233,6 +230,12 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path) } else if (xmlStrEqual(childNode->name, BAD_CAST "objectgroup")) { + // The object group offset is applied to each object individually + const int tileOffsetX = XML::getProperty(childNode, "x", 0); + const int tileOffsetY = XML::getProperty(childNode, "y", 0); + const int offsetX = tileOffsetX * tilew; + const int offsetY = tileOffsetY * tileh; + for_each_xml_child_node(objectNode, childNode) { if (xmlStrEqual(objectNode->name, BAD_CAST "object")) @@ -253,7 +256,8 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path) const int objY = XML::getProperty(objectNode, "y", 0); logger->log("- Loading object name: %s type: %s at %d:%d", - objName.c_str(), objType.c_str(), objX, objY); + objName.c_str(), objType.c_str(), + objX, objY); if (objType == "PARTICLE_EFFECT") { @@ -262,7 +266,9 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path) continue; } - map->addParticleEffect(objName, objX, objY); + map->addParticleEffect(objName, + objX + offsetX, + objY + offsetY); } else { @@ -297,7 +303,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); @@ -313,12 +320,12 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) // Layers are not necessarily the same size as the map const int w = XML::getProperty(node, "width", map->getWidth()); const int h = XML::getProperty(node, "height", map->getHeight()); - const int offsetX = XML::getProperty(node, "xoffset", 0); - const int offsetY = XML::getProperty(node, "yoffset", 0); + const int offsetX = XML::getProperty(node, "x", 0); + const int offsetY = XML::getProperty(node, "y", 0); const std::string name = XML::getProperty(node, "name", ""); - const bool isFringeLayer = (name == "Fringe"); - const bool isCollisionLayer = (name == "Collision"); + const bool isFringeLayer = (name.substr(0,6) == "Fringe"); + const bool isCollisionLayer = (name.substr(0,9) == "Collision"); MapLayer *layer = 0; @@ -361,7 +368,7 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) while (*charStart) { if (*charStart != ' ' && *charStart != '\t' && - *charStart != '\n') + *charStart != '\n') { *charIndex = *charStart; charIndex++; @@ -401,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++; @@ -446,46 +459,96 @@ Tileset *MapReader::readTileset(xmlNodePtr node, const std::string &path, Map *map) { + int firstGid = XML::getProperty(node, "firstgid", 0); + XML::Document* doc = NULL; + Tileset *set = NULL; + if (xmlHasProp(node, BAD_CAST "source")) { - logger->log("Warning: External tilesets not supported yet."); - return NULL; + std::string filename = XML::getProperty(node, "source", ""); + while (filename.substr(0, 3) == "../") + filename.erase(0, 3); // Remove "../" + doc = new XML::Document(filename); + node = doc->rootNode(); + firstGid += XML::getProperty(node, "firstgid", 0); } - const int firstGid = XML::getProperty(node, "firstgid", 0); const int tw = XML::getProperty(node, "tilewidth", map->getTileWidth()); const int th = XML::getProperty(node, "tileheight", map->getTileHeight()); 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; + } + } + + if (ani->getLength() > 0) + { + map->addAnimation(tileGID, new TileAnimation(ani)); + logger->log("Animation length: %d", ani->getLength()); + } else { + delete ani; + } } } - - // Only one image element expected - break; } - return NULL; + delete doc; + + return set; } |