I am trying to bounce a projectile off of a wall in Slick. When the wall is vertical or horizontal, I can just invert the x or y velocity of the projectile, but when this is not the case I am struggling. I found another answer to a similar question in C# and have tried to implement it, but the result is just that the ball goes off at 180 degrees every time. What I have is:
Vector2f norm = wall.getNormal();
float comp = (vect.dot(norm)/norm.dot(norm));
Vector2f u = new Vector2f(norm.getX()*comp,norm.getY()*comp);
Vector2f w = new Vector2f(vect.getX()-u.getX(),u.getX());
vect.set(w.getX()-u.getX(),w.getY()-u.getY());
Where wall is a Vector2f that I am trying to bounce off of (converted from a line to a vector, but not sure if this was necessary) and vect is the trajectory of my projectile.
Any advice would be really helpful. I would love if someone could explain an answer to me rather than just giving me the code, because I think I may need to implement something slightly different later.
Thanks.
The answer here is going to wind up being mostly a question of math. I briefly go over the math/physics involved and trust that you should be able to implement the math/physics in code yourself.
How projectiles are supposed to bounce off of walls
In classical physics, or at least in a reasonably representative model of classical physics, when a projectile collides with a wall, the magnitude of the angle at which it leaves the wall relative to the 'normal' vector of the wall is equal to the magnitude at which it approaches the wall relative to the 'normal' vector. In other words, draw a line perpendicular to the wall the object is colliding with. The angle between this line and the vector of your projectile moving towards the wall will be the same as the angle of the vector of your projectile moving away from the wall.
This is most commonly discussed for light rays, but it works the same way for simple projectiles.
http://hyperphysics.phy-astr.gsu.edu/hbase/phyopt/fermat.html
How to calculate these angles
So let's say you have a vector for the normal of the wall, and a vector for the projectile. For 2-dimensional vectors, this is actually quite easy. You should have a couple of decent options here. One way might be to get the angles of the two vectors and subtract them to find the difference.
Now we know the magnitude of the angle, but we now need to create a vector with the same angle but on the other side of the normal vector. Your vector library conveniently allows you to adjust your vector by a given angle. You should be able to take the projectile's current velocity vector and adjust in the correct direction it by twice the angle between it and the normal-to-wall vector and get the desired velocity vector post-reflection. The trick I will leave you to figure out is a good way to determine if you need to adjust your vector in the clockwise or counter-clockwise direction.
Some things to keep in mind about Vector2f
The getNormal() method returns a unit vector in the same direction as the vector
If you want a vector normal to a certain vector, you must use the getPerpendicular() method
A vector may be rotated/adjusted by a certain angle using the sub(double theta) method
If you would like to retrieve the angle of a vector, you may do so using the getTheta() method
Related
I am hoping someone could point me in the direction of a libGDX example that shows how the rebound angle is calculated when a polygon hits another (which is fixed) - The questions/answers I've found on StackOverflow have all been to general (abstract), I'm hoping for a more libGDX specific answer :)
Currently, I am using Intersector.MinimumTranslationVector to check whether the moving polygon has hit another fixed-stationary polygon and then using the resultant values to shift the objects back out of each other.
When the collision occurs virtually or horizontally, the bounce calculation is easy and currently works well. What I am having troubles with are the diagonal collisions - working out which face was actually hit and the direction in which to bounce.
The moving polygon uses a Vector2 object for it's velocity, so the question is how is the new velocity calculated? I'm assuming it can be done using the Intersector class, but how?
I'm creating a Breakout game to familiarize myself with Java.
Currently I've got everything working but I've noticed that the ball seems to take off in the same direction.
I've programmed it so when the ball hits the paddle the Y velocity is reversed. This works, but the ball seems to follow the same route...
How would a make the collision seem more realistic?
When the ball hits the left side of the paddle, I want to redirect it back to the left but I'm not sure at which angle to reflect it. Can anyone provide a formula to help me work out the angle at which I need to direct the ball upon contact with either the left or right side of the paddle?
If the ball hits the paddle from the top, negate Y velocity.
If the ball hits the paddle from the side, negate X velocity.
Reversing the vertical velocity is the correct thing to do for a perfectly elastic collision, which is what you want in a breakout game (the ball keeps it's total velocity after the collision).
The problem of following the same route can be avoided either by randomizing the initial ball position and velocity, or by changing the collision dynamics to be unrealistic. You could either add a small random component to both coordinates (taking care to keep the total velocity the same), or send the ball at a different angle, depending on where it hits the pad (which is what many games of this type do).
To do the later, you need to calculate the absolute position where the ball hits the pad, normalize it (by subtracting the pad position and dividing by the pad length), and map it into a angle range (maybe -80 to 80 degrees). You can then calculate the desired horizontal and vertical velocities using trigonometric functions.
One idea might be to use motion of the paddle to vary the direction a bit. Say, if the paddle is moving to the right when hitting the ball, change the X velocity of the ball to the right a little in addition to reversing the Y direction. That provides a way for the user to actually use some skill to put the right "English" on the ball.
There are two separate problems involved, a design problem and the physics problem. In the end, the physics problem might have the easier solution:
Compute the collision point on the paddle
Compute the instantaneous horizontal velocity pvx of the paddle
Compute the normed outward surface normal (nx,ny) at the impact point. This is the design decision, in the middle part of the paddle one probably wants (nx,ny)=(0,1), while on the left side (nx,ny)=(-1,0) or generally in WNW direction, on the right side correspondingly (nx,ny)=(1,0) or in the general ENE position.
Use the physics formula for a collision with a moving infinitely massive object to compute the new velocity vector (vx,vy):
dot = nx*(vx-pvx)+ny*vy
vx = vx - 2*dot*nx
vy = vy - 2*dot*ny
One may check if the dot product dot is positive to avoid spurious collision computations if paddle and ball do not separate fast enough after collision.
In my libGDX project I want to move a player around the screen with a touchpad. That already works.
Now I want to rotate the "face" of the player in the direction he is moving.
I have tried it with this little piece of code, but I doesn´t really work
double degree;
degree = Math.tan(touchpad.getKnobPercentX()/touchpad.getKnobPercentY());
playerSprite.setRotation((float) degree);
I hope u can help me (I have bee searching on Google for about 1 hour before I asked this question, so don't tell me to Google it;))
You might want to use the atan(y/x) function or even better the atan2(y,x) function to get the angle. Check the documentation where you get results in radians and expect inputs in degrees.
tan transforms an angle (in radians) to the tangent value, the slope of the angle.
phi=atan(y/x) is the arc tan, centuries ago written as arg(y/x=tan(phi)). It gives the same result for opposite angles, so you would have to correct for the right quadrant.
phi=atan2(y,x) already performs that correction.
My maths isn't that good so I'm having a bit of trouble in one of my applications that I'm trying to do where I want a rectangle to represent a vehicle and I want that vehicle/rectangle to "drive" around in a circle. Imagine a roundabout with only 1 vehicle in it, just circling around forever.
If I can get some help how to do that then I'll be able to build on the example and most importantly learn.
If someone could write up a simple example for me I'd be grateful. No background no images, just a rectangle "driving" around in a circle. I'm using java and Swing.
Sorry, I am not sure if could understand clear you exactly need. If you need to draw rectangle which is moving around inside of circle, you can use sin/cos functions.
Something like that:
double r = 50.0; // radius (it might radius of your circle, but consider dimensions of rectangle to make sure you are drawing inside of circle, e.g. circleRadius - rectangeDimesion / 2.0)
for (int f = 0; f < 360; f++) {
double x = Math.sin(Math.toRadians((double)f)) * r;
double y = Math.cos(Math.toRadians((double)f)) * r;
// draw rectangle on [x, y] coordinates
}
If you know the radius of the round about, all the you would need would be a trigonometric function and the angle which the vehicle makes to the round about. You could take a look at this simple introduction which should get you started in the right direction.
On another hand, another approach would be to use a Transformation Matrix where you start with a matrix containing two points (your X and Y co-ordinates) and you transform them to become the new co-ordinates.
You can then rotate the rectangle to mimic a vehicle turning.
If you have a limited background in Mathematics, the first option might be easier for you to grasp.
This is more an extended comment than an answer.
I would divide the problem up into several easier problems, and work on each of them separately:
Draw your rectangle with a specified center location and long axis orientation.
Determine the center point and long axis orientation for an object orbiting around the origin. Note that to get make the long axis a tangent it needs to be perpendicular to the radius through the center.
Translate the whole system so that it orbits the desired point, rather than the origin.
I am developing an augmented reality application for android and trying to use openGl to place cubes at locations in the world. My current method can be seen in the code below:
for(Marker ma: ARData.getMarkerlist().values()) {
Log.d("populating", "");
gl.glPushMatrix();
Location maLoc = new Location("loc");
maLoc.setLatitude(ma.lat);
maLoc.setLongitude(ma.lng);
maLoc.setAltitude(ma.alt);
float distance = currentLoc.distanceTo(maLoc);
float bearing = currentLoc.bearingTo(maLoc);
Log.d("distance", String.valueOf(distance));
Log.d("bearing", String.valueOf(bearing));
gl.glRotatef(bearing,0,0,1);
gl.glTranslatef(0,0,-distance);
ma.cube.draw(gl);
gl.glPopMatrix();
}
gl.glRotatef(y, 0, 1, 0);
gl.glRotatef(x, 1, 0, 0);`
Where y is yaw and x is the pitch. currently I am getting a single cube on the screen at a 45 degree angle someway in the distance. It looks like I am getting sensible bearing and distance values. Could it have something to do with the phones orientation? If you need more code let me know.
EDIT: I updated bearing rotation to gl.glRotatef(bearing,0,1,0); I am now getting my cubes mapped horizontally along the screen at different depths. Still no movement using heading and pitch but #Mirkules has identified some reasons why that might be.
EDIT 2: I am now attempting to place the cubes by rotating the matrix by the difference in angle between heading and bearing to a marker. However, all I get is a sort of jittering where the cubes appear to be rendered in a new position and then jump back to there old position. Code as above except for the following:
float angleDiff = bearing - y;
gl.glRotatef((angleDiff),0,1,0);
gl.glTranslatef(0,0,-distance);
bearing and y are both normalised to a 0 - 360 scale. Also, I moveed my "camera rotation" to above the code where I set the markers.
EDIT 3: I have heading working now using, float angleDiff = (bearing + y)/2;. However, I cant seem to get pitch working. I have attempted to use gl.glRotatef(-x,1,0,0); but that doesn't seem to work.
It's tricky to tell exactly what you're trying to do here, but there are a few things that stick out as potential problems.
Firstly, your final two rotations don't seem to actually apply to anything. If these are supposed to represent a movement of the world or camera (which mostly amounts to much the same thing) then they need to happen before drawing anything.
Then your rotations themselves perhaps won't entirely do what you intend.
Your cube is rotated around the Z axis. The usual convention in GL is for the camera to look down the Z axis, with the Y axis being considered 'up'. You can naturally interpret axes however you like, but a rotation around 'Z' would not typically be 'bearing', but 'roll'. 'Bearing' to me would be analogous to 'yaw'.
As you translate along the Z axis, I assume you are trying to position the object by rotating and translating, but obviously if the rotation is around the same axis as you translate along, it won't actually alter the position of the cube - it will always just be directly in front of the camera, spinning on its axis.
I'm not really clear on why you're trying to position the cube like that when it seems like you start off with a more specific location. You could probably directly construct a more appropriate matrix.
Finally, your camera/world rotation is two concatenated rotations around Y and X. You call these pitch and roll, but typically using euler angles for a camera rotation does not result in an intuitive result where terms like pitch and roll make complete sense. It is common to maintain an orientation and apply individual rotations to that in order to update it, rather than attempting to update several dependent rotations.
So yes, I would expect that this code, in the absence of other matrix operations, would likely result in drawing one or more cubes straight ahead which are simply rotated by some angle around the view direction.