Jump to content

  • Log In with Google      Sign In   
  • Create Account


Basic 2D square collision


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 Lee Walker   Members   -  Reputation: 107

Like
0Likes
Like

Posted 17 April 2012 - 05:03 PM

I've developed my game to a point where I'm now starting to notice that my current approach to box collisions is wrong.

The code is as follows:

//if the block's origin is within 32px of the actor
if(collision[r][c]->GetPosition().x >= (a.x + av.x) - 32 &&
collision[r][c]->GetPosition().x <= (a.x + av.x) + 32 &&
collision[r][c]->GetPosition().y >= (a.y + av.y) - 32 &&
collision[r][c]->GetPosition().y <= (a.y + av.y) + 32)
{

MyRect b = collision[r][c]->GetPosition();

//Actor collision left
if(a.left() + av.x < b.right() &&
  a.right() > b.left() &&
  (a.top() < b.bottom() &&
  a.bottom() > b.top()) &&
  av.x < 0)
{
  MyRect newVel = av;
  newVel.x = 0;
  act->SetVelocity(&newVel);
  MyRect newPos = a;
  newPos.x = (b.x + b.w);
  act->Move(&newPos);
}
//Actor collision right
if(a.right() + av.x > b.left() &&
  a.left() < b.right() &&
  (a.top() < b.bottom() &&
  a.bottom() > b.top()) &&
  av.x > 0)
{
  MyRect newVel = av;
  newVel.x = av.x - av.x;
  act->SetVelocity(&newVel);
  MyRect newPos = a;
  newPos.x = (b.x - a.w);
  act->Move(&newPos);
}
//Actor collision Top
if(a.top() + av.y < b.bottom() &&
  a.bottom() > b.top() &&
  a.left() < b.right() &&
  a.right() > b.left() &&
  av.y < 0)
{
  act->jumping = false;
  MyRect newVel = av;
  newVel.y = 1;//-(av.y < 0 ? av.y/2 : -1);
  act->SetVelocity(&newVel);
  MyRect newPos = a;
  newPos.y = (b.y + b.h);
  act->Move(&newPos);	
}
//Actor collision Bottom
if(a.bottom() + av.y > b.top() &&
  a.top() + av.y < b.bottom() &&
  a.left() < b.right() &&
  a.right() > b.left() &&
  av.y > 0)
{
  MyRect newVel = av;
  newVel.y = 0;
  act->SetVelocity(&newVel);
  MyRect newPos = a;
  newPos.y = (b.y - a.h);
  act->Move(&newPos);
  groundCollided = true;
  act->jumping = false;
}
}


if(!groundCollided)
{
	 act->isOnGround = false;
}
else {
	 act->isOnGround = true;
}

Where a = the actor's current rectangle
Where av = the actor's velocity
Where b = the collision tile's rectangle

What happens currently is that the actors warp inside walls when moving into corners, which causes them to accelerate very fast until the character is out of the wall. Which often leads to the character is off the screen and then killed.

I've tried several different things but I'm not entirely sure how to fix it, any help would be greatly appreciated!

A video of the problem can be found here
Follow me on twitter! @lwalkeruk
Watch me on youtube! LeeWalkerGM

Sponsor:

#2 jefferytitan   Crossbones+   -  Reputation: 2003

Like
0Likes
Like

Posted 18 April 2012 - 10:37 PM

Don't have time to read the code, but my bet is that if your objects somehow do intersect (e.g. object A is travelling very fast, in one frame goes from being wholly outside object B to wholly inside object B) then the collision code ejects it in the wrong direction. The direction of movement needs to be taken into account, and ideally the area swept by the object during movement rather than a moment in time position.

#3 Lee Walker   Members   -  Reputation: 107

Like
0Likes
Like

Posted 20 April 2012 - 09:35 AM

Thanks! As it's my first real attempt at collision, would you be able to point me in the direction of any code to get me started off? Even Pseudo code would be fine.
Follow me on twitter! @lwalkeruk
Watch me on youtube! LeeWalkerGM

#4 jefferytitan   Crossbones+   -  Reputation: 2003

Like
0Likes
Like

Posted 22 April 2012 - 06:36 PM

Once again, not an expert. Off the top of my head, to fix the fast moving object problem (assuming your boxes are always axis-aligned) I might try the following:

1. Consider X and Y axes separately.
2. Find what period of time during the timestep there is an overlap of X coordinates, e.g. based on X positions, widths and X component of velocity.
3. Do the same for Y coordinates.
4. If there is an overlap in these time periods for X and Y, then there is a collision, e.g. their X coordinates and Y coordinates overlap at the same time.
5. The earliest common moment of these time periods is the collision time, from which you can determine the collision location.

If I'm right steps 2 and 3 can be done with simple algebra, so results will be exact and relatively fast.

If that doesn't help, here are a few links I found that address similar problems:
http://www.metanetsoftware.com/technique/tutorialA.html (may be much more complex than you need)
http://devmaster.net/forums/topic/8653-2d-collision-detection/ (talks about similar issues but with circles)
http://www.gamedev.net/topic/500831-2d-collision-detection-and-response---support-for-fast-moving-objects/ (talks about same problem but without a 100% solution)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS