Jump to content
  • Advertisement
Sign in to follow this  
JWColeman

Collision testing and response, for all active objects, in one function.

This topic is 3240 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I want my Update function in my Physics class to be pretty powerful, perhaps I'm asking too much, but I want it to loop through a box of objects that are currently in play (for instance, a pong ball and two paddles to start). I want it to perform collision checks between all relevant objects, keeping in mind ultimately I plan on having more than just a pong ball and two paddles. It seems overkill for pong, yes this I know, but I'm looking at the future. Here is what I have so far: It's a rough start, a lot of holes, and very incomplete.
void Physics::Update(std::vector<Renderable_Object*> & Game_Objects)
{		
	for (int i = 0; i++ i < Game_Objects.end())
	{
		for (int j = 0; j++; j < Game_Objects.end())
		{
			if (i == j){ j++; }
			if (Game_Objects->AABB)
			{
				if (Game_Objects[j]->AABB)
				{
					if(collision2d(Game_Objects->getMinimum(), Game_Objects->getMaximum(), 
								Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()))
					{
						reverse_x_velocity(Game_Objects->getVelocity());
					}
				}
			}
		}
	}
}
Here is my renderable object abstraction: Also pretty basic, probably not pretty, but functional at this point.
class Renderable_Object
{
public:

	Renderable_Object(float minX, float minY, float maxX, float maxY, float posX, float posY, bool visible, bool physical)
	{
		d_min.x = minX;
		d_min.y = minY;
		d_max.x = maxX;
		d_max.y = maxY;
		position.x = posX;
		position.y = posY;
		isVisible = visible;
		isPhysical = physical;
		velocity.x = 0;
		velocity.y = 0;
	}
	Vector2 & getVelocity()
	{
		return velocity;
	}
	void setVelocity(float x, float y)
	{
		velocity.x = x; velocity.y = y;
	}
	Vector2 & getLocation()
	{
		return position;
	}
	Vector2 & getMinimum()
	{
		return d_min;
	}
	Vector2 & getMaximum()
	{
		return d_max;
	}

private:
	Vector2 position;
	Vector2 velocity;
	Vector2 d_min;
	Vector2 d_max;
	bool isPhysical; // does this object use collision at all?
	bool isVisible; // render this object?
	bool AABB; //compatible with AABB collision detection
};
Does this look like a right step in the direction I'm trying to go? Any tips or hints?

Share this post


Link to post
Share on other sites
Advertisement
As I start to enter in all the variances and possibilities this function is getting more and more complex:


void Physics::Update(std::vector<Renderable_Object*> & Game_Objects)
{
for (int i = 0; i++ i < Game_Objects.end())
{
if (Game_Objects->isPhysical)
{
for (int j = 0; j++; j < Game_Objects.end())
{
if (i == j)
{
j++;
}
else if (Game_Objects->AABB)
{
if (Game_Objects[j]->isPhysical)
{
if (Game_Objects[j]->AABB)
{
if(collision2d(Game_Objects->getMinimum(), Game_Objects->getMaximum(),
Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()))
{
//do stuff
}
}
}
else
{
j++;
}
}
}
}
else
{
i++;
}
}
}


Is this a fruitless attempt?

Share this post


Link to post
Share on other sites
Hmmm, I think this is the most I can write before field testing this thing.

I would love if anyone with half an idea of what I'm trying to do could point out any obvious logical errors that I'm missing!

void Physics::Update(std::vector<Renderable_Object*> & Game_Objects)
{
for (int i = 0; i++ i < Game_Objects.end())
{
if (Game_Objects->isPhysical)
{
for (int j = 0; j++; j < Game_Objects.end())
{
if (i == j)
{
j++;
}
else if (Game_Objects->AABB)
{
if (Game_Objects[j]->isPhysical)
{
if (Game_Objects[j]->AABB)
{
if(collision2d(Game_Objects->getMinimum(), Game_Objects->getMaximum(),
Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()))
{
//do stuff
}
else
{
j++;
}
}
else
{
if(planeIntersection2d(Game_Objects[j], Game_Objects->getLocation()))
{
//do other stuff
}
else
{
j++;
}
}
}
else
{
j++;
}
}
}
}
else
{
i++;
}
}
}

Share this post


Link to post
Share on other sites
tbh that looks a bit of a mess for a collision loop.

