2D maths (bat, ball, bricks and bounce)

Started by
6 comments, last by exhu 17 years, 9 months ago
I am reading these forums for two days already, I did my best to understand how to write physics for 2D and went really mad with those heavily 3D oriented threads. So I beg you clearify some things about 2D ONLY, 3D is too difficult for me in this moment. The thing I want is to write a clone of a bat-ball-bricks 2D game. And the problem is the bouncing of the ball. I want to implement it as natural as possible with the slowest but easiest algorithm, speed and optimization is not the task for now. The acceleration, friction etc. is not needed -- only the collision and bouncing (reflection) matters. So what I have understood is that I need to have a 2D Vector (velocity) for the ball and a normal vector (surface orientation) for the bricks and the bat. The problem is that I don't understand how to get the angle between the velocity vector and the normal on collision and whether I need it at all. As far as I know the angle of the falling ray equals to the angle of the reflected one, so we need to reflect the velocity vector against the normal plane/axis. So how to do it and do I really need to know the angle and how to treat (how to know the normal of the edge) corners/edges of the bricks when the ball hits them??? Please, help! Thanks.
Advertisement
Assuming that the ball doesn't move too quickly, you might start with a simple discrete circle vs. axis-aligned box test. This will give you the info you need (specifically a collision normal) to implement natural collision response.

The first thing you'll need for this is a function to find the closest point on an AAB (axis-aligned box) to a point. Ask if you need help with this.

Next you need a function to test for intersection between a circle and an AAB. The first step of this test is to find the point on the AAB closest to the circle center (using the previous function), and the second is to compare the squared length of the vector between these two points to the circle radius squared. If an intersection is detected, the direction of this vector gives you the collision normal, and the difference between the length of the vector and the circle radius tells you how far along the normal you need to 'push' the circle in order to resolve the interpenetration. You should also move the circle along the normal a bit 'extra' to ensure that it's not intersecting the same AAB at the beginning of the next update.

Once you've resolved the interpenetration, you reflect the ball's velocity vector about the collision normal.

There are some details there, but it actually reduces to not much code at all; of the different methods you could try, I think this would be the easiest.

Some extra work might be required to handle multiple collisions (such as in a corner where two or more blocks meet), but I'd try to get the basic algorithm working first and then address the multiple collision problem if necessary.
http://www.gamedev.net/community/forums/topic.asp?topic_id=398444
Quote:Original post by jyk
The first thing you'll need for this is a function to find the closest point on an AAB (axis-aligned box) to a point. Ask if you need help with this.


sorry, the closest point to which one? and AAB stands for bricks here, isn't it?

Quote:Original post by jyk
...you need to 'push' the circle in order to resolve the interpenetration.


So the interpenetration occurs due to inaccuracy between time and speed (e.g. when N pixels are more than needed to reach the surface of a brick), did I catch it right?
First of all, the linked-to thread above contains the equation for reflecting the velocity vector about the normal, if you need information on that.
Quote:
Quote:The first thing you'll need for this is a function to find the closest point on an AAB (axis-aligned box) to a point. Ask if you need help with this.
sorry, the closest point to which one? and AAB stands for bricks here, isn't it?
An AAB is any axis-aligned box, which in this case means both the bricks and the paddle (assuming you want the collision response to work similarly for each).
Quote:
Quote:...you need to 'push' the circle in order to resolve the interpenetration.
So the interpenetration occurs due to inaccuracy between time and speed (e.g. when N pixels are more than needed to reach the surface of a brick), did I catch it right?
Yes, that sounds right. Depending on how fast the ball is moving, it's likely that its displacement per frame will result in it being embedded in an obstacle. Pushing it out of the obstacle resolves the interpenetration. If you didn't do this, even with the reflected velocity vector the ball would register as colliding with the very same obstacle at the beginning of the next update, and would most likely just get stuck or bounce around randomly.
Quote:Original post by jyk
Yes, that sounds right. Depending on how fast the ball is moving, it's likely that its displacement per frame will result in it being embedded in an obstacle. Pushing it out of the obstacle resolves the interpenetration. If you didn't do this, even with the reflected velocity vector the ball would register as colliding with the very same obstacle at the beginning of the next update, and would most likely just get stuck or bounce around randomly.


Well, *if* the ball was perfectly elastic, and *if* the frame-rate was constant, the ball would go out again next frame regardless of how fast the ball was moving.

Those are pretty big ifs (especially the second one), and either way, it looks bad having the object penetrate for a frame and then bounce, instead of stopping at edge.
Quote:Original post by Ezbez
Well, *if* the ball was perfectly elastic, and *if* the frame-rate was constant, the ball would go out again next frame regardless of how fast the ball was moving.

Those are pretty big ifs (especially the second one), and either way, it looks bad having the object penetrate for a frame and then bounce, instead of stopping at edge.
That's not quite what I mean.

The only real 'if' in my scenario is that the length of the displacement of the ball for any update be no greater than its radius (perhaps minus an epsilon). How or whether to enforce this depends on the circumstances, but one way would be to use a fixed timestep (not a bad idea anyway).

The ball does not 'penetrate and then bounce', but rather stops at the edge, just as you say. The resolution of the interpenetration occurs within the update itself, not between updates or in any way that would be visible to the player.

You're right that with a fixed timestep the ball would (theoretically) always clear the obstacle on the next update, assuming a reflected velocity vector. However, this would cause the visual artifact you mention, whereas resolving the intersection within the update itself would not. Also, due to floating-point error it's entirely possible that even given a fixed timestep the ball would not in fact clear the obstacle on the 'way out', leading to it getting stuck or behaving erratically. For this reason it's important to add a small buffer when resolving the intersection.

I may not have explained what I had in mind well enough in my first post, but perhaps the above will clear things up.
I've got one more question -- how to calculate the normal of the edges, i.e. the nodes of the faces/lines, e.g.

A00000000000A
0ooooooooooo0
0ooooooooooo0
A00000000000A
_____________1
______________B
_______________B
A = edge/rectangle nodes
1 = pointing side of the velocity vector
B = symbolic body of the vector

The problem is that when the ball strikes the edge it shouldn't bounce against
the facet.

This topic is closed to new replies.

Advertisement