Obstacle Collision Poo game

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
aa69sex
Posts: 2
Joined: January 20th, 2022, 7:20 pm

Obstacle Collision Poo game

Post by aa69sex » January 20th, 2022, 7:45 pm

Hi!
I have just completed tutorial 13 of the beginners tutorial series and I'm about to start the snake tutorial.
I am trying to modify the poo game by creating some box(obstacles to reduce the amount of movement space for the dude) with the drawrect function in its own(box) class (the collision function is in the dudeclass). but I am facing a issue with the collision. I am using a function similar to the ClamptoScreen() to decect the collision and restict the movement of the dude. And its not working as I thought. Its detecting the collision but the problem is with dudes position update. what method should I apply to slove the problem? would love to know the answers. Thanks in advance! :roll:
screen shots of the problem:
https://drive.google.com/file/d/1TKQl1r ... sp=sharing
https://drive.google.com/file/d/1t0RyAX ... sp=sharing
https://drive.google.com/file/d/1sIpDrs ... sp=sharing
https://drive.google.com/file/d/1R-g5WM ... sp=sharing
.
.
.
.
.
(type of code i am using to update dudes position)

Code: Select all

int Wallright = wall.GetX() + wall.GetWidth();
int Wallleft = wall.GetX();
int WallDown = wall.GetY() + wall.GetHeight();
int WallUp = wall.GetY();

const int left = x + width;
const int bottom = y + height;

if (left >= Wallleft && bottom >= WallUp && y <= WallDown && x <= Wallright)
{
	x = (Wallleft - 1) - width;
	y = WallDown + 1;
		
	y = (WallUp - 1) - height;
	x = Wallright + 1;
}

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Obstacle Collision Poo game

Post by albinopapa » January 20th, 2022, 9:22 pm

The easiest way is to detect which side of the box you are colliding with. After you find the side you collide with, you calculate the penetration depth. This gives you the direction and amount you need to reverse the dude so there are no more collisions.

To determine which side of the box you collided with, you need to decide which direction dude is coming from: right side if dude is moving left, top if dude is moving down, left if dude is moving right, bottom if dude moving up.

Once you determine the side of collision, take the difference in that side's position and the side of the dude that collided with the box.
If left side box collision: px = box_left - dude_right;
else If right side box collision: px = box_right - dude_left;
If top side box collision: py = box_top - dude_bottom;
else If bottom side box collision: py = box_bottom - dude_top ;

Then offset dude's position by the amount of penetration in each direction:
dudeX += px;
dudeY += py;

Haven't done this in a while, so it might take some work. One of chili's old Intermediate ( Pre-2016 ) covers box collision similar to what I just described. There is also the Separating Axis Theorem if you aren't afraid of a little extra math.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Obstacle Collision Poo game

Post by albinopapa » January 21st, 2022, 10:12 pm

Naïve approach:

Code: Select all

// Least penetration
int px = std::numeric_limits<int>::min();
int py = std::numeric_limits<int>::min();

int dude_left = x;
int dude_top = y;
int dude_right = x + GetWidth();
int dude_bottom = y + GetHeight();

int wall_left = wall.GetX();
int wall_top = wall.GetY();
int wall_right = wall_left + wall.GetWidth();
int wall_bottom = wall_top + wall.GetHeight();

// Check for dude_left overlap with wall_right
if( dude_left < wall_right && dude_right > wall_right ){
    // Possible collision along X axis on wall right and dude left
    px = wall_right - dude_left;
}
else if( dude_right > wall_left && dude_left < wall_right ){
    // Possible collision along X axis on wall left and dude right
    px = wall_left - dude_right;
}
if( dude_top < wall_bottom && dude_bottom > wall_top ){
    // Possible collision along Y axis on wall bottom and dude top
    py = wall_bottom - dude_top;
}
else if( dude_bottom > wall_top && dude_top < wall_bottom ){
    // Possible collision along Y axis on wall top and dude bottom
    py = wall_top - dude_bottom;
}

// The axis with the least penetration is probably the axis Dude came from
if( px < py ){
    x += px;
}
else if( px > py ){
    y += py;
}
else{
    // If px == py, Dude came diagonally and hit a corner
    x += px;
    y += py;
}
I think that should work for the naïve approach. There might be some "corner" cases where it doesn't, either way I haven't tested it.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Obstacle Collision Poo game

Post by albinopapa » January 21st, 2022, 10:37 pm

A couple of suggestions though.

Make a Rect struct with members left,top,right,bottom. Use this struct to act as a bounding box around your entities.
Add a function to Poo, Dude and your collideable objects like boxes that calculates and returns this bounding box.
Dude::GetRect()
Poo::GetRect()
Wall::GetRect()

Add a Point struct to keep track of positions. This makes it easier to return to variables from a function.
struct Point{ int x = 0; int y = 0; };

Add a utility function that takes in 2 Rect objects and returns a Point object.

Code: Select all

Point detect_collision( Rect const& lhs, Rect const& rhs ){
    Point penetration;

    // Check for lhs.left overlap with rhs.right
    if( lhs.left < rhs.right && lhs.right > rhs.left ){
        // Possible collision along X axis on rhs right and lhs left
        penetration.x = rhs.right - lhs.left;
    }
    else if( dude_right > wall_left && dude_left < wall_right ){
        // Possible collision along X axis on rhs left and lhs right
        penetration.x = rhs.left - lhs.right;
    }
    if( lhs.top < rhs.bottom && lhs.bottom > rhs.top ){
        // Possible collision along Y axis on rhs bottom and lhs top
        penetration.y = rhs.bottom - lhs.top;
    }
    else if( lhs.bottom > rhs.top && lhs.top < rhs.bottom ){
        // Possible collision along Y axis on rhs top and lhs bottom
        penetration.y = rhs.top - lhs.bottom;
    }

    // The axis with the least penetration is probably the axis Dude came from
    Point result = { 0, 0 };
    if( penetration.x < penetration.y ){
        result.x = penetration.x;
    }
    else if( penetration.x > penetration.y ){
        result.y = penetration.y;
    }
    else{
        // If penetration.x == penetration.y, Dude came diagonally and hit a corner
        result.x = penetration.x;
        result.y = penetration.y;
    }

    return result;
}

Point result = detect_collision( dude.GetRect(), wall.GetRect() );
dude.SetPosition( dude.GetX() + result.x, dude.GetY() + result.y );

for(int i = 0; i < NPOO; ++i ){
    result = detect_collision( poo[ i ].GetRect(), wall.GetRect() );
    poo[ i ].SetPosition( poo[i].GetX() + result.x, poo[i].GetY() + result.y );
}

With adding a Point struct, a Rect struct and a general utility function for checking and resolving collisions, it will keep you from duplicating your code.

I understand you're early on in the tutorials, so just keep this in mind as you progress.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

aa69sex
Posts: 2
Joined: January 20th, 2022, 7:20 pm

Re: Obstacle Collision Poo game

Post by aa69sex » January 22nd, 2022, 10:40 am

Hey @albinopapa! thanks a lot for your effort :) 🤗.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Obstacle Collision Poo game

Post by albinopapa » January 22nd, 2022, 12:39 pm

You're welcome, did it help any?
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply