diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-09-26 00:58:27 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-09-26 00:58:27 +0200 |
commit | c3e32345e53650a1c231f4e1a41d40c97955b893 (patch) | |
tree | 93b22aedbe355173510a04eafec9f14d7c4c3e0f /src/model/Map.hpp | |
parent | 8b4ca336ce68cc17573115dd07eb1bfc6521b298 (diff) | |
download | rpgedit-c3e32345e53650a1c231f4e1a41d40c97955b893.tar rpgedit-c3e32345e53650a1c231f4e1a41d40c97955b893.zip |
Collision rework
Diffstat (limited to 'src/model/Map.hpp')
-rw-r--r-- | src/model/Map.hpp | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/src/model/Map.hpp b/src/model/Map.hpp index 4e434b1..0343709 100644 --- a/src/model/Map.hpp +++ b/src/model/Map.hpp @@ -30,6 +30,7 @@ #include <memory> #include <stdexcept> #include <unordered_map> +#include <unordered_set> #include <vector> #include "CollisionType.hpp" @@ -68,12 +69,27 @@ private: }; std::vector<std::unique_ptr<Entity>> entities; + std::unordered_map<Position<int>, std::unordered_set<Entity *>> positions; std::unordered_map<const Entity *, EntityState> entityStates; + void addEntityPosition(const Position<int> &position, Entity *entity) { + positions[position].insert(entity); + } + + void removeEntityPosition(const Position<int> &position, Entity *entity) { + auto it = positions.find(position); + it->second.erase(entity); + + if (it->second.empty()) + positions.erase(it); + } + + void pushEntity(Entity *entity, EntityState &&state) { entities.push_back(std::unique_ptr<Entity>(entity)); - entityStates.emplace(entity, state); + addEntityPosition(state.position, entity); + entityStates.emplace(entity, std::move(state)); } void copyEntities(const Map &other) { @@ -81,6 +97,37 @@ private: pushEntity(new Entity(*e), EntityState(other.entityStates.at(e.get()))); } + bool hasTransitionTo(const Position<int> &p, Direction dir) const { + auto it = positions.find(p+dir); + if (it == positions.end()) + return false; + + for (const Entity *entity : it->second) { + const EntityState &state = entityStates.at(entity); + + if (state.transitionEnd && (state.direction == -dir)) + return true; + } + + return false; + } + + bool hasTransitionTo(const Position<int> &p) const { + if (hasTransitionTo(p, Direction::NORTH)) + return true; + + if (hasTransitionTo(p, Direction::EAST)) + return true; + + if (hasTransitionTo(p, Direction::SOUTH)) + return true; + + if (hasTransitionTo(p, Direction::WEST)) + return true; + + return false; + } + Map(size_t width0, size_t height0, size_t layers) : _Map(width0, height0, layers) { } @@ -126,7 +173,6 @@ public: Entity * addEntity(const std::string &name, const Position<int> &pos) { Entity *e = new Entity(name); pushEntity(e, EntityState(pos)); - setCollisionAt(pos.x, pos.y, BLOCKED); return e; } @@ -142,33 +188,39 @@ public: return tiles.size(); } - void setCollisionAt(size_t x, size_t y, CollisionType value) { - if (x >= width || y >= height) + void setCollisionAt(const Position<int> &p, CollisionType value) { + if (p.x < 0 || size_t(p.x) >= width || p.y < 0 || size_t(p.y) >= height) throw std::range_error("Map::setCollisionAt: bad coordinates"); - collision[y*width + x] = value; + collision[p.y*width + p.x] = value; } - CollisionType getCollisionAt(ssize_t x, ssize_t y) const { - if (x < 0 || (size_t)x >= width || y < 0 || (size_t)y >= height) - return BLOCKED; + bool isBlocked(const Position<int> &p) const { + if (p.x < 0 || size_t(p.x) >= width || p.y < 0 || size_t(p.y) >= height) + return true; + + if (positions.find(p) != positions.end()) + return true; + + if (hasTransitionTo(p)) + return true; - return collision[y*width + x]; + return collision[p.y*width + p.x] == CollisionType::BLOCKED; } - void setTileAt(size_t layer, size_t x, size_t y, uint32_t value) { - if (layer >= tiles.size() || x >= width || y >= height) + void setTileAt(size_t layer, const Position<int> &p, uint32_t value) { + if (layer >= tiles.size() || p.x < 0 || size_t(p.x) >= width || p.y < 0 || size_t(p.y) >= height) throw std::range_error("Map::setTileAt: bad coordinates"); - tiles[layer][y*width + x] = value; + tiles[layer][p.y*width + p.x] = value; } - uint32_t getTileAt(size_t layer, ssize_t x, ssize_t y) const { - if (layer >= tiles.size() || x < 0 || (size_t)x >= width || y < 0 || (size_t)y >= height) + uint32_t getTileAt(size_t layer, const Position<int> &p) const { + if (layer >= tiles.size() || p.x < 0 || size_t(p.x) >= width || p.y < 0 || size_t(p.y) >= height) return 0; - return tiles[layer][y*width + x]; + return tiles[layer][p.y*width + p.x]; } Position<float> getEntityPosition(const Entity *entity, uint64_t time) const; |