Java Brickbreaker paddle collision detection - java

I am trying to make a brickbreaker game and I have run into some issues when it comes to collision detection. If you have ever played brick breaker you know that on the paddle, if the ball is moving to the left and you hit the left side of the top, then it continues moving right. Although, if you hit it on the right side in this case, then the ball changes directions. And also if you hit it on the sides of the paddle, it bounces off on the Y axis. Since I have no idea how to do the top part of the paddle, I can't show you the code because I don't have any :) This is the code that I am using for the sides:
Rectangle rect1 = new Rectangle((int) paddleDir, 570, imsLoader.getImage("paddle1").getWidth(), imsLoader.getImage("paddle1").getHeight());
Rectangle rect2 = new Rectangle((int) ballX, (int) ballY, imsLoader.getImage("ball").getWidth(), imsLoader.getImage("ball").getHeight());
if (rect1.intersects(rect2))
{
if (rect1.x == rect2.getMaxX() || rect1.getMaxX() == rect2.x)
{
ballVX = -ballVX;
clipsLoader.play("pattleHit", false);
}
else
{
ballVY = -ballVY;
ballY += 0.05;
clipsLoader.play("pattleHit", false);
}
}
What happens is that the ball when gets hit on the side, just goes right through the paddle going all over the place and when it reaches the other end either goes up or down!

You have to make the ball bounce, right?
Let's look at an example. Think the top square as the ball (I can't draw that nice). When the ball collides from left, it should move right and if it's from right, then go left.
You can achieve this with a simple thing. Don't change the horizontal velocity but instead reverse the vertical one.
if (ball.getBounds().intersects(paddle.getBounds()))
{
ball.setVy(-ball.getVy());
}
Easy right!
Now let's figure out how to do bounce effect on bricks.
This is a scenario when ball hits the brick. The red area is the intersection. Now notice it carefully.
If the intersection width is greater than the intersection height, the ball has hit in the bottom or vertical sides of the brick.
If the intersection height is greater that the intersection width, then it is a horizontal collision.
So we have to first calculate the intersection rectangle. It's so easy with java.
Rectangle intersection = ball.getBounds().intersection(brick.getBounds());
Now let's implement the bouncing.
if (intersection.width >= intersection.height)
{
ball.setVy(-ball.getVy());
}
if (intersection.height >= intersection.width)
{
ball.setVx(-ball.getVx());
}
That's it and you should have it fully functional.

Related

Collision detection in game of pong corner cases causing issues

I have made a game of pong and everything about it is working so far. I did the collisions against the paddles to the ball and it can correctly bounce them away unless it hits the corners.
This is a video of what happens when the ball hits the corner of one of the paddles.
https://drive.google.com/file/d/1nyRzsp5tn5Qvst7kVjtlr_rDNH98avbA/view?usp=sharing
Essentially what you can see happen in the video is the ball hits the the paddle on the left at the corner and it doesn't bounce back it just traverses the paddle downwards and then keeps going and they get a point. Here is my code for the collision testing
public void collision() {
this.width = (float) getBounds().width;
this.height = (float) getBounds().height;
for (int i = 0; i < handler.objects.size(); i++) {
if (handler.objects.get(i).getId() == ID.ball) {
GameObject current = handler.objects.get(i);
if (getBounds().intersects(current.getBounds())) {
current.setVx(current.getVx() * -1);
}
}
}
}
getBounds is an overridden method that just returns a rectangle for both the ball(which is a circle) and the paddle
I am happy to provide more of my code if necessary.
Any help on this would be great, thanks!
You are swapping the velocity direction each time you are hitting the paddle, even when you are still touching the paddle in the next frame. The solution is to swap the velocity direction only when the ball is heading towards the paddle, not when (already) going away. The pseudo code can look like this:
if (GeometryUtil.isDirectionGoingDown(direction)) {
if (GeometryUtil.isBallHittingHorizontalLine(
newPosition,
Ball.RADIUS,
paddleTopLeft,
paddleTopRight)) {
direction = calculateNewDirectionAfterHittingPaddle(
direction,
paddlePosition,
newPosition);
ball.setDirection(direction);
}
}
Here the GeometryUtil.isDirectionGoingDown() method is checking if the ball is actually going down. That way the new direction is only set when this condition returned true. When the direction has been swapped in one frame, the next frame will not swap the direction again because GeometryUtil.isDirectionGoingDown() will return false then.

Order of Collision in 2D Game Development

