Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Collision detection (glitch)

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);

}
like image 763
Feelsbadman Avatar asked Apr 19 '18 06:04

Feelsbadman


1 Answers

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);
    }
}
like image 184
Tschallacka Avatar answered Oct 05 '22 12:10

Tschallacka