Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Collision Detection again..

This thread is locked; no one can reply to it. rss feed Print
Collision Detection again..
Gnamra
Member #12,503
January 2011
avatar

Hello, I'm using the function I got off the wiki for bounding boxes but I'm not able to handle the collision like I want to.

Right now I've got one box that can move and jump, but the problem is I can't make it so it just drops down or stops if I hit the sides or under the box and let's me walk on top of the box. I've tried so many times now, but everytime I fix one bug, another one pops up and ruins it.

I have tried to do setPosX(getPosX - getVelX) then set the velX to 0 for the sides, and setPosY(getPosY - getVelX) and set velY to 0 if under the box, and for the top of the box I do the same thing but disable gravity so the player isn't pushed into the box.

This is what I'm using to figure out which side the player hit the box.

#SelectExpand
1 if ((b1_x > b2_x + b2_w - 1)) side = 1; // player right Right off 2 if ((b1_y > b2_y + b2_h - 1)) side = 2; // player at bottom off 3 if ((b2_x > b1_x + b1_w - 1)) side = 3; // player left off 4 if ((b2_y > b1_y + b1_h - 1)) side = 4; // player on top

I'd really appreciate some help with this, basically I'm just trying to make a platform the player can stand on.

David Sopala
Member #5,056
September 2004

Although it isn't perfect this code will work it does have abug still :/... Maybe you can find the mistake in it I just tossed it together to test collisions.

It uses allegro 4.2

You can convert to 4.4 if you like.

Gnamra
Member #12,503
January 2011
avatar

I know it works, but every time I kept finding bugs I made the code more and more complicated to fix the bugs I found, so I decided to rewrite it again for the 4th or 5th time. This time with help of this awesome community ;)

Edit: Oh I thought you meant the code I posted before I edited the whole post, and I didn't notice the attached file.

Edit 2: Hmm, I gotta convert it to Allegro 5 and I haven't used allegro 4 before, but it helps me a little. Thanks :)

Perhaps I've overlooked something, but I can't find the code for

#SelectExpand
1 2int Get_Y_Correction(C_Rect *, C_Rect *); 3int Get_X_Correction(C_Rect *, C_Rect *);

in the Collision_Handler.cpp file, these two interest me the most cause I'll only be using rectangles in my program.

Also, I have no idea what this is

#SelectExpand
1 if(u < 0) 2 { 3 u &= 0x007F; //save amount needed 4 u = u << 16; //shift 16 bits into first 2 bytes 5 u += 0x8000; //sign preservation 6 }else 7 { 8 u &= 0x007F; //save amount needed 9 u = u << 16; //shift 16 bits into first 2 bytes 10 } 11 12 if(l < 0) 13 { 14 l &= 0x007F; //save amount needed 15 l += 0x80; //sign preservation 16 }else 17 { 18 l &= 0x007F; //save amount needed 19 } 20 return u + l;

What is that called?
I haven't yet learnt what that is, but I have seen it before.

David Sopala
Member #5,056
September 2004

and operators and bit shifting?

I did the correction factors by taking the overlaps and going from there....
That was an abandoned project of mine, even if it did work mostly.

Ah I guess I never wrote those functions....

The thought process was 15 bits of data = 2^15 = 32768 more than enough to correct for a collision.

Then have a sign as well to go with it.

Rect/Rect would be something like

#SelectExpand
1 2int Get_X_Correction(C_Rect *a, C_Rect *b) 3{ 4 if((a->Get_X() < b->Get_X() + b->Get_SX() && a->Get_X() > b->Get_X()) || (a->Get_X() + a->Get_SX() < b->Get_X() + b->Get_SX() && a->Get_X() + a->Get_SX() > b->Get_X()))//basicly if a starts somewhere in b OR if a ends somewhere in b 5 { 6 //We have overlap in the x dimension 7 //determine amount of overlap 8 if(a->Get_X() < b->Get_X() + b->Get_SX() && a->Get_X() > b->Get_X())) //if we are overlapping and needing to move to the RIGHT to get out of collision. 9 { 10 return (b->Get_X() + b->Get_SX()) - a->Get_X(); //b's right side minus a's left side gives the overlap 11 }else //we must need to move to the LEFT if not the right. 12 { 13 return b->Get_X() - (a->Get_X() + a->Get_SX()); //b's left side minus a's right side gives us the overlap(even the correct sign) 14 } 15 16 } 17 return 0; 18}

Change the Xs to Ys and you have the y correction function.

Stas B.
Member #9,615
March 2008

Think in 1D for a moment.
Suppose you have two intervals on an axis: (min1, max1) and (min2, max2). They are overlapping and you want to separate them. The first one is stationary, but you can move the second one along the axis either in the negative or the positive direction, until they stop overlapping. Take a piece of paper, draw the diagram and work out the formulas for how much to move in either direction to separate the intervals. Now, in a game, you'll want to move an object as little as possible while still pushing it out of the tile. You have two axes, giving you 4 directions you could move along. Calculate the minimal amount of motion along the X axis required to push the object out of the tile, then do the same for the Y axis, then just choose the one with the minimal amount of motion. Try to work it out on your own.

Gnamra
Member #12,503
January 2011
avatar

Stas B. said:

Think in 1D for a moment.
Suppose you have two intervals on an axis: (min1, max1) and (min2, max2). They are overlapping and you want to separate them. The first one is stationary, but you can move the second one along the axis either in the negative or the positive direction, until they stop overlapping. Take a piece of paper, draw the diagram and work out the formulas for how much to move in either direction to separate the intervals. Now, in a game, you'll want to move an object as little as possible while still pushing it out of the tile. You have two axes, giving you 4 directions you could move along. Calculate the minimal amount of motion along the X axis required to push the object out of the tile, then do the same for the Y axis, then just choose the one with the minimal amount of motion. Try to work it out on your own.

if abs(Bx2 - Px1) > abs(Bx1 - Px2) where x1 is always closest to 0, then go towards left else right, then use the same for y and check both x and y? Wouldn't that work?

It always gave me the correct result when I tried it on paper, and I tried it with different lengths, if the player somehow swallowed the box and some other stuff.

David Sopala said:

int Get_X_Correction(C_Rect *a, C_Rect *b) code

I'll definitely try this code.

Thanks for the help, both of you!

Go to: