Example #1
0
 static inline int GetCollidingSide2( Rect A,Rect B ){
     if (!IsColliding(A,B))
         return -1;
     Point Center1 = A.GetCenter();
     Point Center2 = B.GetCenter();
     int dir = 0;
     float angle = Center2.GetDirection(Center1);
     /*
         0 left
         1 top
         2 right
         3 bottom
     */
     angle = Geometry::toDeg(angle);
     if (angle <= 45 || angle > 315){
         dir = 0;
     }else if(angle > 45 && angle <= 135){
         dir = 1;
     }else if(angle > 135 && angle <= 225){
         dir = 2;
     }else if(angle > 225 && angle <= 315){
         dir = 3;
     }
     return dir;
 }
void DynamicEntity::TakeAStep()
{
    mySpeed.y+=myGravity;
    
    SetPosition(GetPosition()+mySpeed);
    CollisionGrid::AssignCells(this);
    
    std::list<GridCell*>::iterator accesIt;
    std::list<CollisionEntity*>::iterator cellIt;
    
    //std::cout<<"Number of Cells containing object:"<<CollisionGrid::accessList.size()<<std::endl;
    for (accesIt=CollisionGrid::accessList.begin(); accesIt!=CollisionGrid::accessList.end(); accesIt++)
    {
        //std::cout<<"Number of entities inside the cell "<<(*accesIt)<<" :"<<(*accesIt)->myInstances.size()<<std::endl;
        for (cellIt=(*accesIt)->myInstances.begin(); cellIt!=(*accesIt)->myInstances.end(); cellIt++)
        {
            //Ne pas vérifier avec soi même!
            if ((*cellIt)==this) break;
            
            if (IsColliding(**cellIt))
            {
                //std::cout<<"Collision!\n";
                //Check relative position and bounce
                mySpeed.y=-(mySpeed.y*0.8f);
            }
        }
    }
    
    
}
 void Collision::compareColliders(Collider *collider_a, ECS::RigidBody2D *a,
                                  Collider *collider_b, ECS::RigidBody2D *b,
                                  Contacts &contacts)
 {
     if (IsColliding(*collider_a, *collider_b, contacts))
     {
         collider_a->is_colliding = collider_b->is_colliding = true;
     }
 }
Example #4
0
Rect Collision::GetIntersectRect(Rect& a,  Rect& b){
    if (!IsColliding(a,b)){
        return Rect(0,0,0,0);
    }
    float c1 = std::max(a.x, b.x);
    float c2 = std::max(a.y, b.y);
    float c3 = std::min(a.x+a.w,b.x + b.w);
    float c4 = std::min(a.y + a.h, b.y + b.h);
    return Rect(c1,c2, c3-c1,c4-c2 );
}
Example #5
0
bool MyOctant::ContainsMoreThan(uint a_nBOs)
{
	uint nCount = 0;
	for (uint n = 0; n < m_pBOMngr->GetObjectCount(); n++)
	{
		if (IsColliding(n))
			nCount++;
		if (nCount > a_nBOs)
			return true;
	}
	return false;
}
Example #6
0
 static inline int GetCollidingDepth(Rect& a,  Rect& b){
     if (!IsColliding(a,b)){
         return 0;
     }
     int side = GetCollidingSide2(a,b);
     if (side == 0){
         return abs(a.x - (b.x+b.w) );
     }else if (side == 1){
         return abs(a.y - (b.y+b.h) );
     }else if (side == 2){
         return abs(a.x + a.w - (b.x) );
     }else if (side == 3){
         return abs(a.y + a.h - (b.y) );
     }else{
         return -1;
     }
 }
