yupplemayham/YuppleMayham/include/utility/xmlloader.h

190 lines
No EOL
4.7 KiB
C++

#ifndef _H_XMLLOADER_H
#define _H_XMLLOADER_H
#include <vector>
#include <string>
#include <memory>
#include <unordered_map>
#include <glm/glm.hpp>
#include <sstream>
#include <fstream>
#include <filesystem>
#include <tinyxml2.h>
struct Tile;
struct EntityData {
bool isPlayer;
bool animated;
int x = 0, y = 0;
std::string graphic;
std::string weapon = "pistolGun";
std::string script;
};
struct MapData {
std::string name;
struct TileSet {
int startID = 1;
std::string path;
};
std::vector<TileSet> tileSets;
int width = 0, height = 0;
float tileSize = 32.f;
// 3D array, 0: layer, 1: y, 2: x
// Holding tile startID + ids, 0 is an empty tile
std::vector<std::vector<std::vector<int>>> tiles;
};
struct TileSetData {
std::string name;
std::string type;
std::string file;
int width = 0, height = 0;
int columns = 0;
int tileCount = 0;
float tileSize = 64.f;
struct TileData {
int id = 0;
std::string type;
bool walkable = true;
struct ObjectData {
int id = 0;
std::string name;
glm::vec2 pos;
glm::vec2 size;
bool collidable = false;
bool pickup = false;
};
std::vector<std::shared_ptr<ObjectData>> objects;
};
std::vector<std::shared_ptr<TileData>> tiles;
};
struct SceneData {
std::string id;
std::string type;
std::string bgFile;
std::shared_ptr<MapData> map;
std::vector<EntityData> entities;
};
struct WeaponData {
std::string name;
float fireSpeed = 250.0f;
int clipSize = 21;
int maxAmmo = 512;
std::string script = "";
std::string graphic;
std::string animSet;
bool animated = false;
float sizeX = 50.f, sizeY = 50.f;
float offsetX = 0.f, offsetY = 0.f;
float bulletSizeX = 50.f, bulletSizeY = 50.f;
std::string bulletGraphic;
bool bulletAnimated = false;
float bulletSpread = 1.0f, bulletSpeed = 3.0f, bulletDrop = 500.f;
float modMin = 0.5f, modMax = 1.0f;
};
struct AnimationData {
std::string name;
std::string type;
std::string spriteAtlas;
// Each entity will have a set of animations,
// this animation set is meant to keep each group
// of animations within their set.
// The actual set name is based on the file the animation
// is held in.
std::string animSet;
bool directional = false;
bool oneShot;
float FPS = 1.f;
float frameSize;
};
class XMLLoader
{
public:
XMLLoader() {}
bool loadScenes(const char* sceneFolder);
bool loadWeapons(const char* weaponFolder);
bool loadAnimations(const char* animationFolder);
bool loadTileSets(const char* tileSetFolder);
bool loadMaps(const char* mapFolder);
const std::shared_ptr<SceneData> getSceneData(const std::string& id) const {
try {
return scenes.at(id);
}
catch (std::exception&) {
return nullptr;
}
}
const std::shared_ptr<MapData> getMapData(const std::string& name) const {
try {
return maps.at(name);
}
catch (std::exception&) {
return nullptr;
}
}
const std::shared_ptr<WeaponData> getWeaponData(const std::string& name) const {
try {
return weapons.at(name);
}
catch (std::exception&) {
return nullptr;
}
}
const std::shared_ptr<AnimationData> getAnimationData(const std::string& name) const {
try {
return animations.at(name);
}
catch (std::exception&) {
return nullptr;
}
}
const std::shared_ptr<TileSetData> getTileSetData(const std::string& name) const {
try {
return tileSets.at(name);
}
catch (std::exception&) {
return nullptr;
}
}
// return a full set of animations, may need further optimization.
// one idea is when loading animations we create a seperate map that holds each set by their reference, so we can just do a simple,
// hash table lookup.
std::vector<std::shared_ptr<AnimationData>> getAnimationSet(const std::string& set) const {
std::vector<std::shared_ptr<AnimationData>> animSet;
animSet.reserve(animations.size());
for (const auto& [name, anim] : animations) {
if (anim->animSet == set) animSet.push_back(anim);
}
animSet.shrink_to_fit();
return animSet;
}
void clearData() { scenes.clear(); weapons.clear(); animations.clear(); maps.clear(); tileSets.clear(); }
protected:
bool loadXmlScene(const char* xmlFile, SceneData* out);
bool loadEntityData(const char* xmlFile, SceneData* out);
bool loadTile(tinyxml2::XMLElement* tileElement, TileSetData::TileData* out);
bool loadObject(tinyxml2::XMLElement* objectElement, TileSetData::TileData::ObjectData* out);
private:
std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
std::unordered_map<std::string, std::shared_ptr<WeaponData>> weapons;
std::unordered_map<std::string, std::shared_ptr<AnimationData>> animations;
std::unordered_map<std::string, std::shared_ptr<MapData>> maps;
std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets;
};
#endif // _H_XMLLOADER_H