0
\$\begingroup\$

I'm trying to implement collision detection between Player (the main character) and a Platform. They are both modelled as rectangles; when player hits the side of a platform he should bounce off it and when player hits the top of a platform he should glide (move) along it. The problem I'm facing is that sometimes the player bounces when he lands on top of the platform (near an edge) rather than glide along it.

For the collision detection, I'm using the Intersector class (LibGDX). If you are unfamiliar with this class, all it does is create the new rectangle that occurs when two rectangles intersect (i.e. the rectangle shaded green below).

enter image description here

Code:

for (int i = 0; i < list.size(); i++) {

    // An object from a list of objects that the player can collide with
    GameObject go1 = list.get(i);

    // True if the object is of type platform
    boolean playerPlatformCollision = (go1.getType() == ObjectType.PLATFORM);

    // If the two objects being compared are Player and Platform
    if (playerPlatformCollision) {
        Rectangle objectRect = go1.getRect();

        // If the Player and Platform overlap
        if (player.getRect().overlaps(objectRect)) {

            // The resulting rectangle from the overlap (as shaded green in the above pic)
            Rectangle intersection = new Rectangle();
            Intersector.intersectRectangles(player.getRect(), objectRect, intersection);

            // If the Player collides with bottom side of platform
            if (intersection.y > player.getRect().y) {
                player.setySpeed(-getySpeed()); // Make him bounce downwards 
            }

            // If the Player collides with left side of platform
            if (intersection.x > player.getRect().x) {
                player.bounce(); // Make him bounce
            }

            // If the player collides with the top side of platform
            if (intersection.y + intersection.height
                < player.getRect().y + player.getRect().height)
            {
                player.setGravity(false);
                player.onPlatform(true);
            }
            else {
                player.onPlatform(false);
            }
        }
    }
}

Is there any sort of trick I can use for this? Haven't been able to find anything online that works.

\$\endgroup\$
  • \$\begingroup\$ Why did you vandalize your own question? You should be able to delete your own question properly when you really want to, but usually you shouldn't because it might help future readers. \$\endgroup\$ – Philipp Mar 30 '15 at 7:49
  • \$\begingroup\$ I have to submit my project and was worried that my code might be found online by my marker and they'll mistake it for plagiarism. Didn't expect thread to get bumped back up, apologies \$\endgroup\$ – eyes enberg Mar 30 '15 at 8:16
  • \$\begingroup\$ @eyesenberg This site is not for your personal use. The questions here are to help future visitors as well as yourself. Please don't vandalize any more questions in the future. If you don't want your code to be online, don't post it online. \$\endgroup\$ – MichaelHouse Mar 30 '15 at 14:24
  • \$\begingroup\$ I'm by no means preventing other users from using the site. I just figured since it was my question and my answer I should have the right to remove it (I found the solution by myself, so it would be as if I never asked). In the future, prevent users from editing their question after x time if they don't want questions to be edited. I'll keep it up \$\endgroup\$ – eyes enberg Mar 30 '15 at 19:02
  • \$\begingroup\$ You could just delete it if you no longer want it up. \$\endgroup\$ – Sam Apr 29 '15 at 15:54
1
\$\begingroup\$

Yes, there is a trick you can use here. Based off of your glitch and your code sample, I'm assuming that you're moving both the player's X and Y position at the same time, then checking for collision.

Instead, move the player by its X velocity, then check for collision. If it has collided with any platform, then it must have hit the side of a platform. Take any action necessary for this collision, such as backing the player out of the platform and negating its X velocity.

After X velocity has been handled, you can now move the player by its Y velocity. If there is a collision, then it must have hit either the ceiling or the floor of a platform. Back the player out of the floor/ceiling, then set Y velocity to zero.

Hope this helps!

\$\endgroup\$
  • \$\begingroup\$ Thanks for the reply. The logic makes sense but I'm struggling to implement your suggestion. The collision detection code is in a separate class to Player. Player's update() method starts with moveBy(xSpeed, ySpeed). Taking your suggestion on board I split the method into moveXBy(float dx) and moveYBy(float dy) and moved it out of the update() method and into my collision detection method above (such that moveXBy() is called at the start of the method and moveYBy() is called at the end). Is this what you meant? \$\endgroup\$ – eyes enberg Feb 22 '15 at 20:35
  • \$\begingroup\$ Well it should be somewhat straightforward. Change the player's X position, update the bounding rectangle, check and handle collision. Then change the player's Y position, update the bounding rectangle, check and handle collision. That's basically what I was suggesting. \$\endgroup\$ – Superdoggy Feb 22 '15 at 20:42
  • \$\begingroup\$ Yeah I understood what you were saying and it made sense, my code is just too messy right now and my head isn't in the game so I struggled to implement it properly. Having said that, I found an easier way (see answer above). I still like your idea though, thanks :) \$\endgroup\$ – eyes enberg Feb 22 '15 at 21:29
0
\$\begingroup\$

Found an easy solution to the problem. I just compared the midpoint x-coordinate of the player to the x-coordinate of the intersection to see where the player was relative to the platform (i.e. left or right). If the x midpoint of the player's rectangle > x point of intersection rectangle, then he should be on top - otherwise, he's on the side of the platform. Changed the if statements for left side and top side to:

// left side of platform
if (intersection.x > player.getRect().x
    && player.rectangleMidPointX() < intersection.x) {
    // ...
}

// top side of platform
if (intersection.y + intersection.height < player.getRect().y + player.getRect().height
    && player.rectangleMidPointX() > intersection.x) {
    // ...
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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