I am learning programming on Greenfoot. I'm creating a scenario that has 5 balls which will follow these properties:
The balls must bounce off the edges of the world in such a way that the angle of incidence equals the angle of reflection.
Each ball must move at a random speed in each of the X- and Y-directions, which speed may vary between 0 and 5 pixels per direction when the instance is created but stays constant for the lifetime of the ball.
Any tips on how to get started would be greatly appreciated, thanks!
Related
I'm developing a very simple physical engine.
I have to calculate the final speed of a circle in an elastic collision against another circle. Each circle has a specific mass, radius and speed.
In order to calculate x and y speed I solve a system with conservation on momentum and conservation of kinetic energy equations.
By the way these equations don't consider the "shape" of circles.
So I calculate the rebound angle by finding the tangent where 2 circles intersect.
Now I have 2 different final speeds directions: the one calculated with momentum law and the one calculated with rebound.
I don't know how to combine the 2 speeds to get the final one
You'll need to calculate the speed in both the X and the Y direction.
Basically, what you do is calculate the results of the x component of the collision, the results of the collision in the y direction, and then combine them to find the resultant angles and speeds.
This is a common AP physics question, so you'll find lots of writeups on the internet about how to do it. This one looks like it should work for you:
http://spiff.rit.edu/classes/phys311.old/lectures/coll2d/coll2d.html
The solution I found is to consider normal and tangential components of my 2 circles velocities, and not their X and Y components.
This way I can apply law of conservation of momentum related to tangent and normal, and at the same time it considers the geometry of circles too.
The last part of this tutorial is very helpful, even if I used a different algorithm, with some different logics: https://www.youtube.com/watch?v=LPzyNOHY3A4
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.
Hiho. On a below image we have three situations. Black arrow shows the path before collision, green one - after the collision.
I. Ball 1 hits ball 2 when their are floating on themselves. After the collision, they should both reverse their directions from up to down and from down to up.
II. Ball 1 hits ball 2 and ball 1 reverses it's direction, ball 2 still floats to it's old dir.
III. Here we have a problem. Ball one has lower x position, they collide with just a piece and they should float to some direction that I don't know.
I know some vectors, linear algebra etc. but I just need a point where to start. Is there anyone who know how to solve an issue like this? With vectors? Trig/Cycl functions?
Thanks !
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.
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.