Java - Breakout physics, ball direction on paddle collision? - java

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.

Related

Collision detection between brick and ball (breakout, brick breaker)?

I'm working on a brick breaker game in JavaFX (FXGL). The collision detecting is working like this:
Bricks and players have a x, y position in the game world (placed in LEFT, TOP).
When a collision is detected (this is done by the engine) I use the x, y position to detect where the ball is colliding with the brick to calculate the next direction. The ball direction is created by a velocity vector with (x, y) speed. The collisionLogicSecurityPadding is a small padding which is added since the collision is only detected inside the box. (It's not possible to get the ball and brick exactly at the same x, y coordinates)
if (ball.getX() > levelBrick.getX() - ball.getWidth() + collisionLogicSecurityPadding &&
ball.getX() < levelBrick.getX() + levelBrick.getWidth() - collisionLogicSecurityPadding) {
//velocity.getX(), -velocity.getY()
} else {
//-velocity.getX(), velocity.getY()
}
So I measure if the ball is inside the brick with it x position. If this is the case the collision is TOP or BOTTOM. If not RIGHT or LEFT.
However this is causing the issue when the ball is hitting near the edge it detects wrong. Here a short clip: https://i.imgur.com/U8ybhRl.mp4
The issue is that the x is smaller than the area where it thinks it's TOP or BOTTOM so it's switching the X direction which is causing an issue.
My question here is how to avoid this? Is there any way I can solve the collision that it's working correctly? When I'm looking online the most tutorials are only checking top or bottom collision.
I think you could change the detection of TOP, BOTTOM, LEFT, RIGHT collisions to where the collision happened relative to the ball. Assuming the preservation of momentum you just need to negate the X- or Y-velocity.
In the example above the ball clearly generates a collision TOP and LEFT to his center of mass. Therefore it is impossible to generate a RIGHT collision which would generate the behavior you described. This leaves the Problem, that you do not know yet whether it was a collision on the LEFT or TOP. But since the Vector was pointing to the RIGHT (positive X-Movement), it is impossible to generate a collision on the LEFT. The collision must have happened at the TOP and therefore the Y-velocity needs to be multiplied by -1.
As long as the ball is the only moving object this method cannot generate weird behavior. As soon as you have an Object moving faster then the ball, you need additional checks: An Object hitting the ball on its left, while it is already in a general movement towards right will increase the X-velocity.
As I understood your question it seems to me like your issue is that the red box goes in an incorrect direction after bouncing on an edge.
I think you need to detect collision in three instances.
Top/Bottom
Left/Right
An Edge
If the collision occurs at an edge you need to send it in the same x direction as before with reducing the speed it goes in the direction y. y speed should always be less than initial speed and in the same direction as before.
I think above would solve your issue.

How can one have right movement into diagonal collision boxes giving diagonal movement?

Firstly, apologies for the long title; I could not think of a way to sufficiently cover my problem yet also compact it further.
I am in the process of creating a 2D game in Java with a character in the centre of the screen. My character has a collision box and I have images on the map (looking from above) which also have collision boxes.
However, I'd like to be able to have a "slide" situation if a collision occurs into a side that is not perpendicular to my direction.
For example, if my character is moving east, and there is a wall to his east going in the southwest to northeast direction, instead of just noting that there is an object to the east and not moving, I'd like my character to be able to "slide" along the wall, moving northeast to achieve the attempted Eastern movement.
Is there any easy way to do this?
If it helps in any way, I am using Java Slick2D, and have the collision box of the character as a rectangle where he stands, and the collision boxes of other objects as polygons.
Thanks in advance for any replies!
When you have solved the problem of identifying when a collision has occurred, the sliding motion can be achieved by calculating the component of the motion that is perpendicular to the wall and subtract that from your motion vector.
Say you have a motion vector v = (v_x, v_y) and the normal of the wall n = (n_x,n_y). The normal vector should be of length 1.
Then your new motion vector should be
v_new = v - (v * n) * n.
That in X and Y separately is
v_new_x = v_x - (v_x * n_x + v_y * n_y) * n_y,
and the same way for Y
Class java.awt.geom.Area has a method intersects( Area a ) which should be useful for determining the "point" of impact, call it P. If the character's collision box is a rectangle and the obstacle is bounded by an arbitrary polygon you'll have to determine
the point or side of the rectangle participating in the collision
the point or side of the polygon participating in the collision
If side meets side (they should be parallel), the charcter can't move any more in the current direction; no slide should occur. Equally, if a rectangle side meets a polygon point, movement is blocked.
If a point meets a point, you might resolve this by (arbitrarily?) select one of the sides of the polygon and handle the situation based on that.
Finally, if a rectangle corner meets a slanting side, you'll have to analyze the geometry of this side. (Verify that a 10-to-4 side is met by the upper right (lower left) hand corner if going north or east (south or west), or a 7-to-1 side is met by the upper left (lower right) hand corner when going north or west (south or east)). Then you can determine the forced path along the slanted side.
While this sounds relatively simple, there may be much more complex situations lurking literally round the corner if the collision boxes of objects - polygons - may have concave sections.

Physics circle collisions popping and sliding against bounds

In Java, I'm writing a mobile app for Android to interact with some dynamic balls with some classes I wrote myself. Gravity is determined on the tilt of the phone.
I noticed when I have a bunch of balls bunched up in a corner that some of them will begin to jitter, or sometimes slide while colliding with other balls. Could this be because I'm executing steps in the wrong order?
Right now I have a single loop going through each ball to:
Sim an iteration
Check collisions with other balls
Check collisions against scene bounds
I should add that I have friction with the bounds and when a ball to ball collision occurs, just to lose energy.
Here's a portion of code of how collision is being handled:
// Sim an iteration
for (Ball ball : balls) {
ball.gravity.set(gravity.x, gravity.y);
if (ball.active) {
ball.sim();
// Collide against other balls
for (Ball otherBall : balls) {
if (ball != otherBall) {
double dist = ball.pos.distance(otherBall.pos);
boolean isColliding = dist < ball.radius + otherBall.radius;
if (isColliding) {
// Offset so they aren't touching anymore
MVector dif = otherBall.pos.copy();
dif.sub(ball.pos);
dif.normalize();
double difValue = dist - (ball.radius + otherBall.radius);
dif.mult(difValue);
ball.pos.add(dif);
// Change this velocity
double mag = ball.vel.mag();
MVector newVel = ball.pos.copy();
newVel.sub(otherBall.pos);
newVel.normalize();
newVel.mult(mag * 0.9);
ball.vel = newVel;
// Change other velocity
double otherMag = otherBall.vel.mag();
MVector newOtherVel = otherBall.pos.copy();
newOtherVel.sub(ball.pos);
newOtherVel.normalize();
newOtherVel.mult(otherMag * 0.9);
otherBall.vel = newOtherVel;
}
}
}
}
}
If this is the only code that checks for interactions between balls, then the problem seems pretty clear. There is no way for a ball to rest atop another ball, in equilibrium.
Let's say that you have one ball directly on top of another. When you compute the acceleration of the top ball due to gravity, you should also be doing a collision check like the one you posted, except this time checking for dist <= ball.radius + otherBall.radius. If this is the case, then you should assume a normal force between the balls equal to that of gravity, and negate the component of gravity in line with the vector connecting the two balls' centers. If you fail to do this, then the top ball will accelerate into the bottom one, triggering the collision code you posted, and you'll get the jitters.
Similar logic must be used when a ball is in contact with a scene bound.
Since I've been experimenting with my own Phys2D engine (just for fun), I know you're talking about. (Just in case - you may check my demo here: http://gwt-dynamic-host.appspot.com/ - select "Circle Collisions Demo" there, and corresponding code here: https://github.com/domax/gwt-dynamic-plugins/tree/master/gwt-dynamic-main/gwt-dynamic-module-bar).
The problem is in a nature of iterations and infinite loop of colliding consequences. When e.g. ball is reached the scene corner, it experiences at least 3 vectors of force: impulse of bounce from the wall, impulse of bounce from the floor and impulse of gravity - after you summarize all 3 impulses, reduce it according loosing energy algorithm, you have to have the new vector where your ball should be. But, e.g. this impulse directs it into wall - then you have to recompute the set of vectors again according to all the stuff: energy of bounce, impulses, gravity, etc. Even in case if all these impulses are small, you never get all of them 0, because of precision of doubles and your tolerance comparison constants - that because you have the "jitter" and "sliding" effects.
Actually, most of existing 2D engines have these effects one kind or another: you may see them here: http://brm.io/matter-js/demo/#wreckingBall or here: http://box2d-js.sourceforge.net/index2.html - they actually just make the small impulses to be absorbed faster and stop iterating when the whole system becomes more or less stable, but it is not always possible.
Anyway, I'd just recommend do not reinvent your own wheel unless it is just for your fun - or for your better understanding this stuff.
For last one (JFF) - here is good tutorial: http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
For real things, I'd recommend to use the existing engines, e.g. Unity (https://unity3d.com/learn/tutorials/modules/beginner/2d/physics2d) or Box2d (http://box2d.org/)
Hope this helps.
Iterating through all the balls and changing the balls position for each iteration is probably the cause for the instability, you move a ball left to avoid collision on the right, and then you pushed the ball into another ball on the left, and then the left ball tries to push it back again.
From the top of my head I could recommend trying to sum up all the forces on each ball before doing anything about positioning. And if you iterate from the ball "on top" (furthest away from gravity source/direction) you can probably achieve a stable situation.
Basically, the top ball needs to first calculate forces between itself and the ball(s) under it, plus gravity, then the ball under will know how much force is coming from the top ball, and added with gravity it would also add to the force of which it is pushing the balls under it. When all balls know the forces they're pushed with you can transform that force into motion.
The way you are simulating the physics of the balls is bound to cause instabilities. Your collision resolution tries to separate the balls by projecting one of them in the opposite direction by the collision depth. This may fix the overlap for those two balls but chances are(especially when the balls are stacked) that the ball is now overlapping with another ball.
There are many ways to fix penetration. One of the simplest ways is to add a "bias" or a bit of a push to both bodies to force them to separate over the next couple of frames. This allows that energy to propagate and force all of the bodies apart. Problem is, the bias will often overestimate and cause a bit of a bounce. To fix that problem I'd recommend reading up on sequential impulse.
Making physics look realistic is not as easy as it may seem. Unless you don't mind instabilities I'd recommend spending some time reading up on different techniques or using an engine such as Box2D.

Calculating angle of rebound in java

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

Pacman collision detection with varying character speeds?

I am programming a 2D, grid-based Pacman game. All the tiles are 8x8 in size. In-game, the map tiles are treated as 16x16, and the characters (Pacman and the ghosts) are treated as 32x32. In actuality, they are all pulled from a spritesheet of 8x8 tiles. I store positions as the center point of each character. Since the character tiles are bigger than the map tiles, the map is built in a way that requires the characters being able to "overlap" onto blocked tiles.
To deal with this set of problems, I created an invisible Rectangle and attached it to the character's position. Where the position is an (x,y) point, the Rectangle is a box surrounding that point. This rectangle is essentially 16x16 in-game, and is in the center of the character, which allows for the overlap necessary.
This works fine if you're working with 8px as the global movement speed, but I'd like to treat 8px as "100% speed" and have complete control over character speed with a double that is in the range [0,1). The positions are stored as double points, so on that level, this is fine. I read the positions back as integers, though, since I'm working with pixels.
So the question I ask is essentially "if this moves X amount of pixels to direction Y now, will my collision box be touching a blocked tile? But if you're moving 5px at a time, this eventually causes a very obvious issue. Say you're at x = 0, moving right. The tiles are 16x16 in-game, as stated before, and you have two of these open before the third, which is blocked. So you move, x = 5, x = 10, x = 15, x = 20, we just got to the 2nd tile, x = 25, x = 30, x = 35 now we're in the 3rd tile... but wait. We can't go there, because X = 35 collides. And unfortunately, we needed to turn and start moving down, but we can't, because now our Y-axis isn't aligned properly with the grid. Our X position needs to be 32, but can't.
My question for everyone here is, what are my options? What are some ideas or insights you have? I have a feeling I'm making it more difficult than I need to.
sounds like you have...
Why not give your "pac-man" sprite a velocity vector? The vector will describe not only the speed at which "pac-man" is traveling but in what direction, meaning you can see ahead.
"pac-man" should be calculating and ultimately making a decision based upon the following conversation..."hey, moving at this speed and in this direction..in so many seconds I'm going to hit a wall, when does that happen?". The seconds don't even have to be seconds...they could be "squares".
You would need a function which takes in the initial movement vector (direction and speed) which returns a coordinate of an X,Y point where "pac-man" must stop, where he cannot go further and must change direction (the center of a tile adjacent to a wall). Each time "pac-man" changes direction, run this calculation again...you do not need to keep checking if the next square is passable. If his direction hasn't changed and his speed is constant..you only need calculate once and let the coordinate system do the rest.
With this approach, square size and velocity is irrelevant...until "pac-man" hits or within his next movement exceeds the stopping point, continue to move along the vector.

Categories

Resources