Implemented reading spawn zones on maps. Monsters now spawn according to spawn zones.

pull/28/head
sigonasr2 1 year ago
parent 9a2af45245
commit 57d7f3344b
  1. 2
      Crawler/Class.cpp
  2. 14
      Crawler/Crawler.cpp
  3. 2
      Crawler/Player.cpp
  4. 144
      Crawler/TMXParser.h
  5. 2
      Crawler/Version.h
  6. 56
      Crawler/assets/Campaigns/1_1.tmx

@ -102,7 +102,7 @@ bool Warrior::AutoAttack(){
bool Warrior::Ability1(){
ACCESS_PLAYER
game->AddEffect(Effect(p.pos,0.1,AnimationState::BATTLECRY_EFFECT,1,0.3));
game->AddEffect(Effect(p.pos,0.1,AnimationState::BATTLECRY_EFFECT,p.upperLevel,1,0.3));
p.AddBuff(BuffType::ATTACK_UP,10,0.1);
p.AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
for(Monster&m:MONSTER_LIST){

@ -1034,16 +1034,18 @@ void Crawler::LoadLevel(MapName map){
foregroundTileGroups.clear();
currentLevel=map;
WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height};
for(SpawnerTag&spawner:MAP_DATA[map].SpawnerData){
for(auto key:MAP_DATA[map].SpawnerData){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first];
std::vector<std::pair<MonsterName,vf2d>>monster_list;
vf2d spawnerRadius=vf2d{spawner.ObjectData.GetFloat("width"),spawner.ObjectData.GetFloat("height")}/2;
for(XMLTag&property:spawner.properties){
int monsterTypeID=property.GetInteger("value")-1;
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
for(XMLTag&monster:spawnData.monsters){
int monsterTypeID=monster.GetInteger("value")-1;
if(monsterTypeID>=0&&monsterTypeID<MonsterName::END){
monster_list.push_back({MonsterName(monsterTypeID),{rand()%int(spawnerRadius.x)-spawnerRadius.x/2,rand()%int(spawnerRadius.y)-spawnerRadius.y/2}});
monster_list.push_back({MonsterName(monsterTypeID),{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
}
}
SPAWNER_LIST.push_back(MonsterSpawner{{spawner.ObjectData.GetFloat("x")+spawnerRadius.x,spawner.ObjectData.GetFloat("y")+spawnerRadius.y},spawnerRadius,monster_list});
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list});
}
for(int x=0;x<WORLD_SIZE.x;x++){
for(int y=0;y<WORLD_SIZE.y;y++){

@ -392,7 +392,7 @@ Key Player::GetFacingDirection(){
void Player::Moved(){
for(MonsterSpawner&spawner:SPAWNER_LIST){
if(!spawner.SpawnTriggered()&&geom2d::contains(geom2d::ellipse<float>{spawner.GetPos(),spawner.GetRange()},pos)){
if(!spawner.SpawnTriggered()&&geom2d::contains(geom2d::rect<float>{spawner.GetPos(),spawner.GetRange()},pos)){
spawner.SetTriggered(true);
}
}

@ -31,7 +31,7 @@ struct LayerTag{
struct SpawnerTag{
XMLTag ObjectData;
std::vector<XMLTag>properties;
std::vector<XMLTag>monsters;
std::string str();
friend std::ostream& operator << (std::ostream& os, SpawnerTag& rhs);
};
@ -40,10 +40,10 @@ struct Map{
MapTag MapData;
std::vector<XMLTag> TilesetData;
std::vector<LayerTag> LayerData;
std::vector<SpawnerTag> SpawnerData;
std::map<int,SpawnerTag> SpawnerData; //Spawn groups have IDs, mobs associate which spawner they are tied to via this ID.
std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles);
std::string FormatSpawnerData(std::ostream& os, std::vector<SpawnerTag>tiles);
std::string FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles);
friend std::ostream& operator << (std::ostream& os, Map& rhs);
friend std::ostream& operator << (std::ostream& os, std::vector<XMLTag>& rhs);
};
@ -56,6 +56,10 @@ class TMXParser{
bool buildingSpawner=false;
SpawnerTag obj;
void ParseTag(std::string tag);
int monsterPropertyTagCount=-1;
XMLTag monsterTag;
XMLTag spawnerLinkTag;
std::vector<XMLTag>accumulatedMonsterTags;
public:
TMXParser(std::string file);
};
@ -108,8 +112,8 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
}
std::string SpawnerTag::str() {
std::string displayStr=ObjectData.tag+"\n"+ObjectData.FormatTagData(ObjectData.data);
for(XMLTag tag:properties){
displayStr+=" ("+tag.FormatTagData(tag.data)+" )\n";
for(XMLTag&monster:monsters){
displayStr+=" ("+monster.FormatTagData(monster.data)+" )\n";
}
return displayStr;
}
@ -124,10 +128,10 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
}
return displayStr;
}
std::string Map::FormatSpawnerData(std::ostream& os, std::vector<SpawnerTag>tiles) {
std::string Map::FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles) {
std::string displayStr;
for (int i=0;i<SpawnerData.size();i++) {
displayStr+=SpawnerData[i].str();
for (auto key:SpawnerData) {
displayStr+=SpawnerData[key.first].str();
}
return displayStr;
}
@ -150,51 +154,58 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
return parsedMapInfo;
}
void TMXParser::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==' '&&quotationMarkCount%2==0){
valid=true;
break;
}
data+=character;
if(pastEquals&&quotationMarkCount%2==0){
valid=true;
break;
}
if(character=='='&&quotationMarkCount%2==0){
pastEquals=true;
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==' '&&quotationMarkCount%2==0){
valid=true;
break;
}
data+=character;
if(pastEquals&&quotationMarkCount%2==0){
valid=true;
break;
}
if(character=='='&&quotationMarkCount%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);
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);
//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";
newTag.data[key]=value;
std::cout<<" "<<key<<":"<<newTag.data[key]<<"\n";
}
}
}
}
return newTag;
};
XMLTag newTag=ReadNextTag();
if (newTag.tag=="map") {
parsedMapInfo.MapData={stoi(newTag.data["width"]),stoi(newTag.data["height"])};
@ -207,12 +218,7 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
parsedMapInfo.LayerData.push_back(l);
}else
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup") {
if(buildingSpawner){
parsedMapInfo.SpawnerData.push_back(obj);
}
buildingSpawner=true;
obj={newTag};
goto spawnerResetSkip;
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
} else
if (newTag.tag=="object"&&newTag.data["type"]=="PlayerSpawnLocation") {
parsedMapInfo.MapData.playerSpawnLocation={newTag.GetInteger("x")-newTag.GetInteger("width")/2,newTag.GetInteger("y")-newTag.GetInteger("height")/2};
@ -232,19 +238,25 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
parsedMapInfo.ZoneData[newTag.data["type"]]=zones;
}
}else
if (newTag.tag=="property"&&buildingSpawner) {
if(newTag.data["propertytype"]=="MonsterName"){
obj.properties.push_back(newTag);
}
goto spawnerResetSkip;
if (newTag.tag=="object"&&newTag.data["type"]=="Monster") {
//XMLTag monsterTag=ReadNextTag();
//XMLTag spawnerLinkTag=ReadNextTag();
//newTag.data["value"]=monsterTag.GetInteger("value"); //Value now contains which monster name this spawn represents.
monsterTag=newTag;
monsterPropertyTagCount=0;
} else
if (newTag.tag=="property"&&monsterPropertyTagCount==0) {
monsterTag.data["value"]=newTag.data["value"];
monsterPropertyTagCount++;
} else
if (newTag.tag=="property"&&monsterPropertyTagCount==1) {
spawnerLinkTag=newTag;
monsterTag.data["spawnerLink"]=spawnerLinkTag.data["value"];
accumulatedMonsterTags.push_back(monsterTag);
monsterPropertyTagCount=-1;
} else {
std::cout<<"Unsupported tag format! Ignoring."<<"\n";
}
if(buildingSpawner){
parsedMapInfo.SpawnerData.push_back(obj);
}
buildingSpawner=false;
spawnerResetSkip:
std::cout<<"\n"<<"=============\n";
}
TMXParser::TMXParser(std::string file){
@ -289,8 +301,8 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
}
}
if(buildingSpawner){
parsedMapInfo.SpawnerData.push_back(obj);
for(XMLTag&monster:accumulatedMonsterTags){
parsedMapInfo.SpawnerData[monster.GetInteger("spawnerLink")].monsters.push_back(monster);
}
std::cout<<"Parsed Map Data:\n"<<parsedMapInfo<<"\n";

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 528
#define VERSION_BUILD 547
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="192" height="203" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="45">
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="192" height="203" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="59">
<tileset firstgid="1" source="../maps/grass_tiles_24x24.tsx"/>
<tileset firstgid="784" source="../maps/grass_tiles_modded.tsx"/>
<layer id="5" name="Collision Layer" width="192" height="203">
@ -1044,7 +1044,6 @@
<object id="8" name="Spawn Group 2" type="SpawnGroup" x="1461.33" y="3090.67" width="521.333" height="534.667">
<ellipse/>
</object>
<object id="10" name="Spawn Group 3" type="SpawnGroup" x="2261.33" y="3040" width="242.667" height="592"/>
<object id="12" name="Spawn Group 4" type="SpawnGroup" x="3029.33" y="2946.67" width="513.333" height="509.333">
<ellipse/>
</object>
@ -1054,9 +1053,6 @@
<object id="14" name="Spawn Group 6" type="SpawnGroup" x="3182.67" y="1885.33" width="625.333" height="249.333">
<ellipse/>
</object>
<object id="15" x="3352" y="2328">
<ellipse/>
</object>
<object id="16" name="Spawn Group 7" type="SpawnGroup" x="3109.33" y="1048" width="729.333" height="225.333">
<ellipse/>
</object>
@ -1133,6 +1129,56 @@
<point/>
</object>
<object id="44" name="Player Spawn" type="PlayerSpawnLocation" x="456" y="3288" width="24" height="24"/>
<object id="45" name="Blue Slime" type="Monster" x="1560" y="3270">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="52" name="Blue Slime" type="Monster" x="1578" y="3402">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="53" name="Blue Slime" type="Monster" x="2292" y="3204">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="58"/>
</properties>
<point/>
</object>
<object id="54" name="Blue Slime" type="Monster" x="1746" y="3174">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="55" name="Blue Slime" type="Monster" x="1860" y="3336">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="56" name="Blue Slime" type="Monster" x="1776" y="3420">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="57" name="Blue Slime" type="Monster" x="1704" y="3240">
<properties>
<property name="Type" type="int" propertytype="MonsterName" value="2"/>
<property name="spawner" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="58" name="Spawn Group 3" type="SpawnGroup" x="2220" y="3018" width="242.667" height="592"/>
</objectgroup>
<objectgroup id="7" name="Transition Layerxzs">
<object id="40" type="LowerZone" x="1596" y="1134" width="372" height="684"/>

Loading…
Cancel
Save