A Flash Developer Resource Site

# Thread: Ball inside Ball collision - stop bouncing

1. ## Ball inside Ball collision - stop bouncing

I'm currently wrapping my head around vectors and have tried my hand at ball vs ball collisions.

My problem comes when the ball has bounced enough and should finally be coming to rest.

Code below:
PHP Code:
``` import com.nolentabner.Vector2D; // initialization of the balls var smallBall:Sprite = new Sprite(); var bigBall:Sprite = new Sprite(); // bigger ball bigBall.graphics.lineStyle(1, 0x000000); bigBall.graphics.drawCircle(0, 0, 120); bigBall.x = stage.stageWidth/2; bigBall.y = stage.stageHeight/2; addChild(bigBall); // smaller ball smallBall.graphics.beginFill(0xFF0000); smallBall.graphics.drawCircle(0,0, 40); smallBall.graphics.endFill(); smallBall.x = stage.stageWidth/2 - 50; smallBall.y = stage.stageHeight/2; addChild(smallBall); // initialization of the vectors // main movement vector for smallBall var movement:Vector2D = new Vector2D(0, -2); // vector between ball centers var ballDist:Vector2D = new Vector2D(0,0); // used for collision reaction var projection:Vector2D = new Vector2D(0,0); var proj2:Vector2D = new Vector2D(0,0); // step per frame. will eventually be replaced with a timer stage.addEventListener(Event.ENTER_FRAME, onFrame); // enterframe function function onFrame(e:Event):void {     movement.y += 0.8;          ballDist.x = bigBall.x - smallBall.x;     ballDist.y = bigBall.y - smallBall.y;          // if the smaller ball is outside the bigger ball     // perform reaction     if(ballDist.len+smallBall.width/2 > bigBall.width / 2)     {             var wall:Vector2D = ballDist.leftNormal;         var dp:Number = dot(movement, wall.normal);         var dp2:Number = dot(movement, wall.leftNormal.normal);         projection.x = dp*wall.normal.x;         projection.y = dp*wall.normal.y;         proj2.x = dp2*(wall.leftNormal.x/wall.len);         proj2.y = dp2*(wall.leftNormal.y/wall.len);         proj2.x *= -1;         proj2.y *= -1;         movement.x = projection.x + proj2.x;         movement.y = projection.y + proj2.y;         movement.x *= 0.5;         movement.y *= 0.5;                  /*if(movement.len < 0.4)         {             movement.x = 0;             movement.y = 0;         }*/     }          smallBall.x+=movement.x;     smallBall.y+=movement.y; } // finds the dot product between two vectors function dot(v1:Vector2D, v2:Vector2D):Number {     return (v1.x*v2.x + v1.y*v2.y); }  ```
PHP Code:
``` package com.nolentabner {         public class Vector2D extends Object     {         // x         private var __x:Number;         // y         private var __y:Number;         // length of our vector         private var __len:Number;         // our normal         private var __normal:Vector2D;         // our lefthand normal         private var __leftNormal:Vector2D;         // our righthand normal         private var __rightNormal:Vector2D;                  // tracking variables         private var lenUndefined:Boolean;                  public function Vector2D(x:Number=0, y:Number=0)         {             this.__x = x;             this.__y = y;                          lenUndefined = true;         }                  /*** GETTERS/SETTERS ***/         // x         public function get x():Number         {             return __x;         }                  public function set x(num:Number):void         {             __x = num;         }                  // y         public function get y():Number         {             return __y;         }                  public function set y(num:Number):void         {             __y = num;         }                  // length (read only)         public function get len():Number         {             __len = Math.sqrt(__x * __x + __y * __y);                          return __len;         }         // normal (read only)         public function get normal():Vector2D         {             if(!__normal)             {                 //normalized unit-sized vector                 __normal = new Vector2D();                                  if (this.len>0)                 {                     __normal.x = __x/__len;                     __normal.y = __y/__len;                 } else                 {                     __normal.x = 0;                     __normal.y = 0;                 }             }             return __normal;         }                  // left hand normal (read only)         public function get leftNormal():Vector2D         {             return new Vector2D(__y, __x * -1);         }                  // right hand normal (read only)         public function get rightNormal():Vector2D         {             return new Vector2D(__y * -1, __x);         }                  /*** UTILITIES ***/         public function normalize():void         {             if (this.len == 0)             {                 __x = 0;                 __y = 0;             }             else              {                 __x /= this.len;                 __y /= this.len;             }         }                  public function toString():String         {             var st:String = "Vector2D: x=" + __x.toString() + " y=" + __y.toString();             st += " length="+len.toString();                          return st;         }     } }  ```
You can paste this into any version of Flash CS3 or greater.