I've been stuck on a bug regarding collision in my 2D Mario-like game.
public void collision() {
if (Rect.intersects(Robot.rect2, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY - 32);
robot.setJumped(false);
} else if (Rect.intersects(Robot.rect, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY + 32);
}
updateRect();
if (Rect.intersects(Robot.rect3, r)){
robot.setCenterX(tileX + 32);
robot.setSpeedX(0);
} else if (Rect.intersects(Robot.rect4, r)){
robot.setCenterX(tileX - 32);
robot.setSpeedX(0);
}
}
Collision in my game is checked by comparing rectangles. My robot's rectangles: rect (bottom collision, so rectangle on bottom half of my robot sprite), rect2 (top collision), rect3 (left collision), and rect4 (right collision).
Every tile in my game is bounded by an instanced Rectangle r. When my robot's rectangle and the tile's rectangle intersect, I call collision(), which sets the position of my robots direction.
Here is my problem: If my robot is at a corner, where it is in bottom collision and right collision, and I move to the right, my robot moves INTO the right tile, and that triggers the bottom collision, and screws everything up.
Switching the postiions of the Bottom/Top & Right/Left collision doesn't help since then the same problem occurs, where the robot falls into the ground, triggering the Right/Left collision.
Essentially, I need a way to run all four at the same time.
Thanks
Yku are trying to build it one check at a time. Why not something like
if(!Rect.intersects(robot.rect1) && !Rect.intersects(robot.rect2) && !Rect.intersects(robot.rect3) && !Rect.intersects(robot.rect4)
{
//act normally
} else {
//collieion
}
What youre doing now is checking one side and base your result on that.
yes I also had a trouble with that, what you are missing is to call updateRect(); again after you made the collision detection on the X axis.
And I recommendto check the X axis first.
here is a nice Article about tile based Collision:
http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/

Java Pong - assign various reflection points to different parts of a paddle

I'm making pong in Java and wanted to make the game more fun by assigning different reflection logic to each part of the paddle, like so:
(ball hittins outter edges of paddle will have a different effect than it hitting the middle of the paddle)
The paddle extends Rectangle2D so I could use Rectangle2D's intersects() method to determine if the ball has touched any part of it...
Is it possible to determine where exactly the ball has hit on the paddle?
What I'm planning to do is,
calculate angle of incidence and reflective angle based on that...
If the ball hits at a point x on the paddle... I will change the reflection angle accordingly
Thanks
Is it possible to determine where exactly the ball has hit on the paddle?
If it were me, I would grab the current co-ordinates of both the ball and the paddle. For the paddle, you can get two sets of y co-ordinates, to describe the line facing the ball. Ie:
int paddleY1 = paddle.y;
int paddleY2 = paddle.y + paddle.width;
// assuming the paddle can only go up and down, y is the only co-ordinate that matters.
Then, you can compute the mid point of the paddle as:
int paddleYMid = (paddleY1 + paddleY2) / 2;
You can find out if the ball hit the left or right side of the paddle by comparing the y co-ordinates. Ie:
if(ball.y > paddleYMid)
{
// Right side of the paddle.
}
else
{
// Left side of the paddle.
}
Then it's up to you to develop further refinement.
Since the paddle is always vertical (parallel to Y axis), the point of collision of the ball and the paddle will happen at the same y-coordinate as the center of the ball. That is:
if (ball.centerX - ball.radius <= paddle.rightX && ball.velocityX < 0)
{
// collision point, if any, is at (ball.centerX - ball.radius, ball.centerY)
if (ball.centerY >= paddle.bottomY && ball.centerY <= paddle.topY)
{
// handle collision
}
}
As for the handling of the collision itself, you may not have to deal with angle of reflection, etc, but work solely with the raw values of x and y velocity. For example, to simulate a perfectly elastic collision, simply do:
ball.velocityX = -ball.velocityX;
And to account for ball reflecting at a higher or lower angle, you can scale the y velocity based on the position of the collision from the center of the paddle, eg.
ball.velocityY += SCALE_CONSTANT * (ball.centerY - ((paddle.topY + paddle.bottomY) / 2));
To find the exact spot where the ball hits the paddle, you can formulate the problem as a line intersection problem.
The paddle can be represented as a vertical line at the x-coordinate (+thickness if needed, and corrected for the balls diameter) of the paddle. The ball can then be represented as a line along its movement vector (this line could be simply defined by its current position and its next position if it were to move unimpended).
The problem can now be solved using a line intersection algorythm.
Since the paddle is a vertical line, the equations can be simplified to just answer the question at which Y will the ball pass the paddle's X. Thats also a common problem encountered and solved by line clipping: http://en.wikipedia.org/wiki/Line_clipping (the intersection points can also be computed directly, but I can't find the formula atm).

Circle and Rectangle Collision Android

I have a ball bouncing on my screen and there is a static rectangle that it can collide with and should bounce off of. I have already figured out how to test if the ball has collided with the rectangle and that works great. Now I need to determine which side of the rectangle that the ball has hit. I am currently trying this code (which works for testing the four sides but seems to have problems with the corners)...
if(Math.abs(ball.centerY-boundingBox.top) < ball.radius) {
// Hit the top
}
else if(Math.abs(ball.centerY-boundingBox.bottom) < ball.radius) {
// Hit the bottom
}
else if(Math.abs(ball.centerX-boundingBox.left) < ball.radius) {
// Hit the left
}
else if(Math.abs(ball.centerX-boundingBox.right) < ball.radius) {
// Hit the right
}
... Does anyone have any ideas how I can improve this? Or come up with a better solution for that matter?
I just basically need to determine which side a circle has hit on a rectangle after they collide. And I have already figured out how to test whether they collide or not.
Thanks!
It presumably doesn't work for corners because when the ball hits a corner, it hits two sides simultaneously. And if you're looking to make it bounce accurately, the relevant normal vector is that from the centre of the ball to the corner, which is going to be some diagonal between horizontal and vertical.
Assuming you always detect overlap while the centre of the ball is outside the rectangle, what you probably want to do is something like:
// is the ball above the box?
if(Math.abs(ball.ballCenterY-boundingBox.top) < ball.radius)
{
if(ball.ballCentreX >= boundingBox.left)
{
if(ball.ballCentreY <= boundingBox.right)
{
// ball hit the top edge
}
else
{
// ball hit the top right corner
}
}
else
{
// hit top left corner
}
}
A better test — to handle both inside and outside collisions — would be to find distance to the closest point on each side, pick the smallest distance, then if closest point is a corner then its a corner collision, otherwise it's a side collision.

2d rotation around a point using Canvas and Path

The issue involves an Android Path shape. It's a triangle that I'm using as an arrow to point towards objects on a screen Canvas. This is for a 2d game. player in the middle of the screen, objects around him and offscreen.
These arrows are supposed to rotate around the center of the screen, with a radius so that they rotate in a circle around the player. The arrows point towards objects that the player needs to move towards.
What I have right now is somewhat working, but the arrows are zipping around the circle at ridiculous speeds. Funny enough, they're pointing in the right direction, but they aren't staying at the right point on the circle. (if arrow is pointing northeast, arrow should be on the northeast part of the circle, etc)
I'm sure it's because of the math. I'm probably using atan2 wrong. Or canvas.translate wrong. Or maybe I shouldn't be using atan2 at all. Help! :)
Here is the code:
// set the shape of our radar blips
oBlipPath.moveTo(0, -5);
oBlipPath.lineTo(5, 0);
oBlipPath.lineTo(0, 5);
// Paint all the enemies and radar blips!
for(int i=0; i<iNumEnemies; i++){
if (oEnemies[i].draw(canvas, (int)worldX, (int)worldY)){
//calculate the degree the object is from the center of the screen.
//(user is the player. this could be done easier using iWidth and iHeight probably)
//we use a world coordinate system. worldY and worldX are subtracted
fDegrees = (float)Math.toDegrees(Math.atan2((oEnemies[i].getEnemyCenterY()-worldY)-user.getShipCenterY(), (oEnemies[i].getEnemyCenterX()-worldX)-user.getShipCenterX()));
canvas.save();
//get to the center
canvas.translate((iWidth / 2) , (iHeight / 2) );
//move a little bit depending on direction (trying to make arrows appear around a circle)
canvas.translate((float)(20 * Math.cos(fDegrees)), (float)(20* Math.sin(fDegrees)));
//rotate canvas so arrows will rotate and point in the right direction
canvas.rotate(fDegrees);
//draw arrows
canvas.drawPath(oBlipPath, oBlipPaint);
canvas.restore();
}
}
Affine transformations are are not commutative. They are typically applied in an apparent last-specified-first-applied order. As an alternative, consider the rotate() variation that rotates about a point.
Well, I've got it doing what I wanted, but I don't really know how. I threw in some random numbers until things showed up on the screen the way I wanted. If anyone wants to clue me in as to a better way to do this, I'm all ears.
The code:
// set the shape of our radar blips
oBlipPath.moveTo(0, -5);
oBlipPath.lineTo(6, 0);
oBlipPath.lineTo(0, 5);
oBlipMatrix.setRotate(45, 0, 0);
oBlipPath.transform(oBlipMatrix);
// Paint all the enemies and radar blips!
for(int i=0; i<iNumEnemies; i++){
oEnemies[i].draw(canvas, (int)worldX, (int)worldY);
if (oEnemies[i].bActive){
//calculate the degree the object is from the center of the screen.
//(user is the player. this could be done easier using iWidth and iHeight probably)
//we use a world coordinate system. worldY and worldX are subtracted
fDegrees = (float)Math.toDegrees(Math.atan2((oEnemies[i].getEnemyCenterY()-worldY)-(iHeight / 2), (oEnemies[i].getEnemyCenterX()-worldX)-(iWidth / 2)));
canvas.save();
//get to the center
canvas.translate((iWidth / 2 + 50) , (iHeight / 2 + 50) );
//move a little bit depending on direction (trying to make arrows appear around a circle)
//canvas.translate((float)(20 * Math.cos(fDegrees)), (float)(20* Math.sin(fDegrees)));
//rotate canvas so arrows will rotate and point in the right direction
canvas.rotate(fDegrees-45, -50, -50);
//draw arrows
canvas.drawPath(oBlipPath, oBlipPaint);
canvas.restore();
}
}
For whatever reason, I have to subtract 45 degrees from the canvas rotation, but add 45 degrees to the matrix rotation of the path shape. It works, but why?! :)

Categories