Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Circle Collision-Help Needed
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
zwnage




PostPosted: Sun Jan 14, 2007 9:48 pm   Post subject: Circle Collision-Help Needed

Hello. While looking up peoples sources to try and get ideas, I came across this neat snippet of code from a pool game:

code:

angle := arctand ((ballY (k) - ballY (i)) / ((ballX (k) - ballX (i)))) % angle of hit

cosAngle := cosd (angle)
sinAngle := sind (angle)

speedAfterHit := (2 * ((ballXSpeed (i) * cosAngle + ballYSpeed (i) * sinAngle) - (ballXSpeed (k) * cosAngle + ballYSpeed (k) * sinAngle))) / (ballMass (i) + ballMass (k))

% new velocities of the balls
ballXSpeed (i) -= speedAfterHit * ballMass (k) * cosAngle
ballYSpeed (i) -= speedAfterHit * ballMass (k) * sinAngle
ballXSpeed (k) += speedAfterHit * ballMass (i) * cosAngle
ballYSpeed (k) += speedAfterHit * ballMass (i) * sinAngle


I tried a few test programs with that code, and it works a lot better than the code I'm trying to use, but I really want to learn how this code works, especially whats happening in speedAfterHit and why are we muiltiplying the trig ratios of the angle hit with the ball speeds. Can anyone please explain the code? Thanks.
Sponsor
Sponsor
Sponsor
sponsor
Cervantes




PostPosted: Sun Jan 14, 2007 10:46 pm   Post subject: Re: Circle Collision-Help Needed

First, have you checked this out? Tutorial on Circular Collision data. I admit it isn't much of a tutorial, but it's something.

zynage wrote:
why are we muiltiplying the trig ratios of the angle hit with the ball speeds

This is very common. See, using cosd gives you a number between 0 and 1 that represents the length of a horizontal line from the origin to directly below the point.

math:

     /|
    / |
   /  |   <-- this line is given from sin(theta) where theta is the angle from the horizontal line to the diagonal line
  /   |
 /    |
/_____|   
  ^--- that line is given from cos(theta) where theta is the angle from that line to the diagonal line


So if the speed of a ball is 1, then use cos to get the horizontal speed of the ball. However, if the speed of the ball is 5, simply using cos won't work. We need to extend the length of that horizontal line by 5, because the diagonal line was extended by a factor of 5. So we'd do 5*cos(theta).

I'm not too sure what's going on in speedAfterHit. I'm a bit skeptical of this code because it seems to assuming that the speed of a ball divided by the mass of a ball is a constant number--speedAfterHit. That's clearly not true. Take two pool balls for example. If I shoot one ball directly at the other ball, (ignoring spin) the first ball will transfer 100% energy into the second ball, so the second ball will continue at the speed of the first ball and the first ball will come to a stop. This is because they have the same mass.

I suggest you try to work out the physics of this on paper. You'll need to use conservation of momentum and conservation of kinetic energy (assume this, unless you want inelastic collisions--ones where the balls stick together somewhat or deform slightly). I haven't actually worked out the math of this myself, but I think that'll be all you need in two dimensions.
zwnage




PostPosted: Mon Jan 15, 2007 12:56 am   Post subject: RE:Circle Collision-Help Needed

Thanks for the help. I have tried to work this out on paper, but their code surpasses mine because the balls don't tend to overlap as much. I think I originally got it from thoughtful's tutorial.

Heres what I'm trying to use (pardon the lack of comments, I made it right now out of some notes I had on paper.)

code:

setscreen ("offscreenonly")
var ballX, ballY : flexible array 1 .. 0 of real
var ballXSpeed, ballYSpeed : flexible array 1 .. 0 of real
var ballRadius : flexible array 1 .. 0 of int
var ballAmount : int := 3
var ballVelocity, ballVelocity2, ballNewVelocity, ballNewVelocity2, ballVelocityAngle, ballVelocityAngle2, ballNewAngle, ballNewAngle2 : real := 0

for i : 1 .. ballAmount
    new ballX, upper (ballX) + 1
    new ballY, upper (ballY) + 1
    new ballXSpeed, upper (ballXSpeed) + 1
    new ballYSpeed, upper (ballYSpeed) + 1
    new ballRadius, upper (ballRadius) + 1
    ballRadius (i) := Rand.Int (30, 50)
    ballX (i) := Rand.Int (ballRadius (i), maxx - ballRadius (i))
    ballY (i) := Rand.Int (ballRadius (i), maxy - ballRadius (i))

    ballXSpeed (i) := Rand.Int (1, 2)
    ballYSpeed (i) := Rand.Int (1, 2)

end for

function distance (xInput1, yInput1, xInput2, yInput2 : real) : real % function that returns the distance between two points
    result ((xInput2 - xInput1) ** 2 + (yInput2 - yInput1) ** 2) ** 0.5
