#ifndef TRANSFORM_SYSTEM_H_BA2633BC #define TRANSFORM_SYSTEM_H_BA2633BC #include #include #include #include #include #include "direction.h" #include "system.h" #include "vector.h" #include "sprite.h" #include "consts.h" class Game; struct CollisionResult { Direction dir; bool blocked = false; std::list colliders; vec2i adjustedLoc; }; enum class CheckCollisionOptions { None = 0, AllowSliding = 1 << 0 }; class TransformSystem : public System { public: static constexpr SystemKey Key = SystemKey::Transform; TransformSystem(Game& game) : game_(game) {} void initSprite(int spriteId, vec2i loc, SpriteLayer layer = SpriteLayer::Normal); void setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid); void undoCollision(int spriteId); void moveSprite(int spriteId, vec2i newLoc); auto getSpritesByY(SpriteLayer layer) const { return spritesByY_[static_cast(layer)] | ranges::views::transform([] (const std::tuple& val) { return std::get<1>(val); }); } CollisionResult checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir, CheckCollisionOptions options = CheckCollisionOptions::None); CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc); void destroySprite(int spriteId) override; private: Game& game_; std::set> spritesByY_[static_cast(SpriteLayer::NUM_SPRITE_LAYERS)]; 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 */