#pragma once #include "olcPixelGameEngine.h" #include <strstream> #include "TMXParser.h" #include "Map.h" #include "olcUTIL_Geometry2D.h" using namespace olc; struct Tileset{ XMLTag ImageData; std::map<int,XMLTag> ForegroundTileData; std::map<int,XMLTag> UpperForegroundTileData; std::map<int,TileCollisionData> CollisionData; std::map<int,XMLTag> StaircaseData; friend std::ostream& operator << (std::ostream& os, Tileset& rhs); }; class TSXParser{ public: Tileset&GetData(); private: Tileset parsedTilesetInfo; void ParseTag(std::string tag); std::string previousTag; int previousTagID; std::string staircaseTag=""; public: TSXParser(std::string file); }; #ifdef TSX_PARSER_SETUP #undef TSX_PARSER_SETUP Tileset&TSXParser::GetData() { return parsedTilesetInfo; } std::ostream&operator<<(std::ostream& os, Tileset& rhs){ os<<rhs.ImageData.FormatTagData(rhs.ImageData.data)<<"\n"; return os; } void TSXParser::ParseTag(std::string tag) { XMLTag newTag; //First character is a '<' so we discard it. tag.erase(0,1); tag.erase(tag.length()-1,1); //Erase the first and last characters in the tag. Now parse by spaces. std::stringstream s(tag); //Turn it into a string stream to now parse into individual whitespaces. std::string data; while (s.good()) { int quotationMarkCount=0; bool pastEquals=false; data=""; bool valid=false; while(s.good()){ int character=s.get(); if(character=='"'){ quotationMarkCount++; } if(character==' '&"ationMarkCount%2==0){ valid=true; break; } data+=character; if(pastEquals&"ationMarkCount%2==0){ valid=true; break; } if(character=='='&"ationMarkCount%2==0){ pastEquals=true; } } if(valid&&data.length()>0){ if (newTag.tag.length()==0) { //Tag's empty, so first line is the tag. newTag.tag=data; std::cout<<"Tag: "<<newTag.tag<<"\n"; } else { std::string key = data.substr(0,data.find("=")); std::string value = data.substr(data.find("=")+1,std::string::npos); //Strip Quotation marks. value = value.substr(1,std::string::npos); value = value.substr(0,value.length()-1); newTag.data[key]=value; std::cout<<" "<<key<<":"<<newTag.data[key]<<"\n"; } } } if (newTag.tag=="image") { parsedTilesetInfo.ImageData=newTag; } else if (newTag.tag=="tile"&&newTag.data["type"]=="ForegroundTile"){ parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")]=newTag; } else if (newTag.tag=="tile"&&newTag.data["type"]=="UpperForegroundTile"){ parsedTilesetInfo.UpperForegroundTileData[newTag.GetInteger("id")]=newTag; } else if (newTag.tag=="tile"&&newTag.data["type"]=="Staircase"){ staircaseTag=newTag.tag; previousTagID=newTag.GetInteger("id"); } else if (newTag.tag=="tile"){ previousTag=newTag.tag; previousTagID=newTag.GetInteger("id"); } else if (newTag.tag=="property"&&staircaseTag=="tile"){ parsedTilesetInfo.StaircaseData[previousTagID]=newTag; staircaseTag=""; } else if (newTag.tag=="object"&&previousTag=="tile"){ TileCollisionData data; data.collision=geom2d::rect<int>{{newTag.GetInteger("x"),newTag.GetInteger("y")},{newTag.GetInteger("width"),newTag.GetInteger("height")}}; parsedTilesetInfo.CollisionData[previousTagID]=data; } std::cout<<"\n"<<"=============\n"; } TSXParser::TSXParser(std::string file){ std::ifstream f(file,std::ios::in); std::string accumulator=""; while (f.good()) { std::string data; f>>data; if (data.empty()) continue; if (accumulator.length()>0) { accumulator+=" "+data; //Check if it ends with '>' if (data[data.length()-1]=='>') { ParseTag(accumulator); accumulator=""; } } else if (data[0]=='<') { //Beginning of XML tag. accumulator=data; if(accumulator.length()>1&&accumulator.at(1)=='/'){ accumulator=""; //Restart because this is an end tag. } if(accumulator.length()>1&&accumulator.find('>')!=std::string::npos){ accumulator=""; //Restart because this tag has nothing in it! } } } std::cout<<"Parsed Tileset Data:\n"<<parsedTilesetInfo<<"\n"; } #endif