summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/control/MapContext.cpp8
-rw-r--r--src/control/MapContext.hpp2
-rw-r--r--src/model/CollisionType.hpp (renamed from src/model/Entity.cpp)37
-rw-r--r--src/model/Entity.hpp51
-rw-r--r--src/model/Map.cpp59
-rw-r--r--src/model/Map.hpp89
-rw-r--r--src/model/Position.hpp29
-rw-r--r--src/view/MapView.cpp10
-rw-r--r--src/view/MapView.hpp2
10 files changed, 177 insertions, 111 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b2d55ac..54836d0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,7 +5,6 @@ add_executable(rpgedit
rpgedit.cpp
control/MapContext.cpp
control/RPGEdit.cpp
- model/Entity.cpp
model/Map.cpp
view/MapView.cpp
view/SpriteCache.cpp
diff --git a/src/control/MapContext.cpp b/src/control/MapContext.cpp
index acad969..8900298 100644
--- a/src/control/MapContext.cpp
+++ b/src/control/MapContext.cpp
@@ -35,9 +35,7 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
: eventBus(eventBus0), inputHandler(inputHandler0), map(map0) {
view = std::unique_ptr<View::MapView>(new View::MapView(window, map.getTileset()));
- map.getEntities().emplace_back("square");
- playerEntity = &map.getEntities().back();
- playerEntity->moveTo(&map, Model::Position{8, 8});
+ playerEntity = map.addEntity("square", Model::Position{8, 8});
view->updateEntities(map.getEntities());
@@ -50,12 +48,12 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
}
void MapContext::movePlayer(Model::Direction dir, uint64_t time) {
- if (!playerEntity->move(&map, dir, time, time+250))
+ if (!map.moveEntity(playerEntity, dir, time, time+250))
return;
eventBus->enqueue(
[=] {
- playerEntity->finishTransition(&map);
+ map.finishEntityTransition(playerEntity);
movePlayerContinue(time+250);
},
time+250
diff --git a/src/control/MapContext.hpp b/src/control/MapContext.hpp
index a60bdfc..d9c34f3 100644
--- a/src/control/MapContext.hpp
+++ b/src/control/MapContext.hpp
@@ -54,7 +54,7 @@ private:
void keyPressed(uint16_t key, uint64_t time);
Model::Position getViewPosition(uint64_t time) {
- return playerEntity->getPosition(time);
+ return map.getEntityPosition(playerEntity, time);
}
public:
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);
+ }
};
}
diff --git a/src/view/MapView.cpp b/src/view/MapView.cpp
index dbce5e4..4a6e552 100644
--- a/src/view/MapView.cpp
+++ b/src/view/MapView.cpp
@@ -76,11 +76,11 @@ MapView::~MapView() {
clearEntities();
}
-void MapView::updateEntities(const std::deque<Model::Entity> &entities) {
+void MapView::updateEntities(const std::vector<std::unique_ptr<Model::Entity>> &entities) {
SpriteCache *spriteCache = window->getSpriteCache();
for (auto &entity : entities) {
- const std::string &name = entity.getName();
+ const std::string &name = entity->getName();
if (!entitySprites[name])
entitySprites[name] = SDL_CreateTextureFromSurface(window->getRenderer(), spriteCache->get("entity", name));
@@ -137,8 +137,8 @@ void MapView::render(const Model::Map *map, Model::Position center, uint64_t tim
}
for (auto &entity : map->getEntities()) {
- Model::Position pos = entity.getPosition(time);
- Model::Direction dir = entity.getDirection();
+ Model::Position pos = map->getEntityPosition(entity.get(), time);
+ Model::Direction dir = entity->getDirection();
SDL_Rect src = {
.x = getTileSize()*dir,
@@ -154,7 +154,7 @@ void MapView::render(const Model::Map *map, Model::Position center, uint64_t tim
.h = tilePixels,
};
- SDL_RenderCopy(window->getRenderer(), entitySprites[entity.getName()], &src, &dst);
+ SDL_RenderCopy(window->getRenderer(), entitySprites[entity->getName()], &src, &dst);
}
}
diff --git a/src/view/MapView.hpp b/src/view/MapView.hpp
index f101c24..e813950 100644
--- a/src/view/MapView.hpp
+++ b/src/view/MapView.hpp
@@ -53,7 +53,7 @@ public:
MapView(const std::shared_ptr<Window> &window0, const std::vector<std::string> &tileset);
~MapView();
- void updateEntities(const std::deque<Model::Entity> &entities);
+ void updateEntities(const std::vector<std::unique_ptr<Model::Entity>> &entities);
void clearEntities();
void clear();