2d collision problems

Started by
5 comments, last by escudo825 18 years, 2 months ago
I'm doing some simple 2d collision detection and everything worked fine, I think. but when I threw in some very simple physics some collisions didn't work. for some reason about half the time on top or bottom collisions the sprite passes through another. but the left/right collisions work fine. does anyone know what could be wrong wrong?

for (i = 0; i < NUM_SPRITES; i++)
	{
		if (i != sprite)
		{	
			//top collisions
			RECT1.top = g_Sprite[sprite].fPosY;
			RECT1.left = g_Sprite[sprite].fPosX;
			RECT1.bottom = g_Sprite[sprite].fPosY + SPRITE_DIAMETER;
			RECT1.right = g_Sprite[sprite].fPosX + SPRITE_DIAMETER;

			RECT2.top = g_Sprite.fPosY + g_Sprite.fVelX;
			RECT2.left = g_Sprite.fPosX;
			RECT2.bottom = g_Sprite.fPosY - SPRITE_DIAMETER + g_Sprite.fVelX;
			RECT2.right = g_Sprite.fPosX + SPRITE_DIAMETER;

			collision = IntersectRects(RECT1, RECT2);

			if (collision == true)
			{
				hold = (-g_Sprite.fVelY + g_Sprite[sprite].fVelY)/2;
				g_Sprite.fVelY = hold;
				g_Sprite[sprite].fVelY = -hold;
			}	
		}
	}

	for (i = 0; i < NUM_SPRITES; i++)
	{
		if (i != sprite)
		{	
			//bottom collisions
			RECT1.top = g_Sprite[sprite].fPosY;
			RECT1.left = g_Sprite[sprite].fPosX;
			RECT1.bottom = g_Sprite[sprite].fPosY + SPRITE_DIAMETER;
			RECT1.right = g_Sprite[sprite].fPosX + SPRITE_DIAMETER;

			RECT2.top = g_Sprite.fPosY + g_Sprite.fVelX;
			RECT2.left = g_Sprite.fPosX;
			RECT2.bottom = g_Sprite.fPosY + SPRITE_DIAMETER + g_Sprite.fVelX;
			RECT2.right = g_Sprite.fPosX + SPRITE_DIAMETER;

			collision = IntersectRects(RECT1, RECT2);

			if (collision ==  true)
			{
				 hold = (g_Sprite.fVelY + -g_Sprite[sprite].fVelY)/2;
				 g_Sprite.fVelY = -hold;
				 g_Sprite[sprite].fVelY = hold;
			}	
		}
	}

	for (i = 0; i < NUM_SPRITES; i++)
	{
		if (i != sprite)
		{	
			//left collisions
			RECT1.top = g_Sprite[sprite].fPosY;
			RECT1.left = g_Sprite[sprite].fPosX;
			RECT1.bottom = g_Sprite[sprite].fPosY + SPRITE_DIAMETER;
			RECT1.right = g_Sprite[sprite].fPosX + SPRITE_DIAMETER;

			RECT2.top = g_Sprite.fPosY;
			RECT2.left = g_Sprite.fPosX + g_Sprite.fVelX;
			RECT2.bottom = g_Sprite.fPosY + SPRITE_DIAMETER;
			RECT2.right = g_Sprite.fPosX + SPRITE_DIAMETER + g_Sprite.fVelX;

			collision = IntersectRects(RECT1, RECT2);

			if (collision == true)
			{
				hold = (-g_Sprite.fVelX + g_Sprite[sprite].fVelX)/2;
				g_Sprite.fVelX = hold;
				g_Sprite[sprite].fVelX = -hold;				
			}	
		}
	}

	for (i = 0; i < NUM_SPRITES; i++)
	{
		if (i != sprite)
		{	
			//right collisions
			RECT1.top = g_Sprite[sprite].fPosY;
			RECT1.left = g_Sprite[sprite].fPosX;
			RECT1.bottom = g_Sprite[sprite].fPosY + SPRITE_DIAMETER;
			RECT1.right = g_Sprite[sprite].fPosX + SPRITE_DIAMETER;

			RECT2.top = g_Sprite.fPosY;
			RECT2.left = g_Sprite.fPosX + g_Sprite.fVelX;
			RECT2.bottom = g_Sprite.fPosY + SPRITE_DIAMETER;
			RECT2.right = g_Sprite.fPosX + SPRITE_DIAMETER + g_Sprite.fVelX;

			collision = IntersectRects(RECT1, RECT2);

			if (collision == true)
			{
				hold = (g_Sprite.fVelX + -g_Sprite[sprite].fVelX)/2;
				g_Sprite.fVelX = -hold;
				g_Sprite[sprite].fVelX = hold;
			}	
		}
	}

p.s. if you need to see anything else ask and I'll post it.
Advertisement
I would like to see your IntersectRects(RECT1, RECT2), method if you'd please.
that method seems to work fine. but here you go just in case:

bool IntersectRects(RECT rect1, RECT rect2){		if (rect1.right > rect2.left)	{		if (rect1.left < rect2.right)		{			if (rect1.top < rect2.bottom)			{				if (rect1.bottom > rect2.top)				{					return true;				}			}		}	}	return false;}
That's a one-way collision comparison - that is, you'd have to call IntersectRects(r1, r2) AND IntersectRects(r2, r1) to get a valid collision detection. You can write a rectangular collision detection function that goes both ways without too much trouble, though.
Jetblade: an open-source 2D platforming game in the style of Metroid and Castlevania, with procedurally-generated levels
No, that rectangle collision detection appears to be correct.

On the other hand:

RECT2.top = g_Sprite.fPosY + g_Sprite.fVelX;
RECT2.bottom = g_Sprite.fPosY - SPRITE_DIAMETER + g_Sprite.fVelX;

RECT2.top = g_Sprite.fPosY + g_Sprite.fVelX;
RECT2.bottom = g_Sprite.fPosY + SPRITE_DIAMETER + g_Sprite.fVelX;

Unless there's some sort of explanation for why x velocities are being added to y positions, I think this could be the problem.
that may be the problem, I thought I fixed that :(. well I'm not at a computer with a compiler right now so I can't do anything. but if it works then I'll say, if not I'll say anyway.
yep that fixed it.

moral of the story? never assume something fixed. :)

This topic is closed to new replies.

Advertisement