How about this?


void Physics::Update(std::vector<Renderable_Object*> & Game_Objects)
{
for (int i = 0; i < Game_Objects.size(); i++)
{
if (!Game_Objects->AABB) continue;
if (!Game_Objects->isPhysical) continue;

for (int j = i+1; j < Game_Objects.size(); j++)
{
if (!Game_Objects[j]->AABB) continue;
if (!Game_Objects[j]->isPhysical) continue;

if(collision2d( Game_Objects->getMinimum(), Game_Objects->getMaximum(),
Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()))
{
//do stuff
}
else if(planeIntersection2d(Game_Objects[j], Game_Objects->getLocation()))
{
//do other stuff
}
}
}
}


Share this post


Link to post
Share on other sites
I would say that at first, make a specific collision for your specific problem.
You have plenty of time to make general solutions.
And as the number of objects grow, and so as your experience, you surely will come up with better methods.

For example you will have to implement optimizations (for example quad trees).

and for the code:
Why don't you use fewer if statement with more conditions?
if( i != j && Game_Objects->AABB && Game_Objects[j]->AABB &&
collision2d(Game_Objects->getMinimum(), Game_Objects->getMaximum(),
Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()) )
{
...
}

Share this post


Link to post
Share on other sites
Quote:
Original post by oliii
tbh that looks a bit of a mess for a collision loop.

How about this?

*** Source Snippet Removed ***


I like what you've done, but what about when i == 2, and I want to check it against j 0, and 1?

You start the j loop off by making it i+1, this leaves out anything before i if i = anything but 0, or am I wrong?

Share this post


Link to post
Share on other sites
Quote:
Original post by JWColeman
Quote:
Original post by oliii
tbh that looks a bit of a mess for a collision loop.

How about this?

*** Source Snippet Removed ***


I like what you've done, but what about when i == 2, and I want to check it against j 0, and 1?

You start the j loop off by making it i+1, this leaves out anything before i if i = anything but 0, or am I wrong?
Because you already checked 0-2, so if you would check 2-0, that would be double check, so it would be wrong/nothing happen/objects explode/program crash.

Share this post


Link to post
Share on other sites
Oh, I know why I did that, because of my planeIntersection2d function.

It's funny and only wants to accept a plane as it's first argument, and the second argument can be any physical object with a position, probably an AABB object.

I can probably circumvent this somehow though.

Currently the only object that uses collision of any kind that isn't AABB is a plane, but I can test an AABB object against a plane.

Here's the code for that function:

bool Physics::planeIntersection2d(Plane & boundingPlane, Vector2 & objectPosition)
{
Ray line_between_objects(objectPosition,boundingPlane.position);
double DotProduct=line_between_objects.direction.dot(boundingPlane.normal);
double l2;

//determine if ray parallel to plane
if ((DotProduct<0)&&(DotProduct>-0))
return false;

l2=(boundingPlane.normal.dot(boundingPlane.position-objectPosition))/DotProduct;

if (l2<-0)
return false;

return true;
}





I suppose a plane is a renderable object, considering I will be drawing the borders of my pong game as planes?

The trick is making sure that the plane, whichever index it may fall under in Game_Objects, gets passed as the first argument to the function.

Share this post


Link to post
Share on other sites
something like this?


void Physics::Update(std::vector<Renderable_Object*> & Game_Objects)
{
for (int i = 0; i < Game_Objects.size(); i++)
{
if (!Game_Objects->isPhysical) continue;

for (int j = i+1; j < Game_Objects.size(); j++)
{
if (!Game_Objects[j]->isPhysical) continue;

if( Game_Objects->AABB &&
Game_Objects[j]->AABB &&
collision2d( Game_Objects->getMinimum(), Game_Objects->getMaximum(),
Game_Objects[j]->getMinimum(), Game_Objects[j]->getMaximum()))
{
//do stuff
}

else if(Game_Objects->Plane &&
Game_Objects[j]->AABB &&
planeIntersection2d(Game_Objects, Game_Objects[j]->getLocation())
{
// do stuff
}
else if(Game_Objects[j]->Plane &&
Game_Objects->AABB &&
planeIntersection2d(Game_Objects[j], Game_Objects->getLocation())
{
//do other stuff
}
}
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!