Skip to content

Commit

Permalink
Additional search paths for map assets can be added with AddSearchPath()
Browse files Browse the repository at this point in the history
Loader now searches all additional paths for assets on asset load failure
Updated year in copyright notice
Updated readme
  • Loading branch information
fallahn committed Jan 2, 2014
1 parent 02e1386 commit dc220b2
Show file tree
Hide file tree
Showing 18 changed files with 149 additions and 67 deletions.
45 changes: 29 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format

The zlib license has been used to make this software fully compatible
Expand Down Expand Up @@ -40,31 +40,30 @@ Supports orthogonal maps
Supports isometric maps
Supports conversion between orthogonal and isometric world coords
Parses all types of layers (normal, object and image), layer properties
Parses all type of object, object shapes, types, properties
Option to draw debug output of objects, grid and object names
Parses all types of object, object shapes, types, properties
Option to draw debug output of objects and tile grid
Supports multiple tile sets, including tsx files
Supports all layer encoding and compression: base64, csv, zlib, gzip and xml (requires zlib library, see /lib directory)
Quad tree partitioning / querying of map object data
FAST rendering with sf::VertexArray

Optional utility functions for converting tmx map objects into box2D body data


What's not supported / limitations
----------------------------------

Parsing of individual tile properties
Flipping / rotation of sprites
Flipping / rotation of map objects
Staggered isometric maps
Tile set images must be in the same directory as tmx/tsx files
To display object names when drawing object debug shapes then you must provide a font
and update MapObject.h



Usage
-----

First download and link the zlib library which matches your compiler and link it to your
project, then add the map loader .cpp files to your project/command line.
First download the zlib library which matches your compiler and link it to your
project, then add the map loader .cpp files to your project/command line. Only
add the tmx2box2d files if you are using box2D for physics and wish to convert
map object data to box2D physics bodies.


To quickly get up and running create an instance of the MapLoader class
Expand All @@ -81,8 +80,12 @@ and draw it in your main loop


Note that the constructor takes a path to the directory containing the map files as a parameter (with
or without the trailing '/') so that you only need pass the map name to MapLoader::Load(). Currently
all map files (tmx, tsx, images etc) must be in the directory passed to the constructor.
or without the trailing '/') so that you only need pass the map name to MapLoader::Load().If you have
images and/or tileset data in another directory you may add it with:

ml.AddSearchPath(path);

*before* attempting to load the map file.

New maps can be loaded simply by calling the load function again, existing maps will be automatically
unloaded. MapLoader::Load() also returns true on success and false on failure, to aid running the function
Expand Down Expand Up @@ -139,7 +142,17 @@ This returns a vector of pointers to MapObjects contained within any quads which
by your sprite's bounds. You can then proceed to perform any collision testing as usual.


For more detailed examples see the source for the included demos.
Some utility functions are providied in tmx2box2d.h/cpp. If you use box2D for physics then add these
files to you project and then create box2D physics bodies using:

tmx::BodyCreator::Add(mapObject, b2World);

where b2World is a pointer to a valid box2D physics world.



For more detailed examples see the source for the included demos, and the wiki on github:
https://github.com/fallahn/sfml-tmxloader/wiki



Expand All @@ -148,8 +161,8 @@ Requirements

