Linear collision question

Started by
10 comments, last by Soundstone 10 years, 2 months ago

Thanks Haegarr,

I finally got the algorithm working for the ceiling. It kind of works for the floor at this moment, but I'm sure I'm pretty close to it. Once again thanks for the help.

Regards

Advertisement

I figured I would post the full solution in case anyone ever needs to use this again. Here is how I was able to solve the collision checks for both the ceiling and the floor - both of which are generated randomly with array of Vector3.

In the game loop I calculate if the player is close enough to the ceiling to be worthy of checking and the same goes for the floor. If the player is close enough I use a for loop to cycle through the vector3 positions of the ceiling / floor points. It continues over the points that are too far from the player. Once it finds a pair of contiguous points it sends a call out to check the ceiling or floor for collision based on these two points. Here is the cycle in game loop:


for (int i = 0; i < NUM_POINTS; i++)
    {
	if (ship.shipPos.x > topPoints[i + 1].x)
	      continue;
	if (ship.shipPos.x < topPoints[i].x)
	      continue;
					
	collide = CheckCollisionsTop(ship, topPoints[i], topPoints[i + 1]);
    } 

Below you'll see the collision check for my ceiling. It takes a reference to a SpaceShip because eventually it will alter the ship's position based on collision. It also takes 2 Vector3 positions. The line segment is just a new vector that contains the distance between pointTwo and pointOne. The shipWidthPosition alters the ship position to test based on which side of the ship we want to test. This matters for the direction of the line in question. If the line is upwards - pointTwo.y is higher than pointOne.y then we will use normal ship position since the (X,Y,Z) of shipPos is the upper left corner of the ship. For a downward line (pointOne.y is higher than pointTwo.y) then we use the other side by adding the width to the ships coords.


bool CheckCollisionsTop(SpaceShip &ship, Vector3 pointOne, Vector3 pointTwo)
{
	Vector3 lineSegment = GetVectorDistance(pointOne, pointTwo);
	Vector3 shipWidthPosition(ship.shipPos.x + ship.GetWidth(), ship.shipPos.y, ship.shipPos.z);

	if (pointTwo.y < pointOne.y) //upwards line
	{
		Vector3 lineNormal(lineSegment.y, -lineSegment.x, 0);
		double u = GetVectorDistance(ship.shipPos, pointTwo) * lineNormal;

		if (u > 0)
			return false;
		else if (u < 0)
			return true;
	}
	else if (pointTwo.y > pointOne.y) //downwards line
	{
		Vector3 lineNormal(lineSegment.y, -lineSegment.x, 0);
		double u = GetVectorDistance(shipWidthPosition, pointOne) * lineNormal;

		if (u > 0)
			return false;
		else if (u < 0)
			return true;
	}
}

And here is the collision check for the floor - differs slightly in ship testing coordinates, the sign of "u" and the normal of the line is different.


bool CheckCollisionsBottom(SpaceShip &ship, Vector3 pointOne, Vector3 pointTwo)
{
	Vector3 lineSegment = GetVectorDistance(pointOne, pointTwo);
	Vector3 shipHeightPosition(ship.shipPos.x, ship.shipPos.y + ship.GetHeight(), ship.shipPos.z);
	Vector3 shipWidthHeightPosition(ship.shipPos.x + ship.GetWidth(), ship.shipPos.y + ship.GetHeight(), ship.shipPos.z);

	if (pointTwo.y < pointOne.y) //upwards line
	{
		Vector3 lineNormal(-lineSegment.y, lineSegment.x, 0);
		double u = GetVectorDistance(shipWidthHeightPosition, pointTwo) * lineNormal;

		if (u > 0)
			return false;
		else if (u < 0)
			return true;
	}
	else if (pointTwo.y > pointOne.y) //downwards line
	{
		Vector3 lineNormal(-lineSegment.y, lineSegment.x, 0);
		double u = GetVectorDistance(shipHeightPosition, pointTwo) * lineNormal;

		if (u > 0)
			return false;
		else if (u < 0)
			return true;
	}
}

If you have needed linear collision, then I hope this has been some help to you.

This topic is closed to new replies.

Advertisement