[Collisions] Test before collision

I am having a little trouble here, I can easily fix it but the code is messy and horrible.

Basically I need to invert the X or Y velocity if I touch the edge of the screen, I can do this by doing:

			if (ball.getX() + ball.getWidth() > Engine.graphics.getBox2DCam().viewportWidth) {
				ball.velocity.set(-3, ball.velocity.y);
			}
			if (ball.getX() < 0) {
				ball.velocity.set(3, ball.velocity.y);
			}
			if (ball.getY() < 0) {
				ball.velocity.set(ball.velocity.x, 3);

			}
			if (ball.getY() + ball.getHeight() > Engine.graphics.getBox2DCam().viewportHeight) {
				ball.velocity.set(ball.velocity.x, -3);
			}

This however frustrates the crap out of me, I don’t want to manipulate the ball in the collision code, I simply want to check for collisions then report back to the entities that “hey, you just collided, do something”.

I want something like this, the problem being that because I am checking for collisions when they happen, the ball collides and remains colliding; resulting in a constantly flip of the velcocity:

				if (ball.getX() > Engine.graphics.getBox2DCam().viewportWidth
						|| ball.getX() < 0) {
					event = Event.BOUNDARY_VIOLATION;
					event.setProjection(CollisionProjection.X);
					notify(ball, event);
				}
				if (ball.getY() < 0
						|| ball.getY() > Engine.graphics.getBox2DCam().viewportHeight) {
					event = Event.BOUNDARY_VIOLATION;
					event.setProjection(CollisionProjection.Y);
					notify(ball, event);
				}

This basically checks what axis we are colliding on and sends an notification to the Ball itself to let it know it just hit something, then in the ball code:

@Override
	public void onNotify(Entity entity, Event event) {
		switch (event) {
		case BOUNDARY_VIOLATION:
			if(event.getProjection() == CollisionProjection.X){
				velocity.set(-velocity.x, velocity.y);				
			}else if(event.getProjection() == CollisionProjection.Y){
				velocity.set(velocity.x, -velocity.y);
			}
			break;
		default:
			break;
		}
	}

As you can see this is just going to constantly flip the velocity vector because I check for collision as they happen, is there a simple algorithm I can implement to check for collisions just before they happen? No idea what to google, came up results that mostly just check for collisions when they overlap.

That’s not why it’s not working (and for what it’s worth, there’s nothing wrong at all with handling the collision directly in the collision code - your way is just making things more complex for the sake of it I think).

All you’ve forgotten to do is move the ball again before checking for collisions once more. You’ll find that having reversed the ball’s X or Y direction its next move should take it back out of the collision area (the edge of the screen) and so it shouldn’t collide again.

Cas :slight_smile:

Yep, I am practising apply design patterns to code lol.

Damn, shoot me lol.

So I sort of re-done the code for this, after doing some reading on AABB and the proper way to do it.

I am using the MTD way, I am however having a bit of a problem adjusting the balls position after a collision, it seems to go full on crazy when it collides with something.

I know why this is, it is this line of code here:

ball.getPos().add(mtd);

However, when I remove this code the ball collides and stops on the object and slides along it, like said before its doing this because I have not adjusted the position due to the collision. Can anyone tell me what I am doing wrong?

Here is my collision check code:

if (ball.getBounds().overlaps(block.getBounds())) {
					Vector2 mtd = ball.getBounds().minimumTranslation(
							block.getBounds());
					ball.getPos().add(mtd);
					if (mtd.x != 0) {
						ball.velocity.x = -ball.velocity.x;
					} else if (mtd.y != 0) {
						ball.velocity.y = -ball.velocity.y;

					}
				}

Here is the minimumTranslation method, I followed a tutorial to create it and it original used Vectors for the min/max points but I changed that around and instead just done the vertices calculation in the variable deceleration, afaik it works out the same.

	public Vector2 minimumTranslation(BoundingBox other) {

		/* The collision vector */
		Vector2 mtd = new Vector2();

		/* The left side of the AABB */
		float left = this.getX() - (other.getX() + other.getWidth());
		/* The right side of the AABB */
		float right = (this.getX() + this.getWidth()) - other.getX();
		/* The top side of the AABB */
		float top = this.getY() - (other.getY() + other.getHeight());
		/* The bottom side of the AABB */
		float bottom = (this.getY() + this.getHeight()) - other.getY();


		 /* If any of the edges are zero, there was no collision */
		 if (left > 0 || right < 0 || top > 0 || bottom < 0)
		 return Vector2.Zero;

		/* If right is less than left, we collided left */
		if (Math.abs(left) < right) {
			mtd.x = left;
		} else {
			/* Else we collided right */
			mtd.x = right;
		}

		/* If top is less than bottom, we collided top */
		if (Math.abs(top) < bottom) {
			mtd.y = top;
		} else {
			/* Else we collided bottom */
			mtd.y = bottom;

		}

		/*
		 * See which component of our collision vector is smallest
		 */
		if (Math.abs(mtd.x) < Math.abs(mtd.y)) {
			mtd.y = 0;
		} else {
			mtd.x = 0;
		}

		/* Return our collision vector */
		return mtd;

	}

Don’t tell me exactly what is wrong if you can help it, give me a hint lol.