2D Ball Physics and Collisions
Blitz3D Forums/Blitz3D Programming/2D Ball Physics and Collisions
| ||
Hi, first sorry for my bad english *g* I need a 2D ball collision thats simulate a working "bounce" on every shape. But with no friction, just a ball with constant speed, but with realistic reflect. On 0-360° Walls and circles, half-circles etc. like in a pinballgame, but without friction, gravity, etc... I found something long time ago but its does not work correct. My math is not better than my english lol... Anyone have an example? Or a little source for me? I looked at so many mathsites, but i dont understand the theory :( Thank you =) (i hope someone understand my text lol) |
| ||
A way to do it is to scan around the shape that you want to check for collisions. If you have a ball, you could scan around it in a circle. for i = 0 to 360 coll_pix_x = cos(i) coll_pix_y = sin(i) next For every pixel, check if it has the background color. If not, a collision has occured. If you found a colliding pixel, you could calculate the angle between this pixel and the object using Atan2: oldangle = Atan2(coll_pix_x - obj_x, coll_pix_y - obj_y) With this angle, you could calculate a new angle: newangle = -oldangle - 90 And with this new angle, you can calculate the new velocity of the ball: vx# = cos(newangle) vy# = sin(newangle) Exit the loop and move the ball using: x = x + vx y = y + vy If you have an irregular shape you want to check, there is a floodfill routine in the archives. You can modify it so, that it stores where the boundries were, that stopped the floodfill. Floodfill your objects image background at the start of the program and store all 'boundry coordinates' in a type. In the above code, replace the circle checking routine by a For .. Each loop. |
| ||
many thanks.. this sounds good.. i wanna try it now =) hope it works, but i understand all your tips =) thx again ... Edit: Ok, the collision works fine.. but the "bounce" is wrong. Its just work on one wall and on the other, the ball moves on the line, and then behind it :( |
| ||
@ Head, I don't use alot of 2d stuff but this is how I would do it ... Make a proxy collision map for the lanscape which is not visible to the user. For each of the edges of the landscape colour this with a thick edge ( at least as thick as the fastest speed the ball can travel ) in a ( say red ) colour which represents the angle that that edge points, in effect it's collision normal. Lets say you want to be accurate to 32 angles. Color 5,0,0 represents 0 degrees and color 160,0,0 represents 355 degrees. If your using tiles then you'll need to have a proxy collision tile for each. A naff picture done in paint to show you what I mean. When checking collisions get the red element of the pixel collided and convert this to an angle. Assume ball has a velocity of Vx#, Vy# so from this you can determine the reflection vector. const BallRadius# = 8.0 ;check 8 directions at 45 degree intervals for CheckAngle = 0 to 7 cx# = Ballx + BallRadius * cos( CheckAngle * 45 ) cy# = Bally + BallRadius * sin( CheckAngle * 45 ) ;RedColor = {read pixel at cx, cy and get red element} CollisionAngle# = ( ( RedColor-5) / 5 ) * ( 360.0 / 32.0 ) ;get collision normal vector Nx# = cos( CollisionAngle ) Ny# = sin( CollisionAngle ) ;project velocity onto collision normal vector VdotN# = Vx * Nx + Vy * Ny ;calculate normal force Nfx# = -2.0 * Nx * VdotN Nfy# = -2.0 * Ny * VdotN ;add normal force to velocity vector Vx = Vx + Nfx Vy = Vy + Nfy next Hopefully I've explained this enough? This will work but involves a bit of pre-processing. Stevie |
| ||
ok, thx again.. i will try this one.. oh damn i hate math *g* |
| ||
Here is what I tried: The bouncing back angle is not quite what it should be, my maths are not too good. :( |
| ||
Here's Bram's adapted to include the correct maths as mentioned above. It seems to work well for every angle. Stevie |
| ||
Just a small question, is the collisionwalls to be 2D as well? If that's the case I would probably go with scanning dots around the ball. Doesn't have to be lots and lots of scans. A small pinballball could have an array of 24 points. Noone would ever see any difference and it would be very fast. (no use of sin or cos in the actual checkings) |
| ||
@ AJirlenius, in the version I posted there are only 12 checks around the ball. On modern hardware Cos and Sin are very fast so I see no reason for a lookup. You would have to have thousands being processes each frame to even notice a tiny bit of slowdown. Stevie |
| ||
OK, it works.. I testet it on Walls with different Angles > and < 90° works fine... But one question.. i dont understand the Speed. I wanna change the speed of the ball, but the only effect is that the ball will be faster and faster after collision oO |
| ||
Stevie, that works very nice! :D "Head", the part that moves the ball is x=x+vx y=y+vy The part before that, the "For CheckAngle" loop, is the part that checks for collisions. The ball takes 1px big steps now. If you make those steps too big, it will 'miss out' on collisions. The way to avoid that, is to repeat both the collision checking and the movement a few times after each other: move the ball 1 px, then check it, then moved 1 px again, then checked again etc. |
| ||
thx u all for ur help... i used "x=x+vx+speed" and not "x=x+vx*speed" lol now i try it with the 1px per loop method... but at the moment i need a break.. my brain is emty at the moment :D |
| ||
@ Head. The velocity is the speed, albeit defined as a vector rather than scalar so adding it to the x position makes no logical sense. To set a new speed at the start Global Speed# = 2.0 and change these lines ... newd# = Rand(0, 360) ;set velocities (direction ball) vx = Cos(newd) * Speed vy = Sin(newd) * Speed At the moment the Speed is implied as 1.0. Stevie |