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

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

Related

Shooting object directly at click java libgdx

I am trying to get my player to shoot a spell and it travels to where ever the player clicked. I can easily accomplish this by doing the following.
if(position.x >= destination.x - 1 && position.x <= destination.x + 1)
reachedX = true;
if(position.y >= destination.y - 1 && position.y <= destination.y + 1)
reachedY = true;
However if the players origin is at, for example, 0,0 and I click at 10,300 then it travels right and up but when the spell reaches an x of 10 it travels directly upwards. I want the spell to travel at an angle that it will reach the x coordinate at the same time as the y coordinate. Here is an image showing what happens and what I want to happen.
In the first picture it looks like the spell goes 45° until it reaches the right x-coordinate. This sounds like the x and y speed are equals, no matter where the destination point is.
You shuld instead have a direction and depending on that a x and y speed.
For that you first need to get the point, the player is clicking.
Therefore you can implement InputProcessor and it's touchDown(int screenX, int screenY, int pointer, int button).
The screenX and screenY arguments are given in screen coordinates (pixels) and therefore need to be converted to your world-coordinates. This can be done using the camera or the viewport and it's unproject(Vector2 screenCoords). This method returns a Vector2 giving the world-coordinates.
Now you need to find out the direction Vector2 between you and the clicked point. The direction Vector is calculated like this:
new Vector2(otherPos.x - myPos.x, otherPos.y - myPos.y).nor();
This returns the normalized direction Vector between the two points.
Now you only need to move the spell by dir.x*spellSpeed*delta in x-direction and dir.y*spellSpeed*delta in y-direction and it should look like in your second picture.

Shooting object based on arm rotation in libgdx java

I am trying to shoot an object(a spell) depending on the rotation of the players arm. The spell is supposed to come out of the hand and shoot towards where the mouse cicked(the arm rotates and points to where the mouse is). This is how the arm rotates in game.
public boolean mouseMoved(int screenX, int screenY) {
tmp.x = screenX;
tmp.y = screenY;
tmp.z = 0;
cam.unproject(tmp);
rot = MathUtils.radiansToDegrees * MathUtils.atan2((float)tmp.y - (float)player.getArmSprite().getY() - player.getArmSprite().getHeight(),
tmp.x -player.getArmSprite().getX() - player.getArmSprite().getWidth());
if (rot < 0) rot += 360;
//Last right or left means if hes looking left or right
if(player.lastRight)
player.setObjectRotation(rot + 80);
if(player.lastLeft)
player.setObjectRotation(-rot - 80);
And this is how the spell is supposed to shoot based off rotation
//destination is a vector of where on screen the mouse was clicked
if(position.y < destination.y){
position.y += vel.y * Gdx.graphics.getDeltaTime();
}
if(position.x < destination.x){
position.x += vel.x * Gdx.graphics.getDeltaTime();
}
However this is very wonky and never really reacts the way it supposed to with a few exceptions. It fires from the hand and then if the y axis is equal it completely evens out and goes till it reaches the x position, I want it to fire from the hand to the position clicks perfectly straight from point a to point b, this is clearly a rotation problem that I just can't seem to figure out how to tackle.
Here is an image of what is happening
Example image
The red indicates where I clicked, as you can see it reached the x pos first and now is traveling to the y when it should have reached the x and y pos of where I clicked first
Any help with this problem is extremely appreciated!
I'm pretty bad at radians and tangents but luckily we have vectors.
Since you have the rot ation in degrees of the arm. I advice to use Vectors to use for any Vector related math now.
//A vector pointing up
Vector2 direction = new Vector2(0, 1);
//Let's rotate that by the rotation of the arm
direction.rotate(rot);
Now direction is the direction the arm is pointing. If your rotation is calculated where up = 0. So you might need to rotate it 180, 90 or -90 degrees. Or in the case you did something silly any degrees.
Your spell should have a Vector too for it's position. Set that to the hand or wherever you want to start from. Now all you need to do is scale that direction since it's currently has a length of 1. If you want to move 5 units each frame you can do direction.scl(5) now it is of length 5. But technically speaking it's no direction anymore now everybody calls it velocity so let's do.
//when you need to fire
float speed = 5;
Vector2 velocity = direction.cpy().scl(speed);
//update
position.add(velocity);
draw(fireballImage, position.x, position.y);
I copied direction first, otherwise it would also be scaled. Then I just added the velocity to the position and draw using that Vector.
And to show Vectors are awesome you should see this awesome badlogic vs mouse program I created. https://github.com/madmenyo/FollowMouse there are just a view lines of my own code. It just takes a little bit of vector knowledge and it's very readable.

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 Brickbreaker paddle collision detection

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.

Need help moving an object away from the mouse at the correct rates

I am new to programming, and I am trying to make a 2d applet that will move a circle or ball away from the mouse. The way I want the physics in this program to work is to make the object act like a ball, and the mouse like a movable hill. When the mouse get closer to the ball, it repels the ball faster and farther away, and when the mouse gets farther away from the ball, the ball slows down and eventually stops moving. I need to take into account both the total distance between the mouse and the object, and the x and y distance so the movement of the object is smooth and more realistic. The biggest problem that I have is that even as the distance between the two points become greater, the rate at which the ball moves away stays relatively constant. Currently the rate is the distance of x or y multiplied by a constant, and divided by the total distance. This more or less works when the mouse moves closer to the object, and the rate increases as it should, but it fails when the mouse moves away. I want the rate to decrease and eventually become 0 when the mouse moves away, but in my current set up the x distance will also increase as the distance increases, and the rate will not decrease as much as I want it to, if at all. The way I have it now probably needs to be scraped all together, and thanks for the help.
public void mouseMoved (MouseEvent e)
{
//distance between x coord
xd=e.getX()-x;
//distance between y coord
yd=y-e.getY();
//total distance between mouse and ball
d=Math.sqrt((Math.pow(xd,2))+(Math.pow(yd,2)));
//rate of x change
xrate=(Math.sqrt(Math.pow(xd,2))*4)/(d);
//rate of y change
yrate=(Math.sqrt(Math.pow(yd,2))*4)/(d);
//determines movement of ball based on position of the mouse relative to the ball
if(xd>0)
{
x=x-((int)(xrate));
}
if(xd<0)
{
x=x+((int)(xrate));
}
if(yd>0)
{
y=y+((int)(yrate));
}
if(yd<0)
{
y=y-((int)(yrate));
}
//updates x and y coords of ball
repaint();
}
try this-
//rate of x change
xrate=(1.0/(d))*20; //20 is just a random constant I guessed
//rate of y change
yrate=(1.0/(d))*20;
You just did wrong math.
//total distance between mouse and ball
d=Math.sqrt((Math.pow(xd,2))+(Math.pow(yd,2)));
//rate of x change
xrate=(Math.sqrt(Math.pow(xd,2))*4)/(d);
Think about this :
If you only move on the x cord, will simply make yd equals 0 and d=|xd|
So xrate = |xd|*4/(d) = d*4/d = 4.
There is a easy way to accomplish your task, just make xrate and yrate related with xd and yd.
You can try this :
if(xd==0){
xd = 0.1;//minimum distance
}
if(yd==0){
yd = 0.1;
}
xrate = (1/xd)*10; // you can change number 100 for proper speed
yrate = (1/yd)*10;
x = x - xrate;
y = y - yrate;
Hope this can help.

Categories