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
|
rpgedit.cpp
|
||||||
control/MapContext.cpp
|
control/MapContext.cpp
|
||||||
control/RPGEdit.cpp
|
control/RPGEdit.cpp
|
||||||
|
model/Entity.cpp
|
||||||
model/Map.cpp
|
model/Map.cpp
|
||||||
view/MapView.cpp
|
view/MapView.cpp
|
||||||
view/SpriteCache.cpp
|
view/SpriteCache.cpp
|
||||||
|
|
|
@ -37,7 +37,7 @@ MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const s
|
||||||
|
|
||||||
map.getEntities().emplace_back("square");
|
map.getEntities().emplace_back("square");
|
||||||
playerEntity = &map.getEntities().back();
|
playerEntity = &map.getEntities().back();
|
||||||
playerEntity->moveTo(Model::Position{8, 8});
|
playerEntity->moveTo(&map, Model::Position{8, 8});
|
||||||
|
|
||||||
view->updateEntities(map.getEntities());
|
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) {
|
void MapContext::movePlayer(Model::Direction dir, uint64_t time) {
|
||||||
if (playerEntity->hasTransition())
|
if (!playerEntity->move(&map, dir, time, time+250))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
playerEntity->move(dir, time, time+250);
|
|
||||||
|
|
||||||
eventBus->enqueue(
|
eventBus->enqueue(
|
||||||
[=] {
|
[=] {
|
||||||
playerEntity->finishTransition();
|
playerEntity->finishTransition(&map);
|
||||||
movePlayerContinue(time+250);
|
movePlayerContinue(time+250);
|
||||||
},
|
},
|
||||||
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 {
|
namespace Model {
|
||||||
|
|
||||||
|
class Map;
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
private:
|
private:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
|
@ -97,29 +99,13 @@ public:
|
||||||
return direction;
|
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 {
|
bool hasTransition() const {
|
||||||
return transitionEnd;
|
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 i = 0; i < 16; i++) {
|
||||||
for (int j = 0; j < 16; j++) {
|
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);
|
map->setTileAt(0, i, j, 1);
|
||||||
else
|
map->setCollisionAt(i, j, EMPTY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
map->setTileAt(0, i, j, 0);
|
map->setTileAt(0, i, j, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (4 <= i && i < 12 && j == 8)
|
if (4 <= i && i < 12 && j == 8)
|
||||||
map->setTileAt(1, i, j, 2);
|
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.emplace_back("square");
|
||||||
map->entities.back().moveTo(Model::Position{6, 6});
|
map->entities.back().moveTo(map.get(), Model::Position{6, 6});
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,16 +40,23 @@ namespace RPGEdit {
|
||||||
namespace Model {
|
namespace Model {
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
|
public:
|
||||||
|
enum CollisionType {
|
||||||
|
BLOCKED = 0,
|
||||||
|
EMPTY,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> tileset;
|
std::vector<std::string> tileset;
|
||||||
|
|
||||||
size_t width, height;
|
size_t width, height;
|
||||||
|
std::vector<CollisionType> collision;
|
||||||
std::vector<std::vector<uint32_t>> tiles;
|
std::vector<std::vector<uint32_t>> tiles;
|
||||||
std::deque<Entity> entities;
|
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) {
|
: width(width0), height(height0), collision(width*height) {
|
||||||
for (size_t i = 0; i < layers; i++)
|
for (size_t i = 0; i < layers; i++)
|
||||||
tiles.emplace_back(width*height);
|
tiles.emplace_back(width*height);
|
||||||
}
|
}
|
||||||
|
@ -83,6 +90,21 @@ public:
|
||||||
return tiles.size();
|
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) {
|
void setTileAt(size_t layer, size_t x, size_t y, uint32_t value) {
|
||||||
if (layer >= tiles.size() || x >= width || y >= height)
|
if (layer >= tiles.size() || x >= width || y >= height)
|
||||||
throw std::range_error("Map::setTileAt: bad coordinates");
|
throw std::range_error("Map::setTileAt: bad coordinates");
|
||||||
|
|
Reference in a new issue