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)
(https://i.imgur.com/I44fmPc.mp4)
here is a preview of how the bounds look
and here is a preview of what it actually looks like in game
(click for better quality)
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);
}
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With