Example #7
0
        // Essa é uma implementação do SAT feita pelo Lucas Neves.
        // Recebe dois Rects e suas rotações, e detecta se os retângulos colidem.
        // Mais informações sobre o método podem ser encontradas nos seguintes links:
        // http://www.metanetsoftware.com/technique/tutorialA.html
        // http://www.gamedev.net/page/resources/_/technical/game-programming/2d-rotated-rectangle-collision-r2604
        static inline bool IsColliding(Rect& a,  Rect& b, float angleOfA, float angleOfB) {
            if (angleOfA == 0.0f && angleOfB == 0.0f){
                return IsColliding(a,b);
            }
            Point A[] = { Point( a.x, a.y + a.h ),
                          Point( a.x + a.w, a.y + a.h ),
                          Point( a.x + a.w, a.y ),
                          Point( a.x, a.y )
                        };
            Point B[] = { Point( b.x, b.y + b.h ),
                          Point( b.x + b.w, b.y + b.h ),
                          Point( b.x + b.w, b.y ),
                          Point( b.x, b.y )
                        };

            for (auto& v : A) {
                v = Rotate(v - a.GetCenter(), angleOfA) + a.GetCenter();
            }

            for (auto& v : B) {
                v = Rotate(v - b.GetCenter(), angleOfB) + b.GetCenter();
            }

            Point axes[] = { Norm(A[0] - A[1]), Norm(A[1] - A[2]), Norm(B[0] - B[1]), Norm(B[1] - B[2]) };

            for (auto& axis : axes) {
                float P[4];

                for (int i = 0; i < 4; ++i) P[i] = Dot(A[i], axis);

                float minA = *std::min_element(P, P + 4);
                float maxA = *std::max_element(P, P + 4);

                for (int i = 0; i < 4; ++i) P[i] = Dot(B[i], axis);

                float minB = *std::min_element(P, P + 4);
                float maxB = *std::max_element(P, P + 4);

                if (maxA <= minB || minA >= maxB)
                    return false;
            }

            return true;
        }
Example #8
0
void MyOctant::AssignIDtoBO(void)
{
	//traverse until you reach a leaf
	for (uint nChild = 0; nChild < m_nChildren; nChild++)
	{
		m_pChild[nChild]->AssignIDtoBO();
	}
	if(m_nChildren == 0) //if this is a leaf
	{
		uint nBOs = m_pBOMngr->GetObjectCount();
		for (uint nIndex = 0; nIndex < nBOs; nIndex++)
		{
			if (IsColliding(nIndex))
			{
				m_lBOs.push_back(nIndex);
			}
		}
	}
}
Example #9
0
/**
 * Corrects the box position so as not to collide with
 * the walls.
 */
Rect MovementMap::CorrectPosition(Rect box)
{
    std::cout << "Pos:(" << previousPos.GetX() << "," << previousPos.GetY() << ")" << std::endl;
    std::cout << "Width: " << previousPos.GetW() << std::endl;
    std::cout << "Height: " << previousPos.GetH() << std::endl;

    std::vector<Rect> collidingTiles;
    while (IsColliding(box))
    {
        collidingTiles = GetCollidingTiles(box);
        SortVector(collidingTiles);
        for (int i = 0; i < (int)collidingTiles.size(); i++)
            CorrectCollision(box, collidingTiles[i]);
        collidingTiles.clear();
        std::cout << "LOOP LULZ" << std::endl;
    }
    std::cout << "EXIT LOOP" << std::endl;
    return box;
}
Example #10
0
    bool Collision::CircleToAABB(PhysicBody* first, const Shape* firstShape, PhysicBody* second, const Shape* secondShape, sf::Vector2f& minDisplacement)
    {
        const CircleShape* circle = static_cast<const CircleShape*>(firstShape);
        const RectangleShape* aabb = static_cast<const RectangleShape*>(secondShape);
        sf::Vector2f position1 = first->GetPosition();
        sf::Vector2f position2 = second->GetPosition();
        sf::Vector2f boxHalfSize = aabb->GetHalfSize();

        if (!IsColliding(circle, position1, aabb, position2))
            return false;

        //TODO : set minDisplacement
        /*
        sf::Vector2f nearestPoint =  position1 - position2;
        nearestPoint.x = std::min(std::max(nearestPoint.x, -boxHalfSize.x), boxHalfSize.x);
        nearestPoint.y = std::min(std::max(nearestPoint.y, -boxHalfSize.y), boxHalfSize.y);
        nearestPoint += position2;

        float smallestX = std::min(nearestPoint.x - (position2.x - boxHalfSize.x), (position2.x + boxHalfSize.x) - nearestPoint.x);
        float smallestY = std::min(nearestPoint.y - (position2.y - boxHalfSize.y), (position2.y + boxHalfSize.y) - nearestPoint.y);
        if (smallestX < smallestY)
        {
            if (velocity1.x < 0.f)
                firstShape->SetPosition(sf::Vector2f(nearestPoint.x + circle->GetRadius(), position1.y));
            else
                firstShape->SetPosition(sf::Vector2f(nearestPoint.x - circle->GetRadius(), position1.y));
        }
        else
        {
            if (velocity1.y < 0.f)
                firstShape->SetPosition(sf::Vector2f(position1.x, nearestPoint.y + circle->GetRadius()));
            else
                firstShape->SetPosition(sf::Vector2f(position1.x, nearestPoint.y - circle->GetRadius()));
        }*/

        return true;
    }
