0
\$\begingroup\$

I am working on a game in SDL2, in which the player needs to be able to slide along walls, but NOT go through them. I've read up on things like Quadtrees, and this stackoverflow question https://stackoverflow.com/questions/2656943/2d-platformer-collision-problems-with-both-axes, but I have no idea how to implement Quadtrees (I'm a relative beginner still to C++) and no idea on how to check how much overlap there is. I tried using SDL2's collision functions, but to no avail. Here are my collision functions

main.cpp

//At the top of the program, initialized as global 
//variables are the isCollidingYAxis/isCollidingXAxis variables,
//and those are set to false.
bool check_collision(SDL_Rect a, SDL_Rect b){
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;

    leftA = a.x;
    rightA = a.x + a.w;
    topA = a.y;
    bottomA = a.y + a.h;

    leftB = b.x;
    rightB = b.x + b.w;
    topB = b.y;
    bottomB = b.y + b.h;

    if(rightA <= leftB || leftA >= rightB){
        if(isCollidingYAxis){
            isCollidingYAxis = false;
            return false;
        } else {
            isCollidingXAxis = true;
            return false;
        }
    }

    if(bottomA <= topB || topA >= bottomB){
        if(isCollidingXAxis){
            isCollidingXAxis = false;
            return false;
        } else {
            isCollidingYAxis = true;
            return false;
        }
    }
    return true;
}

void reset_collision()
{
    isCollidingXAxis = false;
    isCollidingYAxis = false;
}

//further down, I call the above functions from my player class...
void Player::move_player(std::vector<SDL_Rect> objectsWeHit)
{
    playerPositionX += playerVelocityX;
    playerPositionY += playerVelocityY;
    pCollider.x = playerPositionX;
    pCollider.y = playerPositionY;

    for(int x = 0; x < vectorOfRectangles.size(); x++){
        if(check_collision(pCollider, objectsWeHit[x])){
            if(isCollidingXAxis){
                playerPositionX -= playerVelocityX;
                pCollider.x = playerPositionX;
                std::cout << "Collision detected on the X axis!" << std::endl;
                reset_collision();
            }
            if(isCollidingYAxis){
                playerPositionY -= playerVelocityY;
                pCollider.y = playerPositionY;
                std::cout << "Collision detected on the Y axis!" << std::endl;
                reset_collision();
            }
        }
    }
}

My collision detection functions are similar to lazy foo production's collision detection. The tutorial that I based my function off of can be found here: http://lazyfoo.net/tutorials/SDL/27_collision_detection/index.php. In case its not obvious, I am using a vector to store rectangles, and I'm positive that part is okay. The problem right now is that only the X axis collision detection works, and not the Y axis. Meaning I can go through the top/bottom of the rectangle and not the left/right. I can, however, slide along the left/right sides of the rectangle, which is the desired behaviour. The complete program can be found here: https://bpaste.net/show/1715097a16e1. I'm at a complete loss, so any help is appreciated!

\$\endgroup\$
  • \$\begingroup\$ Why don't you use already available physics engines, like box2d? \$\endgroup\$ – Ali1S232 Dec 6 '14 at 23:59
  • 1
    \$\begingroup\$ I like to learn how things work under the hood, which is the whole point of programming in my opinion. I could use box2d, but I wouldn't have learned as much as I would have otherwise. \$\endgroup\$ – JohnBobSmith Dec 7 '14 at 0:16
  • \$\begingroup\$ It's hard to tell from just a code dump what might be going wrong. Have you tried debugging your code? You could for example render what your physics engine is "thinking" every frame and step through them in slow-motion? \$\endgroup\$ – Anko Dec 7 '14 at 0:16
  • \$\begingroup\$ I tried using a standard debugger, but the GUI window never opens. I haven't figured out how to log the output of the debugger either, other than debug messages in the program itself. \$\endgroup\$ – JohnBobSmith Dec 7 '14 at 0:18
1
\$\begingroup\$

What you need to do to implement sliding:

1) find the exact location of collision

2) find the normal of the collision

3) move the object to the location of collision

4) set the velocity of object opposite of the collision normal to 0; (or you need projection if you are working with non axis aligned stuff)

5) move the object again using the new adjusted velocity using the remaining time left. You might need to run your collision and resolution algorithm again.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Well, let me try that. I will mark as solved if I can get it working, and wait for other answers in the mean time. \$\endgroup\$ – JohnBobSmith Dec 7 '14 at 4:51

Not the answer you're looking for? Browse other questions tagged or ask your own question.