|
| 1 | +/********************************************************************* |
| 2 | +Matt Marchant 2013 - 2015 |
| 3 | +SFML Tiled Map Loader - https://github.com/bjorn/tiled/wiki/TMX-Map-Format |
| 4 | + http://trederia.blogspot.com/2013/05/tiled-map-loader-for-sfml.html |
| 5 | +
|
| 6 | +The zlib license has been used to make this software fully compatible |
| 7 | +with SFML. See http://www.sfml-dev.org/license.php |
| 8 | +
|
| 9 | +This software is provided 'as-is', without any express or |
| 10 | +implied warranty. In no event will the authors be held |
| 11 | +liable for any damages arising from the use of this software. |
| 12 | +
|
| 13 | +Permission is granted to anyone to use this software for any purpose, |
| 14 | +including commercial applications, and to alter it and redistribute |
| 15 | +it freely, subject to the following restrictions: |
| 16 | +
|
| 17 | +1. The origin of this software must not be misrepresented; |
| 18 | + you must not claim that you wrote the original software. |
| 19 | + If you use this software in a product, an acknowledgment |
| 20 | + in the product documentation would be appreciated but |
| 21 | + is not required. |
| 22 | +
|
| 23 | +2. Altered source versions must be plainly marked as such, |
| 24 | + and must not be misrepresented as being the original software. |
| 25 | +
|
| 26 | +3. This notice may not be removed or altered from any |
| 27 | + source distribution. |
| 28 | +*********************************************************************/ |
| 29 | + |
| 30 | +#ifndef MAP_LOADER_H_ |
| 31 | +#define MAP_LOADER_H_ |
| 32 | + |
| 33 | +#include <tmx/QuadTreeNode.h> |
| 34 | +#include <tmx/MapLayer.h> |
| 35 | + |
| 36 | +#include <pugixml/pugixml.hpp> |
| 37 | + |
| 38 | +#include <array> |
| 39 | +#include <cassert> |
| 40 | +#include <bitset> |
| 41 | + |
| 42 | +namespace tmx |
| 43 | +{ |
| 44 | + enum class MapOrientation |
| 45 | + { |
| 46 | + Orthogonal, |
| 47 | + Isometric, |
| 48 | + SteppedIsometric |
| 49 | + }; |
| 50 | + |
| 51 | + class MapLoader final : public sf::Drawable, private sf::NonCopyable |
| 52 | + { |
| 53 | + public: |
| 54 | + //requires a path to the map directory relative to working directory |
| 55 | + //and the maximum number of tiles in a single patch along one edge |
| 56 | + //where 0 does no patch splitting. |
| 57 | + MapLoader(const std::string& mapDirectory, sf::Uint8 patchSize = 10u); |
| 58 | + //loads a given tmx file, returns false on failure |
| 59 | + bool Load(const std::string& mapFile); |
| 60 | + //loads a map from an xml string in memory |
| 61 | + bool LoadFromMemory(const std::string& xmlString); |
| 62 | + //adds give path to list of directories to search for assets, such as tile sets |
| 63 | + void AddSearchPath(const std::string& path); |
| 64 | + //updates the map's quad tree. Not necessary when not querying the quad tree |
| 65 | + //root area is the are covered by root node, for example the screen size |
| 66 | + void UpdateQuadTree(const sf::FloatRect& rootArea); |
| 67 | + //queries the quad tree and returns a vector of objects contained by nodes enclosing |
| 68 | + //or intersecting testArea |
| 69 | + std::vector<MapObject*> QueryQuadTree(const sf::FloatRect& testArea); |
| 70 | + //returns a vector of map layers |
| 71 | + std::vector<MapLayer>& GetLayers(); |
| 72 | + const std::vector<MapLayer>& GetLayers() const; |
| 73 | + //draws visible tiles to given target, optionally draw outline of objects for debugging |
| 74 | + void Draw(sf::RenderTarget& rt, MapLayer::DrawType type, bool debug = false); |
| 75 | + //overload for drawing layer by index |
| 76 | + void Draw(sf::RenderTarget& rt, sf::Uint16 index, bool debug = false); |
| 77 | + //projects orthogonal world coords to isometric world coords if available, else return original value |
| 78 | + //eg: use to convert an isometric world coordinate to a position to be drawn in view space |
| 79 | + sf::Vector2f IsometricToOrthogonal(const sf::Vector2f& projectedCoords); |
| 80 | + //returns orthogonal world coords from projected coords |
| 81 | + //eg: use to find the orthogonal world coordinates currently under the mouse cursor |
| 82 | + sf::Vector2f OrthogonalToIsometric(const sf::Vector2f& worldCoords); |
| 83 | + //returns the size of an individual tile in pixels |
| 84 | + sf::Vector2u GetTileSize() const; |
| 85 | + //returns the map size in pixels |
| 86 | + sf::Vector2u GetMapSize() const; |
| 87 | + //returns empty string if property not found |
| 88 | + std::string GetPropertyString(const std::string& name); |
| 89 | + //sets the shader property of a layer's rendering states member |
| 90 | + void SetLayerShader(sf::Uint16 layerId, const sf::Shader& shader); |
| 91 | + //so we can test if QuadTree is available |
| 92 | + bool QuadTreeAvailable() const; |
| 93 | + |
| 94 | + private: |
| 95 | + //properties which correspond to tmx |
| 96 | + sf::Uint16 m_width, m_height; //tile count |
| 97 | + sf::Uint16 m_tileWidth, m_tileHeight; //width / height of tiles |
| 98 | + MapOrientation m_orientation; |
| 99 | + float m_tileRatio; //width / height ratio of isometric tiles |
| 100 | + std::map<std::string, std::string> m_properties; |
| 101 | + |
| 102 | + mutable sf::FloatRect m_bounds; //bounding area of tiles visible on screen |
| 103 | + mutable sf::Vector2f m_lastViewPos; //save recalc bounds if view not moved |
| 104 | + std::vector<std::string> m_searchPaths; //additional paths to search for tileset files |
| 105 | + |
| 106 | + mutable std::vector<MapLayer> m_layers; //layers of map, including image and object layers |
| 107 | + std::vector<std::unique_ptr<sf::Texture>> m_imageLayerTextures; |
| 108 | + std::vector<std::unique_ptr<sf::Texture>> m_tilesetTextures; //textures created from complete sets used when drawing vertex arrays |
| 109 | + const sf::Uint8 m_patchSize; |
| 110 | + struct TileInfo //holds texture coords and tileset id of a tile |
| 111 | + { |
| 112 | + std::array<sf::Vector2f, 4> Coords; |
| 113 | + sf::Vector2f Size; |
| 114 | + sf::Uint16 TileSetId; |
| 115 | + TileInfo(); |
| 116 | + TileInfo(const sf::IntRect& rect, const sf::Vector2f& size, sf::Uint16 tilesetId); |
| 117 | + }; |
| 118 | + std::vector<TileInfo> m_tileInfo; //stores information on all the tilesets for creating vertex arrays |
| 119 | + |
| 120 | + sf::VertexArray m_gridVertices; //used to draw map grid in debug |
| 121 | + bool m_mapLoaded, m_quadTreeAvailable; |
| 122 | + //root node for quad tree partition |
| 123 | + QuadTreeRoot m_rootNode; |
| 124 | + |
| 125 | + |
| 126 | + bool LoadFromXmlDoc(const pugi::xml_document& doc); |
| 127 | + //resets any loaded map properties |
| 128 | + void Unload(); |
| 129 | + //sets the visible area of tiles to be drawn |
| 130 | + void SetDrawingBounds(const sf::View& view); |
| 131 | + |
| 132 | + //utility functions for parsing map data |
| 133 | + bool ParseMapNode(const pugi::xml_node& mapNode); |
| 134 | + bool ParseTileSets(const pugi::xml_node& mapNode); |
| 135 | + bool ProcessTiles(const pugi::xml_node& tilesetNode); |
| 136 | + bool ParseCollectionOfImages(const pugi::xml_node& tilesetNode); |
| 137 | + bool ParseLayer(const pugi::xml_node& layerNode); |
| 138 | + TileQuad* AddTileToLayer(MapLayer& layer, sf::Uint16 x, sf::Uint16 y, sf::Uint32 gid, const sf::Vector2f& offset = sf::Vector2f()); |
| 139 | + bool ParseObjectgroup(const pugi::xml_node& groupNode); |
| 140 | + bool ParseImageLayer(const pugi::xml_node& imageLayerNode); |
| 141 | + void ParseLayerProperties(const pugi::xml_node& propertiesNode, MapLayer& destLayer); |
| 142 | + void SetIsometricCoords(MapLayer& layer); |
| 143 | + void DrawLayer(sf::RenderTarget& rt, MapLayer& layer, bool debug = false); |
| 144 | + std::string FileFromPath(const std::string& path); |
| 145 | + |
| 146 | + //sf::drawable |
| 147 | + void draw(sf::RenderTarget& rt, sf::RenderStates states) const; |
| 148 | + |
| 149 | + //utility method for parsing colour values from hex values |
| 150 | + sf::Color ColourFromHex(const char* hexStr) const; |
| 151 | + |
| 152 | + //method for decompressing zlib compressed strings |
| 153 | + bool Decompress(const char* source, std::vector<unsigned char>& dest, int inSize, int expectedSize); |
| 154 | + //creates a vertex array used to draw grid lines when using debug output |
| 155 | + void CreateDebugGrid(void); |
| 156 | + |
| 157 | + //caches loaded images to prevent loading the same tileset more than once |
| 158 | + sf::Image& LoadImage(const std::string& imageName); |
| 159 | + std::map<std::string, std::shared_ptr<sf::Image> >m_cachedImages; |
| 160 | + bool m_failedImage; |
| 161 | + |
| 162 | + //Reading the flipped bits |
| 163 | + std::vector<unsigned char> IntToBytes(sf::Uint32 paramInt); |
| 164 | + std::pair<sf::Uint32, std::bitset<3> > ResolveRotation(sf::Uint32 gid); |
| 165 | + |
| 166 | + //Image flip functions |
| 167 | + void FlipY(sf::Vector2f *v0, sf::Vector2f *v1, sf::Vector2f *v2, sf::Vector2f *v3); |
| 168 | + void FlipX(sf::Vector2f *v0, sf::Vector2f *v1, sf::Vector2f *v2, sf::Vector2f *v3); |
| 169 | + void FlipD(sf::Vector2f *v0, sf::Vector2f *v1, sf::Vector2f *v2, sf::Vector2f *v3); |
| 170 | + |
| 171 | + void DoFlips(std::bitset<3> bits,sf::Vector2f *v0, sf::Vector2f *v1, sf::Vector2f *v2, sf::Vector2f *v3); |
| 172 | + }; |
| 173 | + |
| 174 | + |
| 175 | + //method for decoding base64 encoded strings |
| 176 | + std::string base64_decode(std::string const& string); |
| 177 | +} |
| 178 | + |
| 179 | +#endif //MAP_LOADER_H_ |
0 commit comments