Example #11
0
bool CCharacterController::RecoverFromPenetration(btCollisionWorld* pCollisionWorld)
{
	if (!IsColliding())
		return false;

	bool bPenetration = false;

	pCollisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_pGhostObject->getOverlappingPairCache(), pCollisionWorld->getDispatchInfo(), pCollisionWorld->getDispatcher());

	btVector3 vecCurrentPosition = m_pGhostObject->getWorldTransform().getOrigin();
	btVector3 vecOriginalPosition = vecCurrentPosition;

	btScalar maxPen = btScalar(0.0);
	for (int i = 0; i < m_pGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
	{
		m_aManifolds.resize(0);

		btBroadphasePair* pCollisionPair = &m_pGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];

		btCollisionObject* pObject0 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy0->m_clientObject);
		btCollisionObject* pObject1 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy1->m_clientObject);

		if (!pObject0->hasContactResponse() || !pObject1->hasContactResponse())
			continue;

		if (pObject0->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER || pObject1->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER)
			continue;

		if (pCollisionPair->m_algorithm)
			pCollisionPair->m_algorithm->getAllContactManifolds(m_aManifolds);

		for (int j = 0; j < m_aManifolds.size(); j++)
		{
			btPersistentManifold* pManifold = m_aManifolds[j];

			const btCollisionObject* obA = static_cast<const btCollisionObject*>(pManifold->getBody0());
			const btCollisionObject* obB = static_cast<const btCollisionObject*>(pManifold->getBody1());

			btScalar directionSign;
			CEntityHandle<CBaseEntity> hOther;
			size_t iExtra;
			if (obA == m_pGhostObject)
			{
				if (obB->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(-1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obB->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obB->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}
			else
			{
				if (obA->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obA->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obA->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}

			for (int p = 0; p < pManifold->getNumContacts(); p++)
			{
				const btManifoldPoint& pt = pManifold->getContactPoint(p);

				if (obA == m_pGhostObject)
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnB())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnB())))
							continue;
					}
				}
				else
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnA())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnA())))
							continue;
					}
				}

				btScalar flDistance = pt.getDistance();
				btScalar flMargin = std::max(obA->getCollisionShape()->getMargin(), obB->getCollisionShape()->getMargin());

				if (flDistance < -flMargin)
				{
					flDistance += flMargin;

					if (flDistance < maxPen)
						maxPen = flDistance;

					btScalar flDot = pt.m_normalWorldOnB.dot(GetUpVector());
					btVector3 vecAdjustment;
					if (flDot > 0.707f)
						vecAdjustment = GetUpVector() * (directionSign * flDistance * 1.001f);
					else
						vecAdjustment = pt.m_normalWorldOnB * (directionSign * flDistance * 1.001f);

					if (vecAdjustment.length2() < 0.001*0.001)
						continue;

					vecCurrentPosition += vecAdjustment;

					bPenetration = true;
				} else {
					//printf("touching %f\n", dist);
				}
			}

			//pManifold->clearManifold();
		}
	}

	btTransform mNew = m_pGhostObject->getWorldTransform();
	mNew.setOrigin(mNew.getOrigin() + (vecCurrentPosition - vecOriginalPosition) * m_vecLinearFactor);
	m_pGhostObject->setWorldTransform(mNew);

	return bPenetration;
}
void CollisionSystem::CheckCollisions()
{
    float maxDistance = CFG_GETF("COLLISION_MAX_DISTANCE");
    Quadtree<std::shared_ptr<Entity>> quadtree(Rectangle(CFG_GETF("LEVEL_MIN_X"), CFG_GETF("LEVEL_MIN_Y"), CFG_GETF("LEVEL_MAX_X") - CFG_GETF("LEVEL_MIN_X"), CFG_GETF("LEVEL_MAX_Y") - CFG_GETF("LEVEL_MIN_Y")));
    auto cameraEntities = Engine::GetInstance().GetAllEntitiesWithComponentOfClass("CameraComponent");
    collidableEntities = Engine::GetInstance().GetAllEntitiesWithComponentOfClass("ColliderComponent");

    // Clear deleted entities from last iteration.
    deletedEntities.clear();

    std::shared_ptr<Entity> cameraEntity;
    if (cameraEntities.size() > 0)
        cameraEntity = cameraEntities[0];

    // Build quadtree for close enough entities.
    for (auto entity : collidableEntities)
    {
        auto particleComponent = std::static_pointer_cast<ParticleComponent>(Engine::GetInstance().GetSingleComponentOfClass(entity, "ParticleComponent"));
        auto position = particleComponent->GetPosition();

        // Ignore collision from things that aren't visible.
        if (cameraEntity)
        {
            auto cameraComponent = std::static_pointer_cast<CameraComponent>(Engine::GetInstance().GetSingleComponentOfClass(cameraEntity, "CameraComponent"));
            auto cameraPosition = cameraComponent->GetPosition();

            if (cameraPosition.CalculateDistance(position) > maxDistance)
                continue;
            else
                quadtree.Add(entity, position);
        }
        else
        {
            quadtree.Add(entity, position);
        }
    }

    // Detect and solve collisions.
    for (unsigned int i = 0; i < collidableEntities.size(); ++i)
    {
        auto entity = collidableEntities[i];

        auto particleComponent = std::static_pointer_cast<ParticleComponent>(Engine::GetInstance().GetSingleComponentOfClass(entity, "ParticleComponent"));
        auto position = particleComponent->GetPosition();
        auto quadtreeEntities = quadtree.Get(position);

        for (unsigned int j = 0; j < quadtreeEntities.size(); ++j)
        {
            auto otherEntity = quadtreeEntities[j];

            if (std::find(deletedEntities.begin(), deletedEntities.end(),  entity->GetId()) != deletedEntities.end())
                continue;

            if (std::find(deletedEntities.begin(), deletedEntities.end(),  otherEntity->GetId()) != deletedEntities.end())
                continue;

            if (entity->GetId() != otherEntity->GetId()
                && IsColliding(entity, otherEntity))
                SolveCollision(entity, otherEntity);
        }
    }
}
Example #13
0
bool Scene::IsColliding(const Vec2& vec, const Rect& rect) const
{
	return IsColliding(rect,Rect(vec.x,vec.y,1,1));
}
Example #14
0
void SATCollision::TestCollision()
{
	const int winWidth = 800;
	const int winHeight = 600;

	initRandom();

	sf::RenderWindow window(sf::VideoMode(winWidth, winHeight), "Test");

	sf::RectangleShape rect1(sf::Vector2f(20, 100));
	rect1.setFillColor(sf::Color(0, 255, 0, 255));
	rect1.setOrigin(10, 10);
	rect1.setPosition(300, 400);
	sf::RectangleShape rect2(sf::Vector2f(50, 50));
	rect2.setFillColor(sf::Color(255, 0, 0, 255));
	rect2.setOrigin(rect2.getSize()/2.0f);
	rect2.setPosition(355, 400);

	bool rotLeft = false;
	bool rotRight = false;

    while(true){
		sf::Event anEvent;

		while(window.pollEvent(anEvent)) {
			if(anEvent.type == sf::Event::KeyPressed) {
				switch(anEvent.key.code) {
				case sf::Keyboard::A :
					rotLeft = true;
					break;
				case sf::Keyboard::D :
					rotRight = true;
					break;
				}
			} else if(anEvent.type == sf::Event::KeyReleased) {
				switch(anEvent.key.code) {
				case sf::Keyboard::A :
					rotLeft = false;
					break;
				case sf::Keyboard::D :
					rotRight = false;
					break;
				}
			}
		}

		if(rotLeft) {
			rect1.setRotation(rect1.getRotation()-1.0f);
		}
		if(rotRight) {
			rect1.setRotation(rect1.getRotation()+1.0f);
		}

		sf::FloatRect bbox1 = rect1.getLocalBounds();
		sf::FloatRect bbox2 = rect2.getLocalBounds();
		std::vector<sf::Vector2f> rect1pts = GetTransformedRect(rect1, bbox1);
		std::vector<sf::Vector2f> rect2pts = GetTransformedRect(rect2, bbox2);
		bool collide = IsColliding(rect1pts, rect2pts);
		printf("%s\n", (collide?"colliding":"not colliding"));

		sf::CircleShape point(3.0f);
		point.setOrigin(point.getRadius()/2.0f, point.getRadius()/2.0f);
		window.clear();
		window.draw(rect1);
		window.draw(rect2);

		for(unsigned int i = 0; i < rect1pts.size(); i++) {
			point.setPosition(rect1pts[i]);
			window.draw(point);
		}
		for(unsigned int i = 0; i < rect2pts.size(); i++) {
			point.setPosition(rect2pts[i]);
			window.draw(point);
		}
		window.display();

		sf::sleep(sf::seconds(0.005f));
    }
}