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\$

closed as off-topic by Anko, Josh Dec 10 '14 at 17:39

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Anko, Josh
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\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.

\$\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.