Add collision layer to maps and prevent movement into blocked areas
This commit is contained in:
parent
efa8640aab
commit
eb40e3de72
6 changed files with 107 additions and 29 deletions
|
@ -5,6 +5,7 @@ add_executable(rpgedit
|
|||
rpgedit.cpp
|
||||
control/MapContext.cpp
|
||||
control/RPGEdit.cpp
|
||||
model/Entity.cpp
|
||||
model/Map.cpp
|
||||
view/MapView.cpp
|
||||
view/SpriteCache.cpp
|
||||
|
|
|
@ -37,7 +37,7 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
|
|||
|
||||
map.getEntities().emplace_back("square");
|
||||
playerEntity = &map.getEntities().back();
|
||||
playerEntity->moveTo(Model::Position{8, 8});
|
||||
playerEntity->moveTo(&map, Model::Position{8, 8});
|
||||
|
||||
view->updateEntities(map.getEntities());
|
||||
|
||||
|
@ -50,14 +50,12 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
|
|||
}
|
||||
|
||||
void MapContext::movePlayer(Model::Direction dir, uint64_t time) {
|
||||
if (playerEntity->hasTransition())
|
||||
if (!playerEntity->move(&map, dir, time, time+250))
|
||||
return;
|
||||
|
||||
playerEntity->move(dir, time, time+250);
|
||||
|
||||
eventBus->enqueue(
|
||||
[=] {
|
||||
playerEntity->finishTransition();
|
||||
playerEntity->finishTransition(&map);
|
||||
movePlayerContinue(time+250);
|
||||
},
|
||||
time+250
|
||||
|
|
68
src/model/Entity.cpp
Normal file
68
src/model/Entity.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "Entity.hpp"
|
||||
#include "Map.hpp"
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -39,6 +39,8 @@ namespace RPGEdit {
|
|||
|
||||
namespace Model {
|
||||
|
||||
class Map;
|
||||
|
||||
class Entity {
|
||||
private:
|
||||
const std::string name;
|
||||
|
@ -97,29 +99,13 @@ public:
|
|||
return direction;
|
||||
}
|
||||
|
||||
void moveTo(Position newPos) {
|
||||
pos = newPos;
|
||||
transitionStart = transitionEnd = 0;
|
||||
}
|
||||
|
||||
void move(Direction dir, uint64_t start, uint64_t end) {
|
||||
if (hasTransition())
|
||||
return;
|
||||
|
||||
direction = dir;
|
||||
|
||||
transitionStart = start;
|
||||
transitionEnd = end;
|
||||
}
|
||||
|
||||
void finishTransition() {
|
||||
if (hasTransition())
|
||||
moveTo(translate(direction, 1));
|
||||
}
|
||||
|
||||
bool hasTransition() const {
|
||||
return transitionEnd;
|
||||
}
|
||||
|
||||
void moveTo(Map *map, Position newPos);
|
||||
bool move(Map *map, Direction dir, uint64_t start, uint64_t end);
|
||||
void finishTransition(Map *map);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -39,10 +39,13 @@ std::unique_ptr<Map> Map::load(__attribute__((unused)) const std::string &name)
|
|||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (4 <= i && i < 12 && 4 <= j && j < 12)
|
||||
if (4 <= i && i < 12 && 4 <= j && j < 12) {
|
||||
map->setTileAt(0, i, j, 1);
|
||||
else
|
||||
map->setCollisionAt(i, j, EMPTY);
|
||||
}
|
||||
else {
|
||||
map->setTileAt(0, i, j, 0);
|
||||
}
|
||||
|
||||
if (4 <= i && i < 12 && j == 8)
|
||||
map->setTileAt(1, i, j, 2);
|
||||
|
@ -52,7 +55,7 @@ std::unique_ptr<Map> Map::load(__attribute__((unused)) const std::string &name)
|
|||
}
|
||||
|
||||
map->entities.emplace_back("square");
|
||||
map->entities.back().moveTo(Model::Position{6, 6});
|
||||
map->entities.back().moveTo(map.get(), Model::Position{6, 6});
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -40,16 +40,23 @@ namespace RPGEdit {
|
|||
namespace Model {
|
||||
|
||||
class Map {
|
||||
public:
|
||||
enum CollisionType {
|
||||
BLOCKED = 0,
|
||||
EMPTY,
|
||||
};
|
||||
|
||||
private:
|
||||
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)
|
||||
: width(width0), height(height0) {
|
||||
: width(width0), height(height0), collision(width*height) {
|
||||
for (size_t i = 0; i < layers; i++)
|
||||
tiles.emplace_back(width*height);
|
||||
}
|
||||
|
@ -83,6 +90,21 @@ public:
|
|||
return tiles.size();
|
||||
}
|
||||
|
||||
void setCollisionAt(size_t x, size_t y, CollisionType value) {
|
||||
if (x >= width || y >= height)
|
||||
throw std::range_error("Map::setTileAt: bad coordinates");
|
||||
|
||||
collision[y*width + 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;
|
||||
|
||||
return collision[y*width + x];
|
||||
}
|
||||
|
||||
|
||||
void setTileAt(size_t layer, size_t x, size_t y, uint32_t value) {
|
||||
if (layer >= tiles.size() || x >= width || y >= height)
|
||||
throw std::range_error("Map::setTileAt: bad coordinates");
|
||||
|
|
Reference in a new issue