bool Level::collidesY(const sf::FloatRect& boundingBox, const DynamicTile* exclude) const { // check for collision with level rect if (boundingBox.top < m_levelData.levelRect.top || boundingBox.top + boundingBox.height > m_levelData.levelRect.top + m_levelData.levelRect.height) { return true; } // normalize bounding box values so they match our collision grid. Wondering about the next two lines? Me too. We just don't want to floor values that are exactly on the boundaries. But only those that are down and right. int bottomY = static_cast<int>(floor((boundingBox.top + boundingBox.height) / tileHeight) == (boundingBox.top + boundingBox.height) / tileHeight ? (boundingBox.top + boundingBox.height) / tileHeight - 1 : floor((boundingBox.top + boundingBox.height) / tileHeight)); int rightX = static_cast<int>(floor((boundingBox.left + boundingBox.width) / tileWidth) == (boundingBox.left + boundingBox.width) / tileWidth ? (boundingBox.left + boundingBox.width) / tileWidth - 1 : floor((boundingBox.left + boundingBox.width) / tileWidth)); sf::Vector2i topLeft(static_cast<int>(floor(boundingBox.left / tileWidth)), static_cast<int>(floor(boundingBox.top / tileHeight))); sf::Vector2i topRight(rightX, static_cast<int>(floor(boundingBox.top / tileHeight))); sf::Vector2i bottomLeft(static_cast<int>(floor(boundingBox.left / tileWidth)), bottomY); sf::Vector2i bottomRight(rightX, bottomY); // check top side int y = topLeft.y; for (int x = topLeft.x; x <= topRight.x; x++) { if (y > m_levelData.collidableTilePositions.size() || y < 0 || x < 0 || x > m_levelData.collidableTilePositions[y].size()) { // check for out of range (happens seldom because of rounding problems above) return true; } if (m_levelData.collidableTilePositions[y][x]) { return true; } } // check bottom side y = bottomLeft.y; for (int x = bottomLeft.x; x <= bottomRight.x; x++) { if (y > m_levelData.collidableTilePositions.size() || y < 0 || x < 0 || x > m_levelData.collidableTilePositions[y].size()) { // check for out of range (happens seldom because of rounding problems above) return true; } if (m_levelData.collidableTilePositions[y][x]) { return true; } } // check collidable dynamic tiles for (GameObject* go : *m_dynamicTiles) { if (!go->isViewable()) continue; DynamicTile* tile = dynamic_cast<DynamicTile*>(go); if (tile != nullptr && tile != exclude && tile->getIsCollidable() && tile->getBoundingBox()->intersects(boundingBox)) { return true; } } return false; }
void Level::collideWithDynamicTiles(LevelMovableGameObject* mob, const sf::FloatRect* boundingBox) const { for (auto& it : *m_dynamicTiles) { DynamicTile* tile = dynamic_cast<DynamicTile*>(it); if (tile != nullptr && (tile->getBoundingBox()->intersects(*boundingBox))) { tile->onHit(mob); } } }
void Level::collideWithDynamicTiles(Spell* spell, const sf::FloatRect* boundingBox) const { size_t size = m_dynamicTiles->size(); // Note: this loop type allows objects to be added to the back of the list while iterating over it. for (size_t i = 0; i < size; ++i) { DynamicTile* tile = dynamic_cast<DynamicTile*>(m_dynamicTiles->at(i)); if (tile != nullptr && (tile->getBoundingBox()->intersects(*boundingBox))) { tile->onHit(spell); } } }
/** * @brief Enables or disables the dynamic tiles related to these stairs. * * The dynamic tiles impacted by this function are the ones whose prefix is the stairs's name * followed by "_enabled" or "_disabled", depending on the stairs state. */ void Stairs::update_dynamic_tiles() { std::list<MapEntity*> tiles = get_entities().get_entities_with_prefix(DYNAMIC_TILE, get_name() + "_enabled"); std::list<MapEntity*>::iterator it; for (it = tiles.begin(); it != tiles.end(); it++) { DynamicTile *tile = (DynamicTile*) *it; tile->set_enabled(is_enabled()); } tiles = get_entities().get_entities_with_prefix(DYNAMIC_TILE, get_name() + "_disabled"); for (it = tiles.begin(); it != tiles.end(); it++) { DynamicTile *tile = (DynamicTile*) *it; tile->set_enabled(!is_enabled()); } }
/** * @brief Enables or disables the dynamic tiles related to this door. * * The dynamic tiles impacted by this function are the ones whose prefix is the door's name * followed by "_closed" or "_open", depending on the door state. */ void Door::update_dynamic_tiles() { std::list<MapEntity*> tiles = get_entities().get_entities_with_prefix(DYNAMIC_TILE, get_name() + "_closed"); std::list<MapEntity*>::iterator it; for (it = tiles.begin(); it != tiles.end(); it++) { DynamicTile* tile = static_cast<DynamicTile*>(*it); tile->set_enabled(is_closed() || is_opening()); } tiles = get_entities().get_entities_with_prefix(DYNAMIC_TILE, get_name() + "_open"); for (it = tiles.begin(); it != tiles.end(); it++) { DynamicTile* tile = static_cast<DynamicTile*>(*it); tile->set_enabled(is_open() || is_closing()); } }