Collision isn't working quite right...

Hey guys! I know, second issue came up so fast :3

Welp, my collision detection isn’t working so well. I’m not sure how to explain so I made a GIF but I will also try and explain:

https://gyazo.com/d0da8d79490612ca7187fb9ebab1aff1.png

Okay, so basically, what this GIF is showing, is that when I am on the upper block at the beginning, I am able to move to the left just fine, along with colliding with the tile to the right. However, when I move down to the lower block, right collision seems to work but then the player basically gets stuck and cannot move left. This also happens when I’m simply walking along a flat piece of ground as demonstrated here:

https://gyazo.com/94ed52304f0dabdb4fdcb43e6b1040d3.png

The screen jittering to the left is supposed to show I’m pressing the “A” key to move left.

Here’s the code I use to get the boundaries of the player as well as checking against Tile bounds:

Update method within the Level class.

public void update(Entity player, Rectangle cameraView) {
		for (int x = 0; x < cameraView.getWidth(); x++) {
			for (int y = 0; y < cameraView.getHeight(); y++) {
				if (cameraView.contains(x * 32, y * 32)) {
					if (Tiles[x][y].getTileID() != "elements:air") {
						
						if (player.getBoundsBottom().intersects(Tiles[x][y].getBounds())) {
							player.isFalling = false;
							player.isJumping = false;
							player.position.y = (float)(Tiles[x][y].getY() - 32);
						} else {
							player.isFalling = true;
						}
						
						if (player.getBoundsTop().intersects(Tiles[x][y].getBounds())) {
							player.position.y = (float)(Tiles[x][y].getY() + 32);
							player.position.YVel = 0;
						}
						
						// TODO: Fix.
						if (player.getBoundsRight().intersects(Tiles[x][y].getBounds())) {
							System.out.println("Colliding right.");
							player.position.x = (float)(Tiles[x][y].getX() - 32);
						}
						
						if (player.getBoundsLeft().intersects(Tiles[x][y].getBounds())) {
							System.out.println("Colliding left.");
							player.position.x = (float)(Tiles[x][y].getX() + 32);
						}
					}
				}
			}
		}
	}

All of the “getBounds()” methods for the player.

@Override
	public Rectangle getBoundsBottom() {
		return new Rectangle((int)position.x+(this.PlayerWidth / 2) - ((this.PlayerWidth / 2) / 2), 
				(int)position.y + (this.PlayerHeight / 2), 
				this.PlayerWidth / 2, 
				this.PlayerHeight / 2);
	}
	
	@Override
	public Rectangle getBoundsTop() {
		return new Rectangle((int)position.x+(this.PlayerWidth / 2) - ((this.PlayerWidth / 2) / 2), 
				(int)position.y, 
				this.PlayerWidth / 2, 
				this.PlayerHeight / 2);
	}
	
	@Override
	public Rectangle getBoundsRight() {
		return new Rectangle((int)position.x + this.PlayerWidth - 5, 
				(int)position.y + 5, 
				5, 
				this.PlayerHeight - 10);
	}
	
	@Override
	public Rectangle getBoundsLeft() {
		return new Rectangle((int)position.x, 
				(int)position.y + 5, 
				5, 
				this.PlayerHeight - 10);
	}

My theory is, that somehow the player is intersecting with the block to the left/below him so it gets buggy but I’m not sure. Any help?

Not sure but make sure tile.getBounds() is from bottom left and not top left.

All I’m doing for Tiles.getBounds()

new Rectangle((int)x, (int)y, 32, 32);

how are the tiles rendered?

/* Our render method. */
	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		
		g2d.translate(camera.getX(), camera.getY());
		this.player.render(g);
		for (int x = 0; x < cameraView.getWidth(); x++) {
			for (int y = 0; y < cameraView.getHeight(); y++) {
				if (cameraView.contains(x * 32, y * 32)) {
					try {
						level.Tiles[x][y].render(g);
					} catch (Exception e) { /* Throws an exception after reaching the outer bounds.*/ }
				}
			}
		}
		g2d.translate(-camera.getX(), -camera.getY());
	}

try y-32

None of the images are there now, but there are tiles, they just can’t be seen.

@Xolitude
I think your issue is the lines of code where you do this:

player.position.x = (float)(Tiles[x][y].getX() + 32);

Perhaps you could adjust the position by the number of overlapping pixels?

What do you mean, exactly?

I threw together a quick sketch to illustrate some of my thoughts.

In sketch A, the player is overlapping the right wall, but rather than moving back 32 pixels, it would make more sense to move back however many pixels they overlap (i.e. [icode]playerCenterX + (playerWidth / 2) - tileLeftX[/icode]

More pertinent to your issue:
I think this is what is happening: you have a two block gap. The player hits the right so you move him left a block. But then he hits the left block and moves right. The way your code is written this would happen in one frame and hence the character is stuck. So you should only move him the number of overlapping pixels and it should only be a collision if there is an overlap.

Hm, I seemed to have fixed it. @CopyableCougar4, your method didn’t quite work unless I implemented it wrong.

Anyways, the problem with getting stuck was actually within the left boundary check. The size of the rectangle was (and I’m guessing here) glitching in with the tile below the player, so I just slightly changed the size and I now have correct right/left collision checks. Thanks for all your help, everyone :slight_smile:

You are doing it wrong if you are updating the position before doing collision checks. That’s the sole reason this is happening.

Check first, if it is colliding with something on either side, figure out which side, and disallow the movement in that direction before updating the position. Use a separate variable to store the new position first. Or set it back where it was before hand.


candidatePosition = currentPosition + deltaXy;
if (noCollisions(candidatePosition, vicinity) {
   currentPosition = currentPosition + deltaXy;
}