void CollisionMap::findCollidableTiles(std::vector<CollisionRect> &rects) const { sf::Vector2i worldTileSize = container->getTileSize(); // find collidable tiles sf::Vector2f size(Constants::tileSizef, Constants::tileSizef); // todo: assuming all tiles are the same size for (auto y = 0; y < worldTileSize.y; ++y) { for (auto x = 0; x < worldTileSize.x; ++x) { BlockType bt = container->getBlockAt({x, y}, LAYER_TERRAIN); // the only collidable tile layer bool collide = isCollidable(bt); bool interact = isInteractable(bt); if (!collide && !interact) continue; sf::Vector2f pos(Utils::toPixel(sf::Vector2f(x, y))); rects.emplace_back(sf::FloatRect(pos, size), 0.f, bt); } } // objects auto objects = container->getTerrain().getObjects(); for (auto &obj : objects) { auto pos = obj.tilePos; pos.y -= 1 / Constants::scale; pos = Math::multiply(pos, Constants::tileScale); rects.emplace_back(sf::FloatRect(pos, size), obj.rotation, obj.type); } }
bool Entity::collidesWith(Entity *other) { if (other == this || !isCollidable() || !other->isCollidable()) { return false; } int ax1 = mX, ay1 = mY, ax2 = mX + mW, ay2 = mY + mH; int bx1 = other->mX, by1 = other->mY, bx2 = other->mX + other->mW, by2 = other->mY + other->mH; return ax1 < bx2 && ay1 < by2 && bx1 < ax2 && by1 < ay2; }
//============================================================================== bool BodyNodeDistanceFilter::needDistance( const collision::CollisionObject* object1, const collision::CollisionObject* object2) const { if (object1 == object2) return false; auto shapeNode1 = object1->getShapeFrame()->asShapeNode(); auto shapeNode2 = object2->getShapeFrame()->asShapeNode(); if (!shapeNode1 || !shapeNode2) return true; // We assume that non-ShapeNode is always being checked collision. auto bodyNode1 = shapeNode1->getBodyNodePtr(); auto bodyNode2 = shapeNode2->getBodyNodePtr(); if (!bodyNode1->isCollidable() || !bodyNode2->isCollidable()) return false; if (bodyNode1->getSkeleton() == bodyNode2->getSkeleton()) { auto skeleton = bodyNode1->getSkeleton(); if (!skeleton->isEnabledSelfCollisionCheck()) return false; if (!skeleton->isEnabledAdjacentBodyCheck()) { if (areAdjacentBodies(bodyNode1, bodyNode2)) return false; } } return true; }
bool FCLMESHCollisionDetector::checkCollision(bool _checkAllCollisions, bool _calculateContactPoints) { int num_max_contact = 100; clearAllContacts(); bool collision = false; FCLMESHCollisionNode* FCLMESHCollisionNode1 = NULL; FCLMESHCollisionNode* FCLMESHCollisionNode2 = NULL; for (int i = 0; i < mCollisionNodes.size(); i++) { mCollisionNodes[i]->getBodyNode()->setColliding(false); } for (int i = 0; i < mCollisionNodes.size(); i++) { FCLMESHCollisionNode1 = static_cast<FCLMESHCollisionNode*>(mCollisionNodes[i]); for (int j = i + 1; j < mCollisionNodes.size(); j++) { FCLMESHCollisionNode2 = static_cast<FCLMESHCollisionNode*>(mCollisionNodes[j]); if (!isCollidable(FCLMESHCollisionNode1, FCLMESHCollisionNode2)) { continue; } if(FCLMESHCollisionNode1->checkCollision(FCLMESHCollisionNode2, _calculateContactPoints ? &mContacts : NULL, num_max_contact)) { collision = true; mCollisionNodes[i]->getBodyNode()->setColliding(true); mCollisionNodes[j]->getBodyNode()->setColliding(true); if(!_checkAllCollisions) { return true; } } } } return collision; }
bool object::checkCollision(object &obj) { if ( !isCollidable() || !obj.isCollidable() ) { return false; } if ( x < obj.getX() + obj.getBoundX() - 1 && y < obj.getY() + obj.getBoundY() - 1 && x + boundX -1 > obj.getX() && y + boundY - 1 > obj.getY() ) { collision(); obj.collision(); return true; } return false; }
bool FCLMeshCollisionDetector::detectCollision(bool _checkAllCollisions, bool _calculateContactPoints) { clearAllContacts(); bool collision = false; FCLMeshCollisionNode* FCLMeshCollisionNode1 = NULL; FCLMeshCollisionNode* FCLMeshCollisionNode2 = NULL; for (int i = 0; i < mCollisionNodes.size(); i++) mCollisionNodes[i]->getBodyNode()->setColliding(false); for (int i = 0; i < mCollisionNodes.size(); i++) { FCLMeshCollisionNode1 = static_cast<FCLMeshCollisionNode*>(mCollisionNodes[i]); for (int j = i + 1; j < mCollisionNodes.size(); j++) { FCLMeshCollisionNode2 = static_cast<FCLMeshCollisionNode*>(mCollisionNodes[j]); if (!isCollidable(FCLMeshCollisionNode1, FCLMeshCollisionNode2)) continue; if(FCLMeshCollisionNode1->detectCollision(FCLMeshCollisionNode2, _calculateContactPoints ? &mContacts : NULL, mNumMaxContacts)) { collision = true; mCollisionNodes[i]->getBodyNode()->setColliding(true); mCollisionNodes[j]->getBodyNode()->setColliding(true); if(!_checkAllCollisions) return true; } } } return collision; }
bool DARTCollisionDetector::detectCollision(bool /*_checkAllCollisions*/, bool /*_calculateContactPoints*/) { clearAllContacts(); // Set all the body nodes are not in colliding for (size_t i = 0; i < mCollisionNodes.size(); i++) mCollisionNodes[i]->getBodyNode()->setColliding(false); std::vector<Contact> contacts; for (size_t i = 0; i < mCollisionNodes.size(); i++) { for (size_t j = i + 1; j < mCollisionNodes.size(); j++) { CollisionNode* collNode1 = mCollisionNodes[i]; CollisionNode* collNode2 = mCollisionNodes[j]; dynamics::BodyNode* BodyNode1 = collNode1->getBodyNode(); dynamics::BodyNode* BodyNode2 = collNode2->getBodyNode(); if (!isCollidable(collNode1, collNode2)) continue; for (size_t k = 0; k < BodyNode1->getNumCollisionShapes(); k++) { for (size_t l = 0; l < BodyNode2->getNumCollisionShapes(); l++) { int currContactNum = mContacts.size(); contacts.clear(); collide(BodyNode1->getCollisionShape(k), BodyNode1->getTransform() * BodyNode1->getCollisionShape(k)->getLocalTransform(), BodyNode2->getCollisionShape(l), BodyNode2->getTransform() * BodyNode2->getCollisionShape(l)->getLocalTransform(), &contacts); size_t numContacts = contacts.size(); for (unsigned int m = 0; m < numContacts; ++m) { Contact contactPair; contactPair = contacts[m]; contactPair.bodyNode1 = BodyNode1; contactPair.bodyNode2 = BodyNode2; assert(contactPair.bodyNode1 != NULL); assert(contactPair.bodyNode2 != NULL); mContacts.push_back(contactPair); } std::vector<bool> markForDeletion(numContacts, false); for (size_t m = 0; m < numContacts; m++) { for (size_t n = m + 1; n < numContacts; n++) { Eigen::Vector3d diff = mContacts[currContactNum + m].point - mContacts[currContactNum + n].point; if (diff.dot(diff) < 1e-6) { markForDeletion[m] = true; break; } } } for (int m = numContacts - 1; m >= 0; m--) { if (markForDeletion[m]) mContacts.erase(mContacts.begin() + currContactNum + m); } } } } } for (size_t i = 0; i < mContacts.size(); ++i) { // Set these two bodies are in colliding mContacts[i].bodyNode1->setColliding(true); mContacts[i].bodyNode2->setColliding(true); } return !mContacts.empty(); }