diff --git a/data/monsters/monsters.json b/data/monsters/monsters.json new file mode 100644 index 0000000..3880c02 --- /dev/null +++ b/data/monsters/monsters.json @@ -0,0 +1,30 @@ +{ + "monsters": [ + { + "race": "bat", + "radius": 16.0, + "health": 30.0, + "speed": 1.0, + "attack": { + "cooldownDuration": 1500.0, + "range": 40.0, + "damage": 5.0, + "animation": "slash", + "animationDuration": 300.0 + } + }, + { + "race": "bee", + "radius": 16.0, + "health": 30.0, + "speed": 1.0, + "attack": { + "cooldownDuration": 1500.0, + "range": 40.0, + "damage": 5.0, + "animation": "slash", + "animationDuration": 300.0 + } + } + ] +} diff --git a/src/saland/GameMonsters.cpp b/src/saland/GameMonsters.cpp new file mode 100644 index 0000000..1e68af8 --- /dev/null +++ b/src/saland/GameMonsters.cpp @@ -0,0 +1,122 @@ +/* +=========================================================================== + * Saland Adventures +Copyright (C) 2014-2017 Poul Sander + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see http://www.gnu.org/licenses/ + +Source information and contacts persons can be found at +https://github.com/sago007/saland +=========================================================================== +*/ + +#include "GameMonsters.hpp" +#include +#include "../sago/SagoMisc.hpp" +#include "rapidjson/document.h" +#include + +static std::unordered_map all_monsters; + +static void LoadMonsterDefinitions() { + if (!all_monsters.empty()) { + return; // Already loaded + } + + std::string filename = "monsters/monsters.json"; + std::string content = sago::GetFileContent(filename.c_str()); + rapidjson::Document document; + document.Parse(content.c_str()); + + if (!document.IsObject()) { + std::cerr << "Failed to parse: " << filename << "\n"; + return; + } + + for (auto& m : document.GetObject()) { + const std::string& header = m.name.GetString(); + if (header == "monsters") { + const auto& monsters = m.value; + if (!monsters.IsArray()) { + std::cerr << "Failure reading " << filename << ": 'monsters' must be an array\n"; + continue; + } + + for (const auto& monster : monsters.GetArray()) { + if (!monster.IsObject()) { + continue; + } + + MonsterDef def; + std::string race; + for (const auto& member : monster.GetObject()) { + std::string memberName = member.name.GetString(); + + if (memberName == "race") { + race = member.value.GetString(); + def.race = race; + } + else if (memberName == "radius") { + def.radius = member.value.GetFloat(); + } + else if (memberName == "health") { + def.health = member.value.GetFloat(); + } + else if (memberName == "speed") { + def.speed = member.value.GetFloat(); + } + else if (memberName == "attack" && member.value.IsObject()) { + for (const auto& attackMember : member.value.GetObject()) { + std::string attackName = attackMember.name.GetString(); + if (attackName == "cooldownDuration") { + def.attack.cooldownDuration = attackMember.value.GetFloat(); + } + else if (attackName == "range") { + def.attack.range = attackMember.value.GetFloat(); + } + else if (attackName == "damage") { + def.attack.damage = attackMember.value.GetFloat(); + } + else if (attackName == "animation") { + def.attack.animation = attackMember.value.GetString(); + } + else if (attackName == "animationDuration") { + def.attack.animationDuration = attackMember.value.GetFloat(); + } + } + } + } + + if (!race.empty()) { + all_monsters[race] = def; + } + } + } + } +} + +MonsterDef GetMonsterDefByRace(const std::string& race) { + LoadMonsterDefinitions(); + + auto it = all_monsters.find(race); + if (it != all_monsters.end()) { + return it->second; + } + + // Return default if not found + std::cerr << "Warning: Monster race '" << race << "' not found in monsters.json\n"; + MonsterDef def; + def.race = race; + return def; +} diff --git a/src/saland/GameMonsters.hpp b/src/saland/GameMonsters.hpp new file mode 100644 index 0000000..c699027 --- /dev/null +++ b/src/saland/GameMonsters.hpp @@ -0,0 +1,31 @@ +/* +=========================================================================== + * Saland Adventures +Copyright (C) 2014-2017 Poul Sander + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see http://www.gnu.org/licenses/ + +Source information and contacts persons can be found at +https://github.com/sago007/saland +=========================================================================== +*/ + +#ifndef GAMEMONSTERS_HPP +#define GAMEMONSTERS_HPP + +#include "GameRegion.hpp" + +MonsterDef GetMonsterDefByRace(const std::string& race); + +#endif /* GAMEMONSTERS_HPP */ diff --git a/src/saland/GameRegion.cpp b/src/saland/GameRegion.cpp index 5f4b9ce..6fec626 100644 --- a/src/saland/GameRegion.cpp +++ b/src/saland/GameRegion.cpp @@ -23,6 +23,7 @@ https://github.com/sago007/saland #include "GameRegion.hpp" #include "GameItems.hpp" +#include "GameMonsters.hpp" #include #include @@ -38,31 +39,31 @@ static std::string createFileName(int x, int y,const std::string& worldName) { void GameRegion::SpawnMonster(const MonsterDef& def, float destX, float destY) { - std::shared_ptr bat = std::make_shared(); - bat.get()->Radius = def.radius; - bat.get()->race = def.race; - bat.get()->X = destX; - bat.get()->Y = destY; - if (def.race == "bat") { - bat.get()->health = 30; - } - placeables.push_back(bat); - - b2BodyDef batBodyDef; - batBodyDef.type = b2_dynamicBody; - batBodyDef.position.Set(0, 0); - batBodyDef.linearDamping = 1.0f; - bat->body = physicsBox->CreateBody(&batBodyDef); + std::shared_ptr monster = std::make_shared(); + monster.get()->Radius = def.radius; + monster.get()->race = def.race; + monster.get()->X = destX; + monster.get()->Y = destY; + monster.get()->health = def.health; + monster.get()->speed = def.speed; + monster.get()->attack = def.attack; + placeables.push_back(monster); + + b2BodyDef monsterBodyDef; + monsterBodyDef.type = b2_dynamicBody; + monsterBodyDef.position.Set(0, 0); + monsterBodyDef.linearDamping = 1.0f; + monster->body = physicsBox->CreateBody(&monsterBodyDef); b2CircleShape circleShape; circleShape.m_p.Set(0, 0); //position, relative to body position circleShape.m_radius = def.radius/32.0f; //32 pixel = 1 unit - b2FixtureDef batDef; - batDef.shape = &circleShape; - batDef.density = 10.0f; - bat->body->CreateFixture(&batDef); - bat->body->SetTransform(b2Vec2(bat.get()->X / 32.0f, bat.get()->Y / 32.0f),bat->body->GetAngle()); + b2FixtureDef monsterFixtureDef; + monsterFixtureDef.shape = &circleShape; + monsterFixtureDef.density = 10.0f; + monster->body->CreateFixture(&monsterFixtureDef); + monster->body->SetTransform(b2Vec2(monster.get()->X / 32.0f, monster.get()->Y / 32.0f),monster->body->GetAngle()); } static bool Intersect(const Placeable& p1, const Placeable& p2) { @@ -371,13 +372,10 @@ void GameRegion::Init(int x, int y, const std::string& worldName, bool forceRese SpawnPrefab(getPrefab("basic_house"), 32, 32); - MonsterDef batDef; - batDef.radius = 16.0f; - batDef.race = "bat"; + MonsterDef batDef = GetMonsterDefByRace("bat"); SpawnMonster(batDef, 200.0f, 200.0f); SpawnMonster(batDef, 1200.0f, 1400.0f); - MonsterDef beeDef = batDef; - beeDef.race = "bee"; + MonsterDef beeDef = GetMonsterDefByRace("bee"); SpawnMonster(beeDef, 220.0f, 220.0f); } diff --git a/src/saland/GameRegion.hpp b/src/saland/GameRegion.hpp index 47ba584..0919617 100644 --- a/src/saland/GameRegion.hpp +++ b/src/saland/GameRegion.hpp @@ -35,6 +35,9 @@ https://github.com/sago007/saland struct MonsterDef { float radius = 1.0f; std::string race = ""; + float health = 30.0f; + float speed = 1.0f; + MonsterAttack attack; };