summaryrefslogtreecommitdiffstats
path: root/src/model/Map.hpp
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2014-09-26 00:58:27 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2014-09-26 00:58:27 +0200
commitc3e32345e53650a1c231f4e1a41d40c97955b893 (patch)
tree93b22aedbe355173510a04eafec9f14d7c4c3e0f /src/model/Map.hpp
parent8b4ca336ce68cc17573115dd07eb1bfc6521b298 (diff)
downloadrpgedit-c3e32345e53650a1c231f4e1a41d40c97955b893.tar
rpgedit-c3e32345e53650a1c231f4e1a41d40c97955b893.zip
Collision rework
Diffstat (limited to 'src/model/Map.hpp')
-rw-r--r--src/model/Map.hpp82
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;