config/settings.xml\r
setup.mk\r
TODOS\r
+out/*\r
+screenshots/*\r
--- /dev/null
+#ifndef FIGHT_HPP_
+#define FIGHT_HPP_
+
+#include <entityx/entityx.h>
+
+#include <forward_list>
+
+#include <vector2.hpp>
+
+enum class AttackType : char {
+ ShortSlash,
+ LongSlash
+};
+
+struct AttackEvent {
+ AttackEvent(vec2 p, AttackType at, int pow = 10)
+ : pos(p), type(at), power(pow) {}
+
+ vec2 pos;
+ AttackType type;
+ int power;
+};
+
+class AttackSystem : public entityx::System<AttackSystem>, public entityx::Receiver<AttackSystem> {
+private:
+ std::forward_list<AttackEvent> attacks;
+
+public:
+ explicit AttackSystem() = default;
+
+ void configure(entityx::EventManager& ev) {
+ ev.subscribe<AttackEvent>(*this);
+ }
+
+ void receive(const AttackEvent& ae);
+ void update(entityx::EntityManager& en, entityx::EventManager& ev, entityx::TimeDelta dt) override;
+};
+
+#endif // FIGHT_HPP_
(void)imp;
(void)def;
// TODO
- health = maxHealth = 1;
+ if (def->QueryIntAttribute("value", &health) != XML_NO_ERROR)
+ health = 1;
+ maxHealth = health;
}
};
}
};
+struct Player {};
+
struct ItemDrop {
ItemDrop(InventoryEntry& ie)
: item(ie) {}
return (x < v.x) && (y < v.y);
}
+ bool operator<=(const T& n) const {
+ return (x <= n) && (y <= n);
+ }
+
// other functions
std::string toString(void) const {
return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
--- /dev/null
+#include <attack.hpp>
+#include <components.hpp>
+#include <engine.hpp>
+#include <particle.hpp>
+
+constexpr int shortSlashLength = 100;
+constexpr int longSlashLength = 200;
+
+// math helpers because we don't trust stdlib
+template<typename T>
+inline T abs(const T& n) {
+ static_assert(std::is_arithmetic<T>::value, "abs expects numbers");
+ return n >= 0 ? n : -n;
+}
+
+
+void AttackSystem::receive(const AttackEvent& ae)
+{
+ attacks.emplace_front(ae);
+}
+
+void AttackSystem::update(entityx::EntityManager& en, entityx::EventManager& ev, entityx::TimeDelta dt)
+{
+ (void)en;
+ (void)ev;
+ (void)dt;
+
+ for (const auto& a : attacks) {
+ switch (a.type) {
+ case AttackType::ShortSlash:
+ en.each<Position, Solid, Health>(
+ [&a](entityx::Entity e, Position& pos, Solid& dim, Health& h) {
+ (void)e;
+ if (e.has_component<Player>())
+ return;
+ vec2 eloc (pos.x + dim.width / 2, pos.y + dim.height / 2);
+ if (abs(eloc.x - a.pos.x) <= shortSlashLength) {
+ h.health -= a.power;
+ game::engine.getSystem<ParticleSystem>()->addMultiple(10, ParticleType::SmallBlast,
+ [&](){ return eloc; }, 500, 7);
+ }
+ }
+ );
+ break;
+ case AttackType::LongSlash:
+ break;
+ default:
+ break;
+ }
+ }
+
+ attacks.clear();
+}
+
if (entity.has_component<Health>()) {
float width = entity.component<Solid>()->width;
auto& health = *entity.component<Health>();
- width /= health.health / health.maxHealth;
+ width *= health.health / static_cast<float>(health.maxHealth);
GLfloat health_coord[] = {
pos.x, pos.y, -9, 0, 0,
#include <quest.hpp>
#include <particle.hpp>
#include <weather.hpp>
+#include <attack.hpp>
Engine::Engine(void)
: shouldRun(true), systems(game::entities, game::events)
systems.add<ParticleSystem>();
systems.add<WeatherSystem>();
+ systems.add<AttackSystem>();
systems.configure();
//systems.update<QuestSystem>(dt); // doesn't do anything
systems.update<WeatherSystem>(dt);
systems.update<ParticleSystem>(dt);
+ systems.update<AttackSystem>(dt);
}
#include <gametime.hpp>
#include <world.hpp>
#include <particle.hpp>
+#include <attack.hpp>
static const char *spriteXML =
"<Sprite> \
void PlayerSystem::create(void)
{
player = game::entities.create();
+ player.assign<Player>();
player.assign<Position>(0.0f, 100.0f);
player.assign<Direction>(0.0f, 0.0f);
//player.assign<Physics>(-0.001f);
} else if (kc == SDLK_t) {
game::time::tick(50);
}
+ if (kc == SDLK_j)
+ game::events.emit<AttackEvent>(vec2(loc.x, loc.y), AttackType::ShortSlash);
}
vec2 PlayerSystem::getPosition(void) const
</frame>
</Sprite>
<Direction />
- <Health />
+ <Health value="200" />
<Solid />
<Physics />
<Name value="SKIRL" />