10
votes

I am working on a platformer game for the final year project in HS. However... The collision detection system I use is basically about checking wether a specific part of the character intersects with another block or not.

The collision seems to be working fine except that it causes some bugs such as player kind of getting stuck or slowing down when hitting from the sides or gets thrown up when both upper and < or > keys are used.

My question is; How can I improve the collision code in order to avoid such glitches and have sort of 'slippery' collisions?

This is the kind of collision effect that I am trying to achieve:
(https://i.imgur.com/KB1M3bt.mp4)
enter image description here

(https://i.imgur.com/I44fmPc.mp4) enter image description here

here is a preview of how the bounds look

enter image description here


and here is a preview of what it actually looks like in game (click for better quality) enter image description here
The code i use for collision detection: (tempObject are blocks that the player is intersecting with)

if(getBoundsTop().intersects(tempObject.getBoundsBottom())){
    y = tempObject.getY() + height;
    velY = 0;
    System.out.println("Top collision");
}

if(getBoundsBottom().intersects(tempObject.getBoundsTop())){
    y = tempObject.getY() - height;
    velY = 0;
    falling = false;
    jumping = false;
    //isOnBlock = true;
} else {
    falling = true;
    //isOnBlock = false;
}

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
}

and here are the bound methods:

public Rectangle getBounds() { return new Rectangle( (int)x, (int)y, (int)width, (int)height ); }

    public Rectangle getBoundsTop() {
        return new Rectangle(
                (int)x, 
                (int)y, 
                (int)(width-(width*0.01f)), 
                (int)(height/2)
        );
    }
    public Rectangle getBoundsBottom() {
        return new Rectangle(
                (int)x,
                (int)(y+(height/2)),
                (int)(width-(width*0.01f)),
                (int)(height/2)
        );
    }

    public Rectangle getBoundsLeft() {
        return new Rectangle(
                (int)x,
                (int)y, 
                (int)((int)width*0.15f), 
                (int)height
        );
    }

    public Rectangle getBoundsRight() {
        return new Rectangle(
                (int) 
                ((int)x+(width-(width*0.15f))), 
                (int)y, 
                (int) ((int)width*0.15f), 
                (int)height
        );
    }

Edit: Im using a constant acceleration speed for setting velocity

acc = 2.5f;
MAX_SPEED = 10;


if(Game.keyDownMap.containsKey(KeyEvent.VK_A)){

    setVelX(getVelX() - acc);
    if(getVelX() < -MAX_SPEED)
        setVelX(-MAX_SPEED);

} else if(Game.keyDownMap.containsKey(KeyEvent.VK_D)){

    setVelX(getVelX() + acc);
    if(getVelX() > MAX_SPEED)
        setVelX(MAX_SPEED);

}
1
very well asked! (+1) : you provided a well explained problem with both images/animations on site and a detailed and well formated code example. This should be used as a template for referencing when writing new questions, IMHO. - Rann Lifshitz
Well, you first want to define what do you want to happen when a collission with a wall is happening. Do you want to do wall jumping like mario/prince of persia? do you want a sharp drop? do you want a slide down the wall? what do you want to happen on a sideways collision? - Tschallacka
Looking at the animation, I see that the block keeps moving when its collided with an object. In these cases you probably want to stop it moving in a given direction once its collided, but not reset the position. Try and adjust where you check for a collision and where you change the characters position. Also if you want smoother movements, you can add acceleration instead of changing the velocity straight away. This will make the movements a bit smoother, but you will need to adjust it to suit your purposes. - Shadowzee
@Tschallacka I've updated the question now. :) - Feelsbadman
What do you use for velocity? can you post that part of the code? - Tschallacka

1 Answers

1
votes

When there's a sidewards collision, you want to set your sidewards velocity to zero. That way there can only be a vertical velocity, which I assume will be setVelY();

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
    setVelX(0);
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
    setVelX(0);
}

Also you need to check on key down if there's no collision status active. You'll probably want to make a method to set if it's currently intersecting with something which you update every gametick.

if(Game.keyDownMap.containsKey(KeyEvent.VK_A) && !isIntersectingLeft()){

    setVelX(getVelX() - acc);
    if(getVelX() < -MAX_SPEED)
        setVelX(-MAX_SPEED);

} else if(Game.keyDownMap.containsKey(KeyEvent.VK_D) && !isIntersectingRight()){

    setVelX(getVelX() + acc);
    if(getVelX() > MAX_SPEED)
        setVelX(MAX_SPEED);

}

if you want a little bounce you could set a little velocity in the different direction.

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
    if(this.getVelX() > 0) {
        setVelX(10);
    }
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
    if(this.getVelX() > 0) {
       setVelX(-10);
    }
}