: item(nullptr), count(0) {}
};
+struct UseItemEvent {
+ Item* item;
+ vec2 curs;
+
+ UseItemEvent(Item* i, vec2 c)
+ : item(i), curs(c) {}
+};
+
/**
* @class InventorySystem
* Handles the player's inventory system.
*/
class InventorySystem : public entityx::System<InventorySystem>, public entityx::Receiver<InventorySystem> {
private:
+ constexpr static const char* itemsPath = "config/items.xml";
+ constexpr static int entrySize = 70;
+ constexpr static int hotbarSize = 4;
+ constexpr static float inventoryZ = -5.0f;
+ constexpr static unsigned int rowSize = 8;
+
+ /**
+ * A 'database' of all existing items.
+ */
+ std::unordered_map<std::string, Item> itemList;
+
/**
* A vector for the player's inventory slots.
*/
std::vector<InventoryEntry> items;
- void loadItems(void);
+ vec2 hotStart, hotEnd;
+ vec2 fullStart, fullEnd;
+
+ int movingItem = -1;
+ bool fullInventory = false;
+
+ void loadItems(void);
public:
- InventorySystem(int size = 20) {
- items.resize(size);
- loadItems();
- }
+ InventorySystem(int size = 20);
void configure(entityx::EventManager &ev);
void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
return n >= 0 ? n : -n;
}
+bool inrange(float point, float left, float right, float range)
+{
+ return (left < point + range && left > point - range) ||
+ (right < point + range && right > point - range) ||
+ (point > left && point < right);
+}
void AttackSystem::receive(const AttackEvent& ae)
{
if (e.has_component<Player>())
return;
- if ((pos.x > a.pos.x && pos.x < a.pos.x + shortSlashLength) ||
- (pos.x + dim.width < a.pos.x && pos.x + dim.width > a.pos.x - shortSlashLength)) {
+ if (inrange(a.pos.x, pos.x, pos.x + dim.width, shortSlashLength)) {
h.health -= a.power;
- game::engine.getSystem<ParticleSystem>()->addMultiple(10, ParticleType::DownSlash,
+ game::engine.getSystem<ParticleSystem>()->addMultiple(15, ParticleType::DownSlash,
[&](){ return vec2(pos.x + dim.width / 2, pos.y + dim.height / 2); }, 300, 7);
}
}
extern vec2 offset;
-static std::unordered_map<std::string, Item> itemList;
-constexpr const char* itemsPath = "config/items.xml";
-
-static bool fullInventory = false;
-
-constexpr int entrySize = 70;
-constexpr int hotbarSize = 4;
-constexpr float inventoryZ = -5.0f;
-constexpr unsigned int rowSize = 8;
+inline bool isGoodEntry(const InventoryEntry& ie) {
+ return (ie.item != nullptr) && (ie.count > 0);
+}
-static int movingItem = -1;
+InventorySystem::InventorySystem(int size)
+{
+ items.resize(size);
+ loadItems();
+}
void InventorySystem::configure(entityx::EventManager &ev)
{
for (unsigned int i = 1; i < hotbarSize; i++)
items[i].loc = vec2(items[i - 1].loc.x + entrySize, items[i - 1].loc.y);
- ui::drawNiceBox(items[0].loc - 10, items[hotbarSize - 1].loc + vec2(entrySize + 4, entrySize + 10), inventoryZ);
+ hotStart = items[0].loc - 10;
+ hotEnd = items[hotbarSize - 1].loc + vec2(entrySize + 4, entrySize + 10);
+ ui::drawNiceBox(hotStart, hotEnd, inventoryZ);
if (fullInventory) {
vec2 start (offset.x - entrySize * rowSize / 2, offset.y + game::SCREEN_HEIGHT / 2 - 180);
start.y -= entrySize;
}
- ui::drawNiceBox(items[items.size() - rowSize].loc - 10, items[hotbarSize + rowSize - 1].loc + (entrySize + 4), inventoryZ);
+ fullStart = items[items.size() - rowSize].loc - 10;
+ fullEnd = items[hotbarSize + rowSize - 1].loc + (entrySize + 4);
+ ui::drawNiceBox(fullStart, fullEnd, inventoryZ);
} else {
size = hotbarSize;
}
glUniform4f(Render::textShader.uniform[WU_tex_color], 1, 1, 1, 1);
// draw the item
- if (i.item != nullptr && i.count > 0) {
+ if (isGoodEntry(i)) {
i.item->sprite.use();
glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
}
}
- if (items[0].item != nullptr && items[0].count > 0) {
+ if (isGoodEntry(items[0])) {
Render::textShader.use();
Render::textShader.enable();
e.destroy();
}
});
- } else {
- int end = fullInventory ? items.size() : hotbarSize;
- movingItem = -1;
- for (int i = 0; i < end; i++) {
- if (items[i].item == nullptr || items[i].count == 0)
- continue;
-
- if (mce.position > items[i].loc && mce.position < items[i].loc + entrySize) {
- movingItem = i;
- break;
+ } else if (mce.button == SDL_BUTTON_LEFT) {
+ if ((mce.position > hotStart && mce.position < hotEnd) ||
+ (fullInventory && mce.position > fullStart && mce.position < fullEnd)) {
+ int end = fullInventory ? items.size() : hotbarSize;
+ movingItem = -1;
+ for (int i = 0; i < end; i++) {
+ if (!isGoodEntry(items[i]))
+ continue;
+
+ if (mce.position > items[i].loc && mce.position < items[i].loc + entrySize) {
+ movingItem = i;
+ break;
+ }
}
+ } else if (isGoodEntry(items[0])) {
+ game::events.emit<UseItemEvent>(items[0].item, mce.position);
}
}
}
int end = fullInventory ? items.size() : hotbarSize;
for (int i = 0; i < end; i++) {
if (mre.position > items[i].loc && mre.position < items[i].loc + entrySize) {
- if (items[i].count > 0) {
+ if (isGoodEntry(items[i])) {
std::swap(items[movingItem], items[i]);
} else {
items[i] = items[movingItem];
auto& ie = *i;
// update the slot
- if (ie.item == nullptr) {
+ if (!isGoodEntry(ie)) {
ie.item = &itemList[name];
ie.count = count;
} else {
while (taken < count) {
auto i = std::find_if(next, items.end(),
[&name](const InventoryEntry& ie) {
- return ie.item != nullptr && ie.item->name == name;
+ return isGoodEntry(ie) && ie.item->name == name;
});
if (i >= items.end())
{
ev.subscribe<KeyUpEvent>(*this);
ev.subscribe<KeyDownEvent>(*this);
+ ev.subscribe<UseItemEvent>(*this);
}
void PlayerSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) {
} 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
auto& loc = *game::entities.component<Position>(player.id()).get();
return vec2(loc.x, loc.y);
}
+
+void PlayerSystem::receive(const UseItemEvent& uie)
+{
+ if (uie.item->type == "Sword") {
+ auto loc = getPosition();
+ auto &solid = *player.component<Solid>().get();
+ loc.x += solid.width / 2, loc.y += solid.height / 2;
+ game::events.emit<AttackEvent>(loc, AttackType::ShortSlash);
+ }
+}