Moved raycast from TileManager to World.
This commit is contained in:
parent
0fc271495d
commit
3ee0c71857
5 changed files with 46 additions and 44 deletions
|
@ -241,3 +241,46 @@ World::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a raycast between two points to check if the path between them is
|
||||
* clear of walls. Does not consider characters, bullets etc.
|
||||
*
|
||||
* @param lineStart First point of the line to test.
|
||||
* @param lineEnd Second point of the line to test.
|
||||
* @return True if the ray was not blocked.
|
||||
*/
|
||||
bool
|
||||
World::raycast(const sf::Vector2f& lineStart,
|
||||
const sf::Vector2f& lineEnd) const {
|
||||
assert(lineStart != lineEnd);
|
||||
sf::Vector2f lineCenter = lineStart + 0.5f * (lineEnd - lineStart);
|
||||
for (const auto& it : mDrawables.at(Sprite::Category::CATEGORY_WORLD)) {
|
||||
if (it->collisionEnabled(Sprite::Category::CATEGORY_WORLD))
|
||||
continue;
|
||||
sf::Vector2f axis = it->getPosition() - lineCenter;
|
||||
if (axis == sf::Vector2f())
|
||||
return false;
|
||||
|
||||
axis = thor::unitVector(axis);
|
||||
sf::Vector2f halfsize = it->getSize() / 2.0f;
|
||||
float rectPosProjected = thor::dotProduct(axis, it->getPosition());
|
||||
float lineStartProjected = thor::dotProduct(axis, lineStart);
|
||||
float lineEndProjected = thor::dotProduct(axis, lineEnd);
|
||||
// For corner projections, those on the same line with the rect
|
||||
// center are equal by value, so we only need one on each axis
|
||||
// and take the maximum.
|
||||
float rectHalfWidthProjected = std::max(
|
||||
abs(thor::dotProduct(axis, halfsize)),
|
||||
abs(thor::dotProduct(axis,
|
||||
sf::Vector2f(halfsize.x, -halfsize.y))));
|
||||
Interval line = Interval::IntervalFromPoints(lineStartProjected,
|
||||
lineEndProjected);
|
||||
Interval rect = Interval::IntervalFromRadius(rectPosProjected,
|
||||
rectHalfWidthProjected);
|
||||
// Allow movement if sprites are moving apart.
|
||||
if (line.getOverlap(rect).getLength() > 0.0f)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
void think(int elapsed);
|
||||
std::vector<std::shared_ptr<Character> >
|
||||
getCharacters(const sf::Vector2f& position, float maxDistance) const;
|
||||
bool raycast(const sf::Vector2f& lineStart,
|
||||
const sf::Vector2f& lineEnd) const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ Character::isMoving() const {
|
|||
*/
|
||||
bool
|
||||
Character::isVisible(const sf::Vector2f& target) const {
|
||||
return mTileManager.raycast(getPosition(), target);
|
||||
return mWorld.raycast(getPosition(), target);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -96,44 +96,3 @@ TileManager::insertTile(const TilePosition& position, Type type) {
|
|||
mTiles.push_back(tile);
|
||||
mWorld.insert(tile);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a raycast between two points to check if the path between them is
|
||||
* clear of walls.
|
||||
*
|
||||
* @param lineStart First point of the line to test.
|
||||
* @param lineEnd Second point of the line to test.
|
||||
* @return True if the ray was not blocked.
|
||||
*/
|
||||
bool
|
||||
TileManager::raycast(const sf::Vector2f& lineStart,
|
||||
const sf::Vector2f& lineEnd) const {
|
||||
assert(lineStart != lineEnd);
|
||||
sf::Vector2f lineCenter = lineStart + 0.5f * (lineEnd - lineStart);
|
||||
for (auto it : mTiles) {
|
||||
if (it->getType() == Type::FLOOR)
|
||||
continue;
|
||||
sf::Vector2f axis = it->getPosition() - lineCenter;
|
||||
if (axis == sf::Vector2f())
|
||||
return false;
|
||||
|
||||
axis = thor::unitVector(axis);
|
||||
sf::Vector2f halfsize = it->getSize() / 2.0f;
|
||||
float rectPosProjected = thor::dotProduct(axis, it->getPosition());
|
||||
float lineStartProjected = thor::dotProduct(axis, lineStart);
|
||||
float lineEndProjected = thor::dotProduct(axis, lineEnd);
|
||||
// For corner projections, those on the same line with the rect
|
||||
// center are equal by value, so we only need one on each axis
|
||||
// and take the maximum.
|
||||
float rectHalfWidthProjected = std::max(
|
||||
abs(thor::dotProduct(axis, halfsize)),
|
||||
abs(thor::dotProduct(axis,
|
||||
sf::Vector2f(halfsize.x, -halfsize.y))));
|
||||
Interval line = Interval::IntervalFromPoints(lineStartProjected, lineEndProjected);
|
||||
Interval rect = Interval::IntervalFromRadius(rectPosProjected, rectHalfWidthProjected);
|
||||
// Allow movement if sprites are moving apart.
|
||||
if (line.getOverlap(rect).getLength() > 0.0f)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@ public:
|
|||
explicit TileManager(World& world);
|
||||
|
||||
void insertTile(const TilePosition& position, Type type);
|
||||
bool raycast(const sf::Vector2f& lineStart,
|
||||
const sf::Vector2f& lineEnd) const;
|
||||
|
||||
private:
|
||||
class Tile;
|
||||
|
|
Reference in a new issue