end distance

loop
    for i : 1 .. ballAmount
        for j : 1 .. ballAmount
            if i ~= j then
                if distance (ballX (i), ballY (i), ballX (j), ballY (j)) <= ballRadius (i) + ballRadius (j) then
                   
                    ballVelocity := ((ballXSpeed (i) ** 2 + ballYSpeed (i) ** 2) ** 0.5)
                    ballVelocity2 := ((ballXSpeed (j) ** 2 + ballYSpeed (j) ** 2) ** 0.5)

                    ballVelocityAngle := arctand (ballYSpeed (i) / ballXSpeed (i)) - arctand ((ballY (i) - ballY (j)) / (ballX (i) - ballX (j)))
                    ballVelocityAngle2 := arctand (ballYSpeed (j) / ballXSpeed (j)) - arctand ((ballY (i) - ballY (j)) / (ballX (i) - ballX (j)))

                    ballNewVelocity := ((((cosd (ballVelocityAngle)*ballVelocity - cosd (ballVelocityAngle2)*ballVelocity2) ** 2) + (sin (ballVelocityAngle)*ballVelocity) ** 2) ** 0.5)
                    ballNewVelocity2 := ((((cosd (ballVelocityAngle)*ballVelocity - cosd (ballVelocityAngle2)*ballVelocity2) ** 2) + (sin (ballVelocityAngle2)*ballVelocity2) ** 2) ** 0.5)

                    ballNewAngle := (arctand ((ballY (i) - ballY (j)) / (ballX (i) - ballX (j))) + arctand (ballVelocityAngle / ballNewVelocity))
                    ballNewAngle2 := (arctand ((ballY (i) - ballY (j)) / (ballX (i) - ballX (j))) + arctand (ballVelocityAngle2 / ballNewVelocity2))

                    ballXSpeed (i) := cos (ballNewAngle) * ballNewVelocity
                    ballYSpeed (i) := sin (ballNewAngle) * ballNewVelocity
                    ballXSpeed (j) := cos (ballNewAngle2) * ballNewVelocity2
                    ballYSpeed (j) := sin (ballNewAngle2) * ballNewVelocity2

                    ballX (i) += ballXSpeed (i)
                    ballY (i) += ballYSpeed (i)
                    ballX (j) += ballXSpeed (j)
                    ballY (j) += ballYSpeed (j)
                end if
            end if
        end for
    end for
    for i : 1 .. ballAmount
        if ballX (i) > maxx - ballRadius (i) or ballX (i) < ballRadius (i) then
            ballXSpeed (i) *= -1
        end if
        if ballY (i) > maxy - ballRadius (i) or ballY (i) < ballRadius (i) then
            ballYSpeed (i) *= -1
        end if


        ballX (i) += ballXSpeed (i)
        ballY (i) += ballYSpeed (i)
        Draw.Oval (round (ballX (i)), round (ballY (i)), ballRadius (i), ballRadius (i), black)
    end for
    delay (10)
    View.Update
    cls
end loop


Since I havn't taken physics yet (its next sem), I might have mixed up a few terms. The velocities might be called speed or momentem or something.

Heres the jist of it:

find a hit

find the distance traveled each frame by both the balls before the hit (speed or velocity or whatever you call it)---ie : ballVelocity := ((ballXSpeed (i) ** 2 + ballYSpeed (i) ** 2) ** 0.5)

find the angle the ball was originally travelling at. -- ie : ballVelocity := ((ballXSpeed (i) ** 2 + ballYSpeed (i) ** 2) ** 0.5)

calculate the new velocities by subtracting the balls velocity by the other balls velocity, thus slowing the ball down or reversing the direction.-- ie :ballNewVelocity := ((((cosd (ballVelocityAngle)*ballVelocity - cosd (ballVelocityAngle2)*ballVelocity2) ** 2) + (sin (ballVelocityAngle)*ballVelocity) ** 2) ** 0.5)

calculate the new angle of bounce

use the angle of bounce and the new velocites to get the x and y speeds.


Now this code is far from perfect. The program cannot account for when both balls goes hits while going in the same direction (ie : one is faster than the other and hits it from behind). The velocity minus part will slow one of the balls down like its supposed to, but the other ball is slowed too (and probably will go in the opposite direction, towards the first ball). This causes an overlap, and causes them to stick or fly away wildly. The solution I thought of is to give the velocites a positive or negative value, but that would mean I would have to divide my velocites into a further set: the x and y values, I think.....

I dunno if anyone can do anything with that snippet of code, but your welcome to try.
Ultrahex




PostPosted: Mon Jan 15, 2007 8:53 am   Post subject: Re: Circle Collision-Help Needed

