i have a fixed rectangle. When ball hits a vertex of a triangle, i calculate tangent at point of contact(rectangle vertex). Then i rotate Velocity vector to coincide with the tangent, flip the y value of velocity and rotate it back. Here is my code for top-left corner:
double c1x=rec.x-ball.getX();
double c1y=rec.y-ball.getY();
if(c1*c1+c2*c2<ball.getRadius()*ball.getRadius())
{
double angle=Math.atan2(-c1x,c1y); //angle made by tangent
Vector2D v=ball.velocity.rotate(angle); //rotate velocity vector by 'angle'
if(v.y<0.0f) //ball is already moving away from corner
return;
v.setY(-v.y); //flip y
ball.velocity=v.rotate(-angle); //rotate back
return;
}
But this code doesnot works. When ball strikes the corner it gets stuck, moves along the top edge and then falls off, not bouncing back. Am i doing it correct?
Making some guesses about your conventions, I suggest this:
double angle=Math.atan2(-c1x,-c1y);
If that doesn't work, we can do some experiments to figure out what's actually going on.
EDIT:
All right, we must build up from simpler solutions. Try these experiments:
1) Set velocity to (0,1) and verify that the ball moves straight up after the collision.
2) Set velocity to (-1,1) and verify that the ball moves up and leftward.
If those work as expected, then pick a trajectory that you would expect to behave in a normal way, such as approaching from above and to the left, then rebounding almost straight up but slightly leftward, then run it through your code but print out all the values in the collision and tell us what they are. That's at least c1x, c1y, angle, and the values of velocity initially and after each rotation.You'll probably notice where things go screwy, and if you don't we will.
Related
I'm making a game using Box2D in libGDX. I have a "wall" object which is a static ChainShape body set around the screen, some "balls" which are dynamic CircleShape bodies and negative gravity. The balls should be very bouncy, so I set a big 1.1f restitution to them, but the wall shouldn't, and even if I set the wall's restitution to zero, balls bounce off it too high. I need something like setting negative restitution to the wall so the balls will bounce higher off each other and lower off the wall. Any ideas?
You could have 2 variables storing the direction of movement in both axis.
Example:
double xDirection,yDirection;
then in your update method you can add it to the current position of the object.
now if you want it to bounce off a surface you multiply it's value by -1.This will reverse the direction of the object.
For example, say a ball is moving at a speed of 2units in the x-axis.
When the ball hits the edge, xDirection will be multiplied by -1. Now xDirection is -2. Thus, the direction of the ball is reversed.
However, this will make the ball bounce back at the same speed. In order to fix this, you can multiply xDirection with 0.5.Now if we were to multiply the xDirection of the ball with 0.5, xDirection would be -1. Thus, the ball would move slower. Using the same concept you can make the ball move faster by multiplying by 1.5 instead of 0.5. And, you can do this with yDirection too.
I am writing a program that allows a user to left-click the panel and add a bouncing ball, and right-click to remove a ball. The balls bounce off of all walls with a constant velocity. I have all of this finished. The last part that I cannot figure out is handling the collisions with other bouncing balls. The same results as bouncing off of the walls should occur. Any help will be greatly appreciated. Here is the code for the movement of the ball so far...
#SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")
private void processMovement(long interval)
{
/* Compute the distance moved in the interval. Decompose the distance
moved into x and y components, and determine the next position of the Ball
by those amounts. */
float x = position.x + velocity.getDistanceX(interval);
float y = position.y + velocity.getDistanceY(interval);
position.setLocation(x, y);
/* Collisions with the walls. If so, adjust the speed and direction for
the next period. */
/* Collision with the east or west (vertical) wall. */
float wall;
if( x <= (wall = 0.0F) ||
x >= (wall = model.getDimension().width - SIZE) )
{
x = wall;
velocity.reverseX();
}
/* Collision with the north or south (horizontal) wall. */
if( y <= (wall = 0.0F) ||
y >= (wall = model.getDimension().height - SIZE) )
{
y = wall;
velocity.reverseY();
}
position.setLocation(x, y);
}
When I wrote a program like this, I ended up creating a wall object, which had a start x/y and an end x/y. Geometry was needed in order to determine the correct ricochet/bounce angle since walls could be at any orientation. Essentially the direction of the ball changes by two times the difference in orientation between the wall and the ball's direction. For example, if the ball is moving at 45* above the X-axis, and the wall is oriented at 90* above the X-axis (i.e. it's straight up and down), then the ball's new heading is its original heading plus two times the difference between its heading and the wall's direction, or in other words 45* + 2*(90*-45*), or in other words, 135*. The problem is that it doesn't work if you consider the wall's orientation to be -90* (i.e. 90* below the X-axis, which is still straight up and down). In that case you'd calculate the ball's new heading as -45* which is wrong. It also matters if you hit the wall from the left or from the right. Fun, right? Lots of things to think about.
Balls collide when their centers are within (R1 + R2) distance of each other, where R1 is the radius of the first ball, and R2 is the radius of the second ball.
Essentially, what I did was I created a temporary (invisible) wall that was perpendicular with the vector from the center of one ball to the center of the other, and then I ordered the two balls to bounce off of this wall. This gave the correct ricochet behavior.
I know you probably don't care about my "wall collision" stuff, but I think what I have described could give you something of an idea of the kind of geometry you're going to need to perform in order to solve this problem.
In short, bouncing balls off of each other correctly is difficult. Consider removing/abandoning this functionality if it's not required and/or you're not willing to spend the effort.
You could also put together something less correct, but easier. You could simply have balls move away from each other when they collide, but then you'd get "unnatural" looking ricochets.
I know it certainly doesn't solve your problem, but hopefully this helps.
In Java (at least when using Bluej as the environment), the top left corner pixel is (0,0) and bottom left is (600,600)(depending on window size). Your logic is unfamiliar to me, but assuming your math is correct to have the balls reverse direction when hitting a wall you should have 4 if statements per ball. I know there are ways of getting away with 1 or 2 and my way is ugly and not very effecient, but a least it will isolate if the problem is your math of logic.
if (X<=0 || X>=600)
{
velocity.reverseX();
}
if (Y<=0 || Y>=600)
{
velocity.reverseY();
}
I hope this helps :)
I have a little tech game I am messing around with and I can't figure out the formula to position 1 object given another objects origin.
So I have a Spaceship and a Cannon. I have the game setup to use units, so 1 unit = 16 pixels (pixel art).
Basically my cannon should be placed 0.5625 units on the X and 0 on the Y relative to the origin of the Spaceship, which is located at 0, 0 (bottom left corner).
The cannon should is independent on the angle of the spaceship, it can aim in different directions rather than being fixed to aim the way of the spaceship.
I have it constantly following the cursor, which works fine. Now when I rotate the Spaceship, obviously the origin of the Spaceship is changing in world coordinates, so my formula to place the cannon is all messed up, like so:
protected Vector2 weaponMount = new Vector2();
weaponMount.set(getBody().getPosition().x + 0.5625f, getBody()
.getPosition().y);
Obviously if I position the ship at a 90° angle, X is going to be different and the cannon would be waaaayyy off the ship. Here is a screenshot example of what I mean:
What would be the formula for this? I have tried using cos/sin but that does not work.
Any ideas?
weaponMount.set(0.5625f,0).setAngle(SpaceshipAngle).add(getBody().getPosition());
Where SpaceshipAngle is the angle of your Spaceship.
The origin of the spaceship is the point, arround which the spaceship will rotate and scale (the Texture of it). The position instead is always the lower left corner of the Texture and does not depend on the rotation.
Your problem is, that your offset does not depent on the rotation of your spaceship.
To take care about this rotation you should store a Vector2 offset, which describes your weapons offset (in your case it is a Vector2(0.5625f, 0)).
Next store a float angle describing your spaceships rotation.
Then you can rotate the offset by using: offset.setAngle(rotation).
The last thing is to set the weapons position. The code for this did not change so much:
weaponMount.set(getBody().getPosition().x + offset.x, getBody()
.getPosition().y + offset.y);
I'm trying to make a ball bounce around a window. Depending on how far away the ball hits the wall and at what angle will determine its reflection. You can see in the pic that the black trajectory hits the opposite wall on the inner half... and the gray trajectory represents if it were to reflect and hit the other half... which would decrease the angle of reflection.
I'm not sure if I'm thinking about it correctly... I'm trying to put the coordinates in terms of degrees.
So given the pic... You would take those deltas, then get degrees...
degree = Math.atan2(opposite/adjacent) = (-4/-2)
My code
public class Calculate {
public Calculate() {
System.out.println(getCalc(7,5,4,0));
}
public double getCalc(int x1, int x2, int y1, int y2) {
double deltaX = Math.abs(x2-x1);
double deltaY = Math.abs(y2-y1);
double degrees = Math.toDegrees((java.lang.Math.atan2(deltaX, deltaY)));
return degrees;
}
}
Gives the output: 26.56505117707799
So now I know the ball would reflect off the wall at 26 degrees (since that's the angle of incidence). But I don't want the ball to necessarily reflect uniformly off each wall so it adds variability.
My questions:
Am I calculating the angle of the ball correctly?
How can I add variability to the bounce based on where it hits on the wall?
Once I have the angle in degrees, how can I translate that back to coordinates?
Thank you!
Am I calculating the angle of the ball correctly?
Your drawing is not to scale. The 26 degrees is measured from a line perpendicular to the wall.
How can I add variability to the bounce based on where it hits on the wall?
You already suggested a random angle. You can also adjust the angle of reflection based on the distance from the center of the wall.
Put your angle of reflection calculation into its own method. You can adjust the calculation until your calculations give you the "randomness" you're looking for.
Once I have the angle in degrees, how can I translate that back to coordinates?
Convert the degrees to radians, then calculate the SAS of the triangle. Just leave your angles in radians in the model, and convert to degrees in your display / diagnostic methods.
I think that the distance of the ball from the surface doesn't really have an effect on the angle. The angle of the ball before hitting the surface should be the same (mirror reflected) when it leaves the surface for it to be natural.
You can add some variability by thinking what happens to a rubber ball, since it changes a little on impact depending on the force etc., the reflection is not exactly the same every time. You could simply add or remove a degree or two randomly and see how it goes.
Once you have an angle, its once again down to trigonometry. You have an angle, and you know the hypotenuse (I presume depending on your frame-rate and ball speed the ball would have travelled a certain amount from the surface). So from that you need to get the adjacent and opposite lines of the triangle.
For example:
sin(angle) * hypothenuse = opposite (so Y offset from the surface).
cos(angle) * hypothenuse = adjacent (so X offset from the point of contact).
Just add or remove (depending on the direction) the adjacent and opposite values from the coordinates of the contact point.
If you want to make it seem a little random, you could model spin somewhat--it doesn't have to be too complicated.
If it was not spinning and hit a wall at a 45 degree angle, it would impart a spin to the ball. When it hit the next wall, the spin would added to the angle and the spin would be increased (or decreased) by the angle. I think the spin/angle combination would also effect the speed at which it came off the wall (Just visualizing real-life situations)
That would make it vary without it being truly random--but I don't know how it would actually look--you may have to apply other restrictions (I think that there must be a way to limit the max spin).
I bet there is a simple physics book around that could give enough to model this without going too deep into the math if you didn't just want to make up rules.
I'm making a pong clone to practice my coding, and I've become stuck on making the ball be able to change angle when hit by the paddle.
My current implementation has a deltaX and deltaY for the ball, which moves with the game loop to move the ball. The way I have done it is that if you hit the ball while the paddle is moving, the deltaY is increased or decreased depending on the direction of the paddle, but this does not feel natural at all for the game.
Does anyone know a better way of doing this?
First thing I would do is change the deltaX and deltaY to ballAngle and deltaSpeed. That way you'd be moving from a rectangular coordinates system to a polar one. Due to the nature of the movement of the ball (Goes in a straight line and changes the angle of the line at each impact) this will make your work easier. From now on you'd only have to change ballAngle to update the ball's direction.
However you'll have to update the function that draws the balls for it to move back from polar to rectangular coordinates so you can display it on the screen. A little bit of high-school trigonometry will let you calculate screen position deltas depending on your angle and speed:
newPosition = oldPosition + movementVector
with:
movementVector.x = deltaSpeed*cos(ballAngle)
movementVector.y = deltaSpeed*sin(ballAngle)
Of course these equations might need some modification based on relative to what you measure the ball's angle.
Now to modify the ball's angle at each collision with the paddle, you only have to increment or decrement the angle of the ball depending on which part of the paddle it touches, and the math in the drawing function should take care of updating x and y positions realistically.
I hope this helps.