pugixml (included)
zlib (http://zlib.net/)
SFML 2.0 (http://sfml-dev.org)
C++11 compiler support (tested with VS11 and GCC4.7)
SFML 2.x (http://sfml-dev.org)
Minimal C++11 compiler support (tested with VS11 and GCC4.7)


Revision History
Expand Down
2 changes: 1 addition & 1 deletion examples/Benchmark.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion examples/Box2D.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
4 changes: 2 additions & 2 deletions examples/DrawMapWithDebug.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down Expand Up @@ -37,7 +37,7 @@ int main()
sf::RenderWindow renderWindow(sf::VideoMode(800u, 600u), "TMX Loader");

//create map loader and load map
tmx::MapLoader ml("maps/");
tmx::MapLoader ml("maps\\");
ml.Load("desert.tmx");

bool showDebug = false;
Expand Down
2 changes: 1 addition & 1 deletion examples/IsometricWithConvertCoords.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion examples/MapWithQuadTree.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion include/DebugShape.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion include/Helpers.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
The zlib license has been used to make this software fully compatible
with SFML. See http://www.sfml-dev.org/license.php
Expand Down
10 changes: 6 additions & 4 deletions include/tmx/MapLoader.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down Expand Up @@ -52,6 +52,8 @@ namespace tmx
~MapLoader();
//loads a given tmx file, returns false on failure
bool Load(const std::string& mapFile);
//adds give path to list of directories to search for assets, such as tile sets
void AddSearchPath(const std::string& path);
//updates the map's quad tree. Not necessary when not querying the quad tree
//root area is the are covered by root node, for example the screen size
void UpdateQuadTree(const sf::FloatRect& rootArea);
Expand Down Expand Up @@ -90,10 +92,9 @@ namespace tmx
std::map<std::string, std::string> m_properties;

mutable sf::FloatRect m_bounds; //bounding area of tiles visible on screen
std::string m_mapDirectory; //directory relative to executable containing map files and images
std::vector<std::string> m_searchPaths; //additional paths to search for tileset files

std::vector<MapLayer> m_layers; //layers of map, including image and object layers
//std::vector<sf::Texture> m_tileTextures;
std::vector<sf::Texture> m_imageLayerTextures;
std::vector<sf::Texture> m_tilesetTextures; //textures created from complete sets used when drawing vertex arrays
struct TileInfo //holds texture coords and tileset id of a tile
Expand Down Expand Up @@ -128,6 +129,7 @@ namespace tmx
void m_ParseLayerProperties(const pugi::xml_node& propertiesNode, MapLayer& destLayer);
void m_SetIsometricCoords(MapLayer& layer);
void m_DrawLayer(sf::RenderTarget& rt, MapLayer& layer, bool debug = false);
std::string m_FileFromPath(const std::string& path);

//sf::drawable
void draw(sf::RenderTarget& rt, sf::RenderStates states) const;
Expand All @@ -141,7 +143,7 @@ namespace tmx
void m_CreateDebugGrid(void);

//caches loaded images to prevent loading the same tileset more than once
sf::Image& m_LoadImage(std::string path);
sf::Image& m_LoadImage(const std::string& imageName);
std::map<std::string, std::shared_ptr<sf::Image> >m_cachedImages;
bool m_failedImage;
};
Expand Down
2 changes: 1 addition & 1 deletion include/tmx/MapObject.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion include/tmx/QuadTreeNode.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
2 changes: 1 addition & 1 deletion include/tmx/tmx2box2d.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
4 changes: 2 additions & 2 deletions maps/desert.tmx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="40" height="40" tilewidth="32" tileheight="32">
<tileset firstgid="1" source="desert.tsx"/>
<tileset firstgid="1" source="/usr/local/desert.tsx"/>
<tileset firstgid="49" name="Sewer" tilewidth="24" tileheight="24">
<image source="sewer_tileset.png" trans="ff00ff" width="192" height="217"/>
<image source="c:\some path\sewer_tileset.png" trans="ff00ff" width="192" height="217"/>
<tile id="33">
<properties>
<property name="tileprop" value="sd"/>
Expand Down
2 changes: 1 addition & 1 deletion src/DebugShape.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down
72 changes: 55 additions & 17 deletions src/MapLoaderPrivate.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************
Matt Marchant 2013
Matt Marchant 2013 - 2014
SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format
http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html
Expand Down Expand Up @@ -128,16 +128,26 @@ bool MapLoader::m_ParseTileSets(const pugi::xml_node& mapNode)
if(tileset.attribute("source"))
{
//try loading tsx
std::string path = m_mapDirectory + tileset.attribute("source").as_string();
std::string file = m_FileFromPath(tileset.attribute("source").as_string());
std::string path;
pugi::xml_document tsxDoc;
pugi::xml_parse_result result = tsxDoc.load_file(path.c_str());
pugi::xml_parse_result result;

for(auto& p : m_searchPaths)
{
path = p + file;
result = tsxDoc.load_file(path.c_str());
if(result) break;
}
if(!result)
{
std::cerr << "Failed to open external tsx document: " << path << std::endl;
std::cerr << "Reason: " << result.description() << std::endl;
std::cerr << "Make sure to add any external paths with AddSearchPath()" << std::endl;
m_Unload(); //purge any partially loaded data
return false;
}

//try parsing tileset node
pugi::xml_node ts = tsxDoc.child("tileset");

Expand Down Expand Up @@ -180,14 +190,12 @@ bool MapLoader::m_ProcessTiles(const pugi::xml_node& tilesetNode)
}

//process image from disk
std::string imagePath;
imagePath = m_mapDirectory + imageNode.attribute("source").as_string();

sf::Image sourceImage = m_LoadImage(imagePath);
std::string imageName = m_FileFromPath(imageNode.attribute("source").as_string());
sf::Image sourceImage = m_LoadImage(imageName);
if(m_failedImage)
{
std::cerr << "Failed to load image at " << imagePath << std::endl;
std::cerr << "Please check image exists and path is relative to tmx document." << std::endl;
std::cerr << "Failed to load image " << imageName << std::endl;
std::cerr << "Please check image exists and add any external paths with AddSearchPath()" << std::endl;
return false;
}

Expand Down Expand Up @@ -232,7 +240,7 @@ bool MapLoader::m_ProcessTiles(const pugi::xml_node& tilesetNode)
}
}

