Keep mutable entity list in the MapContext only
This commit is contained in:
parent
ccf859fe80
commit
aadcecf202
7 changed files with 72 additions and 48 deletions
|
@ -31,8 +31,19 @@ namespace RPGEdit {
|
|||
|
||||
namespace Control {
|
||||
|
||||
MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr<const Model::Map> &map0)
|
||||
: eventBus(eventBus0), inputHandler(inputHandler0), map(map0) {
|
||||
MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, View::MapView *view0, const std::shared_ptr<const Model::Map> &map0)
|
||||
: eventBus(eventBus0), inputHandler(inputHandler0), view(view0), map(map0) {
|
||||
for (const Model::Entity &entity : map->getEntities())
|
||||
entities.emplace_back(new Model::Entity(entity));
|
||||
|
||||
playerEntity = new Model::Entity("square");
|
||||
playerEntity->moveTo(Model::Position{8, 8});
|
||||
|
||||
entities.emplace_back(playerEntity);
|
||||
|
||||
view->updateEntities(entities);
|
||||
|
||||
|
||||
inputHandler->registerListener(
|
||||
[this] (uint16_t key, bool pressed, uint64_t time) {
|
||||
if (pressed)
|
||||
|
@ -42,14 +53,14 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
|
|||
}
|
||||
|
||||
void MapContext::movePlayer(Model::Direction dir, uint64_t time) {
|
||||
if (map->getPlayerEntity()->hasTransition())
|
||||
if (playerEntity->hasTransition())
|
||||
return;
|
||||
|
||||
map->getPlayerEntity()->move(dir, time, time+250);
|
||||
playerEntity->move(dir, time, time+250);
|
||||
|
||||
eventBus->enqueue(
|
||||
[=] {
|
||||
map->getPlayerEntity()->finishTransition();
|
||||
playerEntity->finishTransition();
|
||||
movePlayerContinue(time+250);
|
||||
},
|
||||
time+250
|
||||
|
|
|
@ -44,19 +44,26 @@ private:
|
|||
EventBus *const eventBus;
|
||||
InputHandler *const inputHandler;
|
||||
|
||||
View::MapView *const view;
|
||||
|
||||
std::shared_ptr<const Model::Map> map;
|
||||
|
||||
uint64_t totalTicks = 0;
|
||||
std::vector<std::unique_ptr<Model::Entity>> entities;
|
||||
Model::Entity *playerEntity;
|
||||
|
||||
void movePlayer(Model::Direction dir, uint64_t time);
|
||||
void movePlayerContinue(uint64_t time);
|
||||
void keyPressed(uint16_t key, uint64_t time);
|
||||
|
||||
public:
|
||||
MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr<const Model::Map> &map0);
|
||||
|
||||
Model::Position getViewPosition(uint64_t time) {
|
||||
return map->getPlayerEntity()->getPosition(time);
|
||||
return playerEntity->getPosition(time);
|
||||
}
|
||||
|
||||
public:
|
||||
MapContext(EventBus *eventBus0, InputHandler *inputHandler0, View::MapView *view0, const std::shared_ptr<const Model::Map> &map0);
|
||||
|
||||
void render(uint64_t time) {
|
||||
view->render(entities, getViewPosition(time), time);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -74,10 +74,7 @@ void RPGEdit::systemLoop() {
|
|||
{
|
||||
std::unique_lock<std::mutex> lock(modelMutex);
|
||||
|
||||
uint64_t time = std::min(timeProvider.now(), handledTime);
|
||||
|
||||
Model::Position pos = ctx->getViewPosition(time);
|
||||
mapView->render(pos.x, pos.y, time);
|
||||
ctx->render(std::min(timeProvider.now(), handledTime));
|
||||
}
|
||||
|
||||
SDL_RenderPresent(window->getRenderer());
|
||||
|
@ -104,11 +101,11 @@ void RPGEdit::eventLoop() {
|
|||
void RPGEdit::run() {
|
||||
std::shared_ptr<Model::Map> map = Model::Map::load("test");
|
||||
|
||||
ctx = std::make_shared<MapContext>(&eventBus, &inputHandler, map);
|
||||
|
||||
window = std::make_shared<View::Window>();
|
||||
mapView = std::make_shared<View::MapView>(window, map);
|
||||
|
||||
ctx = std::make_shared<MapContext>(&eventBus, &inputHandler, mapView.get(), map);
|
||||
|
||||
eventThread = std::thread([this] { eventLoop(); });
|
||||
|
||||
systemLoop();
|
||||
|
|
|
@ -32,14 +32,11 @@ namespace RPGEdit {
|
|||
namespace Model {
|
||||
|
||||
std::shared_ptr<Map> Map::load(__attribute__((unused)) const std::string &name) {
|
||||
std::shared_ptr<Map> map(new Map(16, 16));
|
||||
std::shared_ptr<Map> map(new Map(16, 16, 2));
|
||||
|
||||
map->tileset.push_back("dirt");
|
||||
map->tileset.push_back("horizontal_bar");
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
map->tiles.emplace_back(new uint32_t[16*16]);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (4 <= i && i < 12 && 4 <= j && j < 12)
|
||||
|
@ -54,10 +51,8 @@ std::shared_ptr<Map> Map::load(__attribute__((unused)) const std::string &name)
|
|||
}
|
||||
}
|
||||
|
||||
map->playerEntity = std::make_shared<Entity>("square");
|
||||
map->playerEntity->moveTo(Model::Position{6, 6});
|
||||
|
||||
map->entities.push_back(map->playerEntity);
|
||||
map->entities.emplace_back("square");
|
||||
map->entities.back().moveTo(Model::Position{6, 6});
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
@ -44,14 +43,14 @@ private:
|
|||
std::vector<std::string> tileset;
|
||||
|
||||
size_t width, height;
|
||||
std::vector<std::unique_ptr<uint32_t[]>> tiles;
|
||||
|
||||
std::shared_ptr<Entity> playerEntity;
|
||||
mutable std::deque<std::shared_ptr<Entity>> entities;
|
||||
std::vector<std::vector<uint32_t>> tiles;
|
||||
std::vector<Entity> entities;
|
||||
|
||||
|
||||
Map(size_t width0, size_t height0)
|
||||
Map(size_t width0, size_t height0, size_t layers)
|
||||
: width(width0), height(height0) {
|
||||
for (size_t i = 0; i < layers; i++)
|
||||
tiles.emplace_back(width*height);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -63,12 +62,12 @@ public:
|
|||
return tileset;
|
||||
}
|
||||
|
||||
std::deque<std::shared_ptr<Entity>> & getEntities() const {
|
||||
std::vector<Entity> & getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Entity> & getPlayerEntity() const {
|
||||
return playerEntity;
|
||||
const std::vector<Entity> & getEntities() const {
|
||||
return entities;
|
||||
}
|
||||
|
||||
size_t getWidth() const {
|
||||
|
|
|
@ -71,21 +71,33 @@ MapView::MapView(const std::shared_ptr<Window> &window0,
|
|||
|
||||
tiles = SDL_CreateTextureFromSurface(window->getRenderer(), surface);
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
for (auto &entity : map->getEntities()) {
|
||||
const std::string &name = entity->getName();
|
||||
entities[name] = SDL_CreateTextureFromSurface(window->getRenderer(), spriteCache->get("entity", name));
|
||||
}
|
||||
}
|
||||
|
||||
MapView::~MapView() {
|
||||
SDL_DestroyTexture(tiles);
|
||||
|
||||
for (const std::pair<std::string, SDL_Texture *> &entity : entities)
|
||||
SDL_DestroyTexture(entity.second);
|
||||
clearEntities();
|
||||
}
|
||||
|
||||
void MapView::render(float centerX, float centerY, uint64_t time) {
|
||||
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();
|
||||
|
||||
if (!entitySprites[name])
|
||||
entitySprites[name] = SDL_CreateTextureFromSurface(window->getRenderer(), spriteCache->get("entity", name));
|
||||
}
|
||||
}
|
||||
|
||||
void MapView::clearEntities() {
|
||||
for (const std::pair<std::string, SDL_Texture *> &entity : entitySprites)
|
||||
SDL_DestroyTexture(entity.second);
|
||||
|
||||
entitySprites.clear();
|
||||
}
|
||||
|
||||
void MapView::render(const std::vector<std::unique_ptr<Model::Entity>> &entities, Model::Position center, uint64_t time) {
|
||||
SDL_RenderClear(window->getRenderer());
|
||||
|
||||
std::pair<int, int> viewport = window->getViewport();
|
||||
|
@ -96,10 +108,10 @@ void MapView::render(float centerX, float centerY, uint64_t time) {
|
|||
float tilesW = viewport.first / tilePixels;
|
||||
float tilesH = viewport.second / tilePixels;
|
||||
|
||||
int minX = std::floor(centerX - tilesW/2 - 0.5f), maxX = std::ceil(centerX + tilesW/2 + 0.5f);
|
||||
int minY = std::floor(centerY - tilesH/2 - 0.5f), maxY = std::ceil(centerY + tilesH/2 + 0.5f);
|
||||
int minX = std::floor(center.x - tilesW/2 - 0.5f), maxX = std::ceil(center.x + tilesW/2 + 0.5f);
|
||||
int minY = std::floor(center.y - tilesH/2 - 0.5f), maxY = std::ceil(center.y + tilesH/2 + 0.5f);
|
||||
|
||||
int baseX = viewport.first/2 - int(centerX * tilePixels) - tilePixels/2, baseY = viewport.second/2 - int(centerY * tilePixels) - tilePixels/2;
|
||||
int baseX = viewport.first/2 - int(center.x * tilePixels) - tilePixels/2, baseY = viewport.second/2 - int(center.y * tilePixels) - tilePixels/2;
|
||||
|
||||
for (size_t layer = 0; layer < map->getLayerCount(); layer++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
|
@ -127,7 +139,7 @@ void MapView::render(float centerX, float centerY, uint64_t time) {
|
|||
}
|
||||
}
|
||||
|
||||
for (const std::shared_ptr<Model::Entity> &entity : map->getEntities()) {
|
||||
for (const std::unique_ptr<Model::Entity> &entity : entities) {
|
||||
Model::Position pos = entity->getPosition(time);
|
||||
Model::Direction dir = entity->getDirection();
|
||||
|
||||
|
@ -145,7 +157,7 @@ void MapView::render(float centerX, float centerY, uint64_t time) {
|
|||
.h = tilePixels,
|
||||
};
|
||||
|
||||
SDL_RenderCopy(window->getRenderer(), entities[entity->getName()], &src, &dst);
|
||||
SDL_RenderCopy(window->getRenderer(), entitySprites[entity->getName()], &src, &dst);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ private:
|
|||
std::shared_ptr<const Model::Map> map;
|
||||
|
||||
SDL_Texture *tiles;
|
||||
std::map<std::string, SDL_Texture *> entities;
|
||||
std::map<std::string, SDL_Texture *> entitySprites;
|
||||
|
||||
int getTileSize() {
|
||||
return 32;
|
||||
|
@ -55,7 +55,10 @@ public:
|
|||
const std::shared_ptr<const Model::Map> &map0);
|
||||
~MapView();
|
||||
|
||||
void render(float centerX, float centerY, uint64_t time);
|
||||
void updateEntities(const std::vector<std::unique_ptr<Model::Entity>> &entities);
|
||||
void clearEntities();
|
||||
|
||||
void render(const std::vector<std::unique_ptr<Model::Entity>> &entities, Model::Position center, uint64_t time);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue