diff options
Diffstat (limited to 'src/model')
-rw-r--r-- | src/model/CollisionType.hpp (renamed from src/model/Entity.cpp) | 37 | ||||
-rw-r--r-- | src/model/Entity.hpp | 51 | ||||
-rw-r--r-- | src/model/Map.cpp | 59 | ||||
-rw-r--r-- | src/model/Map.hpp | 89 | ||||
-rw-r--r-- | src/model/Position.hpp | 29 |
5 files changed, 167 insertions, 98 deletions
diff --git a/src/model/Entity.cpp b/src/model/CollisionType.hpp index 71447e6..4877669 100644 --- a/src/model/Entity.cpp +++ b/src/model/CollisionType.hpp @@ -24,44 +24,17 @@ */ -#include "Entity.hpp" -#include "Map.hpp" +#pragma once namespace RPGEdit { namespace Model { -bool Entity::move(Map *map, Direction dir, uint64_t start, uint64_t end) { - if (hasTransition()) - return false; - - direction = dir; - - Position newPos = translate(dir, 1); - if (map->getCollisionAt(newPos.x, newPos.y) == Map::BLOCKED) - return false; - - map->setCollisionAt(newPos.x, newPos.y, Map::BLOCKED); - - transitionStart = start; - transitionEnd = end; - - return true; -} - -void Entity::moveTo(Map *map, Position newPos) { - map->setCollisionAt(pos.x, pos.y, Map::EMPTY); - map->setCollisionAt(newPos.x, newPos.y, Map::BLOCKED); - - pos = newPos; - transitionStart = transitionEnd = 0; -} - -void Entity::finishTransition(Map *map) { - if (hasTransition()) - moveTo(map, translate(direction, 1)); -} +enum CollisionType { + BLOCKED = 0, + EMPTY, +}; } diff --git a/src/model/Entity.hpp b/src/model/Entity.hpp index 170f23a..eab6983 100644 --- a/src/model/Entity.hpp +++ b/src/model/Entity.hpp @@ -39,41 +39,12 @@ namespace RPGEdit { namespace Model { -class Map; - class Entity { private: - const std::string name; + std::string name; - Position pos; Direction direction; - uint64_t transitionStart = 0; - uint64_t transitionEnd = 0; - - Position translate(Direction dir, float amount) const { - Position p = pos; - - switch (dir) { - case NORTH: - p.y -= amount; - break; - - case EAST: - p.x += amount; - break; - - case SOUTH: - p.y += amount; - break; - - case WEST: - p.x -= amount; - } - - return p; - } - public: Entity(const std::string &name0) : name(name0), direction(NORTH) { @@ -83,29 +54,13 @@ public: return name; } - Position getPosition(uint64_t time) const { - if (hasTransition()) - if (time <= transitionStart) - return pos; - else if (time >= transitionEnd) - return translate(direction, 1); - else - return translate(direction, float(time-transitionStart)/float(transitionEnd-transitionStart)); - else - return pos; - } - Direction getDirection() const { return direction; } - bool hasTransition() const { - return transitionEnd; + void setDirection(Direction dir) { + direction = dir; } - - void moveTo(Map *map, Position newPos); - bool move(Map *map, Direction dir, uint64_t start, uint64_t end); - void finishTransition(Map *map); }; } diff --git a/src/model/Map.cpp b/src/model/Map.cpp index faead6d..a5b5ee9 100644 --- a/src/model/Map.cpp +++ b/src/model/Map.cpp @@ -31,6 +31,62 @@ namespace RPGEdit { namespace Model { +Position Map::getEntityPosition(const Entity *entity, uint64_t time) const { + const EntityState &state = entityStates.at(entity); + + if (state.transitionEnd) + if (time <= state.transitionStart) + return state.position; + else if (time >= state.transitionEnd) + return state.position + state.direction; + else + return state.position.translate(state.direction, + float(time-state.transitionStart)/ + float(state.transitionEnd-state.transitionStart)); + else + return state.position; +} + +bool Map::moveEntity(Entity *entity, Direction dir, uint64_t start, uint64_t end) { + EntityState &state = entityStates.at(entity); + + if (state.transitionEnd) + return false; + + entity->setDirection(dir); + + Position pos = state.position + dir; + + if (getCollisionAt(pos.x, pos.y) == BLOCKED) + return false; + + setCollisionAt(pos.x, pos.y, BLOCKED); + + state.transitionStart = start; + state.transitionEnd = end; + state.direction = dir; + + return true; +} + +void Map::moveEntityTo(Entity *entity, Position pos) { + EntityState &state = entityStates.at(entity); + + setCollisionAt(state.position.x, state.position.y, EMPTY); + setCollisionAt(pos.x, pos.y, BLOCKED); + + state.position = pos; + state.transitionStart = state.transitionEnd = 0; + +} + +void Map::finishEntityTransition(Entity *entity) { + EntityState &state = entityStates.at(entity); + + if (state.transitionEnd) + moveEntityTo(entity, state.position + state.direction); +} + std::unique_ptr<Map> Map::load(__attribute__((unused)) const std::string &name) { std::unique_ptr<Map> map(new Map(16, 16, 2)); @@ -54,8 +110,7 @@ std::unique_ptr<Map> Map::load(__attribute__((unused)) const std::string &name) } } - map->entities.emplace_back("square"); - map->entities.back().moveTo(map.get(), Model::Position{6, 6}); + map->addEntity("square", Model::Position{6, 6}); return map; } diff --git a/src/model/Map.hpp b/src/model/Map.hpp index abbf2f1..c7b9783 100644 --- a/src/model/Map.hpp +++ b/src/model/Map.hpp @@ -27,11 +27,12 @@ #pragma once #include <cstdint> -#include <deque> #include <memory> #include <stdexcept> +#include <unordered_map> #include <vector> +#include "CollisionType.hpp" #include "Entity.hpp" @@ -39,29 +40,77 @@ namespace RPGEdit { namespace Model { -class Map { -public: - enum CollisionType { - BLOCKED = 0, - EMPTY, - }; - -private: +class _Map { +protected: std::vector<std::string> tileset; size_t width, height; std::vector<CollisionType> collision; std::vector<std::vector<uint32_t>> tiles; - std::deque<Entity> entities; - - Map(size_t width0, size_t height0, size_t layers) + _Map(size_t width0, size_t height0, size_t layers) : width(width0), height(height0), collision(width*height) { for (size_t i = 0; i < layers; i++) tiles.emplace_back(width*height); } +}; + +class Map : private _Map { +private: + struct EntityState { + Position position; + + Direction direction; + uint64_t transitionStart = 0; + uint64_t transitionEnd = 0; + + EntityState(const Position &position0) : position(position0) {} + }; + + std::vector<std::unique_ptr<Entity>> entities; + std::unordered_map<const Entity *, EntityState> entityStates; + + + void pushEntity(Entity *entity, EntityState &&state) { + entities.push_back(std::unique_ptr<Entity>(entity)); + entityStates.emplace(entity, state); + } + + void copyEntities(const Map &other) { + for (auto &e : other.entities) + pushEntity(new Entity(*e), EntityState(other.entityStates.at(e.get()))); + } + + + Map(size_t width0, size_t height0, size_t layers) : _Map(width0, height0, layers) { + } public: + Map & operator=(const Map &other) { + static_cast<_Map>(*this) = other; + copyEntities(other); + + return *this; + } + + Map(const Map &other) : _Map(other) { + copyEntities(other); + } + + Map & operator=(Map &&other) { + static_cast<_Map>(*this) = std::move(other); + + entities = std::move(other.entities); + entityStates = std::move(other.entityStates); + + return *this; + } + + Map(Map &&other) : _Map(std::move(other)) { + entities = std::move(other.entities); + entityStates = std::move(other.entityStates); + } + std::vector<std::string> & getTileset() { return tileset; } @@ -70,12 +119,15 @@ public: return tileset; } - std::deque<Entity> & getEntities() { + const std::vector<std::unique_ptr<Entity>> & getEntities() const { return entities; } - const std::deque<Entity> & getEntities() const { - return entities; + Entity * addEntity(const std::string &name, const Position &pos) { + Entity *e = new Entity(name); + pushEntity(e, EntityState(pos)); + setCollisionAt(pos.x, pos.y, BLOCKED); + return e; } size_t getWidth() const { @@ -92,7 +144,7 @@ public: void setCollisionAt(size_t x, size_t y, CollisionType value) { if (x >= width || y >= height) - throw std::range_error("Map::setTileAt: bad coordinates"); + throw std::range_error("Map::setCollisionAt: bad coordinates"); collision[y*width + x] = value; } @@ -119,6 +171,11 @@ public: return tiles[layer][y*width + x]; } + Position getEntityPosition(const Entity *entity, uint64_t time) const; + bool moveEntity(Entity *entity, Direction dir, uint64_t start, uint64_t end); + void moveEntityTo(Entity *entity, Position pos); + void finishEntityTransition(Entity *entity); + static std::unique_ptr<Map> load(const std::string &name); }; diff --git a/src/model/Position.hpp b/src/model/Position.hpp index b68476f..84044e6 100644 --- a/src/model/Position.hpp +++ b/src/model/Position.hpp @@ -26,6 +26,8 @@ #pragma once +#include "Direction.hpp" + namespace RPGEdit { @@ -33,6 +35,33 @@ namespace Model { struct Position { float x, y; + + Position translate(Direction dir, float amount) const { + Position p = *this; + + switch (dir) { + case NORTH: + p.y -= amount; + break; + + case EAST: + p.x += amount; + break; + + case SOUTH: + p.y += amount; + break; + + case WEST: + p.x -= amount; + } + + return p; + } + + Position operator+(Direction dir) const { + return translate(dir, 1); + } }; } |