aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--include/attack.hpp39
-rw-r--r--include/components.hpp6
-rw-r--r--include/vector2.hpp4
-rw-r--r--src/attack.cpp54
-rw-r--r--src/components.cpp2
-rw-r--r--src/engine.cpp3
-rw-r--r--src/player.cpp4
-rw-r--r--xml/entities.xml2
9 files changed, 113 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index d913368..a554d64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ brice.dat
config/settings.xml
setup.mk
TODOS
+out/*
+screenshots/*
diff --git a/include/attack.hpp b/include/attack.hpp
new file mode 100644
index 0000000..412694e
--- /dev/null
+++ b/include/attack.hpp
@@ -0,0 +1,39 @@
+#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_
diff --git a/include/components.hpp b/include/components.hpp
index 541f0f8..0fb8ec6 100644
--- a/include/components.hpp
+++ b/include/components.hpp
@@ -172,7 +172,9 @@ struct Health : public Component {
(void)imp;
(void)def;
// TODO
- health = maxHealth = 1;
+ if (def->QueryIntAttribute("value", &health) != XML_NO_ERROR)
+ health = 1;
+ maxHealth = health;
}
};
@@ -208,6 +210,8 @@ struct Name : public Component {
}
};
+struct Player {};
+
struct ItemDrop {
ItemDrop(InventoryEntry& ie)
: item(ie) {}
diff --git a/include/vector2.hpp b/include/vector2.hpp
index c1148da..828654c 100644
--- a/include/vector2.hpp
+++ b/include/vector2.hpp
@@ -84,6 +84,10 @@ struct vector2 {
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) + ")";
diff --git a/src/attack.cpp b/src/attack.cpp
new file mode 100644
index 0000000..226fe2f
--- /dev/null
+++ b/src/attack.cpp
@@ -0,0 +1,54 @@
+#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();
+}
+
diff --git a/src/components.cpp b/src/components.cpp
index 644d504..f4ac01e 100644
--- a/src/components.cpp
+++ b/src/components.cpp
@@ -182,7 +182,7 @@ void RenderSystem::render(void)
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,
diff --git a/src/engine.cpp b/src/engine.cpp
index ee35d06..640356e 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -11,6 +11,7 @@
#include <quest.hpp>
#include <particle.hpp>
#include <weather.hpp>
+#include <attack.hpp>
Engine::Engine(void)
: shouldRun(true), systems(game::entities, game::events)
@@ -35,6 +36,7 @@ void Engine::init(void) {
systems.add<ParticleSystem>();
systems.add<WeatherSystem>();
+ systems.add<AttackSystem>();
systems.configure();
@@ -54,6 +56,7 @@ void Engine::update(entityx::TimeDelta dt)
//systems.update<QuestSystem>(dt); // doesn't do anything
systems.update<WeatherSystem>(dt);
systems.update<ParticleSystem>(dt);
+ systems.update<AttackSystem>(dt);
}
diff --git a/src/player.cpp b/src/player.cpp
index bcde388..0a85459 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -5,6 +5,7 @@
#include <gametime.hpp>
#include <world.hpp>
#include <particle.hpp>
+#include <attack.hpp>
static const char *spriteXML =
"<Sprite> \
@@ -70,6 +71,7 @@ static const char *animationXML =
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);
@@ -198,6 +200,8 @@ void PlayerSystem::receive(const KeyDownEvent &kde)
} 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
diff --git a/xml/entities.xml b/xml/entities.xml
index 5e33b92..fb69086 100644
--- a/xml/entities.xml
+++ b/xml/entities.xml
@@ -62,7 +62,7 @@
</frame>
</Sprite>
<Direction />
- <Health />
+ <Health value="200" />
<Solid />
<Physics />
<Name value="SKIRL" />