246 lines
6.3 KiB
C++
246 lines
6.3 KiB
C++
#ifndef _H_XMLLOADER_H
|
|
#define _H_XMLLOADER_H
|
|
|
|
#include <functional>
|
|
#include <glm/glm.hpp>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <tinyxml2.h>
|
|
|
|
struct Tile;
|
|
|
|
// Except for the player, these definitions are mostly overrides of the monster
|
|
// data
|
|
struct EntityData {
|
|
bool isPlayer;
|
|
bool animated;
|
|
int x = 0, y = 0;
|
|
float hp;
|
|
std::string monsterDef;
|
|
std::string graphic;
|
|
std::string weapon = "gun/pistol";
|
|
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;
|
|
|
|
const MapData *map;
|
|
std::vector<EntityData> entities;
|
|
};
|
|
|
|
// Store our script as a string so we only need to read the file at boot
|
|
struct ScriptData {
|
|
std::string id;
|
|
std::string fileName;
|
|
std::string script;
|
|
};
|
|
|
|
struct WeaponData {
|
|
std::string id;
|
|
float fireSpeed = 250.0f;
|
|
int clipSize = 21;
|
|
int maxAmmo = 512;
|
|
std::string script = "";
|
|
std::string graphic;
|
|
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;
|
|
};
|
|
|
|
// ID is the new tactic I've decided on.
|
|
// Each animationable object will be given a prefix
|
|
// denoting their type and object so <type>/<object>
|
|
// This prefix will be used to look up the animation on
|
|
// the animation map
|
|
struct AnimationData {
|
|
std::string id;
|
|
std::string spriteAtlas;
|
|
bool directional = false;
|
|
bool oneShot;
|
|
float FPS = 1.f;
|
|
float frameSize;
|
|
};
|
|
|
|
// This holds a lot of defaults, but the scene can
|
|
// override a large portion of the definitions here
|
|
struct MonsterData {
|
|
std::string id;
|
|
std::string anim;
|
|
std::string weapon;
|
|
bool aggressive = false;
|
|
std::string behaviour;
|
|
float hp;
|
|
};
|
|
|
|
struct SoundData {
|
|
std::string id; // <type>/<object>/<state>
|
|
std::string path;
|
|
bool spatial;
|
|
};
|
|
|
|
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);
|
|
bool loadMonsters(const char *monsterFolder);
|
|
// luaLoader is the function we use to load the lua file.
|
|
// This will be defined in our resource manager
|
|
bool loadScripts(const char *scriptFolder,
|
|
std::function<bool(ScriptData *)> luaLoader);
|
|
bool loadSoundEffects(const char *soundFolder);
|
|
|
|
const SceneData *getSceneData(const std::string &id) const {
|
|
try {
|
|
return scenes.at(id).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const ScriptData *getScriptData(const std::string &id) const {
|
|
try {
|
|
return scripts.at(id).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const MapData *getMapData(const std::string &name) const {
|
|
try {
|
|
return maps.at(name).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const WeaponData *getWeaponData(const std::string &id) const {
|
|
try {
|
|
return weapons.at(id).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const AnimationData *getAnimationData(const std::string &id) const {
|
|
try {
|
|
return animations.at(id).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const TileSetData *getTileSetData(const std::string &name) const {
|
|
try {
|
|
return tileSets.at(name).get();
|
|
} catch (std::exception &) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const SoundData *getSoundData(const std::string &id) const {
|
|
try {
|
|
return sounds.at(id).get();
|
|
} 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<AnimationData *>
|
|
getAnimationSet(const std::string &prefix) const {
|
|
std::vector<AnimationData *> animSet;
|
|
animSet.reserve(animations.size());
|
|
for (const auto &[id, anim] : animations) {
|
|
if (id.starts_with(prefix))
|
|
animSet.push_back(anim.get());
|
|
}
|
|
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::unique_ptr<SceneData>> scenes;
|
|
std::unordered_map<std::string, std::unique_ptr<ScriptData>> scripts;
|
|
std::unordered_map<std::string, std::unique_ptr<WeaponData>> weapons;
|
|
std::unordered_map<std::string, std::unique_ptr<AnimationData>> animations;
|
|
std::unordered_map<std::string, std::unique_ptr<MonsterData>> monsters;
|
|
std::unordered_map<std::string, std::unique_ptr<MapData>> maps;
|
|
std::unordered_map<std::string, std::unique_ptr<TileSetData>> tileSets;
|
|
std::unordered_map<std::string, std::unique_ptr<SoundData>> sounds;
|
|
};
|
|
|
|
#endif // _H_XMLLOADER_H
|