• Advertisement
Sign in to follow this  

Collision Response

This topic is 2256 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

Hi, Again I am on collisions. Ok, so this is what I want to do:

If a collision occurs at the bottom of my player, I want to stop the Y increment.
If a collision occurs at either side of my player, I want to stop the X increment.

I have the code in place which will return a vector of the position at which a pixel collides. I have been trying for quite a while now to do this seemingly simple task. I have access to the point of collision, and both colliding objects' position and size.

I should point out, that the resulting vector for the collision point is based on a projected matrix which tests for pixel collision.

I have tried nearly every variation that comes to me.
Making sure the players Xbounds are outside the other objects, meaning a side collision had occured.
Making sure the players Xbounds were in the same range as the objects, and that its Yvalue was less(Top collision)


I tried numerous ways with the collision point. Tried to code it to find out if the point of collision was at the bottom/top/left/right of the player (this is what I want to achieve, it seems the best approach)

But everything I have done just seemed to fail, It would work on top,bottom and 1 side. It would work on both sides,bottom and not top etc.

Any help appreciated.

Share this post


Link to post
Share on other sites
Advertisement
You can store the previous position of the object you are testing for and in the result of a collision set the new position to the old one.

so something like this:

oldPosition = Position;

MovePlayer

if a collision occurs()
{
Position = oldPosition;
}

Share this post


Link to post
Share on other sites

You can store the previous position of the object you are testing for and in the result of a collision set the new position to the old one.

so something like this:

oldPosition = Position;

MovePlayer

if a collision occurs()
{
Position = oldPosition;
}




I don't see how that will work for me, Each update I implement gravity by increasing the yincrement over time. I need the Y to be set to 0 when a collision occurs, otherwise it will keep falling through the floor. But, I cant really just set y to 0 when I find a collision because then if the player collides with the side of a platform for example, he will stick to it.

This is currently my update method of a base CollidableObject class:

increment.y += gravity * acceleration * deltaTime

check collision using projected matrix(based on x and y increments)


if(no collision will occur)
move it


So what way will I structure it so I can use the oldPosition way to resolve collisions, so the gravity stops incrementing when I am on a platform?

Share this post


Link to post
Share on other sites
Break the oldPosition into x and y components, and go back to oldX if an X collision occurs, and go back to oldY if a Y collision occurs:



// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;
OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in X direction
if (CheckXCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}


// check for collision in Y direction
if (CheckYCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}


Something like that.

Share this post


Link to post
Share on other sites

Break the oldPosition into x and y components, and go back to oldX if an X collision occurs, and go back to oldY if a Y collision occurs:



// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;
OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in X direction
if (CheckXCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}


// check for collision in Y direction
if (CheckYCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}


Something like that.



Yes, Thats what I was attempting in the first place, But I cant seem to find a good way of determining if it was an X or Y collision. I tried determining it using the rectangle test before the pixel test etc. But it doesn't seem to work flawlessly. And I also was trying to think of a way to do it using the exact point of collision. I guess my main question is what is the best way of determining if its an X or Y collision

Share this post


Link to post
Share on other sites


// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;

// check for collision in X direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}

OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in Y direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}



Move the object in the X direction 1st, then check for collision.
Move the object in Y direction, then Check for collision.
Would that not work?

I obviously screwed up when I put my pseudo-code. I modified it above in the quoted section

Share this post


Link to post
Share on other sites



// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;

// check for collision in X direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}

OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in Y direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}



Move the object in the X direction 1st, then check for collision.
Move the object in Y direction, then Check for collision.
Would that not work?

I obviously screwed up when I put my pseudo-code. I modified it above in the quoted section





Don't really want to be doing 2 pixel tests per update though. And if I do that for a bounding box test it will not work for complex shapes.

Share this post


Link to post
Share on other sites

[quote name='BeerNutts' timestamp='1324583241' post='4896618']


// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;

// check for collision in X direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}

OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in Y direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}



Move the object in the X direction 1st, then check for collision.
Move the object in Y direction, then Check for collision.
Would that not work?

I obviously screwed up when I put my pseudo-code. I modified it above in the quoted section





Don't really want to be doing 2 pixel tests per update though. And if I do that for a bounding box test it will not work for complex shapes.
[/quote]

If you are doing any sort of spatial hashing, then a bounding-box test, then pixel-level collision, I SERIOUSLY doubt you'd see a performance hit.

If you're world (or level) isn't that large and/or you odn't have too many collideable objects, I bet you could even get by without spatial hashing.

Years ago (2001), I wrote a space-shooter, and it did a bounding box test, then a pixel-perfect test (using load-time bit-masks from the sprites), and i never saw any performance hits. And, I was doing a lot of other stuff. AND, this was over 10 years ago.

So, if you find a better method (which, using a 2d-physics library is a better method, see my sig for an example), go for it, otherwise, I'd bet you don't ave performance issues.

Share this post


Link to post
Share on other sites

[quote name='ravinDavin' timestamp='1324586322' post='4896634']
[quote name='BeerNutts' timestamp='1324583241' post='4896618']


// move our object
OldPosition = OurObjectPos;
OurObjectPos.X += Velocity.X * deltaTime;

// check for collision in X direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and stop X velocity
OurObjectPos.X = OldPosition.X;
Velocity.X = 0;
}

OurObjectPos.Y += Velocity.Y * deltaTime;

// check for collision in Y direction
if (CheckCollision(OurObjectPos) == true) {
// go back to old place, and Set Y velocity to Gravity
// This way, if jumping, and we hit our head, velocity will go back to gravity and we fall
// and it will handle us walking off end of platform
OurObjectPos.Y = OldPosition.Y;
Velocity.Y = Gravity;
}



Move the object in the X direction 1st, then check for collision.
Move the object in Y direction, then Check for collision.
Would that not work?

I obviously screwed up when I put my pseudo-code. I modified it above in the quoted section





Don't really want to be doing 2 pixel tests per update though. And if I do that for a bounding box test it will not work for complex shapes.
[/quote]

If you are doing any sort of spatial hashing, then a bounding-box test, then pixel-level collision, I SERIOUSLY doubt you'd see a performance hit.

If you're world (or level) isn't that large and/or you odn't have too many collideable objects, I bet you could even get by without spatial hashing.

Years ago (2001), I wrote a space-shooter, and it did a bounding box test, then a pixel-perfect test (using load-time bit-masks from the sprites), and i never saw any performance hits. And, I was doing a lot of other stuff. AND, this was over 10 years ago.

So, if you find a better method (which, using a 2d-physics library is a better method, see my sig for an example), go for it, otherwise, I'd bet you don't ave performance issues.
[/quote]



Ah thanks for the replies I'll have a go at it.

Share this post


Link to post
Share on other sites
To determine which side a collision occurred on, you need to calculate intercept times. Find the relative velocity of the 'leader' to the 'collider' and then determine when the leading edge of the leader overlaps with the front edge of the collider. If at that time, they overlap in the other dimension, then you have a collsion time. Repeat for the other dimension. Find the earliest collision - that will tell you which side they collided on. I only know how to do this for Axis Aligned Bounding Boxes though - wouldn't know how to do this pixel perfectly. The only way you can know which side collided first is if one relative velocity component is zero, or if you calculate intercept times. Simply finding overlap of a future position will never tell you which side collided first, only that they overlap.

Share this post


Link to post
Share on other sites

To determine which side a collision occurred on, you need to calculate intercept times. Find the relative velocity of the 'leader' to the 'collider' and then determine when the leading edge of the leader overlaps with the front edge of the collider. If at that time, they overlap in the other dimension, then you have a collsion time. Repeat for the other dimension. Find the earliest collision - that will tell you which side they collided on. I only know how to do this for Axis Aligned Bounding Boxes though - wouldn't know how to do this pixel perfectly. The only way you can know which side collided first is if one relative velocity component is zero, or if you calculate intercept times. Simply finding overlap of a future position will never tell you which side collided first, only that they overlap.


I think maybe pixel perfect could be achieved with a vector field.... And then you look for intersecting lines to determine where and when a collision happened. Kind of turns into a mess when you have an animated sprite.

Vector field:
Set up:
For every visible pixel in a sprite, pre process a 2D vector from the center of the object to that pixel's position
Same for other objects
Run time:
Do a bounding box test, then do a line-line intersection test using all the vectors from the leader sprite, and all the vectors in the collider sprite
When you get a positive line/line intersetion, use the 2D vectors and the resultant intersection point to find the depth of penetration, then negate this value from the leader's position to move them to the correct position where the leader is no longer intersecting.

Warning: I don't know if this will actually work, never tried pixel perfect collisions, ever, and when I have used a pixel look up to find collisions, I used a minimum number of points, say 2, one for the feet position one for the head.

EDIT:

Forgot to mention that when you generate your vectors, you only really need to generate the vectors that describe the pixels at the edges of the sprite, the boundary between visible and non-visible pixels. And you can sort your vectors into a quad tree in the sprite, so that when you look up your vectors for intersection, you use the penetration of the two bounding boxes to limit the intersection tests to just the vectors that are possibly intersecting, rather than testing the whole thing.

Share this post


Link to post
Share on other sites

[quote name='Edgar Reynaldo' timestamp='1324596029' post='4896675']
To determine which side a collision occurred on, you need to calculate intercept times. Find the relative velocity of the 'leader' to the 'collider' and then determine when the leading edge of the leader overlaps with the front edge of the collider. If at that time, they overlap in the other dimension, then you have a collsion time. Repeat for the other dimension. Find the earliest collision - that will tell you which side they collided on. I only know how to do this for Axis Aligned Bounding Boxes though - wouldn't know how to do this pixel perfectly. The only way you can know which side collided first is if one relative velocity component is zero, or if you calculate intercept times. Simply finding overlap of a future position will never tell you which side collided first, only that they overlap.


I think maybe pixel perfect could be achieved with a vector field.... And then you look for intersecting lines to determine where and when a collision happened. Kind of turns into a mess when you have an animated sprite.

Vector field:
Set up:
For every visible pixel in a sprite, pre process a 2D vector from the center of the object to that pixel's position
Same for other objects
Run time:
Do a bounding box test, then do a line-line intersection test using all the vectors from the leader sprite, and all the vectors in the collider sprite
When you get a positive line/line intersetion, use the 2D vectors and the resultant intersection point to find the depth of penetration, then negate this value from the leader's position to move them to the correct position where the leader is no longer intersecting.

Warning: I don't know if this will actually work, never tried pixel perfect collisions, ever, and when I have used a pixel look up to find collisions, I used a minimum number of points, say 2, one for the feet position one for the head.

EDIT:

Forgot to mention that when you generate your vectors, you only really need to generate the vectors that describe the pixels at the edges of the sprite, the boundary between visible and non-visible pixels. And you can sort your vectors into a quad tree in the sprite, so that when you look up your vectors for intersection, you use the penetration of the two bounding boxes to limit the intersection tests to just the vectors that are possibly intersecting, rather than testing the whole thing.
[/quote]

While I don't have any experience with the vector method you mentioned, from a conceptual perspective, I would think it would be more intensive than a pre-processed bit-mask to check intersections. If you need to know the "depth" of intersection, you'd just have to count the bit's overlapping on the specific axis that you are checking.

Share this post


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

  • Advertisement