diff options
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/main.cpp | 12 | ||||
-rw-r--r-- | src/map.cpp | 7 | ||||
-rw-r--r-- | src/map.h | 5 | ||||
-rw-r--r-- | src/resources/image.cpp | 2 | ||||
-rw-r--r-- | src/resources/image.h | 2 | ||||
-rw-r--r-- | src/resources/mapreader.cpp | 229 | ||||
-rw-r--r-- | src/resources/mapreader.h | 57 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 71 |
9 files changed, 343 insertions, 46 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7cdf49a9..f7a8cfbb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,6 +78,8 @@ tmw_SOURCES = graphic/graphic.cpp \ net/win2linux.h \ resources/image.cpp \ resources/image.h \ + resources/mapreader.cpp \ + resources/mapreader.h \ resources/resource.cpp \ resources/resource.h \ resources/resourcemanager.cpp \ @@ -105,5 +107,5 @@ INCLUDES= $(all_includes) # the library search path. tmw_LDFLAGS = $(all_libraries) $(LIBSDL_RPATH) -lguichan_sdl -lguichan `pkg-config --libs libxml-2.0` tmw_CXXFLAGS = $(LIBSDL_CFLAGS) `pkg-config --cflags libxml-2.0` -tmw_LDADD = $(LIBSDL_LIBS) -lguichan_opengl -lguichan -lGL +tmw_LDADD = $(LIBSDL_LIBS) -lguichan_opengl -lguichan -lGL -lphysfs tmw_TARGET = ../tmw diff --git a/src/main.cpp b/src/main.cpp index 82f669d7..256b2943 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -114,10 +114,6 @@ class InitWarningListener : public gcn::ActionListener { */ void init_engine() { - // Initialize libxml2 and check for potential ABI mismatches between - // compiled version and the shared library actually used. - LIBXML_TEST_VERSION - // Initialize SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { std::cerr << "Could not initialize SDL: " << @@ -324,9 +320,15 @@ void exit_engine() /** Main */ int main(int argc, char *argv[]) { - init_engine(); + // Initialize libxml2 and check for potential ABI mismatches between + // compiled version and the shared library actually used. + LIBXML_TEST_VERSION; + + // Initialize PhysicsFS PHYSFS_init(argv[0]); + init_engine(); + SDL_Event event; while (state != EXIT) diff --git a/src/map.cpp b/src/map.cpp index 76fba34a..2c7524a4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -94,6 +94,13 @@ Map::Map(): tiles = new Tile[width * height]; } +Map::Map(int width, int height): + width(width), height(height), + onClosedList(1), onOpenList(2) +{ + tiles = new Tile[width * height]; +} + Map::~Map() { delete[] tiles; @@ -83,6 +83,11 @@ class Map Map(); /** + * Constructor that takes initial map size as parameters. + */ + Map(int width, int height); + + /** * Destructor. */ ~Map(); diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 3f2e9560..d30d6c92 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -198,7 +198,7 @@ Image* Image::load(const std::string &filePath, int flags) #endif } -Image* Image::load(const char* buffer, const unsigned int bufferSize) +Image* Image::load(const char* buffer, unsigned int bufferSize) { // Define our RWops structure SDL_RWops* rw = NULL; diff --git a/src/resources/image.h b/src/resources/image.h index 031f6645..ed1e0905 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -77,7 +77,7 @@ class Image : public Resource * @return <code>NULL</code> if the an error occurred, a * valid pointer otherwise. */ - static Image *load(const char* buffer, const unsigned int bufferSize); + static Image *load(const char* buffer, unsigned int bufferSize); /** * Frees the resources created by SDL. diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp new file mode 100644 index 00000000..7e604b93 --- /dev/null +++ b/src/resources/mapreader.cpp @@ -0,0 +1,229 @@ +/* + * The Mana World + * Copyright 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 + * 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 + * + * $Id$ + */ + +#include "mapreader.h" +#include "../log.h" + +#include <iostream> + +#define DEFAULT_TILE_WIDTH 32 +#define DEFAULT_TILE_HEIGHT 32 + + +Map *MapReader::readMap(const std::string &filename) +{ + std::cout << "Attempting to parse XML map data"; + + FILE* f = fopen(filename.c_str(), "rb"); + char *map_string; + + if (!f) { + error(std::string("Error: failed to open ") + filename); + } + + // Get size of file + fseek(f, 0, SEEK_END); + long size = ftell(f); + rewind(f); + + // Read file into character array + map_string = new char[size + 1]; + fread(map_string, 1, size, f); + map_string[size] = '\0'; + + fclose(f); + + xmlDocPtr doc = xmlReadMemory(map_string, size, NULL, NULL, 0); + delete[] map_string; + + if (doc) { + std::cout << "Looking for root node"; + xmlNodePtr node = xmlDocGetRootElement(doc); + + if (!node || !xmlStrEqual(node->name, BAD_CAST "map")) { + log("Warning: No map file (%s)!", filename.c_str()); + return NULL; + } + + std::cout << "Loading map from XML tree"; + return readMap(node, filename); + xmlFreeDoc(doc); + } else { + log("Error while parsing map file (%s)!", filename.c_str()); + } + + return NULL; +} + +Map* MapReader::readMap(xmlNodePtr node, const std::string &path) +{ + xmlChar *prop; + + prop = xmlGetProp(node, BAD_CAST "version"); + xmlFree(prop); + + int w = getProperty(node, "width", 0); + int h = getProperty(node, "height", 0); + int tilew = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); + int tileh = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); + int layerNr = 0; + Map* map = new Map(w, h); + + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (xmlStrEqual(node->name, BAD_CAST "tileset")) { + /* + Tileset* set = readTileset(node, path); + if (set) { + map->tilesets.push_back(set); + } + */ + } + else if (xmlStrEqual(node->name, BAD_CAST "layer")) { + log("- Loading layer %d", layerNr); + readLayer(node, map, layerNr); + layerNr++; + } + /* + else if (xmlStrEqual(node->name, BAD_CAST "object")) { + int x = getProperty(node, "x", 0); + int y = getProperty(node, "y", 0); + + // Spawn the object + prop = xmlGetProp(node, BAD_CAST "type"); + + log("- Adding %s at (%d, %d)", (char*)prop, x, y); + map->addObject(double(x) / tilew, double(y) / tileh, (char*)prop); + xmlFree(prop); + } + */ + } + + return map; +} + +void MapReader::readLayer(xmlNodePtr node, Map *map, int layer) +{ + // Ignored layer attributes + //int w = getProperty(node, "width", 0); // Map width is used + //int h = getProperty(node, "height", 0); // Map height is used + //xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + + node = node->xmlChildrenNode; + int x = 0; + int y = 0; + + // Load the tile data + /* + while (node != NULL) + { + if (xmlStrEqual(node->name, BAD_CAST "tile") && y < h) + { + xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + int gid = getProperty(node, "gid", -1); + + if (gid > -1) { + layer->setTile(Point(x, y), map->getTile(gid)); + } + else { + layer->setTile(Point(x, y), NULL); + } + + x++; + if (x == w) {x = 0; y++;} + } + + if (xmlStrEqual(node->name, BAD_CAST "data")) { + node = node->xmlChildrenNode; + } else { + node = node->next; + } + } + */ +} + +/* +Tileset* MapReader::readTileset(xmlNodePtr node, const std::string &path) +{ + Tileset* set = NULL; + + xmlChar* prop = xmlGetProp(node, BAD_CAST "source"); + if (prop) { + console.log(CON_LOG, CON_ALWAYS, + "Warning: External tilesets not supported yet."); + xmlFree(prop); + return NULL; + } + + int firstgid = getProperty(node, "firstgid", 0); + int tw = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); + int th = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); + int ts = getProperty(node, "spacing", 0); + xmlChar* name = xmlGetProp(node, BAD_CAST "name"); + + node = node->xmlChildrenNode; + + while (node != NULL) { + if (xmlStrEqual(node->name, BAD_CAST "image")) { + xmlChar* source = xmlGetProp(node, BAD_CAST "source"); + + if (source) { + char* srcname = get_filename((char*)source); + BITMAP* tilebmp = module->findBitmap(srcname); + + if (tilebmp) { + set = new Tileset(); + set->importTileBitmap(tilebmp, (char*)source, tw, th, ts); + set->setFirstGid(firstgid); + if (name) { set->setName((char*)name); } + xmlFree(source); + } else { + printf("Warning: Failed to load tileset %s (%s)\n", + srcname, (char*)name); + } + } + + break; + } + + node = node->next; + } + + xmlFree(name); + + return set; +} +*/ + +int MapReader::getProperty(xmlNodePtr node, const char* name, int def) +{ + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + int val = atoi((char*)prop); + xmlFree(prop); + return val; + } + else { + return def; + } +} diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h new file mode 100644 index 00000000..cf34f96f --- /dev/null +++ b/src/resources/mapreader.h @@ -0,0 +1,57 @@ +/* + * The Mana World + * Copyright 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 + * 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 + * + * $Id$ + */ + +#ifndef _INCLUDED_MAPREADER_H +#define _INCLUDED_MAPREADER_H + +#include "../map.h" +#include <libxml/parser.h> +#include <libxml/tree.h> + +/** + * Reader for XML map files (*.tmx) + */ +class MapReader +{ + public: + /** + * Read an XML map from a file. + */ + static Map *readMap(const std::string &filename); + + /** + * Read an XML map from a parsed XML tree. The path is used to find the + * location of referenced tileset images. + */ + static Map *readMap(xmlNodePtr node, const std::string &path); + + private: + /** + * Helper function that handler reading the map layers. + */ + static void readLayer(xmlNodePtr node, Map *map, int layer); + + static int getProperty(xmlNodePtr node, const char* name, int def); +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 1e4af1a2..13cbc4d6 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -33,7 +33,6 @@ #else #include <unistd.h> #include <dirent.h> - #endif ResourceEntry::ResourceEntry(): @@ -108,24 +107,27 @@ Resource* ResourceManager::get(const E_RESOURCE_TYPE &type, reinterpret_cast<Resource*>(Image::load(filePath, flags)); // If the object is invalid, try using PhysicsFS - if(resource == NULL) { - std::cout << "Check If Exists: " << filePath << std::endl; + if (resource == NULL) { + std::cout << "Check if exists: " << filePath << std::endl; // If the file is in the PhysicsFS search path - if(PHYSFS_exists(filePath.c_str()) != 0) { + if (PHYSFS_exists(filePath.c_str()) != 0) { // Open the file for read PHYSFS_file* imageFile = PHYSFS_openRead(filePath.c_str()); - std::cout << filePath << " - " << PHYSFS_fileLength(imageFile) << " bytes" << std::endl; + std::cout << filePath << " - " << + PHYSFS_fileLength(imageFile) << " bytes" << std::endl; // Read the file data into a buffer char* buffer = new char[PHYSFS_fileLength(imageFile)]; - PHYSFS_read(imageFile, buffer, 1, PHYSFS_fileLength(imageFile)); + PHYSFS_read(imageFile, buffer, 1, + PHYSFS_fileLength(imageFile)); // Cast the file to a valid resource - resource = reinterpret_cast<Resource*>(Image::load(buffer, PHYSFS_fileLength(imageFile))); + resource = reinterpret_cast<Resource*>(Image::load(buffer, + PHYSFS_fileLength(imageFile))); // Close the file PHYSFS_close(imageFile); - delete buffer; + delete[] buffer; } } @@ -189,19 +191,21 @@ void ResourceManager::searchAndAddZipFiles() struct _finddata_t findFileInfo; // Find the first zipped file - long handle = static_cast<long>(::_findfirst(searchString.c_str(), &findFileInfo)); - long file = handle; + long handle = + static_cast<long>(::_findfirst(searchString.c_str(), &findFileInfo)); + long file = handle; // Loop until all files we're searching for are found while (file >= 0) { // Define the file path string - std::string filePath = std::string("data/") + std::string(findFileInfo.name); + std::string filePath = std::string("data/") + + std::string(findFileInfo.name); + + std::cout << "Adding to PhysicsFS: " << findFileInfo.name << std::endl; // Add the zip file to our PhysicsFS search path PHYSFS_addToSearchPath(filePath.c_str(), 1); - std::cout << "Add To PhysicsFS: " << findFileInfo.name << std::endl; - // Find the next file file = ::_findnext(handle, &findFileInfo); } @@ -212,40 +216,31 @@ void ResourceManager::searchAndAddZipFiles() // Retrieve the current path char programPath[256]; getcwd(programPath, 256); + strncat(programPath, "/data", 256 - strlen(programPath) - 1); // Create our directory structure - DIR directory = opendir(programPath); + DIR *dir = opendir(programPath); - // If the directory is invalid - if (directory == NULL) { - // Return from the function + // Return if the directory is invalid + if (dir == NULL) { return; } - // Change the directory to the folder - chdir(programPath); + struct dirent *direntry; + while ((direntry = readdir(dir)) != NULL) { + char *ext = strstr(direntry->d_name, ".zip"); + if (ext != NULL && strcmp(ext, ".zip") == 0) { + // Define the file path string + std::string filePath = std::string(programPath) + + std::string("/") + std::string(direntry->d_name); - // Create the find file data structure - struct finddata_t* findFileInfo = &directory->dd_dta; - - // Find the first occurence of the requested file - long handle = static_cast<long>(findfirst("*", "*.zip")); - long file = handle; - - // Loop until all files we're searching for are found - while (file >= 0) { - // Define the file path string - std::string filePath = std::string("data/") + std::string(findFileInfo->name); + std::cout << "Adding to PhysicsFS: " << filePath << std::endl; - // Add the zip file to our PhysicsFS search path - PHYSFS_addToSearchPath(filePath.c_str(), 1); - - // Find the next file - file = findnext(handle, findFileInfo); + // Add the zip file to our PhysicsFS search path + PHYSFS_addToSearchPath(filePath.c_str(), 1); + } } - // Perform cleanup - findclose(handle); - closedir(directory); + closedir(dir); #endif } |