edit: I posted the Vector2D class as well. It's nothing amazing but works for now.

You can see where i commented out a check where if the length of the movement vector is less than a specific amount, to set the x/y properties of the vector to 0. It somewhat worked but it didn't look natural.

Can anyone take a look at this and help point me in the right direction? I just want a mostly-realistic collision reaction between two balls where one is inside the other.

Here is an example of what happens for those who don't want to create their own .swf. I know how lazy some of you are out there .
http://www.nolentabner.com/projects/ball/test.swf

Thanks!

2. PHP Code:
``` function updateVelocity(){    //Applying acceleration    VelocityVector += AccelerationVector //Can be any number, so you can use 0 when no acceleration    //Applying friction    VelocityVector.length * 0.8   //Or any number between 0 and 1 }  ```
So I think in your example you keep Velocity at a certain value and after a while when you want to stop it apply friction. To actually have balls of different weight you should also add a Force vector and acceleration should be:
PHP Code:
``` AccelerationVector += ForceVector / Mass  ```

3. Originally Posted by TOdorus
PHP Code:
``` function updateVelocity(){    //Applying acceleration    VelocityVector += AccelerationVector //Can be any number, so you can use 0 when no acceleration    //Applying friction    VelocityVector.length * 0.8   //Or any number between 0 and 1 }  ```
So I think in your example you keep Velocity at a certain value and after a while when you want to stop it apply friction. To actually have balls of different weight you should also add a Force vector and acceleration should be:
PHP Code:
``` AccelerationVector += ForceVector / Mass  ```

When you refer to Velocity, are you meaning the vector I named 'movement'? That one seems to change as gravity is applied and it bounces off the other circle. I think I'm still a bit confused.

4. Bump for the "morning" crew.

5. I couldn't tell by glancing from your code, but this may be a similar problem to one I had. I was working on collision with a point and a line and I had this infinite bouncing dilemma as well. I finally realized that it was my gravity that kept adding energy to the system every frame and so the point (ball in your case) would never come to rest because that downward vector was being redirected upward based on the angle of the line (or circle). I think I abandoned that project after that but at least this may have helped you find your problem? Or maybe I'm the only one with that issue =p

6. Originally Posted by Frag
I couldn't tell by glancing from your code, but this may be a similar problem to one I had. I was working on collision with a point and a line and I had this infinite bouncing dilemma as well. I finally realized that it was my gravity that kept adding energy to the system every frame and so the point (ball in your case) would never come to rest because that downward vector was being redirected upward based on the angle of the line (or circle). I think I abandoned that project after that but at least this may have helped you find your problem? Or maybe I'm the only one with that issue =p
Yeah, I can see that it's the gravity that's making it "shiver". My issue comes from knowing when to make the gravity stop affecting the ball.

When I turn it off too early, it stops the ball on the side of the larger ball, thus giving an unrealistic feel.

I'll keep playing around with the code, but hopefully someone can hop in and say, "hey dude, you're doing it wrong. try this". Haha.

7. Originally Posted by nolen
You can paste this into any version of Flash CS3 or greater.
and it will not compile because...
Originally Posted by nolen
the Vector2D class is just a small class I came up with to simplify things. I don't think it's relevant to post it.
yeah well I don't think it's relevant for me to re-write it to get your code to compile :P
My issue comes from knowing when to make the gravity stop affecting the ball.
you dont need to turn it off, instead you need to multiply your ball velocity by something smaller than 1 (like 0.98) - this will eventually stop it.

8. Originally Posted by realMakc
and it will not compile because...yeah well I don't think it's relevant for me to re-write it to get your code to compile :Pyou dont need to turn it off, instead you need to multiply your ball velocity by something smaller than 1 (like 0.98) - this will eventually stop it.
Oh poop. You're totally right. I'll upload a copy of the class when I'm home from the office tonight.

