1
\$\begingroup\$

So I'm having some problems with my collision detection with my platformer. Take the image below as an example.

enter image description here

When I'm running right I am unable to go through the platform, but when I hold my right key and jump, I end up going through the object as shown in the image, below is the code im using:

if(shapePlatform.intersects(player.getCollisionShape())){

     Vector2f vectorSide = new Vector2f(shapePlatform.getCenter()[0] - player.getCollisionShape().getCenter()[0], 
             shapePlatform.getCenter()[1] - player.getCollisionShape().getCenter()[1]);
            player.setVerticleSpeed(0f);

            player.setJumping(false);
            if(vectorSide.x > 0 && !(vectorSide.y > 0)){
                 player.getPosition().set(player.getPosition().x-3, player.getPosition().y);

            }else if(vectorSide.y > 0){
                player.getPosition().set(player.getPosition().x, player.getPosition().y);

            }else if(vectorSide.x < 0 && !(vectorSide.y > 0)){
                 player.getPosition().set(player.getPosition().x+3, player.getPosition().y);
            }

}

I'm basically getting the difference between the centre of the player and the centre of the colliding platform to determine which side the player is colliding with. When my player jumps and walks right on the platform he goes right through. The same can also be observed when I jump on the actual platform, should I be resetting the players y in this situation?

\$\endgroup\$
1
  • \$\begingroup\$ The way you are determining which side is the player on wont work if you have non-square tiles, by the way. \$\endgroup\$
    – jcora
    Jun 26, 2012 at 22:05

5 Answers 5

1
\$\begingroup\$

I haven't spent a ton of time looking at your code, but just on brief inspection I would say you need to do more than just

player.getPosition().set(player.getPosition().x-3, player.getPosition().y);

You're assuming the player only needs to move back 3 units, which is probably incorrect. How incorrect it is depends on how much they've moved in your latest update. If they moved 10 units and you move them back 3, they are still 7 units into the block. You need to continue moving them back until there is no longer a collision.

Perhaps something like

while(shapePlatform.intersects(player.getCollisionShape())
{
    player.getPosition().set(player.getPosition().x-3, player.getPosition().y);
}

Not super performant but once you get it working you can work on how fast it runs.

I also notice you're not doing any corrections for y. The up/down of your boxes/player is just as collidable as the right/left, so you should definitely factor that in. If your player is falling say 10 units per update, and they fall into the block 10 units, you'll stop them from falling but you never correct their y position to get them back on top of the block. Now they are stuck 10 units into the block with no way out. You should do the same type of correction - while there is a collision, walk them back until the collision is resolved.

\$\endgroup\$
1
\$\begingroup\$

You might want to do the following things when you detect a collision:

  1. Restore the previous position of your character. This means, you need to have a field in your Character class that stores the previous position. You update this value every time before the character's position changes.

  2. Apply some kind of effect to the character, so that it doesn't get "stuck" in that position. This could be a rebound effect (reverse the direction of the character's velocity, and perhaps multiply it by an arbitrary value). Or you could show a small animation (the character looks like he just run into a wall, some dust falls etc.).

\$\endgroup\$
1
\$\begingroup\$

Before reacting to the collisions, first position your player so that he will not be stuck again. This can be achieved as follows.

public void collision(GObject other){
    if (other instanceof wall){
        // check velocities
        if (dx>0){
            // collision occurred on the left
            this.x = other.x - this.width;
        } else if (dx<0){
            // collision occurred on the right
            this.x = other.x + other.width;
        }
        if (dy>0){
            // collision occurred on the bottom
            this.y = other.y - this.height;
        } else if (dy<0){
            // collision occurred on the top
            this.y = other.y + other.y;
        }
    }
}

Note that snap only the y-axis for the floors. If you know the difference between the floor and horizontal objects.

\$\endgroup\$
1
  • \$\begingroup\$ Sorry but this is only psuedocode, not slick. \$\endgroup\$ Jul 9, 2012 at 0:41
0
\$\begingroup\$

After going through the problem, it was clear that the standard intersect method provided by slick wouldn't do. Instead, I wrote a SAT collision detection method to detect collisions. But more importantly, the algorithm returned a correction vector to correctly place the player outside the colliding shape. This seems more natural than to adjust the players x/y buy some value.

Thanks to all other answers as they have all helped me in solving this issue.

\$\endgroup\$
-2
\$\begingroup\$

I wrote a lil engine called TwoTryEngine with Slick.The only thing i want to say about the engine is that my engine is checking the new positions before the player is moving to the new positions.This also solves a problem with moving on top problems, but my engine still has to get much more fixes.So i dont gonna upload it if you are interessted.like other guy before said use dx and this stuff.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .