Computer Science Canada Programming C, C++, Java, PHP, Ruby, Turing, VB   Username:   Password: Wiki   Blog   Search   Turing   Chat Room  Members
[Tutorial]Circular Collision Data
Author Message
Cervantes

Posted: Sun May 30, 2004 5:57 pm   Post subject: [Tutorial]Circular Collision Data

One of the greatest challanges I have faced in my programming life is getting two circles to bounce off each other as they would in real life: obeying the laws of physics. There have been many attempts at solving this riddle.
Homer_Simpson's approach
He uses angles, velocities, and weights. I took the basis of this code and tried to make my own Slime Volleyball program, one where the ball bounces correctly off the walls. I found this exceedingly difficult, and gave up. Cicular collision works well, but I find it difficult to do much else.
thoughtful's approach
He uses the method I like, x, y, vx, and vy. vx and vy are the x velocity, and y velocity. This style makes for easy bouncing off of a flat surface (a wall, for example). Simply make the vx or vy value negative, depending on where the wall is. thoughtful's collision between circles (in this case, pool balls) is flawless for this type of program: for when energy transfer is not 100%. I tried several times to modify his code into my slime volleyball program or also into a pong program where the paddles are circles, and failed. The collision just wasn't right.
rhomer's approach
This approach is nice and simple. It uses the x, y, vx, and vy style, and works well for the most part. The main problem is that the ball tends to go inside the player and do some wild things, or possibly even go through the player.

Cervantes' Approach
A while back tony taught me how to create gravity fields. When you have a gravity field (a spot that sucks whatever objects towards it) it is easy to reverse its effect, creating a repulsing field.
Today I had a revelation: this could be used as a form of circular collision.
I was using it in a slime volleyball setting, so I'm going to be talking in terms of players and balls.
If the ball has collided with the player (determine using the distance formula) then make the player a repulsing gravity field. Also, have a maximum speed for the ball's velocity, so as to not let it get out of control.

 code: setscreen ("offscreenonly") var player :     record         x, y, vy, GFstrength, GFdist, GFforce, GFangle : real %GF = Gravity Field -- Collisions between ball and players in this         radius, score : int                         %uses repulsing gravity fields         jump : boolean     end record player.x := maxx div 2 player.y := maxy div 2 player.vy := 0 player.GFstrength := 3 player.radius := 40 player.score := 0 player.jump := false var ball :     record         x, y, vx, vy : real         radius : int     end record ball.x := 100 ball.y := 100 ball.vx := 0 ball.vy := 0 ball.radius := 12 var keys : array char of boolean const max_speed := 7 loop     ball.x += ball.vx     ball.y += ball.vy     if ball.x <= 0 + ball.radius or ball.x >= maxx - ball.radius then         ball.vx *= -1     end if     if ball.y <= 0 + ball.radius or ball.y >= maxy - ball.radius then         ball.vy *= -1     end if     if ball.vx > max_speed then         ball.vx := max_speed     elsif ball.vx < -max_speed then         ball.vx := -max_speed     end if     if ball.vy > max_speed then         ball.vy := max_speed     elsif ball.vy < -max_speed then         ball.vy := -max_speed     end if     Input.KeyDown (keys)     if keys (KEY_LEFT_ARROW) then         player.x -= 2     end if     if keys (KEY_RIGHT_ARROW) then         player.x += 2     end if     if keys (KEY_UP_ARROW) then         player.y += 2     end if     if keys (KEY_DOWN_ARROW) then         player.y -= 2     end if     if Math.Distance (player.x, player.y, ball.x, ball.y) < player.radius + ball.radius then         player.GFdist := Math.Distance (player.x, player.y, ball.x, ball.y) %figure out the distance between the player and the ball         player.GFforce := player.GFstrength * (1 / player.GFdist * player.GFdist) %inverse square.  it's a gravity field thing.         if player.x = ball.x then %this must be here or a division by 0 error could occur.              if ball.y > player.y then                 player.GFangle := 90             else                 player.GFangle := 270             end if         else             player.GFangle := arctand ((player.x - ball.x) / (player.y - ball.y)) %determine the angle between the player and the ball         end if         if ball.y < player.y then %without this, if the ball hits the underside of the player, it will             player.GFangle += 180 %go into the player and do some wild turns, then shoot out the top somewhere.         end if         ball.vx += player.GFforce * sind (player.GFangle) %finally, apply the force of the gravity field to the x vector of the ball         ball.vy += player.GFforce * cosd (player.GFangle) %apply the force of the gravity field to the y vector of the ball     end if     cls     drawfilloval (round (player.x), round (player.y), player.radius, player.radius, 42)     drawfilloval (round (ball.x), round (ball.y), ball.radius, ball.radius, blue)     View.Update     delay (10) end loop

Please, let me know of any errors in the collision data in this program. In this program, if the ball is moving really slowly, and it hits you (you are still) it will fire off with decent velocity away. I haven't gotten around to trying to fix this, but I have an idea of how to.

The methods of determining the colision data between two circles that I have seen so far all have their varying pros and cons. I hope this new method has very few cons.

Tony

Posted: Sun May 30, 2004 7:11 pm   Post subject: (No subject)

not bad Cervantes - I see you advancing in your programming skillz. I'm glad that you're able to take the consept from one program and modify it to apply properly to another, but there's one major flaw.

when two balls collide, an inpulse force is created that acts only once during the brief moment two balls are in physical contact.

a force field (such as gravity, or negative gravity as in the example) on the other hand act continuely (all the time), but are just not as effective at the distance.

and while the code works since the field's activation is limited to the actual contact moment, the reasoning behind the physics model is wrong
Tony's programming blog. DWITE - a programming contest.
Cervantes

Posted: Sun May 30, 2004 9:46 pm   Post subject: (No subject)

true, its not an actual collision, but it works well enough. Since the gravity field has no effect until there is a collision between the player and the ball (Math.Distance < sum of 2 radii) the ball gets repulsed quickly and it doesn't really look like its going into the player at all.

tony wrote:
and while the code works since the field's activation is limited to the actual contact moment

it's very interesting playing slime volleyball if you take out the two if Math.Distance lines and have the repulsing gravity fields working non-stop
TheZsterBunny

Posted: Tue Feb 08, 2005 8:27 pm   Post subject: (No subject)

Hey,

Nice effect.

How 'bout a tutorial on gravity fields? this looks like something worth learning.

well, the concept anyways.

-Z

Posted: Sun Oct 16, 2011 12:11 pm   Post subject: Re: [Tutorial]Circular Collision Data

umm... you should make it so your ball cant go off the screen, i find a simple if statement works well,

 code: if player.y < (maxy - player.radius) then         if keys ('w') then               player.y := player.y + 5         end if end if
smool

Posted: Thu Dec 08, 2011 10:16 am   Post subject: RE:[Tutorial]Circular Collision Data

Why not calculate tangent of cirlce at point of collision and use angle of incidence = angle of reflection to calculate a bounce?
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

Page 1 of 1  [ 6 Posts ]
 Jump to:  Select a forum  CompSci.ca ------------ - Network News - General Discussion     General Forums   -----------------   - Hello World   - Featured Poll   - Contests     Contest Forums   -----------------   - DWITE   - [FP] Contest 2006/2008   - [FP] 2005/2006 Archive   - [FP] 2004/2005 Archive   - Off Topic     Lounges   ---------   - User Lounge   - VIP Lounge     Programming -------------- - General Programming     General Programming Forums   --------------------------------   - Functional Programming   - Logical Programming   - C     C   --   - C Help   - C Tutorials   - C Submissions   - C++     C++   ----   - C++ Help   - C++ Tutorials   - C++ Submissions   - Java     Java   -----   - Java Help   - Java Tutorials   - Java Submissions   - Ruby     Ruby   -----   - Ruby Help   - Ruby Tutorials   - Ruby Submissions   - Turing     Turing   --------   - Turing Help   - Turing Tutorials   - Turing Submissions   - PHP     PHP   ----   - PHP Help   - PHP Tutorials   - PHP Submissions   - Python     Python   --------   - Python Help   - Python Tutorials   - Python Submissions   - Visual Basic and Other Basics     VB   ---   - Visual Basic Help   - Visual Basic Tutorials   - Visual Basic Submissions     Education ----------- - Student Life   Graphics and Design ----------------------- - Web Design     Web Design Forums   ---------------------   - (X)HTML Help   - (X)HTML Tutorials   - Flash MX Help   - Flash MX Tutorials   - Graphics     Graphics Forums   ------------------   - Photoshop Tutorials   - The Showroom   - 2D Graphics   - 3D Graphics     Teams ------ - dTeam Public

 Style: Appalachia blueSilver eMJay subAppalachia subBlue subCanvas subEmjay subGrey subSilver subVereor Search: