Slick 2D Collision Detection Issues

Hello JGO forum, I have done my best in searching this topic through Google but have found nothing but broken links to slickcokeandcode forums. I have been trying to create a top down Zelda-esque game for fun. I cannot seem to get collision among the player and walls to act as they should.

Right now the player moves across the walls but gets stuck sliding across them and I know its because of how I have set up the walls in the arrays. But I honestly don’t know how else to write it, I have posted my code for the player update method in hopes someone can help me out to smooth the collision.

Thanks!


    public void update(Room room)
    {
        pbound.setBounds(x, y, playerimg.getWidth(),playerimg.getHeight());
        
        for(Wall wall : room.wallList)
        {
            if(pbound.intersects(wall.bound))
            {
                if(pbound.getMaxX() == wall.bound.getX())
                {
                    if(key.isKeyDown(Input.KEY_LEFT))
                        dx = -1;
                    else
                        dx = 0;

                    if(key.isKeyDown(Input.KEY_DOWN))
                        dy = 1;
                    if(key.isKeyDown(Input.KEY_UP))
                        dy = -1;
                    break;
                }
                else if(pbound.getX() == wall.bound.getMaxX())
                {
                    if(key.isKeyDown(Input.KEY_RIGHT))
                        dx = 1;
                    else
                        dx = 0;

                    if(key.isKeyDown(Input.KEY_DOWN))
                        dy = 1;
                    if(key.isKeyDown(Input.KEY_UP))
                        dy = -1;
                    break;
                }
                else if(pbound.getY() == wall.bound.getMaxY())
                {
                    if(key.isKeyDown(Input.KEY_DOWN))
                        dy = 1;
                    else
                        dy = 0;

                    if(key.isKeyDown(Input.KEY_LEFT))
                        dx = -1;
                    if(key.isKeyDown(Input.KEY_RIGHT))
                        dx = 1;
                    break;
                }
                else if(pbound.getMaxY() == wall.bound.getY())
                {
                    if(key.isKeyDown(Input.KEY_UP))
                        dy = -1;
                    else
                        dy = 0;

                    if(key.isKeyDown(Input.KEY_LEFT))
                        dx = -1;
                    if(key.isKeyDown(Input.KEY_RIGHT))
                        dx = 1;
                    break;
                }
                break;
            }

            if(!pbound.intersects(wall.bound))
            {
                if(key.isKeyDown(Input.KEY_RIGHT) && key.isKeyDown(Input.KEY_LEFT))
                    dx = 0;
                else if(key.isKeyDown(Input.KEY_LEFT))
                    dx = -1;
                else if(key.isKeyDown(Input.KEY_RIGHT))
                    dx = 1;
                else
                    dx = 0;

                if(key.isKeyDown(Input.KEY_UP) && key.isKeyDown(Input.KEY_DOWN))
                    dy = 0;
                else if(key.isKeyDown(Input.KEY_DOWN))
                    dy = 1;
                else if(key.isKeyDown(Input.KEY_UP))
                    dy = -1;
                else
                    dy = 0;
            }
        }
        x += dx;
        y += dy;
    }

Just briefly looking through you’re not handling what should happen correctly.

The general logic:
(From the object)

  • I want to move by an amount in a direction
  • If I did this would I be colliding?
  • Yes, then move back to were I was
  • Nope, OK then move to new position

You can interpolate between the two positions to work out closest point to be but for the type of movement you’re talking about this isn’t necessary.

So basically it should never actually come in contact with the wall object?

I’m just having a hard time processing how to do that without grid based movement.

Yeh, You just don’t want to actually move the object, as such you want to see if it can first then actually move it.

If you first just think about it in one dimension. So a object travelling side ways.

Lets say its moving at 1 block per turn… or 1 pixel per update.

And we have lava at the sixth pixel.

So, we begin with the object at pixel zero (If you’re not aware most programming starts with zero) and then we get an input from the user for it to move to the right, until it hits a wall for instance.
Ok, then what we’ll do is create an imaginary object, or like a test dummy and move him one pixel, it doesn’t matter if he falls into the lava and dies. So we tell him to go check that next pixel out for us, he reaches it and then shouts back saying that he is alive. Now we know it is ok, we can then move that pixel. The same thing happens with the next pixel another dummy is sent to check it first and then when we know it is safe we move. However when we reach the 5th pixel we then send out the dummy and we hear a scream as this dummy falls into the lava. Now we know that we shouldn’t do that and so we stop.

That probably sounds really stupid but I hope it helps you understand the concept.

(Extra)

You can then progress this idea into more dimensions, but keep them separate so check if dummy is ok going up and another sideways, if both say ok then you can move to that new position.

If you want to move more than one block/pixel at a time, also to keep the analogy going, you could teach your dummy to shout-out what tile it is on as it moves along and so the last tile that you hear is the safe one you can move to.

Man I really hope this helps because otherwise it sounds so weird.