Stopping when there's a collision

Member
Posts: 196
Joined: 2002.04
Post: #1
My code checks before and after a collision to test which side of the box has been hit. Is there a better way to find which side of the box has been hit? Sometimes my player goes right through the boxes.

Code:
- (int)checkCollisionBetweenPlayer:(Player *)thePlayer andRock:(Rect3f)rect2
{
    Rect3f rect1 = [thePlayer rectBox];
    int collision;
    Point3f before;
    
    before.x = [thePlayer beforeX];
    before.y = [thePlayer beforeY];
    
    collision = [self checkCollisionBetweenRect1:rect1 before:before andRect2:rect2];
    
    if (collision == COLLISION_TOP)
    {
        [thePlayer setY:(rect2.point.y - rect1.size.height)];
    }

    if (collision == COLLISION_RIGHT)
    {
        [thePlayer setX:(rect2.point.x - rect1.size.width)];
    }

    if (collision == COLLISION_LEFT)
    {
        [thePlayer setX:(rect2.point.x + rect2.size.width)];
    }

    if (collision == COLLISION_BOTTOM)
    {
        [thePlayer setY:(rect2.point.y + rect2.size.height)];
    }
    
    return collision;
}

- (int)checkCollisionBetweenRect1:(Rect3f)rect1 before:(Point3f)before andRect2:(Rect3f)rect2
{
    // Finding the middle point of the rectangle
    float point1X = rect1.point.x + (rect1.size.width / 2);
    float point1Y = rect1.point.y + (rect1.size.height / 2);
    float length1X = rect1.size.width / 2;
    float length1Y = rect1.size.height / 2;

    float point2X = rect2.point.x + (rect2.size.width / 2);
    float point2Y = rect2.point.y + (rect2.size.height / 2);
    float length2X = rect2.size.width / 2;
    float length2Y = rect2.size.height / 2;
    
    // find out if there is any collision
    if (fabs(point1X - point2X) <= (length1X + length2X)
        && fabs(point1Y - point2Y) <= (length1Y + length2Y))
    {
        // Check a collision between The top of the object and the bottom of the rock
        if ((before.y + rect1.size.height) <= rect2.point.y
            && (rect1.point.y + rect1.size.height) >= rect2.point.y)
        {
            return COLLISION_TOP;
        }

        // Check a collision between The right of the object and the left of the rock
        if ((before.x + rect1.size.width) <= rect2.point.x
            && (rect1.point.x + rect1.size.width) >= rect2.point.x)
        {
            return COLLISION_RIGHT;
        }

        // Check a collision between The left of the object and the right of the rock
        if (before.x >= (rect2.point.x + rect2.size.width)
            && rect1.point.x <= (rect2.point.x + rect2.size.width))
        {
            return COLLISION_LEFT;
        }

        // Check a collision between The bottom of the object and the top of the rock
        if (before.y >= (rect2.point.y + rect2.size.height)
            && rect1.point.y <= (rect2.point.y + rect2.size.height))
        {
            return COLLISION_BOTTOM;
        }
        
        return COLLISION;
    }
    
    return NO_COLLISION;    
}
Quote this message in a reply
Nibbie
Posts: 2
Joined: 2006.10
Post: #2
Iceman Wrote:My code checks before and after a collision to test which side of the box has been hit. Is there a better way to find which side of the box has been hit? Sometimes my player goes right through the boxes.

Code:
- (int)checkCollisionBetweenRect1:(Rect3f)rect1 before:(Point3f)before andRect2:(Rect3f)rect2
{
    // Finding the middle point of the rectangle
    float point1X = rect1.point.x + (rect1.size.width / 2);
    float point1Y = rect1.point.y + (rect1.size.height / 2);
    float length1X = rect1.size.width / 2;
    float length1Y = rect1.size.height / 2;

    float point2X = rect2.point.x + (rect2.size.width / 2);
    float point2Y = rect2.point.y + (rect2.size.height / 2);
    float length2X = rect2.size.width / 2;
    float length2Y = rect2.size.height / 2;
    
    // find out if there is any collision
    if (fabs(point1X - point2X) <= (length1X + length2X)
        && fabs(point1Y - point2Y) <= (length1Y + length2Y))

You should probably remove the first part of your code for checkCollisionBetweenRect1:before:andRect2 above. It checks if there is CURRENTLY a collision between the two rects and so completely negates your use of beforeX and beforeY, which otherwise would have allowed you to detect collisions that occurred between frames.

--phillip
Quote this message in a reply
Member
Posts: 196
Joined: 2002.04
Post: #3
Thanks I'll change my code. I also figured out a better way to find which side of the squares were colliding. The way I'm doing it now is I find which two sides are closest to each other.
Quote this message in a reply
Post Reply