@ -2,6 +2,7 @@
# include "olcPixelGameEngine.h"
# include "olcUTIL_Geometry2D.h"
# include <sstream>
# include "GameState.h"
using namespace olc ;
@ -57,6 +58,20 @@ struct Map{
friend std : : ostream & operator < < ( std : : ostream & os , std : : vector < XMLTag > & rhs ) ;
} ;
struct Property {
std : : string name ;
std : : string value ;
int GetInteger ( ) ;
float GetFloat ( ) ;
double GetDouble ( ) ;
bool GetBool ( ) ;
} ;
struct StagePlate {
XMLTag tag ;
std : : map < std : : string , Property > properties ;
} ;
class TMXParser {
public :
Map GetData ( ) ;
@ -69,13 +84,16 @@ class TMXParser{
int monsterPropertyTagCount = - 1 ;
XMLTag monsterTag ;
XMLTag spawnerLinkTag ;
StagePlate * currentStagePlate ;
std : : vector < XMLTag > accumulatedMonsterTags ;
std : : map < int , StagePlate > stagePlates ;
bool infiniteMap = false ;
public :
TMXParser ( std : : string file ) ;
} ;
typedef std : : map < std : : string , std : : vector < geom2d : : rect < int > > > ZoneData ;
//#define TMX_PARSER_SETUP //Toggle for code-writing.
# ifdef TMX_PARSER_SETUP
# undef TMX_PARSER_SETUP
@ -114,6 +132,22 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
return true ;
}
}
int Property : : GetInteger ( ) {
return std : : stoi ( value ) ;
}
float Property : : GetFloat ( ) {
return std : : stof ( value ) ;
}
double Property : : GetDouble ( ) {
return std : : stod ( value ) ;
}
bool Property : : GetBool ( ) {
if ( value = = " 0 " ) {
return false ;
} else {
return true ;
}
}
MapTag : : MapTag ( ) { }
MapTag : : MapTag ( int width , int height , int tilewidth , int tileheight )
: width ( width ) , height ( height ) , tilewidth ( tilewidth ) , tileheight ( tileheight ) , MapSize ( { width , height } ) , TileSize ( { tilewidth , tileheight } ) { }
@ -221,24 +255,30 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
} ;
XMLTag newTag = ReadNextTag ( ) ;
if ( newTag . tag = = " object " & & newTag . data [ " type " ] ! = " StagePlate " ) {
currentStagePlate = nullptr ;
}
if ( newTag . tag = = " map " ) {
if ( newTag . tag = = " map " ) {
if ( stoi ( newTag . data [ " infinite " ] ) = = 1 ) {
infiniteMap = true ;
return ;
}
parsedMapInfo . MapData = { stoi ( newTag . data [ " width " ] ) , stoi ( newTag . data [ " height " ] ) , stoi ( newTag . data [ " tilewidth " ] ) , stoi ( newTag . data [ " tileheight " ] ) } ;
} else
if ( newTag . tag = = " tileset " ) {
if ( newTag . tag = = " tileset " ) {
parsedMapInfo . TilesetData . push_back ( newTag ) ;
} else
if ( newTag . tag = = " layer " ) {
if ( newTag . tag = = " layer " ) {
LayerTag l = { newTag } ;
parsedMapInfo . LayerData . push_back ( l ) ;
} else
if ( newTag . tag = = " object " & & newTag . data [ " type " ] = = " SpawnGroup " ) {
parsedMapInfo . SpawnerData [ newTag . GetInteger ( " id " ) ] = { newTag } ;
prevSpawner = newTag . GetInteger ( " id " ) ;
if ( newTag . GetInteger ( " id " ) ! = 0 ) {
parsedMapInfo . SpawnerData [ newTag . GetInteger ( " id " ) ] = { newTag } ;
prevSpawner = newTag . GetInteger ( " id " ) ;
}
} else
if ( newTag . tag = = " property " & & newTag . data [ " name " ] = = " Optimize " & & newTag . data [ " value " ] = = " true " ) {
parsedMapInfo . MapData . optimized = true ;
@ -250,10 +290,7 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
parsedMapInfo . MapData . playerSpawnLocation = { newTag . GetInteger ( " x " ) - newTag . GetInteger ( " width " ) / 2 , newTag . GetInteger ( " y " ) - newTag . GetInteger ( " height " ) / 2 } ;
} else
if ( newTag . tag = = " object " & & newTag . data . find ( " type " ) ! = newTag . data . end ( )
& & newTag . data . find ( " x " ) ! = newTag . data . end ( )
& & newTag . data . find ( " y " ) ! = newTag . data . end ( )
& & newTag . data . find ( " width " ) ! = newTag . data . end ( )
& & newTag . data . find ( " height " ) ! = newTag . data . end ( ) ) {
& & ( newTag . data [ " type " ] = = " LowerZone " | | newTag . data [ " type " ] = = " UpperZone " ) ) {
//This is an object with a type that doesn't fit into other categories, we can add it to ZoneData.
if ( parsedMapInfo . ZoneData . find ( newTag . data [ " type " ] ) ! = parsedMapInfo . ZoneData . end ( ) ) {
std : : vector < geom2d : : rect < int > > & zones = parsedMapInfo . ZoneData [ newTag . data [ " type " ] ] ;
@ -280,7 +317,16 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
monsterTag . data [ " spawnerLink " ] = spawnerLinkTag . data [ " value " ] ;
accumulatedMonsterTags . push_back ( monsterTag ) ;
monsterPropertyTagCount = - 1 ;
} else {
} else
if ( newTag . tag = = " object " & & newTag . data [ " type " ] = = " StagePlate " ) {
if ( newTag . GetInteger ( " id " ) ! = 0 ) {
stagePlates [ newTag . GetInteger ( " id " ) ] = { newTag } ;
currentStagePlate = & stagePlates . at ( newTag . GetInteger ( " id " ) ) ;
}
} else
if ( newTag . tag = = " property " & & currentStagePlate ! = nullptr ) {
currentStagePlate - > properties [ newTag . data [ " name " ] ] = { newTag . data [ " name " ] , newTag . data [ " value " ] } ;
} else {
if ( _DEBUG_MAP_LOAD_INFO ) std : : cout < < " Unsupported tag format! Ignoring. " < < " \n " ;
}
if ( _DEBUG_MAP_LOAD_INFO ) std : : cout < < " \n " < < " ============= \n " ;
@ -354,6 +400,30 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
std : : sort ( parsedMapInfo . TilesetData . begin ( ) , parsedMapInfo . TilesetData . end ( ) , [ ] ( XMLTag & t1 , XMLTag & t2 ) { return t1 . GetInteger ( " firstgid " ) < t2 . GetInteger ( " firstgid " ) ; } ) ;
std : : map < int , int > idToIndexMap ; //Since the original map data relies on IDs decided by Tiled and we are condensing all this data into a vector of connection points, each connection point is going to be in a different ID.
//therefore, we need to convert the Tiled IDs into whatever vector index we insert each connection into for State_OverworldMap::connections.
for ( auto key : stagePlates ) {
StagePlate & plate = key . second ;
idToIndexMap [ plate . tag . GetInteger ( " id " ) ] = State_OverworldMap : : connections . size ( ) ;
ConnectionPoint newConnection = { { plate . tag . GetFloat ( " x " ) , plate . tag . GetFloat ( " y " ) } , plate . properties [ " Map " ] . value , plate . properties [ " Unlock Condition " ] . value } ;
int iterationCount = 0 ;
for ( auto key2 : plate . properties ) {
if ( key2 . first . starts_with ( " Connection " ) ) {
newConnection . neighbors [ iterationCount ] = key2 . second . GetInteger ( ) ;
iterationCount + + ;
}
}
State_OverworldMap : : connections . push_back ( newConnection ) ;
}
for ( ConnectionPoint & connection : State_OverworldMap : : connections ) {
std : : array < int , 4 > ;
for ( int & val : connection . neighbors ) {
if ( idToIndexMap . count ( val ) ) {
val = idToIndexMap . at ( val ) ; //Convert from given Tiled ID to indexed ID in State_OverworldMap::connections
}
}
}
if ( _DEBUG_MAP_LOAD_INFO ) std : : cout < < " Parsed Map Data: \n " < < parsedMapInfo < < " \n " ;
}
# endif