std::cerr << "Processed " << imagePath << std::endl;
std::cerr << "Processed " << imageName << std::endl;
return true;
}

Expand Down Expand Up @@ -649,12 +657,12 @@ bool MapLoader::m_ParseImageLayer(const pugi::xml_node& imageLayerNode)
return false;
}

std::string imageName = m_mapDirectory + imageNode.attribute("source").as_string();
std::string imageName = imageNode.attribute("source").as_string();
sf::Image image = m_LoadImage(imageName);
if(m_failedImage)
{
std::cerr << "Failed to load image at " << imageName << std::endl;
std::cerr << "Please check image exists and path is relative to tmx document." << std::endl;
std::cerr << "Please check image exists and add any external paths with AddSearchPath()" << std::endl;
return false;
}

Expand Down Expand Up @@ -774,6 +782,21 @@ void MapLoader::m_DrawLayer(sf::RenderTarget& rt, MapLayer& layer, bool debug)
}
}

std::string MapLoader::m_FileFromPath(const std::string& path)
{
assert(!path.empty());

for(auto it = path.rbegin(); it != path.rend(); ++it)
{
if(*it == '/' || *it == '\\')
{
int pos = std::distance(path.rbegin(), it);
return path.substr(path.size() - pos);
}
}
return path;
}

void MapLoader::draw(sf::RenderTarget& rt, sf::RenderStates states) const
{
sf::View view = rt.getView();
Expand Down Expand Up @@ -911,19 +934,34 @@ bool MapLoader::m_Decompress(const char* source, std::vector<unsigned char>& des
return true;
}

sf::Image& MapLoader::m_LoadImage(std::string path)
sf::Image& MapLoader::m_LoadImage(const std::string& imageName)
{
auto i = m_cachedImages.find(path);
if(i != m_cachedImages.end())
return *i->second;
for(auto& p : m_searchPaths)
{
auto i = m_cachedImages.find(p + imageName);
if(i != m_cachedImages.end())
return *i->second;
}

//else attempt to load
std::shared_ptr<sf::Image> newImage = std::shared_ptr<sf::Image>(new sf::Image());
if(path.empty() || !newImage->loadFromFile(path))

//try other paths first
bool loaded = false;
std::string path;
for(auto& p : m_searchPaths)
{
path = p + imageName;
loaded = newImage->loadFromFile(path);
if(loaded) break;
}
if(!loaded)
{
newImage->create(20u, 20u, sf::Color::Yellow);
m_failedImage = true;
path = "default";
}

m_cachedImages[path] = newImage;
return *m_cachedImages[path];//newImage;
}
Expand Down
Loading

0 comments on commit dc220b2

Please sign in to comment.