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