Just for your guys information, this is collision response, not collision detection correct?, so what you are trying to do is determine angular momentum, along with momentum, so you need to determine the new velocities along with the new direction.

For those who don't understand the collision detection:

The Collision of a Circle to a Circle is very simple, It is explained by the pictures below:

Posted Image, might have been reduced in size. Click Image to view fullscreen.

Posted Image, might have been reduced in size. Click Image to view fullscreen.

code:
type Ball :
    record
        x : real
        y : real
        v : real % magnitude of velocity
        dir : real
        r : real
    end record

var balls : array 1 .. 2 of Ball

balls (1).x := 50.0
balls (1).y := 50.0
balls (1).v := 5
balls (1).dir := 180
balls (1).r := 40

balls (2).x := 150.0
balls (2).y := 150.0
balls (2).v := 5
balls (2).dir := 45
balls (2).r := 40

View.Set ("offscreenonly")
loop
    % Update Position
    for i : 1 .. upper (balls)
        % Wall Collision

        %---Horizontal
        if (balls (i).x + balls (i).r + cosd (balls (i).dir) * balls (i).v) >= maxx or (balls (i).x - balls (i).r + cosd (balls (i).dir) * balls (i).v) < 0 then
            balls (i).dir := -balls (i).dir + 180
            put balls (i).dir
        end if
        %---Vertical
        if (balls (i).y + balls (i).r + sind (balls (i).dir) * balls (i).v) > maxy or (balls (i).y - balls (i).r + sind (balls (i).dir) * balls (i).v) < 0 then
            balls (i).dir := -balls (i).dir + 360
        end if

        % Update x/y positon based on magnitude of velocity
        balls (i).x += cosd (balls (i).dir) * balls (i).v
        balls (i).y += sind (balls (i).dir) * balls (i).v
    end for


    % Drawing
    for i : 1 .. upper (balls)
        drawoval (round (balls (1).x), round (balls (1).y), round (balls (1).r), round (balls (1).r), red)
        drawoval (round (balls (2).x), round (balls (2).y), round (balls (2).r), round (balls (2).r), blue)
    end for

    % Circle-To-Circle Collison
    if sqrt ((balls (1).x - balls (2).x) ** 2 + (balls (1).y - balls (2).y) ** 2) <= (balls (1).r + balls (2).r) then
        % Collison Has Occured
        put "Collision!"
        View.Update()
        delay(100)
    end if


    View.Update ()
    delay (20)
    cls
end loop
zwnage




PostPosted: Mon Jan 15, 2007 11:45 pm   Post subject: Re: Circle Collision-Help Needed

Yes, I'm trying to find collision response, not collision detection. I did a little research overnight and found that the method I was trying to implement is based on vectors, yet I still have no idea how to fix it so that they don't stick so often. Is there an expample code with vectors out there?

And I'm still confused about the first piece of code. I looked over thoughtful's tutorial a few more times, but there wern't too many comments explaining the collision responce process. Anyone have any ideas?
Skynet




PostPosted: Tue Jan 16, 2007 9:33 am   Post subject: Re: Circle Collision-Help Needed

Yeah, I figured out how their code works.

There are two major points:
1) All of those cosAngle and sinAngle terms are performing a rotation on the x and y axis. When you have a collision between two circles, force is only applied in the direction from one center to the other. (or, in more complicated terms, the normal of the surfaces at the point of contact) So, if you have objects moving in two dimensions, force is going to be applied in both the x and the y direction. The programmer redefines the x and y direction and solves the physics in only one dimension - simplifying the collision response to something that acts like two balls moving directly towards each other. That's easier to solve.

2) There's a generalization the programmer derived - "speedAfterHit". It's not a speed, it's...something else, with the units of m/(s * kg). I didn't find it until I actively tried to make my equations I found match the code you posted. It's a clean way of reducing the amount of work the computer has to do.

If you'd like, I can clean up my work and post it this evening.
For the benefit of anyone else reading this, concepts you should be familiar with:
Trigonometry
Vectors/'Components'
Momentum
Coefficient of Restitution
zwnage




PostPosted: Tue Jan 16, 2007 4:47 pm   Post subject: Re: Circle Collision-Help Needed

Thank you for your help. The "speedAfterHit" was originally named something else, but I renamed it while I was testing the formula in my code. I guess "speed" is not really a good way of describing it.

After thinking your post over a bit, I think my approach to collision responce is simular to the method in question, but as you said, it is much simpler and faster than what I was doing. Oh, and after a bit more tinkering, I think I found my mistake in the code I posted. Instead of subtracting the vectors, I think I should switch them between the two balls. Hopefully, this is the proper way of doing it; I will try to impliment it as soon as I have the time.
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 7 Posts ]
Jump to:   


Style:  
Search: