From 93b3e4004387047c25b2f5a190aced01c9091934 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 2 Feb 2021 19:34:48 -0500 Subject: Added collision with map tiles --- src/direction.h | 10 +++++ src/map.cpp | 38 +++++++++++++----- src/map.h | 3 ++ src/party.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++------------- src/party.h | 2 + src/vector.h | 8 +++- 6 files changed, 144 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/direction.h b/src/direction.h index ebc0e46..a83a6f8 100644 --- a/src/direction.h +++ b/src/direction.h @@ -41,4 +41,14 @@ inline vec2i unitVecInDirection(Direction dir) { } } +inline bool dirHasDir(Direction value, Direction inner) { + switch (inner) { + case Direction::up: return value == Direction::up_left || value == Direction::up || value == Direction::up_right; + case Direction::down: return value == Direction::down_left || value == Direction::down || value == Direction::down_right; + case Direction::left: return value == Direction::up_left || value == Direction::left || value == Direction::down_left; + case Direction::right: return value == Direction::up_right || value == Direction::right || value == Direction::down_right; + default: return value == inner; + } +} + #endif /* end of include guard: DIRECTION_H_AB66A90E */ diff --git a/src/map.cpp b/src/map.cpp index a60cbba..7d9800d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,6 +1,7 @@ #include "map.h" #include #include +#include #include #include #include "renderer.h" @@ -21,11 +22,10 @@ Map::Map(std::string_view filename, Renderer& renderer) { int firstGID = 0; // There should only be one tileset. - for (const tmx::Tileset& tileset : mapfile.getTilesets()) { - firstGID = tileset.getFirstGID(); - tilesetTextureId_ = renderer.loadImageFromFile(tileset.getImagePath()); - tilesetColumns_ = tileset.getColumnCount(); - } + const tmx::Tileset& tileset = mapfile.getTilesets()[0]; + firstGID = tileset.getFirstGID(); + tilesetTextureId_ = renderer.loadImageFromFile(tileset.getImagePath()); + tilesetColumns_ = tileset.getColumnCount(); for (const auto& layer : mapfile.getLayers()) { if (layer->getType() == tmx::Layer::Type::Tile) { @@ -34,13 +34,33 @@ Map::Map(std::string_view filename, Renderer& renderer) { std::vector tilesToStore; for (const auto& maptile : tileLayer.getTiles()) { - tilesToStore.push_back(Tile { - .id = maptile.ID - firstGID, - .flipHorizontal = (maptile.flipFlags & tmx::TileLayer::Horizontal) != 0, - .flipVertical = (maptile.flipFlags & tmx::TileLayer::Vertical) != 0 }); + Tile tile; + tile.id = maptile.ID - firstGID; + tile.flipHorizontal = (maptile.flipFlags & tmx::TileLayer::Horizontal) != 0; + tile.flipVertical = (maptile.flipFlags & tmx::TileLayer::Vertical) != 0; + + for (const tmx::Property& property : tileset.getTile(maptile.ID)->properties) { + if (property.getName() == "solid" && property.getBoolValue()) { + tile.blocked = true; + } + } + + tilesToStore.push_back(std::move(tile)); } layers_.push_back(std::move(tilesToStore)); } } } + +bool Map::isBlocked(int x, int y) const { + int i = x + y * mapSize_.w(); + + for (const std::vector& layer : layers_) { + if (layer.at(i).blocked) { + return true; + } + } + + return false; +} diff --git a/src/map.h b/src/map.h index 1031996..2f8ec1a 100644 --- a/src/map.h +++ b/src/map.h @@ -12,6 +12,7 @@ struct Tile { unsigned int id = 0; bool flipHorizontal = false; bool flipVertical = false; + bool blocked = false; }; class Map { @@ -29,6 +30,8 @@ public: int getTilesetColumns() const { return tilesetColumns_; } + bool isBlocked(int x, int y) const; + private: vec2i mapSize_; diff --git a/src/party.cpp b/src/party.cpp index 2af252f..307bca8 100644 --- a/src/party.cpp +++ b/src/party.cpp @@ -1,5 +1,6 @@ #include "party.h" #include "consts.h" +#include void Party::addMember(Game& game, int spriteId) { int index = members_.size(); @@ -93,41 +94,84 @@ void Party::move(Game& game, const Input& keystate) { pLoc += (unitVecInDirection(dir) * speed); - game.moveSprite(members_[0].spriteId, pLoc); + // Check collision. + const Map& map = game.getMap(); + bool blocked = false; + + const vec2i UL_COL_BOX = { 8, 8 }; + const vec2i DR_COL_BOX = { 4, 0 }; + vec2i oldColPosUL = (p1.loc() - UL_COL_BOX) / map.getTileSize(); + vec2i newColPosUL = (pLoc - UL_COL_BOX) / map.getTileSize(); + vec2i oldColPosDR = (p1.loc() + DR_COL_BOX) / map.getTileSize(); + vec2i newColPosDR = (pLoc + DR_COL_BOX) / map.getTileSize(); + + if (dirHasDir(dir, Direction::right) && + newColPosDR.x() > oldColPosDR.x()) { + for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { + if (map.isBlocked(newColPosDR.x(), y)) { + blocked = true; + pLoc.x() = p1.loc().x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } - for (int i = 1; i < members_.size(); i++) { - const Sprite& pNext = game.getSprite(members_[i].spriteId); - const Movement& posdir = members_[i].movement.front(); - game.moveSprite(members_[i].spriteId, posdir.pos); - game.setSpriteDirection(members_[i].spriteId, posdir.dir); + if (dirHasDir(dir, Direction::left) && + newColPosUL.x() < oldColPosUL.x()) { + for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { + if (map.isBlocked(newColPosUL.x(), y)) { + blocked = true; + pLoc.x() = p1.loc().x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } - members_[i].movement.pop_front(); - members_[i].movement.push_back({.pos = pLoc, .dir = dir}); + if (dirHasDir(dir, Direction::down) && + newColPosDR.y() > oldColPosDR.y()) { + for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { + if (map.isBlocked(x, newColPosDR.y())) { + blocked = true; + pLoc.y() = p1.loc().y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } } -} -void Party::beginCrouch(Game& game) { - if (state_ == State::Running) { - state_ = State::Normal; + if (dirHasDir(dir, Direction::up) && + newColPosUL.y() < oldColPosUL.y()) { + for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { + if (map.isBlocked(x, newColPosUL.y())) { + blocked = true; + pLoc.y() = p1.loc().y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } + + if (blocked && state_ == State::Running) { + stopRunning(game); + } + + // Move everything + if (pLoc != p1.loc()) { + game.moveSprite(members_[0].spriteId, pLoc); - // Double the movement buffer for the followers. for (int i = 1; i < members_.size(); i++) { - std::deque newMove; - vec2i lastPos = game.getSprite(members_[i].spriteId).loc(); - - while (!members_[i].movement.empty()) { - Movement m1 = members_[i].movement.front(); - Movement m2 = m1; - m1.pos = (m1.pos + lastPos) / 2; - lastPos = m2.pos; - - newMove.push_back(m1); - newMove.push_back(m2); - members_[i].movement.pop_front(); - } + const Sprite& pNext = game.getSprite(members_[i].spriteId); + const Movement& posdir = members_[i].movement.front(); + game.moveSprite(members_[i].spriteId, posdir.pos); + game.setSpriteDirection(members_[i].spriteId, posdir.dir); - members_[i].movement = std::move(newMove); + members_[i].movement.pop_front(); + members_[i].movement.push_back({.pos = pLoc, .dir = dir}); } + } +} + +void Party::beginCrouch(Game& game) { + if (state_ == State::Running) { + stopRunning(game); } else { state_ = State::Crouching; @@ -159,3 +203,26 @@ void Party::endCrouch(Game& game) { } } } + +void Party::stopRunning(Game& game) { + state_ = State::Normal; + + // Double the movement buffer for the followers. + for (int i = 1; i < members_.size(); i++) { + std::deque newMove; + vec2i lastPos = game.getSprite(members_[i].spriteId).loc(); + + while (!members_[i].movement.empty()) { + Movement m1 = members_[i].movement.front(); + Movement m2 = m1; + m1.pos = (m1.pos + lastPos) / 2; + lastPos = m2.pos; + + newMove.push_back(m1); + newMove.push_back(m2); + members_[i].movement.pop_front(); + } + + members_[i].movement = std::move(newMove); + } +} diff --git a/src/party.h b/src/party.h index 06f8639..2864073 100644 --- a/src/party.h +++ b/src/party.h @@ -18,6 +18,8 @@ public: private: + void stopRunning(Game& game); + enum class State { Normal, Crouching, diff --git a/src/vector.h b/src/vector.h index 8019edf..9f6d54f 100644 --- a/src/vector.h +++ b/src/vector.h @@ -97,12 +97,16 @@ public: return vec2(x() * other.x(), y() * other.y()); } + vec2 operator/(const vec2& other) const { + return vec2(x() / other.x(), y() / other.y()); + } + bool operator==(const vec2& other) const { - return std::tie(x(), other.x()) == std::tie(y(), other.y()); + return (x() == other.x()) && (y() == other.y()); } bool operator!=(const vec2& other) const { - return std::tie(x(), other.x()) != std::tie(y(), other.y()); + return (x() != other.x()) || (y() != other.y()); } }; -- cgit 1.4.1