Skip to content

Commit

Permalink
replace std::function with templates in EntityGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
silverweed committed Sep 26, 2017
1 parent c960f4b commit 3b079d9
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 86 deletions.
6 changes: 6 additions & 0 deletions src/core/EntityGroup.cpp
Expand Up @@ -77,6 +77,12 @@ void EntityGroup::clear() {
collidingEntities.clear();
}

lif::Entity* EntityGroup::add(lif::Entity *entity) {
entity->init();
entities.emplace_back(entity);
return _putInAux(entities.back().get());
}

lif::Entity* EntityGroup::_putInAux(lif::Entity *entity) {
// Put in aux collections, if not already managed
auto klb = entity->getShared<lif::Killable>();
Expand Down
65 changes: 17 additions & 48 deletions src/core/EntityGroup.hpp
Expand Up @@ -6,6 +6,7 @@
#include <iterator>
#include <unordered_set>
#include <functional>
#include <algorithm>
#include <SFML/System/NonCopyable.hpp>
#include "Entity.hpp"
#include "Temporary.hpp"
Expand All @@ -22,16 +23,6 @@ namespace lif {
class CollisionDetector;
class LevelRenderer;

namespace {
template<class T>
struct identity {
typedef T type;
};

template<class T, typename... Args>
using AppliedFunc = typename identity<std::function<void(T, Args...)>>::type;
}

/**
* A container for Entities, providing convenient methods for operating
* on all or a specific type of them.
Expand Down Expand Up @@ -86,20 +77,15 @@ class EntityGroup final : private sf::NonCopyable {
*/
explicit EntityGroup();

/** Applies a void(Args...) function to all entities (ref-args version) */
template<typename... Args>
void apply(AppliedFunc<lif::Entity*, Args&...> func, Args&... args);

/** Applies a void(Args...) function to all entities (const version) */
template<typename... Args>
void apply(AppliedFunc<const lif::Entity*, Args...> func, Args... args) const;
/** Applies a function to all entities */
template<class T, typename... Args>
void apply(const T& func, Args&... args);

/** Applies a void(Args...) function to all entities (weak_ptr version) */
template<typename... Args>
void apply(AppliedFunc<std::weak_ptr<lif::Entity>, Args...> func, Args... args) const;
/** Applies a function to all entities (const version) */
template<class T, typename... Args>
void apply(const T& func, Args&... args) const;

template<class T>
lif::Entity* add(T *entity);
lif::Entity* add(lif::Entity *entity);

template<class T>
lif::Entity* add(std::shared_ptr<T> entity);
Expand Down Expand Up @@ -154,31 +140,17 @@ class EntityGroup final : private sf::NonCopyable {

///// Implementation /////

template<typename... Args>
void EntityGroup::apply(AppliedFunc<lif::Entity*, Args&...> func, Args&... args) {
template<class T, typename... Args>
void EntityGroup::apply(const T& func, Args&... args) {
for (auto& e : entities)
func(e.get(), args...);
}

template<typename... Args>
void EntityGroup::apply(AppliedFunc<const lif::Entity*, Args...> func, Args... args) const {
for (const auto& e : entities)
template<class T, typename... Args>
void EntityGroup::apply(const T& func, Args&... args) const {
for (auto& e : entities)
func(e.get(), args...);
}

template<typename... Args>
void EntityGroup::apply(AppliedFunc<std::weak_ptr<lif::Entity>, Args...> func, Args... args) const {
for (const auto& e : entities)
func(e, args...);
}

template<class T>
lif::Entity* EntityGroup::add(T *entity) {
entity->init();
entities.emplace_back(entity);
return _putInAux(entities.back().get());
}

template<class T>
lif::Entity* EntityGroup::add(std::shared_ptr<T> entity) {
entity->init();
Expand All @@ -188,12 +160,9 @@ lif::Entity* EntityGroup::add(std::shared_ptr<T> entity) {

template<class T>
size_t EntityGroup::size() const {
size_t sz = 0;
for (auto& e : entities) {
if (dynamic_cast<T*>(e.get()) != nullptr)
++sz;
}
return sz;
return std::accumulate(entities.begin(), entities.end(), 0u, [this] (size_t acc, const auto& e) {
return acc + !!dynamic_cast<const T*>(e.get());
});
}

}
} // end namespace lif
11 changes: 4 additions & 7 deletions src/core/components/FreeSighted.cpp
Expand Up @@ -17,18 +17,15 @@ void FreeSighted::update() {
seen.clear();

const auto sqrVR = visionRadius * lif::TILE_SIZE * visionRadius * lif::TILE_SIZE;
entities->apply([this, sqrVR] (std::weak_ptr<lif::Entity> e) {
if (e.expired())
return;
const auto ptr = e.lock();
entities->apply([this, sqrVR] (lif::Entity *e) {
// Don't see self
if (ptr.get() == &owner)
if (e == &owner)
return;
const auto dist = lif::sqrDistance(ptr->getPosition(), owner.getPosition());
const auto dist = lif::sqrDistance(e->getPosition(), owner.getPosition());
if (visionRadius > 0 && dist > sqrVR)
return;
// Only see living entities
const auto killable = ptr->get<lif::Killable>();
const auto killable = e->get<lif::Killable>();
if (killable == nullptr || !killable->isKilled())
seen.emplace_back(e, dist);
});
Expand Down
17 changes: 8 additions & 9 deletions src/core/components/FreeSighted.hpp
Expand Up @@ -7,7 +7,7 @@
namespace lif {

class FreeSighted : public lif::Sighted {
using SeenEntitiesList = std::vector<std::pair<std::weak_ptr<lif::Entity>, float>>;
using SeenEntitiesList = std::vector<std::pair<lif::Entity*, float>>;

SeenEntitiesList seen;

Expand All @@ -27,14 +27,13 @@ class FreeSighted : public lif::Sighted {

template<class T>
T* FreeSighted::nearest() {
std::pair<T*, float> cur(nullptr, 0);
for (auto& e : seen) {
if (e.first.expired()) continue;
auto ptr = e.first.lock();
if (std::dynamic_pointer_cast<const T>(ptr) != nullptr
&& (cur.first == nullptr || cur.second > e.second))
std::pair<T*, float> cur{nullptr, 0};
for (auto& pair : seen) {
auto e = pair.first;
if (dynamic_cast<const T*>(e) != nullptr
&& (cur.first == nullptr || cur.second > pair.second))
{
cur = std::make_pair(static_cast<T*>(ptr.get()), e.second);
cur = std::make_pair(static_cast<T*>(e), pair.second);
}
}
return cur.first;
Expand All @@ -46,7 +45,7 @@ inline lif::Entity* FreeSighted::nearest<lif::Entity>() {
return a.second < b.second;
});
if (it == seen.end()) return nullptr;
return it->first.expired() ? nullptr : it->first.lock().get();
return it->first;
}

}
5 changes: 1 addition & 4 deletions src/core/utils.hpp
Expand Up @@ -91,10 +91,7 @@ inline std::ostream& operator<<(std::ostream& stream, const sf::RectangleShape&
}

inline std::ostream& operator<<(std::ostream& stream, const sf::Color& col) {
return stream << "(" << static_cast<int>(col.r)
<< ", " << static_cast<int>(col.g)
<< ", " << static_cast<int>(col.b)
<< ", " << static_cast<int>(col.a) << ")";
return stream << "(" << int{col.r} << ", " << int{col.g} << ", " << int{col.b} << ", " << int{col.a} << ")";
}

template<typename T, typename R>
Expand Down
26 changes: 15 additions & 11 deletions src/lifish/entities/HauntingSpiritBoss.cpp
Expand Up @@ -135,15 +135,18 @@ void HauntingSpiritBoss::_updateStart() {
}

void HauntingSpiritBoss::_updateSearching() {
// Task: find all the HauntedStatues in the level. Do this once and keep track of them internally thereafter.
// Task: find all the HauntedStatues in the level.
// Note: since FreeSighted returns raw pointers but we want to keep track of the living state of
// the statues, we track the *weak pointers* to their Killable component. This will expire together
// with the statue itself.
auto sighted = get<lif::FreeSighted>();
const auto seen = sighted->entitiesSeen();
for (auto& pair : seen) {
if (auto statue = std::dynamic_pointer_cast<lif::HauntedStatue>(pair.first.lock()))
const auto& seen = sighted->entitiesSeen();
for (const auto& pair : seen) {
if (auto statue = dynamic_cast<const lif::HauntedStatue*>(pair.first))
if (!statue->isPossessed())
statues.emplace_back(statue);
statues.emplace_back(statue->getShared<lif::Killable>());
}
sighted->setActive(false); // no need for this anymore
sighted->setActive(false); // no need for this anymore.
state = State::SELECT_NEW_STATUE;
}

Expand Down Expand Up @@ -179,7 +182,7 @@ void HauntingSpiritBoss::_updateTransitioningBegin() {
state = State::DYING;
return;
}
position.x = statue->getPosition().x + lif::TILE_SIZE / 2;
position.x = statue->getOwner().getPosition().x + lif::TILE_SIZE / 2;
animated->getSprite().rotate(180);
state = State::TRANSITIONING_END;
} else {
Expand All @@ -193,14 +196,14 @@ void HauntingSpiritBoss::_updateTransitioningEnd() {
state = State::SELECT_NEW_STATUE;
return;
}
if (position.y >= statue->getPosition().y) {
if (position.y >= statue->getOwner().getPosition().y) {
animated->getSprite().rotate(180);
animated->getSprite().setLooped(true);
animated->setAnimation("idle");
animated->getSprite().play();
hauntClock->restart();
atkClock->restart();
targetStatue.lock()->setPossessed(true);
static_cast<lif::HauntedStatue&>(targetStatue.lock()->getOwnerRW()).setPossessed(true);
get<lif::Drawable>()->setActive(false);
selectedNewPattern = false;
state = State::HAUNTING;
Expand All @@ -218,6 +221,7 @@ void HauntingSpiritBoss::_updateHaunting() {
curShootPattern->setActive(false);
return;
}
auto& statue = static_cast<lif::HauntedStatue&>(targetStatue.lock()->getOwnerRW());
if (_isShooting()) {
atkClock->restart();
return;
Expand All @@ -229,12 +233,12 @@ void HauntingSpiritBoss::_updateHaunting() {
std::uniform_int_distribution<unsigned> dist(0, shootPatterns.size() - 1);
const auto idx = dist(lif::rng);
curShootPattern = shootPatterns[idx];
targetStatue.lock()->setSpiritColor(shootColors[idx]);
statue.setSpiritColor(shootColors[idx]);
}
// We haunted this statue long enough: select a new one
if (hauntClock->getElapsedTime() > lif::conf::boss::haunting_spirit_boss::CHANGE_STATUE_DELAY) {
get<lif::Drawable>()->setActive(true);
targetStatue.lock()->setPossessed(false);
statue.setPossessed(false);
state = State::SELECT_NEW_STATUE;
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/lifish/entities/HauntingSpiritBoss.hpp
Expand Up @@ -25,8 +25,8 @@ class HauntingSpiritBoss : public lif::Boss {
} state;

bool selectedNewPattern = false;
std::vector<std::weak_ptr<lif::HauntedStatue>> statues;
std::weak_ptr<lif::HauntedStatue> targetStatue;
std::vector<std::weak_ptr<lif::Killable>> statues;
std::weak_ptr<lif::Killable> targetStatue;
/**
* 0. circle
* 1. spiral
Expand Down
9 changes: 4 additions & 5 deletions src/lifish/entities/RexBoss.cpp
Expand Up @@ -187,7 +187,6 @@ void RexBoss::_updateAttacking() {
std::uniform_int_distribution<> dist(0, 3);
moving->setDirection(lif::ai::directions[dist(lif::rng)]);
state = State::WALKING;
std::cout << "=-----\n";
steps = 0;
}
}
Expand Down Expand Up @@ -429,15 +428,15 @@ void RexBoss::_kill() {
}

void RexBoss::_updatePlayersPos() {
const auto seen = sighted->entitiesSeen();
const auto& seen = sighted->entitiesSeen();
const auto lm = get<lif::AI>()->getLevelManager();
assert(lm && "lm is null in _updatePlayersPos!");
latestPlayersPos.fill({ -1, -1 });
int found = 0;
for (auto ptr : seen) {
const auto e = ptr.first.lock();
for (const auto& pair : seen) {
const auto e = pair.first;
if (lm->isPlayer(*e) && !e->template get<lif::Killable>()->isKilled()) {
latestPlayersPos[static_cast<const lif::Player*>(e.get())->getInfo().id - 1] = e->getPosition();
latestPlayersPos[static_cast<const lif::Player*>(e)->getInfo().id - 1] = e->getPosition();
if (++found == static_cast<signed>(latestPlayersPos.size()))
break;
}
Expand Down

0 comments on commit 3b079d9

Please sign in to comment.