So right now I'm adding gravity to the velocity (that's the 0.8 at the beginning of the frame loop, and if there is a collision I am multiplying the velocity by 0.5 (that's at the end of the loop). You're saying I need to multiply it by yet another number?

Sorry to be so dense. It was a long weekend.

9. Alright, I've updated the first post with the code for the Vector2D class in case anyone else wanted to compile the example and whatnot.

I appreciate all the help so far. Thanks!

10. bah, TOdorus already said that.

11. I'd say just check at what speed the ball is traveling at, and if yspeed is 0 (or very VERY close to zero), then set the yspeed to 0, and if xspeed is VERY close to zero, set that to zero too. That way, when you multiply your speeds by the gravity, it doesn't have anything to multiply by...
Not sure, but at first thought, it should work...

P.

12. Allright, please read up on mechanics. A force creates acceleration which gives something velocity. Something with velocity generates friction with the stuff surrounding it.

So in mechanical terms multiplying something by .xx is friction. Gravity is not friction, it is a constant acceleration downward. So when a ball is thrown it moves at a pretty much constant speed in the horizontal vector (slight friction and only little time in the air) and a constant acceleration towards the earth in the vertical vector, because of gravity. Example

13. Originally Posted by Pazil
I'd say just check at what speed the ball is traveling at, and if yspeed is 0 (or very VERY close to zero), then set the yspeed to 0, and if xspeed is VERY close to zero, set that to zero too. That way, when you multiply your speeds by the gravity, it doesn't have anything to multiply by...
Not sure, but at first thought, it should work...

P.
I just tried that and it stops the ball unnaturally on either side, instead of in the middle. There has to be something simple that I'm missing.

14. So your code in your first post is still the code your using for your onEnterFrame function? Because there's still no friction in there, only when the small ball it hits the big ball.

15. Originally Posted by TOdorus
So your code in your first post is still the code your using for your onEnterFrame function? Because there's still no friction in there, only when the small ball it hits the big ball.
So the "if(ballDist.len+smallBall.width/2 > bigBall.width / 2)" statement, I should multiply the movement vector by something like 0.5? That seems to slow the whole thing down and still cause a wiggle.

I think vectors and I aren't meant to be friends.

16. Not vector but physics really. You seem to understand vectors just fine, it's just that if an object doesn't generate any friction it will never stop. Well here we go:

PHP Code:
``` // enterframe function  function onFrame(e:Event):void  {      movement.y += 0.8;            ballDist.x = bigBall.x - smallBall.x;      ballDist.y = bigBall.y - smallBall.y;            // if the smaller ball is outside the bigger ball      // perform reaction      if(ballDist.len+smallBall.width/2 > bigBall.width / 2)      {              (....)         //Friction is applied         movement.x *= 0.5;         movement.y *= 0.5;                    /*if(movement.len < 0.4) //This is still quite a big number. I'd go with a value like < 0.000001         {              movement.x = 0;              movement.y = 0;          }*/      } else {          //Friction is applied          movement.x *= 0.95;          movement.y *= 0.95;      }     smallBall.x+=movement.x;      smallBall.y+=movement.y;  }  ```
Unless the ball is in a vacuum, it generates friction by rubbing against the air or whatever gas it is in. This is considerably less friction then rubbing against a solid wall, but friction none the less.

17. I know, but sometimes it's easier to simply multiply something by a number rather than adding it, solely for the behavour of multiplication versus addition.

I can only suggest what I've found to work in most cases, though of course, it doesn't reflect real life at all...something I should work on, since I like precise math anyway. Anyways, I'm paying attention to this thread...

P.

18. hmmm...

Well, I've never used physics like yours before...I've only used shortcuts, and that was a long time ago too...

I'll try to read up on some physics, see if I find anything...

P.

19. The length is a getter property, and the length is calculated only when you get it.

20. Originally Posted by Pazil
The length is a getter property, and the length is calculated only when you get it.
Yeah this is correct. The length is being calculated and updated properly, from what I can see. Otherwise my projections wouldn't be working, I think.

Something with my reaction code is wrong.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

 » Home » Movies » Tutorials » Submissions » Board » Links » Reviews » Feedback » Gallery » Fonts » The Lounge » Sound Loops » Sound FX » About FK » Sitemap