parent
3f9a30c16a
commit
f234f1a4fe
@ -0,0 +1,14 @@ |
||||
{ |
||||
"automappingRulesFile": "", |
||||
"commands": [ |
||||
], |
||||
"compatibilityVersion": 1100, |
||||
"extensionsPath": "extensions", |
||||
"folders": [ |
||||
"." |
||||
], |
||||
"properties": [ |
||||
], |
||||
"propertyTypes": [ |
||||
] |
||||
} |
@ -0,0 +1,23 @@ |
||||
{ |
||||
"Map/SizeTest": { |
||||
"height": 4300, |
||||
"width": 2 |
||||
}, |
||||
"activeFile": "", |
||||
"expandedProjectPaths": [ |
||||
], |
||||
"fileStates": { |
||||
}, |
||||
"last.imagePath": "C:/Users/sigon/source/repos/hamster/assets", |
||||
"map.lastUsedFormat": "tmx", |
||||
"openFiles": [ |
||||
], |
||||
"project": "HamsterGame.tiled-project", |
||||
"recentFiles": [ |
||||
], |
||||
"tileset.lastUsedFormat": "tsx", |
||||
"tileset.tileSize": { |
||||
"height": 16, |
||||
"width": 16 |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<tileset version="1.10" tiledversion="1.10.2" name="Terrain" tilewidth="16" tileheight="16" tilecount="1484" columns="28"> |
||||
<image source="gametiles.png" width="448" height="848"/> |
||||
<tile id="493" probability="20"/> |
||||
<tile id="1120" probability="4"/> |
||||
<tile id="1148" probability="4"/> |
||||
<tile id="1176" probability="4"/> |
||||
<tile id="1207" probability="10"/> |
||||
<wangsets> |
||||
<wangset name="Sand" type="corner" tile="-1"> |
||||
<wangcolor name="Desert" color="#ff0000" tile="-1" probability="1"/> |
||||
<wangcolor name="" color="#00ff00" tile="-1" probability="1"/> |
||||
<wangtile tileid="297" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="992" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1020" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1021" wangid="0,1,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1022" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1023" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1024" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1025" wangid="0,1,0,1,0,2,0,1"/> |
||||
<wangtile tileid="1049" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1050" wangid="0,2,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1051" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1052" wangid="0,2,0,2,0,1,0,2"/> |
||||
<wangtile tileid="1053" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1077" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1078" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1080" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1081" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1105" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1106" wangid="0,1,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1107" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1108" wangid="0,2,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1109" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1133" wangid="0,2,0,1,0,1,0,1"/> |
||||
<wangtile tileid="1134" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1135" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1136" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1137" wangid="0,1,0,1,0,1,0,2"/> |
||||
</wangset> |
||||
<wangset name="Grass" type="corner" tile="-1"> |
||||
<wangcolor name="" color="#ff0000" tile="-1" probability="1"/> |
||||
<wangcolor name="" color="#00ff00" tile="-1" probability="1"/> |
||||
<wangtile tileid="493" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1120" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1148" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1149" wangid="0,1,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1150" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1151" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1152" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1153" wangid="0,1,0,1,0,2,0,1"/> |
||||
<wangtile tileid="1176" wangid="0,2,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1177" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1178" wangid="0,2,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1179" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1180" wangid="0,2,0,2,0,1,0,2"/> |
||||
<wangtile tileid="1181" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1205" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1206" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1208" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1209" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1233" wangid="0,2,0,2,0,1,0,1"/> |
||||
<wangtile tileid="1234" wangid="0,1,0,2,0,2,0,2"/> |
||||
<wangtile tileid="1235" wangid="0,1,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1236" wangid="0,2,0,2,0,2,0,1"/> |
||||
<wangtile tileid="1237" wangid="0,1,0,1,0,2,0,2"/> |
||||
<wangtile tileid="1261" wangid="0,2,0,1,0,1,0,1"/> |
||||
<wangtile tileid="1262" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1263" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1264" wangid="0,2,0,1,0,1,0,2"/> |
||||
<wangtile tileid="1265" wangid="0,1,0,1,0,1,0,2"/> |
||||
</wangset> |
||||
</wangsets> |
||||
</tileset> |
@ -0,0 +1,28 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="1"> |
||||
<tileset firstgid="1" source="Terrain.tsx"/> |
||||
<layer id="1" name="Tile Layer 1" width="30" height="20"> |
||||
<data encoding="csv"> |
||||
1206,494,494,1179,1181,1235,1151,1236,1154,1234,494,1238,1209,494,1079,1078,298,1082,1050,993,1054,1138,1022,1109,1079,1081,993,1082,1134,1137, |
||||
1262,1180,1181,1182,1209,494,494,494,1207,1206,1177,1235,1237,494,1079,1134,1135,1138,1134,1053,1107,1026,1078,1021,1054,1134,1135,1138,1022,1026, |
||||
1152,1236,1237,1235,1237,494,494,1149,1235,1237,494,1179,1181,494,1107,1026,1022,1024,1108,1109,298,1054,1078,1021,1054,1022,1025,1023,1109,1082, |
||||
1179,1265,1180,1180,1263,1181,1179,1264,1265,1263,1180,1266,1178,494,1080,1054,1050,1051,1053,1021,298,1079,1078,993,1054,1134,1136,1137,1136,1138, |
||||
1235,1152,1151,1153,1154,1178,1182,1150,1151,1236,1151,1152,1178,494,1051,1138,1134,1138,1134,1136,1053,1110,1134,1053,1107,1023,1025,1024,1024,1025, |
||||
1179,1180,1180,1263,1266,1209,1182,1178,494,494,1177,1235,1179,494,1079,1022,1026,1022,1026,1022,1109,1110,1022,1109,993,298,993,1051,1053,298, |
||||
1238,1150,1151,1153,1151,1237,1235,1237,1121,1149,494,494,1238,494,1079,1081,1054,1078,1079,1078,1051,1138,1081,993,1051,1052,1136,1138,1134,1136, |
||||
1238,1234,1179,1263,1181,1177,1121,494,1121,494,494,494,1235,494,1079,1078,1107,1109,1079,1078,1082,1022,1109,993,1082,1022,1024,1026,1022,1026, |
||||
1235,1237,1235,1152,1237,1121,1149,494,494,494,1177,494,494,494,1079,1134,1137,1052,1138,1050,1079,1050,993,298,1054,1078,1021,1054,1081,1079, |
||||
1179,1265,1264,1181,1179,1181,1149,1177,1177,1177,1121,494,1177,494,1107,1108,1024,1023,1108,1109,1054,1081,298,1021,1082,1081,1051,1138,1078,1079, |
||||
1235,1153,1154,1234,1207,1234,494,1177,494,494,494,494,494,494,1021,298,1021,298,1051,1137,1138,1106,993,1021,1110,1134,1138,1022,1109,1082, |
||||
1181,1179,1266,1178,1182,1234,494,494,494,1149,494,1179,1181,494,1051,1136,1137,1137,1138,1022,1025,1109,993,993,1110,1022,1026,1134,1137,1138, |
||||
1234,1235,1151,1237,1266,1209,1149,1179,1180,1180,1263,1266,1209,494,1107,1108,1108,1108,1108,1109,993,1021,1080,298,1107,1109,1107,1108,1108,1108, |
||||
1206,1149,1121,1238,1266,1262,1264,1266,1150,1236,1153,1236,1237,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494, |
||||
1209,494,1177,1210,1150,1153,1152,1154,1206,494,494,494,494,494,1121,1121,1149,1179,1180,1181,1207,1206,1177,1121,494,494,1149,494,494,1121, |
||||
1209,494,1177,1235,1237,1121,1177,1207,1234,1149,1121,494,494,1177,494,494,1149,1235,1154,1206,1235,1237,1179,1181,494,494,494,494,494,1149, |
||||
1178,494,494,494,1121,494,1121,1238,1209,494,494,494,494,494,1149,494,1121,494,1182,1262,1263,1265,1266,1209,494,494,494,494,1179,1264, |
||||
1237,1149,1177,494,494,494,494,1238,1178,494,1121,1179,1265,1265,1180,1181,494,1121,1235,1151,1154,1150,1154,1206,1149,494,494,1149,1235,1152, |
||||
494,1121,1149,1121,494,1149,1179,1266,1206,494,1177,1207,1150,1236,1151,1237,494,1177,1121,494,1238,1234,1235,1237,494,494,494,494,494,1149, |
||||
494,494,494,494,494,494,1235,1154,1234,1179,1263,1266,1209,1121,494,1177,494,1149,1177,494,1210,1209,494,1177,494,494,1149,1121,1121,494 |
||||
</data> |
||||
</layer> |
||||
</map> |
@ -0,0 +1,395 @@ |
||||
#pragma region License |
||||
/*
|
||||
License (OLC-3) |
||||
~~~~~~~~~~~~~~~ |
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com> |
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, |
||||
are permitted provided that the following conditions are met: |
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above |
||||
copyright notice. This list of conditions and the following disclaimer must be |
||||
reproduced in the documentation and/or other materials provided with the distribution. |
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may |
||||
be used to endorse or promote products derived from this software without specific |
||||
prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
SUCH DAMAGE. |
||||
|
||||
Portions of this software are copyright © 2024 The FreeType |
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information. |
||||
All rights reserved. |
||||
*/ |
||||
#pragma endregion |
||||
#pragma once |
||||
#include "olcUTIL_Geometry2D.h" |
||||
#include "olcPixelGameEngine.h" |
||||
#include <sstream> |
||||
#include <set> |
||||
#include <queue> |
||||
|
||||
using MapName=std::string; |
||||
using namespace olc; |
||||
using namespace std::literals; |
||||
|
||||
struct XMLTag{ |
||||
std::string tag; |
||||
std::map<std::string,std::string> data; |
||||
const std::string FormatTagData(std::map<std::string,std::string>tiles); |
||||
friend std::ostream& operator << (std::ostream& os, XMLTag& rhs); |
||||
std::string str(); |
||||
int GetInteger(std::string dataTag); |
||||
float GetFloat(std::string dataTag); |
||||
double GetDouble(std::string dataTag); |
||||
bool GetBool(std::string dataTag); |
||||
std::string GetString(std::string dataTag)const; |
||||
}; |
||||
|
||||
struct ForegroundTileTag:public XMLTag{ |
||||
//Whether or not to hide this foreground tile
|
||||
bool hide=true; |
||||
}; |
||||
|
||||
struct MapTag{ |
||||
int width=0,height=0; |
||||
int tilewidth=0,tileheight=0; |
||||
bool optimized=false; //An optimized map will require us to flatten it out and use it as a single tile.
|
||||
bool provideOptimization=false; //An optimized map will require us to flatten it out and use it as a single tile.
|
||||
vi2d playerSpawnLocation; |
||||
vi2d MapSize; //The number of tiles in width and height of this map.
|
||||
vi2d TileSize; //How large in pixels the map's tiles are.
|
||||
MapTag(); |
||||
MapTag(int width,int height,int tilewidth,int tileheight); |
||||
friend std::ostream& operator << (std::ostream& os, MapTag& rhs); |
||||
}; |
||||
|
||||
struct LayerTag{ |
||||
XMLTag tag; |
||||
std::vector<std::vector<int>> tiles; |
||||
std::string unlockCondition=""; |
||||
std::string str(); |
||||
}; |
||||
|
||||
struct ZoneData{ |
||||
geom2d::rect<int>zone; |
||||
bool isUpper=false; |
||||
std::vector<XMLTag>properties; |
||||
}; |
||||
|
||||
struct Map{ |
||||
friend class AiL; |
||||
friend class TMXParser; |
||||
private: |
||||
MapTag MapData; |
||||
std::string name; |
||||
Renderable*optimizedTile=nullptr; |
||||
std::vector<XMLTag> TilesetData; |
||||
std::vector<LayerTag> LayerData; |
||||
std::string mapType=""; |
||||
std::set<std::string>spawns; |
||||
std::map<std::string,std::vector<::ZoneData>>ZoneData; |
||||
public: |
||||
Map(); |
||||
void _SetMapData(MapTag data); |
||||
bool skipLoadoutScreen=false; |
||||
const MapTag&GetMapData()const; |
||||
const std::string_view GetMapType()const; |
||||
const std::vector<LayerTag>&GetLayers()const; |
||||
const MapName&GetMapName()const; |
||||
const std::string_view GetMapDisplayName()const; |
||||
const Renderable*const GetOptimizedMap()const; |
||||
const std::map<std::string,std::vector<::ZoneData>>&GetZones()const; |
||||
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles); |
||||
friend std::ostream& operator << (std::ostream& os, Map& rhs); |
||||
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(); |
||||
}; |
||||
|
||||
class TMXParser{ |
||||
public: |
||||
Map GetData(); |
||||
private: |
||||
Map parsedMapInfo; |
||||
std::string fileName; |
||||
ZoneData*prevZoneData=nullptr; |
||||
void ParseTag(std::string tag); |
||||
int monsterPropertyTagCount=-1; |
||||
bool infiniteMap=false; |
||||
LayerTag*currentLayerTag=nullptr; |
||||
public: |
||||
TMXParser(std::string file); |
||||
}; |
||||
|
||||
//#define TMX_PARSER_SETUP //Toggle for code-writing.
|
||||
|
||||
#ifdef TMX_PARSER_SETUP |
||||
#undef TMX_PARSER_SETUP |
||||
const std::string XMLTag::FormatTagData(std::map<std::string,std::string>tiles){ |
||||
std::string displayStr=""; |
||||
for (std::map<std::string,std::string>::iterator it=data.begin();it!=data.end();it++) { |
||||
displayStr+=" "+it->first+": "+it->second+"\n"; |
||||
} |
||||
return displayStr; |
||||
} |
||||
std::ostream& operator << (std::ostream& os, XMLTag& rhs){
|
||||
os <<
|
||||
rhs.tag <<"\n"<<
|
||||
rhs.FormatTagData(rhs.data) <<"\n"; |
||||
return os; |
||||
} |
||||
std::ostream& operator << (std::ostream& os, MapTag& rhs){
|
||||
os <<
|
||||
"(width:"<<rhs.width<<", height:"<<rhs.height<<", Tile width:"<<rhs.tilewidth<<", Tile height:"<<rhs.tileheight<<",playerSpawnLocation:"<<rhs.playerSpawnLocation<<")\n"; |
||||
return os; |
||||
} |
||||
int XMLTag::GetInteger(std::string dataTag) { |
||||
return std::stoi(data[dataTag]); |
||||
} |
||||
float XMLTag::GetFloat(std::string dataTag) { |
||||
return std::stof(data[dataTag]); |
||||
} |
||||
double XMLTag::GetDouble(std::string dataTag) { |
||||
return std::stod(data[dataTag]); |
||||
} |
||||
std::string XMLTag::GetString(std::string dataTag)const{ |
||||
return data.at(dataTag); |
||||
} |
||||
bool XMLTag::GetBool(std::string dataTag) { |
||||
if (data[dataTag]=="0"||data[dataTag]=="false") { |
||||
return false; |
||||
}else{ |
||||
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; |
||||
} |
||||
} |
||||
Map::Map(){ |
||||
ZoneData["UpperZone"]; |
||||
ZoneData["LowerZone"]; |
||||
} |
||||
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}){} |
||||
std::string XMLTag::str() { |
||||
return tag+"\n"; |
||||
} |
||||
std::string LayerTag::str() { |
||||
std::string displayStr=tag.tag+"\n"+tag.FormatTagData(tag.data); |
||||
displayStr+=" DATA ("+std::to_string(tiles[0].size())+"x"+std::to_string(tiles.size())+" )\n"; |
||||
return displayStr; |
||||
} |
||||
std::string Map::FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles) { |
||||
std::string displayStr; |
||||
for (int i=0;i<LayerData.size();i++) { |
||||
displayStr+=LayerData[i].str(); |
||||
} |
||||
return displayStr; |
||||
} |
||||
const std::string_view Map::GetMapType()const{ |
||||
return mapType; |
||||
} |
||||
const MapName&Map::GetMapName()const{ |
||||
return name; |
||||
} |
||||
void Map::_SetMapData(MapTag data){ |
||||
MapData=data; |
||||
} |
||||
const MapTag&Map::GetMapData()const{ |
||||
return MapData; |
||||
} |
||||
const std::vector<LayerTag>&Map::GetLayers()const{ |
||||
return LayerData; |
||||
} |
||||
const std::string_view Map::GetMapDisplayName()const{ |
||||
return name; |
||||
} |
||||
const Renderable*const Map::GetOptimizedMap()const{ |
||||
return optimizedTile; |
||||
} |
||||
std::ostream& operator <<(std::ostream& os, std::vector<XMLTag>& rhs) {
|
||||
for(XMLTag&tag:rhs){ |
||||
os <<
|
||||
tag<<"\n"; |
||||
} |
||||
return os; |
||||
} |
||||
std::ostream& operator <<(std::ostream& os, Map& rhs) {
|
||||
os <<
|
||||
rhs.MapData <<"\n"<<
|
||||
rhs.TilesetData <<"\n"<<
|
||||
rhs.FormatLayerData(os,rhs.LayerData) <<"\n"; |
||||
return os; |
||||
} |
||||
Map TMXParser::GetData() { |
||||
return parsedMapInfo; |
||||
} |
||||
void TMXParser::ParseTag(std::string tag) { |
||||
auto ReadNextTag=[&](){ |
||||
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; |
||||
}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; |
||||
} |
||||
} |
||||
} |
||||
return newTag; |
||||
}; |
||||
|
||||
XMLTag newTag=ReadNextTag(); |
||||
|
||||
auto ParseMonsterTemplateName=[](const XMLTag&monsterTag){ |
||||
std::string monsterName=monsterTag.GetString("template").substr("../maps/Monsters/"s.length()); |
||||
monsterName=monsterName.substr(0,monsterName.find(".tx")); |
||||
return monsterName; |
||||
}; |
||||
|
||||
if (newTag.tag=="map"){ |
||||
if(stoi(newTag.data["infinite"])==1){ |
||||
infiniteMap=true; |
||||
throw std::runtime_error{std::format("WARNING! Infinite maps are not supported! Invalid map: {}",fileName)}; |
||||
return; |
||||
} |
||||
parsedMapInfo.MapData={stoi(newTag.data["width"]),stoi(newTag.data["height"]),stoi(newTag.data["tilewidth"]),stoi(newTag.data["tileheight"])}; |
||||
}else |
||||
if (newTag.tag=="tileset"){ |
||||
parsedMapInfo.TilesetData.push_back(newTag); |
||||
}else |
||||
if (newTag.tag=="layer"){ |
||||
LayerTag l = {newTag}; |
||||
parsedMapInfo.LayerData.push_back(l); |
||||
currentLayerTag=&parsedMapInfo.LayerData.back(); |
||||
}else
|
||||
if(newTag.tag=="property"&&prevZoneData!=nullptr){ |
||||
//This is a property for a zone that doesn't fit into the other categories, we add it to the previous zone data encountered.
|
||||
prevZoneData->properties.push_back(newTag); |
||||
}else |
||||
if (newTag.tag=="object"&&newTag.data.find("type")!=newTag.data.end()){ |
||||
//This is an object with a type that doesn't fit into other categories, we can add it to ZoneData.
|
||||
std::vector<ZoneData>&zones=parsedMapInfo.ZoneData[newTag.data["type"]]; |
||||
float width=1.f; |
||||
float height=1.f; |
||||
if(newTag.data.count("width")>0)width=newTag.GetFloat("width"); |
||||
if(newTag.data.count("height")>0)height=newTag.GetFloat("height"); |
||||
zones.emplace_back(geom2d::rect<int>{{newTag.GetInteger("x"),newTag.GetInteger("y")},{int(width),int(height)}}); |
||||
prevZoneData=&zones.back(); |
||||
} |
||||
} |
||||
TMXParser::TMXParser(std::string file){ |
||||
fileName=file; |
||||
std::ifstream f(file,std::ios::in); |
||||
|
||||
std::string accumulator=""; |
||||
|
||||
while (f.good()&&!infiniteMap) { |
||||
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!
|
||||
} |
||||
}else{ |
||||
//Start reading in data for this layer.
|
||||
std::vector<int>rowData; |
||||
while (data.find(",")!=std::string::npos) { |
||||
std::string datapiece = data.substr(0,data.find(",")); |
||||
data = data.substr(data.find(",")+1,std::string::npos); |
||||
rowData.push_back(stoi(datapiece)); |
||||
} |
||||
if (data.length()) { |
||||
rowData.push_back(stoi(data)); |
||||
} |
||||
parsedMapInfo.LayerData[parsedMapInfo.LayerData.size()-1].tiles.push_back(rowData); |
||||
} |
||||
} |
||||
std::sort(parsedMapInfo.TilesetData.begin(),parsedMapInfo.TilesetData.end(),[](XMLTag&t1,XMLTag&t2){return t1.GetInteger("firstgid")<t2.GetInteger("firstgid");}); |
||||
} |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,189 @@ |
||||
#pragma region License |
||||
/*
|
||||
License (OLC-3) |
||||
~~~~~~~~~~~~~~~ |
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com> |
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, |
||||
are permitted provided that the following conditions are met: |
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above |
||||
copyright notice. This list of conditions and the following disclaimer must be |
||||
reproduced in the documentation and/or other materials provided with the distribution. |
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may |
||||
be used to endorse or promote products derived from this software without specific |
||||
prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
SUCH DAMAGE. |
||||
|
||||
Portions of this software are copyright © 2024 The FreeType |
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information. |
||||
All rights reserved. |
||||
*/ |
||||
#pragma endregion |
||||
#pragma once |
||||
#include <sstream> |
||||
#include "TMXParser.h" |
||||
|
||||
using namespace olc; |
||||
|
||||
|
||||
struct TileCollisionData{ |
||||
geom2d::rect<float>collision; |
||||
}; |
||||
|
||||
struct Tileset{ |
||||
XMLTag ImageData; |
||||
int tilewidth=0,tileheight=0; |
||||
int imagewidth=0,imageheight=0; |
||||
bool isTerrain=false; |
||||
std::unordered_map<int,TileCollisionData>CollisionData; |
||||
std::unordered_map<int,std::vector<int>>AnimationData; |
||||
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; |
||||
public: |
||||
TSXParser(std::string file); |
||||
}; |
||||
|
||||
//#define TSX_PARSER_SETUP
|
||||
|
||||
#ifdef TSX_PARSER_SETUP |
||||
#undef TSX_PARSER_SETUP |
||||
extern bool _DEBUG_MAP_LOAD_INFO; |
||||
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; |
||||
} 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; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (newTag.tag=="tileset") { |
||||
parsedTilesetInfo.tilewidth=stoi(newTag.data["tilewidth"]); |
||||
parsedTilesetInfo.tileheight=stoi(newTag.data["tileheight"]); |
||||
if(newTag.data.find("class")!=newTag.data.end()){ |
||||
parsedTilesetInfo.isTerrain=newTag.GetString("class")=="Terrain"; |
||||
} |
||||
} else |
||||
if (newTag.tag=="image") { |
||||
parsedTilesetInfo.ImageData=newTag; |
||||
parsedTilesetInfo.imagewidth=newTag.GetInteger("width"); |
||||
parsedTilesetInfo.imageheight=newTag.GetInteger("height"); |
||||
} else |
||||
if (newTag.tag=="tile"){ |
||||
previousTag=newTag.tag; |
||||
previousTagID=newTag.GetInteger("id"); |
||||
} else |
||||
if (newTag.tag=="frame"){ |
||||
//The way animation data is stored is every "animation_tile_precision" ms indicating which frame we should be on.
|
||||
for(int i=0;i<newTag.GetInteger("duration")/100;i++){ |
||||
parsedTilesetInfo.AnimationData[previousTagID].push_back(newTag.GetInteger("tileid")); |
||||
} |
||||
} |
||||
if (newTag.tag=="object"&&previousTag=="tile"){ |
||||
TileCollisionData data; |
||||
data.collision=geom2d::rect<float>{{newTag.GetFloat("x"),newTag.GetFloat("y")},{newTag.GetFloat("width"),newTag.GetFloat("height")}}; |
||||
if(!parsedTilesetInfo.CollisionData.count(previousTagID)){ |
||||
parsedTilesetInfo.CollisionData[previousTagID]=data; |
||||
} |
||||
} |
||||
} |
||||
TSXParser::TSXParser(std::string file) |
||||
:previousTagID(-1){ |
||||
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!
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
#endif |
Loading…
Reference in new issue