2

tl;dr demo with editor of the bounce function

click to add new ball to the area

There's a question with over 200 votes on this topic with best answer scoring less than half of that. I'm noting that because typically the answers outscore the questions.

I tried to convert the suggested code into javascript. My balls asteroids have following properties:

  • vx, vy - speed in x and y axes
  • x and y for position
  • mass in kilograms, if that matters

My code therefore reads as:

  function bounce(objectA, objectB) { 
    /** objectA and objectB have following properties:
     *   vx, vy - speed in x and y direction
     *   x, y   - position
     *   mass   - masss
     *   radius - diameter, calculated from mass
     *            using average rock density according to wikipedia
   ***/  
  
    // Colision point as seen from B's perspective  
    var collision = [objectA.x-objectB.x, objectA.y-objectB.y];
    var distance = Math.sqrt(collision[0]*collision[0] + collision[1]*collision[1]);
    
    collision[0] /= distance;
    collision[1] /= distance;
    
    var aci = objectA.vx* collision[0] + objectA.vy* collision[1]; 
    var bci = objectB.vx* collision[0] + objectB.vy*collision[1]; 
    
    var totalMass = objectA.mass + objectB.mass;
    // This is what I had to add since the original answer doesn't account for mass
    var acf = bci * objectB.mass/totalMass;
    var bcf = aci * objectA.mass/totalMass;
    
    // I put velocities in arrays in case I wanted to apply more changes
    // I mean I need to apply some changes, but I don't know what changes exactly
    // to make this crap of code work
    var v1 = [(acf-aci) * collision[0], (acf-aci) * collision[1]]; 
    var v2 = [(bcf-bci) * collision[0], (bcf-bci) * collision[1]];     
  
    
    // Addition sure works better than assignment, but I encourage to try it for
    // the lulz
    objectA.vx += v1[0];
    objectA.vy += v1[1];
    objectB.vx += v2[0];
    objectB.vy += v2[1];
  }

Now in my scenario, I observe weird behavior. If big ball hits small ball, small ball flies away fast, but the big ball stops completely. Sufficiently large ball should shove small balls away without slowing down.

In the situation:

image description

This happens:

image description

And this does never happen, no matter what size you use:

image description

I think it's caused by the way I divide speed between two balls. But how else determine the change?

I understand this question can hardly be answered just from looking at code. Unfortunatelly the context can't fit in SSCCE within jsfiddle. Therefore, with some effort, I created online demo on github pages, where the above function can be edited to immediate effect. I will do my best to ensure that demo is preserved for further reference.

Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

1 Answers1

1

Read up on elastic collisions. Your equations are missing important factors like the difference in masses and—since you're working in two dimensions—the collision angle.

For a one-dimensional collision, you need to implement the following equation (from that Wikipedia page), where u1 and u2 are the velocities of each object before the collision, and v1/v2 are the velocities after.

One-dimensional elastic collision, object 1

One-dimensional elastic collision, object 1

You can verify your results by checking that the total momentum and kinetic energy of the system remain the same across the collision.

The two dimensional equations are in that article as well, but significantly more involved so I won't copy them here (I'd just be pasting the whole article). Importantly, they require use of trigonometric functions (sin, cos), and the dot product, which are absent from your current implementation.

Kristján
  • 18,165
  • 5
  • 50
  • 62
  • I implemented inelastic collision (which equals to elastic when `Cr` is `1`) exactly as wikipedia demands. The results are flawed. I created [new demo which demonstrates the problem](http://darker.github.io/asteroids/demo-elastic-bounce/). You can see how wrongly two balls bounce at the bottom right corner of the screen. Also note the way small ball bounces of the large one - in opposite direction. The function responsible for the bounce is in editor again. And you can see it's exactly the formula from wikipedia. – Tomáš Zato Apr 12 '16 at 09:56
  • 1
    You've implemented the 1-dimensional equations, so your small asteroids behave as if everything is a head-on collision. Now extend your code to account for [the angle of collision](https://en.wikipedia.org/wiki/Elastic_collision#Two-dimensional). – Kristján Apr 12 '16 at 13:35
  • Yeah! Now it works as I needed. Do you have any clue where do I put the coefficient of restitution (the thing that causes bouncing to stop) in the equations? – Tomáš Zato Apr 12 '16 at 14:25
  • Great! I think you can apply the coefficient of restitution to both objects' speeds either before or after the collision to get a close enough result. I'm not sure exactly where in the 2D equations to apply it for perfect simulation. – Kristján Apr 12 '16 at 15:00
  • Applying the factor on the speed itself will affect irrelevant parts of speed. For example imagine two balls flying in parallel and bouncing. Obviously from balls' point of view they are stationary except for the bouncing. Only their relative velocity should diminish, the absolute velocity must not change. – Tomáš Zato Apr 12 '16 at 15:15
  • Bouncing off what? Energy is lost during the collision. The ball flying in parallel is irrelevant. – Kristján Apr 12 '16 at 16:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108963/discussion-between-tomas-zato-and-kristjan). – Tomáš Zato Apr 12 '16 at 16:06