#ifndef TRANSFORM_SYSTEM_H_BA2633BC #define TRANSFORM_SYSTEM_H_BA2633BC #include #include #include #include #include "direction.h" #include "system.h" #include "vector.h" class Game; struct AxisResult { Direction dir; bool blocked = false; int colliderSprite = -1; }; struct CollisionResult { AxisResult horiz; AxisResult vert; }; class TransformSystem : public System { public: static constexpr SystemKey Key = SystemKey::Transform; TransformSystem(Game& game) : game_(game) {} void initSprite(int spriteId, vec2i loc); void setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid); void moveSprite(int spriteId, vec2i newLoc); auto getSpritesByY() const { return spritesByY_ | ranges::views::transform([] (const std::tuple& val) { return std::get<1>(val); }); } CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); void clearSpriteCache() override; private: Game& game_; std::set> spritesByY_; struct Collidable { int lower; int upper; Collidable(int lower, int upper) : lower(lower), upper(upper) {} }; // The way these work is that the key is (axis position, entity ID). The // entity ID being there makes the mapping unique and makes removal easy. using asc_collidables_type = std::map< std::tuple, const Collidable, std::less>>; using desc_collidables_type = std::map< std::tuple, const Collidable, std::greater>>; desc_collidables_type leftCollidables_; asc_collidables_type rightCollidables_; desc_collidables_type upCollidables_; asc_collidables_type downCollidables_; void addCollidable(int spriteId); void removeCollidable(int spriteId); }; #endif /* end of include guard: TRANSFORM_SYSTEM_H_BA2633BC */